我是SFML和C ++的新手,所以我试图同时学习它们。我决定写一个Snake游戏。对于我的蛇身体,我使用的是RectangleShapes矢量。我在屏幕中央画了一个浆果,我可以检测到我的蛇头与浆果发生碰撞,但我不知道如何测试蛇是否与自身发生碰撞。
我已经考虑过测试蛇的头部与整个块的矢量之间的碰撞,但是当蛇的头部与自身碰撞时,这将始终返回。
我很感激对我的代码提出任何建议和批评,谢谢!
#include <iostream>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <string>
#include <sstream>
using namespace sf;
constexpr int windowWidth{800}, windowHeight{600};
Vector2f blockLocation{0, 0};
struct Block
{
RectangleShape shape;
Vector2f blockSize{15,15};
Block(float posX, float posY)
{
shape.setPosition(posX, posY);
shape.setSize(blockSize);
shape.setFillColor(Color::Blue);
shape.setOutlineColor(Color::Green);
shape.setOutlineThickness(3);
}
};
struct Berry
{
CircleShape shape;
Berry(float posX, float posY)
{
shape.setPosition(posX, posY);
shape.setRadius(8);
shape.setFillColor(Color::Red);
shape.setOutlineColor(Color::Magenta);
shape.setOutlineThickness(3);
}
};
bool keyUp(void)
{
if(Keyboard::isKeyPressed(Keyboard::Key::Up)) return true;
return false;
}
bool keyDown(void)
{
if(Keyboard::isKeyPressed(Keyboard::Key::Down)) return true;
return false;
}
bool keyLeft(void)
{
if(Keyboard::isKeyPressed(Keyboard::Key::Left)) return true;
return false;
}
bool keyRight(void)
{
if(Keyboard::isKeyPressed(Keyboard::Key::Right)) return true;
return false;
}
int stat(std::vector<Block> *blocks, RenderWindow *window)
{
sf::Font font;
if(!font.loadFromFile("Oswald-Bold.ttf"))
{
std::cerr << "Cannot load font!" << std::endl;
return 1;
}
sf::Text text;
text.setFont(font);
std::ostringstream message;
message << "x: " << blockLocation.x << std::endl
<< "y: " << blockLocation.y << std::endl
<< "blocks: " << blocks->size() << std::endl;
text.setString(message.str());
text.setCharacterSize(24);
text.setColor(sf::Color::Magenta);
text.setOrigin(0, 0);
window->draw(text);
return 0;
}
bool collision(Block *shapeA, Berry *shapeB)
{
if( shapeA->shape.getGlobalBounds().intersects(shapeB->shape.getGlobalBounds()) )
{
std::cout << "collision with ";
std::cout << "x: " << shapeA->shape.getPosition().x << "y: " <<
shapeA->shape.getPosition().y << "and x: " << shapeB->shape.getPosition().x << "y: " << shapeB->shape.getPosition().y << std::endl;
return true;
}
else
return false;
}
int main(void)
{
Clock clock;
Time timeSinceLastUpdate = Time::Zero;
const Time TimePerFrame = seconds(3.0f/30.f);
std::vector<Block> blocks;
RenderWindow window{ {windowWidth, windowHeight} , "blocks!"};
bool up(false);
bool down(false);
bool left(false);
bool right(false);
window.setFramerateLimit(60);
Berry berry(400, 300);
blocks.emplace_back(blockLocation.x, blockLocation.y);
while(window.isOpen())
{
if(Keyboard::isKeyPressed(Keyboard::Key::Escape)) return 0;
Time elapsedTime = clock.restart();
timeSinceLastUpdate += elapsedTime;
while(timeSinceLastUpdate > TimePerFrame)
{
timeSinceLastUpdate -= TimePerFrame;
window.clear(Color::Black);
// Get the Head of the snake
auto first = blocks.back();
if(keyUp())
{
up = true;
down = false, left = false, right = false;
blocks.emplace_back(blockLocation.x, blockLocation.y);
blocks.erase(blocks.begin());
}
else if(keyDown())
{
down = true;
up = false, left = false, right = false;
blocks.emplace_back(blockLocation.x, blockLocation.y);
blocks.erase(blocks.begin());
}
else if(keyLeft())
{
left = true;
right = false, up = false, down = false;
blocks.emplace_back(blockLocation.x, blockLocation.y);
blocks.erase(blocks.begin());
}
else if(keyRight())
{
right = true;
left = false, up = false, down = false;
blocks.emplace_back(blockLocation.x, blockLocation.y);
blocks.erase(blocks.begin());
}
if(up) { blockLocation.y-=19; blocks.emplace_back(blockLocation.x, blockLocation.y); blocks.erase(blocks.begin());
}
if(down) { blockLocation.y+=19; blocks.emplace_back(blockLocation.x, blockLocation.y); blocks.erase(blocks.begin());
}
if(left) { blockLocation.x-=19; blocks.emplace_back(blockLocation.x, blockLocation.y); blocks.erase(blocks.begin());
}
if(right){ blockLocation.x+=19; blocks.emplace_back(blockLocation.x, blockLocation.y); blocks.erase(blocks.begin());
}
if (collision(&first, &berry)) blocks.emplace_back(blockLocation.x, blockLocation.y);
if(blocks.size() > 50)
{
blocks.erase(blocks.begin());
}
for(auto a : blocks)
{
window.draw(a.shape);
}
window.draw(berry.shape);
stat(&blocks, &window);
window.display();
}
}
return 0;
}