gpt4 book ai didi

c++ - 圆和线段之间的错误碰撞检测

转载 作者:行者123 更新时间:2023-11-30 05:35:52 24 4
gpt4 key购买 nike

我正在用 C++ 制作 SFML 游戏。

这是一款赛车游戏,从顶部观察汽车。该电路由 2 种不同类型的路障(方形)组成:直路和拐角。

问题是汽车(有一个圆形碰撞框)和道路周围的墙壁(是路段)之间的碰撞没有被正确检测到。

路段是用(近似地)从路障中获取的值初始化的常量。

然后,我们围绕 block 的中心旋转线段以允许 block 旋转。

game 是游戏的主循环。RoadBox 定义了 RoadBlock 的命中框。

碰撞.hpp:

/*
* Definitions of all that are related to collisions:
* -hitBox
* -repulsions
*/
#ifndef DEF_COLLISION_HPP
#define DEF_COLLISION_HPP

#include <SFML/Graphics/Rect.hpp>

class RoadBox;

namespace collision
{
class RectHitBox
{
public:
RectHitBox();
RectHitBox(const sf::FloatRect &rect1, float orient1);

sf::FloatRect rect;
float orientation;

};

class LineHitBox
{
public:
LineHitBox();
LineHitBox(const sf::Vector2f &point1, const sf::Vector2f &point2);

void move(const sf::Vector2f &point2);

sf::Vector2f p1;
sf::Vector2f p2;
};

class CircleHitBox
{
public:
CircleHitBox();
CircleHitBox(const sf::Vector2f &point, float rayon1);

sf::Vector2f p;
float rayon;

};

bool collision(const RectHitBox &rectBox1, const RectHitBox &rectBox2);
bool collision(const RectHitBox &rectBox, const LineHitBox &lineBox);
bool collisionAsInfiniteLine(const CircleHitBox &cercleBox, const LineHitBox &lineBox);

//circle and segment
bool collision(const CircleHitBox &cercleBox, const LineHitBox &lineBox);
bool collision(const sf::Vector2f &point, const CircleHitBox &cercleBox);
bool collision(const CircleHitBox &cercleBox1, const CircleHitBox &cercleBox2);

bool collision(const CircleHitBox &circleBox, const RoadBox &roadBox);

}

#endif

碰撞.cpp:

#include "collision.hpp"
#include "RoadBox.hpp"
#include <cmath> //sqrt needed

#include <iostream>

