(WIP) Pinball Engine for the Pokitto

I’m working on a pinball engine for the Pokitto and have been discussing it over on the discord channel. Here’s the progress so far:

For the physics it would be far simpler to use the old-school methods of calculating line angles on a per-pixel level and storing it in a 256 grayscale image. The example below shows the table on the right and the collision mask on the left (NOTE: the mask is extruded outward by the balls radius so that only the pixel under the center of the ball needs to be checked). The value from the mask translates to an angle between 0 and 360 which is the direction the ball should be pushed in (basically reflect the balls trajectory across this angle).
example

For the screen layout I was thinking either having the table take up the entire screen and having a small row of pixels at the bottom for the score display, or having the table take a smaller portion to the left of the screen and have more room on the right for additional graphics (the green dot is the size of the ball for reference).
screen_test

I think I personally like the ability to have more information on the right (since it could also be used for making adventure style pinball games). The engine would not have a vertical limit on the table height, only that it’s a multiple of 16 pixels.

As far as table programming goes I was thinking of adapting an event system similar to the one I made in Open RPG Maker that would easily compile to a bytecode (but could also support pure ASM since the m0+ can load instructions into RAM and execute them, would just need to figure out how to compile the code to a separate file).

The main idea is that each table would be a file on the SD card and the user would flash the engine, then browse and load tables to play. Plus the table can have multiple sub-tables and events could teleport the ball to different locations within the table, or to other tables entirely.

I could theoretically design it to be able to work with both style tables, however the smaller sized one would only take 7680 bytes for 3-rows of data for both the table background and the collision mask. Then when the ball moves to a different row it would only need to read 2560 bytes from the SD card to get the new row. This should allow for easy streaming of table content from the SD card and would leave approximately 20KB of space to program the table’s content (some routines that would be common across multiple tables can be pre-built into the engine to save on space). The whole screen one could still be optimized to not load a whole table row at a time, so it is theoretically possible to support both, but it might mean more reads to the SD card since it would only load a 3x3 area of 16x16 pixel chunks. Loading a whole row at a time means it can speed up the file I/O by only needing one seek operation as opposed to three.

I think that covers most of what’s currently been discussed over on the discord channel last night, but if I miss anything I’ll add to it here.

  • Whole Screen Layout (small score display at bottom).
  • Partial Screen Layout (large 60px display at right for additional table mechanics).
  • Try to make both work (might not be possible, or may induce more restraints on both).

0 voters

8 Likes

Amazing work.

Whenever possible I prefer scripting in the same language as the game, i.e. C/C++, and having them part of the game source. You have to recompile the whole game when you change scripts but that’s not really an issue, the only issue is storing scripts in files, which I would personally avoid and compile everything into one executable, but since I reckon it’s a feature you want, you could compile a C/C++ script the same way you compile any Pokitto program, then simply open the file and load the code into RAM. But it’s gonna be difficult, buggy, unportable and won’t be fun to program.

Maybe a reasonable middle ground would be to give up on a full featured Turing complete scripting language such as ASM, and simply have a few types of special objects that can be placed on a table, such as a ball teleporter, something that writes out a text when you hit it with a ball etc. That’s easily stored in files and can do most things you want.

The mask approach really simplifies the ball physics.
I prefer bigger graphics as it makes the game more enjoyable. Having a partial screen would make the pinball table really small on Pokitto’s screen.

I’m not quite sure how you can script in the same language when using a compiled language. The idea here is that you would have one BIN file to load and multiple tables can be made using the one engine. You can also make a modified version of the base engine for more advanced functionality, but I would like to include everything needed to make a fully customizable table without having to re-compile the engine.

This would be what’s called a shared library (DLL on windows, SO on linux, and DYLIB on mac) and is very much different from a scripting language which doesn’t need a compilation step (though they can sometimes be “compiled” to bytecode instructions but they must still be run through the interpreter).

