Posts tagged: gamedev
Ristretto Physics System GET? #7
Ran into several random roadblocks over the last week that were filtering me for a while, but we're getting somewhere.

Apologies in advance, this post is going to be entirely nerdly, slightly whiny, otacon shit.

¥animation system, GET!

As sketched out in >>4 the animation system is based on a animation subclass of timer which holds a table of animation states and modifies the active sprite slot based on those states, then an angled subclass which just hotswaps the entire animation table based on the character's angle relative to the camera. The system is fairly spartan, with each animation frame being a separately loaded image file, but whatever, it was super easy to implement, and should be flexible for expanding later.

¥physics system, GET! *Kind of.

Basic entities just have a x/z coordinate and are drawn at the height of their tile, to get a y-coordinate that means anything I had to implement a physics/collision system. Rather than simulate constant forces, I chose to abstract "impulses" as decaying bursts of velocity on tangible entities.
In theory this could allow for more "physical" feeling movement since we could simulate individual footfalls rather than modeling characters as sliding boxes. In practice simulating long strides feel godawful, in part because I chose to have impulses decay according to a geometric series so either the decay is too fast and it feels like you're glitching into the air, or the decay is too slow and it's like sliding on ice. I could change the decay function but I think the problem's more fundamental: you can't have precise player movement if all your strides are a fixed, wide, length. You'd have to do a ton of analysis on the player's keystrokes to figure out exactly how long the stride should be. Which sounds fucking hard.
If I set the stride length to like 2 ticks or something short like that all of this is basically negligible and it just gives entities a bit of ramp-up when moving which feels fine, so I'll just leave it as is for now. I do like the idea of simulating footfalls though...

Anyways, none of this shit is what took me a week implement, that's the fucking collision detection's fault. Draw a line from an entity's current position to it's next position, see if it hits a wall/floor, and cut it's movement off there if so. "Easy".
I got upset enough that I don't even fucking remember what filtered me for so long. Looking sat my notes, I wasted a a some time because I somehow forgot the non-parametric equation of a line breaks down at/near vertical and floats aren't precise enough to test for degenerate values, I was calculating X/Z and Y collisions at the same time so the floor collision always blocked any sideways movement while grounded, wall clipping caused entities to get stuck, there were some some other degenerate floating point cases. The code I wrote looks fine in retrospect, clever, even, but this is after I had copied and modified the code function by function into another file.

I could show off that the "math" core of the grid hitscan code is only 30 lines, and fairly brief lines at that, if maybe superficially inscrutable. I found a lot of refernces to "DDA" and Breshnam's algorithm when I was looking around for this sort of thing but both are centered around the imperative for loop, which isn't at all idiomatic in Factor. My implementation just straight up solves the parametric form of a line q=tdq+q0 (where q represents {x,y,z} and t an arbitrary value along that line) for t for all integer intersections of x and z between two end points, then computes the xyz coordinates of each, and we get a bunch of other helpful words for dealing with 3D lines we can reuse elswhere.
*It's technically 34 counting my combinator that's just a modification of Factor's base spread with call replaced with call-effect to work on runtime quotations.

The rest is just interpreting the results into tilemap collisions, checking some edge cases, and actually applying the results to the world. There's still room for improvement, I'd rather entities slide along walls than simply brake into them as they do now, and there's probably some way to get the sprite on top of the front-facing side of a quad so you can't see it visibly clipping inside of a tile.

¥Shooting system...ah, eto, bleh.


This hitscan code should be reusable for a shooting system, so I wanted to try implementing that quickly just to see
it in action, took me a day to figure out how to translate window clicks into target points, then another to figure out why the crosshair location was all over the place until I remembered my fucking camera yaw is below my camera translations in the matrix stack, so the relatively straightforwards math I had in place doesn't work unless I rearrange my camera code, at which point it becomes obvious I need to get that straightened out first. Still, if I just swap the translation and yaw in the rendering code (and break movement in the process) it does, in fact, work exactly as expected.

Fuck, I really didn't want to do camera code.
Mon, 30 Mar 2026 15:26:50 GMT
Ristretto Level Editing & Engine Theory #4
Got some more progress done this week, albeit slowly, and implemented a tile material system and parts of a UI for a proper level editor.

This needs to be polished and expanded a bunch more before I can brag about it though, so instead I feel like should show off some of the design for the engine itself, especially now that I have a Git (thing) up so you can see the whole of the code for yourself.

Being one of my projects, the engine is obviously written in factor, which (hopefully) means I can exploit it's Smalltalk-like Object system and first order functions to create an intuitive system for writing games in. The contents of a game world are contained within a "stage" tuple class, over which a few generic words allow entities to run custom code in response to the state of the world.
 ! From stage/stage.factor
GENERIC#: entity-action 1 ( entity stage -- quots )
M: entity entity-action 2drop { [ drop ] } ;

: internal-actions ( stage -- actions )
   dup entities>> over [ entity-action ] curry 
   map concat nip ; 

: apply-actions ( stage actions -- )
   2dup [ entities>> ] dip [ cleave( x -- ) ] curry each
   cleave( x -- ) ; inline

: do-actions ( stage -- )
   [ internal-actions ] [ actions>> ] [ V{ } >>actions ] tri
   -rot append apply-actions ;

