{"id":15663587,"url":"https://github.com/frankhale/roguely","last_synced_at":"2025-05-06T15:28:53.257Z","repository":{"id":53586300,"uuid":"341785770","full_name":"frankhale/Roguely","owner":"frankhale","description":"A simple Roguelike in SDL2/C++/Lua","archived":false,"fork":false,"pushed_at":"2025-02-11T16:12:09.000Z","size":29564,"stargazers_count":23,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-31T01:31:41.224Z","etag":null,"topics":["ecs","game","roguelike","sdl2"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frankhale.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-24T05:07:39.000Z","updated_at":"2025-03-27T02:41:14.000Z","dependencies_parsed_at":"2025-02-03T04:22:20.088Z","dependency_job_id":"87a3fa4f-e01d-484f-a0b8-866a5957b4b8","html_url":"https://github.com/frankhale/Roguely","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankhale%2FRoguely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankhale%2FRoguely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankhale%2FRoguely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frankhale%2FRoguely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frankhale","download_url":"https://codeload.github.com/frankhale/Roguely/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252712612,"owners_count":21792344,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecs","game","roguelike","sdl2"],"created_at":"2024-10-03T13:38:30.569Z","updated_at":"2025-05-06T15:28:53.238Z","avatar_url":"https://github.com/frankhale.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Roguely\n\n![Roguely Logo](assets/roguely-logo.png)\n\nRoguely is a very simple Roguelike in SDL/C++/Lua.\n\nThe game is using very simple cellular automata algorithm to generate maps.\nEach time you run the game you'll get a new map. Enemies spawn, move around\nrandomly and you can attack them to increase your score. You can pick up health\ngems and coins. Dead enemies can spawn a treasure chests which increase score.\nLook for the golden candle and if you collect it you will win the game.\n\nThere is no real point to the game. It was a fun exercise to create an engine\nand integrate Lua into it.\n\n## Screenshots (some are from the progression over the years of development)\n\nTitle Screen:\n\n![Title Screen](screenshots/title-screen.png)\n\nCombat Text:\n\n![Combat Text](screenshots/combat-text.png)\n\nCurrent Gameplay:\n\n![Current](screenshots/current.png)\n\nOlder gameplay showing how it evolved:\n\n![Old](screenshots/seventh.png)\n\n![Old](screenshots/sixth.png)\n\n![Old](screenshots/fifth.png)\n\n![Old](screenshots/fourth.png)\n\n![Old](screenshots/third.png)\n\n![Old](screenshots/second.png)\n\nMy first screenshot when I was able to render sprites:\n\n![Old](screenshots/first.png)\n\n## Videos\n\n[![Game Play (Part 2)](https://img.youtube.com/vi/Bs1GXWLNYok/0.jpg)](https://www.youtube.com/watch?v=Bs1GXWLNYok)\n\n[![Game Play (Part 1)](https://img.youtube.com/vi/IOBuFlfgCSE/0.jpg)](https://www.youtube.com/watch?v=IOBuFlfgCSE)\n\n## Building\n\nThis code uses `vcpkg` and for dependencies management and `cmake` to build.\n\nYou can get `vckpg` here: [https://github.com/Microsoft/vcpkg](https://github.com/Microsoft/vcpkg)\n\nRoguely has the following dependencies which are managed by `vcpkg`:\n\nIn order to build you must install these dependencies:\n\n- SDL2\n- SDL_image\n- SDL_mixer (with mpg123 support)\n- SDL_ttf\n- Lua\n- Sol2\n- Boost\n- magic_enum\n- fmt\n\nYou may want to have a look at the CMakePresets.json file to see if it needs \nupdating, specifically the location of `vcpkg`.\n\n## How to use the game engine\n\nThis engine provides a simple Entity Component System and exposes that to Lua.\nSince this engine uses SDL2 it also exposes several SDL2 functions to Lua to\nmake creating grid turn based games easier. The engines primary design is to\nmake creating grid turn based games easier.\n\nThe engine expects that the `roguely.lua` file will have a global table called\n`Game` which at the least defines the following properties:\n\n```lua\nGame = {\n  window_title = \"Roguely (2023 Edition) - A simple Roguelike in C++/Lua/SDL2\",\n  window_icon_path = \"assets/icon.png\",\n  window_width = 1280,\n  window_height = 640,\n  map_width = 100,\n  map_height = 100,\n  spritesheet_name = \"roguely-x\",\n  spritesheet_path = \"assets/roguely-x.png\",\n  spritesheet_sprite_width = 8,\n  spritesheet_sprite_height = 8,\n  spritesheet_sprite_scale_factor = 4,\n  font_path = \"assets/NESCyrillic.ttf\",\n  soundtrack_path = \"assets/ExitExitProper.mp3\",\n  logo_image_path = \"assets/roguely-logo.png\",\n  start_game_image_path = \"assets/press-space-bar-to-play.png\",\n  credit_image_path = \"assets/credits.png\",\n  sounds = {\n      coin = \"assets/sounds/coin.wav\",\n      bump = \"assets/sounds/bump.wav\",\n      combat = \"assets/sounds/combat.wav\",\n      death = \"assets/sounds/death.wav\",\n      pickup = \"assets/sounds/pickup.wav\",\n      warp = \"assets/sounds/warp.wav\",\n      walk = \"assets/sounds/walk.wav\"\n  },\n  entities = {\n    player = {\n      components = {\n          sprite_component = {\n              name = \"player\",\n              spritesheet_name = \"roguely-x\",\n              sprite_id = 15,\n              blink = false,\n              render = function(self, game, player, dx, dy, scale_factor)\n                  -- handle sprite player render here\n              end\n          },\n          position_component = { x = 0, y = 0 },\n          stats_component = {\n              max_health = 50,\n              health = 50,\n              health_recovery = 10,\n              attack = 5,\n              crit_chance = 2,\n              crit_multiplier = 2,\n              score = 0,\n              kills = 0,\n              level = 0,\n              experience = 0,\n          },\n          healthbar_component = {\n            -- handle render of health bar\n          },\n          tick_component = {\n            -- handle what occurs during a game tick (every one second)\n          }\n      }\n    }\n  }\n}\n```\n\nWhen games are started up the engine first looks to make sure required\nproperties are in the `Game` table and then it calls `_init()`. This function\ncan be used to setup your game. You can spawn entities, set up your maps, etc...\n\nIt's expected that during the intialization you will add various system\nfunctions that will be called in order to handle game entities.\n\nFor instance:\n\n```lua\nadd_system(\"render_system\", render_system)\nadd_system(\"keyboard_input_system\", keyboard_input_system)\nadd_system(\"combat_system\", combat_system)\nadd_system(\"leveling_system\", leveling_system)\nadd_system(\"loot system\", loot_system)\nadd_system(\"tick_system\", tick_system)\nadd_system(\"mob_movement_system\", mob_movement_system)\n```\n\nSystems are just functions that look like:\n\n```lua\nfunction keyboard_input_system(key, player, entities, entities_in_viewport)\nend\n```\n\nHave a look at `roguely.lua` to see how more about how to use the engine.\n\n## Lua APIs\n\n`get_sprite_info` - Returns a Lua table with information about sprites in a\nsprite sheet.\n\n`draw_text` - Draws white text to the screen.\n\n`draw_text_with_color` - Draws text to the screen with a specific color.\n\n`draw_sprite` - Draws a sprite to the screen.\n\n`draw_sprite_scaled` - Draws a sprite to the screen scaled by a factor.\n\n`draw_sprite_sheet` - Draws a sprite sheet to the screen.\n\n`set_draw_color` - Sets the draw color.\n\n`draw_point` - Draws a point to the screen.\n\n`draw_rect` - Draws a rectangle to the screen.\n\n`draw_filled_rect` - Draws a filled rectangle to the screen.\n\n`draw_filled_rect_with_color` - Draws a filled rectangle to the screen with a specific color.\n\n`draw_graphic` - Draws a graphic to the screen.\n\n`play_sound` - Plays a sound.\n\n`get_random_number` - Returns a random number.\n\n`generate_uuid` - Returns a UUID.\n\n`generate_map` - Generates a map using a cellular automata algorithm.\n\n`get_random_point_on_map` - Returns a random open point on the map (eg not a\nwall).\n\n`set_map` - Sets the map.\n\n`draw_visible_map` - Draws the visible map (eg. what's visible in the current\nviewport).\n\n`draw_full_map` - Draws the full map (great for minimaps).\n\n`add_entity` - Adds an entity to the game.\n\n`remove_entity` - Removes an entity from the game.\n\n`remove_component` - Removes a component from an entity.\n\n`get_component_value` - Returns the value of a component (deprecated).\n\n`set_component_value` - Sets the value of a component (deprecated).\n\n`update_player_viewport` - Updates the player viewport.\n\n`get_text_extents` - Returns the width and height of a string.\n\n`add_system` - Adds a system to the game.\n\n`get_random_key_from_table` - Returns a random key from a table.\n\n`find_entity_with_name` - Returns an entity with a specific name (finds based on starts with).\n\n`get_overlapping_points` - Returns a list of points that overlap with a given\npoint.\n\n`get_blocked_points` - Returns a list of points that are blocked (eg. walls).\n\n`is_within_viewport` - Returns true if a point is within the viewport.\n\n`force_redraw_map` - Forces a redraw of the map.\n\n`add_font` - Adds a font.\n\n`set_font` - Sets the font.\n\n`get_adjacent_points` - Returns a list of points that are adjacent to a given\npoint (up, down, left and right).\n\n`map_to_world` - Converts a map point to a world point.\n\n`set_highlight_color` - Sets the highlight color.\n\n`reset_highlight_color` - Resets the highlight color.\n\n## License\n\nMIT\n\n## Credits for Audio\n\nMusic track `Exit Exit Proper - Pipe Choir` from:\n\n- [http://www.pipechoir.com/](http://www.pipechoir.com/)\n- [https://soundcloud.com/pipe-choir-three](https://soundcloud.com/pipe-choir-three)\n- [https://freemusicarchive.org/music/P_C_III](https://freemusicarchive.org/music/P_C_III)\n\nCreative Commons License: \u003chttp://www.pipechoir.com/music-licenses.html\u003e\n\nThe sounds in the `assets/sounds` folder came from [https://opengameart.org/](https://opengameart.org/)\n\n## Author(s)\n\nFrank Hale \u0026lt;\u003cfrankhaledevelops@gmail.com\u003e\u0026gt;\n\n## Date\n\n11 Feb 2025\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankhale%2Froguely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrankhale%2Froguely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrankhale%2Froguely/lists"}