We're a community of 1076K IT Pros here for help, advice, solutions, professional growth and fun. Join us!
1,075,983 Members — Technology Publication meets Social Media
Username:
Password:
Lost login information?
Start New Discussion Reply to this Discussion

SFML Help with timing

So, I wrote this snake game in C++ using SFML 2.0 RC and everything was working perfectly until I tried to implement frame independent movement. I understand how to do it, but I can't seem to make it work with my snake game. If the SCALE define is set to 10, then I want the snake to move 10 pixels. I never want it to move less or more than that, but I want the snake to move at the same speed on all computers, which is why I needed to implement frame independent movement. Here is my code, in the updateSnake method is where the movement occurs.

If someone could help me fix this problem it would be much appreciated :)

#include <SFML/Graphics.hpp>
#include <iostream>
#include <cmath>
#include <ctime>
#include <sstream>

#define WIDTH 40
#define HEIGHT 40
#define SCALE 20

const int MAX_PARTS = HEIGHT * WIDTH;

enum {
    UP,
    DOWN,
    LEFT,
    RIGHT
};

struct Apple {
    Apple() {
        x = (int) ((rand() % (WIDTH - 1)) + 1) * SCALE;
        y = (int) ((rand() % (HEIGHT - 1)) + 1) * SCALE;
        texture.loadFromFile("Apple.png");
    }
    float x, y;
    sf::Texture texture;
};

struct SnakePart {
    SnakePart(float x, float y) {
        this->x = x;
        this->y = y;
    }
    float x, y;
};

struct Snake {
    Snake(float x, float y, int dir) {
        this->x = x;
        this->y = y;
        this->dir = dir;
        numParts = 0;
        headTexture.loadFromFile("HeadSnake.png");
        bodyTexture.loadFromFile("BodySnake.png");
        for (int i = 0; i < MAX_PARTS; i++) {
            parts[i] = NULL;
        }
        parts[0] = new SnakePart((((WIDTH - 1) * SCALE) / 2), 
            ((HEIGHT * SCALE) / 2));
        numParts++;
    }
    ~Snake() {
        for (int i = 0; i < MAX_PARTS; i++) {
            delete parts[i];
        }
    }
    int dir, numParts;
    float x, y;
    SnakePart* parts[MAX_PARTS];
    sf::Texture headTexture;
    sf::Texture bodyTexture;
};

bool gameRunning;

void updateSnake(Snake&, Apple&, const long);
void drawSnake(const Snake&, sf::RenderWindow&);
void drawApple(const Apple&, sf::RenderWindow&);

int main(int argc, char* argv[]) {
    srand(static_cast<unsigned int>(time(0)));
    sf::RenderWindow window(sf::VideoMode(WIDTH * SCALE, HEIGHT * SCALE), 
        "SFML Snake");
    //window.setFramerateLimit(60);

    Snake* snake = new Snake((WIDTH * SCALE) / 2, 
        (HEIGHT * SCALE) / 2, RIGHT);
    Apple* apple = new Apple();
    sf::Clock clock;
    gameRunning = true;
    sf::Text text;
    sf::Font font;
    font.loadFromFile("digital-7.ttf");
    text.setFont(font);
    text.setPosition(30, 30);
    text.setString("Score: 0");
    text.setCharacterSize(15);

    while (window.isOpen() && gameRunning) {
        sf::Time time = clock.restart();
        long delta = time.asMilliseconds();
        sf::Event event;
        while (window.pollEvent(event)) {
            if (event.type == sf::Event::Closed) {
                window.close();
            }
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::A) && 
            snake->dir != RIGHT)  {
            snake->dir = LEFT;
        } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D) && 
            snake->dir != LEFT) {
            snake->dir = RIGHT;
        } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) && 
            snake->dir != DOWN) {
            snake->dir = UP;
        } else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S) && 
            snake->dir != UP) {
            snake->dir = DOWN;
        }
        std::stringstream ss;
        ss << (snake->numParts - 1);
        text.setString("Score: " + ss.str());
        updateSnake(*snake, *apple, delta);
        window.clear();
        drawSnake(*snake, window);
        drawApple(*apple, window);
        window.draw(text);
        window.display();
    }
    delete snake;
    delete apple;
    //std::cin.get();
    return 0;
}

void updateSnake(Snake& snake, Apple& apple, const long delta) {
    int x = 0, y = 0;
    switch (snake.dir) {
    case UP:
        y = -1;
        break;
    case DOWN:
        y = 1;
        break;
    case LEFT:
        x = -1;
        break;
    case RIGHT:
        x = 1;
        break;
    }
    snake.x += (x * SCALE) * (delta / 1000.f);
    snake.y += (y * SCALE) * (delta / 1000.f);
    if (snake.x >= (WIDTH * SCALE) || 
        snake.y >= (HEIGHT * SCALE) ||
        snake.x < 0 ||
        snake.y < 0) {
            gameRunning = false;
            return;
    }
    if ((snake.x == apple.x) && (snake.y == apple.y)) {
        snake.parts[snake.numParts] = new SnakePart(snake.parts[snake.numParts - 1]->x - 1, 
            snake.parts[snake.numParts - 1]->y);
        snake.numParts++;
        apple.x = (int) ((rand() % (WIDTH - 1)) + 1) * SCALE;
        apple.y = (int) ((rand() % (HEIGHT - 1)) + 1) * SCALE;
    }
    for (int i = 0; i < snake.numParts; i++) {
        if ((snake.x == snake.parts[i]->x) && 
            (snake.y == snake.parts[i]->y)) {
            gameRunning = false;
            return;
        }
    }
    float lastPartX = snake.x - (x * SCALE), 
        lastPartY = snake.y - (y * SCALE);
    for (int i = 0; i < snake.numParts; i++) {
        SnakePart* part = snake.parts[i];
        float oldX = part->x, oldY = part->y;
        part->x = lastPartX;
        part->y = lastPartY;
        lastPartX = oldX;
        lastPartY = oldY;
    }
}

void drawSnake(const Snake& snake, sf::RenderWindow& window) {
    sf::Sprite sprite;
    sprite.setTexture(snake.headTexture);
    sprite.setPosition(snake.x, snake.y);
    float scaleFactor = SCALE / 10;
    sprite.setScale(scaleFactor, scaleFactor);
    window.draw(sprite);
    for (int i = 0; i < snake.numParts; i++) {
        sprite.setTexture(snake.bodyTexture);
        sprite.setPosition(snake.parts[i]->x, snake.parts[i]->y);
        window.draw(sprite);
    }
}

void drawApple(const Apple& apple, sf::RenderWindow& window) {
    sf::Sprite sprite;
    sprite.setTexture(apple.texture);
    sprite.setPosition(apple.x, apple.y);
    float scaleFactor = SCALE / 10;
    sprite.setScale(scaleFactor, scaleFactor);
    window.draw(sprite);
}

Thank you in advance for any help :)

1
Contributor
1
Reply
19 Hours
Discussion Span
11 Months Ago
Last Updated
2
Views
Haxifix
Newbie Poster
9 posts since Aug 2010
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

Can someone please help me?

Haxifix
Newbie Poster
9 posts since Aug 2010
Reputation Points: 10
Solved Threads: 0
Skill Endorsements: 0

This article has been dead for over three months: Start a new discussion instead

Post: Markdown Syntax: Formatting Help
 
You
 
© 2013 DaniWeb® LLC
Page rendered in 0.0931 seconds using 2.69MB