From 9ccf3248f2d9cd2cb9bd5a4826e8d0409f98f3d1 Mon Sep 17 00:00:00 2001 From: Stephen Enders Date: Tue, 5 Jan 2021 00:30:53 -0500 Subject: Initial commit - Rendering --- .gitignore | 6 +++ CMakeLists.txt | 13 ++++++ README.md | 16 ++++++++ helper.cpp | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ helper.h | 55 +++++++++++++++++++++++++ reformat | 1 + res/DejaVuSansMono.ttf | Bin 0 -> 340712 bytes res/ur.aseprite | Bin 0 -> 1107 bytes res/ur.png | Bin 0 -> 1125 bytes ur.cpp | 63 +++++++++++++++++++++++++++++ 10 files changed, 260 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 helper.cpp create mode 100644 helper.h create mode 100755 reformat create mode 100644 res/DejaVuSansMono.ttf create mode 100644 res/ur.aseprite create mode 100644 res/ur.png create mode 100644 ur.cpp 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 + +std::shared_ptr> +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>(); + + 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 +createPiece(int id, sf::Texture texture) +{ + std::shared_ptr s = std::make_shared(); + s->setTexture(texture); + + auto p = std::make_shared(); + p->id = id; + p->sprite = s; + + return p; +} + +std::shared_ptr +createPlayer(sf::Texture texture) +{ + std::shared_ptr player = std::make_shared(); + player->score = 0; + player->pieces = + std::make_shared>>(); + 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>> myPieces, + std::shared_ptr>> enemyPieces) +{ + int next = piece->position + roll; + + // rolled passed the exit + if (next > EXIT_SPACE) { + return false; + } + + // colliding with another piece + for (std::shared_ptr 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 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 +#include +#include + +// 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 sprite; +}; + + +struct player_t +{ + int score; + std::shared_ptr>> pieces; +}; + + +std::shared_ptr> +loadTextures(const char* path); + +sf::Font loadFont(); + +std::shared_ptr +createPlayer(sf::Texture pieceTexture); + +std::shared_ptr +createPiece(int id, sf::Texture texture); + +bool +clickedPiece(sf::Vector2i mousePosition, std::shared_ptr piece); + +bool +canMovePiece( + std::shared_ptr piece, + int roll, + std::shared_ptr>> myPieces, + std::shared_ptr>> enemyPieces); + +std::vector getLegalMoves(std::shared_ptr activePlayer, std::shared_ptr 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 new file mode 100644 index 0000000..9d65312 Binary files /dev/null and b/res/DejaVuSansMono.ttf differ diff --git a/res/ur.aseprite b/res/ur.aseprite new file mode 100644 index 0000000..6c75ad4 Binary files /dev/null and b/res/ur.aseprite differ diff --git a/res/ur.png b/res/ur.png new file mode 100644 index 0000000..cec8744 Binary files /dev/null and b/res/ur.png differ diff --git a/ur.cpp b/ur.cpp new file mode 100644 index 0000000..c39c048 --- /dev/null +++ b/ur.cpp @@ -0,0 +1,63 @@ +#include +#include +#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> textures = + loadTextures(TEXTURE_PATH); + + const std::shared_ptr p1 = + createPlayer((*textures)[P1_PIECE]); + + const std::shared_ptr 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; +} -- cgit v1.2.3-54-g00ecf