For a good reference look at how tables are programmed in Future Pinball and Visual Pinball which use Visual Basic Script. This allows for both simple and complex tables to be created without having to re-compile the engine.

Writing script code in the same language as the program defeats the purpose of using scripts in the first place, it might as well be a skeleton engine that requires the user to to all the tweaking and adjustments, much like TAS mode is not able to play any games, you still have to create the game. The idea with this is everything is there and you just have to make a table for it to load.

Most likely what I’ll end up doing is something like the Event System used in Open RPG Maker (which in turn was based on the one used in the RPG Maker series). This system is easily able to be compressed to bytecode like structures.

The main reason for the pole is I will probably still end up having both in the end (most likely separate engines, but might be able to combine them). However, I’d rather get one up and running and see what we like and what needs improving. Then I can get the other setup if there’s a lot of interest in it as I really like the possibilities that both provide.

Actually I put that image on the Pokitto and just have the engine draw it to the screen to see how it would look and the results are actually not that bad. Keep in mind the ball size will be able to be set based on the table. The eventual editor would just need to take the ball size into account when creating the collision mask. It also won’t affect the collision buffers at all since it only needs to look at the center point of the ball.

1 Like

There’s two aspects to consider here: executing the bytecode and converting text into bytecode (“compiling”).
By designing your own the execution part becomes pretty simple, but you’ll lose time writing a compiler.

By using native code you can get GCC to do what you want somewhat easily, but execution requires careful planning. It’s not just a matter of putting the code in RAM and jumping to it, but it can be done. It would be possible to make a FemtoIDE project that builds tables, making it easy for others to make their own.

Of course, having certain components built-in to the engine is also an option. Just pick whatever fits your definition of fun, they’re all viable options.

1 Like

I’ve been wondering when we’d get a pinball game.
I have fond memories of playing Pokemon Pinball on my GBA.

Ah, brads. Very efficient.

I feel that bytecode is a greatly underused technique that would be quite good for this.

(I’m going to leave this link here for anyone interested in using bytecode for games.)

Theoretically this should be faster and more efficient,
so if you can get it to work then it’s probably the best option from a size & speed efficiency standpoint.

However, on top of the difficulty of compiling the functions (I suspect the ‘script’ functions would have to avoid making too many assumptions about their environment),
there’s also the risk that comes with arbitrary code execution.

Security isn’t much of an issue on the Pokitto because (at the moment at least) there’s no important information to be stolen,
but it’s perfectly possible that a user could (either accidentally or maliciously) mess around with RAM that shouldn’t be messed around with (buffer overruns and the like).

With bytecode it’s a lot easier to make the code safe and error free (and guard against both accidental and malicious misuse) even if it comes at a performance and storage cost.


I opted for ‘whole screen’ because information that doesn’t need to be checked frequently can be kept on the pause screen,
but I can imagine that a square viewport might be more optimal for playing pinball games.

It’s hard to decide without having a better idea of what information is expected to be kept on the side panel.
Indicators showing which board features are active? Mission text?


I quite disagree here.

A single program capable of loading levels off the SD card is likely to take less space than multiple programs that have large chunks of similar code (i.e. the engine itself).

Also the time taken to flash a new game versus being able to go back to the main menu to load a different level would really hamper the user experience.

The way I described it. Strictly speaking it is not scripting anymore, but I call it scripting in a less strict sense of the word – here a script is a code that is not part of the engine, but belongs to a table/level/etc.

I understand – what I am trying to communicate is this is not necessarily a good approach in my view, it’s an approach taken by extremely heavy and bloated PC programs that require a PhD degree and a few hours to recompile. Good programs compile easily, quickly, and can be distributed in source-only form. If compiling is as easy as uploading a BIN to Pokitto, then you don’t need to limit yourself by insisting on having a binary program that contains an interpreter of another language.

I know this is subjective, take it as a proposal that’s up to you to accept or not.

