I’ve had a dream to make Super Off-Road style game for Playdate for a long time - this looks really great!
That’s fun to play! It’s really nice to bump into things
Does cranking changes the angle where the car try to turn to? It was a bit difficult to have a feeling of the inner working of the controls.
In this version cranking CW/CCW is the same as pressing L/R. You get used to it… but I’m still trying other ways to map the crank to steering.
Mapping crank angle directly, like in my earlier lap gif, makes everything too easy and didn’t feel like driving. Maybe one for easy mode.
Finally found and fixed a bug in my collision code - needed to use math.abs() in one place to avoid some double negatives messing up collision rebound direction. D’oh!
And now it’s time to Play Ball!
lap count and checkpoints are back in. best lap time too
Fantastic! Getting some NES Super Sprint vibes (with a little Rocket League on the side!)
Well Done! Keep going!
Thanks Dan! That combo is fine by me.
A few of my influences for vibe:
- Atari's Sprint series
- including Badlands!
- Super Off-Road
I really love the unique and kind-of-forgotten perspective of those games.
And for gameplay:
- Mario Kart DS/Wii
- Power Drive
- Richard Burns Rally
- The Italian Job: LA Heist
- Pro Rally
- GTi Club
- ...so many more!
I don't get much time to work on this game, Daily Driver, but I'm pushing to get a vertical slice done relatively soon. I intend to do a thread for its development and I've been keeping notes and GIFs for it.
Bit of fun at lunch today.
Trying out some different things: a grab bag of scenarios
2 weeks have passed? Yikes.
I guess this looks like a looped GIF, but it’s not!
Woah no way! Any chance you’re gonna write about how you accomplished this? Are you capturing controls/state and just running it again with those inputs? This project is so impressive already-- you’re doing awesome work
Yes, it’s very little code (thanks to how the rest of things are put together) so I’ll write it up in the morning.
Until then: pause mode activated
that last slide where you stopped short of the dot for some reason the car looks a lot more nimble in this gif, a lot more controlled too. Did you change the specs? Also, are you thinking of adding multiple car types/unlocks or anything?
No changes to physics in a long time, but I guess on this level there are no collisions so you can go full throttle. Maybe I changed the tolerance for showing skid marks slightly, so there are less here? I’d have to double check.
I’ve already done multiple car types with different handling and sprites. Still more to do though.
I don’t show everything, got to leave some surprises, right?
Wanted to reply here because it pertains directly to this project–
In the modding thread you mentioned your workflow for 3D to sprite sheet @matt, I was wondering if you’d be able to go into more detail here about that. I’m interested in the car results you got for my own projects as pixel art is mysterious to my tiny brain while 3D modelling just makes sense. I would love to be able to take some 3D models I have made / animated and export them relatively easily for PD sprite scripts. You mentioned it briefly above this but if you’re willing, I’d love to hear a more detailed explanation of your workflow/tools.
Sure thing! I finished a new car last night and simplified my files and process a little more. I’ll put together a post today.
Caveat: part of my workflow uses Mac-only app Retrobatch https://flyingmeat.com/retrobatch/
Apologies for the delay, I took the plunge and upgraded to a Mac mini and 4K display so had to migrate my setup and then figure out why my workflow was broken (hint: retina!) compared to my old rMBP with non-retina display.
So, my workflow uses the following apps:
- OpenSCAD "The Programmers Solid 3D CAD Modeller"
- Retrobatch "a unique application for automating actions on multiple images at the same time"
- post-processing "greyscale and dithering tool" (I use my own realtime tool, but any image editor would do it to a degree, see this other thread)
This is so I can re-run a workflow at any point (maybe in a make file) which I often do during development. These become executable assets, of sorts, in my project.
- define 3D models (I get a feeling like coding CSS in a strange way)
- animate the model spinning through one 360-degree rotation
- dump frames out as PNG files
Here's the model definition to try out: car.scad · GitHub
I love building 3D this way, it's kind of like LEGO. I use basic geometric building blocks (cube, sphere, cylinder, polygon, etc) and some boolean operations (difference, intersection, union). There are some other cool things (hull, minkowski). I have the commands in Dash.app alongside the Playdate SDK docs.
This is what the model looks like with all the blocks I have used to make it visible at once.
My particular approach is subtractive — kind of like sculpting — I start with large blocks and cut away at them using other shapes and the difference function. When finding the exact placement for a block I use the # precedent which makes the blocks show up as semi-opaque red blocks.
I colour each block in a one or two shades of grey, black and white. This is to help with the conversion to 1-bit later on. It's not so obvious here as the lighting makes the colours look many different shades - for example the wheels are black with white centre but look grey here.
Using some simple programming constructs and variables I can add booleans to trigger different states, I use this for angled front wheels and tilted car body.
And also to set the distance and rotation of the camera relative to the model when in animation mode. In this mode I enter a speed (doesn't matter but higher the better) number of frames = 32, and the tick the box to dump the images. The tick disappears when the images are all done.
I also rendered the skid marks, car shadow, and some other elements.
There is a lot that is annoying about this app
- not retina-optimised (so I run it in Low Resolution, set using Get Into on the app) [no longer true in 2022]
- runs maxed out on a single core [run it from the command line for parallelism/multi-core]
- doesn't have configurable lighting (I'd prefer uniform or no lighting)
- Qt framework app so not really macOS-native
...but I still use it! I am not aware of anything else quite like it.
- process dumped frames x 32
- once each for left, right and straight directions
- stitch processed frames together as spritesheets x 3
- we end up with three long images
- stitch 3x spritesheets together
- we end up with our final image ready for post-processing
Edit: since writing this post I've been able to condense this process into 1 single workflow that executes much faster. See further down this thread.
For each batch all I need to do (now the they are set up!) is set source and destination folders and press the go button. As time goes on I refine these, so at some point I'll make it so that it automatically gets the filename of my current model. Not a priority right now though.
Post-processing (details vary per car sprite)
- greyscale using one of many algorithms
- reduce colours to 1-bit with dithering or by threshold level
The grey shades that I applied to my model in OpenSCAD give an element of control during this conversion process. Greys can be pushed either way, towards black or white, depending on my need with the specific model I am working on. In this instance I desaturated the greys which blows them out to nearer white. And then I chose to threshold to reduce to b/w. I also have the wheels as a separate finished image so I don't have to worry if their detail is lost during this phase, I can just paste over the accurate/finished wheels.
Final result, unedited:
I would later touch up the sprite by hand to reinforce any details I think have been lost. I use Piskel for edited sprites because it has really nice sprite sheet support, drag and drop loading, and quick and versatile exporting.
holy batman! What a great write up, thank you so much for sharing!!
I find it fascinating that you use OpenSCAD to program your models instead of something like blender, but I can also see how small, more simple objects might be easier to program than model by hand. I’ll have to dig into OpenSCAD more than I have in the past (for 3D printing stuff).
Looking at your explanation for Retrobatch, I wonder how much could be accomplished using vanilla Automator actions. Certainly a cool app, I never knew it exited!
Thank you again for the explanation, you’re doing great things with this project and I continue to look forward to your progress updates
I shouldn’t be this surprised but that is an impressive number of sprites for one car and explains why your animations are so smooth. How are you handling your animation tree so smoothly @ 50fps??
Keep up the awesome work!
Confession time: I have never used Blender. The barrier to having to learn it is always too great when I can just carry on with my existing tools. You know?
No idea about Automator, but I think it would be more limited and way more difficult than Retrobatch. I mean, you could do all this on the command line if you wanted to. But why would you when there’s a great app like Retrobatch?
32 is a number that is a leftover from a different prototype and it’s stuck. I guess it should really be 36? or 24? or 18?. But it’s too late now! Actually it would be relatively easy to change but I have bigger fish to fry.
Handling the animation changes - there is no tree! I don’t do anything special other than set the frame number based on the angle when that changes, but only actually change the sprite image if it needs changing. It’s so very important to do all you can to not update or move sprites unless you actually need to. Minimise drawing!
The animations alone could run at 99fps — it’s anything that causes more drawing which slow things down. Collisions, not because they are computationally heavy, but because they cause a lot of sprite updates - which means drawing moving things - to happen. I’m working hard to maintain 60fps on device (50fps in simulator for… reasons) and am excited I’ve managed to get here.
I’ll have a think about posts for other aspects of my game.