namespace collision
{

RectHitBox::RectHitBox()
{
orientation = 0;
}

RectHitBox::RectHitBox(const sf::FloatRect &rect1, float orient1)
{
rect = rect1;
orientation = orient1;
}

LineHitBox::LineHitBox()
{
p1 = sf::Vector2f(0, 0);
p2 = p1;
}

LineHitBox::LineHitBox(const sf::Vector2f &point1, const sf::Vector2f &point2)
{
p1 = point1;
p2 = point2;
}

void LineHitBox::move(const sf::Vector2f &point2)
{
p1 += point2;
p2 += point2;
}


CircleHitBox::CircleHitBox()
{
p = sf::Vector2f(0,0);
rayon = 1;
}

CircleHitBox::CircleHitBox(const sf::Vector2f &point, float rayon1)
{
p = point;
rayon = rayon1;
}

bool collision(const RectHitBox &rectBox1, const RectHitBox &rectBox2)
{
sf::FloatRect rect1 = rectBox1.rect, rect2 = rectBox2.rect;

/*int centre1_x = rect1.left + rect1.width/ 2;
int centre1_y = rect1.top + rect1.height/ 2;
int centre2_x = rect2.left + rect2.width/ 2;
int centre2_y = rect2.top + rect2.height/ 2;*/

int dis2centre = (rect1.left-rect2.left)*(rect1.left-rect2.left) + (rect1.top-rect2.top)*(rect1.top-rect2.top); //Distance entre deux centre

int rayon1 = ((rect1.height * rect1.height) + (rect1.width * rect1.width))/2;
int rayon2 = ((rect2.height * rect2.height) + (rect2.width * rect2.width))/2;
return (dis2centre < (rayon1 + rayon2)*(rayon1 + rayon2));
}

bool collision(const sf::Vector2f &point, const CircleHitBox &cercleBox)
{
sf::Vector2f C(cercleBox.p);
float x = point.x, y = point.y;
float rayon = cercleBox.rayon;

float d2 = (x-C.x)*(x-C.x) + (y-C.y)*(y-C.y);
if (d2>rayon*rayon)
return false;
else
return true;
}

bool collisionAsInfiniteLine(const CircleHitBox &cercleBox, const LineHitBox &lineBox)
{
sf::Vector2f A(lineBox.p1), B(lineBox.p2), C(cercleBox.p);
sf::Vector2f u;
u.x = B.x - A.x;
u.y = B.y - A.y;

sf::Vector2f AC;
AC.x = C.x - A.x;
AC.y = C.y - A.y;

float numerateur = u.x*AC.y - u.y*AC.x;
if(numerateur < 0)
{
numerateur = -numerateur;
}

float denominateur = std::sqrt(u.x*u.x + u.y*u.y);
float CI = numerateur / denominateur;
if(CI < cercleBox.rayon)
{
return true;
}
return false;
}

bool collision(const CircleHitBox &cercleBox, const LineHitBox &lineBox)
{
sf::Vector2f A(lineBox.p1), B(lineBox.p2), C(cercleBox.p);

if(!collisionAsInfiniteLine(cercleBox, lineBox))
{
return false;
}

sf::Vector2f AB,AC,BC;
AB.x = B.x - A.x;
AB.y = B.y - A.y;
AC.x = C.x - A.x;
AC.y = C.y - A.y;
BC.x = C.x - B.x;
BC.y = C.y - B.y;
float pscal1 = AB.x*AC.x + AB.y*AC.y; // produit scalaire
float pscal2 = (-AB.x)*BC.x + (-AB.y)*BC.y; // produit scalaire
if (pscal1>=0 && pscal2>=0)
return true; // I entre A et B, ok.
// dernière possibilité, A ou B dans le cercle
if (collision(A,cercleBox))
return true;
if (collision(B,cercleBox))
return true;
return false;
}

bool collision(const CircleHitBox &cercleBox1, const CircleHitBox &cercleBox2)
{
sf::Vector2f C1(cercleBox1.p), C2(cercleBox2.p);
float d2 = (C1.x-C2.x)*(C1.x-C2.x) + (C1.y-C2.y)*(C1.y-C2.y);
if (d2 > (cercleBox1.rayon + cercleBox2.rayon)*(cercleBox1.rayon + cercleBox2.rayon))
return false;
else
return true;
}

bool collision(const CircleHitBox &circleBox, const RoadBox &roadBox)
{
bool collided = false;
const std::vector<collision::LineHitBox> &hitBox = roadBox.getLineArray();

for(unsigned int i = 0; i < hitBox.size() && !collided; i++)
{
collided = collision(circleBox, hitBox[i]);
/*if(collided)
{
//std::cout<< "collision\n";
}*/
}

return collided;
}

} //namespace collision

汽车.hpp:

// A Car shall be drawable and transformable. It can collide with other objects.

#ifndef DEF_CAR_HPP
#define DEF_CAR_HPP

#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/Sprite.hpp>

#include "Timer.hpp"
#include "collision.hpp"

namespace sf
{
class Texture;
}

class Car : public sf::Drawable, public sf::Transformable
{
public:
Car(sf::Texture &tex, float maxSpeed = 100);


void accelerate(float accel);

void rotate(float rot);

void apply_physics();

collision::CircleHitBox getHitBox() const;

protected:
virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const;

private:
float norm(const sf::Vector2f &v) const;

float m_acceleration;
float m_rotation;

sf::Sprite m_sprite;

Timer m_physicTimer; //timer that permit the physics to apply at every frame

sf::Vector2f m_speedVector;
float m_maxSpeed;


float m_hitBoxRadius;
};

#endif

汽车.cpp:

#include "Car.hpp"

#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>

#include <cmath>
#include <iostream>