This is just playing with words, you are looking for a solution that works for you, it doesn’t matter if it’s called a dynamic library or a compiled script or whatever. As you say, many scripting languages such as QuakeC are still compiled, and also many bytecode compiled languages JIT compile into native instructions, so in essence scripts and dynamic libraries may not be so different either – in the end these are just words.


Have you considered this?

I think this may be the best way to go. Full scripting sounds good, but I am afraid the engine/game will be so complex that it may very likely end up unfinished.

I’ll disagree with this. The bytecode/DLL approach is less complex as it moves unneeded responsibilities out of the engine and into the scripts/plugins that do need them, reducing “bloat.”
This approach also has no problem with the second part of your comment. Compilation will still be quick, easy and distribution of source-code is still possible.

2 Likes

That was one option I considered. Have an editor that creates the table data, and a FemtoIDE project that compiles the tables code.

That was the other thing I was looking at is a sort of combination of both. Some functions built into the engine, which would take fewer instructions to call and return from. Plus there would be built in resources (fonts, sfx, etc, depends on how much flash space is left once the rest is implemented) that the tables could use or provide their own at the cost of less code space (kind of like developing on Arduino).

Googling scripting language vs programming language shows that there definitely used to be a clear distinction between the two, but that line has been heavily blurred over the years with more advanced languages (like Java) that compile to bytecode and then use JIT compilers to translate to machine code on the fly.

That’s essentially what the event-like system would be. Not full scripting/coding, but more of visual coding which would make creating tables easy for beginners as well.

Not really an issue here as I’ve used this event system in quite a number of projects and already have a crystal clear idea on how it can be used for this design.

Yeah it would have the ability to have indicators, mission text, and could even have a fake LCD display (possibly with it’s own buffer to write to, 48x32x8bpp would only require 1536 bytes of RAM), depending on what the table designer wants. Using the widescreen approach puts more focus on just the table (however Pokemon Pinball showed us that you could still have a fake LCD like panel right on the playfield, so it’s still possible).

As I mentioned I really like both designs and I think both are still possible (just separate engines with slight variations on features, but similar cores).

Part of the reason for having a lengthy discussion on this now, is I can also get a good feel for what others would like to see, since it’s also possible to go entirely my own route and not release anything to it’s a working prototype but there might be some really valuable feedback that others might like to see.

3 Likes

Scripting capability is not usually what makes them ‘heavy and bloated’ though.

Usually what makes programs ‘heavy’ is things like poor use of resources, kludges to maintain backwards compatibility and (most importantly) feature creep.

The shared library (.dll) for Python 27 is about 2MB and the one for Lua is only 208KB.
Compared to the size of most graphically capable programs that’s a small fraction.

Whilst being able to distribute a set of easy-to-compile source code is very amicable,
there are people who will want a pre-compiled distribution so pre-compilation must also be possible.

In particular people who want to play the game but aren’t programmers will most likely be flummoxed at having to compile levels before they can play them.
They’ll most likely see it as nothing more than a waste of time and effort.

That’s because compiling is hell because of bad technology. Compiling should – and can be – literally no more difficult than uploading a binary program from computer, it should be a matter of running a single command. Binary distributions became a thing only because of corporate interests (not sharing source, intentional incompatibility, …) etc., not because they’re a good thing. With mainstream PCs the situation is beyond saving, what concerns me now is that this thinking is finding its way to Pokitto and similar platforms that should be an example of doing things right, I think we should know better. Again, it’s my opinion, but I also think it’s more or less a fact.

1 Like

The problem is, at what point would you compile the scripts?

  • If the scripts are bytecode-based:
    • You could have a program that compiles them before copying them to the SD card,
      but that’s still less convinient than just being able to copy precompiled files onto the SD card.
    • You could try to get the loader to compile them before uploading the game,
      but that would be a lot of effort assuming it’s even possible.
  • If the scripts are compiled into the program:
    • You’d have to compile them as part of the program, which is awkard because not everyone uses the same compilation system so it’s virtually impossible to have ‘one click compiling’ for everyone.
      Even if we had perfect one-click compiling that’s still an extra step versus uploading a precompiled program.
      You could turn it into a single command line command,
      but then that’s going to be unfriendly to non-programmers,
      and you’d still have to specify the source files and the destination which is more hassle than a simple drag & drop operation.

