繁体   English   中英

(SFML)角色移动不自然且有奇怪的怪癖

[英](SFML) Character movement is unnatural and has strange quirks

tld; dr:角色移动容易出现毛刺,似乎并不总是能记录到按键的释放,并且总体上很差; 有任何改进建议(或错误修复)?

你好,
我(仍在)致力于使用C ++在SFML中制作一个相对简单的平台游戏,而我一直在努力使动作流畅。 我的“地图”由(x,y)对的网格组成,这些网格定义了要在该点显示的图块(x和y代表我的关卡Spritesheet中图块Sprite的坐标)。

我遇到的问题是,即使该运动看起来可行,它有时仍会以意想不到的方式运行,而且我也不知道如何解决它,甚至也不知道为什么会发生这种情况。

例如,向箭头发出垃圾邮件(快速按下),有时您可以使角色在地图上滑动(并失去对他的控制),直到他撞到某物为止。 在其他时候(通常是倾斜进入),您可能会卡在地板上,除非先跳下车才能解开,否则无法移动。

截至目前,我正在通过使用4个点进行碰撞检测,这些点代表角色的Hitbox的矩形,因此这可能是问题的一部分。

(旁注:我的按键操作也只检测箭头键,而不检测WASD ...即使它们在相同的if语句中)

(main.cpp)(相关代码)

if (event.type == sf::Event::KeyPressed)
            {
                if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right)
                    thePlayer.goingRight = true;
                if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)
                    thePlayer.goingLeft = true;
                if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)
                {
                    thePlayer.isJumping = true;
                    thePlayer.goingUp = true;
                }
                if (event.key.code == sf::Keyboard::S || event.key.code == sf::Keyboard::Down)
                    thePlayer.goingDown = true;
            }
            if (event.type ==  sf::Event::KeyReleased)
            {
                if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right)
                    thePlayer.goingRight = false;
                if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)
                    thePlayer.goingLeft = false;
                if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)
                    thePlayer.goingUp = false;
                if (event.key.code == sf::Keyboard::Space)
                {
                    if (bulletsfired != true)
                    {
                        bulletsfired = true;
                        if (thePlayer.directionFacing == 0)
                        {
                            bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
                        }
                        else
                        {
                            bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x + 25.f, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
                        }
                        bulletCount++;
                    }
                }
            }

            thePlayer.updatePlayer();

            for (int i = 0; i < bulletsList.size(); i++)
            {
                bulletsList[i].update();
            }


(player.cpp)(相关代码)

void player::updatePlayer()
{
    if (player::isJumping == true)
        player::goingDown = true;

    playerPosX = player::mSprite.getPosition().x;
    playerPosY = player::mSprite.getPosition().y;
    //Gravity
    if (((map[(playerPosY+48)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+48)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+28)/32].y) != 0 ))
    {
        player::isJumping = false;
        player::goingDown = false;
    }
    else
    {
        player::isJumping = true;
        player::goingDown = true;
    }

    //Collision top
    if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
    {
        player::goingUp = false;
    }

    //Collision right
    if (((map[(playerPosY+46)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+28)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
    {
        if (((map[(playerPosY+46)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+46)/32][(playerPosX+28)/32].y) == 5 ) && ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+28)/32].y) == 5 ))
        {
            std::cout << "Ladder right!";
            player::goingDown = false;
            player::isJumping = false;
        }
        else
        {
            player::goingRight = false;
        }
    }

    //Collision left
    if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+46)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+5)/32].y) != 0 ))
    {
        if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+5)/32].y) == 5 ) && ((map[(playerPosY+46)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+46)/32][(playerPosX+5)/32].y) == 5 ))
        {
            std::cout << "Ladder left!";
            player::goingDown = false;
            player::isJumping = false;
        }
        else
        {
            player::goingLeft = false;
        }
    }



    if (player::goingRight == true)
    {
        player::moveRight(player::playerSpeed);
    }
    if (player::goingLeft == true)
    {
        player::moveLeft(player::playerSpeed);
    }
    if (player::goingDown == true)
    {
        player::moveDown(player::playerFallSpeed);
    }
    if (player::goingUp == true)
    {
        player::moveUp(player::playerJumpSpeed);
    }
    if (player::goingRight == true && player::goingUp == true)
    {
        player::mSprite.move(player::playerSpeed * 0.5 , -player::playerJumpSpeed * 0.5);
    }
    if (player::goingLeft == true && player::goingUp == true)
    {
        player::mSprite.move(-player::playerSpeed * 0.5 , -player::playerJumpSpeed * 0.5);
    }
    if (player::goingRight == true && player::goingDown == true)
    {
        player::mSprite.move(player::playerSpeed * 0.5 , player::playerFallSpeed * 0.5);
    }
    if (player::goingLeft == true && player::goingDown == true)
    {
        player::mSprite.move(-player::playerSpeed * 0.5 , player::playerFallSpeed * 0.5);
    }
}


map [i] [j] .x = 4定义的图块,map [i] [j] .y = 5是“梯形”图块,因此我希望玩家能够在其中移动(以及为什么)它将“梯形图/ direction /!”输出到控制台)。

如果完全相关; playerSpeed = 4.f; playerFallSpeed = 5.f; playerJumpSpeed = 10.f;

最后,感谢您阅读本文! 我非常感谢任何帮助,因为我已经为此苦苦挣扎了大约一个星期。

