I am currently stuck trying to create a grid for my controllable snake to move around. Currently. I am using a resolution of 1024x768 and would like the snake to move between a 16x16 grid (64x48 resolution)
So far the snake just moves pixel by pixel at a set speed.
I'll paste the .cpp and .hpp files below which i think are relevant to where i need to implement the code. If anyone could provide any suggestions/code that would be great!
snake.cpp
#include "snake.hpp"
#include <cstdlib>
void Snake::move()
{
    switch(direction_){
    case Direction::North:
        position_.y += 1;
        break;
    case Direction::East:
        position_.x += 1;
        break;
    case Direction::South:
        position_.y -= 1;
        break;
    case Direction::West:
        position_.x -= 1;
    }
    if (position_.x < 0) position_.x = 63; else if (position_.x > 63) position_.x = 0;
    if (position_.y < 0) position_.y = 47; else if (position_.y > 47) position_.y = 0;
}
void Snake::render(prg::Canvas& canvas) const
{
    canvas.drawCircle(getPosition().x * 16, getPosition().y * 16,16,prg::Colour::WHITE);
}
void Snake::changeDirection(Direction new_direction)
{
    direction_ = new_direction;
}
snake.hpp
#if !defined SNAKE_HPP
#define SNAKE_HPP
#include <prg_interactive.hpp>
enum class Direction {
    North = 1, East, South, West
};
struct Position final {
    int x{0}, y{0};
    Position(int ix, int iy) : x{ix}, y{iy} {}
};
class Snake {
public:
    virtual ~Snake() {}
    virtual void move();
    void render(prg::Canvas& canvas) const;
    void changeDirection(Direction new_direction);
    const Position& getPosition() const {return position_;}
    void setPosition(const Position& position){ position_ = position;}
 private:
    Direction direction_ {Direction::North};
    Position position_ {0,0};
};
    class PlayerSnake : public Snake,
                        public prg::IKeyEvent {
    public:
        PlayerSnake();
        virtual ~PlayerSnake();
        bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
};
#endif // SNAKE_HPP
play_state.cpp
#include "play_state.hpp"
#include "ai_snake.hpp"
#include "player_snake.hpp"
#include <iostream>
const size_t MaxShapes {5};
const unsigned int MaxScale {5};
bool PlayState::onCreate()
{
    snakes_.push_back(new AISnake);
    snakes_.back()->setPosition(Position(100,100));
    snakes_.push_back(new PlayerSnake);
    snakes_.back()->setPosition(Position(50,50));
    double x, y;
    for(unsigned shape = 0;shape < MaxShapes;shape++)
    {
        x = (double)(rand() % prg::application.getScreenWidth());
        y = (double)(rand() % prg::application.getScreenHeight());
        shapes_.push_back(Square({x, y}));
    }
    return true;
}
bool PlayState::onDestroy()
{
    return true;
}
void PlayState::onEntry()
{
    prg::application.addKeyListener(*this);
    game_timer_.start();
}
void PlayState::onExit()
{
    prg::application.removeKeyListener(*this);
    game_timer_.stop();
}
void PlayState::onUpdate()
{
}
void PlayState::onRender(prg::Canvas& canvas)
{
    const std::string text = "";
    canvas.blitFast(
        background_,
        canvas.getWidth() / 2 - background_.getWidth() / 2,
        canvas.getHeight() / 2 - background_.getHeight() / 2
    );
    prg::uint text_dims[2];
    prg::Font::MASSIVE.computePrintDimensions(text_dims, text);
    prg::Font::MASSIVE.print(
      canvas,
      prg::application.getScreenWidth() / 2 - text_dims[0] / 2,
      prg::application.getScreenHeight() / 2 - text_dims[1] / 2,
      prg::Colour::RED,
      text);
    for(const auto snake : snakes_) {
    snake->render(canvas);
    }
    for(Shape shapes : shapes_) {
    shapes.render(canvas);
    }
}
bool PlayState::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
    if(key_event.key_state == KeyEvent::KB_DOWN) {
        switch(key_event.key) {
        case KeyEvent::KB_ESC_KEY:
            prg::application.exit();
            break;
        }
    }
    return true;
}
void PlayState::onTimer(prg::Timer& timer)
{
    for(auto snake : snakes_) {
        snake->move();
    }
}
play_state.hpp
#if !defined PLAY_STATE_HPP
#define PLAY_STATE_HPP
#include <prg_interactive.hpp>
#include "snake.hpp"
#include "square.hpp"
#include <list>
//Example of forward declaration of Snake class
class Snake;
class PlayState final : public prg::IAppState,
                        public prg::IKeyEvent,
                        public prg::ITimerEvent {
public:
    PlayState() = default;
    bool onCreate() override;
    bool onDestroy() override;
    void onEntry() override;
    void onExit() override;
    void onUpdate() override;
    void onRender(prg::Canvas& canvas) override;
    bool onKey(const prg::IKeyEvent::KeyEvent& key_event) override;
    void onTimer(prg::Timer& timer) override;
private:
    //Snake* snakes_[2] {nullptr,nullptr};
    std::list<Snake*> snakes_;
    prg::Timer game_timer_ {0, 1000 / 30, *this};
    const prg::Image background_ {prg::ImageFile("resources/images/border.bmp").load()};
        std::vector<Shape> shapes_;
};
#endif // PLAY_STATE_HPP
player_snake.cpp
#include "player_snake.hpp"
//PlayerSnake Implementation
//
PlayerSnake::PlayerSnake()
{
    prg::application.addKeyListener(*this);
}
PlayerSnake::~PlayerSnake()
{
    prg::application.removeKeyListener(*this);
}
bool PlayerSnake::onKey(const prg::IKeyEvent::KeyEvent& key_event)
{
    if(key_event.key_state == KeyEvent::KB_DOWN) {
        switch(key_event.key) {
        case KeyEvent::KB_LEFT_KEY:
            changeDirection(Direction::West);
            break;
        case KeyEvent::KB_RIGHT_KEY:
            changeDirection(Direction::East);
            break;
        case KeyEvent::KB_UP_KEY:
            changeDirection(Direction::North);
            break;
        case KeyEvent::KB_DOWN_KEY:
            changeDirection(Direction::South);
            break;
        }
    }
    return true;
}
player_snake.hpp
#if !defined PLAYER_SNAKE_HPP
#define PLAYER_SNAKE_HPP
#include "snake.hpp"
#include <prg_interactive.hpp>
#endif //PLAYER_SNAKE_HPP
 
    