Car::Car(sf::Texture &tex, float maxSpeed)
{
m_acceleration = 0;
m_rotation = 0;

m_sprite.setTexture(tex);

sf::Vector2u texSize(tex.getSize());
m_sprite.setOrigin(float(texSize.x)/2.f, float(texSize.y)/2.f);
m_speedVector = sf::Vector2f(0, 0);

//to take the included circle, take the min btw width and height
m_hitBoxRadius = 93/2;

m_maxSpeed = maxSpeed;

m_physicTimer.setDuration(sf::seconds(1./60.)); //60 fps
m_physicTimer.restart();

}

void Car::accelerate(float accel)
{
m_acceleration = accel;
}

void Car::rotate(float rot)
{
m_rotation = rot;
}

void Car::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
states.transform *= getTransform();
//states.transform.rotate(-90); //the car is not well orientated in the loaded image
target.draw(m_sprite, states);
}

void Car::apply_physics()
{
if(m_physicTimer.ticked())
{
float currentSpeed = norm(m_speedVector);

sf::Transformable::rotate(m_rotation/**(currentSpeed / m_maxSpeed)*/);
float rotation = getRotation();

float accelFactor = m_physicTimer.getFullWaitedDuration().asSeconds();

//std::cout<< accelFactor * 60<< "\n";

//calculate the new speed with the acceleration
m_speedVector.x += std::cos(rotation*M_PI/180)*m_acceleration*accelFactor;
m_speedVector.y += std::sin(rotation*M_PI/180)*m_acceleration*accelFactor;

//calculate the new position with the speed
move(m_speedVector);


m_acceleration = 6;
m_physicTimer.restart();

//std::cout<< getPosition().x<< " ; "<< getPosition().y<< '\n';
//std::cout<< 60*accelFactor<< '\n';
}
}

float Car::norm(const sf::Vector2f &v) const
{
return std::sqrt((v.y*v.y) + (v.x*v.x));
}

collision::CircleHitBox Car::getHitBox() const
{
return collision::CircleHitBox(getPosition(), m_hitBoxRadius);
}

路障.hpp :

#ifndef DEF_ROADBLOCK_HPP   
#define DEF_ROADBLOCK_HPP

#include <SFML/Graphics/Drawable.hpp>
#include <SFML/Graphics/Transformable.hpp>
#include <SFML/Graphics/RenderStates.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Sprite.hpp>

#include <string>
#include <vector>

#include "collision.hpp"
#include "RoadBox.hpp"

namespace sf
{
class RenderTarget;
}

static const std::string STRAIGHT_TEXTURE_NAME("gameData/images/straight.png");
static const std::string CORNER_TEXTURE_NAME("gameData/images/corner1.png");
static const std::string GRASS_TEXTURE_NAME("gameData/images/grass2.png");

class RoadBlock : public sf::Drawable, public sf::Transformable
{
public:
enum roadType
{
straight = 0,
corner = 1
};

enum rotation //clockwise
{
standard = 0,
right= 1,
left = 2,
down = 3
};

RoadBlock();
RoadBlock(const sf::Texture &texture, roadType t, rotation r, const sf::Vector2f &pos);
RoadBlock(roadType t, rotation r, const sf::Vector2f &pos = sf::Vector2f(0.0, 0.0));

rotation getRotation() const;
roadType getRType() const;

void setRotation(rotation r);
void setType(roadType t);

RoadBox getHitBox() const;

//standard shared textures
static const sf::Texture straightTexture;
static const sf::Texture cornerTexture;
static const sf::Texture grassTexture;

//standard shared textures size
static const sf::Vector2i texSize;

protected:
virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const;

private:
sf::Sprite m_sprite;
roadType m_type;
};

//turn 90° clockwise
RoadBlock::rotation operator++(RoadBlock::rotation &r, int);

//turn -90° clockwise
RoadBlock::rotation operator--(RoadBlock::rotation &r, int);

//change of roadType to the next one
RoadBlock::roadType operator++(RoadBlock::roadType &r, int);

#endif

路障.cpp:

#include "RoadBlock.hpp"

