I sectioned each frame is to five numbers, called observations: the dinosaur’s normalized height and vertical velocity, the horizontal distance to the next obstacle, and that obstacle’s width and height. It never receives pixels or any timing rules.
The action space has only two choices: do nothing or jump. A small MinGRU policy carries state from one frame to the next, then selects one of those actions from the current observation and its memory.
Passing a cactus earns a reward, and both jumping and colliding have associated penalties. The jump penalty discourages repeated jumping without prescribing when a jump should happen (this separated the demo you see from just a dinosaur which always stood still or jumped all the time - refer to previous versions 👇). Training ran for 10 million environment steps with PufferLib; the browser loads the resulting checkpoint directly.
Next
This first version intentionally keeps the trained task fixed: one obstacle type, one speed, autonomous playback, and a 2.7 MB generic resource bundle.
I intend next iterations to let visitors "throw" obstacles or change the playback speed. Also, I plan to make each episode in which a user gets the dino to loose, to improve the next iteration of the demo - making loosing harder each time. Different dino poses and obstacle types are also features to be added.
A huge shoutout to the PufferLib team for making such an awesome resource. Go and check their website 🐡.
Notes
June 29, 2026
I really like Yacine's way to blog about progress in projects. I aim to do the same here: everyting related to pufferosaurus and the progress made from day to day, will be written down here in the form of a daily log. Main content explaining the project will be kept at the top of the page for an easy access to it.
Revisiting Andrej Karpathy's policy gradients before even thinking about messing with PPO and some other papers.