我无法在SFML中获得良好的32x32基于网格的移动,并需要一些帮助来确定如何使其工作。这是我到目前为止所得到的:
void player::updateMovement()
{
if(walkFinish) {
pixelWalked = 0;
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
direction = 1; // direction set to up
EndYPos = GetPosition().y - 32; // The position the character is moving towards.
walkFinish = false;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && canMoveRight) {
direction = 2; // Right
EndXPos = GetPosition().x + 32;
walkFinish = false;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
direction = 3; // Down
EndYPos = GetPosition().y + 32;
walkFinish = false;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
direction = 4; // Left
EndXPos = GetPosition().x - 32;
walkFinish = false;
}
} else if(!walkFinish && direction > 0 && direction < 5) { // if walk is not finished, move character.
if(direction == 1 && !(EndYPos == GetPosition().y)){ // Up
rect.move(0, -movementSpeed);
} else if(direction == 2 && !(EndXPos == GetPosition().x) && canMoveRight) { // Right
rect.move(movementSpeed, 0);
} else if(direction == 3 && !(EndYPos == GetPosition().y)) { // Down
rect.move(0, movementSpeed);
} else if(direction == 4 && !(EndXPos == GetPosition().x)) { // Left
rect.move(-movementSpeed, 0);
}
}
if( ((EndXPos == GetPosition().x) && (EndYPos == GetPosition().y)) && !(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) && !(sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) && !(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) && !(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) ) {
walkFinish = true; // if character has reached endpos in both axis, walkFinish becomes true
} else if( ((EndXPos == GetPosition().x) && (EndYPos == GetPosition().y))) { // This gets rid of a 1 frame character pause and makes the movement smoother
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
direction = 1; // direction set to up
EndYPos = GetPosition().y - 32; // Same deal as the first if statement of this function.
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right) && canMoveRight) {
direction = 2;
EndXPos = GetPosition().x + 32;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
direction = 3;
EndYPos = GetPosition().y + 32;
} else if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
direction = 4;
EndXPos = GetPosition().x - 32;
}
}
}
和我的碰撞检查:
counter = 0;
for(iterWall = wallArray.begin(); iterWall != wallArray.end(); iterWall++) {
if(objectPlayer.rect.getPosition().x == (wallArray[counter].rect.getPosition().x + 64)) {
objectPlayer.canMoveLeft = false;
} else if(objectPlayer.rect.getPosition().x == (wallArray[counter].rect.getPosition().x - 64)) {
objectPlayer.canMoveRight = false;
} else if(objectPlayer.rect.getPosition().y == (wallArray[counter].rect.getPosition().y - 64)) {
objectPlayer.canMoveDown = false;
} else if(objectPlayer.rect.getPosition().y == (wallArray[counter].rect.getPosition().y + 64)) {
objectPlayer.canMoveUp = false;
} else {
objectPlayer.canMoveUp = true;
objectPlayer.canMoveRight = true;
objectPlayer.canMoveDown = true;
objectPlayer.canMoveLeft = true;
}
counter++;
}
此代码的问题在于碰撞部分,因为角色在碰撞墙壁时会有卡住的风险。碰撞甚至发生在墙上,我的角色因此而不能移动到那里。我不知道如何实现基于网格的移动和碰撞,任何人都有示例代码,博客文章,教程或一些提示?
编辑: 碰撞部分发生在updateMovement函数之前!
答案 0 :(得分:0)
我不知道你是否这样做,但通常你可以在你申请之前检查注册的移动(或者如果需要可以移动并稍后撤消),然后检查它是否与墙碰撞,如果它只是忽略了输入移动。或者你可以在检测到碰撞后应用非常小的余量,这样如果没有再次按下它就不会再次碰撞。
答案 1 :(得分:0)
最后想出来了:
counter = 0;
for(iterWall = wallArray.begin(); iterWall != wallArray.end(); iterWall++) {
if(!leftCheck){
if( ( (wallArray[counter].rect.getPosition().x + 64) == objectPlayer.rect.getPosition().x ) && ( (wallArray[counter].rect.getPosition().y) == objectPlayer.rect.getPosition().y ) ) {
objectPlayer.canMoveLeft = false; // if character is standing directly to the right of player AND(wall and player is at the same height), player cant move left.
leftCheck = true;
} else {
objectPlayer.canMoveLeft = true;
}
}
if(!rightCheck) {
if( ( (wallArray[counter].rect.getPosition().x + - 64) == objectPlayer.rect.getPosition().x ) && ( (wallArray[counter].rect.getPosition().y) == objectPlayer.rect.getPosition().y ) ) {
objectPlayer.canMoveRight = false;
rightCheck = true;
} else {
objectPlayer.canMoveRight = true;
}
}
if(!downCheck) {
if( ( (wallArray[counter].rect.getPosition().y + 64) == objectPlayer.rect.getPosition().y ) && ( wallArray[counter].rect.getPosition().x == objectPlayer.rect.getPosition().x ) ) {
objectPlayer.canMoveUp = false;
downCheck = true;
} else {
objectPlayer.canMoveUp = true;
}
}
if(!upCheck) {
if( ( (wallArray[counter].rect.getPosition().y - 64) == objectPlayer.rect.getPosition().y ) && ( wallArray[counter].rect.getPosition().x == objectPlayer.rect.getPosition().x ) ) {
objectPlayer.canMoveDown = false;
upCheck = true;
} else {
objectPlayer.canMoveDown = true;
}
}
counter++;
}
upCheck = false;
rightCheck = false;
downCheck = false;
leftCheck = false;
当我在游戏中添加更多墙壁时,我意识到下一个墙壁覆盖了之前的墙壁canMoveUp布尔变化。为了防止这种变化,我在代码中添加了一些检查。检查在游戏启动时添加一次,但在代码中的任何其他位置都没有更改,但在此处。
并且我的updateMovement被分成两部分以防止帧暂停:
void player::updateEndPos() {
if( (EndXPos == GetPosition().x) && (EndYPos == GetPosition().y) ) {
if(canMoveUp && sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) {
direction = 1; // direction set to Up
EndYPos = GetPosition().y - 64; // Sets end-pos so the character knows where to stop.
} else if(canMoveRight && sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) {
direction = 2; // direction set to Right
EndXPos = GetPosition().x + 64;
} else if(canMoveDown && sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) {
direction = 3; // direction set to Down
EndYPos = GetPosition().y + 64;
} else if(canMoveLeft && sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) {
direction = 4; // direction set to Left
EndXPos = GetPosition().x - 64;
}
}
}
以及:
void player::updateMovement() {
if(EndYPos != GetPosition().y) {
if(direction == 1) {
rect.move(0, -movementSpeed); // moves player at "movementSpeed" speed.
} else if(direction == 3) {
rect.move(0, movementSpeed);
} else {
std::cout << "ERROR IN Y AXIS" << std::endl;
}
} else if(EndXPos != GetPosition().x) {
if(direction == 2) {
rect.move(movementSpeed, 0);
} else if(direction == 4) {
rect.move(-movementSpeed, 0);
} else {
std::cout << "ERROR IN X AXIS" << std::endl;
}
}
}
首先我检查碰撞,然后执行updateEndPos(),然后直接执行updateMovement()。
我拆分了updateEndPos和updateMovement,因为如果我不这样做,我会得到一个框架,其中updateEndPos()部分将不会执行,并且玩家将在该框架中静止不动。它是非常明显的,但是它修复了它,现在角色的动作看起来很平滑。