#include <SFML/Graphics/RenderTarget.hpp>
#include "FileLoader.hpp"
#include "collision.hpp"

#include <iostream>

const sf::Texture RoadBlock::straightTexture = createFromFile<sf::Texture>(STRAIGHT_TEXTURE_NAME);
const sf::Texture RoadBlock::cornerTexture = createFromFile<sf::Texture>(CORNER_TEXTURE_NAME);
const sf::Texture RoadBlock::grassTexture = createFromFile<sf::Texture>(GRASS_TEXTURE_NAME);

const sf::Vector2i RoadBlock::texSize = sf::Vector2i(256, 256);

RoadBlock::RoadBlock()
{
m_sprite.setOrigin(float(texSize.x)/2.f, float(texSize.y)/2.f);
}

RoadBlock::RoadBlock(const sf::Texture &texture, roadType t, rotation r, const sf::Vector2f &pos)
{
setPosition(pos);

m_sprite.setTexture(texture);
setType(t);

m_sprite.setOrigin(float(texSize.x)/2.f, float(texSize.y)/2.f);

setRotation(r);

m_sprite.setOrigin(0, 0);
}

RoadBlock::RoadBlock(roadType t, rotation r, const sf::Vector2f &pos)
{
m_sprite.setOrigin(float(texSize.x)/2.f, float(texSize.y)/2.f);

setPosition(pos);

//std::cout<< pos.x<< " ; "<< pos.y<< '\n';

setRotation(r);
setType(t);
}

void RoadBlock::setRotation(rotation r)
{
switch(r)
{
case right:
m_sprite.setRotation(90);
break;
case left:
m_sprite.setRotation(-90);
break;
case down:
m_sprite.setRotation(180);
break;
case standard:
m_sprite.setRotation(0);
break;
default:
break;
}
//m_sprite.rotate(10);
}

void RoadBlock::setType(roadType t)
{
m_type = t;

switch(t)
{
case straight:
m_sprite.setTexture(RoadBlock::straightTexture);
break;
case corner:
m_sprite.setTexture(RoadBlock::cornerTexture);
break;
default:
break;
}
}

RoadBlock::rotation RoadBlock::getRotation() const
{
float r = m_sprite.getRotation();
std::cout<< r<< '\n';
switch(int(r))
{
case 90:
return right;
break;
case 270:
return left;
break;
case 180:
return down;
break;
default:
break;
}
return standard; //shall never be executed
}

RoadBlock::roadType RoadBlock::getRType() const
{
return m_type;
}

RoadBox RoadBlock::getHitBox() const
{
return RoadBox(*(this));
}

void RoadBlock::draw(sf::RenderTarget &target, sf::RenderStates states) const
{
states.transform *= getTransform();
states.transform.translate(float(texSize.x)/2.f, float(texSize.y)/2.f);

target.draw(m_sprite, states);
}

RoadBlock::rotation operator++(RoadBlock::rotation &r, int nn)
{
RoadBlock::rotation ans(r); //answer
switch(r)
{
case RoadBlock::standard:
r = RoadBlock::right;
break;
case RoadBlock::right:
r = RoadBlock::down;
break;
case RoadBlock::down:
r = RoadBlock::left;
break;
case RoadBlock::left:
r = RoadBlock::standard;
break;
default:
break;
}
return ans;
}

RoadBlock::rotation operator--(RoadBlock::rotation &r, int nn)
{
RoadBlock::rotation ans(r); //answer
switch(r)
{
case RoadBlock::standard:
r = RoadBlock::left;
break;
case RoadBlock::right:
r = RoadBlock::standard;
break;
case RoadBlock::down:
r = RoadBlock::right;
break;
case RoadBlock::left:
r = RoadBlock::down;
break;
default:
break;
}
return ans;
}

RoadBlock::roadType operator++(RoadBlock::roadType &r, int)
{
RoadBlock::roadType ans(r);
switch(r)
{
case RoadBlock::straight:
r = RoadBlock::corner;
break;
case RoadBlock::corner:
r = RoadBlock::straight;
break;
default:
break;
}
return ans;
}

