diff options
author | Stephen Enders <smenders@gmail.com> | 2021-01-17 15:40:44 -0500 |
---|---|---|
committer | Stephen Enders <smenders@gmail.com> | 2021-01-17 15:40:44 -0500 |
commit | eead8271c8ac12e75f52c58bf8a523f1d1897829 (patch) | |
tree | dc850bd9fdc6a26c70e405b34e9017ed6531933a | |
parent | 1dbd3c241ea6af43a26449e515438cc241de46ad (diff) |
Rolling updates + Score change
Added state
Added dice + roll button
Updated blank tile graphic
-rw-r--r-- | helper.cpp | 165 | ||||
-rw-r--r-- | helper.h | 55 | ||||
-rw-r--r-- | res/ur.aseprite | bin | 1107 -> 1547 bytes | |||
-rw-r--r-- | res/ur.png | bin | 1125 -> 1769 bytes | |||
-rw-r--r-- | ur.cpp | 203 |
5 files changed, 380 insertions, 43 deletions
@@ -27,11 +27,100 @@ loadTextures(const char* path) return textures; } -sf::Font loadFont() +// increment through the textures +inline int +next(int* p) { - sf::Font font; - if (!font.loadFromFile("./res/DejaVuSansMono.ttf")) + int i = *p; + (*p) = (i + 1) % 2; + return i; +} + +std::shared_ptr<std::vector<sf::Sprite>> +createBoard(std::shared_ptr<std::vector<sf::Texture>> textures) +{ + auto sprites = std::make_shared<std::vector<sf::Sprite>>(); + sf::Texture& star_texture = (*textures)[STAR_TILE]; + sf::Texture& blank_texture = (*textures)[BLANK_TILE]; + int sp_idx = 0; + // p1 pieces + // p1 star { + sf::Sprite s; + s.setTexture(star_texture); + s.setPosition(pos(3, 5)); + sprites->push_back(s); + } + // p1 start + for (int i = 0; i < 3; i++) { + sf::Texture& t = (*textures)[P1_BOARD_TILES[next(&sp_idx)]]; + sf::Sprite s; + s.setTexture(t); + s.setPosition(pos(4 + i, 5)); + sprites->push_back(s); + } + // p1 end + { + sf::Sprite end_star; + end_star.setTexture(star_texture); + end_star.setPosition(pos(9, 5)); + sprites->push_back(end_star); + + sf::Texture& t = (*textures)[P1_BOARD_TILES[next(&sp_idx)]]; + sf::Sprite s; + s.setTexture(t); + s.setPosition(pos(10, 5)); + sprites->push_back(s); + } + // center pieces + for (int i = 0; i < 8; i++) { + sf::Sprite s; + if (i == 3) { + s.setTexture(star_texture); + } else { + s.setTexture(blank_texture); + } + s.setPosition(pos(3 + i, 4)); + sprites->push_back(s); + } + // p2 pieces + // p2 star + { + sf::Sprite s; + s.setTexture(star_texture); + s.setPosition(pos(3, 3)); + sprites->push_back(s); + } + // p2 start + for (int i = 0; i < 3; i++) { + sf::Texture& t = (*textures)[P2_BOARD_TILES[next(&sp_idx)]]; + sf::Sprite s; + s.setTexture(t); + s.setPosition(pos(4 + i, 3)); + sprites->push_back(s); + } + // p2 end + { + sf::Sprite end_star; + end_star.setTexture(star_texture); + end_star.setPosition(pos(9, 3)); + sprites->push_back(end_star); + + sf::Texture& t = (*textures)[P2_BOARD_TILES[next(&sp_idx)]]; + sf::Sprite s; + s.setTexture(t); + s.setPosition(pos(10, 3)); + sprites->push_back(s); + } + + return sprites; +} + +sf::Font +loadFont() +{ + sf::Font font; + if (!font.loadFromFile("./res/DejaVuSansMono.ttf")) { std::cerr << "Unable to load font" << std::endl; throw std::runtime_error("Unable to load font"); } @@ -64,11 +153,70 @@ createPlayer(sf::Texture& texture) return player; } +std::shared_ptr<std::vector<struct dice_t>> +createAllDice(sf::Texture& die0Texture, sf::Texture& die1Texture) +{ + auto dice = std::make_shared<std::vector<struct dice_t>>(); + + // create dice, even 0 odds 1 + // there are 8 dice results int total + // 4 potential 0s + // 4 potential 1s + // The dice will be rendered in pairs + // [0, 1] will be the left most die + // [2, 3] will be the second + // ... and so on + // Since a die can only have 2 results (0 or 1) + // To simplify how we will be placing them, the results of the roll + // will dictate which value each die gets + for (int i = 0; i < 8; i++) { + if (i % 2 == 0) { + sf::Sprite s; + s.setTexture(die0Texture); + struct dice_t die = { 0, true, s }; + dice->push_back(die); + } else { + sf::Sprite s; + s.setTexture(die1Texture); + struct dice_t die = { 1, false, s }; + dice->push_back(die); + } + } + + return dice; +} + +std::shared_ptr<std::vector<std::shared_ptr<sf::Sprite>>> +createRollSprites(sf::Texture& t1, sf::Texture& t2) +{ + auto sprites = std::make_shared<std::vector<std::shared_ptr<sf::Sprite>>>(); + + auto s1 = std::make_shared<sf::Sprite>(); + s1->setTexture(t1); + + auto s2 = std::make_shared<sf::Sprite>(); + s2->setTexture(t2); + + sprites->push_back(s1); + sprites->push_back(s2); + + return sprites; +} + +void +makeNum(sf::Sprite* sprite_ptr, + int num, + std::shared_ptr<std::vector<sf::Texture>> textures) +{ + sf::Texture& t = (*textures)[NUMS_TILES[num]]; + sprite_ptr->setTexture(t); +}; + bool clickedPiece(sf::Vector2i mousePosition, struct piece_t* piece) { return piece->sprite.getGlobalBounds().contains(mousePosition.x, - mousePosition.y); + mousePosition.y); } bool @@ -103,3 +251,12 @@ canMovePiece( return true; } + +// This function takes in an row and col we want to put the sprite in +// and translate it to a real position in the view +// This is because we've ZOOMed in an that adjusts the entire view. +sf::Vector2f +pos(float c, float r) +{ + return { c * SPRITE_SIZE, r * SPRITE_SIZE }; +} @@ -11,9 +11,33 @@ static const unsigned int SPRITE_SIZE = 16; static const unsigned int NUM_PIECES = 7; static const unsigned int SAFE_SPACE = 7; // 0-indexed static const unsigned int EXIT_SPACE = 14; // final space + 1 - +static const float ZOOM = 0.5f; +static const float SPRITE_ROWS = 9.f; +static const float SPRITE_COLS = 14.f; +static const float SCR_W = SPRITE_SIZE / ZOOM * SPRITE_COLS / ZOOM; +static const float SCR_H = SPRITE_SIZE / ZOOM * SPRITE_ROWS / ZOOM; +static const int P1_PIECE = 6; +static const int P2_PIECE = 5; +static const int P1_BOARD_TILES[2] = { 0, 1 }; +static const int P2_BOARD_TILES[2] = { 2, 3 }; +static const int STAR_TILE = 4; +static const int BLANK_TILE = 9; +static const int DIE_0 = 8; +static const int DIE_1 = 7; +static const int NUMS_TILES[8] = { 10, 11, 12, 13, 14, 15, 16, 17 }; +static const int ROLL_TILES[2] = { 18, 19 }; + +static const char* TITLE = "Royal Game of Ur"; static const sf::Color GLOBAL_MASK(255, 0, 255, 255); +enum GameState +{ + WAITING, + ROLLING, + PLACING, + GAME_OVER +}; + struct piece_t { int id; @@ -28,10 +52,20 @@ struct player_t std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> pieces; }; +struct dice_t +{ + int value; + bool show; + sf::Sprite sprite; +}; + std::shared_ptr<std::vector<sf::Texture>> loadTextures(const char* path); +std::shared_ptr<std::vector<sf::Sprite>> +createBoard(std::shared_ptr<std::vector<sf::Texture>> textures); + sf::Font loadFont(); std::shared_ptr<struct player_t> @@ -40,6 +74,17 @@ createPlayer(sf::Texture& pieceTexture); std::shared_ptr<struct piece_t> createPiece(int id, sf::Texture& texture); +std::shared_ptr<std::vector<struct dice_t>> +createAllDice(sf::Texture& die0Texture, sf::Texture& die1Texture); + +std::shared_ptr<std::vector<std::shared_ptr<sf::Sprite>>> +createRollSprites(sf::Texture& t1, sf::Texture& t2); + +void makeNum( + sf::Sprite* sprite_ptr, + int num, + std::shared_ptr<std::vector<sf::Texture>> textures); + bool clickedPiece(sf::Vector2i mousePosition, std::shared_ptr<struct piece_t> piece); @@ -50,6 +95,12 @@ canMovePiece( std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> myPieces, std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> enemyPieces); -std::vector<int> getLegalMoves(std::shared_ptr<struct player_t> activePlayer, std::shared_ptr<struct player_t> opponent); +std::vector<int> +getLegalMoves( + std::shared_ptr<struct player_t> activePlayer, + std::shared_ptr<struct player_t> opponent); + +sf::Vector2f +pos(float c, float r); #endif diff --git a/res/ur.aseprite b/res/ur.aseprite Binary files differBinary files differindex 6c75ad4..a7a25eb 100644 --- a/res/ur.aseprite +++ b/res/ur.aseprite @@ -1,58 +1,157 @@ +#include "helper.h" #include <SFML/Graphics.hpp> #include <iostream> #include <string> -#include "helper.h" -const float SCR_W = 800.f; -const float SCR_H = 600.f; -const char* TITLE = "Royal Game of Ur"; const char* TEXTURE_PATH = "./res/ur.png"; -const int P1_PIECE = 6; -const int P2_PIECE = 5; -const int P1_BOARD_TILES[2] = { 0, 1 }; -const int P2_BOARD_TILES[2] = { 2, 3 }; -const int STAR_TILE = 4; -const int BLANK_TILE = 9; -const int DIE_0 = 8; -const int DIE_1 = 7; -const float ZOOM = 0.5f; const float PAD = 32.f; const float PIECE_PAD = 8.f; const float TEXT_OFFSET = 8.f; const sf::Color BG_COLOR = sf::Color(66, 47, 81, 255); +const sf::Color GREY = sf::Color(255, 255, 255, 128); + +GameState state = GameState::WAITING; +GameState prev_state = GameState::WAITING; + +inline void +change_state(GameState next) +{ + std::cout << "GameState == " << next << std::endl; + prev_state = state; + state = next; +} + +// p1 = false, p2 = true +bool turn_tracker = true; + +inline void +next_turn() +{ + turn_tracker = !turn_tracker; +} + +inline bool +p1_turn() +{ + return !turn_tracker; +} + +inline bool +p2_turn() +{ + return turn_tracker; +} + +inline void +render_dice( + sf::RenderWindow* window, + std::shared_ptr<std::vector<struct dice_t>> dice, + std::shared_ptr<std::vector<std::shared_ptr<sf::Sprite>>> roll_sprites) +{ + + // draw dice + int dice_r, dice_c, roll_r, roll_c; + if (p1_turn()) { + dice_r = 6; + dice_c = 11; + roll_r = dice_r + 2; + roll_c = dice_c; + } else { + dice_r = 1; + dice_c = 11; + roll_r = dice_r - 1; + roll_c = dice_c; + } + if (state == GameState::PLACING) { + int result = 0; + // draw roll result + int r = dice_r, c = dice_c; + for (int i = 0; i < 8; i++) { + auto die = (*dice)[i]; + if (die.show) { + die.sprite.setPosition(pos(c, r)); + result += die.value; + window->draw(die.sprite); + + if (i % 2 == 0) { + c += 1; + // reset if we've already bumped it once + if (c % 2 == 0) { + c = dice_c; + } + } else { + r += 1; + } + } + } + } + /* + else if (state == GameState::ROLLING) + { + // animate the dice. This is attached to a timer + // which will move between rolling and placing + } + */ + else { + // draw initial values + // draw the 0s + int c = dice_c, r = dice_r; + for (int i = 0; i < 8; i += 2) { + auto die = (*dice)[i]; + die.sprite.setPosition(pos(c++, r)); + window->draw(die.sprite); + if (i == 2) { + c = dice_c; + r += 1; + } + } + // draw roll text + c = roll_c; + r = roll_r; + for (auto s : (*roll_sprites)) { + s->setPosition(pos(c++, r)); + window->draw(*s); + } + } +} int main() { const std::shared_ptr<std::vector<sf::Texture>> textures = loadTextures(TEXTURE_PATH); - + + const std::shared_ptr<std::vector<sf::Sprite>> board = createBoard(textures); + const std::shared_ptr<struct player_t> p1 = createPlayer((*textures)[P1_PIECE]); const std::shared_ptr<struct player_t> p2 = createPlayer((*textures)[P2_PIECE]); - sf::Font font = loadFont(); - sf::RenderWindow window(sf::VideoMode(SCR_W, SCR_H), TITLE); + const std::shared_ptr<std::vector<std::shared_ptr<sf::Sprite>>> roll_sprites = + createRollSprites((*textures)[ROLL_TILES[0]], (*textures)[ROLL_TILES[1]]); - sf::Text p1ScoreMsg(std::to_string(p1->score), font, 36); - p1ScoreMsg.setPosition(TEXT_OFFSET, SCR_H - p1ScoreMsg.getGlobalBounds().height - (TEXT_OFFSET * 2)); - auto p1HudY = SCR_H - p1ScoreMsg.getGlobalBounds().height - TEXT_OFFSET - SPRITE_SIZE; - auto p1PieceOffset = p1ScoreMsg.getGlobalBounds().width + PAD; + const std::shared_ptr<std::vector<struct dice_t>> dice = + createAllDice((*textures)[DIE_0], (*textures)[DIE_1]); - sf::Text p2ScoreMsg(std::to_string(p2->score), font, 36); - p2ScoreMsg.setPosition(TEXT_OFFSET, (SPRITE_SIZE / ZOOM / 2.f) - (p2ScoreMsg.getGlobalBounds().height / 2.f)); - auto p2PieceOffset = p2ScoreMsg.getGlobalBounds().width + PAD; - auto p2HudY = TEXT_OFFSET / 2.f + SPRITE_SIZE; + sf::Sprite p1Score; + p1Score.setPosition(pos(0, SPRITE_ROWS - 1)); + makeNum(&p1Score, 0, textures); + + sf::Sprite p2Score; + p2Score.setPosition(pos(0, 0)); + makeNum(&p2Score, 0, textures); + + sf::RenderWindow window(sf::VideoMode(SCR_W, SCR_H), TITLE); + window.setFramerateLimit(60); + window.setVerticalSyncEnabled(true); sf::View view(window.getDefaultView()); view.zoom(ZOOM); view.setSize(view.getSize() * ZOOM); view.setCenter(view.getSize() / 2.f); - sf::Sprite s((*textures)[0]); - s.setPosition(0, 0); while (window.isOpen()) { sf::Event event; @@ -61,25 +160,55 @@ main() sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { window.close(); } + + if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) { + if (state == GameState::WAITING) { + window.setView(view); + auto mPos = window.mapPixelToCoords(sf::Mouse::getPosition(window)); + std::cout << "Pressed!: " << mPos.x << ", " << mPos.y << std::endl; + for (auto s : (*roll_sprites)) { + // zoom sprite bounds + if (s->getGlobalBounds().contains(mPos)) { + change_state(GameState::ROLLING); + break; + } + } + if (state == GameState::ROLLING) { + for (auto s : (*roll_sprites)) { + s->setColor(GREY); + } + } + + window.setView(window.getDefaultView()); + } + } } window.clear(BG_COLOR); window.setView(view); - int p_num = 0; - for (auto p : *(p1->pieces)) - { - p->sprite.setPosition(SPRITE_SIZE + PIECE_PAD + (p_num++ * SPRITE_SIZE), view.getSize().y - SPRITE_SIZE); + + for (auto s : *(board)) { + window.draw(s); + } + + // draw unused pieces + int p_num = (SPRITE_COLS / 2) - (p1->pieces->size() / 2) - 1; + for (auto p : *(p1->pieces)) { + p->sprite.setPosition(pos(p_num++, SPRITE_ROWS - 1)); window.draw(p->sprite); } - for (int i = 0; i < 7; i++) - { - sf::Sprite s((*textures)[P2_PIECE]); - s.setPosition(SPRITE_SIZE + PIECE_PAD + (i * SPRITE_SIZE), 0.f); - window.draw(s); + + p_num = (SPRITE_COLS / 2) - (p2->pieces->size() / 2) - 1; + for (auto p : *(p2->pieces)) { + p->sprite.setPosition(pos(p_num++, 0)); + window.draw(p->sprite); } + + render_dice(&window, dice, roll_sprites); + + window.draw(p1Score); + window.draw(p2Score); window.setView(window.getDefaultView()); - window.draw(p1ScoreMsg); - window.draw(p2ScoreMsg); window.display(); } |