diff options
-rw-r--r-- | .gitignore | 6 | ||||
-rw-r--r-- | CMakeLists.txt | 13 | ||||
-rw-r--r-- | README.md | 16 | ||||
-rw-r--r-- | helper.cpp | 106 | ||||
-rw-r--r-- | helper.h | 55 | ||||
-rwxr-xr-x | reformat | 1 | ||||
-rw-r--r-- | res/DejaVuSansMono.ttf | bin | 0 -> 340712 bytes | |||
-rw-r--r-- | res/ur.aseprite | bin | 0 -> 1107 bytes | |||
-rw-r--r-- | res/ur.png | bin | 0 -> 1125 bytes | |||
-rw-r--r-- | ur.cpp | 63 |
10 files changed, 260 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9620655 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.o +ur +Makefile +CMakeFiles +CMakeCache.txt +cmake_install.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..be11c85 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.13) +project(ur-sfml) +set(CMAKE_CXX_STANDARD 20) +set(EXECUTABLE_NAME ur) + +# setup SFML +set(SFML_LIBRARIES sfml-system sfml-window sfml-graphics) +find_package(SFML 2.5 REQUIRED COMPONENTS system window graphics) + +add_executable(${EXECUTABLE_NAME} ur.cpp helper.h helper.cpp) +target_link_libraries(${EXECUTABLE_NAME} ${SFML_LIBRARIES}) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/res DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/README.md b/README.md new file mode 100644 index 0000000..5e3913b --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# The Royal Game of Ur + +``` +[ ][ ] [ ][ ][ ][ ] +[ ][ ][ ][ ][ ][ ][ ][ ] +[ ][ ] [ ][ ][ ][ ] +``` +[Gameplay Wiki](https://en.wikipedia.org/wiki/Royal_Game_of_Ur#Gameplay) +[Play video](https://www.youtube.com/watch?v=WZskjLq040I) + +## How to play + +Two players - 7 pieces each - + + + diff --git a/helper.cpp b/helper.cpp new file mode 100644 index 0000000..c16cb3a --- /dev/null +++ b/helper.cpp @@ -0,0 +1,106 @@ +#include "helper.h" +#include <iostream> + +std::shared_ptr<std::vector<sf::Texture>> +loadTextures(const char* path) +{ + int sprite_width = SPRITE_SIZE, sprite_height = SPRITE_SIZE; + sf::Image textureAtlas; + if (!textureAtlas.loadFromFile(path)) { + std::cerr << "Unable to load textures from file: " << path << std::endl; + throw std::runtime_error("Unable to load spritesheet"); + } + + textureAtlas.createMaskFromColor(GLOBAL_MASK); + auto imageSize = textureAtlas.getSize(); + + auto textures = std::make_shared<std::vector<sf::Texture>>(); + + for (int y = 0; y < imageSize.y; y += sprite_height) { + for (int x = 0; x < imageSize.x; x += sprite_width) { + sf::Texture t; + t.loadFromImage(textureAtlas, + sf::IntRect(x, y, sprite_width, sprite_height)); + textures->push_back(t); + } + } + return textures; +} + +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"); + } + return font; +} + +std::shared_ptr<struct piece_t> +createPiece(int id, sf::Texture texture) +{ + std::shared_ptr<sf::Sprite> s = std::make_shared<sf::Sprite>(); + s->setTexture(texture); + + auto p = std::make_shared<struct piece_t>(); + p->id = id; + p->sprite = s; + + return p; +} + +std::shared_ptr<struct player_t> +createPlayer(sf::Texture texture) +{ + std::shared_ptr<struct player_t> player = std::make_shared<struct player_t>(); + player->score = 0; + player->pieces = + std::make_shared<std::vector<std::shared_ptr<struct piece_t>>>(); + for (int i = 0; i < NUM_PIECES; i++) { + player->pieces->push_back(createPiece(i + 1, texture)); + } + + return player; +} + +bool +clickedPiece(sf::Vector2i mousePosition, struct piece_t* piece) +{ + return piece->sprite->getGlobalBounds().contains(mousePosition.x, + mousePosition.y); +} + +bool +canMovePiece( + struct piece_t* piece, + int roll, + std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> myPieces, + std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> enemyPieces) +{ + int next = piece->position + roll; + + // rolled passed the exit + if (next > EXIT_SPACE) { + return false; + } + + // colliding with another piece + for (std::shared_ptr<struct piece_t> p : (*myPieces)) { + // cannot move onto your own piece + if (p->id != piece->id && p->position == next) { + return false; + } + } + + // can't attack in safe square + for (std::shared_ptr<struct piece_t> p : (*enemyPieces)) { + // cannot move onto a protected enemy piece + if (next == SAFE_SPACE && p->position == SAFE_SPACE) { + return false; + } + } + + return true; +} diff --git a/helper.h b/helper.h new file mode 100644 index 0000000..dbebfb6 --- /dev/null +++ b/helper.h @@ -0,0 +1,55 @@ +#ifndef UR_HELPER_H +#define UR_HELPER_H + +#include <SFML/Graphics.hpp> +#include <memory> +#include <vector> + +// BOARD LAYOUT [0, 1, 2, 3](start) [4,5,6,7,8,9,10,11](middle), [12,13](end) + +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 sf::Color GLOBAL_MASK(255, 0, 255, 255); + +struct piece_t +{ + int id; + int position; + std::shared_ptr<sf::Sprite> sprite; +}; + + +struct player_t +{ + int score; + std::shared_ptr<std::vector<std::shared_ptr<struct piece_t>>> pieces; +}; + + +std::shared_ptr<std::vector<sf::Texture>> +loadTextures(const char* path); + +sf::Font loadFont(); + +std::shared_ptr<struct player_t> +createPlayer(sf::Texture pieceTexture); + +std::shared_ptr<struct piece_t> +createPiece(int id, sf::Texture texture); + +bool +clickedPiece(sf::Vector2i mousePosition, std::shared_ptr<struct piece_t> piece); + +bool +canMovePiece( + std::shared_ptr<struct piece_t> piece, + int roll, + 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); +#endif + diff --git a/reformat b/reformat new file mode 100755 index 0000000..64a1a59 --- /dev/null +++ b/reformat @@ -0,0 +1 @@ +clang-format -i --style=Mozilla *.*pp diff --git a/res/DejaVuSansMono.ttf b/res/DejaVuSansMono.ttf Binary files differnew file mode 100644 index 0000000..9d65312 --- /dev/null +++ b/res/DejaVuSansMono.ttf diff --git a/res/ur.aseprite b/res/ur.aseprite Binary files differnew file mode 100644 index 0000000..6c75ad4 --- /dev/null +++ b/res/ur.aseprite diff --git a/res/ur.png b/res/ur.png Binary files differnew file mode 100644 index 0000000..cec8744 --- /dev/null +++ b/res/ur.png @@ -0,0 +1,63 @@ +#include <SFML/Graphics.hpp> +#include <iostream> +#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 = 5; +const int P2_PIECE = 6; +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 = .5f; +const float PAD = 32.f; +const sf::Color BG_COLOR = sf::Color(66, 47, 81, 255); + +int +main() +{ + const std::shared_ptr<std::vector<sf::Texture>> textures = + loadTextures(TEXTURE_PATH); + + 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); + sf::Text p1Text("Player one text here!", font, 24); + p1Text.setPosition(0.f, 0.f); + 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; + while (window.pollEvent(event)) { + if (event.type == sf::Event::Closed || + sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { + window.close(); + } + } + + window.clear(BG_COLOR); + window.setView(view); + window.draw(s); + window.setView(window.getDefaultView()); + window.draw(p1Text); + window.display(); + } + + return EXIT_SUCCESS; +} |