RoadBox.hpp:

// A RoadBox is the RoadBlock's hit box.
// It's meant to easy collisions with the cars.

#ifndef DEF_ROADBOX_HPP
#define DEF_ROADBOX_HPP

#include <SFML/Graphics/Transformable.hpp>
#include "collision.hpp"
//#include "RoadBlock.hpp"

#include <vector>

class RoadBlock;

class RoadBox: public sf::Transformable //be careful with SFML transformations, none shall be used from a outside
{
public:
RoadBox(const RoadBlock &roadBlock);

const std::vector<collision::LineHitBox> & getLineArray() const;

/*
These variables are initialized on program start.
They represent the different standard hitBoxes of RoadBlocks.
*/
static const std::vector<collision::LineHitBox> bigArcHitBox;
static const std::vector<collision::LineHitBox> smallArcHitBox;
static const std::vector<collision::LineHitBox> straightHitBox;

private:
std::vector<collision::LineHitBox> m_hitBox;

};

#endif //DEF_ROADBOX_HPP

RoadBox.cpp:

#include "RoadBox.hpp"
#include "RoadBlock.hpp"


/*
All functions defined as static in this file are initializers for RoadBox's static variables (hit boxes).
Therefore there is no mean to give access to these in other files.
*/

namespace pv //private
{
static std::vector<collision::LineHitBox> getBigArcHitBox();
static std::vector<collision::LineHitBox> getSmallArcHitBox();
static std::vector<collision::LineHitBox> getStraightHitBox();
}
namespace pv //private
{
static std::vector<collision::LineHitBox> getBigArcHitBox()
{
using namespace collision;

sf::Vector2f posOffsetToCenter( - RoadBlock::texSize/2);

std::vector<LineHitBox> hitBox(3);
hitBox[0] = LineHitBox(sf::Vector2f(31, 256), sf::Vector2f(31, 134));
hitBox[1] = LineHitBox(sf::Vector2f(31, 134), sf::Vector2f(121, 32));
hitBox[2] = LineHitBox(sf::Vector2f(121, 32), sf::Vector2f(256, 31));

//center the hitBox on (0, 0)
for(unsigned int i = 0; i < hitBox.size(); i++)
{
hitBox[i].move(posOffsetToCenter);
}

return hitBox;
}

static std::vector<collision::LineHitBox> getSmallArcHitBox()
{
using namespace collision;

sf::Vector2f posOffsetToCenter( - RoadBlock::texSize/2);

std::vector<LineHitBox> hitBox(2);
hitBox[0] = LineHitBox(sf::Vector2f(225, 255), sf::Vector2f(226, 224));
hitBox[1] = LineHitBox(sf::Vector2f(226, 224), sf::Vector2f(256, 225));

//center the hitBox on (0, 0)
for(unsigned int i = 0; i < hitBox.size(); i++)
{
hitBox[i].move(posOffsetToCenter);
}

return hitBox;
}

static std::vector<collision::LineHitBox> getStraightHitBox()
{
using namespace collision;

sf::Vector2f posOffsetToCenter( - RoadBlock::texSize/2);

std::vector<LineHitBox> hitBox(2);
hitBox[0] = LineHitBox(sf::Vector2f(31, 256), sf::Vector2f(31, 0)/*sf::Vector2f(0, 0), sf::Vector2f(0, 256)*/);
hitBox[1] = LineHitBox(sf::Vector2f(225, 256), sf::Vector2f(225, 0)/*sf::Vector2f(256, 0), sf::Vector2f(256, 256)*/);

//center the hitBox on (0, 0)
for(unsigned int i = 0; i < hitBox.size(); i++)
{
hitBox[i].move(posOffsetToCenter);
}

return hitBox;
}

}

const std::vector<collision::LineHitBox> RoadBox::bigArcHitBox = pv::getBigArcHitBox();
const std::vector<collision::LineHitBox> RoadBox::smallArcHitBox = pv::getSmallArcHitBox();
const std::vector<collision::LineHitBox> RoadBox::straightHitBox = pv::getStraightHitBox();

