/*..........................................................................*/ QState Tunnel_game_over(Tunnel *me, QEvt const *e) { switch (e->sig) { case Q_ENTRY_SIG: { QTimeEvt_postEvery(&me->blinkTimeEvt, (QActive *)me, BSP_TICKS_PER_SEC/2); /* 1/2 sec */ QTimeEvt_postIn(&me->screenTimeEvt, (QActive *)me, BSP_TICKS_PER_SEC*5); /* 5 sec timeout */ me->blink_ctr = 0; BSP_drawNString((GAME_SCREEN_WIDTH - 6*9)/2, 0, "Game Over"); return Q_HANDLED(); } case Q_EXIT_SIG: { QTimeEvt_disarm(&me->blinkTimeEvt); QTimeEvt_disarm(&me->screenTimeEvt); BSP_updateScore(0); /* update the score on the display */ return Q_HANDLED(); } case BLINK_TIMEOUT_SIG: { me->blink_ctr ^= 1; /* toggle the blink couner */ BSP_drawNString((GAME_SCREEN_WIDTH - 6*9)/2, 0, ((me->blink_ctr == 0) ? "Game Over" : " ")); return Q_HANDLED(); } case SCREEN_TIMEOUT_SIG: { return Q_TRAN(&Tunnel_demo); } } return Q_SUPER(&Tunnel_active); }
/*..........................................................................*/ static LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { /* Perform initialization upon cration of the main dialog window * NOTE: Any child-windows are NOT created yet at this time, so * the GetDlgItem() function can't be used (it will return NULL). */ case WM_CREATE: { l_hWnd = hWnd; /* save the window handle */ /* initialize the owner-drawn buttons... * NOTE: must be done *before* the first drawing of the buttons, * so WM_INITDIALOG is too late. */ OwnerDrawnButton_init(&l_userBtn, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_BTN_UP)), LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_BTN_DWN)), LoadCursor(NULL, IDC_HAND)); return 0; } /* Perform initialization after all child windows have been created */ case WM_INITDIALOG: { GraphicDisplay_init(&l_oled, BSP_SCREEN_WIDTH, 2U, /* scale horizontally by 2 */ BSP_SCREEN_HEIGHT, 2U, /* scale vertically by 2 */ GetDlgItem(hWnd, IDC_LCD), c_offColor); SegmentDisplay_init(&l_userLED, 1U, /* 1 "segment" (the LED itself) */ 2U); /* 2 bitmaps (for LED OFF/ON states) */ SegmentDisplay_initSegment(&l_userLED, 0U, GetDlgItem(hWnd, IDC_LED)); SegmentDisplay_initBitmap(&l_userLED, 0U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_LED_OFF))); SegmentDisplay_initBitmap(&l_userLED, 1U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_LED_ON))); SegmentDisplay_init(&l_scoreBoard, 4U, /* 4 "segments" (digits 0-3) */ 10U); /* 10 bitmaps (for 0-9 states) */ SegmentDisplay_initSegment(&l_scoreBoard, 0U, GetDlgItem(hWnd, IDC_SEG0)); SegmentDisplay_initSegment(&l_scoreBoard, 1U, GetDlgItem(hWnd, IDC_SEG1)); SegmentDisplay_initSegment(&l_scoreBoard, 2U, GetDlgItem(hWnd, IDC_SEG2)); SegmentDisplay_initSegment(&l_scoreBoard, 3U, GetDlgItem(hWnd, IDC_SEG3)); SegmentDisplay_initBitmap(&l_scoreBoard, 0U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG0))); SegmentDisplay_initBitmap(&l_scoreBoard, 1U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG1))); SegmentDisplay_initBitmap(&l_scoreBoard, 2U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG2))); SegmentDisplay_initBitmap(&l_scoreBoard, 3U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG3))); SegmentDisplay_initBitmap(&l_scoreBoard, 4U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG4))); SegmentDisplay_initBitmap(&l_scoreBoard, 5U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG5))); SegmentDisplay_initBitmap(&l_scoreBoard, 6U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG6))); SegmentDisplay_initBitmap(&l_scoreBoard, 7U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG7))); SegmentDisplay_initBitmap(&l_scoreBoard, 8U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG8))); SegmentDisplay_initBitmap(&l_scoreBoard, 9U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG9))); BSP_updateScore(0U); /* --> QP: spawn the application thread to run main_gui() */ Q_ALLEGE(CreateThread(NULL, 0, &appThread, NULL, 0, NULL) != (HANDLE)0); return 0; } case WM_DESTROY: { BSP_terminate(0); return 0; } /* commands from regular buttons and menus... */ case WM_COMMAND: { SetFocus(hWnd); switch (wParam) { case IDOK: case IDCANCEL: { BSP_terminate(0); break; } } return 0; } /* owner-drawn buttons... */ case WM_DRAWITEM: { LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT)lParam; switch (pdis->CtlID) { case IDC_USER: { /* USER owner-drawn button */ switch (OwnerDrawnButton_draw(&l_userBtn, pdis)) { case BTN_DEPRESSED: { playerTrigger(); SegmentDisplay_setSegment(&l_userLED, 0U, 1U); break; } case BTN_RELEASED: { SegmentDisplay_setSegment(&l_userLED, 0U, 0U); break; } default: { break; } } break; } } return 0; } /* mouse input... */ case WM_MOUSEWHEEL: { if ((HIWORD(wParam) & 0x8000U) == 0U) {/* wheel turned forward? */ moveShipUp(); } else { /* the wheel was turned backwards */ moveShipDown(); } return 0; } /* keyboard input... */ case WM_KEYDOWN: { switch (wParam) { case VK_UP: moveShipUp(); break; case VK_DOWN: moveShipDown(); break; case VK_SPACE: playerTrigger(); break; } return 0; } } return DefWindowProc(hWnd, iMsg, wParam, lParam) ; }
//............................................................................ static LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { switch (iMsg) { // Perform initialization upon cration of the main dialog window // NOTE: Any child-windows are NOT created yet at this time, so // the GetDlgItem() function can't be used (it will return NULL). // case WM_CREATE: { l_hWnd = hWnd; // save the window handle // initialize the owner-drawn buttons... // NOTE: must be done *before* the first drawing of the buttons, // so WM_INITDIALOG is too late. // l_userBtn.init(LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_BTN_UP)), LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_BTN_DWN)), LoadCursor(NULL, IDC_HAND)); return 0; } // Perform initialization after all child windows have been created case WM_INITDIALOG: { l_oled.init(BSP_SCREEN_WIDTH, 2U, // scale horizontally by 2 BSP_SCREEN_HEIGHT, 2U, // scale vertically by 2 GetDlgItem(hWnd, IDC_LCD), c_offColor); l_userLED.init(1U, // 1 "segment" (the LED itself) 2U); // 2 bitmaps (for LED OFF/ON states) l_userLED.initSegment(0U, GetDlgItem(hWnd, IDC_LED)); l_userLED.initBitmap(0U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_LED_OFF))); l_userLED.initBitmap(1U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_LED_ON))); l_scoreBoard.init(4U, // 4 "segments" (digits 0-3) 10U); // 10 bitmaps (for 0-9 states) l_scoreBoard.initSegment(0U, GetDlgItem(hWnd, IDC_SEG0)); l_scoreBoard.initSegment(1U, GetDlgItem(hWnd, IDC_SEG1)); l_scoreBoard.initSegment(2U, GetDlgItem(hWnd, IDC_SEG2)); l_scoreBoard.initSegment(3U, GetDlgItem(hWnd, IDC_SEG3)); l_scoreBoard.initBitmap(0U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG0))); l_scoreBoard.initBitmap(1U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG1))); l_scoreBoard.initBitmap(2U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG2))); l_scoreBoard.initBitmap(3U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG3))); l_scoreBoard.initBitmap(4U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG4))); l_scoreBoard.initBitmap(5U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG5))); l_scoreBoard.initBitmap(6U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG6))); l_scoreBoard.initBitmap(7U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG7))); l_scoreBoard.initBitmap(8U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG8))); l_scoreBoard.initBitmap(9U, LoadBitmap(l_hInst, MAKEINTRESOURCE(IDB_SEG9))); BSP_updateScore(0U); // --> QP: spawn the application thread to run main() Q_ALLEGE(CreateThread(NULL, 0, &appThread, NULL, 0, NULL) != (HANDLE)0); return 0; } case WM_DESTROY: { BSP_terminate(0); return 0; } // commands from regular buttons and menus... case WM_COMMAND: { SetFocus(hWnd); switch (wParam) { case IDOK: case IDCANCEL: { BSP_terminate(0); break; } } return 0; } // owner-drawn buttons... case WM_DRAWITEM: { LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT)lParam; switch (pdis->CtlID) { case IDC_USER: { // USER owner-drawn button switch (l_userBtn.draw(pdis)) { case OwnerDrawnButton::BTN_DEPRESSED: { BSP_playerTrigger(); l_userLED.setSegment(0U, 1U); break; } case OwnerDrawnButton::BTN_RELEASED: { l_userLED.setSegment(0U, 0U); break; } } break; } } return 0; } // mouse input... case WM_MOUSEWHEEL: { if ((HIWORD(wParam) & 0x8000U) == 0U) { // wheel turned forward? BSP_moveShipUp(); } else { // the wheel was turned backwards BSP_moveShipDown(); } return 0; } // keyboard input... case WM_KEYDOWN: { switch (wParam) { case VK_UP: BSP_moveShipUp(); break; case VK_DOWN: BSP_moveShipDown(); break; case VK_SPACE: BSP_playerTrigger(); break; } return 0; } } return DefWindowProc(hWnd, iMsg, wParam, lParam) ; }
/*..........................................................................*/ QState Tunnel_playing(Tunnel *me, QEvt const *e) { uint8_t x; int8_t y; uint8_t bmp; switch (e->sig) { case Q_ENTRY_SIG: { static QEvt const takeoff = { TAKE_OFF_SIG, 0 }; me->minimal_gap = GAME_SCREEN_HEIGHT - 3; /* erase the walls */ memset(l_walls, (uint8_t)0, (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8)); QACTIVE_POST(AO_Ship, &takeoff, me); /* post the TAKEOFF sig */ return Q_HANDLED(); } case Q_EXIT_SIG: { QEvt recycle; recycle.sig = MINE_RECYCLE_SIG; Tunnel_dispatchToAllMines(me, &recycle); /* recycle all Mines */ return Q_HANDLED(); } case TIME_TICK_SIG: { /* render this frame on the display */ BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT); Tunnel_advance(me); Tunnel_plantMine(me); Tunnel_dispatchToAllMines(me, e); return Q_HANDLED(); } case SHIP_IMG_SIG: case MISSILE_IMG_SIG: { x = (uint8_t)((ObjectImageEvt const *)e)->x; y = (int8_t)((ObjectImageEvt const *)e)->y; bmp = (uint8_t)((ObjectImageEvt const *)e)->bmp; /* did the Ship/Missile hit the tunnel wall? */ if (Tunnel_isWallHit(me, bmp, x, y)) { static QEvt const hit = { HIT_WALL_SIG, 0}; if (e->sig == SHIP_IMG_SIG) { QACTIVE_POST(AO_Ship, &hit, me); } else { QACTIVE_POST(AO_Missile, &hit, me); } } Tunnel_addImageAt(me, bmp, x, y); Tunnel_dispatchToAllMines(me, e); /* let Mines check for hits */ return Q_HANDLED(); } case MINE_IMG_SIG: case EXPLOSION_SIG: { x = (uint8_t)((ObjectImageEvt const *)e)->x; y = (int8_t)((ObjectImageEvt const *)e)->y; bmp = (uint8_t)((ObjectImageEvt const *)e)->bmp; Tunnel_addImageAt(me, bmp, x, y); return Q_HANDLED(); } case SCORE_SIG: { BSP_updateScore(((ScoreEvt const *)e)->score); /* increase difficulty of the game: * the tunnel gets narrower as the score goes up */ me->minimal_gap = GAME_SCREEN_HEIGHT - 3 - ((ScoreEvt const *)e)->score/2000; return Q_HANDLED(); } case GAME_OVER_SIG: { uint16_t score = ((ScoreEvt const *)e)->score; char str[5]; BSP_updateScore(score); /* clear the screen */ memset(l_frame, (uint8_t)0, (GAME_SCREEN_WIDTH * GAME_SCREEN_HEIGHT/8)); BSP_drawBitmap(l_frame, GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT); /* Output the final score to the screen */ BSP_drawNString((GAME_SCREEN_WIDTH - 6*10)/2, 1, "Score:"); str[4] = '\0'; /* zero-terminate the string */ str[3] = '0' + (score % 10); score /= 10; str[2] = '0' + (score % 10); score /= 10; str[1] = '0' + (score % 10); score /= 10; str[0] = '0' + (score % 10); BSP_drawNString((GAME_SCREEN_WIDTH - 6*10)/2 + 6*6, 1, str); return Q_TRAN(&Tunnel_game_over); } } return Q_SUPER(&Tunnel_active); }