在尝试实施Dundee的建议后,我终于得到了(或多或少)可以工作的代码。 关键的变化是在碰撞中将方向速度设置为0(例如,向右移动是x正,因此,如果我与右侧的墙碰撞,并且我的玩家速度大于0,则将其设置为0)。 另一个重大变化是抵消有时玩家“掉进地板上”的事实。 我相信会发生这种情况,因为我每秒仅检查碰撞60次,因此有时播放器的高度可能会下降几像素,所以我会检查是否发生了这种情况,如果确实发生,将播放器上移两个像素。 (当然,播放器可能会比预期的多掉2到5个像素,但这似乎或多或少地解决了这个问题)。 该解决方案的唯一缺点是存在明显的“反弹”。 我将利用动画的优势来使游戏看起来更加逼真。

这是新代码:

(main.cpp)

if (event.type == sf::Event::KeyReleased)
            {
                if (event.key.code == sf::Keyboard::D || event.key.code == sf::Keyboard::Right)
                {
                    thePlayer.playerVelocity.x = 0.f;
                }
                if (event.key.code == sf::Keyboard::A || event.key.code == sf::Keyboard::Left)
                {
                    thePlayer.playerVelocity.x = 0.f;
                }
                if (event.key.code == sf::Keyboard::W || event.key.code == sf::Keyboard::Up)
                {   
                    //Nothing
                }
                if (event.key.code == sf::Keyboard::Space)
                {
                    if (bulletsfired != true)
                    {
                        bulletsfired = true;
                        if (thePlayer.directionFacing == 0)
                        {
                            bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
                        }
                        else
                        {
                            bulletsList.push_back(myPlayerNamespace::projectile (bulletTexture, thePlayer.mSprite.getPosition().x + 25.f, (thePlayer.mSprite.getPosition().y + 20.f), thePlayer.directionFacing, bulletCount));
                        }
                        bulletCount++;
                    }
                    thePlayer.playerVelocity.x = 0;
                }
            }

            //Direct input for movement
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) || sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
            {
                if (thePlayer.playerVelocity.y >= -thePlayer.playerMaxVelocity.y && thePlayer.isJumping == false)
                {
                    thePlayer.playerVelocity.y -= thePlayer.playerJumpSpeed;
                }   
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) || sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
            {
                thePlayer.mSprite.setTextureRect(sf::IntRect(0,0,32,48));
                thePlayer.directionFacing = 0;
                if (thePlayer.playerVelocity.x >= -thePlayer.playerMaxVelocity.x)
                {
                    thePlayer.playerVelocity.x -= thePlayer.playerSpeed;
                }
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) || sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
            {
                //Nothing
                //thePlayer.playerVelocity.y += gravity.y;
            }
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) || sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
            {
                thePlayer.mSprite.setTextureRect(sf::IntRect(32,0,32,48));
                thePlayer.directionFacing = 1;
                if (thePlayer.playerVelocity.x <= thePlayer.playerMaxVelocity.x)
                {
                    thePlayer.playerVelocity.x += thePlayer.playerSpeed;
                }
            }

            thePlayer.updatePlayer();



(player.cpp)

void player::updatePlayer()
{
    playerPosX = player::mSprite.getPosition().x;
    playerPosY = player::mSprite.getPosition().y;
    //Gravity + Collision bottom
    if ((((map[(playerPosY+48)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+48)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+48)/32][(playerPosX+28)/32].y) != 0 )) && isJumping==true)
    {
        {
            playerVelocity.y = 0.f;
            isJumping = false;
            if ((((map[(playerPosY+46)/32][(playerPosX+10)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+10)/32].y) != 0 ) || ((map[(playerPosY+46)/32][(playerPosX+20)/32].x) != 0 || (map[(playerPosY+46)/32][(playerPosX+20)/32].y) != 0 )))
            {
                playerPosY -= 2;
                mSprite.setPosition(playerPosX, playerPosY);
                outline.setPosition(playerPosX+8, playerPosY+6);
            }
        }
    }
    else
    {
        if (playerVelocity.y <= playerMaxVelocity.y && isJumping == true)
        {
            playerVelocity.y += gravity.y;
        }
        isJumping = true;
    }

    //Collision top
    if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
    {
        if (playerVelocity.y < 0)
        {
            playerVelocity.y = 0;
        }
    }

    //Collision right
    if (((map[(playerPosY+45)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+45)/32][(playerPosX+28)/32].y) != 0 ) || ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+28)/32].y) != 0 ))
    {
        if (((map[(playerPosY+45)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+45)/32][(playerPosX+28)/32].y) == 5 ) && ((map[(playerPosY+6)/32][(playerPosX+28)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+28)/32].y) == 5 ))
        {
            //std::cout << "Ladder right!";
        }
        else
        {
            if (playerVelocity.x > 0)
            {
                playerVelocity.x = 0;
            }
        }
    }

    //Collision left
    if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+6)/32][(playerPosX+5)/32].y) != 0 ) || ((map[(playerPosY+45)/32][(playerPosX+5)/32].x) != 0 || (map[(playerPosY+45)/32][(playerPosX+5)/32].y) != 0 ))
    {
        if (((map[(playerPosY+6)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+6)/32][(playerPosX+5)/32].y) == 5 ) && ((map[(playerPosY+45)/32][(playerPosX+5)/32].x) == 4 && (map[(playerPosY+46)/32][(playerPosX+5)/32].y) == 5 ))
        {
            //std::cout << "Ladder left!";
        }
        else
        {
            if (playerVelocity.x < 0)
            {
                playerVelocity.x = 0;
            }
        }
    }
    mSprite.move(playerVelocity.x, playerVelocity.y);
    outline.move(playerVelocity.x, playerVelocity.y);
}



特别感谢Dundee,他提出了使用矢量进行运动的好主意。 如果可以通过某种方式为您提供互联网积分,请告诉我,我很乐意做! :D

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM