我正在用C ++制作SFML游戏。
这是一款赛车游戏,从顶部看车。 该电路由2种不同类型的路障(方形)制成:直线和角落。
问题是汽车(有一个圆形撞击盒)和道路周围的墙壁(都是段)之间的碰撞都没有被正确检测到。
段是使用(大约)从路障中获取的值初始化的常量。
然后,我们围绕块的中心旋转线段,以允许块旋转。
游戏是游戏的主要循环。 RoadBox定义了RoadBlock的点击框。
Collision.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
Collision.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
Car.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
Car.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);
}
RoadBlock.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
RoadBlock.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;
}
game.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行开始
然后我让调试器完成了他的工作。我只是开始游戏,然后按下向下按钮,直到找到测试圆和roadBox之间碰撞的函数中的断点。
(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.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...
}
答案 0 :(得分:1)
首先感谢那些花时间做我们工作的人。 我设法自己解决了这个问题。
我们的代码中存在很多错误,在RoadBox :: RoadBox中:
最后,我将解释我遇到的最后一个错误,因为它很有趣: 当测试与角块和汽车的碰撞时,gdb的调用告诉我bigArcHitBox值在这里,而不是smallArcHitBox值,是straightHitBox值! 事实上,我在smallArcHitBox中走得太远了。但是如果你看一下RoadBox.hpp / cpp文件,就会在smallArcHitBox之后存储directHitBox。所以我最终没有出现段错误,但错误的值来自错误的位置。
度过美好的一天!