Do you have a new .pdx for the latest firmware?
Not quite yet, Brian. Very soon though!
I want to finish a couple of small bits. Then I’ll build the latest code. Previously I’ve been lazy and recompiled the same old snapshot from end of July.
(and now for something completely different)
Sparrow-Solitaire.pdx.zip (231.6 KB)
- no game, just tile shuffle and layout
This is how things looked with hastily ripped and converted placeholder graphics, before I drew my own graphics from scratch.
playdate.menu:addOptionsMenuItem to provide (kinda) sub-menu options:
- undo move
- show hint
Added some satisfying mahjong tile sounds
- tile on table, lone
- tile on table, adjacent
- tile on tile, edge knock
- tile on tile, full
all with slightly randomised pitch so they don’t sound repetitive
Board Games a-go-go!
Mancala (work-in-progress, before sprites and animations)
Following up on the ability to display a shade of grey by flashing pixels very quickly (click the reply arrow above to see message this one is replying to; and some chat on the Discord) here is a demo!
Shadow.pdx.zip (19.0 KB)
- up/down/left/right change target frame rate
- A/B to toggle movement of the ball
- left ball has flashing shadow
- right ball has static dithered shadow
- the effect is only viewable on device
- fps needs to be >60, higher the better, to get good results
- added a very rough/quick method of trying to keep the ball speed constant-ish
it looks like below, but ball shadow is flashing to make it look like grey (on device!)
ps: i didn’t have time to create any new sprites so you have a small ball plus shadow, but the code will cope if you replace the 3 cell image table with something of a different dimension
I had a bit of a eureka moment with my car shadows in Daily Driver.
Since very early on shadows in Daily Driver have just been simple rectangles: one size fits all, rendered from a single 3D model, and post-processed to add dithering. MVP, you know? Over time I decided to do multiple shadows, one each for short cars and long cars.
Sometime later I threw caution to the wind and decided to render per-car shadows. However, the OpenSCAD
projection() command that I was using was so slow! In fact it zapped my desire to finish implementing the feature. Instead, I let it sit for many months.
Recently, I picked things up again to get the a new trailer and demo out. And then it hit me, that if I flatten a car on the z-axis—as if Looney Tunes dropped a heavy weight on it—then that flat thing will be enough of an equivalent to a shadow for my use. So I did just that and the results were great, and more importantly very quick to render!
So I went all in and decided to not only render one shadow per-car but to render shadows for each individual frame. So now the direction of the front wheels and details of the body shape are reflected in the shadow. It might sound like a small thing but it really makes a big difference. You can see old vs new shadows in the image carousel below.
It’s in situations like these that I’m really proud I put a ton of early effort into the tooling and build process that generates my sprites.
During the shadow rendering changes I was generating new sprites quite frequently, and I quickly realised that my mess of shell scripts just wasn’t a good enough system to be used in anger. I would have to call my scripts manually, with a variety of parameters, and remember a bunch of stuff unique to each script.
So I spent a day converting the script system into a Makefile, with rules for:
I also improved the scripts to make them touch all their output files with the last-modified timestamp of the original 3D model, meaning the scripts could become self-aware and know which output files are up-to-date and which need re-rendering.
With this system I can generate a full set of renders of all vehicles in ~minutes, or render just a single car in ~seconds. This is such a huge time saver and has enabled me to iterate on car designs more quickly and easily than ever before. I’m already seeing the gains in much better sprites.
Believe it or not this was the first Makefile I’ve ever needed to write from scratch. I knew enough about them to know that they would be a good fit for this task, and it was fun to learn more about something I only knew in passing.
I love this! Genius.
I love OpenSCAD “the programmer’s solid 3D CAD modeller”, despite its idiosyncrasies. One of the quirks that causes me most pain are the lack of controls for scene lighting in the Preview render. Unfortunately, I use that very Preview render as my main output!
This lighting issue manifests as shadows cast on the model. As I rotate the car some white “highlight” elements become darker. At this point the model is made up of many more shades of grey than I’d like.
The problem escalated when I take the Preview renders and convert them to 1-bit monochrome (black and white) ready for display on Playdate . I use a simple threshold conversion where any pixels darker than the threshold value become black, and any lighter become white. The highlight elements that have been cast in shadow are now grey and in many cases after the threshold conversion they end up as black pixels when they should be white. The net visual result is a loss of detail and flashing elements as they disappearing from the model on certain frames.
My first attempt at solving this problem was to set model-specific threshold levels. This worked to a degree but there were still elements that would flash on and off as the car rotated, with headlights being the most noticeable. Whilst I lived with the issue for a long time it always bothered me as it did make the sprite feel buggy. Deep down I knew that the results could be better. However, looking at the OpenSCAD development roadmap made it clear that any improvements would have to come from me.
Eventually I realised that if black pixels are more reliably rendered then why don’t I take advantage of that and render the model in opposite colours so that the highlights are now black. After rendering I could simply negate the colours in the resulting image and the highlights would become white again. I tried a quick test and the results were good!
Of course this means an additional render stage is added to my workflow, but that’s of little consequence since the Makefile is doing all the hard work. I also had to make some changes to my render scripts so that the normal and negative images were composited together into the final image. The resulting sprites have no flashing elements, maintain more fine detail, and appear a lot more solid as a result. Excellent!
Afterwards it struck me that this process is similar to HDR photography where multiple photographs are combined to increase the dynamic range in the final image. So, just for kicks, I’m referring to this technique as HDR 1-bit rendering .
(Refresh the page so these are in sync)
Old rendering workflow: note the disappearing headlights
New rendering workflow: headlights are present and correct
Foot is back on the pedal!
I’ve introduced a third colour that can be isolated the same way as the highlights. It allows me to specify details that will be dithered in a pattern of my choice. Here I’ve used it for the rear/boot grille! Blog post soon.
A new post about how I render models in Red, Green & Blue …and then split the image into Channels to make it easy to composite 1-bit sprites with a lot of detail and custom dither patterns from a single render.
How about now? It’s looking so good!
Yes! Today's the day.
I had tried to get something wrapped up (excluding and stripping out a bunch of stuff) for the update video day, but ran out of time.
Anyway! Here we go:
new build! 14 Aug 2021
Delete any old builds before installing.
Still not representative of where I am right now with the game, I’ve cut a bunch of things, but it shows my progress since the last demo (July/August 2020!). It also includes improvements that I’ve added since I sent my footage in for the update video:
- better car rendering
- rotating wheels
- object-object collision
- 90 renders per rotation (previously 32)
- multiple types of crank control
Would love to know your thoughts! Especially regarding the Additional Collisions option.
~60seconds, 462 KB
- any combination of d-pad, A/B, Crank
- d-pad U/D, or A/B = accel/brake
- d-pad L/R, or Crank = steer left/right
- while using the crank L/R are disabled (to prevent fighting against the crank, I may change that at some point)
- press and hold both A and B, pressed in that order, to reverse (I'll make this easier, too)
- options (full debug menu)
- additional collisions (car aim affected during collision)
- car (let me know your favourite!)
- clear skid marks
- crank sensitivity
- crank style (constant, momentary, analogue, directional)
- display invert
- garbage collect
- garbage collect time
- set frame rate (only on device)
- set z-index always
- show collider
- show frame rate
- show frame stats
- show hud
- show inputs
- show wheel overlay
- steering assist (slowly nudges aim towards certain angles after you stop steering)
- swap a/b
- swap left/right
- to editor
- reset stage
- select stage (1–42)
- runs at 60fps on device (50fps in Simulator)
- 42 different stages (car demos, cone layouts, sports, random)
- 35 vehicles (not final selection)
- includes level editor
- replays currently broken? need to regression test
Debug Keys for game (simulator only):
- C = reset stage
- E = open level editor
- i = toggle input display
- J = jump!
- L = list all sprites
- N = next stage
- P = play replay data
- R = print replay data to console
- T = toggle telemetry
- U = toggle frame limiter
- V = cause car to spin out
- W = print all objects to console
Controls for editor (simulator only):
- d-pad = move cursor
- A = place an object or increment object under the cursor
- B = toggle precision mode
- cursor moves in smaller increments (5px vs 20px)
- drag/move item under cursor
- A = delete item under cursor
Debug Keys for editor (simulator only):
- B = new blank stage
- D = dump stage JSON to console (for copy and pasting)
- E = exit level editor
- O = output stage as "m-edited.json" in game Sandbox directory
- Z = undo (deletes last item placed)
Love it! Is it crazy that I find myself wanting to drive on a larger track? That is, a track that takes up more area than the display.
Not at all, I know what you mean.
Lack of large stages will disappoint some people. Also the fact there are no CPU cars (though ghosts are still on my list).
I had dismissed scrolling levels, as I assumed it would destroy my high frame rate. Though I’m yet to test that hypothesis!
Though I had considered a sort-of Zelda-like transition when you reach the edge of the screen, but I find those annoying. This one I still want to do something with.
The stages in the proper game are more about testing driving skill with various waypoints and objectives that encouraging drifting and manoeuvrability. Rather than going full throttle for any prolonged period of time. Right now the levels in this demo build don’t have any of this in so it probably feels a bit aimless (because it is!).
The closest I can think of is Trials where it’s about finesse and control rather than full speed (unless you’re really good and can do both).
Note to self, more representative levels in the next demo!
Honestly just driving around a small island or whatever would be fun. Like a roam mode or something. Anyway, I also respect the focus of the game currently. I just like the little cards and handling so much I’d love to whip around a larger map. I’ve been experimenting with large maps in Playmaker’s Blocks and I’m creating a giant image that blocks get baked into once they’ve snapped into place and the performance is great. I know you have physics and hit detection to worry about but maybe… mayyyybe.
Would be an interesting test, I’ll move it up my list.
It’d be a good fit because… the levels are already organised as a big playground island!
It would also save me having to finish making my map grid.
@dustin did you try toggling “Additional Collisions” and/or “Steering Assist”? They’re subtle but I wondered if you preferred them on/off.
Maybe a challenging obstacle course, and with all the pseudo-3D how about a jump?
The physics are great!