RoadBox::RoadBox(const RoadBlock &roadBlock)
{
using namespace collision;

//to get the right hit box, we need to transform the default hit box, because no rotation is in it
sf::Transform transf;
transf.rotate(roadBlock.sf::Transformable::getRotation());

RoadBlock::roadType t = roadBlock.getRType();
switch(t)
{
case RoadBlock::straight:
m_hitBox.resize(straightHitBox.size());
for(unsigned int i = 0; i < m_hitBox.size(); i++)
{
m_hitBox[i] = LineHitBox
(
transf.transformPoint(straightHitBox[i].p1)
,transf.transformPoint(straightHitBox[i].p2)
);
}
break;
case RoadBlock::corner:
m_hitBox.resize(bigArcHitBox.size() + smallArcHitBox.size());
for(unsigned int i = 0; i < bigArcHitBox.size(); i++)
{
m_hitBox[i] = LineHitBox
(
transf.transformPoint(bigArcHitBox[i].p1)
,transf.transformPoint(bigArcHitBox[i].p2)
);
}
for(unsigned int i = 0; i < smallArcHitBox.size(); i++)
{
m_hitBox[i] = LineHitBox
(
transf.transformPoint(smallArcHitBox[i].p1)
,transf.transformPoint(smallArcHitBox[i].p2)
);
}
break;
default: //shall never be used
break;

}

//place the calculated hit boxes at the right position
sf::Vector2f pos(roadBlock.getPosition());
for(unsigned int i = 0; i < m_hitBox.size(); i++)
{
m_hitBox[i].p1 += pos;
m_hitBox[i].p2 += pos;
}
}

const std::vector<collision::LineHitBox> & RoadBox::getLineArray() const
{
return m_hitBox;
}

游戏.cpp:

#include "game.hpp"

#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/Window/Event.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/View.hpp>

#include <iostream>

#include "Map.hpp"
#include "Timer.hpp"
#include "OpenFileError.hpp"

namespace game
{
Action::Action(float orien, int accel):
orientation(orien), acceleration(accel)
{
}

void getEvents(sf::RenderWindow &window, Action &action)
{
action.acceleration = 0;
action.orientation = 0;
sf::Event event;
while(window.pollEvent(event))
{
switch(event.type)
{
case sf::Event::Closed:
exit(EXIT_SUCCESS);
break;
case sf::Event::KeyPressed:
switch(event.key.code)
{
case sf::Keyboard::Escape:
exit(EXIT_SUCCESS);
break;
default:
break;
}
break;
case sf::Event::KeyReleased:
break;
default:
break;
}
}

if(sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
action.acceleration = -5;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
action.acceleration = 5;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
action.orientation = 5;
}
if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
action.orientation = -5;
}

}

void game(sf::RenderWindow &window)
{
//view that will follow the car
sf::View carView(sf::FloatRect(0, 0, 800, 600));
//carView.setSize(640, 480);
window.setView(carView);

//image loading
sf::Texture texPlayerCar;
if(!texPlayerCar.loadFromFile(CAR_FILE))
{
throw OpenFileError();
}

Map map(std::string("saveMap.pwet"));

std::cout<< map.begin()->getPosition().x<< " ; "<< map.begin()->getPosition().y<< '\n';

Car playerCar(texPlayerCar, 50); //50 = max speed
playerCar.setPosition(sf::Vector2f(RoadBlock::texSize/2));

//other variables
Action action;

Timer loopTimer(sf::seconds(1./60.)); //60 fps
//std::cout<< loopTimer.getDuration().asSeconds()<< '\n';
loopTimer.restart();

int j = 0; //count the number of collisions (max 1 each frame)

//main loop
while(true)
{
getEvents(window, action);

//game physic/////////////////////////////
playerCar.accelerate(action.acceleration);
playerCar.rotate(action.orientation);

playerCar.apply_physics();

//collisions tests
bool collided = false;
int i = 0;
for(Map::iterator it = map.begin(); it != map.end() && !collided; it++)
{
collided = collision::collision(playerCar.getHitBox(), it->getHitBox());
}
if(collided)
{
std::cout<< ++j<<"\n";
}

// \game physics /////////////////////////

//game display////////////////////////////
carView.setCenter(playerCar.getPosition());
window.setView(carView);

window.clear(sf::Color::Black);

window.draw(map);
window.draw(playerCar);

window.display();

// \game display//////////////////////////

//time handling///////////////////////////

loopTimer.autoSleep();

// \time handling/////////////////////////
}

}