One invocation of do-actions constitutes a tick, the desired actions of each entity are collected and broadcast to the stage as well as each of it's constituent entities as a method of type ( entity/stage -- ) . This might not scale with large numbers of entities but it should make things like e.g. hitboxes easy to implement later. It also makes separating pure code from user input piss easy since a gadget (Factor's basic UI graphical element) can just append it's user's desired actions to the action list before invoking do-actions.

In any case, this means we can should be able to write all of a game's pure code by simply defining the an appropriate set of generics and methods, with a system for developing a UI bugbear I've still to figure out. level-editor/level-editor.factor isn't really a game, but shows the basic idea, I really should make a syntax word to factor out that GENERIC#: x (blah), M: object xdrop pattern.

I wasn't really thinking about this when I was wrote this part of the code, but this also means I build up to a given level of complexity by iteratively subclassing over inherited interfaces.
¥ in english, otacon

In other words, to create a system for entity animation, I can write create a subclass of entity timer < entity and a bunch of associated actions and words just for keeping track of elapsed ticks, then a subclass animated < timer which uses those words to update it's sprite and expose new actions to change which animation it's using, and top of *that*, (etc). This feels superficially reminiscent of Monad Transformers...that's probably a bad thing, but I don't want to dwell on it.

* To actually make deep subclassing like this work on entities entity-action ( entity stage -- quots ) should probably be ( entity stage quots -- quots ), each subclass appending their own action to the quote list before invoking call-next-method, the baseline entity method simply dropping the first 2 arguments. As it stands, only the most specific method is called for any given entity.

This design also means I should be able to subclass over game *forms*, e.g.
beyond-citadel < fps-shooter < action-game < stage
Where we might define an action-game subclass with a system for games with continuous entity movement and collision physics, fps-shooter a limited form within that, providing some system for defining guns and shooting, and beyond-citadel a work within that form, extending or redefining the methods defined in fps-shooter as needed. This might be too granular, or not granular enough, but ideally these subclasses act as mini-rpgmakers for their respective forms. An obvious pitfall lies in treating these genres as a fetish in-of-themselves, not something too concerning given how easy it is to redefine methods or move up a superclass entirely, but something to be aware of.

Anyways, this is little too ambitious to start talking about now considering the state of the unfinished level editor you saw earlier in this post, so I'll probably leave that alone for a while until I can make a basic shooting range thing to see how well these ideas actually work in practice.
Thu, 19 Mar 2026 02:37:16 GMT
Ristretto Black Winged Angel + Juere Engine #1
I've been trying to develop a game/engine by myself for a while, and I've finally gotten things down to a point where I'm not just constantly regretting not just doing things in some prebuilt engine.

Visually, my end goal is for the engine to have games look like Nippon Ichi's (Disgea) or Sting's (Gungnir, Knights in the Nightmare) DS/PSP era games; 3D tile based environments and props, 2D sprite characters. A potentially much more expressive amount of space to work with than pure 2D, while also striking a good balance with the limits of what a 1guy dev could reasonably manage. Right now I've just about got all the bones for a basic level editor and not too much else, but it's feeling pretty promising so far.

As for game itself, I originally wanted to do basic 3rd person shooter in the spirit of Elona Shooter just to have a tech demo out, hence the ripped Elona assets for characters (just like this website wwwwww), but I'd have to draw my own characters anyways to get all the necessary angles for each sprite, so I'm thinking might as well go all out and make some short crazy touhou-like arcade thing. I'll have to develop the engine a bit further before I get too far off on the ideasguy rails, but I already have some character concepts I want to play with once I do.
Thu, 12 Mar 2026 15:17:23 GMT
Ristretto Interactive Level Editing, GET! #13
>>12
Gaaaah that's on me, I forgot to test the level-editor gadget before un-hardcoding the FOV.

Not only is there a fallback for that, you can now swap between tile-editing and physics modes from the level editor itself. Which I should've implemented earlier since it revealed several bugs (minor design mistakes, really) in the physics code--getting stuck in between flat tiles, falling through tiles. Pretty sure I know how to fix these, but I'll leave that for tomorrow.

LLMs really have no idea how to deal with Factor since there's no stackoverflow posts for them to scrape lol, even the fancy ones I get for free with Kagi will start hallucinating almost instantly if you ask them about it. Maybe part of that is just the more "abstract" model of combinator-centric programming too--but in your case, you just missed a vocabulary dependency (generic). That's what the Auto-Use button is for.

Factor has some unfortunately awkward error messages, but the Traceback and Walker tools usually make up for that. Maybe I'll rev up the programming thread in /dilletante/ again soon so I can write some guides on it.
Fri, 3 Apr 2026 04:50:59 GMT
Ristretto bweh #14
Fixed those that, and entities now walk up shallow floor differences.

Also gravity now scales with airtime to simulate constant acceleration of real gravity.
I ended up rewriting the collision code without any of the hitscan words I wrote about earlier, which is...fine. Not too upset about that since I'm sure they'll come in useful later. Some of the code ((apply-velocity)) became a lot uglier, which *is* upsetting. But I'll leave cleaning that up for after I figure out the camera and shooting system so I can say I have the start of a real game on my hands first.
Sun, 5 Apr 2026 00:55:52 GMT