Compare this to pre-compiled code:

  • If the scripts are bytecode-based:
    • You can copy precompiled files straight to the SD card. In fact you could even download the precompiled scripts straight to the SD, entirely skipping the computer’s hard drive.
    • The loader wouldn’t need to compile them at all.
  • If the scripts are compiled into the program:
    • If the program is distributed pre-compiled then the program is just uploaded, no hassle. Similarly the program can be uploaded from the SD card by the loader without any hassle.

It’s a matter of convinience, not corporate interest.

If someone doesn’t need to edit the scripts, doesn’t want to edit the scripts or doesn’t want to read the scripts then they don’t actually need the scripts.

I’m not saying the source code of the map scripts shouldn’t be available for those who want it,
quite the opposite, I think all map scripts should be available for download and free to be edited by whomever wants to do so,
(and ideally all scripts should use open source licences or be in the public domain,)
but I cannot deny that precompiled scripts are simply more convinient in the majority of cases.

(Not to mention a better use of resources and SD card space.)


I disagree with some of your other assertions,
but I’m not going to dispute them here because doing so is not pertinent to @tuxinator2009’s pinball project,
lest we forget what this thread’s actual topic is.

3 Likes

Oh, yes. Remember when i said, we need a pinball game?

2 Likes

Pepperidge Farm remembers :grin:

On another note I’ve got a working graphic for an 8x8 ball that looks rather nice.
ball
I made it using blender, just made a sphere with a light shining on it and rendered it 8x8 pixels.

I don’t think rotation of the ball would be easily doable though. First there’s calculating the angle of rotation, which might be doable without complex math involved. Then there’s the rotating of the sprite (costly in frame rate) or storing pre-rotated copies of the sprite (needs to be 16 copies otherwise it looks very choppy). I don’t want the ball to use a 16 color pallete because it takes extra cycles to separate the nibbles, but it can use the same 256 color palette of the table. This would mean an 8x8 ball would take 1024 bytes and so if it works it might be a toggleable option on a per-table basis and the table would need to provide it’s own ball sprite.

Later if I figure out a cheap way to calculate the rotations and rotate the sprite then I’ll revisit it, but I think at the moment I agree with @Pharap mentioned in a PM on something else. Which is better to get it up and running with a basic event-like system that can easily make good quality tables with little effort, then later the system can be expanded as needed to provide more flexibility and power. This way I can focus on getting something that works, is fun, and is easy to use, rather than get bogged down with trying to determine every possible feature before I even get started (just determine core functionality needed to make it fun, easy to use, and working). Planet Escape reminds me of this in a way since there’s loads of features the developer still would like to implement, but its better to have the core functionality working then improve upon the results.

Also keeping in mind that everything we do here is purely for the fun of it and done during our spare time (something some of us have very little of these days). So in that sense lets keep it fun and exciting and not get bogged down with trying to re-invent the entire computer programming ecosystem from the ground up.

So far it looks like the Whole Screen version is winning at the time of writing this (though yesterday it was the Partial Screen) and has been a neck-and-neck race between the two. Very excited to see the outcome as I think both are equally good in their own way, and they both have their own strengths and weaknesses. If you can’t see yourself voting for one because you aren’t able to see the potential of it THAT’S GREAT. That’s what the vote is going to help me decide on is how much potential others see in the two possible modes.

I’ll be prototype the collision system using the Partial Screen mode since I have a good example to use, but it’s going to store all the data for the table in flash to get the system working and optimized before I tackle streaming from the SD card (which does have an impact on the different modes). Once I have a working collision system with a ball flying around the table I’ll post a GIF.

6 Likes

So I’m working on the physics part of the engine now. I think I’ve figured out how to handle the collision information. The tables background image will be 16bpp (correction 4bpp, for 16-colors) and I think I may have figured out how to allow both styles of table dimensions to work without imposing hard limits (ie. one table could be 160px wide with a 60px side area, another could choose 156px wide for a 64px side area, another could be 220px wide and 160px tall for 16px on the top/bottom or 8px on both, and yet another table could do 220x168px and only have an 8px portion at the top/bottom for score/other display, even then a table could also use the full 220x176 resolution and have the score and other information overlaid on top of the table and scroll with the table or stay in one spot on screen).

Table collision data will be broken up into 32x32x8bpp pixel chunks (1024 bytes). The collision data would be streamed from the SD cart based on the ball’s current coordinates and would stream a new 1024 byte buffer when the ball moves outside the current buffer. The angle of impact represents the angle of the normal that the balls trajectory get’s reflected across (this way it doesn’t matter what direction/velocity the ball is traveling when colliding with that pixel). The second byte could be dropped in favor of sensors/triggers being lines/circles/bboxes, though they could also be smaller collision maps that overlay the normal collision map (flippers will be handled in this way as described below).

For the flippers I’ll need 4 8bpp images.

  1. Flipper is in the raised position (button held) and the ball collides with it much like a wall (possibly with a bounce factor).
  2. Flipper is in the down position (button released) and again the ball collides with it much like a wall.
  3. Flipper is transitioning from the down position to the up position and the ball is somewhere in it’s path (velocity of flipper can be stored as a single value and applied to the actual angle of impact).
  4. Flipper is transitioning from the up position to the down position and the ball is somewhere in it’s path (treated the same as the 3rd image).

I would like to provide graphics and collision maps for default small, medium, and large flippers in flash that tables can use (changing the appropriate pallet colors to customize the flipper’s color), while also providing table’s the ability to override the sprite, collision map, or both at the cost of less space for other graphics/logic (allows tables to balance themselves according to what the designer would like to do).

I’ve got a working prototype of a ball moving at constant velocity up and down the table vertically (reversing direction when it reaches the table edge) which is able to stream the table’s background at about 27FPS if the whole table needs updating, otherwise it flags specific scanlines to be redrawn based on objects movements/animations and with just a ball moving around maxes out at 333FPS when it’s only updating the balls old location and new location (with some overlap).

On the physics side of things I’m having the physics engine perform constant 5ms steps (200 steps/second) and each frame it simply steps the physics engine until the previous time catches up with the current time. Will need to see what impact this has in the final frame rate once collision is being processed (currently a max speed of 1px/step, which is 200px/s, seems like a good terminal velocity for the ball, otherwise the ball moves so fast that it’s nigh impossible for the user to keep up with it’s movement even if it got a smooth 60 FPS).

The collision info will also be layered so that you can have ramps leading to an upper portion of the table with rails going over a lower portion. To achieve this the ball will be treated as a normal sprite and can move up or down in the list of sprites to render (thus going above/below individual sprites), with a separate pointer to the ball sprite so the physics engine can update it’s location.

Tables can have more complex sprites (think the Mewtwo bonus stage of Pokemon Pinball) that use collision maps overlaid on top of the tables collision map (allowing them to be moving targets). However, to decrease the size of basic table lights they’ll store a single palette index for their color (allowing lights to change color by changing the color in the palette) and would store their pixel data in horizontal RLE-encoded lines. The encoding would use 1-byte per off-on segment (ie. off-off-on-on-on would be stored as 0x23), and if a section has more than 15 off/on segments in a row then there would be a 0 in between them (ex. 4 pixels off followed by 20 pixels on would result in 0x4F, 0x05). This is best suited as the rendering is done one scanline at a time. If there’s enough space left in FLASH there will be a set of default lights provided as well. These would be commonly used shapes like circles, squares, and arrows, as well as circles with each letter in them (most likely as 8x8 images). The worst possible compression of the RLE would encode an 8x8 light in 32 bytes (equivalent of a 16-color image as opposed to 8 bytes as a 1bpp image), however this compression also offers performance improvements when drawing is done in scanlines.

