#include <iostream>
#include <string>
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "globals.h"
#include "Snake.h"
#include "Food.h"
#include "SoundEffect.h"
void doEvents(sf::RenderWindow & window, bool & up, bool & down, bool & left, bool & right, bool & pressed);
void move(Snake & snake, bool up, bool down, bool left, bool right);
bool intersect(const Snake & snake);
bool intersect(const Snake & snake, const Food & food, size_t & i);
bool borderIntersect(const Snake & snake, const sf::RenderWindow & window);
int main(){
srand(time(0));
sf::RenderWindow window(sf::VideoMode(SCRSIZE, SCRSIZE), "Snake");
float volume = 50;
SoundEffect moveSound("sounds/move.wav", volume);
SoundEffect foodSound("sounds/food.wav", volume);
SoundEffect extraSound("sounds/extra.wav", volume);
SoundEffect deathSound("sounds/death.wav", volume);
sf::Color foodColor(0, 123, 123);
Snake snake(sf::Vector2f(SIZE, SIZE), sf::Vector2f(GRIDSIZE/2, GRIDSIZE/2), 3, sf::Color::White, OUTLINE);
Food food(1, foodColor);
Food extra(2, RAND_COL);
food.spawn(snake, extra, foodColor);
bool gameOver = false;
bool up = true;
bool down = false;
bool left = false;
bool right = false;
bool pressed = false;
int collectedItems = 0;
int level = 1;
int score = 0;
int lives = LIVES;
// Fixed time step loop setup
sf::Clock clock;
double skippedTime = 0;
double secondsElapsed = 0;
double interval = INTERVAL;
int updates = 0;
// Game loop
while (window.isOpen()){
const double elapsedTime = clock.getElapsedTime().asMicroseconds() / 1000.0;
skippedTime += elapsedTime;
secondsElapsed += elapsedTime;
extra.clock(elapsedTime);
clock.restart();
pressed = false;
if (snake.getLength() <= 20)
interval = INTERVAL * 2;
else if (snake.getLength() <= 40)
interval = INTERVAL / 2.0;
else if (snake.getLength() <= 60)
interval = INTERVAL / 1.2;
else if (snake.getLength() <= 80)
interval = INTERVAL;
while (skippedTime >= interval){
//Second timer
updates++;
while (secondsElapsed >= 1000){
//system("cls");
std::cout << updates << " Updates, " << secondsElapsed / updates << " Average Interval\n";
std::cout << "Score: " << score << '\n';
std::cout << "Level: " << level << '\n';
std::cout << "Lives: " << lives << '\n';
updates = 0;
secondsElapsed -= 1000;
}
//Events
doEvents(window, up, down, left, right, pressed);
//Update
size_t pos = 0;
move(snake, up, down, left, right);
if (interval < 300 && (updates == 3 || updates == 6 || updates == 9))
moveSound.play();
else if (interval >= 300)
moveSound.play();
if (rand() % 1000 <= 5){
extra.spawn(snake, food, RAND_COL, interval * 40);
}
if (intersect(snake) || borderIntersect(snake, window)){
deathSound.play();
gameOver = true;
}
if (intersect(snake, food, pos)){
foodSound.play();
food.remove();
food.spawn(snake, extra, foodColor);
collectedItems++;
score += food.getPoints();
snake.grow();
}
if (intersect(snake, extra, pos)){
extraSound.play();
extra.remove(pos);
collectedItems++;
score += extra.getPoints();
snake.grow();
}
if (collectedItems >= 10){
level++;
collectedItems = 0;
extra.setPoints(level * level);
food.setPoints(level);
}
if (gameOver){
lives--;
if (lives < 0)
window.close();
snake = Snake(sf::Vector2f(SIZE, SIZE), sf::Vector2f(GRIDSIZE / 2, GRIDSIZE / 2), 3, sf::Color::White, OUTLINE);
food = Food(level, sf::Color(0, 123, 123));
food.spawn(snake, extra, foodColor);
extra = Food(level*level, RAND_COL);
interval = INTERVAL;
collectedItems = 0;
if (score >= 100)
score -= score / 3;
else
score = 0;
gameOver = false;
up = true;
down = false;
left = false;
right = false;
}
//Subtract time
skippedTime -= interval;
}
// Render
window.clear();
snake.draw(window);
food.draw(window);
extra.draw(window);
window.display();
}
return 0;
}
void doEvents(sf::RenderWindow & window, bool & up, bool & down, bool & left, bool & right, bool & pressed){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed){
window.close();
}
if (event.type == sf::Event::KeyPressed){
sf::Keyboard k;
if (event.key.code == k.Escape){
window.close();
}
if (event.key.code == k.Up && !down && !pressed){
up = true;
down = false;
left = false;
right = false;
pressed = true;
}
else if (event.key.code == k.Down && !up && !pressed){
up = false;
down = true;
left = false;
right = false;
pressed = true;
}
else if (event.key.code == k.Left && !right && !pressed){
up = false;
down = false;
left = true;
right = false;
pressed = true;
}
else if (event.key.code == k.Right && !left && !pressed){
up = false;
down = false;
left = false;
right = true;
pressed = true;
}
}
}
}
void move(Snake & snake, bool up, bool down, bool left, bool right){
if (up){
snake.moveUp();
}
else if (down){
snake.moveDown();
}
else if (left){
snake.moveLeft();
}
else if (right){
snake.moveRight();
}
}
bool intersect(const Snake & snake){
for (int i = 1; i < snake.getLength(); i++){
if (snake.getGridPos() == snake.getGridPos(i)){
return true;
}
}
return false;
}
bool intersect(const Snake & snake, const Food & food, size_t & item){
for (int i = 0; i < food.getLength(); i++){
if (snake.getGridPos() == food.getGridPos(i)){
item = i;
return true;
}
}
return false;
}
bool borderIntersect(const Snake & snake, const sf::RenderWindow & window){
if (snake.getPos().x >= window.getSize().x)
return true;
if (snake.getPos().x < 0)
return true;
if (snake.getPos().y >= window.getSize().y)
return true;
if (snake.getPos().y < 0)
return true;
return false;
}