Making a pinball game for Playdate: Part 03, the first level editor

Welcome back to this December adventure, where I will write about the process of making our latest game, Devils on the Moon pinball.

When following the Pikuma 2D Physics course, one thing I did quite fast was making a simple polygon editor. I quickly got tired of inputting every vertex by hand.

Draw polygons with the mouse

This presented a problem: how are we going to author the pinball table for our game? Not only that, but good pinball games have a lot of curves. Am I going to need a way to create Bézier curves? How do I convert Bézier curves to something useful? In my case, to polygon colliders? Should I start working on a custom level editor?

I briefly tried writing an Aseprite extension to generate the collision masks but failed. It was fun though.

Aseprite extension

The main thing we wanted to know was if we could use the same approach from the physics engine for the Playdate game. First I had to translate from C++ to plain C and from SDL to the Playdate. Second, I wanted to put a lot of polygons on the screen, a couple of balls, and see how the frame rate behaved.

As you will see in future posts, I don’t need a lot of reasons to start making a new tool, but everything was still up in the air; if performance wasn’t good enough, I would need to go back to the drawing board and find a different way to define the level.

So I started searching for a UI to make polygons. I wanted something simple that would let me define some polygons and ideally set different stats on the polygons to test the physics.

In my search, I found the Code & Web Physics Editor. It ran on macOS and Linux; it had a simple UI and allowed me to write a plugin to change the export file to something that fitted my needs. I didn’t have a good way of defining custom entities that weren’t physics-related, but it was good enough to start.

Code & Web physics editor

One intermediately obvious benefit of the Code & Web editor was that it took care of subdividing the polygons to make them concave automatically.

I hacked around a custom exporter that would generate a .h file with an array of polygons and started working from there.

// map.h struct body TABLE_BODIES[43] = { { /* ID=poly0-0 */ .p = {0.0, 0.0}, .restitution = 0.60f, .friction = 1.00f, .mass = 0.0f, .inertia = 0.0f, .mass_inv = 0.0f, .inertia_inv = 0.0f, .shape.shape_type = COL_TYPE_POLY, .shape.poly = { .count=6, .verts={{44, 105},{39, 109},{39, 162},{45, 171},{50, 160},{50, 109}} } }, ...

Then came the porting process to the Playdate, we were super excited the first time we saw the ball moving around the screen and colliding with the polygons. We knew at that point that we were actually going to be able to make it. Suddenly making a janky pinball game similar to early game boy pinball games wasn’t enough; we knew we could do better.

photo_2024-12-04_00-08-08.jpg

While I was playing around with the physics system, Jp finally had some tools to start designing; he already had some ideas for the design of the table. The Code & Web editor got us really far. It allowed us to focus on the overall design of the table and making sure the physics were right before moving on to the next steps of the game.

Polygon Editor

I wrote a really basic camera system, that followed the main ball, and as Jp added more and more polygons, the game kept running at steady 50FPS.

There were a lot of things left to do, but the scariest part was done, or at least done enough. In retrospect, I really like that we went with the Code & Web editor first; eventually we migrated to Tiled, but only after we took the Code & Web editor to its very limits.

debug.gif

Now we just needed to find a way to draw textures on the screen, and there was a message on the Playdate Squad discord server that excited us a ton.

See you in the next adventure, Part 04: The image format.

Comments

Other Posts

Archive

You can subscribe via RSS or follow us @amanogames_

Making a pinball game for Playdate: Part 07, the debugger

Making a pinball game for Playdate: Part 07, the debugger

Searching for a debugger on Linux

Making a pinball game for Playdate: Part 06, the profiler

Making a pinball game for Playdate: Part 06, the profiler

Learning how to use a profiler

Making a pinball game for Playdate: Part 05, the spatial partition

Making a pinball game for Playdate: Part 05, the spatial partition

2 Bits image formats.

Making a pinball game for Playdate: Part 04, the image format

Making a pinball game for Playdate: Part 04, the image format

2 Bits image formats.

Making a pinball game for Playdate: Part 02, the physics

Making a pinball game for Playdate: Part 02, the physics

Let's talk about physics.

Making a pinball game for Playdate: Part 01, the language

Making a pinball game for Playdate: Part 01, the language

Welcome to this December adventure, where I will try to write about the process of our last game, Devils on the Moon pinball. Today I will talk about our choice of programming language for the game.

Let’s finish this

Let’s finish this

We are back working on Pullfrog! What happened?

Let's talk about Don Salmon

Let's talk about Don Salmon

Don salmon, a new platforming game made in Godot and a small update on Pullfrog

Spooky eyes and level editors

Spooky eyes and level editors

Last year we made the decision to take a break and focus on a spooky game around the spooky season.

This kills the frog

This kills the frog

After rewriting the physics system for the third time, it was time to start working on more fun stuff. The frog death system™.

On starting a game

On starting a game

A couple of things I would recommend when starting your first game on the Playdate.

How to correct a corner

How to correct a corner

There are many techniques that you can apply so that a platformer game feels good. One of those is corner correction.

On "Bouncy" Animation

On "Bouncy" Animation

Another Equally important decision, is choosing which poses you want to emphasize in order to get that reactive feeling when a character interacts with the world.

The collision stair case

The collision stair case

As stated on the previous post, updating all the pieces all the time was a bad idea. We needed to figure out a way to update only the ones that needed to be updated after another block got destroyed. The quick and dirty solution was to check all the pieces inside a bounding box on top of the piece that got destroyed.

About Amano & the collision conundrum

About Amano & the collision conundrum

So, a couple of months back, Mario and I were happily working away on The game, finding out the workflow and working out the kinks of developing for the PlayDate. We laid down the main mechanic, blocks were falling and colliding correctly the character was moving alright but we were doing everything on the simulator, NOT testing on the actual device. so when we decided to take it for a spin…  it crashed.

Pullfrog postmortem, Long Live Pullfrog 2-Bits

Pullfrog postmortem, Long Live Pullfrog 2-Bits

So towards the end of the year, Mario managed to get his hands on a Development console for the handheld "Playdate" and we decided to attempt do make a second version of Pullfrog, this time featuring a playful little crank and seemingly less restrictions except for the apparent ones like the black and white color of the screen. Oh the naivety.