For the memory layout the engine will allocate a large chunk of RAM as a static array which will be used to store all the currently needed information for a table (ie. sprite graphics, lights, collision maps, table logic, etc). However, through the event system tables can swap out sprites so they only have to load the ones currently being used. The editor will take the table’s designs (collision shapes, sprites, logic, and everything else) and compile it to a single file that the engine can load from the SD card. This has the added benefit of non-programmers being able to design their own custom tables with a, more or less, basic logic event system.

The events themselves will be functions in FLASH that get called and would use 1 byte to store the event type (allows for 255 different functions) ranging from basic math operations (addition, subtraction, etc) on variables, toggling switches, changing palette colors, and many more things to be determined later when I start work on the first actual table.

This has been a very lengthy documentation of the core concepts I’ve worked out so far. Stay tuned for more info as it develops. Be sure to set the tracking status of this topic to “Watching” if you want to be notified of any updates as things progress. Trying to document everything here because if things go smoothly and I can get this done in a decent amount of time with a finished table then this has the makings of a great article for the second magazine (Trials and Tribulations: The Development of a Pinball Engine for the Pokitto) :crazy_face:

8 Likes

Normally I try not to double-post, but I’m also documenting updates as they develop for a possible magazine article :grin:

Update to the flippers:
After discussing it on the Discord chat a bit, I think I’ve figured out a better way to handle the flippers. Arguably they’re also one of the most crucial parts to get right as they can easily make or break the gameplay. The way I plan on doing them now is to instead use collision shapes to represent the flippers. A single flipper can easily be represented using 2 circles and 2 lines (see below for a rough diagram). In the event that a collision occurs between a circle and a line at the same time, the line collision would take priority (this is because the ball would bounce off in a more predictable manner and usually would only overlap in 1 or 2 pixels). Since I’ll need to store sin/cos lookup tables anyway the shapes can be easily rotated in stepped increments (to coincide with the individual steps of the physics engine) and collisions checked and handled at each step. The sprite for the flippers could potentially be rotated each frame as well (though it might prove difficult with a scanline drawing approach, but I’ll try, or it could prove extremely simple). If the sprites aren’t rotated then their could be multiple frames that would be animated to roughly coincide with the stepped collision shapes (might not be pixel perfect collision but it’ll be close enough that you won’t really notice).

flipperCollisionExample
Flipper collision diagram.

4 Likes

How are you planning to implement the velocity aspect of the flipper?

As you know, hitting a stationary flipper has a very different outcome to a moving one. The circumferential velocity of the point of impact is also not uniform, being 0 at base, and pi x D x angular velocity at the tip

2 Likes

Good question. Since everything moves in the same timed increments (currently 5ms increments) for the collision, then the velocity of the flipper can be approximated at the moment of impact by cross referencing the time taken for the flipper to move from one final position to the other.

Since the flipper moves rather quickly, say it’s set to take 1/4 of a second to go from down to fully raised and vice-versa you could approximate it’s velocity by calculating the point of collision and determining it’s angular velocity by it’s distance from the point of rotation and the start and end angles of rotation. I’m working on a diagram showing the individual details because it’ll help when translating the math into code and optimizing it for speed while maintaining accuracy (initially there won’t be float optimizations since it’s better to make sure the formula works, then work on optimizing it, since you can compare the changes with a known working implementation). I’ll edit this post once I’m done drawing the basic diagram.

AP (Advanced Placement) Physics was one of my favorite classes back in High School (11th grade to be precise) so it’s all coming back to me. Math in general was some of my favorite classes and I fondly remember reciting 110 digits of PI from memory (I memorized it at the time because it felt like fun). :crazy_face:

1 Like

Very impressive work so far :slight_smile: I will be making my own Pinball table when this is ready.

1 Like

Really?! I can memorize 3.14 :stuck_out_tongue_winking_eye:

3 Likes