// game update // state change: 1) kinect event. in GameUpdate 2) mouse event . in OnWindowMessage void GameObject::GameUpdate() { // update each game state switch (myGameState) { case GS_Menu: myGameMenu.Update(); if (myGameMenu.isGo2Play) { ChangeToState(GS_Playing); } break; case GS_Playing: myGamePlaying.Update(); if (myGamePlaying.isGameOver) { ChangeToState(GS_Result); } break; case GS_Result: myGameResult.Update(); if (myGameResult.isGo2Play) { ChangeToState(GS_Playing); } break; } }
void TPlayer::Tick(double delta_seconds) { m_seconds_since_last_frame_change += delta_seconds; // don't animate if standing still if (m_state == eSTATE_STANDING) m_frameIndex = 0; else if (m_seconds_since_last_frame_change >= ANIMATION_RATE) { m_frameIndex = (m_frameIndex + 1) % eFRAMES_PER_ANIMATION; m_seconds_since_last_frame_change = 0.0; } switch (m_state) { case eSTATE_WALKING: m_animation = (m_facing == eFACING_RIGHT) ? eANIM_STANDING_RIGHT : eANIM_STANDING_LEFT; MoveHorizontal(delta_seconds); if (OnSolidGround()) ChangeToState(eSTATE_STANDING); else ChangeToState(eSTATE_FALLING); break; case eSTATE_STANDING: m_animation = (m_facing == eFACING_RIGHT) ? eANIM_STANDING_RIGHT : eANIM_STANDING_LEFT; // in case the ground disappears out from under the player //if (!OnSolidGround()) // ChangeToState(eSTATE_FALLING); break; case eSTATE_JUMPING: // FALL THROUGH case eSTATE_FALLING: m_animation = (m_facing == eFACING_RIGHT) ? eANIM_JUMPING_RIGHT : eANIM_JUMPING_LEFT; MoveVertical(delta_seconds); MoveHorizontal(delta_seconds); break; case eSTATE_FIRING: m_animation = (m_facing == eFACING_RIGHT) ? eANIM_SHOOTING_RIGHT : eANIM_SHOOTING_LEFT; MoveVertical(delta_seconds); MoveHorizontal(delta_seconds); // stay in the firing state for [x] amount of time in order to display the animation // and prevent rapid-fire (full auto) // after enough time has passed, go to the other states depending on velocities. break; } }
void PlayerFSM::InitDefaultState() { FState* state = new FIdleState(mpOwner); RegisterState("Idle", state); state = new FJumpState(mpOwner); RegisterState("Jump", state); state = new FRunState(mpOwner); RegisterState("Run", state); ChangeToState("Idle"); }
void GameObject::OnWindowMessage( HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam ) { switch(myGameState) { case GS_Menu: switch(message) { case WM_LBUTTONUP: ChangeToState(GS_Playing); break; default: break; } break; case GS_Playing: switch(message) { case WM_KINECT_GESTURE_TRIGGER: switch( (int) wParam ) { case GAME_GESTURE_LEFT_MOVE: myGamePlaying.iPlayerPositionX -= HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionX < 0) { myGamePlaying.iPlayerPositionX = 0; } break; case GAME_GESTURE_RIGHT_MOVE: myGamePlaying.iPlayerPositionX += HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionX > WINDOW_WIDTH - HERO_SIZE_WIDTH) { myGamePlaying.iPlayerPositionX = WINDOW_WIDTH - HERO_SIZE_WIDTH; } break; case GAME_GESTURE_UP_MOVE: myGamePlaying.iPlayerPositionY -= HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionY < 0) { myGamePlaying.iPlayerPositionY = 0; } break; case GAME_GESTURE_DOWN_MOVE: myGamePlaying.iPlayerPositionY += HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionY > WINDOW_HEIGHT - HERO_SIZE_HEIGHT) { myGamePlaying.iPlayerPositionY = WINDOW_HEIGHT - HERO_SIZE_HEIGHT; } break; case GAME_GESTURE_GIVE_UP: //::SendMessage(this->hwnd,WM_CLOSE,0,0); myGamePlaying.isGiveUp = true; break; case GAME_GESTURE_ALL_KILL_1: if (!myGamePlaying.isAllKilledTemp1) { myGamePlaying.isAllKilledTemp1 = true; SetTimer(this->hwnd,GAME_DYNAMIC_GESTURE_TIMER,1200,NULL); } break; case GAME_GESTURE_ALL_KILL_2: if (myGamePlaying.isAllKilledTemp1) { myGamePlaying.isAllKilledTemp1 = false; myGamePlaying.isAllKilled = true; } break; default: break; } break; case WM_KEYDOWN: switch(wParam) { case 0x41: case VK_LEFT: myGamePlaying.iPlayerPositionX -= HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionX < 0) { myGamePlaying.iPlayerPositionX = 0; } break; case 0x44: case VK_RIGHT: myGamePlaying.iPlayerPositionX += HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionX > WINDOW_WIDTH - HERO_SIZE_WIDTH) { myGamePlaying.iPlayerPositionX = WINDOW_WIDTH - HERO_SIZE_WIDTH; } break; case 0x57: case VK_UP: myGamePlaying.iPlayerPositionY -= HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionY < 0) { myGamePlaying.iPlayerPositionY = 0; } break; case 0x53: case VK_DOWN: myGamePlaying.iPlayerPositionY += HERO_MOVE_SPEED; if (myGamePlaying.iPlayerPositionY > WINDOW_HEIGHT - HERO_SIZE_HEIGHT) { myGamePlaying.iPlayerPositionY = WINDOW_HEIGHT - HERO_SIZE_HEIGHT; } break; } break; case WM_LBUTTONDOWN: myGamePlaying.bIsMouseDown = true; GetCursorPos(&(myGamePlaying.pPreMousePoint)); break; case WM_LBUTTONUP: myGamePlaying.bIsMouseDown = false; break; default: break; } break; case GS_Result: switch(message) { case WM_LBUTTONUP: ChangeToState(GS_Playing); break; default: break; } break; } }
void TPlayer::MoveVertical(double secondsThisTick) { double yVelocityThisTick = secondsThisTick * m_yVelocityPerSecond; // getting less than one tick per second? something's gone very wrong or player's // computer is way too slow. assert(secondsThisTick <= 1.0); // player is either jumping or falling if (m_yVelocityPerSecond < 0) // negative Y velocity meaning moving upward. { if (CanMoveVerticalBy(yVelocityThisTick)) { m_y += yVelocityThisTick; // velocity starts out at max negative and slows down (by getting closer to zero) as jump progresses // to form something slightly resembling parabolic motion m_yVelocityPerSecond += ((ACCELERATION_PER_SECOND / 2) * secondsThisTick); if (m_yVelocityPerSecond >= 0) // positive velocity means falling ChangeToState(eSTATE_FALLING); } else // solid blocks somewhere above { // determine how far we actually can move double canMove; for (canMove = 1.0 + yVelocityThisTick; CanMoveVerticalBy(canMove) && (canMove <= 0); ++canMove) ; // no more work to do. canMove determines how far player can move. if (canMove < 0) m_y += canMove; ChangeToState(eSTATE_FALLING); } } else // apply gravity. positive Y velocity means falling. (may be falling or firing) { printf("\nDBUG: MoveVertical Path 2"); if (CanMoveVerticalBy(yVelocityThisTick+TILE_HEIGHT_PIXELS_UNSCALED)) // need to account for player height when trying to move downward since // player's m_y is the top of the head and feet are what touch the ground. { printf("\nDBUG: MoveVertical Path 2a"); m_y += yVelocityThisTick; if (OnSolidGround()) // might be now that we fell down some { printf("\nDBUG: MoveVertical Path 2a1"); m_yVelocityPerSecond = 0; if (m_xVelocityPerSecond != 0) { printf("\nDBUG: MoveVertical Path 2a1a"); ChangeToState(eSTATE_WALKING); } else { printf("\nDBUG: MoveVertical Path 2a1b"); ChangeToState(eSTATE_STANDING); } } else // still falling { printf("\nDBUG: MoveVertical Path 2a2"); // player falls faster the farther they fall (up to a terminal velocity) m_yVelocityPerSecond += (ACCELERATION_PER_SECOND * secondsThisTick); if (m_yVelocityPerSecond > MAX_Y_VELOCITY_PER_SECOND) m_yVelocityPerSecond = MAX_Y_VELOCITY_PER_SECOND; } } else // ground is closer than our present velocity. find out where it is and stop there { printf("\nDBUG: MoveVertical Path 2b"); m_y = trunc(m_y); double canMove; for (canMove = TILE_HEIGHT_PIXELS_UNSCALED; // one pixel below current position CanMoveVerticalBy(canMove); // can player move that far? ++canMove) // try even a bit further ; m_y = trunc(m_y + (canMove - TILE_HEIGHT_PIXELS_UNSCALED)); m_yVelocityPerSecond = 0; if (m_xVelocityPerSecond != 0) { printf("\nDBUG: MoveVertical Path 2b1"); ChangeToState(eSTATE_WALKING); } else { printf("\nDBUG: MoveVertical Path 2b2"); ChangeToState(eSTATE_STANDING); } } } }
void TPlayer::ProcessAction(action_t action) { // assume there will not be a state transition unless otherwise determined TPlayer::TPlayerState newState = m_state; // what the player is allowed to do depends on which state player is currently in. switch (m_state) { case eSTATE_STANDING: // all actions are valid from the standing state switch (action) { case eACTION_MOVE_LEFT: m_facing = eFACING_LEFT; newState = eSTATE_WALKING; break; case eACTION_MOVE_RIGHT: m_facing = eFACING_RIGHT; newState = eSTATE_WALKING; break; case eACTION_JUMP: if (OnSolidGround()) newState = eSTATE_JUMPING; break; case eACTION_FIRE: if (m_ammo) newState = eSTATE_FIRING; break; default: assert(0); } break; case eSTATE_WALKING: // all actions are valid from the walking state switch (action) { case eACTION_MOVE_LEFT: m_facing = eFACING_LEFT; newState = eSTATE_WALKING; break; case eACTION_MOVE_RIGHT: m_facing = eFACING_RIGHT; newState = eSTATE_WALKING; break; case eACTION_JUMP: if (OnSolidGround()) newState = eSTATE_JUMPING; break; case eACTION_FIRE: if (m_ammo) newState = eSTATE_FIRING; break; default: assert(0); } break; case eSTATE_JUMPING: // from the jumping state, you are allowed to switch directions or land switch (action) { case eACTION_MOVE_LEFT: m_facing = eFACING_LEFT; m_xVelocityPerSecond = MAX_X_VELOCITY_PER_SECOND; break; case eACTION_MOVE_RIGHT: m_facing = eFACING_RIGHT; m_xVelocityPerSecond = MAX_X_VELOCITY_PER_SECOND; break; case eACTION_JUMP: // no double-jumping allowed break; case eACTION_FIRE: // currently not allowed to fire in mid-air. break; default: assert(0); } break; case eSTATE_FALLING: // while falling you are allowed to switch directions, shoot, or land switch (action) { case eACTION_MOVE_LEFT: m_facing = eFACING_LEFT; m_xVelocityPerSecond = MAX_X_VELOCITY_PER_SECOND; break; case eACTION_MOVE_RIGHT: m_facing = eFACING_RIGHT; m_xVelocityPerSecond = MAX_X_VELOCITY_PER_SECOND; break; case eACTION_JUMP: // no double-jumping allowed break; case eACTION_FIRE: if (m_ammo) newState = eSTATE_FIRING; break; default: assert(0); } break; case eSTATE_FIRING: // only thing you can do is turn around. switch (action) { case eACTION_MOVE_LEFT: m_facing = eFACING_LEFT; break; case eACTION_MOVE_RIGHT: m_facing = eFACING_RIGHT; break; case eACTION_JUMP: break; case eACTION_FIRE: // no rapid-firing at the moment break; default: assert(0); } break; default: assert(0); } ChangeToState(newState); }