Bonjour,
je viens de reprendre la SFMLet pour me remettre en condition j'ai coder un snake vraiment basique, mais j'aimerais savoir si il est proprement coder, et si il exploite au mieux les concepts de la POO.
Merci.
#include <iostream>
#include <SFML/Graphics.hpp>
#include "Snake.h"
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 640
int main(int, char const**)
{
sf::RenderWindow window(sf::VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "SFML window");
window.setFramerateLimit(60);
window.setKeyRepeatEnabled(false);
Snake snake(window, 32, 32);
while (window.isOpen())
{
snake.Move();
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
snake.Update(event);
}
window.clear(sf::Color(0,162,255));
snake.Draw();
window.display();
}
return EXIT_SUCCESS;
}
#ifndef SNAKE_H_INCLUDED
#define SNAKE_H_INCLUDED
#include <iostream>
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include <ctime>
class Snake
{
public:
Snake(sf::RenderWindow &window, int sSize, int sSpeed);
void Move();
void Update(sf::Event &event);
void Draw();
private:
sf::RenderWindow &mWindow;
sf::Clock mClock;
sf::CircleShape mFood;
int mTimeToUpdate;
int mSize;
int mSpeed;
bool mLeft, mRight, mUp, mDown;
float mCurrentTime;
std::vector<sf::RectangleShape> mSnakes;
void CheckCollision();
void AddCase();
void FoodGenerator();
};
#endif // SNAKE_H_INCLUDED
#include "Snake.h"
using namespace std;
using namespace sf;
Snake::Snake(RenderWindow &window, int sSize, int sSpeed) : mWindow(window), mSize(sSize), mSpeed(sSpeed)
{
mTimeToUpdate = 250; // 1/4 second
mCurrentTime = 0.0f;
mLeft = mUp = mDown = false;
mRight = true;
srand(std::time(0));
AddCase();
AddCase();
mFood.setRadius(mSize / 2); // Food circle
mFood.setFillColor(sf::Color::Green);
FoodGenerator();
}
void Snake::FoodGenerator() // Generates the new food position
{
int randomX = rand() % (mWindow.getSize().x / mSize);
int randomY = rand() % (mWindow.getSize().y / mSize);
for(unsigned int i = 0; i < mSnakes.size(); i++)
{
if((mSnakes[0].getPosition().x != randomX * mSize) && (mSnakes[0].getPosition().y != randomY))
{
mFood.setPosition(randomX * mSize, randomY * mSize);
}
}
}
void Snake::AddCase() // Add 1 more case
{
sf::RectangleShape rect;
rect.setSize(sf::Vector2f(32, 32));
rect.setOutlineColor(sf::Color::Black);
rect.setOutlineThickness(1.0f);
if (mSnakes.empty())
{
rect.setFillColor(sf::Color::Red);
rect.setPosition(320, 256);
}
else
{
rect.setFillColor(sf::Color::Yellow);
rect.setPosition(mSnakes[mSnakes.size() - 1].getPosition().x - rect.getSize().x, mSnakes[mSnakes.size() - 1].getPosition().y);
}
mSnakes.push_back(rect);
}
void Snake::Move() // Move the snake every 250 ms and check collision
{
if (mCurrentTime < mTimeToUpdate)
{
mCurrentTime += mClock.restart().asMilliseconds();
}
else
{
mCurrentTime = 0.0f;
if (mSnakes.size() > 1)
{
for (unsigned int i = mSnakes.size() - 1; i > 0; i--)
{
mSnakes[i].setPosition(sf::Vector2f(mSnakes[i-1].getPosition().x, mSnakes[i-1].getPosition().y));
}
}
if (mLeft)
{
mSnakes[0].move(-mSpeed, 0);
}
if (mRight)
{
mSnakes[0].move(mSpeed, 0);
}
if (mUp)
{
mSnakes[0].move(0, -mSpeed);
}
if (mDown)
{
mSnakes[0].move(0, mSpeed);
}
CheckCollision();
}
}
void Snake::CheckCollision()
{
for (unsigned int i = 2; i < mSnakes.size(); i++) // Snake's boxes
{
if (mSnakes[0].getPosition().x == mSnakes[i].getPosition().x
&& mSnakes[0].getPosition().y == mSnakes[i].getPosition().y)
{
mWindow.close();
}
}
if (mSnakes[0].getPosition().x < 0 || mSnakes[0].getPosition().x + mSnakes[0].getSize().x > mWindow.getSize().x // Window collision
|| mSnakes[0].getPosition().y < 0 || mSnakes[0].getPosition().y + mSnakes[0].getSize().y > mWindow.getSize().y)
{
mWindow.close();
}
if (mSnakes[0].getPosition().x == mFood.getPosition().x // Food collision
&& mSnakes[0].getPosition().y == mFood.getPosition().y)
{
AddCase();
FoodGenerator();
}
}
void Snake::Update(Event &event) // Check key input
{
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Left)
{
if(mSnakes[0].getPosition().x - mSnakes[0].getSize().x != mSnakes[1].getPosition().x)
{
if(!mLeft && !mRight)
{
mLeft = true;
mRight = false;
mUp = false;
mDown = false;
}
}
}
if (event.key.code == sf::Keyboard::Right)
{
if(mSnakes[0].getPosition().x + mSnakes[0].getSize().x != mSnakes[1].getPosition().x)
{
if(!mRight && !mLeft)
{
mLeft = false;
mRight = true;
mUp = false;
mDown = false;
}
}
}
if (event.key.code == sf::Keyboard::Up)
{
if(mSnakes[0].getPosition().y - mSnakes[0].getSize().x != mSnakes[1].getPosition().y)
{
if(!mUp && !mDown)
{
mLeft = false;
mRight = false;
mUp = true;
mDown = false;
}
}
}
if (event.key.code == sf::Keyboard::Down)
{
if(mSnakes[0].getPosition().y + mSnakes[0].getSize().x != mSnakes[1].getPosition().y)
{
if(!mUp && !mDown)
{
mLeft = false;
mRight = false;
mUp = false;
mDown = true;
}
}
}
}
}
void Snake::Draw()
{
mWindow.draw(mFood);
for (unsigned int i = 0; i < mSnakes.size(); i++)
mWindow.draw(mSnakes[i]);
}
Tout est bon. Pour moi ton code est propre.
Après si tu veut optimiser tu pourrait faire une classe pour ton snake, une pour la nourriture et une pour le jeu. Dans le main tu aurait un truc du style :
int main()
{
Game game;
game.run(); //Creation de le fenêtre dans la fonction et affichage du snake et de la nourriture
//Les classes snake et nourriture héritent de sf::Drawable
}
Mais sa c'est plus pour les "gros" jeu pour snake ce que tu as fait suffit largement.