-
13-03-2014, 12:02 PM #11Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 21: Các tính toán để di chuyển Tank
Kiểm tra Tank bị chặn bởi khung chơi
Mã:BOOL TankE_HitBorder(PENEMYTANK pTank){ if(pTank->iFrend == FM_LEFT && pTank->x-1 < 0) return TRUE; // Dung bien ben trai if(pTank->iFrend == FM_UP && pTank->y-1 < 0) return TRUE; // Dung bien phia tren if(pTank->iFrend == FM_RIGHT && pTank->x+1 > LARGE*12) return TRUE; // Dung bien ben phai if(pTank->iFrend == FM_DOWN && pTank->y+1 > LARGE*12) return TRUE; // Dung bien phia duoi return FALSE;}BOOL Tank_HitBorder(PTANK pTank){ if(pTank->iFrend == FM_LEFT && pTank->x-1 < 0) return TRUE; // Dung bien ben trai if(pTank->iFrend == FM_UP && pTank->y-1 < 0) return TRUE; // Dung bien phia tren if(pTank->iFrend == FM_RIGHT && pTank->x+1 > LARGE*12) return TRUE; // Dung bien ben phai if(pTank->iFrend == FM_DOWN && pTank->y+1 > LARGE*12) return TRUE; // Dung bien phia duoi return FALSE;}
Mã:BOOL TankE_HitCell(PENEMYTANK pTank,BYTE pCells[52][52]){ POINT Cell[4]; int i; BYTE iStyle; if(pTank->iFrend == FM_LEFT) // Tank dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x-1)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else if(pTank->iFrend == FM_UP) // Tank dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y-1)/SMALL; } } else if(pTank->iFrend == FM_RIGHT) // Tank dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x+LARGE)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else // Tank dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y+LARGE)/SMALL; } } for(i=0;i<4;i++) // Tank se bi can khi dung phai: Brick,Steel,River,House { iStyle = pCells[Cell[i].x][Cell[i].y]; if(iStyle == TC_BRICK || iStyle == TC_STEEL || iStyle == TC_RIVER || iStyle == TC_HOUSE) return TRUE; } return FALSE;}BOOL Tank_HitCell(PTANK pTank,BYTE pCells[52][52]){ POINT Cell[4]; int i; BYTE iStyle; if(pTank->iFrend == FM_LEFT) // Tank dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x-1)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else if(pTank->iFrend == FM_UP) // Tank dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y-1)/SMALL; } } else if(pTank->iFrend == FM_RIGHT) // Tank dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x+LARGE)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else // Tank dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y+LARGE)/SMALL; } } for(i=0;i<4;i++) // Tank se bi can khi dung phai: Brick,Steel,House. Can xem xet Tank co vuot song hay khong ? { iStyle = pCells[Cell[i].x][Cell[i].y]; if(iStyle == TC_BRICK || iStyle == TC_STEEL || iStyle == TC_HOUSE) return TRUE; if(!pTank->bRiver && iStyle == TC_RIVER) return TRUE; } return FALSE;}
Mã:BOOL TankE_HitTankE(PENEMYTANK pTank,CPtrArray * arTankE){ PENEMYTANK pAnother; int i,cCount; cCount = arTankE->GetSize(); for(i=0;i<cCount;i++) if(pAnother = (PENEMYTANK)arTankE->GetAt(i)) if(pTank != pAnother) { if(pTank->iFrend == FM_LEFT) // Sang trai { if(pTank->x-1 >= pAnother->x) if(abs(pTank->x - pAnother->x) <= LARGE) if(abs(pTank->y - pAnother->y) < LARGE) return TRUE; } else if(pTank->iFrend == FM_UP) // Di len { if(pTank->y-1 >= pAnother->y) if(abs(pTank->x - pAnother->x) < LARGE) if(abs(pTank->y - pAnother->y) <= LARGE) return TRUE; } else if(pTank->iFrend == FM_RIGHT) // Sang phai { if(pTank->x+1 <= pAnother->x) if(abs(pTank->x - pAnother->x) <= LARGE) if(abs(pTank->y - pAnother->y) < LARGE) return TRUE; } else // Di xuong { if(pTank->y+1 <= pAnother->y) if(abs(pTank->x - pAnother->x) < LARGE) if(abs(pTank->y - pAnother->y) <= LARGE) return TRUE; } } return FALSE;}BOOL Tank_HitTankE(PTANK pTank,CPtrArray * arTankE){ PENEMYTANK pTankE; int i,cCount; cCount = arTankE->GetSize(); for(i=0;i<cCount;i++) if(pTankE = (PENEMYTANK)arTankE->GetAt(i)) { if(pTank->iFrend == FM_LEFT) // Sang trai { if(pTank->x-1 >= pTankE->x) if(abs(pTank->x - pTankE->x) <= LARGE) if(abs(pTank->y - pTankE->y) < LARGE) return TRUE; } else if(pTank->iFrend == FM_UP) // Di len { if(pTank->y-1 >= pTankE->y) if(abs(pTank->x - pTankE->x) < LARGE) if(abs(pTank->y - pTankE->y) <= LARGE) return TRUE; } else if(pTank->iFrend == FM_RIGHT) // Sang phai { if(pTank->x+1 <= pTankE->x) if(abs(pTank->x - pTankE->x) <= LARGE) if(abs(pTank->y - pTankE->y) < LARGE) return TRUE; } else // Di xuong { if(pTank->y+1 <= pTankE->y) if(abs(pTank->x - pTankE->x) < LARGE) if(abs(pTank->y - pTankE->y) <= LARGE) return TRUE; } } return FALSE;}
Mã:BOOL TankE_HitTank(PENEMYTANK pTank){ if(g_TankL.bReady) { if(pTank->iFrend == FM_LEFT) // Sang trai { if(pTank->x-1 >= g_TankL.x) if(abs(pTank->x - g_TankL.x) <= LARGE) if(abs(pTank->y - g_TankL.y) < LARGE) return TRUE; } else if(pTank->iFrend == FM_UP) // Di len { if(pTank->y-1 >= g_TankL.y) if(abs(pTank->x - g_TankL.x) < LARGE) if(abs(pTank->y - g_TankL.y) <= LARGE) return TRUE; } else if(pTank->iFrend == FM_RIGHT) // Sang phai { if(pTank->x+1 <= g_TankL.x) if(abs(pTank->x - g_TankL.x) <= LARGE) if(abs(pTank->y - g_TankL.y) < LARGE) return TRUE; } else // Di xuong { if(pTank->y+1 <= g_TankL.y) if(abs(pTank->x - g_TankL.x) < LARGE) if(abs(pTank->y - g_TankL.y) <= LARGE) return TRUE; } } if(g_TankR.bReady) { if(pTank->iFrend == FM_LEFT) // Sang trai { if(pTank->x-1 >= g_TankR.x) if(abs(pTank->x - g_TankR.x) <= LARGE) if(abs(pTank->y - g_TankR.y) < LARGE) return TRUE; } else if(pTank->iFrend == FM_UP) // Di len { if(pTank->y-1 >= g_TankR.y) if(abs(pTank->x - g_TankR.x) < LARGE) if(abs(pTank->y - g_TankR.y) <= LARGE) return TRUE; } else if(pTank->iFrend == FM_RIGHT) // Sang phai { if(pTank->x+1 <= g_TankR.x) if(abs(pTank->x - g_TankR.x) <= LARGE) if(abs(pTank->y - g_TankR.y) < LARGE) return TRUE; } else // Di xuong { if(pTank->y+1 <= g_TankR.y) if(abs(pTank->x - g_TankR.x) < LARGE) if(abs(pTank->y - g_TankR.y) <= LARGE) return TRUE; } } return FALSE;}BOOL Tank_HitTank(PTANK pTank){ PTANK pAnother; if(!pTank || !g_TankL.bReady || !g_TankR.bReady) return FALSE; if(pTank == &g_TankL) pAnother = &g_TankR; else pAnother = &g_TankL; if(pTank->iFrend == FM_LEFT) // Sang trai { if(pTank->x-1 >= pAnother->x) if(abs(pTank->x - pAnother->x) <= LARGE) if(abs(pTank->y - pAnother->y) < LARGE) return TRUE; } else if(pTank->iFrend == FM_UP) // Di len { if(pTank->y-1 >= pAnother->y) if(abs(pTank->x - pAnother->x) < LARGE) if(abs(pTank->y - pAnother->y) <= LARGE) return TRUE; } else if(pTank->iFrend == FM_RIGHT) // Sang phai { if(pTank->x+1 <= pAnother->x) if(abs(pTank->x - pAnother->x) <= LARGE) if(abs(pTank->y - pAnother->y) < LARGE) return TRUE; } else // Di xuong { if(pTank->y+1 <= pAnother->y) if(abs(pTank->x - pAnother->x) < LARGE) if(abs(pTank->y - pAnother->y) <= LARGE) return TRUE; } return FALSE;}
( Nếu thấy khó hiểu, các bạn cứ nêu ra mình sẽ giải thích tỉ mỉ hơn).
Sau đây là 2 hàm tổng hợp các hàm trên
Mã:BOOL TankE_CanStepByStep(PENEMYTANK pTank,BYTE pCells[52][52]){ if(TankE_HitBorder(pTank)) return FALSE; if(TankE_HitCell(pTank,pCells)) return FALSE; if(TankE_HitTankE(pTank,&g_arTankE)) return FALSE; if(TankE_HitTank(pTank)) return FALSE; return TRUE;}BOOL Tank_CanStepByStep(PTANK pTank,BYTE pCells[52][52]){ if(Tank_HitBorder(pTank)) return FALSE; if(Tank_HitCell(pTank,pCells)) return FALSE; if(Tank_HitTankE(pTank,&g_arTankE)) return FALSE; if(Tank_HitTank(pTank)) return FALSE; return TRUE;}
Và khi đã "CanStepByStep" thì tại sao không "StepByStep"
Mã:void TankE_StepByStep(PENEMYTANK pTank){ if(pTank->iFrend == FM_LEFT) pTank->x --; else if(pTank->iFrend == FM_UP) pTank->y --; else if(pTank->iFrend == FM_RIGHT) pTank->x ++; else pTank->y ++;}void Tank_StepByStep(PTANK pTank){ if(pTank->iFrend == FM_LEFT) pTank->x --; else if(pTank->iFrend == FM_UP) pTank->y --; else if(pTank->iFrend == FM_RIGHT) pTank->x ++; else pTank->y ++;}
Mã:BOOL TankE_CanRotate4Frend(PENEMYTANK pTank){ if(pTank->x % MEDIUM == 0 && pTank->y % MEDIUM == 0) return TRUE; return FALSE;}BOOL Tank_CanRotate4Frend(PTANK pTank){ if(pTank->x % MEDIUM == 0 && pTank->y % MEDIUM == 0) return TRUE; return FALSE;}
Khi Tank di chuyển ngang, tọa độ y của nó luôn thỏa điều kiện : y % MEDIUM == 0.
Khi Tank di chuyển dọc, tọa độ x của nó luôn thỏa điều kiện : x % MEDIUM == 0.
Trước khi cho phép Tank bất kỳ chuyển hướng vuông góc với hướng đang có, chúng ta phải kiểm tra theo 2 hàm này.
Ngày hôm nay mã nhiều rùi, nghỉ thui, hẹn gặp lại các huynh đệ.
[IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
16-03-2014, 09:33 AM #12Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 22: Tiếp tục các tính toán di chuyen cho Enemy Tank
Thêm vào các biến toàn cục sau:
Mã:CPtrArray g_arWave(TRUE); // WaveSoundDATASETUP g_DataSetup;
Mã:void TankE_BackRotate(PENEMYTANK pTank) // Quay lui TankE{ if(pTank->iFrend == FM_LEFT) pTank->iFrend = FM_RIGHT; else if(pTank->iFrend == FM_UP) pTank->iFrend = FM_DOWN; else if(pTank->iFrend == FM_RIGHT) pTank->iFrend = FM_LEFT; else pTank->iFrend = FM_UP;}void TankE_RotateRandom(PENEMYTANK pTank){ if(pTank->iSmart > 0) // Tăng cường xác suất TankE di chuyển tới bộ chỉ huy của ta { if(rand()%3 == 0) pTank->iFrend = FM_DOWN; else if(rand()%3 == 0) { if(pTank->x > (SMALL*52)/2) pTank->iFrend = FM_LEFT; else pTank->iFrend = FM_RIGHT; } else pTank->iFrend = rand()%4 + 1; } else pTank->iFrend = rand()%4 + 1;}
Điều này gây áp lực cho người chơi phải mau chóng bắn hạ nó nếu không muốn bị dồn vào thế thụ động.
Mã:BOOL TankE_IsFaceTank(PENEMYTANK pTankE,PTANK pTank){ if(pTank->bReady) // Tank ta đang hoạt động if(abs(pTankE->iFrend - pTank->iFrend) == 2) // TankE và Tank ta đang di chuyển cùng phương if(abs(pTankE->x - pTank->x) < LARGE || abs(pTankE->y - pTank->y) < LARGE) // 2 Tank có thể nhìn thấy nhau, tiếp theo là kiểm tra đối diện { if((pTankE->iFrend == FM_LEFT && pTankE->x > pTank->x) || (pTankE->iFrend == FM_UP && pTankE->y > pTank->y) || (pTankE->iFrend == FM_RIGHT && pTankE->x < pTank->x) || (pTankE->iFrend == FM_DOWN && pTankE->y < pTank->y)) return TRUE; } return FALSE;}
Mã:void TankE_Shoot(PENEMYTANK pTank){ PBULLETE pBullE; CWaveSound * pWave; CHAR szWave[MAX_PATH]; if(pBullE = (PBULLETE)malloc(sizeof(BULLETE))) { // Chuyển giao các thuộc tính từ TankE cho viên đạn, tọa độ ban đầu là đầu nòng súng pBullE->bBullF = pTank->bBullF; pBullE->iFrend = pTank->iFrend; pBullE->iSpeed = pTank->iShoot; if(pTank->iFrend == FM_LEFT) { pBullE->x = pTank->x - SMALL/2; pBullE->y = pTank->y + SMALL + SMALL/2; } else if(pTank->iFrend == FM_UP) { pBullE->x = pTank->x + SMALL + SMALL/2; pBullE->y = pTank->y - SMALL/2; } else if(pTank->iFrend == FM_RIGHT) { pBullE->x = pTank->x + LARGE + SMALL/2; pBullE->y = pTank->y + SMALL + SMALL/2; } else { pBullE->x = pTank->x + SMALL + SMALL/2; pBullE->y = pTank->y + LARGE + SMALL/2; } if(g_arBullE.Add(pBullE)) { // Xem xét xuất âm thanh ra loa if(g_DataSetup.sndEnemyShoot) { GetModuleFileName(NULL,szWave,MAX_PATH); PathRemoveFileSpec(szWave); lstrcat(szWave,"\\Tank2D\\ETankShoot.wav"); if(PathFileExists(szWave)) if(pWave = new CWaveSound()) { if(!g_arWave.Add(pWave)) delete pWave; else pWave->Play(szWave,g_lpDS,FALSE); } } } else free(pBullE); }}
Sau đây là hàm cuối cùng của ngày hôm nay
Mã:void TankE_Update(PENEMYTANK pTank,BYTE pCells[52][52]){ int cStep; BOOL bStep; if(TankE_CanRotate4Frend(pTank)) { if((( pTank->iRequest == FM_LEFT || pTank->iRequest == FM_RIGHT ) && ( pTank->iFrend == FM_UP || pTank->iFrend == FM_DOWN )) ||(( pTank->iRequest == FM_UP || pTank->iRequest == FM_DOWN ) && ( pTank->iFrend == FM_LEFT || pTank->iFrend == FM_RIGHT ))) pTank->iFrend = pTank->iRequest; else if(rand()%10 == 0) TankE_RotateRandom(pTank); pTank->iRequest = FM_NULL; } cStep = pTank->iSpeed; bStep = FALSE; while(cStep>0) { if(TankE_CanStepByStep(pTank,pCells)) { TankE_StepByStep(pTank); bStep = TRUE; cStep --; } else { if(rand()%50==0) TankE_Shoot(pTank); else if(rand()%50==0) { TankE_BackRotate(pTank); pTank->iRequest = rand()%4 + 1; } break; } } if(bStep) { if(++pTank->iFrame == 4) pTank->iFrame = 0; if(rand()%150==0) TankE_Shoot(pTank); } if(pTank->iSmart > 1 && rand()%20 == 0) if(TankE_IsFaceTank(pTank,&g_TankL) || TankE_IsFaceTank(pTank,&g_TankR)) // Khi đối mặt với Tank ta sẽ khai hỏa tức thì TankE_Shoot(pTank);}
Đầu tiên xem xét Tank có ở vị trí quay được 4 hướng không, nếu được -> xem xét yêu cầu đổi hướng và hướng hiện tại. Nếu là vuông góc thì đổi hướng di chuyển theo hướng yêu cầu.
Nếu không chúng ta ngẫu nhiên có thể đổi hướng TankE một cách ngẫu nhiên. Sau đó tắt yêu cầu đổi hướng TankE.
Chúng ta sẽ cho Tank tiến từng bước một cho tới khi bước đủ số bước hoặc không thể tiến được. Nếu là không thể tiến được, chúng ta sẽ cho Tank bắn ngẫu nhiên hoặc cho Tank quay lui và bật yêu cầu đổi hướng mới, song song đó nếu Tank bước được ít nhất 1 bước thì biến lưu có di chuyển được bật.
Nếu biến lưu được bật, thay đổi khung hiển thị tới vị trí kế tiếp và xem xét cho Tank khai hỏa.
Cuối cùng nếu TankE có thuộc tính thông minh lớn hơn 1 và đối mặt với Tank ta, chúng ta cũng xem xét cho TankE bắn.
Ngày hôm nay tới đây thôi, chào tạm biệt !!! [IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 16-03-2014 lúc 02:33 PM - - -</font>
<font color="#0000FF">NGÀY 23: Tính toán để di chuyển Tank của chúng ta.
Trước khi đi vào chủ điểm của ngày hôm nay, các bạn sửa giùm dòng mã 15 trong hàm TankE_Update() như sau:
cStep = pTank->iSpeed;
cStep = pTank->iSpeed * (TankE_MoveOnGlide(pTank,pCells) ? 2:1 );
Mã:BOOL TankE_MoveOnGlide(PENEMYTANK pTank,BYTE pCells[52][52]){ POINT Cell[4]; int i; if(pTank->iFrend == FM_LEFT) // Tank dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else if(pTank->iFrend == FM_UP) // Tank dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = pTank->y/SMALL; } } else if(pTank->iFrend == FM_RIGHT) // Tank dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x+LARGE-1)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else // Tank dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y+LARGE-1)/SMALL; } } for(i=0;i<4;i++) if(pCells[Cell[i].x][Cell[i].y] != TC_GLIDE) return FALSE; return TRUE;}BOOL Tank_MoveOnGlide(PTANK pTank,BYTE pCells[52][52]){ POINT Cell[4]; int i; if(pTank->iFrend == FM_LEFT) // Tank dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else if(pTank->iFrend == FM_UP) // Tank dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = pTank->y/SMALL; } } else if(pTank->iFrend == FM_RIGHT) // Tank dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = (pTank->x+LARGE-1)/SMALL; Cell[i].y = pTank->y/SMALL + i; } } else // Tank dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pTank->x/SMALL + i; Cell[i].y = (pTank->y+LARGE-1)/SMALL; } } for(i=0;i<4;i++) if(pCells[Cell[i].x][Cell[i].y] != TC_GLIDE) return FALSE; return TRUE;}
Có lẽ chúng ta phải thay đổi kiểu cấu trúc TANK cho phù hợp theo yêu cầu phát sinh:
Mã:typedef struct{ BOOL bBullF; // Tank nay ban dan lua ? BOOL bReady; // Tank da san sang ? BOOL bRiver; // Tank co the vuot song ? int cBulletJoin; // So dan noi tiep nhau duoc phep ban tu 1->3 int cLife; // So lan song cua Tank int cSafety; // So lan con lai Tank an toan trong che do duoc bao ve ? Khoi tao 1000 int cTimes; // So lan lam tre giua 2 vien dan int iFrame; // Khung hien hanh trong bitmap int iFrend; // Huong di chuyen hien hanh int iFroze; // Thoi gian dong bang con lai - Khoi tao tu dau la 300 int iPower; // Suc manh cua Tank tu 1->5 int iRequestFrend; // Huong di chuyen duoc yeu cau int iShoot; // Toc do di chuyen cua dan duoc ban tu Tank nay tu 5->10 Pixels trong 1 lan int iSpeed; // Toc do di chuyen tu 1->3 Pixels trong 1 lan int x,y; // Toa do LeftTop cua TankE tinh tu goc tren trai trong khung choi}TANK,*PTANK;
Mã:void Tank_Shoot(PTANK pTank){ PBULLET pBull; CWaveSound * pWave; CHAR szWave[MAX_PATH]; int i; if(pBull = (PBULLET)malloc(sizeof(BULLET))) { // pBull->bBullF = pTank->bBullF; pBull->iFrend = pTank->iFrend; pBull->iSpeed = pTank->iShoot; if(pTank->iFrend == FM_LEFT) { pBull->x = pTank->x - SMALL/2; pBull->y = pTank->y + SMALL + SMALL/2; } else if(pTank->iFrend == FM_UP) { pBull->x = pTank->x + SMALL + SMALL/2; pBull->y = pTank->y - SMALL/2; } else if(pTank->iFrend == FM_RIGHT) { pBull->x = pTank->x + LARGE + SMALL/2; pBull->y = pTank->y + SMALL + SMALL/2; } else { pBull->x = pTank->x + SMALL + SMALL/2; pBull->y = pTank->y + LARGE + SMALL/2; } pBull->pTank = pTank; if(pTank == & g_TankL) { if(g_arBullL.Add(pBull)) { for(i=0;i<g_TankL.cBulletJoin;i++) if(!g_TankL.pBull[i]) { g_TankL.pBull[i] = pBull; break; } if(g_DataSetup.sndOurShoot) { GetModuleFileName(NULL,szWave,MAX_PATH); PathRemoveFileSpec(szWave); lstrcat(szWave,"\\Tank2D\\TankShoot.wav"); if(PathFileExists(szWave)) if(pWave = new CWaveSound()) { if(!g_arWave.Add(pWave)) delete pWave; else pWave->Play(szWave,g_lpDS,FALSE); } } } else free(pBull); } if(pTank == & g_TankR) { if(g_arBullR.Add(pBull)) { for(i=0;i<g_TankR.cBulletJoin;i++) if(!g_TankR.pBull[i]) { g_TankR.pBull[i] = pBull; break; } if(g_DataSetup.sndOurShoot) { GetModuleFileName(NULL,szWave,MAX_PATH); PathRemoveFileSpec(szWave); lstrcat(szWave,"\\Tank2D\\TankShoot.wav"); if(PathFileExists(szWave)) if(pWave = new CWaveSound()) { if(!g_arWave.Add(pWave)) delete pWave; else pWave->Play(szWave,g_lpDS,FALSE); } } } else free(pBull); } }}
Sau đây là hàm cuối của ngày hôm nay, hàm này cũng thuộc hàng nhức xương khớp
Mã:void Tank_Update(BYTE pCells[52][52]){ INPUTKEYBOARD Keyboard; INPUTMOUSE Mouse; int cStep; BOOL bStep; if(g_TankL.iFroze > 0) g_TankL.iFroze --; if(g_TankL.bReady && g_TankL.iFroze == 0) if(DirectX_GetInputKeyboard(&Keyboard)) { if(Keyboard.bLeft) g_TankL.iRequestFrend = FM_LEFT; else if(Keyboard.bUp) g_TankL.iRequestFrend = FM_UP; else if(Keyboard.bRight) g_TankL.iRequestFrend = FM_RIGHT; else if(Keyboard.bDown) g_TankL.iRequestFrend = FM_DOWN; else g_TankL.iRequestFrend = FM_NULL; if(g_TankL.iRequestFrend != FM_NULL) { if(g_TankL.iRequestFrend != g_TankL.iFrend) // Neu khac huong { if(abs(g_TankL.iRequestFrend - g_TankL.iFrend) == 2) // Yeu cau quay nguoc g_TankL.iFrend = g_TankL.iRequestFrend; else if(Tank_CanRotate4Frend(&g_TankL)) // Quay vuong goc g_TankL.iFrend = g_TankL.iRequestFrend; } // Di chuyen Tank cStep = g_TankL.iSpeed * (Tank_MoveOnGlide(&g_TankL,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankL,pCells)) { Tank_StepByStep(&g_TankL); bStep = TRUE; cStep --; } else break; } if(bStep) { if(++ g_TankL.iFrame == 4) g_TankL.iFrame = 0; } } // Nguoi choi dang nhan nut ban if(Keyboard.bSpace) if(++ g_TankL.cTimes >= 8) { g_TankL.cTimes = 0; if(g_arBullL.GetSize() < g_TankL.cBulletJoin) Tank_Shoot(&g_TankL); } } if(g_TankR.iFroze > 0) g_TankR.iFroze --; if(g_TankR.bReady && g_TankR.iFroze == 0) if(DirectX_GetInputMouse(&Mouse)) { g_TankR.iRequestFrend = Mouse.iRotateFrend; if(g_TankR.iRequestFrend != FM_NULL) if(g_TankR.iRequestFrend != g_TankR.iFrend) { if(abs(g_TankR.iRequestFrend - g_TankR.iFrend) == 2) // Yeu cau quay nguoc g_TankR.iFrend = g_TankR.iRequestFrend; else // Yeu cau quay vuong goc { if(Tank_CanRotate4Frend(&g_TankR)) g_TankR.iFrend = g_TankR.iRequestFrend; else // Neu chua the quay { // Chúng ta xem xét 2 vị trí gần nhất mà Tank có thể quay được. Ưu tiên cho vị trí ở phía trước nếu Tank có thể di chuyển theo hướng đó mà không bị cản. // Trong trường hợp cả 2 vị trí là không thể di chuyển tới, cho Tank di chuyển tới được bao nhiêu cũng được. int xTank = g_TankR.x; int yTank = g_TankR.y; int iFrend = g_TankR.iFrend; int cStepForward = 0,cStepBack = 0; BOOL bForward = FALSE, bBack = FALSE; while(Tank_CanStepByStep(&g_TankR,pCells) && cStepForward < MEDIUM) { cStepForward ++; Tank_StepByStep(&g_TankR); if(Tank_CanRotate4Frend(&g_TankR)) { bForward = TRUE; break; } } g_TankR.x = xTank; g_TankR.y = yTank; if(iFrend == FM_LEFT) g_TankR.iFrend = FM_RIGHT; else if(iFrend == FM_UP) g_TankR.iFrend = FM_DOWN; else if(iFrend == FM_RIGHT) g_TankR.iFrend = FM_LEFT; else g_TankR.iFrend = FM_UP; while(Tank_CanStepByStep(&g_TankR,pCells) && cStepBack < MEDIUM) { cStepBack ++; Tank_StepByStep(&g_TankR); if(Tank_CanRotate4Frend(&g_TankR)) { bBack = TRUE; break; } } g_TankR.x = xTank; g_TankR.y = yTank; if(bForward && bBack) { if(cStepForward <= cStepBack) { cStep = cStepForward; g_TankR.iFrend = iFrend;} else cStep = cStepBack; } else if(bForward && !bBack) { cStep = cStepForward; g_TankR.iFrend = iFrend; } else if(!bForward && bBack) cStep = cStepBack; else { cStep = cStepForward; g_TankR.iFrend = iFrend; } // bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankR,pCells)) { Tank_StepByStep(&g_TankR); bStep = TRUE; cStep --; if(Tank_CanRotate4Frend(&g_TankR)) { g_TankR.iFrend = g_TankR.iRequestFrend; break; } } else break; } if(bStep) if(++ g_TankR.iFrame == 4) g_TankR.iFrame = 0; } } } // Di chuyen if(Mouse.bRightPress) { cStep = g_TankR.iSpeed * (Tank_MoveOnGlide(&g_TankR,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankR,pCells)) { Tank_StepByStep(&g_TankR); bStep = TRUE; cStep --; } else break; } if(bStep) if(++ g_TankR.iFrame == 4) g_TankR.iFrame = 0; } // Khai hoa if(Mouse.bLeftPress) if(++ g_TankR.cTimes >= 8) { g_TankR.cTimes = 0; if(g_arBullR.GetSize() < g_TankR.cBulletJoin) Tank_Shoot(&g_TankR); } }}
hoàn toàn không có sự ngẫu nhiên nào ở đây.
Viết được tới đây đã thấy nhức cả đầu, hoa mắt. Chương trình này chỉ nhỏ xíu mà đã vậy, mới thấy cảm phục các nhà làm phần mềm lắm thay !!!
Dừng thôi ( Có ai muốn nhậu không hè ) [IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG]
-
18-03-2014, 07:07 PM #13Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 24: Tính toán để di chuyển những viên đạn
Mã:BOOL BulletE_HitBorder(PBULLETE pBullE){ if((pBullE->iFrend == FM_LEFT && pBullE->x < 0) // Dung bien ben trai || (pBullE->iFrend == FM_UP && pBullE->y < 0) // Dung bien phia tren || (pBullE->iFrend == FM_RIGHT && pBullE->x > LARGE*13 - SMALL) // Dung bien ben phai || (pBullE->iFrend == FM_DOWN && pBullE->y > LARGE*13 - SMALL)) // Dung bien phia duoi return TRUE; return FALSE;}BOOL Bullet_HitBorder(PBULLET pBull){ if((pBull->iFrend == FM_LEFT && pBull->x < 0) // Dung bien ben trai || (pBull->iFrend == FM_UP && pBull->y < 0) // Dung bien phia tren || (pBull->iFrend == FM_RIGHT && pBull->x > LARGE*13 - SMALL) // Dung bien ben phai || (pBull->iFrend == FM_DOWN && pBull->y > LARGE*13 - SMALL)) // Dung bien phia duoi return TRUE; return FALSE;}
Mã:BOOL BulletE_HitCell(PBULLETE pBullE,BYTE pCells[52][52]) // Ghi nho vien dan chi co the dung truc tiep 2 Cells{ POINT Cell[4],Next[4]; int i,x,y; BYTE iCell[4],iNext[4]; BOOL bHitCell; if(pBullE->iFrend == FM_LEFT) // BulletE dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = pBullE->x/SMALL; Cell[i].y = pBullE->y/SMALL + i - 1; Next[i].x = Cell[i].x - ((Cell[i].x > 0) ? 1:0); Next[i].y = Cell[i].y; } } else if(pBullE->iFrend == FM_UP) // BulletE dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pBullE->x/SMALL + i - 1; Cell[i].y = pBullE->y/SMALL; Next[i].x = Cell[i].x; Next[i].y = Cell[i].y - ((Cell[0].y > 0) ? 1:0); } } else if(pBullE->iFrend == FM_RIGHT) // BulletE dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = pBullE->x/SMALL; Cell[i].y = pBullE->y/SMALL + i - 1; Next[i].x = Cell[i].x + ((Cell[0].x < 51) ? 1:0); Next[i].y = Cell[i].y; } } else // BulletE dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pBullE->x/SMALL + i - 1; Cell[i].y = pBullE->y/SMALL; Next[i].x = Cell[i].x; Next[i].y = Cell[i].y + ((Cell[0].y < 51) ? 1:0); } } for(i=0;i<4;i++) { iCell[i] = pCells[Cell[i].x][Cell[i].y]; iNext[i] = pCells[Next[i].x][Next[i].y]; } bHitCell = FALSE; if(iCell[1] == TC_BRICK || iCell[1] == TC_STEEL || iCell[1] == TC_HOUSE || iCell[2] == TC_BRICK || iCell[2] == TC_STEEL || iCell[2] == TC_HOUSE) bHitCell = TRUE; if(iCell[1] == TC_HOUSE || iCell[2] == TC_HOUSE) { for(x=24;x<28;x++) for(y=48;y<52;y++) pCells[x][y] = TC_FREE; // Vi tri cua bo chi huy } if(iCell[1] == TC_BRICK) // Neu Cell thu 2 la Brick { pCells[Cell[1].x][Cell[1].y] = TC_FREE; // Pha huy Brick if(iCell[0] == TC_BRICK) // Neu Cell dau tien la Brick pCells[Cell[0].x][Cell[0].y] = TC_FREE; // Pha huy Brick } else if(iCell[1] == TC_STEEL && pBullE->bBullF) // Neu Cell thu 2 la Steel va dan la dan lua { pCells[Cell[1].x][Cell[1].y] = TC_FREE; // Pha huy Steel pCells[Cell[0].x][Cell[0].y] = TC_FREE; pCells[Next[1].x][Next[1].y] = TC_FREE; pCells[Next[0].x][Next[0].y] = TC_FREE; } if(iCell[2] == TC_BRICK) { pCells[Cell[2].x][Cell[2].y] = TC_FREE; if(iCell[3] == TC_BRICK) pCells[Cell[3].x][Cell[3].y] = TC_FREE; } else if(iCell[2] == TC_STEEL && pBullE->bBullF) { pCells[Cell[2].x][Cell[2].y] = TC_FREE; // Pha huy Steel pCells[Cell[3].x][Cell[3].y] = TC_FREE; pCells[Next[2].x][Next[2].y] = TC_FREE; pCells[Next[3].x][Next[3].y] = TC_FREE; } return bHitCell;}BOOL Bullet_HitCell(PBULLET pBull,BYTE pCells[52][52]) // Ghi nho vien dan chi co the dung truc tiep 2 Cells{ POINT Cell[4],Next[4]; int i,x,y; BYTE iCell[4],iNext[4]; BOOL bHitCell; if(pBull->iFrend == FM_LEFT) // BulletE dang di chuyen sang trai { for(i=0;i<4;i++) { Cell[i].x = pBull->x/SMALL; Cell[i].y = pBull->y/SMALL + i - 1; Next[i].x = Cell[i].x - ((Cell[i].x > 0) ? 1:0); Next[i].y = Cell[i].y; } } else if(pBull->iFrend == FM_UP) // BulletE dang di chuyen di len { for(i=0;i<4;i++) { Cell[i].x = pBull->x/SMALL + i - 1; Cell[i].y = pBull->y/SMALL; Next[i].x = Cell[i].x; Next[i].y = Cell[i].y - ((Cell[i].y > 0) ? 1:0); } } else if(pBull->iFrend == FM_RIGHT) // BulletE dang di chuyen sang phai { for(i=0;i<4;i++) { Cell[i].x = pBull->x/SMALL; Cell[i].y = pBull->y/SMALL + i - 1; Next[i].x = Cell[i].x + ((Cell[i].x < 51) ? 1:0); Next[i].y = Cell[i].y; } } else // BulletE dang di chuyen di xuong { for(i=0;i<4;i++) { Cell[i].x = pBull->x/SMALL + i - 1; Cell[i].y = pBull->y/SMALL; Next[i].x = Cell[i].x; Next[i].y = Cell[i].y + ((Cell[i].y < 51) ? 1:0); } } for(i=0;i<4;i++) { iCell[i] = pCells[Cell[i].x][Cell[i].y]; iNext[i] = pCells[Next[i].x][Next[i].y]; } bHitCell = FALSE; if(iCell[1] == TC_BRICK || iCell[1] == TC_STEEL || iCell[1] == TC_HOUSE || iCell[2] == TC_BRICK || iCell[2] == TC_STEEL || iCell[2] == TC_HOUSE) bHitCell = TRUE; if(iCell[1] == TC_HOUSE || iCell[2] == TC_HOUSE) { for(x=24;x<28;x++) for(y=48;y<52;y++) pCells[x][y] = TC_FREE; // Vi tri cua bo chi huy } if(iCell[1] == TC_BRICK) // Neu Cell thu 2 la Brick { pCells[Cell[1].x][Cell[1].y] = TC_FREE; // Pha huy Brick if(iCell[0] == TC_BRICK) // Neu Cell dau tien la Brick pCells[Cell[0].x][Cell[0].y] = TC_FREE; // Pha huy Brick } else if(iCell[1] == TC_STEEL && pBull->bBullF) // Neu Cell thu 2 la Steel va dan la dan lua { pCells[Cell[1].x][Cell[1].y] = TC_FREE; // Pha huy Steel pCells[Cell[0].x][Cell[0].y] = TC_FREE; pCells[Next[1].x][Next[1].y] = TC_FREE; pCells[Next[0].x][Next[0].y] = TC_FREE; } if(iCell[2] == TC_BRICK) { pCells[Cell[2].x][Cell[2].y] = TC_FREE; if(iCell[3] == TC_BRICK) pCells[Cell[3].x][Cell[3].y] = TC_FREE; } else if(iCell[2] == TC_STEEL && pBull->bBullF) { pCells[Cell[2].x][Cell[2].y] = TC_FREE; // Pha huy Steel pCells[Cell[3].x][Cell[3].y] = TC_FREE; pCells[Next[2].x][Next[2].y] = TC_FREE; pCells[Next[3].x][Next[3].y] = TC_FREE; } return bHitCell;}
Kế đó là xác định 4 SmallCells mà núp sau lưng của 4 SmallCells ban đầu.
Vì viên đạn luôn luôn đụng vào khoảng giữa của 2 SmallCells nên chúng ta xem xét theo từng Cell
Nếu Cell là Brick => hủy Cell và xem Cell cạnh nó phía ngoài rìa là Brick thì hủy luôn.
Nếu Cell là Steel và thuộc tính của đạn là đạn lửa => hủy tất cả 4 SmallCells mà đang chứa giá trị TC_STEEL. Bao gồm Cell này, Cell sau lưng, Cell ngoài rìa, Cell sau lưng và ngoài rìa.
Mã:BOOL BulletE_HitTank(PBULLETE pBullE,PTANK pTank){ PSMOKE pSmoke; if(pTank->bReady) if(abs(pBullE->x-pTank->x) < (LARGE+SMALL)/2 && abs(pBullE->y-pTank->y) < (LARGE+SMALL)/2) { if(pTank->bSafety) { pTank->bBullF = FALSE; pTank->bRiver = FALSE; if((--pTank->cBulletJoin) < 1) pTank->cBulletJoin = 1; if((--pTank->iShoot) < 5) pTank->iShoot = 5; if((--pTank->iSpeed) < 1) pTank->iSpeed = 1; if((--pTank->iPower) == 0) // Tank se mat 1 mang { pTank->iPower = 5; // Tao dam chay if(pSmoke = (PSMOKE)malloc(sizeof(SMOKE))) // Kich thuoc 1 khung la 88x96 { pSmoke->iFrame = 0; pSmoke->x = pTank->x - (88-LARGE)/2; pSmoke->y = pTank->y - (96-LARGE)/2; if(!g_arSmoke.Add(pSmoke)) free(pSmoke); } if((--pTank->cLife) == 0) // Game Over voi Tank nay pTank->bReady = FALSE; else // Khoi tao lai Tank ta { pTank->bBullF = FALSE; pTank->bReady = TRUE; pTank->bRiver = FALSE; pTank->bSafety = FALSE; pTank->cBulletJoin = 1; pTank->cTimes = 0; pTank->iFrame = 0; pTank->iFrend = FM_UP; pTank->iFroze = 0; pTank->iPower = 5; pTank->iRequestFrend = FM_NULL; pTank->iShoot = 5; pTank->iSpeed = 1; for(int i=0;i<3;i++) if(pTank->pBull[i]) pTank->pBull[i] = NULL; pTank->x = LARGE*((pTank == &g_TankL) ? 4:8); pTank->y = 12*LARGE; } } } return TRUE; } return FALSE;}
Nếu chỉ số sức mạnh giảm tới 0 -> Tank sẽ giảm số lần sống và khởi tạo lại vị trí ban đầu và cũng đặt lại chỉ số sức mạnh ở mức cao nhất.
Nếu Tank bị giảm số lần sống tới 0, tắt cờ bReady, GameOver đối với Tank này.
Mã:BOOL Bullet_HitTankE(PBULLET pBull,CPtrArray * arTankE){ PENEMYTANK pTankE; PCARD pCard; PSMOKE pSmoke; int i; for(i=0;i<arTankE->GetSize();i++) if(pTankE = (PENEMYTANK)arTankE->GetAt(i)) if(abs(pBull->x-pTankE->x) < (LARGE+SMALL)/2 && abs(pBull->y-pTankE->y) < (LARGE+SMALL)/2) { if(pTankE->bCard) { pTankE->bCard = FALSE; if(pCard = (PCARD)malloc(sizeof(CARD))) { pCard->cDelay = 2000; pCard->iStyle = pTankE->iCard; pCard->x = (rand()%49)*SMALL; pCard->y = (rand()%49)*SMALL; if(!g_arCard.Add(pCard)) free(pCard); } } if((--pTankE->iPower) < 1) { if(pSmoke = (PSMOKE)malloc(sizeof(SMOKE))) // Kich thuoc 1 khung la 88x96 { pSmoke->iFrame = 0; pSmoke->x = pTankE->x - (88-LARGE)/2; pSmoke->y = pTankE->y - (96-LARGE)/2; if(!g_arSmoke.Add(pSmoke)) free(pSmoke); } arTankE->RemoveAt(i); } return TRUE; } return FALSE;}
Nếu sức mạnh của TankE giảm tới 0, chúng ta tạo một đám cháy và lưu vào mảng khói, đồng thời xóa TankE này khỏi mảng TankE.
"Vạn sự khởi đầu nan, gian nan bắt đầu nản" hì hì.
Vui vậy thôi, sức chiến đấu vẫn còn dài dài. Hẹn gặp lại !
[IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 18-03-2014 lúc 12:07 PM - - -</font>
<font color="#0000FF">NGÀY 25: Tính toán để di chuyển những viên đạn ( Tiếp theo )
Trường hợp đạn của ta đụng Tank của ta
Mã:BOOL Bullet_HitTank(PBULLET pBull) // Đạn của ta đụng Tank của ta{ if(pBull->pTank == &g_TankL) if(abs(pBull->x-g_TankR.x) < (LARGE+SMALL)/2 && abs(pBull->y-g_TankR.y) < (LARGE+SMALL)/2) { g_TankR.iFroze = 300; // Tank bên phải bắt đầu tê liệt return TRUE; } if(pBull->pTank == &g_TankR) if(abs(pBull->x-g_TankL.x) < (LARGE+SMALL)/2 && abs(pBull->y-g_TankL.y) < (LARGE+SMALL)/2) { g_TankL.iFroze = 300; // Đóng băng Tank bên trái return TRUE; } return FALSE;}
Mã:BOOL Bullet_HitBullet(PBULLET pBull) // Đạn của ta đụng đạn của ta{ PBULLET pAnother; int i; if(pBull->pTank == &g_TankL) for(i=0;i<g_arBullR.GetSize();i++) // Duyệt từng viên đạn của Tank ta còn lại if(pAnother = (PBULLET)g_arBullR.GetAt(i)) if(abs(pBull->x - pAnother->x) < SMALL && abs(pBull->y - pAnother->y) < SMALL) { for(j=0;j<3;j++) if(g_TankR.pBull[j] == pAnother) g_TankR.pBull[j] = NULL; g_arBullR.RemoveAt(i); // Xóa viên đạn của Tank kia return TRUE; } if(pBull->pTank == &g_TankR) for(i=0;i<g_arBullL.GetSize();i++) if(pAnother = (PBULLET)g_arBullL.GetAt(i)) if(abs(pBull->x - pAnother->x) < SMALL && abs(pBull->y - pAnother->y) < SMALL) { for(j=0;j<3;j++) if(g_TankL.pBull[j] == pAnother) g_TankL.pBull[j] = NULL; g_arBullL.RemoveAt(i); return TRUE; } return FALSE;}
Mã:BOOL BulletE_HitBullet(PBULLETE pBullE){ PBULLET pBull; int i,j,cCount; cCount = g_arBullL.GetSize(); for(i=0;i<cCount;i++) if(pBull = (PBULLET)g_arBullL.GetAt(i)) // Duyet tung vien dan cua TankL if(abs(pBullE->x - pBull->x) < SMALL && abs(pBullE->y - pBull->y) < SMALL) { for(j=0;j<3;j++) if(g_TankL.pBull[j] == pBull) g_TankL.pBull[j] = NULL; g_arBullL.RemoveAt(i); return TRUE; } cCount = g_arBullR.GetSize(); for(i=0;i<cCount;i++) if(pBull = (PBULLET)g_arBullR.GetAt(i)) // Duyet tung vien dan cua TankR if(abs(pBullE->x - pBull->x) < SMALL && abs(pBullE->y - pBull->y) < SMALL) { for(j=0;j<3;j++) if(g_TankR.pBull[j] == pBull) g_TankR.pBull[j] = NULL; g_arBullR.RemoveAt(i); return TRUE; } return FALSE;}
Mã:BOOL Bullet_HitBulletE(PBULLET pBull){ PBULLETE pBullE; int i; for(i=0;i<g_arBullE.GetSize();i++) if(pBullE = (PBULLETE)g_arBullE.GetAt(i)) if(abs(pBullE->x - pBull->x) < SMALL && abs(pBullE->y - pBull->y) < SMALL) { g_arBullE.RemoveAt(i); return TRUE; } return FALSE;}
Mã:BOOL BulletE_CanStepByStep(PBULLETE pBullE,BYTE pCells[52][52]){ CHAR szWave[MAX_PATH]; CWaveSound * pWave; if(BulletE_HitBorder(pBullE) || BulletE_HitCell(pBullE,pCells) || BulletE_HitBullet(pBullE) || BulletE_HitTank(pBullE,&g_TankL) || BulletE_HitTank(pBullE,&g_TankR)) { if((g_DataSetup.sndEnemyLargeBullet && pBullE->bBullF) || (g_DataSetup.sndEnemySmallBullet && !pBullE->bBullF)) { GetModuleFileName(NULL,szWave,MAX_PATH); PathRemoveFileSpec(szWave); lstrcat(szWave,pBullE->bBullF ? "\\Tank2D\\EBullF.wav" : "\\Tank2D\\EBullN.wav"); if(PathFileExists(szWave)) if(pWave = new CWaveSound()) { if(!g_arWave.Add(pWave)) delete pWave; else pWave->Play(szWave,g_lpDS,FALSE); } } return FALSE; } return TRUE;}BOOL Bullet_CanStepByStep(PBULLET pBull,BYTE pCells[52][52]){ CHAR szWave[MAX_PATH]; CWaveSound * pWave; if(Bullet_HitBorder(pBull) || Bullet_HitCell(pBull,pCells) || Bullet_HitBullet(pBull) || Bullet_HitBulletE(pBull)|| Bullet_HitTank(pBull) || Bullet_HitTankE(pBull,&g_arTankE)) { if((g_DataSetup.sndOurLargeBullet && pBull->bBullF) || (g_DataSetup.sndOurSmallBullet && !pBull->bBullF)) { GetModuleFileName(NULL,szWave,MAX_PATH); PathRemoveFileSpec(szWave); lstrcat(szWave,pBull->bBullF ? "\\Tank2D\\BullF.wav" : "\\Tank2D\\BullN.wav"); if(PathFileExists(szWave)) if(pWave = new CWaveSound()) { if(!g_arWave.Add(pWave)) delete pWave; else pWave->Play(szWave,g_lpDS,FALSE); } } return FALSE; } return TRUE;}void BulletE_StepByStep(PBULLETE pBullE){ if(pBullE->iFrend == FM_LEFT) pBullE->x --; else if(pBullE->iFrend == FM_UP) pBullE->y --; else if(pBullE->iFrend == FM_RIGHT) pBullE->x ++; else pBullE->y ++;}void Bullet_StepByStep(PBULLET pBull){ if(pBull->iFrend == FM_LEFT) pBull->x --; else if(pBull->iFrend == FM_UP) pBull->y --; else if(pBull->iFrend == FM_RIGHT) pBull->x ++; else pBull->y ++;}
Sau đây là 2 hàm cuối cùng của ngày hôm nay
Mã:void BulletE_UpdateAll(CPtrArray * arBullE,BYTE pCells[52][52]){ PBULLETE pBullE; PFIRE pFire; int i,cStep; for(i=0;i<arBullE->GetSize();i++) if(pBullE = (PBULLETE)arBullE->GetAt(i)) // Duyệt từng viên đạn của địch { cStep = pBullE->iSpeed; while(cStep>0) { if(BulletE_CanStepByStep(pBullE,pCells)) // Có thể di chuyển { BulletE_StepByStep(pBullE); // Di chuyển cStep --; } else // Không di chuyển được - đã đụng phải vật cản. { if(pFire = (PFIRE)malloc(sizeof(FIRE))) // Phát nổ { pFire->cDelay = 5; pFire->iFrame = 0; pFire->x = pBullE->x - (40-SMALL)/2; pFire->y = pBullE->y - (40-SMALL)/2; if(!g_arFire.Add(pFire)) free(pFire); } arBullE->RemoveAt(i); // Xóa viên đạn này i--; break; } } }}void Bullet_UpdateAll(BYTE pCells[52][52]){ PBULLET pBull; PFIRE pFire; int i,cStep; // Update tat ca cac vien dan cua TankL for(i=0;i<g_arBullL.GetSize();i++) if(pBull = (PBULLET)g_arBullL.GetAt(i)) // Duyệt từng viên đạn { cStep = pBull->iSpeed; while(cStep>0) { if(Bullet_CanStepByStep(pBull,pCells)) // Có thể di chuyển ? { Bullet_StepByStep(pBull); // Di chuyển cStep --; } else // Không thể di chuyển { if(pFire = (PFIRE)malloc(sizeof(FIRE))) // Phát nổ { pFire->cDelay = 5; pFire->iFrame = 0; pFire->x = pBull->x - (40-SMALL)/2; pFire->y = pBull->y - (40-SMALL)/2; if(!g_arFire.Add(pFire)) free(pFire); } g_arBullL.RemoveAt(i); // Xóa viên đạn này i--; break; } } } // Update tat ca cac vien dan cua TankR for(i=0;i<g_arBullR.GetSize();i++) if(pBull = (PBULLET)g_arBullR.GetAt(i)) { cStep = pBull->iSpeed; while(cStep>0) { if(Bullet_CanStepByStep(pBull,pCells)) { Bullet_StepByStep(pBull); cStep --; } else { if(pFire = (PFIRE)malloc(sizeof(FIRE))) { pFire->cDelay = 5; pFire->iFrame = 0; pFire->x = pBull->x - (40-SMALL)/2; pFire->y = pBull->y - (40-SMALL)/2; if(!g_arFire.Add(pFire)) free(pFire); } g_arBullR.RemoveAt(i); i--; break; } } }}
Một chút khó khăn khi chúng ta phải xem xét để hủy các vật cản hay tạo các đối tượng mới như Card hay Smoke.
Ngày nay tới đây thôi, tạm biệt !
[IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
21-03-2014, 10:52 AM #14Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 26: Cập nhật cho Fire, Smoke và Card
Mã:void Fire_Update(){ PFIRE pFire; int i; for(i=0;i<g_arFire.GetSize();i++) if(pFire = (PFIRE)g_arFire.GetAt(i)) if((++pFire->iFrame)>5) g_arFire.RemoveAt(i);}
Mã:void Smoke_Update(){ PSMOKE pSmoke; int i; for(i=0;i<g_arSmoke.GetSize();i++) if(pSmoke = (PSMOKE)g_arSmoke.GetAt(i)) if((--pSmoke->cDelay) <= 0) { pSmoke->cDelay = 5; if(++pSmoke->iFrame > 14) g_arSmoke.RemoveAt(i); }}
Mã:void Card_Update(){ PCARD pCard; PENEMYTANK pTankE; PSMOKE pSmoke; int i,j,x,y,xCard,yCard,xTankL,yTankL,xTankR,yTankR; xTankL = g_TankL.x + MEDIUM; // Tọa độ tâm x của TankL yTankL = g_TankL.y + MEDIUM; // Tọa độ tâm y của TankL xTankR = g_TankR.x + MEDIUM; // Tọa độ tâm x của TankR yTankR = g_TankR.y + MEDIUM; // Tọa độ tâm y của TankR for(i=0;i<g_arCard.GetSize();i++) if(pCard = (PCARD)g_arCard.GetAt(i)) // Duyệt từng Card { if((--pCard->cDelay)==0) // Đã hết thời gian hiển thị -> Hủy Card g_arCard.RemoveAt(i); else { xCard = pCard->x + 12; // Tọa độ tâm x của Card yCard = pCard->y + 12; // Tọa độ tâm y của Card if(g_TankL.bReady && abs(xCard-xTankL) < 12+MEDIUM && abs(yCard-yTankL) < 12+MEDIUM) // TankL - Card đụng nhau { switch(pCard->iStyle) { case 0: g_TankL.cLife ++; break; // Card tăng mạng sống của Tank case 1: g_TankL.bBullF = TRUE; break; // Card cho phép Tank bắn đạn lửa case 8: g_TankL.bRiver = TRUE; break; // Card cho phép Tank vượt sông case 9: g_TankL.cSafety = 1000; break; // Card bảo vệ Tank khi bị bắn trúng case 10: g_TankL.iPower = 5; break; // Card phục hồi sức mạnh Tank case 3: if(++g_TankL.iSpeed > 3) g_TankL.iSpeed = 3; break; // Card tăng tốc độ di chuyển của Tank case 4: if(++g_TankL.iShoot > 10) g_TankL.iShoot = 10; break; // Card tăng tốc độ của viên đạn được Tank bắn ra case 7: if(++g_TankL.cBulletJoin > 3) g_TankL.cBulletJoin = 3; break; // Card tăng số đạn bắn liên thanh của Tank case 2: // Card nổ mìn tất cả các TankE for(j=0;j<g_arTankE.GetSize();j++) if(pTankE = (PENEMYTANK)g_arTankE.GetAt(j)) { if(pSmoke = (PSMOKE)malloc(sizeof(SMOKE))) { pSmoke->cDelay = 5; pSmoke->iFrame = 0; pSmoke->x = pTankE->x - (88-LARGE)/2; pSmoke->y = pTankE->y - (96-LARGE)/2; if(!g_arSmoke.Add(pSmoke)) free(pSmoke); } } g_arTankE.RemoveAll(); break; case 5: // Card thép hóa tường bao bộ chỉ huy for(x=22;x<30;x++) for(y=46;y<52;y++) g_DataLevel.iCells[x][y] = TC_STEEL; // Tao vung thep xung quanh bo chi huy for(x=24;x<28;x++) for(y=48;y<52;y++) g_DataLevel.iCells[x][y] = TC_HOUSE; // Vi tri cua bo chi huy break; case 6: // Card đóng băng tất cả TankE for(j=0;j<g_arTankE.GetSize();j++) if(pTankE = (PENEMYTANK)g_arTankE.GetAt(j)) pTankE->iFroze += 1000; break; } g_arCard.RemoveAt(i); // Hủy Card } else if(g_TankR.bReady && abs(xCard-xTankR) < 12+MEDIUM && abs(yCard-yTankR) < 12+MEDIUM) { switch(pCard->iStyle) { case 0: g_TankR.cLife ++; break; case 1: g_TankR.bBullF = TRUE; break; case 8: g_TankR.bRiver = TRUE; break; case 9: g_TankR.cSafety = 1000; break; case 10: g_TankR.iPower = 5; break; case 3: if(++g_TankR.iSpeed > 3) g_TankR.iSpeed = 3; break; case 4: if(++g_TankR.iShoot > 10) g_TankR.iShoot = 10; break; case 7: if(++g_TankR.cBulletJoin > 3) g_TankR.cBulletJoin = 3; break; case 2: for(j=0;j<g_arTankE.GetSize();j++) if(pTankE = (PENEMYTANK)g_arTankE.GetAt(j)) { if(pSmoke = (PSMOKE)malloc(sizeof(SMOKE))) { pSmoke->cDelay = 5; pSmoke->iFrame = 0; pSmoke->x = pTankE->x - (88-LARGE)/2; pSmoke->y = pTankE->y - (96-LARGE)/2; if(!g_arSmoke.Add(pSmoke)) free(pSmoke); } } g_arTankE.RemoveAll(); break; case 5: for(x=22;x<30;x++) for(y=46;y<52;y++) g_DataLevel.iCells[x][y] = TC_STEEL; // Tao vung thep xung quanh bo chi huy for(x=24;x<28;x++) for(y=48;y<52;y++) g_DataLevel.iCells[x][y] = TC_HOUSE; // Vi tri cua bo chi huy break; case 6: for(j=0;j<g_arTankE.GetSize();j++) if(pTankE = (PENEMYTANK)g_arTankE.GetAt(j)) pTankE->iFroze += 1000; break; } g_arCard.RemoveAt(i); } } }}
Chào thân ái! [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 20-03-2014 lúc 04:54 PM - - -</font>
NGÀY 27: Vẽ chữ lên bề mặt Back
Thêm vào các khai báo sau
Mã:enum {SP_LEVEL=0,SP_PLAY,SP_WIN,SP_LOST};typedef struct{ BOOL bBullF; int iPower; int iShoot; int iSmart; int iSpeed;}TYPETANK,*PTYPETANK;TYPETANK g_TypeTank[50];HINSTANCE g_hInst;HWND g_hwndMCI;BOOL g_bActive;BOOL g_bMoused;BOOL g_bPause;int g_IndexTank;int g_iStatus;int g_iLevel;
Mã:void App_CheckWinLost(){ if((!g_TankL.bReady && !g_TankR.bReady) || g_DataLevel.iCells[24][48] == TC_FREE) g_iStatus = SP_LOST; else if(g_IndexTank == 30 && g_arTankE.GetSize() == 0) g_iStatus = SP_WIN;}
Nếu TankE đã nhập cuộc hết 30 Tank và mảng hiện tại không còn Tank nào => Người chơi đã thắng vòng này.
Hàm đóng khung vùng chơi với độ dày là 4 Pixels với màu được thiết lập trước.
Mã:void DirectX_DrawFrame(int xFrame,int yFrame){ HDC hdc; HBRUSH hBrush; RECT r; int i; if(g_lpBack->GetDC(&hdc) == DD_OK) { hBrush = CreateSolidBrush(g_DataSetup.crFrame); for(i=1;i<4;i++) { SetRect(&r,xFrame-i,yFrame-i,xFrame+LARGE*13+1+i,yFrame+LARGE*13+1+i); FrameRect(hdc,&r,hBrush); } DeleteObject(hBrush); g_lpBack->ReleaseDC(hdc); }}
Mã:void DirectX_DrawTitle(int iLevel,int xFrame,int yFrame){ CHAR szTitle[MAX_PATH]; HDC hdc; HFONT hFont; RECT r; if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crTitle); SetRect(&r,xFrame,0,xFrame+LARGE*13,yFrame); hFont = CreateFont(24,0,0,0,FW_BOLD,0,0,0,0,0,0,0,0,"MS Sans Serif"); SelectObject(hdc,hFont); wsprintf(szTitle,"TANK2D - LEVEL %i",iLevel+1); DrawText(hdc,szTitle,-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); DeleteObject(hFont); g_lpBack->ReleaseDC(hdc); }}
Mã:void DirectX_DrawTextPause(int xFrame,int yFrame){ HDC hdc; RECT r; if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crText); SetRect(&r,xFrame,yFrame/2,xFrame+LARGE*13,yFrame); DrawText(hdc,"PAUSE - Press < Pause > to Continue !",-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); g_lpBack->ReleaseDC(hdc); }}
Mã:void DirectX_DrawTextLevel(int xFrame,int yFrame){ HDC hdc; RECT r; if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crText); SetRect(&r,xFrame,yFrame/2,xFrame+LARGE*13,yFrame); DrawText(hdc,"Press < Enter > to Play !",-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); g_lpBack->ReleaseDC(hdc); }}
Mã:void DirectX_DrawTextWin(int xFrame,int yFrame){ HDC hdc; RECT r; if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crText); SetRect(&r,xFrame,yFrame/2,xFrame+LARGE*13,yFrame); DrawText(hdc,"YOU WIN - Press < Enter > for Next Level !",-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); g_lpBack->ReleaseDC(hdc); }}
Mã:void DirectX_DrawTextLost(int xFrame,int yFrame){ HDC hdc; RECT r; if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crText); SetRect(&r,xFrame,yFrame/2,xFrame+LARGE*13,yFrame); DrawText(hdc,"YOU LOST - Press < Enter > to Replay This Level !",-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); g_lpBack->ReleaseDC(hdc); }}
Mã:void App_Update(int iLevel){ PENEMYTANK pTankE; DDBLTFX ddbltfx; HRESULT hr; int i; int xFrame = (GetSystemMetrics(SM_CXSCREEN) - LARGE*13)/2; int yFrame = (GetSystemMetrics(SM_CYSCREEN) - LARGE*13)/2; RECT r = { xFrame,yFrame,xFrame+LARGE*13,yFrame+LARGE*13}; // Xóa trống bề mặt Back ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = DirectX_ColorMatch(g_lpBack,g_DataSetup.crScreen); while(1) { hr = g_lpBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL,&ddbltfx); if(hr == DD_OK) break; if(hr == DDERR_SURFACELOST) if(!DirectX_RestoreSurfaceAll()) return; if(hr != DDERR_WASSTILLDRAWING) return; } // Tô màu vùng chơi ddbltfx.dwFillColor = DirectX_ColorMatch(g_lpBack,g_DataSetup.crBack); while(1) { hr = g_lpBack->Blt(&r,NULL,NULL,DDBLT_COLORFILL,&ddbltfx); if(hr == DD_OK) break; if(hr == DDERR_SURFACELOST) if(!DirectX_RestoreSurfaceAll()) return; if(hr != DDERR_WASSTILLDRAWING) return; } // Xử lý chương trình theo từng trạng thái switch(g_iStatus) { case SP_LEVEL: DirectX_DrawTitle(iLevel,xFrame,yFrame); DirectX_DrawFrame(xFrame,yFrame); DirectX_DrawBricks(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawSteels(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawGlides(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawRivers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawCovers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawHouse(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawTextLevel(xFrame,yFrame); // Trong còn trong màn hình giới thiệu vòng, lặp lại âm thanh nền nếu MCI đã chơi hết tập tin hoặc bị tạm dừng if(g_DataSetup.sndBackSound && g_hwndMCI) { TCHAR szText[MAX_PATH]; if(MCIWndGetMode(g_hwndMCI,szText,MAX_PATH) == MCI_MODE_STOP) { MCIWndHome(g_hwndMCI); MCIWndPlay(g_hwndMCI); } } break; case SP_PLAY: if(!g_bPause) { for(i=0;i<g_arTankE.GetSize();i++) // Cap nhat TankE if(pTankE = (PENEMYTANK)g_arTankE.GetAt(i)) TankE_Update(pTankE,g_DataLevel.iCells); Tank_Update(g_DataLevel.iCells); // Cap nhat Tank BulletE_UpdateAll(&g_arBullE,g_DataLevel.iCells); // Cap nhat BullE Bullet_UpdateAll(g_DataLevel.iCells); // Cap nhat Bull Fire_Update(); Smoke_Update(); Card_Update(); App_CheckWinLost(); } DirectX_DrawTitle(iLevel,xFrame,yFrame); DirectX_DrawFrame(xFrame,yFrame); DirectX_DrawBricks(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawSteels(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawGlides(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawRivers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawHouse(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawTankE(&g_arTankE,xFrame,yFrame); DirectX_DrawTankL(xFrame,yFrame); DirectX_DrawTankR(xFrame,yFrame); DirectX_DrawBulletE(&g_arBullE,xFrame,yFrame); DirectX_DrawBulletL(&g_arBullL,xFrame,yFrame); DirectX_DrawBulletR(&g_arBullR,xFrame,yFrame); DirectX_DrawFire(&g_arFire,xFrame,yFrame); DirectX_DrawCovers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawCards(&g_arCard,xFrame,yFrame); DirectX_DrawSmoke(&g_arSmoke,xFrame,yFrame); if(g_bPause) DirectX_DrawTextPause(xFrame,yFrame); break; case SP_WIN: Tank_Update(g_DataLevel.iCells); // Cap nhat Tank BulletE_UpdateAll(&g_arBullE,g_DataLevel.iCells); // Cap nhat BullE Bullet_UpdateAll(g_DataLevel.iCells); // Cap nhat Bull Fire_Update(); Smoke_Update(); Card_Update(); DirectX_DrawTitle(iLevel,xFrame,yFrame); DirectX_DrawFrame(xFrame,yFrame); DirectX_DrawBricks(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawSteels(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawGlides(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawRivers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawHouse(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawTankL(xFrame,yFrame); DirectX_DrawTankR(xFrame,yFrame); DirectX_DrawBulletE(&g_arBullE,xFrame,yFrame); DirectX_DrawBulletL(&g_arBullL,xFrame,yFrame); DirectX_DrawBulletR(&g_arBullR,xFrame,yFrame); DirectX_DrawFire(&g_arFire,xFrame,yFrame); DirectX_DrawCovers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawCards(&g_arCard,xFrame,yFrame); DirectX_DrawSmoke(&g_arSmoke,xFrame,yFrame); DirectX_DrawTextWin(xFrame,yFrame); break; case SP_LOST: for(i=0;i<g_arTankE.GetSize();i++) // Cap nhat TankE if(pTankE = (PENEMYTANK)g_arTankE.GetAt(i)) TankE_Update(pTankE,g_DataLevel.iCells); BulletE_UpdateAll(&g_arBullE,g_DataLevel.iCells); // Cap nhat BullE Bullet_UpdateAll(g_DataLevel.iCells); // Cap nhat Bull Fire_Update(); Smoke_Update(); Card_Update(); DirectX_DrawTitle(iLevel,xFrame,yFrame); DirectX_DrawFrame(xFrame,yFrame); DirectX_DrawBricks(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawSteels(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawGlides(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawRivers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawHouse(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawTankE(&g_arTankE,xFrame,yFrame); DirectX_DrawTankL(xFrame,yFrame); DirectX_DrawTankR(xFrame,yFrame); DirectX_DrawBulletE(&g_arBullE,xFrame,yFrame); DirectX_DrawBulletL(&g_arBullL,xFrame,yFrame); DirectX_DrawBulletR(&g_arBullR,xFrame,yFrame); DirectX_DrawFire(&g_arFire,xFrame,yFrame); DirectX_DrawCovers(g_DataLevel.iCells,xFrame,yFrame); DirectX_DrawCards(&g_arCard,xFrame,yFrame); DirectX_DrawSmoke(&g_arSmoke,xFrame,yFrame); DirectX_DrawTextLost(xFrame,yFrame); break; } // Duyệt qua mảng âm thanh, nếu âm thanh nào không còn chơi => Remove nó ra khỏi mảng. for(i=0;i<g_arWave.GetSize();i++) { CWaveSound * pWave = (CWaveSound*)g_arWave.GetAt(i); if(pWave) if(pWave->lpdsb) { DWORD dwStatus = 0; if(pWave->lpdsb->GetStatus(&dwStatus) == DS_OK) if(!(dwStatus & DSBSTATUS_PLAYING)) g_arWave.RemoveAt(i); } } // Flip Screen - Chuyển hình ảnh từ bề mặt tổng lên màn hình while(TRUE) { hr = g_lpMaster->Flip(NULL,0); if(hr == DD_OK) break; if(hr == DDERR_SURFACELOST) if(!DirectX_RestoreSurfaceAll()) return; if(hr != DDERR_WASSTILLDRAWING) return; }}
Ví dụ : Tank thì có thể ở trên River, Glide nhưng phải ở dưới Cover. Hoặc một đám khói thì phải ở trên cùng. v.v...
Tới đây đã có thể coi chương trình là tạm ổn chỉ còn mã hóa 2 hàm chính trong chương trình Windows nữa là có thể biên dịch và chạy.
Chương trình này không sử dụng MFC - Hai hàm còn lại là WinMain và WindowProc.
Chào tạm biệt. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 21-03-2014 lúc 03:21 PM - - -
NGÀY 28: Chuẩn bị cho Biên dịch phiên bản tạm thời.
Hàm sau đây vẽ các Text thuộc tính của Tank ta
Mã:void DirectX_DrawTankProperties(PTANK pTank,int xFrame,int yFrame){ CHAR szText[MAX_PATH]; HDC hdc; HFONT hFont; RECT r; UINT uFormat; if(pTank->bReady) { uFormat = (pTank == &g_TankL) ? (DT_LEFT|DT_SINGLELINE|DT_VCENTER) : (DT_RIGHT|DT_SINGLELINE|DT_VCENTER); if(g_lpBack->GetDC(&hdc) == DD_OK) { SetBkMode(hdc,TRANSPARENT); SetTextColor(hdc,g_DataSetup.crText); hFont = CreateFont(8,0,0,0,FW_NORMAL,0,0,0,0,0,0,0,0,"MS Sans Serif"); SelectObject(hdc,hFont); r.left = xFrame; r.right = xFrame + LARGE*13; r.top = yFrame + LARGE*13 + 10; r.bottom = r.top + 20; wsprintf(szText,"Amout : %i",pTank->cLife); // Số lần sống còn lại DrawText(hdc,szText,-1,&r,uFormat); r.top += 20; r.bottom += 20; wsprintf(szText,"Power : %i",pTank->iPower); // Sức mạnh hiện tại DrawText(hdc,szText,-1,&r,uFormat); r.top += 20; r.bottom += 20; wsprintf(szText,"Move Speed : %i",pTank->iSpeed); // Tốc độ di chuyển DrawText(hdc,szText,-1,&r,uFormat); r.top += 20; r.bottom += 20; wsprintf(szText,"Shoot Speed : %i",pTank->iShoot); // Tốc độ bắn DrawText(hdc,szText,-1,&r,uFormat); r.left += 100; r.right -= 100; r.top = yFrame + LARGE*13 + 10; r.bottom = r.top + 20; wsprintf(szText,"Bullet : %i",pTank->cBulletJoin); // Số đạn bắn liên thanh DrawText(hdc,szText,-1,&r,uFormat); if(pTank->cSafety > 0) { pTank->cSafety --; r.top += 20; r.bottom += 20; wsprintf(szText,"Safety : %i",pTank->cSafety); // Số thời khắc an toàn còn lại mà Tank được bảo vệ DrawText(hdc,szText,-1,&r,uFormat); } if(pTank->bBullF) { r.top += 20; r.bottom += 20; wsprintf(szText,"+ FireBullet"); // Tank bắn đạn lửa DrawText(hdc,szText,-1,&r,uFormat); } if(pTank->bRiver) { r.top += 20; r.bottom += 20; wsprintf(szText,"+ No River"); // Tank có thể vượt sông DrawText(hdc,szText,-1,&r,uFormat); } DeleteObject(hFont); g_lpBack->ReleaseDC(hdc); } }}
Hàm kế tiếp vẽ tất cả các TankE mà chưa tham chiến tại phần bên phải của khung chơi.
Mã:void DirectX_DrawRightSide(int xFrame,int yFrame){ int i,x,y; RECT r = {0,0,LARGE,LARGE}; // Lấy khung đầu tiên, dòng đầu tiên của Bitmap để vẽ. // Lần lượt vẽ tất cả các TankE chưa tham chiến for(i=29;i>=g_IndexTank;i--) { x = (29-i)%4; y = (29-i)/4; g_lpBack->BltFast(xFrame+LARGE*13+20+x*(LARGE+8),yFrame+y*(LARGE+8),g_lpTankE[g_DataLevel.iStyleTank[i]],&r,DDBLTFAST_SRCCOLORKEY); }}
Mã:LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam){ CHAR szFolder[MAX_PATH]; CHAR szFile[MAX_PATH]; PENEMYTANK pTankE; int iStyleTank; int i; switch(message) { case WM_ACTIVATEAPP: g_bActive = (BOOL)wparam; if(g_bActive) { g_bMoused = FALSE; if(g_lpKeyboard) g_lpKeyboard->Acquire(); if(g_lpMouse) g_lpMouse->Acquire(); } else g_bMoused = TRUE; break; case WM_CREATE: GetModuleFileName(NULL,szFolder,MAX_PATH); PathRemoveFileSpec(szFolder); lstrcat(szFolder,"\\Tank2D"); wsprintf(szFile,"%s\\BackSound.mp3",szFolder); if(!PathFileExists(szFile)) { wsprintf(szFile,"%s\\BackSound.wav",szFolder); if(!PathFileExists(szFile)) wsprintf(szFile,"%s\\BackSound.mid",szFolder); } if(g_hwndMCI = MCIWndCreate(hwnd,g_hInst,MCIWNDF_NOTIFYMODE|MCIWNDF_NOERRORDLG,szFile)) { ShowWindow(g_hwndMCI,SW_HIDE); if(g_DataSetup.sndBackSound) MCIWndPlay(g_hwndMCI); } if(!Level_LoadData(&g_DataLevel,g_iLevel)) { Cells_CreateValueRandom(g_DataLevel.iCells); for(i=0;i<5;i++) g_DataLevel.iStyleCard[i] = rand()%11; for(i=0;i<30;i++) g_DataLevel.iStyleTank[i] = rand()%4; Level_SaveData(&g_DataLevel,g_iLevel); } // TankL g_TankL.bBullF = FALSE; g_TankL.bReady = TRUE; g_TankL.bRiver = FALSE; g_TankL.cSafety = 0; g_TankL.cBulletJoin = 1; g_TankL.cLife = 5; g_TankL.cTimes = 8; g_TankL.iFrame = 0; g_TankL.iFrend = FM_UP; g_TankL.iFroze = 0; g_TankL.iPower = 5; g_TankL.iRequestFrend = FM_NULL; g_TankL.iShoot = 5; g_TankL.iSpeed = 1; g_TankL.x = LARGE*4; g_TankL.y = 12*LARGE; // TankR g_TankR.bBullF = FALSE; g_TankR.bReady = TRUE; g_TankR.bRiver = FALSE; g_TankR.cSafety = 0; g_TankR.cBulletJoin = 1; g_TankR.cLife = 5; g_TankR.cTimes = 8; g_TankR.iFrame = 0; g_TankR.iFrend = FM_UP; g_TankR.iFroze = 0; g_TankR.iPower = 5; g_TankR.iRequestFrend = FM_NULL; g_TankR.iShoot = 5; g_TankR.iSpeed = 1; g_TankR.x = LARGE*8; g_TankR.y = 12*LARGE; for(i=0;i<50;i++) { g_TypeTank[i].bBullF = (rand()%30 == 0) ? TRUE:FALSE; g_TypeTank[i].iPower = rand()%5 + 1; g_TypeTank[i].iShoot = rand()%6 + 5; g_TypeTank[i].iSmart = rand()%3; g_TypeTank[i].iSpeed = rand()%3 + 1; } break; case WM_TIMER: if(g_bPause) return 0; if(g_IndexTank < 30) { if(pTankE = (PENEMYTANK)malloc(sizeof(ENEMYTANK))) { iStyleTank = g_DataLevel.iStyleTank[g_IndexTank]; pTankE->bBullF = g_TypeTank[iStyleTank].bBullF; pTankE->bCard = (g_IndexTank % 6 == 0) ? TRUE:FALSE; pTankE->iCard = g_DataLevel.iStyleCard[g_IndexTank / 6]; pTankE->iFrame = 0; pTankE->iFrend = FM_DOWN; pTankE->iFroze = 0; pTankE->iPower = g_TypeTank[iStyleTank].iPower; pTankE->iRequest = FM_NULL; pTankE->iShoot = g_TypeTank[iStyleTank].iShoot; pTankE->iSmart = g_TypeTank[iStyleTank].iSmart; pTankE->iSpeed = g_TypeTank[iStyleTank].iSpeed; pTankE->iStyle = iStyleTank; pTankE->y = 0; if(g_IndexTank % 3 == 0) pTankE->x = 0; // TankE ben trai else if(g_IndexTank % 3 == 1) pTankE->x = LARGE * 6; // TankE o giua else pTankE->x = LARGE * 12; // TankE ben phai if(!g_arTankE.Add(pTankE)) free(pTankE); else g_IndexTank ++; } } else KillTimer(hwnd,1); return 0; case WM_SETCURSOR: if(!g_bMoused) SetCursor(NULL); else SetCursor(LoadCursor(NULL,IDC_ARROW)); return 0; case WM_MBUTTONDOWN: SendMessage(hwnd,WM_COMMAND,MAKEWPARAM(IDC_ENTER,0),0); return 0; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_ESCAPE: SendMessage(hwnd,WM_CLOSE,0,0); return 0; case IDC_F1: // Chưa cài đặt return 0; case IDC_F2: // Chưa cài đặt return 0; case IDC_F3: // Chưa cài đặt return 0; case IDC_F4: // Chưa cài đặt return 0; case IDC_F5: // Chưa cài đặt return 0; case IDC_F6: // Chưa cài đặt return 0; case IDC_F7: // Chưa cài đặt return 0; case IDC_F8: // Chưa cài đặt return 0; case IDC_F9: // Chưa cài đặt return 0; case IDC_F10: // Chưa cài đặt return 0; case IDC_F11: // Chưa cài đặt return 0; case IDC_F12: // Chưa cài đặt return 0; case IDC_PAUSE: if(g_iStatus == SP_PLAY) g_bPause ^= 1; return 0; case IDC_INSERT: // Chưa cài đặt return 0; case IDC_DELETE: // Chưa cài đặt return 0; case IDC_HOME: // Chưa cài đặt return 0; case IDC_END: // Chưa cài đặt return 0; case IDC_PAGEUP: // Di chuyển lên một vòng if(g_iStatus == SP_LEVEL) if(g_iLevel > 0) { g_iLevel --; if(!Level_LoadData(&g_DataLevel,g_iLevel)) // Nạp lại dữ liệu { Cells_CreateValueRandom(g_DataLevel.iCells); for(i=0;i<5;i++) g_DataLevel.iStyleCard[i] = rand()%11; for(i=0;i<30;i++) g_DataLevel.iStyleTank[i] = rand()%4; Level_SaveData(&g_DataLevel,g_iLevel); } } return 0; case IDC_PAGEDOWN: // Di chuyển xuống một vòng if(g_iStatus == SP_LEVEL) { g_iLevel ++; if(!Level_LoadData(&g_DataLevel,g_iLevel)) // Nạp lại dữ liệu { Cells_CreateValueRandom(g_DataLevel.iCells); for(i=0;i<5;i++) g_DataLevel.iStyleCard[i] = rand()%11; for(i=0;i<30;i++) g_DataLevel.iStyleTank[i] = rand()%4; Level_SaveData(&g_DataLevel,g_iLevel); } } return 0; case IDC_ENTER: if(g_iStatus == SP_LEVEL) { g_iStatus = SP_PLAY; if(g_hwndMCI) MCIWndStop(g_hwndMCI); SendMessage(hwnd,WM_TIMER,0,0);// Cho 3 TankE xuất hiện khi bắt đầu chơi 1 vòng SendMessage(hwnd,WM_TIMER,0,0); SendMessage(hwnd,WM_TIMER,0,0); SetTimer(hwnd,1,5000,NULL); // Định thời để lần lượt xuất hiện các Tank địch } else if(g_iStatus == SP_WIN) { g_iLevel ++; if(!Level_LoadData(&g_DataLevel,g_iLevel)) { Cells_CreateValueRandom(g_DataLevel.iCells); for(i=0;i<5;i++) g_DataLevel.iStyleCard[i] = rand()%11; for(i=0;i<30;i++) g_DataLevel.iStyleTank[i] = rand()%4; Level_SaveData(&g_DataLevel,g_iLevel); } g_IndexTank = 0; g_arBullE.RemoveAll(); g_arBullL.RemoveAll(); g_arBullR.RemoveAll(); g_arCard.RemoveAll(); g_arFire.RemoveAll(); g_arSmoke.RemoveAll(); g_TankL.cSafety = 0; g_TankL.iFrame = 0; g_TankL.iFrend = FM_UP; g_TankL.iFroze = 0; g_TankL.iRequestFrend = FM_NULL; g_TankL.x = LARGE*4; g_TankL.y = 12*LARGE; g_TankR.cSafety = 0; g_TankR.iFrame = 0; g_TankR.iFrend = FM_UP; g_TankR.iFroze = 0; g_TankR.iRequestFrend = FM_NULL; g_TankR.x = LARGE*8; g_TankR.y = 12*LARGE; g_iStatus = SP_LEVEL; KillTimer(hwnd,1); } else if(g_iStatus == SP_LOST) { if(!Level_LoadData(&g_DataLevel,g_iLevel)) { Cells_CreateValueRandom(g_DataLevel.iCells); for(i=0;i<5;i++) g_DataLevel.iStyleCard[i] = rand()%11; for(i=0;i<30;i++) g_DataLevel.iStyleTank[i] = rand()%4; Level_SaveData(&g_DataLevel,g_iLevel); } g_arBullE.RemoveAll(); g_arBullL.RemoveAll(); g_arBullR.RemoveAll(); g_arCard.RemoveAll(); g_arFire.RemoveAll(); g_arSmoke.RemoveAll(); g_arTankE.RemoveAll(); g_IndexTank = 0; // TankL g_TankL.bBullF = FALSE; g_TankL.bReady = TRUE; g_TankL.bRiver = FALSE; g_TankL.cSafety = 0; g_TankL.cBulletJoin = 1; g_TankL.cLife = 5; g_TankL.cTimes = 8; g_TankL.iFrame = 0; g_TankL.iFrend = FM_UP; g_TankL.iFroze = 0; g_TankL.iPower = 5; g_TankL.iRequestFrend = FM_NULL; g_TankL.iShoot = 5; g_TankL.iSpeed = 1; g_TankL.x = LARGE*4; g_TankL.y = 12*LARGE; // TankR g_TankR.bBullF = FALSE; g_TankR.bReady = TRUE; g_TankR.bRiver = FALSE; g_TankR.cSafety = 0; g_TankR.cBulletJoin = 1; g_TankR.cLife = 5; g_TankR.cTimes = 8; g_TankR.iFrame = 0; g_TankR.iFrend = FM_UP; g_TankR.iFroze = 0; g_TankR.iPower = 5; g_TankR.iRequestFrend = FM_NULL; g_TankR.iShoot = 5; g_TankR.iSpeed = 1; g_TankR.x = LARGE*8; g_TankR.y = 12*LARGE; g_iStatus = SP_LEVEL; KillTimer(hwnd,1); } return 0; } break; case WM_DESTROY: KillTimer(hwnd,1); if(g_hwndMCI) MCIWndDestroy(g_hwndMCI); g_arWave.RemoveAll(); g_arTankE.RemoveAll(); g_arBullE.RemoveAll(); g_arBullL.RemoveAll(); g_arBullR.RemoveAll(); g_arCard.RemoveAll(); g_arSmoke.RemoveAll(); g_arFire.RemoveAll(); DirectX_DeleteDD(); DirectX_DeleteDS(); DirectX_DeleteDI(); PostQuitMessage(0); return 0; } return DefWindowProc(hwnd,message,wparam,lparam);}
Mình cố gắng viết theo tiêu chuẩn của 1 hàm Xử lý thông điệp Windows ( các bạn nào đã học C for Windows chắc là nắm rõ).
Mã:int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrev,LPSTR lp,int nShow){ MSG msg; WNDCLASS w; HWND hwnd; HACCEL hAccel; if(!App_EnableRun()) return 0; if(!App_UpdateFiles(hInstance)) return 0; srand(time(NULL)); App_CheckLevelFile(); App_CheckSoundFile(); if(!Setup_LoadData(&g_DataSetup)) { g_DataSetup.crBack = RGB(0,0,0); g_DataSetup.crFrame = RGB(255,102,0); g_DataSetup.crScreen = RGB(0,51,0); g_DataSetup.crText = RGB(0,255,255); g_DataSetup.crTitle = RGB(255,255,0); g_DataSetup.sndBackSound = TRUE; g_DataSetup.sndBonusSound = TRUE; g_DataSetup.sndEnemyLargeBullet = FALSE; g_DataSetup.sndEnemyShoot = FALSE; g_DataSetup.sndEnemySmallBullet = FALSE; g_DataSetup.sndLostSound = TRUE; g_DataSetup.sndMineSound = TRUE; g_DataSetup.sndOurLargeBullet = TRUE; g_DataSetup.sndOurShoot = TRUE; g_DataSetup.sndOurSmallBullet = TRUE; g_DataSetup.sndWinSound = TRUE; Setup_SaveData(&g_DataSetup); } g_hInst = hInstance; w.cbClsExtra = 0; w.cbWndExtra = 0; w.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); w.hCursor = LoadCursor(NULL,IDC_ARROW); w.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_TANK2D)); w.hInstance = hInstance; w.lpfnWndProc = WndProc; w.lpszClassName = "Tank2D"; w.lpszMenuName = NULL; w.style = CS_DBLCLKS; if(!RegisterClass(&w)) return 0; if(!(hAccel = LoadAccelerators(hInstance,MAKEINTRESOURCE(IDR_ACCEL)))) return 0; if(!(hwnd = CreateWindowEx(0,w.lpszClassName,w.lpszClassName,WS_VISIBLE|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),NULL,NULL,hInstance,NULL))) return 0; // Các khởi tạo DirectX chỉ được thực hiện sau khi cửa sổ đã hiển thị, nên chúng ta không khởi tạo trong thông điệp WM_CREATE. if(!DirectX_InitDD(hwnd) || !DirectX_RestoreSurfaceAll() || !DirectX_InitDI(hInstance,hwnd) || !DirectX_InitDS(hwnd)) { DestroyWindow(hwnd); return 0; } while(TRUE) { if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) { if(!GetMessage(&msg,NULL,0,0)) return msg.wParam; if(!TranslateAccelerator(hwnd,hAccel,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else if(g_bActive) App_Update(g_iLevel); else WaitMessage(); }}
Mình đã biên dịch và chạy tương đối ổ định, đang tiếp tục tìm các lỗi Logic, màn hình biên dịch như sau
Thư mục dự án mình sẽ làm gọn và post lên trang kế tiếp.
Chào thân ái.
[IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG][IMG]images/smilies/opacli.gif[/IMG]
<font color="silver">- - - Nội dung đã được cập nhật ngày 21-03-2014 lúc 03:52 PM - - -
Đây là thư mục dự án Tank2D
-
25-03-2014, 10:08 AM #15Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
Ngày 29: Chức năng của F2
Trong chương trình Tank2D còn rất nhiều điều chúng ta chưa xử lý, hôm nay mình viết tiếp các thao tác của người chơi khi thao tác
thiết kế lại một vòng chơi bất kỳ. Như đã biết, một vòng chơi có 3 yếu tố : Cấu trúc khung chơi, các kiểu Tank. và các thẻ cộng thêm.
Ngày hôm nay, mình sẽ mã thêm cho chức năng của phím F2 - Người chơi thay đổi kết cấu của 1 vòng chơi.
Điều này cần thiết phải hiển thị 1 hộp thoại cho người chơi thay đổi vòng chơi một cách trực quan nhất.
Từ IDE của VC++6.0, Insert->Resource...->Insert Resource->Dialog->New. Thay đổi id hộp thoại thành IDD_DIALOG_DESIGN
Trong bản mẫu hôp thoại, xóa 2 button <OK> và <Cancel>, chúng ta không cần 2 button này.
Tính toán ban đầu cho thấy chúng ta cần 52*52=2704 button cho các SmallCells, 30 button cho các hình ảnh Tank, 5 hình ảnh cho các Card, trình soạn thảo tài nguyên của
Microsotft VC++6.0 không cho phép vượt quá 512 điều khiển trên khung hiển thị khi thiết kế. Vì vậy chúng ta sẽ dùng mã để thêm vào khi chượng trình thực thi.
Trong hàm WndProc(), ở Đoạn mã xử lý thông điệp WM_COMMAND thêm vào như sau:
Mã:case IDC_F2: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_DESIGN),hwnd,DlgProc_Design); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_Design(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){#define IDC_BUTTON_RANDOM 10001#define IDC_BUTTON_RESET 10002#define IDC_BUTTON_UPDATE 10003#define IDC_BUTTON_CLOSE 10004#define IDC_COMBO_CURSOR 10005 static HWND hCell[52][52]; // 2704 static HWND hTank[30]; // static HWND hCard[5]; // static HWND hCombo; static DATALEVEL Data; static int iLevel; static HBRUSH hbrBack; static int iCursor; static BOOL bChanged; LPDRAWITEMSTRUCT pd; LPDIRECTDRAWSURFACE lpSur; CHAR szText[MAX_PATH]; RECT r; HBRUSH hBrush; HDC hdcSur; HANDLE hFile; int i,x,y,x1,y1,m,n,cx,cy,value; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); bChanged = FALSE; iLevel = g_iLevel; wsprintf(szText,"Design Level %i",iLevel+1); SetWindowText(hDlg,szText); if(!Level_LoadData(&Data,iLevel)) { Cells_CreateValueRandom(Data.iCells); for(i=0;i<30;i++) Data.iStyleTank[i] = rand()%50; for(i=0;i<5;i++) Data.iStyleCard[i] = rand()%11; } else Cells_CreateValueDefault(Data.iCells); SetRect(&r,0,0,20+LARGE*13+20+40*4+20,20+LARGE*13+20+25+20); AdjustWindowRect(&r,WS_CAPTION,FALSE); cx = r.right-r.left; cy = r.bottom-r.top; x = (GetSystemMetrics(SM_CXSCREEN) - cx)/2; y = (GetSystemMetrics(SM_CYSCREEN) - cy)/2; MoveWindow(hDlg,x,y,cx,cy,FALSE); for(x=0;x<52;x++) for(y=0;y<52;y++) hCell[x][y] = CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,20+x*8,20+y*8,8,8,hDlg,(HMENU)(x+y*52),g_hInst,NULL); for(i=0;i<30;i++) hTank[i] = CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,20+LARGE*13+20+(i%4)*40,20+(i/4)*40,32,32,hDlg,(HMENU)(5000+i),g_hInst,NULL); for(i=0;i<5;i++) hCard[i] = CreateWindow("button","",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,20+LARGE*13+20+i*30,20+40*8+20,SMALL*3,SMALL*3,hDlg,(HMENU)(6000+i),g_hInst,NULL); hCombo = CreateWindow("combobox","",WS_VSCROLL|WS_CHILD|WS_VISIBLE|CBS_DROPDOWNLIST,20+LARGE*13+20,20+40*8+20+SMALL*3+20,40*4,100,hDlg,(HMENU)IDC_COMBO_CURSOR,g_hInst,NULL); SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)"Change LargeCell"); SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)"Change MediumCell"); SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)"Change SmallCell"); SendMessage(hCombo,CB_SETCURSEL,iCursor,0); CreateWindow("button","Random",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,20+LARGE, 20+LARGE*13+20,LARGE*3,25,hDlg,(HMENU)IDC_BUTTON_RANDOM,g_hInst,NULL); CreateWindow("button","Reset", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,20+LARGE*5, 20+LARGE*13+20,LARGE*3,25,hDlg,(HMENU)IDC_BUTTON_RESET,g_hInst,NULL); CreateWindow("button","Update",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,20+LARGE*9, 20+LARGE*13+20,LARGE*3,25,hDlg,(HMENU)IDC_BUTTON_UPDATE,g_hInst,NULL); CreateWindow("button","Close", WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,20+LARGE*14, 20+LARGE*13+20,LARGE*4,25,hDlg,(HMENU)IDC_BUTTON_CLOSE,g_hInst,NULL); hbrBack = CreateSolidBrush(g_DataSetup.crScreen); return TRUE; case WM_DRAWITEM: pd = (LPDRAWITEMSTRUCT) lparam; if(pd->CtlID < 52*52) { x = pd->CtlID % 52; y = pd->CtlID / 52; if(Data.iCells[x][y] == TC_FREE) { hBrush = CreateSolidBrush(g_DataSetup.crBack); FillRect(pd->hDC,&pd->rcItem,hBrush); DeleteObject(hBrush); } else if(Data.iCells[x][y] == TC_BRICK) { if(g_lpBrick->GetDC(&hdcSur) == DD_OK) { BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0,0,SRCCOPY); g_lpBrick->ReleaseDC(hdcSur); } } else if(Data.iCells[x][y] == TC_STEEL) { if(g_lpSteel->GetDC(&hdcSur) == DD_OK) { if(x%2==0 && y%2==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0,0,SRCCOPY); else if(x%2==0 && y%2!=0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0,SMALL,SRCCOPY); else if(x%2!=0 && y%2==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL,0,SRCCOPY); else BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL,SMALL,SRCCOPY); g_lpSteel->ReleaseDC(hdcSur); } } else { if(Data.iCells[x][y] == TC_RIVER) lpSur = g_lpRiver; else if(Data.iCells[x][y] == TC_COVER) lpSur = g_lpCover; else if(Data.iCells[x][y] == TC_GLIDE) lpSur = g_lpGlide; else lpSur = g_lpHouse; if(lpSur->GetDC(&hdcSur) == DD_OK) { if(x%4==0 && y%4==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0, 0, SRCCOPY); else if(x%4==0 && y%4==1) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0, SMALL, SRCCOPY); else if(x%4==0 && y%4==2) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0, SMALL*2,SRCCOPY); else if(x%4==0 && y%4==3) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,0, SMALL*3,SRCCOPY); else if(x%4==1 && y%4==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL, 0, SRCCOPY); else if(x%4==1 && y%4==1) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL, SMALL, SRCCOPY); else if(x%4==1 && y%4==2) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL, SMALL*2,SRCCOPY); else if(x%4==1 && y%4==3) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL, SMALL*3,SRCCOPY); else if(x%4==2 && y%4==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*2, 0, SRCCOPY); else if(x%4==2 && y%4==1) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*2, SMALL, SRCCOPY); else if(x%4==2 && y%4==2) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*2, SMALL*2,SRCCOPY); else if(x%4==2 && y%4==3) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*2, SMALL*3,SRCCOPY); else if(x%4==3 && y%4==0) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*3, 0, SRCCOPY); else if(x%4==3 && y%4==1) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*3, SMALL, SRCCOPY); else if(x%4==3 && y%4==2) BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*3, SMALL*2,SRCCOPY); else BitBlt(pd->hDC,0,0,SMALL,SMALL,hdcSur,SMALL*3, SMALL*3,SRCCOPY); lpSur->ReleaseDC(hdcSur); } } } else if(pd->CtlID >= 5000 && pd->CtlID <= 5029) { if(g_lpTankE[Data.iStyleTank[29-(pd->CtlID - 5000)]]->GetDC(&hdcSur) == DD_OK) { BitBlt(pd->hDC,0,0,LARGE,LARGE,hdcSur,0,0,SRCCOPY); g_lpTankE[Data.iStyleTank[29-(pd->CtlID - 5000)]]->ReleaseDC(hdcSur); } } else if(pd->CtlID >= 6000 && pd->CtlID <= 6004) { if(g_lpCard[Data.iStyleCard[pd->CtlID - 6000]]->GetDC(&hdcSur) == DD_OK) { BitBlt(pd->hDC,0,0,SMALL*3,SMALL*3,hdcSur,0,0,SRCCOPY); g_lpCard[Data.iStyleCard[pd->CtlID - 6000]]->ReleaseDC(hdcSur); } } return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_COMBO_CURSOR: if(HIWORD(wparam) == CBN_SELCHANGE) { i = SendMessage(hCombo,CB_GETCURSEL,0,0); if(i != CB_ERR) iCursor = i; return TRUE; } break; case IDC_BUTTON_RANDOM: Cells_CreateValueRandom(Data.iCells); for(i=0;i<30;i++) Data.iStyleTank[i] = rand()%50; for(i=0;i<5;i++) Data.iStyleCard[i] = rand()%11; for(x=0;x<52;x++) for(y=0;y<52;y++) InvalidateRect(hCell[x][y],NULL,FALSE); for(i=0;i<30;i++) InvalidateRect(hTank[i],NULL,FALSE); for(i=0;i<5;i++) InvalidateRect(hCard[i],NULL,FALSE); bChanged = TRUE; return TRUE; case IDC_BUTTON_RESET: GetModuleFileName(NULL,szText,MAX_PATH); PathRemoveFileSpec(szText); lstrcat(szText,"\\Tank2D"); wsprintf(szText,"%s\\Level%i.lev",szText,iLevel+1); if(INVALID_HANDLE_VALUE!=(hFile=CreateFile(szText,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL))) { HRSRC hFind,hLoad; PCHAR pLock; BOOL bFlag = TRUE; if(hFind = FindResource(GetModuleHandle(NULL),MAKEINTRESOURCE(IDR_LEVEL1+iLevel),"LEVEL")) if(hLoad = (HRSRC)LoadResource(GetModuleHandle(NULL),hFind)) if(pLock = (PCHAR)LockResource(hLoad)) { DWORD dw,dwSize = SizeofResource(GetModuleHandle(NULL),hFind); if(!WriteFile(hFile,pLock,dwSize,&dw,NULL) || dwSize != dw) bFlag = FALSE; } CloseHandle(hFile); if(!bFlag) DeleteFile(szText); if(!Level_LoadData(&Data,iLevel)) { Cells_CreateValueRandom(Data.iCells); for(i=0;i<30;i++) Data.iStyleTank[i] = rand()%50; for(i=0;i<5;i++) Data.iStyleCard[i] = rand()%11; } else Cells_CreateValueDefault(Data.iCells); for(x=0;x<52;x++) for(y=0;y<52;y++) InvalidateRect(hCell[x][y],NULL,FALSE); for(i=0;i<30;i++) InvalidateRect(hTank[i],NULL,FALSE); for(i=0;i<5;i++) InvalidateRect(hCard[i],NULL,FALSE); bChanged = TRUE; } return TRUE; case IDC_BUTTON_UPDATE: if(bChanged) { Level_SaveData(&Data,iLevel); CopyMemory(&g_DataLevel,&Data,sizeof(DATALEVEL)); DirectX_RestoreSurfaceAll(); bChanged = FALSE; } return TRUE; case IDC_BUTTON_CLOSE: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } if(LOWORD(wparam) < 52*52) { x = LOWORD(wparam) % 52; y = LOWORD(wparam) / 52; if(y<4) { if(x<4) return 0; if(x>=24 && x<28) return 0; if(x>47) return 0; } if(x>=16 && x<36 && y>43) return 0; value = Data.iCells[x][y]; if(iCursor == 0) // Thay doi 4x4 { value++; if(value == TC_HOUSE) value = TC_FREE; x1 = x/4*4; y1 = y/4*4; for(m=x1;m<x1+4;m++) for(n=y1;n<y1+4;n++) { Data.iCells[m][n] = value; InvalidateRect(hCell[m][n],NULL,FALSE); } } else if(iCursor == 1) // Thay doi 2x2 { if(value > TC_STEEL) { iCursor = 0; SendMessage(hCombo,CB_SETCURSEL,0,0); value++; if(value == TC_HOUSE) value = TC_FREE; x1 = x/4*4; y1 = y/4*4; for(m=x1;m<x1+4;m++) for(n=y1;n<y1+4;n++) { Data.iCells[m][n] = value; InvalidateRect(hCell[m][n],NULL,FALSE); } } else { value++; if(value > TC_STEEL) value = TC_FREE; x1 = x/2*2; y1 = y/2*2; for(m=x1;m<x1+2;m++) for(n=y1;n<y1+2;n++) { Data.iCells[m][n] = value; InvalidateRect(hCell[m][n],NULL,FALSE); } } } else // Thay doi 1 { if(value > TC_STEEL) { iCursor = 0; SendMessage(hCombo,CB_SETCURSEL,0,0); value++; if(value == TC_HOUSE) value = TC_FREE; x1 = x/4*4; y1 = y/4*4; for(m=x1;m<x1+4;m++) for(n=y1;n<y1+4;n++) { Data.iCells[m][n] = value; InvalidateRect(hCell[m][n],NULL,FALSE); } } else if(value == TC_STEEL) { iCursor = 1; SendMessage(hCombo,CB_SETCURSEL,1,0); value++; if(value > TC_STEEL) value = TC_FREE; x1 = x/2*2; y1 = y/2*2; for(m=x1;m<x1+2;m++) for(n=y1;n<y1+2;n++) { Data.iCells[m][n] = value; InvalidateRect(hCell[m][n],NULL,FALSE); } } else { value++; if(value > TC_BRICK) value = TC_FREE; Data.iCells[x][y] = value; InvalidateRect(hCell[x][y],NULL,FALSE); } } bChanged = TRUE; return TRUE; } i = LOWORD(wparam); if(i >= 5000 && i <= 5029) { if(++Data.iStyleTank[29-(i-5000)] >= 50) Data.iStyleTank[29-(i-5000)] = 0; SetFocus(hDlg); bChanged = TRUE; return TRUE; } break; case WM_CTLCOLORDLG: return (int)hbrBack; case WM_CLOSE: DeleteObject(hbrBack); EndDialog(hDlg,0); return TRUE; } return FALSE;}
Ở đây, vì mình chỉ chạy theo mã hóa nên ít có chú thích, bạn nào thấy khó hiểu thì cứ nêu lên mình sẽ giải thích rõ hơn.
Mong rằng các bạn có thể hiểu và góp ý thêm cho mình.
Ngày hôm nay đến đây thôi, cũng mỏi tay rồi, hẹn ngày sau chúng ta sẽ xử lý F3 !
[IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG] [IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 25-03-2014 lúc 03:08 PM - - -</font>
<font color="#0000FF">NGÀY 30: Chức năng của phím F3
Chúng ta sẽ cho người chơi thực hiện các thay đổi màu sắc bằng phím F3, màu sẽ được lưu trữ bên ngoài chương trình nên được sử dụng cho cả các lần chơi sau.
Tạo một hộp thoại với id là IDD_DIALOG_COLOR.
Ngoài 2 button có sẵn, chúng ta thêm vào 6 Button mới có id là : IDC_BUTTON1,IDC_BUTTON2,IDC_BUTTON3,IDC_BUTTON4,ID C_BUTTON5,IDC_BUTTON6.
5 Button đầu có kiểu tự vẽ, button thứ 6 bình thường có Text là "Origin".
Đổi Text button OK thành "Update".
Đổi Text button Cancel thành "Close".
Sắp xếp lại cho dễ nhìn như hình ở cuối ngày.
Trong hàm WndProc(), ở Đoạn mã xử lý thông điệp WM_COMMAND thêm vào như sau:
Mã:case IDC_F3: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_COLOR),hwnd,DlgProc_Color); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_Color(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ static HWND hButton[5]; static DATASETUP Data; static BOOL bChanged; LPDRAWITEMSTRUCT pd; HBRUSH hBrush; CHOOSECOLOR cc; COLORREF arColor[16]; COLORREF cr; CHAR szText[MAX_PATH]; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); hButton[0] = GetDlgItem(hDlg,IDC_BUTTON1); hButton[1] = GetDlgItem(hDlg,IDC_BUTTON2); hButton[2] = GetDlgItem(hDlg,IDC_BUTTON3); hButton[3] = GetDlgItem(hDlg,IDC_BUTTON4); hButton[4] = GetDlgItem(hDlg,IDC_BUTTON5); CopyMemory(&Data,&g_DataSetup,sizeof(DATASETUP)); bChanged = FALSE; return TRUE; case WM_DRAWITEM: pd = (LPDRAWITEMSTRUCT)lparam; if(pd->CtlID == IDC_BUTTON1) cr = Data.crScreen; // Screen Color else if(pd->CtlID == IDC_BUTTON2) cr = Data.crBack; // Back Color else if(pd->CtlID == IDC_BUTTON3) cr = Data.crFrame; // Frame Color else if(pd->CtlID == IDC_BUTTON4) cr = Data.crTitle; // Title Color else cr = Data.crText; // Text Color hBrush = CreateSolidBrush(cr); FillRect(pd->hDC,&pd->rcItem,hBrush); DeleteObject(hBrush); SetTextColor(pd->hDC, (~(cr << 8)) >> 8); // Màu chữ là màu đảo của màu nền SetBkMode(pd->hDC,TRANSPARENT); if(pd->CtlID == IDC_BUTTON1) wsprintf(szText,"Screen Color"); else if(pd->CtlID == IDC_BUTTON2) wsprintf(szText,"Back Color"); else if(pd->CtlID == IDC_BUTTON3) wsprintf(szText,"Frame Color"); else if(pd->CtlID == IDC_BUTTON4) wsprintf(szText,"Title Color"); else wsprintf(szText,"Text Color"); DrawText(pd->hDC,szText,-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_VCENTER); return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_BUTTON1: case IDC_BUTTON2: case IDC_BUTTON3: case IDC_BUTTON4: case IDC_BUTTON5: if(LOWORD(wparam) == IDC_BUTTON1) cr = Data.crScreen; // Screen Color else if(LOWORD(wparam) == IDC_BUTTON2) cr = Data.crBack; // Back Color else if(LOWORD(wparam) == IDC_BUTTON3) cr = Data.crFrame; // Frame Color else if(LOWORD(wparam) == IDC_BUTTON4) cr = Data.crTitle; // Title Color else cr = Data.crText; // Text Color ZeroMemory(&cc,sizeof(CHOOSECOLOR)); cc.lStructSize = sizeof(CHOOSECOLOR); cc.hwndOwner = hDlg; cc.lpCustColors = arColor; cc.Flags = CC_FULLOPEN|CC_RGBINIT; cc.rgbResult = cr; if(ChooseColor(&cc)) // Show ChooseColor Dialog if(cr != cc.rgbResult) { if(LOWORD(wparam) == IDC_BUTTON1) { Data.crScreen = cc.rgbResult; InvalidateRect(hButton[0],NULL,FALSE);} // Screen Color else if(LOWORD(wparam) == IDC_BUTTON2) { Data.crBack = cc.rgbResult; InvalidateRect(hButton[1],NULL,FALSE);} // Back Color else if(LOWORD(wparam) == IDC_BUTTON3) { Data.crFrame = cc.rgbResult; InvalidateRect(hButton[2],NULL,FALSE);} // Frame Color else if(LOWORD(wparam) == IDC_BUTTON4) { Data.crTitle = cc.rgbResult; InvalidateRect(hButton[3],NULL,FALSE);} // Title Color else { Data.crText = cc.rgbResult; InvalidateRect(hButton[4],NULL,FALSE);} // Text Color bChanged = TRUE; } return TRUE; case IDC_BUTTON6: Data.crScreen = RGB(0,51,0); InvalidateRect(hButton[0],NULL,FALSE); // Screen Color Data.crBack = RGB(0,0,0); InvalidateRect(hButton[1],NULL,FALSE); // Back Color Data.crFrame = RGB(255,102,0); InvalidateRect(hButton[2],NULL,FALSE); // Frame Color Data.crTitle = RGB(255,255,0); InvalidateRect(hButton[3],NULL,FALSE); // Title Color Data.crText = RGB(0,255,255); InvalidateRect(hButton[4],NULL,FALSE); // Text Color bChanged = TRUE; return TRUE; case IDOK: if(bChanged) { CopyMemory(&g_DataSetup,&Data,sizeof(DATASETUP)); Setup_SaveData(&g_DataSetup); } case IDCANCEL: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CLOSE: EndDialog(hDlg,0); return TRUE; } return FALSE;}
Button "Origin" là để lấy lại màu nguyên thủy ( màu mặc định lấy từ trong chương trình).
Nếu người chơi chọn "Update", và nếu có bất kỳ 1 trong 5 màu đã thay đổi, chương trình sẽ cập nhật và lưu lại cho sau này.
Có 1 chỗ mã hơi rắc rối : SetTextColor(pd->hDC, (~(cr << 8)) >> 8);
Hiện tại, màu rgb được lưu trong 32bits, nhưng giá trị chỉ ở trong 24Bits cuối, 8Bits đầu phải là 0, vì vậy mới có cách tính trên.
Ví dụ :
_ Cho màu A là : 00000000 01010111 00110101 11110001
_ Dịch trái 8Bits: 01010111 00110101 11110001 00000000
_ Đảo màu đã dịch: 10101000 11001010 00001110 11111111
_ Dịch phải 8Bits: 00000000 10101000 11001010 00001110
Màu cuối cùng là màu đảo của A.
Ngày hôm nay tới đây, tạm gác bút thôi. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
27-03-2014, 10:41 AM #16Junior Member
- Ngày tham gia
- Dec 2015
- Bài viết
- 0
NGÀY 31: Chức năng của phím F1
Hầu hết các bạn nào đã học qua C for Windows hoặc VC đều có thể xuất một hộp thoại About một cách dễ dàng.
Ngày nay, chúng ta sẽ thêm nó khi người sử dụng nhấn F1.
Tạo một bản mẫu hộp thoại mới, thay đổi id = IDD_DIALOG_ABOUT, xóa button có sẵn OK.
Đổi kiểu của button Cancel thành tự vẽ, canh chỉnh lại hộp thoại cho khoảng 6 dòng Text, bề ngang đủ chứa Text trong thanh địa chỉ
mà bạn thấy ở phía trên, đây chỉ là tương đối thôi, sau khi biên dịch và chạy bạn có thể thay đổi lại cho vừa vặn.
Mã cập nhật cho hàm WndProc, thông điệp WM_COMMAND, cho F1 như sau
Mã:case IDC_F1: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_ABOUT),hwnd,DlgProc_About); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_About(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ LPDRAWITEMSTRUCT pd; HBRUSH hBrush; HFONT hFont; RECT r; int i; PCHAR psz[] = { "__________ GAME DIRECTX - TANK2D __________", "Programer : Nguyen Minh Hoang", "Language : C / C++", "IDE : Microsoft Visual C++6.0", "Building : 2-3 / 2014", "http://diendan.congdongcviet.com/threads/t203373::thuc-hanh-lap-trinh-game-vc-6-0-su-dung-directx-tank2d.cpp" }; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); // Nạp biểu tượng chính cho hộp thoại GetClientRect(hDlg,&r); MoveWindow(GetDlgItem(hDlg,IDCANCEL),0,0,r.right-r.left,r.bottom-r.top,FALSE); // Mở rộng Button Cancel chiếm hết vùng Client return TRUE; case WM_DRAWITEM: pd = (LPDRAWITEMSTRUCT)lparam; hBrush = CreateSolidBrush(g_DataSetup.crScreen); FillRect(pd->hDC,&pd->rcItem,hBrush); // Tô màu button Cancel DeleteObject(hBrush); SetBkMode(pd->hDC,TRANSPARENT); GetClientRect(GetDlgItem(hDlg,IDCANCEL),&r); SetTextColor(pd->hDC,g_DataSetup.crTitle); hFont = CreateFont(24,0,0,0,FW_BOLD,0,0,0,0,0,0,0,0,"MS Sans Serif"); // Tạo Font chữ lớn cho Title SelectObject(pd->hDC,hFont); r.top = 20; r.bottom = 50; DrawText(pd->hDC,psz[0],-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); DeleteObject(hFont); r.top += 50; r.bottom = r.top + 25; SetTextColor(pd->hDC,g_DataSetup.crText); hFont = CreateFont(8,0,0,0,FW_NORMAL,0,0,0,0,0,0,0,0,"MS Sans Serif"); // Tạo Font chữ nhỏ cho các Text SelectObject(pd->hDC,hFont); for(i=1;i<6;i++) { if(i==5) SetTextColor(pd->hDC,g_DataSetup.crFrame); // Tạo màu khác cho Link DrawText(pd->hDC,psz[i],-1,&r,DT_SINGLELINE|DT_CENTER|DT_VCENTER); r.top += 25; r.bottom = r.top + 25; } DeleteObject(hFont); return TRUE; case WM_COMMAND: if(LOWORD(wparam) == IDCANCEL) { SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CLOSE: EndDialog(hDlg,0); return TRUE; } return FALSE;}
quảng cáo cho Game mà thôi ( cũng khuyến khích bạn thêm bất kỳ hoa lá cành ở hộp thoại này) . Khi thực thi nó trông sẽ như sau
Ngày nay tới đây thôi, Byebye !!! [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
28-03-2014, 12:00 PM #17Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 32: Thay đổi hình ảnh bất kỳ với F4
Trong các ngày đầu, chúng ta đã nói rằng sẽ để cho người chơi toàn quyền thay đổi các hình ảnh của chương trình.
Chức năng này đáng ra không nên có nếu bạn là người có năng khiếu vẽ, do mình vẽ quá xấu nên phải bù vào bằng
mã thôi ( Nếu vẽ tốt, chúng ta chỉ cần tạo 50 hình ảnh TankE và 2 Tank của ta rồi lưu vào tài nguyên, lúc đó cũng chẳng cần
tới 4 hàm DirectX_RestoreSurfaceFromFile(), App_CheckBMPFile(), Bitmap_CreateFile(), Bitmap_CreateInfoStruct()).
Tạo một bản mẫu hộp thoại mới, thay đổi id = IDD_DIALOG_IMAGE. Xóa tất cả các Button.
Đưa vào 1 listbox với id = IDC_LIST1, nhấn phải vào nó chọn Properties, chuyển tới tab <Styles> bỏ dấu kiểm "Sort",
chuyển tới tab <Extended Styles> check vào dấu kiểm "Modal frame" để cho khung dễ nhìn hơn.
Đưa vào 1 Button với id = IDC_BUTTON1, trong hộp thuộc tính của nó, ở tab <Styles> Check thuộc tính "Owner draw",
ở tab <Extended Styles> Check vào thuộc tính "Modal frame"
Kéo dãn hộp thoại ra thêm và chỉnh sửa thêm sau khi biên dịch và chạy chương trình.
Mã cập nhật cho hàm WndProc, thông điệp WM_COMMAND, cho F1 như sau
Mã:case IDC_F4: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_IMAGE),hwnd,DlgProc_Image); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_Image(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ static HWND hList; static HWND hbtOwnerDraw; static HBRUSH hbrBack; CHAR szText[MAX_PATH],szFolder[MAX_PATH],szFile[MAX_PATH]; LPDIRECTDRAWSURFACE lpSur; LPDRAWITEMSTRUCT pd; HDC hdcSur; DDSURFACEDESC ddsd; int i,iIndex; RECT r; SIZE sizeTotal,sizeArray,sizeFrame; OPENFILENAME ofn; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); hbrBack = CreateSolidBrush(g_DataSetup.crScreen); hbtOwnerDraw = GetDlgItem(hDlg,IDC_BUTTON1); hList = GetDlgItem(hDlg,IDC_LIST1); // Bắt đầu đổ dữ liệu vào Listbox for(i=0;i<50;i++) { wsprintf(szText,"Enemy Tank #%i",i+1); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Left Tank"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Right Tank"); for(i=0;i<=10;i++) { wsprintf(szText,"Card #%i",i+1); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Brick"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Steel"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"River"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Cover"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Glide"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"House"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Fire"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Smoke"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Fire Bullet"); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)"Normal Bullet"); SendMessage(hList,LB_SETCURSEL,0,0); SetFocus(hList); return FALSE; case WM_DRAWITEM: pd = (LPDRAWITEMSTRUCT)lparam; iIndex = SendMessage(hList,LB_GETCURSEL,0,0); FillRect(pd->hDC,&pd->rcItem,(HBRUSH)GetStockObject(DKGRAY_BRUSH)); // Tô màu xám đậm cho Button if(iIndex == LB_ERR) return TRUE; if(iIndex >= 0 && iIndex < 50) lpSur = g_lpTankE[iIndex]; // 50 TankE else if(iIndex == 50) lpSur = g_lpTankL; // TankL else if(iIndex == 51) lpSur = g_lpTankR; // TankR else if(iIndex > 51 && iIndex <= 62) lpSur = g_lpCard[iIndex-52]; // 11 Card else if(iIndex == 63) lpSur = g_lpBrick; // Brick else if(iIndex == 64) lpSur = g_lpSteel; // Steel else if(iIndex == 65) lpSur = g_lpRiver; // River else if(iIndex == 66) lpSur = g_lpCover; // Cover else if(iIndex == 67) lpSur = g_lpGlide; // Glide else if(iIndex == 68) lpSur = g_lpHouse; // House else if(iIndex == 69) lpSur = g_lpFire; // Fire else if(iIndex == 70) lpSur = g_lpSmoke; // Smoke else if(iIndex == 71) lpSur = g_lpBullF; // Fire Bullet else lpSur = g_lpBullN; // Normal Bullet GetClientRect(hbtOwnerDraw,&r); if(lpSur->GetDC(&hdcSur) == DD_OK) { ddsd.dwSize = sizeof(ddsd); ddsd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH; if(lpSur->GetSurfaceDesc(&ddsd) == DD_OK) BitBlt(pd->hDC,(r.right-r.left-ddsd.dwWidth)/2,(r.bottom-r.top-ddsd.dwHeight)/2-50,ddsd.dwWidth,ddsd.dwHeight,hdcSur,0,0,SRCCOPY); lpSur->ReleaseDC(hdcSur); } if(iIndex >= 0 && iIndex < 50) { sizeTotal.cx = 128; sizeTotal.cy = 128; sizeArray.cx = 4; sizeArray.cy = 4; sizeFrame.cx = 32; sizeFrame.cy = 32;} // 50 TankE else if(iIndex == 50) { sizeTotal.cx = 128; sizeTotal.cy = 128; sizeArray.cx = 4; sizeArray.cy = 4; sizeFrame.cx = 32; sizeFrame.cy = 32;} // TankL else if(iIndex == 51) { sizeTotal.cx = 128; sizeTotal.cy = 128; sizeArray.cx = 4; sizeArray.cy = 4; sizeFrame.cx = 32; sizeFrame.cy = 32;} // TankR else if(iIndex>51 && iIndex<=62) { sizeTotal.cx = 24; sizeTotal.cy = 24; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 24; sizeFrame.cy = 24;} // 11 Card else if(iIndex == 63) { sizeTotal.cx = 8; sizeTotal.cy = 8; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 8; sizeFrame.cy = 8; } // Brick else if(iIndex == 64) { sizeTotal.cx = 16; sizeTotal.cy = 16; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 16; sizeFrame.cy = 16;} // Steel else if(iIndex == 65) { sizeTotal.cx = 32; sizeTotal.cy = 32; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 32; sizeFrame.cy = 32;} // River else if(iIndex == 66) { sizeTotal.cx = 32; sizeTotal.cy = 32; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 32; sizeFrame.cy = 32;} // Cover else if(iIndex == 67) { sizeTotal.cx = 32; sizeTotal.cy = 32; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 32; sizeFrame.cy = 32;} // Glide else if(iIndex == 68) { sizeTotal.cx = 32; sizeTotal.cy = 32; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 32; sizeFrame.cy = 32;} // House else if(iIndex == 69) { sizeTotal.cx = 200; sizeTotal.cy = 40; sizeArray.cx = 5; sizeArray.cy = 1; sizeFrame.cx = 40; sizeFrame.cy = 40;} // Fire else if(iIndex == 70) { sizeTotal.cx = 1232; sizeTotal.cy = 96; sizeArray.cx = 14; sizeArray.cy = 1; sizeFrame.cx = 88; sizeFrame.cy = 96;} // Smoke else if(iIndex == 71) { sizeTotal.cx = 8; sizeTotal.cy = 8; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 8; sizeFrame.cy = 8; } // Fire Bullet else { sizeTotal.cx = 8; sizeTotal.cy = 8; sizeArray.cx = 1; sizeArray.cy = 1; sizeFrame.cx = 8; sizeFrame.cy = 8; } // Normal Bullet SetBkMode(pd->hDC,TRANSPARENT); SetTextColor(pd->hDC,RGB(0,0,255)); if(iIndex == 70) // Smoke DrawText(pd->hDC,"Bitmap too large for Display",-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_VCENTER); pd->rcItem.bottom -= 100; wsprintf(szText,"Total Size(Pixels) : %i x %i",sizeTotal.cx,sizeTotal.cy); // Kích thước Bitmap DrawText(pd->hDC,szText,-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_BOTTOM); if(sizeArray.cx != 1 || sizeArray.cy != 1) // Nếu Bitmap có hơn 1 khung { pd->rcItem.bottom += 25; wsprintf(szText,"Frame Numbers : %i x %i",sizeArray.cx,sizeArray.cy); // Hiển thi ma trận khung DrawText(pd->hDC,szText,-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_BOTTOM); pd->rcItem.bottom += 25; wsprintf(szText,"Frame Size(Pixels) : %i x %i",sizeFrame.cx,sizeFrame.cy); // Hiển thị kích thước mỗi khung DrawText(pd->hDC,szText,-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_BOTTOM); } SetTextColor(pd->hDC,RGB(255,255,0)); pd->rcItem.bottom += 30; DrawText(pd->hDC,"Click here to change the Image",-1,&pd->rcItem,DT_SINGLELINE|DT_CENTER|DT_BOTTOM); return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_LIST1: if(HIWORD(wparam) == LBN_SELCHANGE) { InvalidateRect(hbtOwnerDraw,NULL,FALSE); return TRUE; } break; case IDC_BUTTON1: szFile[0] = '\0'; ZeroMemory(&ofn,sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile); ofn.lpstrFilter = "Bitmap Files (*.bmp)\0*.bmp\0"; // Chỉ tìm tập tin Bitmap ofn.nFilterIndex = 1; ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_EXPLORER; if(GetOpenFileName(&ofn)) { iIndex = SendMessage(hList,LB_GETCURSEL,0,0); GetModuleFileName(NULL,szFolder,MAX_PATH); PathRemoveFileSpec(szFolder); lstrcat(szFolder,"\\Tank2D"); if(iIndex >= 0 && iIndex < 50) { lpSur = g_lpTankE[iIndex]; wsprintf(szText,"\\Tank%i.bmp",iIndex+1);} // 50 TankE else if(iIndex == 50) { lpSur = g_lpTankL; wsprintf(szText,"\\TankL.bmp");} // TankL else if(iIndex == 51) { lpSur = g_lpTankR; wsprintf(szText,"\\TankR.bmp");} // TankR else if(iIndex > 51 && iIndex <= 62) { lpSur = g_lpCard[iIndex-52]; wsprintf(szText,"\\Card%i.bmp",iIndex-51);} // 11 Card else if(iIndex == 63) { lpSur = g_lpBrick; wsprintf(szText,"\\Brick.bmp");} // Brick else if(iIndex == 64) { lpSur = g_lpSteel; wsprintf(szText,"\\Steel.bmp");} // Steel else if(iIndex == 65) { lpSur = g_lpRiver; wsprintf(szText,"\\River.bmp");} // River else if(iIndex == 66) { lpSur = g_lpCover; wsprintf(szText,"\\Cover.bmp");} // Cover else if(iIndex == 67) { lpSur = g_lpGlide; wsprintf(szText,"\\Glide.bmp");} // Glide else if(iIndex == 68) { lpSur = g_lpHouse; wsprintf(szText,"\\House.bmp");} // House else if(iIndex == 69) { lpSur = g_lpFire; wsprintf(szText,"\\Fire.bmp");} // Fire else if(iIndex == 70) { lpSur = g_lpSmoke; wsprintf(szText,"\\Smoke.bmp");} // Smoke else if(iIndex == 71) { lpSur = g_lpBullF; wsprintf(szText,"\\BullF.bmp");} // Fire Bullet else { lpSur = g_lpBullN; wsprintf(szText,"\\BullN.bmp");} // Normal Bullet lstrcat(szFolder,szText); if(CopyFile(szFile,szFolder,FALSE)) // Copy hình ảnh về thư mục Tank2D của chương trình { DirectX_RestoreSurfaceFromFile(lpSur,szFolder); // Vẽ lại bề mặt liên quan InvalidateRect(hbtOwnerDraw,NULL,FALSE); // Vẽ lại Button tự vẽ } } return TRUE; case IDOK: return TRUE; case IDCANCEL: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CTLCOLORDLG: return (int)hbrBack; case WM_CLOSE: DeleteObject(hbrBack); EndDialog(hDlg,0); return TRUE; } return FALSE;}
nên thay đổi hay không. Chương trình chấp nhận bất kỳ hình ảnh mới để thay đổi, chỉ là nếu nó không phù hợp lắm
thì trách nhiệm đó thuộc về người chơi ( "Tui đã cung cấp thông tin đầy đủ rồi mà !!!").
Hộp thoại này khi thực thi trông sẽ như sau
Ngày hôm nay tới đây, chào tạm biệt các anh chị em. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
30-03-2014, 10:15 AM #18Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 33: Chức năng về âm thanh của phím F5
Tạo 1 hộp thoại mới với id = IDD_DIALOG_SOUND, xóa Button OK.
Thêm Button id = IDC_BUTTON1, text = "Enable".
Thêm Button id = IDC_BUTTON2, text = "Change".
Xắp xếp 3 Button trên hàng ngang ở đáy hộp thoại.
Thêm 1 điều khiển ListView có id = IDC_LIST1, mở thuộc tính, trong tab <Styles> combo View đặt ở "Report", check "Single Selection", check "Show selection always".
trong tab <Extended Styles> check "Client edge", check "Modal frame".
Mã cập nhật cho hàm WndProc, thông điệp WM_COMMAND, cho F5 như sau
Mã:case IDC_F5: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_SOUND),hwnd,DlgProc_Sound); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_Sound(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ static HWND hList; static HBRUSH hbrBack; CHAR szFolder[MAX_PATH],szText[MAX_PATH],szFile[MAX_PATH]; LVCOLUMN lvc; LVITEM lvi; OPENFILENAME ofn; int i,cCount; PCHAR psz[] = {"BackSound","Bonus","Lost","Mine","Win","EBullN","EBullF","ETankShoot","BullN","BullF","TankShoot"}; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); hbrBack = CreateSolidBrush(g_DataSetup.crScreen); hList = GetDlgItem(hDlg,IDC_LIST1); lvc.mask = LVCF_FMT|LVCF_WIDTH|LVCF_TEXT|LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.cx = 80; lvc.iSubItem = 0; lvc.pszText = "Sound"; ListView_InsertColumn(hList,0,&lvc); // Cột đầu tiên là "Sound" lvc.fmt = LVCFMT_CENTER; lvc.cx = 60; lvc.iSubItem = 1; lvc.pszText = "Enable"; ListView_InsertColumn(hList,1,&lvc); // Cột thứ hai là "Enable" lvc.fmt = LVCFMT_LEFT; lvc.cx = 260; lvc.iSubItem = 2; lvc.pszText = "Location"; ListView_InsertColumn(hList,2,&lvc); // Cột thứ 3 là đường dẫn tập tin âm thanh // Tạo màu nền, màu text, tạo khung lưới, thiết lập kiểu chọn nguyên dòng ListView_SetTextBkColor(hList,RGB(0,255,255)); ListView_SetBkColor(hList,RGB(0,255,255)); ListView_SetTextColor(hList,RGB(255,0,0)); ListView_SetExtendedListViewStyle(hList,LVS_EX_GRIDLINES|LVS_EX_FULLROWSELECT); // Tạo ra 11 Item coh ListView GetModuleFileName(NULL,szFolder,MAX_PATH); PathRemoveFileSpec(szFolder); lstrcat(szFolder,"\\Tank2D"); for(i=0;i<11;i++) { lvi.mask = LVIF_TEXT; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = psz[i]; ListView_InsertItem(hList,&lvi); } // Chèn chữ vào cột 2 ListView_SetItemText(hList,0,1,g_DataSetup.sndBackSound ? "x":" "); ListView_SetItemText(hList,1,1,g_DataSetup.sndBonusSound ? "x":" "); ListView_SetItemText(hList,2,1,g_DataSetup.sndLostSound ? "x":" "); ListView_SetItemText(hList,3,1,g_DataSetup.sndMineSound ? "x":" "); ListView_SetItemText(hList,4,1,g_DataSetup.sndWinSound ? "x":" "); ListView_SetItemText(hList,5,1,g_DataSetup.sndEnemySmallBullet ? "x":" "); ListView_SetItemText(hList,6,1,g_DataSetup.sndEnemyLargeBullet ? "x":" "); ListView_SetItemText(hList,7,1,g_DataSetup.sndEnemyShoot ? "x":" "); ListView_SetItemText(hList,8,1,g_DataSetup.sndOurSmallBullet ? "x":" "); ListView_SetItemText(hList,9,1,g_DataSetup.sndOurLargeBullet ? "x":" "); ListView_SetItemText(hList,10,1,g_DataSetup.sndOurShoot ? "x":" "); // Chèn chữ vào cột 3 cho dòng đầu wsprintf(szText,"%s\\BackSound.mid",szFolder); if(PathFileExists(szText)) ListView_SetItemText(hList,0,2,szText); wsprintf(szText,"%s\\BackSound.wav",szFolder); if(PathFileExists(szText)) ListView_SetItemText(hList,0,2,szText); wsprintf(szText,"%s\\BackSound.mp3",szFolder); if(PathFileExists(szText)) ListView_SetItemText(hList,0,2,szText); // và các dòng còn lại for(i=1;i<11;i++) { wsprintf(szText,"%s\\%s.wav",szFolder,psz[i]); if(PathFileExists(szText)) ListView_SetItemText(hList,i,2,szText); } return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_BUTTON1: cCount = ListView_GetItemCount(hList); for(i=0;i<cCount;i++) if(LVIS_SELECTED == (ListView_GetItemState(hList,i,LVIS_SELECTED))) // Nhận Item được chọn { ListView_GetItemText(hList,i,1,szText,MAX_PATH); if(lstrcmp(szText,"x") == 0) { ListView_SetItemText(hList,i,1," "); } else { ListView_SetItemText(hList,i,1,"x"); } if (i==0) g_DataSetup.sndBackSound ^= 1; else if (i==1) g_DataSetup.sndBonusSound ^= 1; else if (i==2) g_DataSetup.sndLostSound ^= 1; else if (i==3) g_DataSetup.sndMineSound ^= 1; else if (i==4) g_DataSetup.sndWinSound ^= 1; else if (i==5) g_DataSetup.sndEnemySmallBullet ^= 1; else if (i==6) g_DataSetup.sndEnemyLargeBullet ^= 1; else if (i==7) g_DataSetup.sndEnemyShoot ^= 1; else if (i==8) g_DataSetup.sndOurSmallBullet ^= 1; else if (i==9) g_DataSetup.sndOurLargeBullet ^= 1; else g_DataSetup.sndOurShoot ^= 1; Setup_SaveData(&g_DataSetup); return TRUE; } MessageBox(hDlg,"You must Select a Item !","Change Sounds",MB_OK|MB_ICONINFORMATION); return TRUE; case IDC_BUTTON2: cCount = ListView_GetItemCount(hList); for(i=0;i<cCount;i++) if(LVIS_SELECTED == (ListView_GetItemState(hList,i,LVIS_SELECTED))) // Nhận Item được chọn { szFile[0] = '\0'; ZeroMemory(&ofn,sizeof(OPENFILENAME)); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hDlg; ofn.lpstrFile = szFile; ofn.nMaxFile = sizeof(szFile); ofn.lpstrFilter = (i==0) ? "Sound Files (*.mp3),(*.wav),(*.mid)\0*.mp3;*.wav;*.mid\0" : "Bitmap Files (*.wav)\0*.wav\0"; ofn.nFilterIndex = 1; ofn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_EXPLORER; if(GetOpenFileName(&ofn)) // Nhận âm thanh mới { // Nếu là BackSound if(i==0) { GetModuleFileName(NULL,szFolder,MAX_PATH); PathRemoveFileSpec(szFolder); lstrcat(szFolder,"\\Tank2D"); wsprintf(szText,"%s\\BackSound.mid",szFolder); DeleteFile(szText); wsprintf(szText,"%s\\BackSound.wav",szFolder); DeleteFile(szText); wsprintf(szText,"%s\\BackSound.mp3",szFolder); DeleteFile(szText); if(lstrcmp(PathFindExtension(szFile),".mp3") == 0) wsprintf(szText,"%s\\BackSound.mp3",szFolder); else if(lstrcmp(PathFindExtension(szFile),".wav") == 0) wsprintf(szText,"%s\\BackSound.wav",szFolder); else wsprintf(szText,"%s\\BackSound.mid",szFolder); } else { ListView_GetItemText(hList,i,2,szText,MAX_PATH); } if(CopyFile(szFile,szText,FALSE)) // Thay đổi với tập tin mới { ListView_SetItemText(hList,i,2,szText); } else { ListView_SetItemText(hList,i,2,""); } } return TRUE; } MessageBox(hDlg,"You must Select a Item !","Change Sounds",MB_OK|MB_ICONINFORMATION); return TRUE; case IDCANCEL: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CTLCOLORDLG: return (int)hbrBack; case WM_CLOSE: DeleteObject(hbrBack); EndDialog(hDlg,0); return TRUE; } return FALSE;}
Khi thực thi hộp thoại sẽ trông như hình bên dưới.
Thư mục dự án trong đính kèm Tank2D.zip.
Chương trình thực thi trong đính kèm Tank.zip.
Ngày hôm nay tới đây thôi, chào tạm biệt. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
- - - Nội dung đã được cập nhật ngày 30-03-2014 lúc 03:15 PM - - -</font>
<font color="#0000FF">NGÀY 34: Thêm chức năng chỉnh sửa kiểu thuộc tính Tank cho F6.
Các thuộc tính xác định sự nguy hiểm của 1 TankE là : Có bắn đạn lửa không, Tốc độ di chuyển, Tốc độ di chuyển của đạn, Chịu đựng được bao nhiêu viên đạn, Mức độ di chuyển thông minh.
Nếu chúng ta lấy tất cả các hoán vị của 5 thuộc tính này để xác định kiểu thì số kiểu sẽ là rất lớn, không khoa học.
Thay vào đó, chúng ta để cho người chơi tự xác định thuộc tính cho 50 kiểu TankE.
Thêm vào 2 hàm lưu và nạp tập tin thuộc tính ở vị trí gần các hàm Setup_LoadData(),Setup_SaveData()
Mã:BOOL TypeTank_Load(TYPETANK TypeTank[50]){ CHAR szText[MAX_PATH]; HANDLE hFile; TYPETANK Type[50]; DWORD dw; BOOL bFlag; GetModuleFileName(NULL,szText,MAX_PATH); PathRemoveFileSpec(szText); lstrcat(szText,"\\Tank2D"); if(!PathIsDirectory(szText)) return FALSE; lstrcat(szText,"\\Type.typ"); hFile = CreateFile(szText,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == INVALID_HANDLE_VALUE) return FALSE; if(GetFileSize(hFile,NULL) != sizeof(TYPETANK)*50) { CloseHandle(hFile); return FALSE; } bFlag = ReadFile(hFile,Type,sizeof(TYPETANK)*50,&dw,NULL); CloseHandle(hFile); if(!bFlag || dw != sizeof(TYPETANK)*50) return FALSE; CopyMemory(TypeTank,Type,sizeof(TYPETANK)*50); return TRUE;}BOOL TypeTank_Save(TYPETANK TypeTank[50]){ CHAR szText[MAX_PATH]; HANDLE hFile; DWORD dw; BOOL bFlag; GetModuleFileName(NULL,szText,MAX_PATH); PathRemoveFileSpec(szText); lstrcat(szText,"\\Tank2D"); if(!PathIsDirectory(szText)) return FALSE; lstrcat(szText,"\\Type.typ"); hFile = CreateFile(szText,GENERIC_WRITE,FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); if(hFile == INVALID_HANDLE_VALUE) return FALSE; bFlag = WriteFile(hFile,TypeTank,sizeof(TYPETANK)*50,&dw,NULL); CloseHandle(hFile); if(!bFlag || dw != sizeof(TYPETANK)*50) { DeleteFile(szText); return FALSE; } return TRUE;}
Trong thủ tục xử lý thông điệp chính ( WndProc), trong WM_CREATE, xóa bỏ đoạn mã sau
Mã:for(i=0;i<50;i++) { g_TypeTank[i].bBullF = (rand()%30 == 0) ? TRUE:FALSE; g_TypeTank[i].iPower = rand()%5 + 1; g_TypeTank[i].iShoot = rand()%6 + 5; g_TypeTank[i].iSmart = rand()%3; g_TypeTank[i].iSpeed = rand()%3 + 1; }
Mã:if(!TypeTank_Load(g_TypeTank)) // Đoạn mã mới { for(int i=0;i<50;i++) { g_TypeTank[i].bBullF = (rand()%30 == 0) ? TRUE:FALSE; g_TypeTank[i].iPower = rand()%5 + 1; g_TypeTank[i].iShoot = rand()%6 + 5; g_TypeTank[i].iSmart = rand()%3; g_TypeTank[i].iSpeed = rand()%3 + 1; } TypeTank_Save(g_TypeTank); } g_hInst = hInstance; // Mã cũ
Bây giờ là lúc tạo hộp thoại cho người chơi thay đổi trực quan các thuộc tính của 50 kiểu Tank.
Tạo 1 hộp thoại mới với id = IDD_DIALOG_TANKE, mở hộp thuộc tính, trong tab <More Styles> check "Center".
Thêm vào các điều khiển sau:
1. Listbox: id = IDC_LIT1, trong tab <Styles> bỏ check "Sort", trong tab<Extended Styles> check "Modal frame".
2. 4 Combobox: id từ IDC_COMBO1 tới IDC_COMBO4, cả 4 có kiểu giống nhau, trong <Styles> chọn "Drop List" trong combo "Type", bỏ check trong "Sort",
trong khung thiết kế nhấn vào nút kéo xuống của từng combo và canh chỉnh chiều cao của nó.
3. Checkbox: id = IDC_CHECK1, text = "Fire Bullet", check thuộc tính nâng cao "Modal frame".
4. Button: id = IDC_BUTTON1, thay đổi thành button tự vẽ, check thuộc tính nâng cao "Modal frame".
Đổi text của button OK thành "Update", đổi text của Cancel thành "Close".
Sắp xếp lại tất cả cho dễ nhìn theo ý thích của bạn.
Mã cập nhật cho hàm WndProc, thông điệp WM_COMMAND, cho F6 như sau
Mã:case IDC_F6: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_TANKE),hwnd,DlgProc_TankE); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_TankE(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ static HBRUSH hbrBack; static HWND hList,hbtOwner,hCheck; static HWND hComboPower,hComboShoot,hComboSmart,hComboSpeed; static TYPETANK TypeTank[50]; static BOOL bChanged; CHAR szText[MAX_PATH]; LPDRAWITEMSTRUCT pd; HDC hdcSur; int i,iIndex; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); hbrBack = CreateSolidBrush(g_DataSetup.crScreen); hList = GetDlgItem(hDlg,IDC_LIST1); hbtOwner = GetDlgItem(hDlg,IDC_BUTTON1); hCheck = GetDlgItem(hDlg,IDC_CHECK1); hComboPower = GetDlgItem(hDlg,IDC_COMBO1); hComboShoot = GetDlgItem(hDlg,IDC_COMBO2); hComboSmart = GetDlgItem(hDlg,IDC_COMBO3); hComboSpeed = GetDlgItem(hDlg,IDC_COMBO4); CopyMemory(&TypeTank,&g_TypeTank,sizeof(TYPETANK)*50); bChanged = FALSE; for(i=0;i<50;i++) // Hiển thị 50 kiểu TankE trong List { wsprintf(szText," Tank #%i",i+1); SendMessage(hList,LB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hList,LB_SETCURSEL,0,0); for(i=0;i<5;i++) // Combo Power có 5 dòng { wsprintf(szText," Power = %i",i+1); SendMessage(hComboPower,CB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hComboPower,CB_SETCURSEL,TypeTank[0].iPower-1,0); for(i=0;i<6;i++) // Combo Shoot có 6 dòng { wsprintf(szText," ShootSpeed = %i",i+5); SendMessage(hComboShoot,CB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hComboShoot,CB_SETCURSEL,TypeTank[0].iShoot-5,0); for(i=0;i<3;i++) // Combo Smart có 3 dòng { wsprintf(szText," Smart = %i",i); SendMessage(hComboSmart,CB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hComboSmart,CB_SETCURSEL,TypeTank[0].iSmart,0); for(i=0;i<3;i++) // Combo Speed có 3 dòng { wsprintf(szText," Speed = %i",i+1); SendMessage(hComboSpeed,CB_ADDSTRING,0,(LPARAM)szText); } SendMessage(hComboSpeed,CB_SETCURSEL,TypeTank[0].iSpeed-1,0); CheckDlgButton(hDlg,IDC_CHECK1,TypeTank[0].bBullF ? BST_CHECKED : BST_UNCHECKED); SetFocus(hList); return FALSE; case WM_DRAWITEM: pd = (LPDRAWITEMSTRUCT)lparam; FillRect(pd->hDC,&pd->rcItem,(HBRUSH)GetStockObject(DKGRAY_BRUSH)); // Tô màu xám đậm cho button iIndex = SendMessage(hList,LB_GETCURSEL,0,0); if(iIndex != LB_ERR) if(g_lpTankE[iIndex]) if(g_lpTankE[iIndex]->GetDC(&hdcSur) == DD_OK) // Nhận Thiết bị ngữ cảnh sau đó BitBlt { BitBlt(pd->hDC,(pd->rcItem.right - pd->rcItem.left - LARGE)/2, (pd->rcItem.bottom - pd->rcItem.top - LARGE)/2,LARGE,LARGE,hdcSur,0,0,SRCCOPY); g_lpTankE[iIndex]->ReleaseDC(hdcSur); } return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_LIST1: if(HIWORD(wparam) == LBN_SELCHANGE) // Người chơi chuyển sang Tank khác { iIndex = SendMessage(hList,LB_GETCURSEL,0,0); if(iIndex != LB_ERR) { SendMessage(hComboPower,CB_SETCURSEL,TypeTank[iIndex].iPower-1,0); SendMessage(hComboShoot,CB_SETCURSEL,TypeTank[iIndex].iShoot-5,0); SendMessage(hComboSmart,CB_SETCURSEL,TypeTank[iIndex].iSmart,0); SendMessage(hComboSpeed,CB_SETCURSEL,TypeTank[iIndex].iSpeed-1,0); CheckDlgButton(hDlg,IDC_CHECK1,TypeTank[iIndex].bBullF ? BST_CHECKED : BST_UNCHECKED); InvalidateRect(hbtOwner,NULL,FALSE); } return TRUE; } break; case IDC_COMBO1: if(HIWORD(wparam) == CBN_SELCHANGE) // Thay đổi Power { TypeTank[SendMessage(hList,LB_GETCURSEL,0,0)].iPower = SendMessage(hComboPower,CB_GETCURSEL,0,0) + 1; bChanged = TRUE; return TRUE; } break; case IDC_COMBO2: if(HIWORD(wparam) == CBN_SELCHANGE) // Thay đổi Shoot { TypeTank[SendMessage(hList,LB_GETCURSEL,0,0)].iShoot = SendMessage(hComboShoot,CB_GETCURSEL,0,0) + 5; bChanged = TRUE; return TRUE; } break; case IDC_COMBO3: if(HIWORD(wparam) == CBN_SELCHANGE) // Thay đổi Smart { TypeTank[SendMessage(hList,LB_GETCURSEL,0,0)].iSmart = SendMessage(hComboSmart,CB_GETCURSEL,0,0); bChanged = TRUE; return TRUE; } break; case IDC_COMBO4: if(HIWORD(wparam) == CBN_SELCHANGE) // Thay đổi Speed { TypeTank[SendMessage(hList,LB_GETCURSEL,0,0)].iSpeed = SendMessage(hComboSpeed,CB_GETCURSEL,0,0) + 1; bChanged = TRUE; return TRUE; } break; case IDC_CHECK1: // Bật/Tắt Fire Bullet TypeTank[SendMessage(hList,LB_GETCURSEL,0,0)].bBullF = (BST_CHECKED == IsDlgButtonChecked(hDlg,IDC_CHECK1)) ? TRUE:FALSE; bChanged = TRUE; return TRUE; case IDOK: if(bChanged) // Nếu có bất kỳ thay đổi { CopyMemory(&g_TypeTank,&TypeTank,sizeof(TYPETANK)*50); TypeTank_Save(TypeTank); // Lưu thay đổi cho sau này } case IDCANCEL: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CTLCOLORDLG: return (int)hbrBack; case WM_CLOSE: DeleteObject(hbrBack); EndDialog(hDlg,0); return TRUE; } return FALSE;}
Ngày nay tới đây thôi, tạm biệt. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
31-03-2014, 10:53 AM #19Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 35: Cộng thêm hoa lá vào trò chơi, cộng chức năng F12.
Trên toàn bộ màn hình khi chơi chúng ta thấy.
Vùng chơi nằm ở giữa màn hình, các Title nằm ở phía trên, các thuộc tính Tank ta nằm ở dưới, 30 TankE mà sẽ tham chiến ở bên phải, còn lại vùng trống ở bên trái làm gì đây.
Chưa nghĩ ra được gì nên mình sẽ thêm vào các đường Bezier chạy xung quanh vùng này ( chủ yếu là cho vui mắt thôi).
Thêm vào 2 định nghĩa cấu trúc sau
Mã:typedef struct{ COLORREF cr; // Màu của đường Bezier này POINT pt[4]; // Mảng cho 2 đầu mút và 2 điểm uốn int dx[4]; // Độ dời theo trục x của các điểm cho đường Bezier kế tiếp int dy[4]; // Độ dời theo trục y của các điểm cho đường Bezier kế tiếp}BEZIER,*PBEZIER;typedef struct{ int cMax; // So đường Bezier đồng thời hiển thị lớn nhất int xMax; // Độ dời tối đa giữa 2 điểm tương ứng của 2 Bezier theo trục x int yMax; // Độ dời tối đa giữa 2 điểm tương ứng của 2 Bezier theo trục x}PARAMBEZIER,*PPARAMBEZIER;
Mã:PARAMBEZIER g_ParamBezier; // ParamBezier
Mã:g_ParamBezier.cMax = (rand()%20)*5+5; g_ParamBezier.xMax = rand()%10+1; g_ParamBezier.yMax = rand()%10+1; g_hInst = hInstance; // Mã cũ
Mã:void DirectX_DrawAndUpdateBezier(LPDIRECTDRAWSURFACE pBack,PPARAMBEZIER pParam,int xFrame,int yFrame){ static CPtrArray aBezier(FALSE); HDC hdc; PBEZIER p,pBezier; HPEN hPen; int i,cBezier; RECT r = {0,yFrame,xFrame-5,yFrame+LARGE*13}; // r chứa hình chữ nhật mà các Bezier không thể vượt qua if(!pBack) return; if(pBack->GetDC(&hdc) != DD_OK) return; for(i=aBezier.GetSize()-1;i>=pParam->cMax;i--) // Xóa bớt nếu vừa thay đổi biến lưu tổng số đường trong pParam aBezier.RemoveAt(i); for(i=0;i<aBezier.GetSize();i++) // Duyệt từng Bezier { pBezier = (PBEZIER)aBezier.GetAt(i); hPen = CreatePen(PS_SOLID,0,pBezier->cr); SelectObject(hdc,hPen); PolyBezier(hdc,pBezier->pt,4); // Vẽ nó ra DeleteObject(hPen); } pBack->ReleaseDC(hdc); if(NULL == (pBezier = (PBEZIER)malloc(sizeof(BEZIER)))) // Tạo 1 đường mới return; cBezier = aBezier.GetSize(); if(cBezier == 0) // Nếu chưa có đường thì nào tạo ngẫu nhiên màu, độ dời cũng như tọa độ cho 4 điểm Bezier { pBezier->cr = RGB(rand()&255,rand()&255,rand()&255); for(i=0;i<4;i++) { pBezier->dx[i] = (rand()%pParam->xMax+1)*((rand()%2)?-1:1); pBezier->dy[i] = (rand()%pParam->yMax+1)*((rand()%2)?-1:1); pBezier->pt[i].x = rand()%(r.right-r.left); pBezier->pt[i].y = rand()%(r.bottom-r.top)+r.top; } } else // { if(cBezier == pParam->cMax) // Nếu đã đủ số lượng đường thì xóa đường đầu tiên trong mảng ( cũng là đường đã hiển thị lâu nhất) { aBezier.RemoveAt(0); cBezier--; } p = (PBEZIER)aBezier.GetAt(cBezier-1); // Cho một xác xuất để tạo màu mới hay sử dụng màu của đường cuối trong mảng để ... pBezier->cr = (rand()%10>5) ? (RGB(rand()&255,rand()&255,rand()&255)):p->cr; // ... Đổi màu đường Bezier này. for(i=0;i<4;i++) { if(p->pt[i].x + p->dx[i] <= r.left) // Thay đổi ngẫu nhiên các độ dời, đảo chiều theo x { p->dx[i] = (rand()%pParam->xMax+1)*((p->dx[i]>0) ? (-1):1); p->dy[i] = (rand()%pParam->yMax+1)*((p->dy[i]>0) ? 1:(-1)); } if(p->pt[i].y + p->dy[i] <= r.top) // Thay đổi ngẫu nhiên các độ dời, đảo chiều theo y { p->dy[i] = (rand()%pParam->yMax+1)*((p->dy[i]>0) ? (-1):1); p->dx[i] = (rand()%pParam->xMax+1)*((p->dx[i]>0) ? 1:(-1)); } if(p->pt[i].x + p->dx[i] >= r.right-1) // Thay đổi ngẫu nhiên các độ dời, đảo chiều theo x { p->dx[i] = (rand()%pParam->xMax+1)*((p->dx[i]>0) ? (-1):1); p->dy[i] = (rand()%pParam->yMax+1)*((p->dy[i]>0) ? 1:(-1)); } if(p->pt[i].y + p->dy[i] >= r.bottom-1) // Thay đổi ngẫu nhiên các độ dời, đảo chiều theo y { p->dy[i] = (rand()%pParam->yMax+1)*((p->dy[i]>0) ? (-1):1); p->dx[i] = (rand()%pParam->xMax+1)*((p->dx[i]>0) ? 1:(-1)); } // Đặt mới độ dời và tọa độ các đầu mút, điểm uốn. pBezier->pt[i].x = p->pt[i].x + p->dx[i]; pBezier->pt[i].y = p->pt[i].y + p->dy[i]; pBezier->dx[i] = p->dx[i]; pBezier->dy[i] = p->dy[i]; } } aBezier.Add(pBezier);}
Mã:// Mã đã có sẵn ddbltfx.dwFillColor = DirectX_ColorMatch(g_lpBack,g_DataSetup.crBack); while(1) { hr = g_lpBack->Blt(&r,NULL,NULL,DDBLT_COLORFILL,&ddbltfx); if(hr == DD_OK) break; if(hr == DDERR_SURFACELOST) if(!DirectX_RestoreSurfaceAll()) return; if(hr != DDERR_WASSTILLDRAWING) return; } // Thêm dòng này vào DirectX_DrawAndUpdateBezier(g_lpBack,&g_ParamBezier,xFrame,yFrame);
Tiếp theo, chúng ta sẽ cho thêm chức năng chỉnh sửa hiển thị của các đường Bezier bằng phím F12 ( không quan trọng nên cho nó ở F tận cùng).
Tạo hộp thoại mới với id=IDD_DIALOG_BEZIER. Thay tên hộp thoại thành "Bezier Params", check thuộc tính nâng cao "Center".
Thêm vào 3 Combobox với id từ IDC_COMBO1 tới IDC_COMBO3, đặt kiểu là "Drop list" rồi uncheck "Sort" cho cả 3, mở rộng chiều cao cho combo để chứa khoảng 20 dòng.
Mã cập nhật cho hàm WndProc, thông điệp WM_COMMAND, cho F12 như sau
Mã:case IDC_F12: if(g_lpDD && g_iStatus == SP_LEVEL) { g_lpDD->FlipToGDISurface(); g_bMoused = TRUE; SendMessage(hwnd,WM_SETCURSOR,0,0); DialogBox(g_hInst,MAKEINTRESOURCE(IDD_DIALOG_BEZIER),hwnd,DlgProc_Bezier); g_bMoused = FALSE; SendMessage(hwnd,WM_SETCURSOR,0,0); } return 0;
Mã:BOOL CALLBACK DlgProc_Bezier(HWND hDlg,UINT message,WPARAM wparam,LPARAM lparam){ static HBRUSH hbrBack; static HWND hComboC,hComboX,hComboY; static PARAMBEZIER Params; static BOOL bChanged; CHAR szText[MAX_PATH]; int i; switch(message) { case WM_INITDIALOG: SetClassLong(hDlg,GCL_HICON,(LONG)LoadIcon(g_hInst,MAKEINTRESOURCE(IDI_TANK2D))); hbrBack = CreateSolidBrush(g_DataSetup.crScreen); hComboC = GetDlgItem(hDlg,IDC_COMBO1); hComboX = GetDlgItem(hDlg,IDC_COMBO2); hComboY = GetDlgItem(hDlg,IDC_COMBO3); for(i=0;i<20;i++) { wsprintf(szText," Lines : %i",(i+1)*5); // Hiển thị theo bước tăng 5, bắt đầu từ 5 SendMessage(hComboC,CB_ADDSTRING,0,(LPARAM)szText); if(i == (g_ParamBezier.cMax-5)/5) // Chọn giá trị hiện hành SendMessage(hComboC,CB_SETCURSEL,i,0); } for(i=0;i<20;i++) { wsprintf(szText," Max Step X : %i",i+1); // Hiển thị theo bước tăng 1, bắt đầu từ 1 SendMessage(hComboX,CB_ADDSTRING,0,(LPARAM)szText); if(i == g_ParamBezier.xMax-1) // Chọn giá trị hiện hành SendMessage(hComboX,CB_SETCURSEL,i,0); wsprintf(szText," Max Step Y : %i",i+1); // Hiển thị theo bước tăng 1, bắt đầu từ 1 SendMessage(hComboY,CB_ADDSTRING,0,(LPARAM)szText); if(i == g_ParamBezier.yMax-1) // Chọn giá trị hiện hành SendMessage(hComboY,CB_SETCURSEL,i,0); } CopyMemory(&Params,&g_ParamBezier,sizeof(PARAMBEZIER)); bChanged = FALSE; return TRUE; case WM_COMMAND: switch(LOWORD(wparam)) { case IDC_COMBO1: case IDC_COMBO2: case IDC_COMBO3: if(HIWORD(wparam) == CBN_SELCHANGE) { bChanged = TRUE; return TRUE; } break; case IDOK: if(bChanged) // Nếu có thay đổi, nhận các giá trị từ combo rồi lưu lại { i = SendMessage(hComboC,CB_GETCURSEL,0,0); if(i != CB_ERR) Params.cMax = (i+1)*5; i = SendMessage(hComboX,CB_GETCURSEL,0,0); if(i != CB_ERR) Params.xMax = i+1; i = SendMessage(hComboY,CB_GETCURSEL,0,0); if(i != CB_ERR) Params.yMax = i+1; CopyMemory(&g_ParamBezier,&Params,sizeof(PARAMBEZIER)); } case IDCANCEL: SendMessage(hDlg,WM_CLOSE,0,0); return TRUE; } break; case WM_CTLCOLORDLG: return (int)hbrBack; case WM_CLOSE: DeleteObject(hbrBack); EndDialog(hDlg,0); return TRUE; } return FALSE;}
Ngày nay viết nhiều rồi, nghỉ thôi, hẹn gặp lại. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
-
02-04-2014, 08:52 AM #20Junior Member
- Ngày tham gia
- Sep 2015
- Bài viết
- 0
NGÀY 36: Thêm Logic xử lý Joystick cho chương trình
Trong các ngày trước, chúng ta còn chừa lại phần mã xử lý thiết bị điều khiển Game cầm tay (Joystick), bây giờ là lúc thêm nó vào.
Có thể chúng ta phải sửa lại rất nhiều hàm, vậy hãy hít một hơi dài và bắt đầu.
Thêm vào 1 định nghĩa cấu trúc
Mã:typedef struct{ BOOL bShoot; // Button1 dang nhan hay tha ? TRUE:nhan FALSE:tha BOOL bLeft; // Left Arrow BOOL bUp; // Up Arrow BOOL bRight; BOOL bDown;}INPUTJOYSTICK,*PINPUTJOYSTICK;
Mã:// Mã đã có sẵnLPDIRECTINPUTDEVICE g_lpKeyboard; // Thiet bi KeyboardLPDIRECTINPUTDEVICE g_lpMouse; // Thiet bi Mouse// Mã thêm mớiLPDIRECTINPUTDEVICE g_lpJoystick1; // Thiet bi Joystick1LPDIRECTINPUTDEVICE g_lpJoystick2; // Thiet bi Joystick2
Mã:BOOL CALLBACK DirectX_EnumAndCreateJoystick(LPCDIDEVICEINSTANCE pdinst,LPVOID pvRef){ static int iNum; DIPROPRANGE diprg; DIPROPDWORD dipdw; if(iNum > 1) // Nếu đã có đủ 2 Joystick thì dừng đếm return DIENUM_STOP; if(g_lpDI->CreateDevice(pdinst->guidInstance,(iNum==0) ? (&g_lpJoystick1):(&g_lpJoystick2),NULL) != DI_OK) // Tạo thiết bị Joystick return DIENUM_CONTINUE; if(iNum == 0) // Thiet lap dinh dang va Cooper cho Joystick1 { if(g_lpJoystick1->SetDataFormat(&c_dfDIJoystick) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } if(g_lpJoystick1->SetCooperativeLevel((HWND)pvRef,DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } } else // Thiet lap dinh dang va Cooper cho Joystick2 { if(g_lpJoystick2->SetDataFormat(&c_dfDIJoystick) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } if(g_lpJoystick2->SetCooperativeLevel((HWND)pvRef,DISCL_NONEXCLUSIVE | DISCL_FOREGROUND) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } } diprg.diph.dwSize = sizeof(diprg); diprg.diph.dwHeaderSize = sizeof(diprg.diph); diprg.diph.dwHow = DIPH_BYOFFSET; diprg.lMin = -1000; diprg.lMax = +1000; if(iNum == 0) // Thiet lap Min_Max cho X va Y cho Joystick1 { diprg.diph.dwObj = DIJOFS_X; if(g_lpJoystick1->SetProperty(DIPROP_RANGE,&diprg.diph) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } diprg.diph.dwObj = DIJOFS_Y; if(g_lpJoystick1->SetProperty(DIPROP_RANGE,&diprg.diph) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } } else // Thiet lap Min_Max cho X va Y cho Joystick2 { diprg.diph.dwObj = DIJOFS_X; if(g_lpJoystick2->SetProperty(DIPROP_RANGE,&diprg.diph) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } diprg.diph.dwObj = DIJOFS_Y; if(g_lpJoystick2->SetProperty(DIPROP_RANGE,&diprg.diph) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } } dipdw.diph.dwSize = sizeof(dipdw); dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); dipdw.diph.dwHow = DIPH_BYOFFSET; dipdw.dwData = 5000; if(iNum == 0) // Thiet lap Data cho Joystick1 { dipdw.diph.dwObj = DIJOFS_X; if(g_lpJoystick1->SetProperty(DIPROP_DEADZONE,&dipdw.diph) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } dipdw.diph.dwObj = DIJOFS_Y; if(g_lpJoystick1->SetProperty(DIPROP_DEADZONE,&dipdw.diph) != DI_OK) { g_lpJoystick1->Release(); g_lpJoystick1 = NULL; return DIENUM_CONTINUE; } } else // Thiet lap Data cho Joystick2 { dipdw.diph.dwObj = DIJOFS_X; if(g_lpJoystick2->SetProperty(DIPROP_DEADZONE,&dipdw.diph) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } dipdw.diph.dwObj = DIJOFS_Y; if(g_lpJoystick2->SetProperty(DIPROP_DEADZONE,&dipdw.diph) != DI_OK) { g_lpJoystick2->Release(); g_lpJoystick2 = NULL; return DIENUM_CONTINUE; } } if(iNum == 0) g_lpJoystick1->Acquire(); else g_lpJoystick2->Acquire(); iNum ++; return DIENUM_CONTINUE;}
Mã:BOOL DirectX_InitDI(HINSTANCE hInstance,HWND hwnd){ DIPROPDWORD dipdw = {sizeof(DIPROPDWORD),sizeof(DIPROPHEADER),0,DIPH_DEVICE,16}; if(DirectInputCreate(hInstance,DIRECTINPUT_VERSION,&g_lpDI,NULL) != DI_OK) return FALSE; if(g_lpDI->CreateDevice(GUID_SysKeyboard,&g_lpKeyboard,NULL) != DI_OK) return FALSE; if(g_lpKeyboard->SetDataFormat(&c_dfDIKeyboard) != DI_OK) return FALSE; if(g_lpKeyboard->SetCooperativeLevel(hwnd,DISCL_NONEXCLUSIVE|DISCL_FOREGROUND) != DI_OK) return FALSE; if(g_lpKeyboard->Acquire() != DI_OK) return FALSE; if(g_lpDI->CreateDevice(GUID_SysMouse,&g_lpMouse,NULL) != DI_OK) return FALSE; if(g_lpMouse->SetDataFormat(&c_dfDIMouse) != DI_OK) return FALSE; if(g_lpMouse->SetCooperativeLevel(hwnd,DISCL_NONEXCLUSIVE|DISCL_FOREGROUND) != DI_OK) return FALSE; if(!(g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL))) return FALSE; if(g_lpMouse->SetEventNotification(g_hEvent) != DI_OK) return FALSE; if(g_lpMouse->SetProperty(DIPROP_BUFFERSIZE,&dipdw.diph) != DI_OK) return FALSE; if(g_lpMouse->Acquire() != DI_OK) return FALSE; g_lpDI->EnumDevices(DIDEVTYPE_JOYSTICK,DirectX_EnumAndCreateJoystick,hwnd,DIEDFL_ATTACHEDONLY); return TRUE;}void DirectX_DeleteDI(){ if(g_lpDI) { if(g_lpKeyboard) {g_lpKeyboard->Unacquire(); g_lpKeyboard->Release(); g_lpKeyboard = NULL;} if(g_lpMouse) {g_lpMouse->Unacquire(); g_lpMouse->Release(); g_lpMouse = NULL;} if(g_hEvent) {CloseHandle(g_hEvent); g_hEvent = NULL;} if(g_lpJoystick1) {g_lpJoystick1->Unacquire(); g_lpJoystick1->Release(); g_lpJoystick1 = NULL;} if(g_lpJoystick2) {g_lpJoystick2->Unacquire(); g_lpJoystick2->Release(); g_lpJoystick2 = NULL;} g_lpDI->Release(); g_lpDI = NULL; }}
Mã:BOOL DirectX_GetInputJoystick(LPDIRECTINPUTDEVICE lpJoystick,PINPUTJOYSTICK pInput){ HRESULT hr; DIJOYSTATE js; ZeroMemory(pInput,sizeof(INPUTJOYSTICK)); hr = lpJoystick->GetDeviceState(sizeof(DIJOYSTATE),&js); if(hr != DI_OK) { if(hr == DIERR_INPUTLOST) lpJoystick->Acquire(); return FALSE; } if(js.lX < 0) pInput->bLeft ^= 1; if(js.lX > 0) pInput->bRight ^= 1; if(js.lY < 0) pInput->bUp ^= 1; if(js.lY > 0) pInput->bDown ^= 1; if(js.rgbButtons[0] & 0x80) pInput->bShoot ^= 1; return TRUE;}
Mã:void Tank_Update(BYTE pCells[52][52]){ INPUTKEYBOARD Keyboard; INPUTMOUSE Mouse; INPUTJOYSTICK Joystick1,Joystick2; int cStep; BOOL bStep; if(g_TankL.iFroze > 0) g_TankL.iFroze --; if(g_TankL.bReady && g_TankL.iFroze == 0) { if(DirectX_GetInputKeyboard(&Keyboard)) { if(Keyboard.bLeft) g_TankL.iRequestFrend = FM_LEFT; else if(Keyboard.bUp) g_TankL.iRequestFrend = FM_UP; else if(Keyboard.bRight) g_TankL.iRequestFrend = FM_RIGHT; else if(Keyboard.bDown) g_TankL.iRequestFrend = FM_DOWN; else g_TankL.iRequestFrend = FM_NULL; if(g_TankL.iRequestFrend != FM_NULL) { if(g_TankL.iRequestFrend != g_TankL.iFrend) // Neu khac huong { if(abs(g_TankL.iRequestFrend - g_TankL.iFrend) == 2) // Yeu cau quay nguoc g_TankL.iFrend = g_TankL.iRequestFrend; else if(Tank_CanRotate4Frend(&g_TankL)) // Quay vuong goc g_TankL.iFrend = g_TankL.iRequestFrend; } // Di chuyen Tank cStep = g_TankL.iSpeed * (Tank_MoveOnGlide(&g_TankL,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankL,pCells)) { Tank_StepByStep(&g_TankL); bStep = TRUE; cStep --; } else break; } if(bStep) { if(++ g_TankL.iFrame == 4) g_TankL.iFrame = 0; } } // Nguoi choi dang nhan nut ban if(Keyboard.bSpace) if(++ g_TankL.cTimes >= 8) { g_TankL.cTimes = 0; if(g_arBullL.GetSize() < g_TankL.cBulletJoin) Tank_Shoot(&g_TankL); } } if(g_lpJoystick1) if(DirectX_GetInputJoystick(g_lpJoystick1,&Joystick1)) { if(Joystick1.bLeft) g_TankL.iRequestFrend = FM_LEFT; else if(Joystick1.bUp) g_TankL.iRequestFrend = FM_UP; else if(Joystick1.bRight) g_TankL.iRequestFrend = FM_RIGHT; else if(Joystick1.bDown) g_TankL.iRequestFrend = FM_DOWN; else g_TankL.iRequestFrend = FM_NULL; if(g_TankL.iRequestFrend != FM_NULL) { if(g_TankL.iRequestFrend != g_TankL.iFrend) // Neu khac huong { if(abs(g_TankL.iRequestFrend - g_TankL.iFrend) == 2) // Yeu cau quay nguoc g_TankL.iFrend = g_TankL.iRequestFrend; else if(Tank_CanRotate4Frend(&g_TankL)) // Quay vuong goc g_TankL.iFrend = g_TankL.iRequestFrend; } // Di chuyen Tank cStep = g_TankL.iSpeed * (Tank_MoveOnGlide(&g_TankL,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankL,pCells)) { Tank_StepByStep(&g_TankL); bStep = TRUE; cStep --; } else break; } if(bStep) { if(++ g_TankL.iFrame == 4) g_TankL.iFrame = 0; } } // Nguoi choi dang nhan nut ban if(Joystick1.bShoot) if(++ g_TankL.cTimes >= 8) { g_TankL.cTimes = 0; if(g_arBullL.GetSize() < g_TankL.cBulletJoin) Tank_Shoot(&g_TankL); } } } if(g_TankR.iFroze > 0) g_TankR.iFroze --; if(g_TankR.bReady && g_TankR.iFroze == 0) { if(DirectX_GetInputMouse(&Mouse)) { g_TankR.iRequestFrend = Mouse.iRotateFrend; if(g_TankR.iRequestFrend != FM_NULL) if(g_TankR.iRequestFrend != g_TankR.iFrend) { if(abs(g_TankR.iRequestFrend - g_TankR.iFrend) == 2) // Yeu cau quay nguoc g_TankR.iFrend = g_TankR.iRequestFrend; else // Yeu cau quay vuong goc { if(Tank_CanRotate4Frend(&g_TankR)) g_TankR.iFrend = g_TankR.iRequestFrend; else // Neu chua the quay { // // // // // int xTank = g_TankR.x; int yTank = g_TankR.y; int iFrend = g_TankR.iFrend; int cStepForward = 0,cStepBack = 0; BOOL bForward = FALSE, bBack = FALSE; while(Tank_CanStepByStep(&g_TankR,pCells) && cStepForward < MEDIUM) { cStepForward ++; Tank_StepByStep(&g_TankR); if(Tank_CanRotate4Frend(&g_TankR)) { bForward = TRUE; break; } } g_TankR.x = xTank; g_TankR.y = yTank; if(iFrend == FM_LEFT) g_TankR.iFrend = FM_RIGHT; else if(iFrend == FM_UP) g_TankR.iFrend = FM_DOWN; else if(iFrend == FM_RIGHT) g_TankR.iFrend = FM_LEFT; else g_TankR.iFrend = FM_UP; while(Tank_CanStepByStep(&g_TankR,pCells) && cStepBack < MEDIUM) { cStepBack ++; Tank_StepByStep(&g_TankR); if(Tank_CanRotate4Frend(&g_TankR)) { bBack = TRUE; break; } } g_TankR.x = xTank; g_TankR.y = yTank; if(bForward && bBack) { if(cStepForward <= cStepBack) { cStep = cStepForward; g_TankR.iFrend = iFrend;} else cStep = cStepBack; } else if(bForward && !bBack) { cStep = cStepForward; g_TankR.iFrend = iFrend; } else if(!bForward && bBack) cStep = cStepBack; else { cStep = cStepForward; g_TankR.iFrend = iFrend; } // bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankR,pCells)) { Tank_StepByStep(&g_TankR); bStep = TRUE; cStep --; if(Tank_CanRotate4Frend(&g_TankR)) { g_TankR.iFrend = g_TankR.iRequestFrend; break; } } else break; } if(bStep) if(++ g_TankR.iFrame == 4) g_TankR.iFrame = 0; } } } // Di chuyen if(Mouse.bRightPress) { cStep = g_TankR.iSpeed * (Tank_MoveOnGlide(&g_TankR,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankR,pCells)) { Tank_StepByStep(&g_TankR); bStep = TRUE; cStep --; } else break; } if(bStep) if(++ g_TankR.iFrame == 4) g_TankR.iFrame = 0; } // Khai hoa if(Mouse.bLeftPress) if(++ g_TankR.cTimes >= 8) { g_TankR.cTimes = 0; if(g_arBullR.GetSize() < g_TankR.cBulletJoin) Tank_Shoot(&g_TankR); } } if(g_lpJoystick2) if(DirectX_GetInputJoystick(g_lpJoystick2,&Joystick2)) { if(Joystick2.bLeft) g_TankR.iRequestFrend = FM_LEFT; else if(Joystick2.bUp) g_TankR.iRequestFrend = FM_UP; else if(Joystick2.bRight) g_TankR.iRequestFrend = FM_RIGHT; else if(Joystick2.bDown) g_TankR.iRequestFrend = FM_DOWN; else g_TankR.iRequestFrend = FM_NULL; if(g_TankR.iRequestFrend != FM_NULL) { if(g_TankR.iRequestFrend != g_TankR.iFrend) // Neu khac huong { if(abs(g_TankR.iRequestFrend - g_TankR.iFrend) == 2) // Yeu cau quay nguoc g_TankR.iFrend = g_TankR.iRequestFrend; else if(Tank_CanRotate4Frend(&g_TankR)) // Quay vuong goc g_TankR.iFrend = g_TankR.iRequestFrend; } // Di chuyen Tank cStep = g_TankR.iSpeed * (Tank_MoveOnGlide(&g_TankR,pCells) ? 2:1 ); bStep = FALSE; while(cStep>0) { if(Tank_CanStepByStep(&g_TankR,pCells)) { Tank_StepByStep(&g_TankR); bStep = TRUE; cStep --; } else break; } if(bStep) { if(++ g_TankR.iFrame == 4) g_TankR.iFrame = 0; } } // Nguoi choi dang nhan nut ban if(Joystick2.bShoot) if(++ g_TankR.cTimes >= 8) { g_TankR.cTimes = 0; if(g_arBullR.GetSize() < g_TankR.cBulletJoin) Tank_Shoot(&g_TankR); } } }}
mới xử lý. Chúng ta cũng gán thiết bị được tìm thấy trước (Master Joystick) cho TankL và thấy sau cho bên phải.
Biên dịch và chạy, chúng ta có thể thao tác với Joystick như sau:
_ Nút số 1 dùng để bắn
_ Nút tròn lớn 4 hướng dùng để di chuyển.
Chào tạm biệt. [IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG][IMG]images/smilies/17.gif[/IMG]
Nhiều nữ giới quan niệm rằng, sự thèm muốn tình dục khi không có chồng là một điều gì đó rất xấu xa và lăn loàn. Thế nhưng, theo các chuyên gia tình dục cho biết, việc phụ nữ có ham muốn và cần giải...
Mang đồ chơi tình dục vào phòng...