c++ - C++/SFML 超级马里奥游戏与块的碰撞问题
问题描述
我正在用 C++/SFML 制作一个类似超级马里奥的游戏,在尝试为马里奥碰撞编写一些代码时,我遇到了一些问题:角色在沿水平轴移动时与垂直堆叠的块碰撞时,卡住了在块的一侧,就像它在一个看不见的块上行走一样。我试图修改碰撞功能,比如让马里奥与块水平碰撞,只有当他与块相关的位置包含在块坐标中时。
我包含了一些运动代码(keyPressed 是一个返回按下的键的函数):
void Player::movement(Time& gameTime) {
player.move(v * gameTime.asSeconds());
view.setCenter(player.getPosition().x + 16, 590);
if (keyPressed(up) && !jumping) {
jumping = true;
v.y = jumpSpeed;
}
if (v.y > 200) {
jumping = true;
}
else {
crouch = false;
}
if (keyPressed(left)) {
if (v.x > -moveSpeed) {
v.x -= 100;
}
else {
v.x = -moveSpeed;
}
}
else if (keyPressed(right)) {
noKeyPressed = false;
if (v.x < moveSpeed) {
v.x += 100;
}
else {
v.x = moveSpeed;
}
}
else {
if (v.x < -100) {
v.x += 100;
}
else if (v.x > 100) {
v.x -= 100;
}
else {
v.x = 0;
}
}
gravity();
if (big) { //Big is a variable that tells me if mario is big or small
heightValue = 33; //heightValue is a variable that stores the sprite height in pixels
}
else {
heightValue = 16;
}
}
void Player::gravity() {
if (!big) {
if (player.getPosition().y + 32 < 1100) {
if (v.y < maxSpeed) {
v.y += 100;
}
}
if (alive) { //This is useful to check if big mario has fallen
if (player.getPosition().y + 32 >= 1200) {
player.setPosition(player.getPosition().x, 1200 - 32);
jumping = false;
alive = false;
}
}
}
else {
if (player.getPosition().y + 64 < 1100) {
if (v.y < maxSpeed) {
v.y += 100;
}
}
if (alive) { //This is useful to check if small mario has fallen
if (player.getPosition().y + 64 >= 1200) {
player.setPosition(player.getPosition().x, 1200 - 64);
jumping = false;
alive = false;
}
}
}
}
还有碰撞功能,块类在块精灵周围有 4 个小块,以简化碰撞:
void Player::collisions(Block* block) {
if (this->player.getGlobalBounds().intersects(block->up.getGlobalBounds())) {
if (!big) {
if (this->player.getPosition().y + heightValue <= block->block.getPosition().y) {
this->player.setPosition(this->player.getPosition().x, block->up.getPosition().y - 32);
v.y = 0;
jumping = false;
score = 100;
}
}
else {
if (this->player.getPosition().y + heightValue <= block->block.getPosition().y) {
this->player.setPosition(this->player.getPosition().x, block->up.getPosition().y - 64);
v.y = 0;
jumping = false;
score = 100;
}
}
}
if (this->player.getGlobalBounds().intersects(block->down.getGlobalBounds())) {
this->player.setPosition(this->player.getPosition().x, block->down.getPosition().y + 1);
v.y = 0;
}
if (this->player.getGlobalBounds().intersects(block->left.getGlobalBounds()) && v.x > 0) {
this->player.setPosition(block->left.getPosition().x - 32, this->player.getPosition().y);
}
else if (this->player.getGlobalBounds().intersects(block->right.getGlobalBounds()) && v.x < 0) {
this->player.setPosition(block->right.getPosition().x + 1, this->player.getPosition().y);
}
}
我希望我准确地解释了这个问题。
解决方案
一次只做一个轴的碰撞检测,这允许沿着瓷砖平滑移动
伪代码示例:
//X axis
oldPos = position
if(leftKey):
position.x -= speed
if(rightKey):
position.x += speed
if(collision):
position = oldPos
//Y axis
oldPos = position
if(upKey):
position.y -= speed
if(downKey):
position.y += speed
if(collision):
position = oldPos
推荐阅读
- python - 如何修复错误:“无法挤压 dim[1],预期维度为 1,得到 2 [[{{node Squeeze}}]] [Op:IteratorGetNext]”
- oauth - 如何将角色从 Keycloak 映射到外部数据库?
- python - 如何访问 DataFrame 中的值,其中 df.columns 值的字符串以“.L”结尾
- python - “./file.py” VS “python 文件.py”
- php - 将天添加到空数据库时间
- flutter - 如何为子集合firestore颤振自动创建字段
- database - 按钮正在生成空查询,WHERE 子句不起作用
- java - MultipartUpload 多个文件的附加信息
- python - 与 SIFT 匹配后如何应用 Delaunay 变换
- json - 如何在 Flutter 中初始化现有模型中的新变量