跳跃时我遇到了一些碰撞问题,
当玩家跳到盒子上时,它会很奇怪,因为当它保持在盒子的顶部时,它会一直上下移动,我可以看到玩家的跳跃速度不断增加(因此它会下降)并且会减少(所以它会并且重力也是如此。
这就是我的意思:
代码(我上传了新版本,之前有一个损坏的png错误) http://s000.tinyupload.com/index.php?file_id=07023750129261943350
我复制了代码的重要部分。
struct SPlayer
{
void Move();
void ApplyBoxCollision();
float Width = 100.0f;
float Height = 100.0f;
float XPosition = (WINDOW_WIDTH * 0.5f) - (Width * 0.5f); //center of the screen
float YPosition = 362;//top of the player
float YDesiredPosition = 362; //Player DesiredStart Position on Y axis (it updates every time Player.Yposition changes). So if I press S to jump at the very beginning of the program coming down the player will go to start position
float XDesiredPosition = 0;
float XPrevDesiredPosition = 0;
float YPrevDesiredPosition = 0;
float XVelocity = 160.0f;
float YVelocity = 160.0f;
float JumpVelocity = -422.0f;
float Gravity = 0;
EPlayerState State = PLAYER_STILL;
SDL_Texture* playerTexturewr = nullptr;
SDL_Texture* playerTexturewl = nullptr;
SDL_Texture* playerTexturejr = nullptr;
SDL_Texture* playerTexturejl = nullptr;
SDL_Texture* playerTextureclimb = nullptr;
SDL_Rect Quad;
};
void HandleEvents(void)
{
....
case SDLK_s:
{
if (Player.OnLadder == false) //Player can jump only if not on ladder
{
keyS_Down = 1;//key down (it means we are pressing S)
keyS_Up = 0;//(Releasing S is disabled)
if (spritestill == 2) //was set to 2 when right key is pressed
{
Player.State = PLAYER_JUMP_RIGHT;
}
if (spritestill == 1) //was set to 1 when left key is pressed
Player.State = PLAYER_JUMP_LEFT;
if (Player.State == PLAYER_STILL)
{
Player.State = PLAYER_JUMP_RIGHT;
}
}
break;
}
......
else if( Event.type == SDL_KEYUP && Event.key.repeat == 0 )
{
....
case SDLK_s:
{
keyS_Down = 1; //important: so player keeps jumping also when released (until it jump before being affected by gravity)
}
break;
}
void SPlayer::Move()
{
switch (Player.State)
{
case PLAYER_MOVING_LEFT:
//converting double DeltaTime in float
Player.XPosition += -Player.XVelocity*(float)DeltaTime;
break;
case PLAYER_MOVING_RIGHT:
Player.XPosition += Player.XVelocity * (float)DeltaTime;
break;
case PLAYER_MOVING_UP:
Player.YPosition += -Player.YVelocity * (float)DeltaTime;
break;
case PLAYER_MOVING_DOWN:
Player.YPosition += +Player.YVelocity * (float)DeltaTime;
break;
}
default:
break;
}
}
void Update(void) {
HandleEvents(); //check events every time we update....
// Calculate the deltatime every time we update....
NewTime = SDL_GetTicks(); //time in msecs running since this call
DeltaTime = (NewTime - OldTime) / 1000.0; //convert msecs in seconds
OldTime = NewTime;.....
.............
if(keyS_Down == 1 ) //it means is true that I pressed S (the jump key)
{
Player.Gravity = 1022.0f;
Player.JumpVelocity = Player.JumpVelocity += Player.Gravity * (float)DeltaTime;
Player.YPosition += Player.JumpVelocity * (float)DeltaTime;
if (Player.YPosition >= Player.YDesiredPosition)
{
Player.Gravity = 0;
Player.JumpVelocity = -422.0f;
Player.YPosition = Player.YDesiredPosition;
/* every time the player gets down it is set to the current YDesiredPosition that is updated every time except when jumping*/
keyS_Down = 0;
Player.State = PLAYER_STILL;
}
}
if (keyS_Down && keyL_Down)
{
Player.State = PLAYER_JUMP_LEFT;
Player.XPosition -= 2.5f; //jump on the left
}
if (keyS_Down && keyR_Down)
{
Player.State = PLAYER_JUMP_RIGHT;
Player.XPosition += 2.5f; //jump on the right
}
Player.ApplyBoxCollision();
void SPlayer::ApplyBoxCollision()
{
for( int i = 0; i<2; i++)
if ((QuadVsQuad(Player.Quad, Block[i].Quad) == true))
{
blockCollision = 1;
Player.XPrevDesiredPosition = Player.XDesiredPosition;
Player.YPrevDesiredPosition = Player.YDesiredPosition;
//move back if we have collisions
switch (Player.State)
{
case PLAYER_MOVING_LEFT:
Player.XPosition += +Player.XVelocity*(float)DeltaTime;
break;
case PLAYER_MOVING_RIGHT:
Player.XPosition += -Player.XVelocity * (float)DeltaTime;
break;
case PLAYER_MOVING_UP:
Player.YPosition += +Player.YVelocity * (float)DeltaTime;
break;
case PLAYER_MOVING_DOWN:
Player.YPosition += -Player.YVelocity * (float)DeltaTime;
break;
case PLAYER_JUMP_RIGHT:
Player.YPosition = Player.YPosition -50; //to get on top of the box
Player.Gravity = 0;
Player.JumpVelocity = 0;
KeyD_Down = 0;
break;
case PLAYER_JUMP_LEFT:
Player.YPosition = Player.YPosition - 50; // top get on top of the box
Player.Gravity = 0;
Player.JumpVelocity = 0;
break;
default:
break;
}
//update player quad after collision
Player.Quad = {static_cast<int>(Player.XPosition), static_cast<int>(Player.YPosition) , static_cast<int>(Player.Width), static_cast<int>(Player.Height)};
}
else
blockCollision = 0;
}