提问人:Chorgard 提问时间:11/10/2023 最后编辑:genpfaultChorgard 更新时间:11/10/2023 访问量:63
碰撞无法正常工作(使玩家卡住)[已关闭]
Collisions not working properly (Making the player get stuck) [closed]
问:
我无法恰到好处地进行碰撞。玩家只是被困在方块中,即使在它们上面。(顺便说一句,有重力)
我的碰撞依赖于玩家的“过去”位置
编辑:我在代码中犯了一个错误,所以我更改了它。
这是我的代码:
#include <SFML/Graphics.hpp>
#include <iostream>
#include <math.h>
constexpr auto PI = 3.14159265;
bool rr(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) {
return (x1 + w1 > x2 && y1 + h1 > y2 && x1 < x2 + w2 && y1 < y2 + h2);
};
//#include <string>
int main()
{
//Player stuffs
sf::Vector2f playerPos(0, 0);
sf::Vector2f playerPastPos(0, 0);
sf::Vector2f playerVel(0, 0);
sf::RectangleShape playerRender;
playerRender.setSize(sf::Vector2f(20, 20));
playerRender.setFillColor(sf::Color(0, 255, 0));
sf::RenderWindow window(sf::VideoMode(600, 400), "Platformer (SFML)");
window.setFramerateLimit(60);
sf::Vector2u windowSize = window.getSize();
int block_map[] = {
0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,1,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,2,
1,0,0,0,0,0,1,1,
1,1,1,1,1,1,1,1,
};
int map_width = 8;
int map_height = 8;
sf::RectangleShape rect[sizeof(block_map) / sizeof(*block_map)];
for (int i = 0; i < sizeof(block_map) / sizeof(*block_map); i++) {
rect[i].setPosition(sf::Vector2f((i%(map_width))*20, std::floor(i/map_height)*20));
rect[i].setFillColor(sf::Color(255, 255, 255, 0));
switch(block_map[i]){
case 1:
rect[i].setFillColor(sf::Color(255, 255, 255));
break;
case 2:
rect[i].setFillColor(sf::Color(255, 0, 255));
break;
}
//std::cout <<"/"+std::to_string((a[i].at(j)));
}
int i = 0, j = 50, l = 0;
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
windowSize = window.getSize();
playerPastPos = playerPos;
while (l < sizeof(rect) / sizeof(rect[0])) {
rect[l].setSize(sf::Vector2f(20, 20));
//rect[l].setPosition(i, j);
window.draw(rect[l]);
//i += 25;
l++;
}
for (int i = 0; i < sizeof(block_map) / sizeof(*block_map); i++) {
bool canColl = false;
sf::Vector2f pos = sf::Vector2f((i % (map_width)) * 20, std::floor(i / map_height) * 20);
if (rr(playerPos.x, playerPos.y, 20, 20, pos.x, pos.y, 20, 20)) {
switch (block_map[i]) {
case 1:
canColl = true;
break;
case 2:
canColl = true;
break;
}
//0.0174532925
if (canColl) {
if (playerPastPos.y < pos.y - 20) {
playerVel.y = 0;
playerPos.y = pos.y - 20;
}
if (playerPastPos.x > pos.x + 20) {
playerVel.x = 0;
playerPos.x = pos.x + 20;
}
if (playerPastPos.y > pos.y + 20) {
playerVel.y = 0;
playerPos.y = pos.y + 20;
}
if (playerPastPos.x < pos.x - 20) {
playerVel.x = 0;
playerPos.x = pos.x - 20;
}
}
}
}
//Player in game stuffs
playerVel.x *= 0.95;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) && playerVel.x < 3) {
playerVel.x += 0.5;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) && playerVel.x > -3) {
playerVel.x -= 0.5;
}
playerVel.y += 0.3;
playerPos += playerVel;
playerRender.setPosition(playerPos);
window.draw(playerRender);
// Reset variables.
l = 0;
i = 0;
// Copy the buffer to the window.
window.display();
}
}
答:
0赞
Olivier Samson
11/10/2023
#1
请注意,默认情况下,矩形形状的原点位于其左上角。这意味着在检查冲突时,您拥有的 and 值位于块的左上角。如果您的播放器继承了 .考虑到这一点,你的计算都是错误的。你应该有:pos.x
pos.y
sf::Transformable
bool rr(float x1, float y1, float w1, float h1, float x2, float y2, float w2, float h2) {
// Is player pos x inside block pos x?
// Yes if top right x of player is greater than top left x of block
// and if top left x of player is lesser than top right x of block at the same time
bool xIn = (x1 + w1 > x2) && (x1 < x2 + w2);
// Is player pos y inside block pos y?
// Yes if top left y of player is greater than bottom left y of block
// and if bottom left y of player is lesser than top left y of block at the same time
bool yIn = (y1 > y2 - h2) && (y1 - h1 < y2);
return xIn && yIn;
};
现在你知道你有碰撞,你必须纠正玩家的位置。现在,您的实现很难遵循,可以改进。我会尝试改变它:
// Correct x pos
// Is player coming from left or right?
if ((playerVel.x > 0) && (playerPastPos.x + 20 < pos.x)) {
// Coming from left
playerVel.x = 0;
playerPos.x = pos.x - 20;
}
else if ((playerVel.x < 0) && (playerPastPos.x > pos.x + 20)) {
// Coming from right
playerVel.x = 0;
playerPos.x = pos.x + 20;
}
// Correct y pos
// Is player coming from top or bottom?
if ((playerVel.y > 0) && (playerPastPos.y < pos.y - 20)) {
// Coming from bottom
playerVel.y = 0;
playerPos.y = pos.y - 20;
}
else if ((playerVel.y < 0) && (playerPastPos.y - 20 > pos.y)) {
// Coming from top
playerVel.y = 0;
playerPos.y = pos.y + 20;
}
这显然不是最好的做事方式,但我试图遵循你实现的基本思想。
评论