The next little game in the series where I make a fancy rogue game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
Zed A. Shaw d8400d0a76 Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
assets Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
docs Fix up the gitignor and bring in the ragel manual for safe keeping. 1 month ago
scratchpad Now have more fancy rooms with different floors to play with. 1 week ago
scripts Fix for OSX build. 4 weeks ago
shaders Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
tests World builder now loads the tile map json and usese the keys to figure out how to randomize the floor configurations. 1 week ago
tools Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
wraps Update to SFML 2.6.2 1 week ago
.gdbinit Basic tile map implemented. 2 weeks ago
.gitignore Fix up the gitignor and bring in the ragel manual for safe keeping. 1 month ago
.tarpit.json Ignore more irrelevant things. 3 months ago
.vimrc_proj Now have a configurable displayable tilemap to do better tiles. 2 weeks ago
LICENSE Initial commit 3 months ago
Makefile A barely working tool to find font characters and pick their color. 4 weeks ago
README.md More complete readme but need a screenshot. 1 month ago
ansi_parser.cpp Designer is working great now, and this fixes a bunch of things about the mouse. 3 weeks ago
ansi_parser.hpp Upgraded to the latest winlibs/gcc 14. 2 weeks ago
ansi_parser.rl Designer is working great now, and this fixes a bunch of things about the mouse. 3 weeks ago
collider.cpp Light works with multiple sources and strengths, walls are faked out but I think I may keep that to make it easier to play. 1 month ago
collider.hpp Light works with multiple sources and strengths, walls are faked out but I think I may keep that to make it easier to play. 1 month ago
color.hpp Change the color namespace to ColorValue. Need to come up with the organizational theme for the code. 1 month ago
combat.cpp Almost working save sytem but the data I store is totally wrong. I need to also save the entity IDs being used and map them to the components. 2 months ago
combat.hpp First coverage reports. Tests don't get near enough coverage but running the program does. 1 month ago
components.hpp World builder now loads the tile map json and usese the keys to figure out how to randomize the floor configurations. 1 week ago
config.cpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
config.hpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
constants.hpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
dbc.cpp Initial commit that has most of what I need. 3 months ago
dbc.hpp Initial commit that has most of what I need. 3 months ago
dinkyecs.hpp Fixing a stupid bug where it would crash because a fact wasn't in the world. 2 weeks ago
events.hpp Event system now accepts any data and the GUI receives simpler events with data for them. 2 months ago
flecs.wrap Brought in FLECS to play with, tomorrow we learn it. 3 months ago
fsm.hpp Conver to using \ for member variables in classes. In structs just use the name. 3 months ago
gui.cpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
gui.hpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
lights.cpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
lights.hpp Lighting is working way better and now for world generation work. 1 week ago
main.cpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
map.cpp World builder does a better job of placing entities in rooms and not walls. 1 week ago
map.hpp fixed the map generator doing paths that hit the edge which made it look like the map was out of bounds. 1 week ago
matrix.cpp Lighting now uses pathing to determine where it can go, but _distance_ to determin strength. Looks way better. 1 week ago
matrix.hpp Lighting now uses pathing to determine where it can go, but _distance_ to determin strength. Looks way better. 1 week ago
meson.build Now have more fancy rooms with different floors to play with. 1 week ago
panel.cpp Designer is working great now, and this fixes a bunch of things about the mouse. 3 weeks ago
panel.hpp Designer is working great now, and this fixes a bunch of things about the mouse. 3 weeks ago
pathing.cpp Now using the box iterator everywhere I can before writing a flood iterator. 3 weeks ago
pathing.hpp A bit of late night work designing the little iterators. 3 weeks ago
point.hpp Lighting is now in its own class using the new Pathing class. This should allow me to make it more consistent and possibly make Pathing more efficient. 1 month ago
rand.cpp Just wrote my own entity system to figure it out. 3 months ago
rand.hpp Just wrote my own entity system to figure it out. 3 months ago
render.cpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
render.hpp Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
save.cpp Added a couple of test enemies to the game for the next stream. 1 week ago
save.hpp Removed the variable limit setting since it's never used and instead just have WALL_PATH_LIMIT. 1 month ago
sound.cpp Rendering code stripped out of the GUI code. 2 months ago
sound.hpp Rendering code stripped out of the GUI code. 2 months ago
status.txt Tinkering with a way to do modal UIs for things like inventory etc. 5 days ago
systems.cpp Lighting is working way better and now for world generation work. 1 week ago
systems.hpp Lighting is now in its own class using the new Pathing class. This should allow me to make it more consistent and possibly make Pathing more efficient. 1 month ago
tilemap.cpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
tilemap.hpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
tser.hpp Upgraded to the latest winlibs/gcc 14. 2 weeks ago
tser.wrap Stripped tser.hpp down to the essentials so I can study it. No base64 encoding, less than comparison (wtf is that for), and I may even remove the 'json' output. 2 months ago
worldbuilder.cpp Fixed worldgen to only use tiles without collision in filling rooms, then a couple more changes to lighting so that if the light is <= 1 it just assumes the base light strength which ends up looking nicer and more like the kind of light I want. 7 days ago
worldbuilder.hpp Now have more fancy rooms with different floors to play with. 1 week ago

