summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Enders <smenders@gmail.com>2021-01-17 15:40:44 -0500
committerStephen Enders <smenders@gmail.com>2021-01-17 15:40:44 -0500
commiteead8271c8ac12e75f52c58bf8a523f1d1897829 (patch)
treedc850bd9fdc6a26c70e405b34e9017ed6531933a
parent1dbd3c241ea6af43a26449e515438cc241de46ad (diff)
Rolling updates + Score change
Added state Added dice + roll button Updated blank tile graphic
-rw-r--r--helper.cpp165
-rw-r--r--helper.h55
-rw-r--r--res/ur.asepritebin1107 -> 1547 bytes
-rw-r--r--res/ur.pngbin1125 -> 1769 bytes
-rw-r--r--ur.cpp203
5 files changed, 380 insertions, 43 deletions
diff --git a/helper.cpp b/helper.cpp
index 8c68a28..d09318f 100644
--- a/helper.cpp
+++ b/helper.cpp
@@ -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 };
+}
diff --git a/helper.h b/helper.h
index 8626e23..950dbab 100644
--- a/helper.h
+++ b/helper.h
@@ -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
index 6c75ad4..a7a25eb 100644
--- a/res/ur.aseprite
+++ b/res/ur.aseprite
Binary files differ
diff --git a/res/ur.png b/res/ur.png
index cec8744..ff20a18 100644
--- a/res/ur.png
+++ b/res/ur.png
Binary files differ
diff --git a/ur.cpp b/ur.cpp
index c8ea723..1162c0b 100644
--- a/ur.cpp
+++ b/ur.cpp
@@ -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();
}