Znalazłem grę w wężową grę SFML w języku C++, a ja się z tym zmierzyłem i zmieniłem kilka rzeczy, ale jedną z rzeczy, których nie potrafię wymyślić, jest to, jak sprawić, by było bardziej płynne/responsywne za pomocą klawiszy strzałek. Teraz jest za pomocą enum Direction {Up, Down, Left, Right};
zCzy gra SFML Snake lepiej reaguje na naciskanie klawiszy?
while (window.isOpen())
{
sf::Vector2f lastPosition(snakeBody[0].getPosition().x, snakeBody[0].getPosition().y);
// Event
sf::Event event;
while (window.pollEvent(event))
{
//.....
if (event.type == sf::Event::KeyPressed && event.key.code
== sf::Keyboard::Return)
{
//clock.restart;
if (!currentlyPlaying)
currentlyPlaying = true;
move = Down;
New_Game(snakeBody, window_width, window_height, engine, apple, score, scoreText, lowBounds);
mode = 1;
moveClock.restart();
//start game
}
if(inputClock.getElapsedTime().asSeconds() >= 0.07)
{
if(event.key.code == sf::Keyboard::Up && move != Down)
move = Up;
inputClock.restart();
if(event.key.code == sf::Keyboard::Down && move != Up)
move = Down;
inputClock.restart();
if(event.key.code == sf::Keyboard::Left && move != Right)
move = Left;
inputClock.restart();
if(event.key.code == sf::Keyboard::Right && move != Left)
move = Right;
inputClock.restart();
}
}
To frustrujące odgrywać obecnie, bo nie może się poruszać tak dokładnie, jak chciałbym. Czy istnieje sposób na szybsze reagowanie na polecenia lub czy już reaguje na naciśnięcia klawiszy tak szybko, jak to możliwe na moim sprzęcie?
Jestem kompletnym początkującym dla OOP i SFML, więc mam trochę problemów ze zrozumieniem zegara, a także z grą w węża w innych językach, aby przetłumaczyć to na. W razie potrzeby mogę opublikować cały kod.
Tak wiem, że to nie jest ładna, ale tu jest cały kod:
#include <iostream>
#include <SFML/Graphics.hpp>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
// Global directions
enum Direction {Up, Down, Left, Right};
// Reads high scores
void High_Scores(std::vector<int> &top10scores)
{
top10scores.clear();
std::string line;
std::ifstream highscores("highscores.txt");
while (std::getline(highscores, line))
top10scores.push_back(stoi(line));
highscores.close();
}
// Checks new score against high scores
void New_High(std::vector<int> newScores)
{
std::ofstream fileoutput;
fileoutput.open("highscores.txt");
for (int i = 0; i < 10; i++)
fileoutput << newScores[i] << "\n";
fileoutput.close();
}
// Writes over highscores.txt file
int Update_Scores(int &score, std::vector<int> &top10scores)
{
for (int i = 0; i < 10; i++)
{
if (score >= top10scores[i])
{
for (int j = 9; j >= 0+i; j--)
{
top10scores[j] = top10scores[j-1];
}
top10scores[i] = score;
New_High(top10scores);
High_Scores(top10scores);
return i;
}
}
return 11;
}
// Start menu
void Welcome_Screen(sf::RenderWindow &window)
{
sf::Texture texture;
texture.loadFromFile("welcome2.png");
sf::Sprite background(texture);
// Create welcome text
sf::Font font;
if (!font.loadFromFile("bonzai.ttf"))
std::cout << "Can't find the font file 'bonzai.ttf'" << std::endl;
sf::Text text("\n\n\n\n \t\t\t Welcome!\n\t Press 'Enter' to begin.", font, 50);
text.setColor(sf::Color::White);
sf::Text quitText(" 'Esc' to quit", font, 17);
quitText.setColor(sf::Color::Black);
window.clear();
window.draw(background);
window.draw(text);
window.draw(quitText);
window.display();
}
// Basic collision check for apple placement
bool Collision_Detect(std::vector<sf::RectangleShape> &snakeBody, sf::CircleShape &apple)
{
for (int i = 0; i != snakeBody.size(); i++)
{
if (snakeBody[i].getPosition() == apple.getPosition())
return true;
}
return false;
}
// Sets up starting values for game
void New_Game(std::vector<sf::RectangleShape> &snakeBody, int window_width, int window_height,
std::default_random_engine &engine, sf::CircleShape &apple, int score, sf::Text &scoreText,
int lowBounds)
{
score = 0;
scoreText.setString("Score: 0");
snakeBody.clear();
snakeBody.push_back(sf::RectangleShape(sf::Vector2f(20,20))); // one square
snakeBody[0].setPosition(window_width/2, window_height/2 - 120);
snakeBody[0].setFillColor(sf::Color(200,255,200));
snakeBody[0].setOutlineThickness(-1);
snakeBody[0].setOutlineColor(sf::Color::Black);
std::uniform_int_distribution<int> xPosition(lowBounds, 39);
auto randX = std::bind(xPosition, std::ref(engine));
std::uniform_int_distribution<int> yPosition(lowBounds, 23); // path length of 20 pixels I think
auto randY = std::bind(yPosition, std::ref(engine));
do
apple.setPosition(randX()*20+10, randY()*20+10);
while (Collision_Detect(snakeBody, apple));
for (int i = 0; i < 2; i++)
{
snakeBody.push_back(sf::RectangleShape(sf::Vector2f(20,20)));
snakeBody[snakeBody.size()-1].setFillColor(sf::Color(100,150,100));
snakeBody[snakeBody.size()-1].setOutlineThickness(-1);
snakeBody[snakeBody.size()-1].setOutlineColor(sf::Color::Black);
snakeBody.back().setPosition(snakeBody.begin()->getPosition().x,
snakeBody.begin()->getPosition().y);
}
}
//Display all blocks of snake
void Draw_Snake(sf::RenderWindow &window, std::vector<sf::RectangleShape> &snakeBody)
{
for (int i = 0; i != snakeBody.size(); i++)
window.draw(snakeBody[i]);
}
// Moves snake's head and tail
void Move_Snake(std::vector<sf::RectangleShape> &snakeBody, sf::Vector2f &lastPosition, int move)
{
switch (move)
{
case Up:
snakeBody[0].move(0, -20);
break;
case Down:
snakeBody[0].move(0, 20);
break;
case Left:
snakeBody[0].move(-20, 0);
break;
case Right:
snakeBody[0].move(20, 0);
break;
default:
break;
}
sf::Vector2f newPosition(lastPosition);
if (snakeBody.size() > 1)
{
for (int i = 1; i != snakeBody.size(); i++)
{
lastPosition = snakeBody[i].getPosition();
snakeBody[i].setPosition(newPosition);
newPosition = lastPosition;
}
}
}
// Apple placement
bool Apple_Placement(int lowBounds, std::default_random_engine &engine,
std::vector<sf::RectangleShape> &snakeBody, sf::CircleShape &apple, sf::Clock &immuneTimer)
{
std::uniform_int_distribution<int> xPosition(lowBounds, 39);
auto randX = std::bind(xPosition, std::ref(engine));
std::uniform_int_distribution<int> yPosition(lowBounds, 23);
auto randY = std::bind(yPosition, std::ref(engine));
if ((apple.getPosition().x == snakeBody[0].getPosition().x + 10) &&
(apple.getPosition().y == snakeBody[0].getPosition().y + 10))
{
// for (int i = 0; i < 2; i++)
// {
snakeBody.push_back(sf::RectangleShape(sf::Vector2f(20,20)));
snakeBody[snakeBody.size()-1].setFillColor(sf::Color(100,150,100));
snakeBody[snakeBody.size()-1].setOutlineThickness(-1);
snakeBody[snakeBody.size()-1].setOutlineColor(sf::Color::Black);
snakeBody.back().setPosition(snakeBody.begin()->getPosition().x, snakeBody.begin()->getPosition().y);
// }
do
apple.setPosition(randX()*20+10, randY()*20+10);
while (Collision_Detect(snakeBody, apple));
immuneTimer.restart();
return true;
}
else
return false;
}
// Checks body collision and out of bounds
bool Snake_Alive(std::vector<sf::RectangleShape> &snakeBody, sf::Clock &immuneTimer)
{
if (snakeBody[0].getPosition().x < 0 || snakeBody[0].getPosition().x > 790
|| snakeBody[0].getPosition().y < 0 || snakeBody[0].getPosition().y > 460)
{
// snakeBody[0].setFillColor(sf::Color::Yellow);
return false;
}
if(immuneTimer.getElapsedTime().asSeconds() >= .15)
{
for (int i = 1; i != snakeBody.size(); i++)
{
if (snakeBody[0].getPosition() == snakeBody[i].getPosition())
{
// snakeBody[i].setFillColor(sf::Color::Yellow);
return false;
}
}
}
return true;
}
int main()
{
int window_width = 800, window_height = 600;
int bitsPerPixel = 24, start = 0, mode = 0, score = 0, difficulty = 2, lowBounds = 0;
std::vector<int> top10scores;
std::vector<sf::RectangleShape> snakeBody;
int move;
bool currentlyPlaying = false;
// Create main window
sf::RenderWindow window(sf::VideoMode(window_width, window_height,
bitsPerPixel), "Snake!", sf::Style::Close);
window.setVerticalSyncEnabled(true);
// Set the icon
sf::Image icon;
if (!icon.loadFromFile("icon.png"))
return EXIT_FAILURE;
window.setIcon(icon.getSize().x, icon.getSize().y, icon.getPixelsPtr());
// Game board
sf::Texture texture;
texture.loadFromFile("grass.png"); //replace with game board
sf::Sprite grass(texture);
// Apple
sf::CircleShape apple(10);
apple.setOutlineThickness(-1); // should be diameter of 20
apple.setOutlineColor(sf::Color::Black);
apple.setFillColor(sf::Color::Red);
apple.setOrigin(apple.getRadius(), apple.getRadius());
// Random generator
std::random_device seed_device;
std::default_random_engine engine(seed_device());
// Clocks
sf::Clock moveClock;
sf::Clock inputClock;
sf::Clock immuneTimer;
// Score box
sf::RectangleShape scoreBox(sf::Vector2f(window_width, window_height - 480));
scoreBox.setFillColor(sf::Color(0,200,0));
scoreBox.setOutlineColor(sf::Color::Black);
scoreBox.setOutlineThickness(-3.f);
scoreBox.setPosition(0, 480);
sf::Font font;
if (!font.loadFromFile("bonzai.ttf"))
std::cout << "Can't find the font file 'bonzai.ttf'" << std::endl;
sf::Text scoreText("Score: ", font, 60);
scoreText.setColor(sf::Color::White);
scoreText.setPosition(314, 497);
sf::Text pauseText("GAME PAUSED", font, 80);
pauseText.setColor(sf::Color::Black);
pauseText.setPosition(174, 185);
sf::Text overText(" GAME OVER", font, 78);
overText.setColor(sf::Color(150,0,0));
overText.setPosition(174, 185);
sf::Text newquitText("Pause: 'P'\nNew game: 'Enter'\nQuit to main menu: 'Q'", font, 20);
newquitText.setColor(sf::Color::Black);
newquitText.setPosition(5, 525);
sf::Text highScoreText("", font, 85);
highScoreText.setColor(sf::Color::Black);
//High scores
High_Scores(top10scores);
if (difficulty == 2)
lowBounds = 0;
New_Game(snakeBody, window_width, window_height, engine, apple, score, scoreText, lowBounds);
// Main game loop
while (window.isOpen())
{
sf::Vector2f lastPosition(snakeBody[0].getPosition().x, snakeBody[0].getPosition().y);
// Event
sf::Event event;
while (window.pollEvent(event))
{
// Welcome screen
if (start <= 1)
{
Welcome_Screen(window);
start++;
}
// Close window: Exit
if (event.type == sf::Event::Closed)
window.close();
// Esc pressed: Exit
if (event.type == sf::Event::KeyPressed && event.key.code
== sf::Keyboard::Escape)
window.close();
// Q pressed: Exit to main menu
if (event.type == sf::Event::KeyPressed && event.key.code
== sf::Keyboard::Q)
{
start = 1;
mode = 0;
}
if (event.type == sf::Event::KeyPressed && event.key.code
== sf::Keyboard::Return)
{
if (!currentlyPlaying)
currentlyPlaying = true;
move = Down;
New_Game(snakeBody, window_width, window_height, engine, apple, score, scoreText, lowBounds);
mode = 1;
score = 0;
moveClock.restart();
inputClock.restart();
immuneTimer.restart();
}
if(event.type == sf::Event::KeyPressed && inputClock.getElapsedTime().asSeconds() >= 0.06) //0.07
{
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Up && move != Down)
{
move = Up;
inputClock.restart();
}
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Down && move != Up)
{
move = Down;
inputClock.restart();
}
if(event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Left && move != Right)
{
move = Left;
inputClock.restart();
}
if(event.key.code == sf::Keyboard::Right && move != Left)
{
move = Right;
inputClock.restart();
}
}
// P pressed: Pause simulation
if (event.type == sf::Event::KeyPressed && event.key.code
== sf::Keyboard::P)
{
if (mode == 1)
{
window.draw(pauseText);
window.display();
}
mode *= -1;
moveClock.restart();
immuneTimer.restart();
inputClock.restart();
}
}
if (mode == 1)
{
window.clear();
window.draw(grass);
window.draw(apple);
Draw_Snake(window, snakeBody);
window.draw(scoreBox);
window.draw(scoreText);
window.draw(newquitText);
if(moveClock.getElapsedTime().asSeconds() >= .075) // change back to 0.09
{
Move_Snake(snakeBody, lastPosition, move);
moveClock.restart();
}
if(Apple_Placement(lowBounds, engine, snakeBody, apple, immuneTimer))
{
if (difficulty == 1)
score += 5;
else if (difficulty == 2)
score += 10;
else
score += 20;
std::string newScore = std::to_string(score);
scoreText.setString("Score: " + newScore);
}
if(!Snake_Alive(snakeBody, immuneTimer))
{
window.draw(overText);
int scorePlacement = Update_Scores(score, top10scores);
if (scorePlacement != 11)
{
std::string newHighText = std::to_string(scorePlacement+1);
highScoreText.setString("#" + newHighText
+ " out of top 10 scores!");
if (scorePlacement == 9)
highScoreText.setPosition(15, 50);
else
highScoreText.setPosition(30, 50);
window.draw(highScoreText);
}
window.display();
mode = 0;
window.display();
}
window.display();
}
}
return EXIT_SUCCESS;
}
'if (inputClock.getElapsedTime(). AsSeconds()> = 0.07)' cóż, to jest trochę podejrzane ... – Manu343726
Co masz na myśli mówiąc o płynności? Gra Snake nie jest płynna z definicji, segmenty są po prostu przyciągane z jednego miejsca do drugiego. –
Mam na myśli kontrolowanie głowy węża bardziej płynnie. Na przykład bardzo trudno wykonać konsekwentnie ciasny zawrót (gdy nie ma dodatkowego miejsca). – Austin