README.md

An Homage to Rogue

When I was a kid I played a game that used only text characters in a terminal called [Rogue](https://en.wikipedia.org/wiki/Rogue_(video_game). This game ran in my little MSDOS computer using only the ASCII characters the computer supported. No graphics and I think no sound but I can't remember. Despite this very low quality graphical experience the game delivered an amazing game experience. Even today the term "roguelike" denotes certain qualities that come from the original Rogue:

  • Dying is permanent but each time you restart you'll retain some previous skills or equipment so the next run is easier.
  • However, it's only easier to the point where you previously died, as each level through the dungeon gets more and more difficult.
  • A randomly generated world (dungeon) that features a new experience every time.
  • A focus on mechanics rather than graphics, but creative use of the limited graphical characters to make the game playable.
  • This lack of graphics weirdly makes the game more imaginative because you have to fill in what's going on with your own imagination, similar to a game of Dungeons and Dragons.

This is why I chose Rogue as the basis for my first actual game in C++.

A "Classical" Game Development Education

In the world of art there's a concept of a "classical education," which means you learn to paint and draw using old methods meant to teach a realistic style. These methods are hundreds--maybe even thousands--of years old and work very well...assuming you have the patience. Learning to paint and draw like this is almost an art history lesson since not many people do art using these techniques anymore.

I'm planning to do my study of game development in the same way by making games in historic order. Rather than run off and start using Unreal Engine immediately I'm going to make an homage to each kind of game I played when I was younger. Each game I make will hopefully teach me both the history of Game Development and also a technique that's either very useful or long forgotten.

My little Rogue game is the first entry in this series.

It's Not 1980 Anymore

My goal is to maintain the constraint of "Text Only, but not Terminal Only." What I mean by this is I'll use only text glyphs for the graphics in the game but I won't restrict myself to the textual grid, layout, or traditional Terminal constraints. I'm rendering these characters using modern graphics capabilities that allow me to create a more fun experience.

For example, I code the whole UI in a Terminal UI (TUI) library named FTXUI but I render the ANSI terminal output of FTXUI into an SFML window using an ANSI Code Parser that renders to a Render Pipeline. This lets me render full Text UIs at one scale while rendering the map in a different scale and allow zooming.

I also use a full true color encoding so I can implement things like lighting effects and complex color changes. I even have sounds, simple camera shake effects when you take damage, and other things found in top-down games.

In addition to that, I'm not limited to one character per cell. Since I'm only treating characters as sprites I'm actually able to layer them in the same cell, so I can show weapons being held, damage effects, and other changes using character on the player or other entities.

Why Not Just Use Pixel Art?

I mean...I am...it just looks like text. An Homage doesn't mean you copy something exactly. It means you create something that's your own, but references or takes things from another artist's work. It's a respectful copy that doesn't really steal but instead pays respects to those who came before while still creating something new for the future.

In my game I'm using the constraint of "Text Only, not Terminal Only" to give me an artistic constraint and to keep the game an homage to all the Rogues that came before.

But also, I mean c'mon folks, it's 2025. We do have sound now.

Where's the LICENSE?

You don't need a LICENSE that gives everything away to thieving corporations just to publish your works online. Nobody makes artists, musicians, painters, photographers, or sculptors get a license before posting online, so why do programmers need one? You worried you'll get sued? Ok, so just put a disclaimer but why do you also have to give your hard work away for anyone to steal and profit from just so they don't sue you?

You don't, and no matter what the OSI says, nobody can sue you if they steal your code and cause a plane to crash. They would get sued for stealing your code and putting it in a plane, not you. Requiring only programmers to release their code with a license to avoid lawsuits creates a Chilling Effect on programmer free speech and that violates the First Amendment.

So this code isn't licensed, it's copyright by default. I'm publishing it using my free speech rights to express myself and that means you can look at it the same as if I posted a painting or an essay on my blog. I obviously can't sue you for just looking at it and playing the game because I published it so you can, but that doesn't mean you own shit. You can't resell it, fork it, nothing.

Just grab the code and play it. That's it. Tell people about it. Fair use says you can even record videos reviewing it and talking about it.

See? That's how Free Speech works. You don't need a LICENSE.

Build Instructions

On all platforms you'll need these components:

  • Meson -- which needs Python.
  • C++ Compiler -- Tested with Clang and G++. You can use my C++ Setup Guide which features an automated installer for Windows.
  • GNU make -- For the convenience Makefile. On Windows you should have this if you used my setup scripts. Otherwise winget install ezwinports.make will set you up.
  • git -- Which should be on almost every platform, and is installed by default with my Windows setup scripts.

Windows Instructions

I primarily develop in Windows using the above setup, so this should work the best. Open Windows Terminal and run these commands one at a time. Don't copy-past bomb this:

git clone https://git.learnjsthehardway.com/learn-code-the-hard-way/roguish.git

cd roguish

# ignore the errors the first time
./scripts/reset_build.ps1

# first compile takes a while
make

# this copies the binary so you can run it
make run

After that the game should be running. It'll be in different states depending on how far I've pushed it, but you should at least have two enemies, some loot that gives you a better torch, and a room with a light in it. Go find them.

Linux and OSX

Linux and OSX have the same requirements as Windows and almost the same install steps. The only difference is that once you get your developer tools installed then you only need Meson. Linux and OSX should have everything else you need or there's a package for it.

Once you have that installed you can run these commands:

git clone https://git.learnjsthehardway.com/learn-code-the-hard-way/roguish.git

cd roguish

# ignore the errors the first time
./scripts/reset_build.sh

# first compile takes a while
make

./builddir/roguish

You don't need make run because Linux and OSX are sane operating systems that don't lock every damn thing a process touches.

Other Platforms

No testing done on other platforms but let me know if you get it to build somewhere fun and I'll mention it.

Development Guide

You can look in the status.txt file for my informal TODO list of things to fix and make. I'm not really accepting contributions from others, but if you want to follow along then that's what I'm doing.

If you're just starting out in C++ or programming then the project is designed to be readable by someone who knows very little. Every file is small and should be easy to read. I don't use any insane tricks or weird C++ idioms. I also try to avoid too many external libraries so I'll use plain old std::vector and std::unordered_map rather than external libraries that might be faster. This is done on purpose so people (myself included) can learn about the basics of C++ and the STL.

I also don't do a lot of performance tuning or obsession over THE CACHE. Clean, simple, readable code is more important than squeezing 4% performance out of the code. I do however attempt to design things so that it doesn't do useless work because the fastest thing you can do in a computer is nothing. If I can architect away a performance issue and not make the code too complex then I'll do that instead.

That means if you have a suggestion for a micro-benchmark improvement that will dramatically boost performance, but the code is convoluted and hard to understand, then it won't work. If your suggestion is interesting and provides a massive boost then let me know and I'll check it out. But, I would also like statistics that show it's better, not just your word.

Known Bugs

  • Map Generation isn't refined enough so sometimes it makes a map with no path out. Just start it again.

Look in status.txt for more bugs that aren't as major as this.

OSX Build Notes

  • Quite a bad experience. Need to install Python, cmake, meson, and ninja all which are in homebrew but if you don't use homebrew then this is a problem.
  • You need to run the .command script in Application/your python that updates the SSL certs.
  • You have to give iTerm access to your keystrokes...because wtf it already has them?
  • This points out a problem that I'm getting the keys using FTXUI but should either get them from SFML or connect FTXUI to SFML's keyboard input events instead.
  • No actually this first run delay seems to be related to the security feature that blocks keyboard access on iTerm, so probably fixing that would speed it up.