void loadCars(std::vector<Car> &carsTab, std::vector<sf::Texture> &texTab)
{
try
{
sf::Texture texCar;
if(!texCar.loadFromFile(CAR_FILE))
{
OpenFileError error;
throw error;
}

texTab.push_back(texCar);
carsTab.push_back(Car(texTab[0], CAR_SPEED));
}
catch(std::exception &except)
{
std::cerr<< except.what()<< "\n";
}
}
}

我正在给你一个问题的例子,正如 Anon Mail 所建议的那样。

我取消了 collision.cpp 中的以下行的注释:

bool collision(const CircleHitBox &circleBox, const RoadBox &roadBox)
{
bool collided = false;
const std::vector<collision::LineHitBox> &hitBox = roadBox.getLineArray();

for(unsigned int i = 0; i < hitBox.size() && !collided; i++)
{
collided = collision(circleBox, hitBox[i]);
if(collided) //These ones, from here ...
{
std::cout<< "collision\n";
} //... to here
}

return collided;
}

从第 161 行开始

然后我让调试器完成他的工作。我只是开始游戏,然后按下向下按钮,直到找到测试 circle 和 roadBoxes 之间碰撞的函数中的断点。

(gdb) break collision.cpp:171
Breakpoint 1 at 0x404577: file collision.cpp, line 171.
(gdb) run
Starting program: /home/victor/projetCarRacing/carRacing
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7fffeeebe700 (LWP 2878)]
0 ; 0

Breakpoint 1, collision::collision (circleBox=..., roadBox=...) at collision.cpp:171
171 std::cout<< "collision\n";
(gdb) print circleBox
$1 = (const collision::CircleHitBox &) @0x7fffffffd740: {p = {x = 75,2980652, y = 128}, rayon = 46}
(gdb) print hitBox[i]
$2 = {p1 = {x = 31, y = 256}, p2 = {x = 31, y = 0}}

我想您需要一张图片才能完全理解正在发生的事情。记住一件事:汽车碰撞框的半径是汽车的宽度:46 像素。汽车后面的道路上的线不是墙。它不应有命中框。

game screenshot

我需要补充一点,game.hpp/cpp 的大部分内容与这里无关。只有测试碰撞的部分才可能有用:

            //collisions tests
bool collided = false;
int i = 0;
for(Map::iterator it = map.begin(); it != map.end() && !collided; it++)
{
collided = collision::collision(playerCar.getHitBox(), it->getHitBox());
}
if(collided)
{
//some stuff...
}

最佳答案

首先感谢那些花时间参与我们工作的人。我设法自己解决了这个问题。

实际上我们的代码中有很多错误,在 RoadBox::RoadBox 中:

  1. 我忘记了中断指令(愚蠢的错误,是的)
  2. 我没有修改m_hitBox中好的值
  3. 当使用变换来旋转 hitBox 时,我使用了错误的函数 sf::Transform::rotate。本来应该是有一个中心作为参数的那个,但是我拿了另一个。它起作用的唯一原因是标准碰撞盒以 (0, 0) 为中心。

最后我会解释我遇到的最后一个错误,因为它很有趣:当测试与角 block 和汽车的碰撞时,gdb 的调用告诉我这里有 bigArcHitBox 值,但不是 smallArcHitBox 值,而是 straightHitBox 值!事实上,我只是在 smallArcHitBox 中走得太远了。但是如果你查看 RoadBox.hpp/cpp 文件,straightHitBox 就存储在 smallArcHitBox 之后。所以我以没有段错误结束,但错误的值来自错误的位置。

祝你有美好的一天!

关于c++ - 圆和线段之间的错误碰撞检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33741174/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com