Space Rocks 3D!

It’s a bit hard to find specifications, but it appears that the Meowbit has 96kB RAM, compared to 192kB RAM on the PyGamer? I suspect that it’s running out of memory and struggling with garbage collection to make room. While I have tried to reuse data structures across frames, the program still doing a fair amount of on-the-fly allocation of small arrays.

Are there good resources to help investigate memory usage? I found the Memory Tools in MakeCode Arcade thread, but my brief experiments with trying to get console output from the PyGamer had been unsuccessful. Profiling memory says that the heap snapshot doesn’t track strings or numbers, and much of the program’s data is numbers…

@ggiscool, I like your dashboard, but I worry that adding a fullscreen image (~10kB each) may make it even harder for this to fit on hardware.

1 Like

okay I just made that in 1 minute for fun, it wasn’t actually supposed to do anything except be a tiny mod

1 Like

@mmoskal would be the one to ask about memory tools

1 Like

Here’s a small update:

Changes:

  • Added a laser heat gauge, it now overheats if fired continuously. You can still do some burst fire, but it shoots at a slower rate while too hot. (I think the game got too easy if people can hold down the fire button continuously.)
  • Removed the non-OSHA-compliant rear-facing laser. (Due to a mistake in hit detection, the laser also destroyed rocks directly behind you.)
  • Fixed the rock radius, hits weren’t registering at their outer edges. It’s now a bit easier to shoot rocks, but on the flip side they also crash into you more easily.
  • Fixed the hold-A-to-advance-waves bug. (Let me know if you were using that intentionally, I could look into adding a difficulty setting.)
6 Likes

Strings that you just write in code "foo bar" do not take any RAM (of which you have 96kB) just flash (where your game is stored, 512kB on all our boards). As you use them, they do not use any more memory. If you dynamically allocate more strings (eg. by doing "foo" + "bar" or using backtick literals with ${...} inside them), they do take RAM, for as long as you use them.

Numbers do not take any heap if they are integers less than about 1 billion (between -2^30 and 2^30). Fractional numbers and larger numbers are heap (RAM) allocated (boxed). Also math operations are much slower (like 100x) on boxed numbers than on 30-bit integers which is why the game engine is using that funky fx8 type - fixed point with 8 bit after the decimal dot.

Actually, images (unless you clone them at runtime), also do not take any RAM - they are stored in flash. Similar for hex literals.

I hope this helps!

3 Likes

Thanks for the explanations, that’s good to know. If code is using an array of numbers where each element happens to fit in the unboxed 31bit size, does it then use roughly 4 bytes per entry also, so that there’s a single heap entry for the array content that contains the numbers directly? I’m using that quite extensively for coordinates and matrices, and I’m also trying to prefill and reuse them to avoid having them resized too frequently.

I’m unsure why the meowbit has memory issues, the first few levels shouldn’t have that much additional data that needs to be allocated.

Overall, my approach was to use fixed point math with 7 bits after the decimal point for most of the speed critical loops, but sticking with floating point for once-per-frame operations such as updating the viewer matrix where accuracy and convenience were more important. Unfortunately it’s fairly easy to make mistakes and let a float number slip through which then slows things down elsewhere. It would be nice if there were a language feature to declare types to be integers and throw errors if that’s violated, but I guess that’s not what TypeScript is designed to do.

1 Like

Maybe add achievements?
Achievements extension

2 Likes

Great, then I could add a cockpit overlay after all without needing to worry about exhausting RAM. I suspect there’s some performance cost for drawing it every frame, but that should be minimal when it’s handled by fast native code.

1 Like

Now I have to watch The Last Starfighter! What a great game and I think the cockpit will be a nice addition. It runs great on the Pygamer!

1 Like

Yes, the array will take 4 bytes per element. As you add elements to the array it grows, so it may be slightly bigger than required. There is currently no way to avoid that.

There may be a memory leak somewhere. I take it the profiling in the browser doesn’t show any new objects staying alive after each frame/level?

Yeah, TS unfortunately has only one number type, and it would be really difficult for us to change this.

The Fx module uses an abstract type and casting (which has no runtime cost) to keep this type-safe. You have to then say Fx.add(a,b) instead of a+b. You could do something similar, or just use the Fx module.

1 Like

this kida looks like star fox

2 Likes

Yeah, that’s what we all think

1 Like

Here’s another new build:

Changes:

  • Added a cockpit dashboard overlay by popular request.
  • Asteroids now rotate!
  • Moved the laser heat gauge to the dashboard, it’s now an energy meter that drops as you fire.
  • Various updates to internals to save memory and fix renderer issues.

Please let me know in case you see any performance regressions, especially on hardware devices.

Would you be willing to check if it’s still crashing on Meowbit in this version? I’ve tried to reduce memory consumption.

There are some smallish reallocations after each level. I’m using an array with reusable triangle data (trapezoids) to reduce the per-frame garbage collector churn. That array grows a bit for each new level, but it only has ~150 elements and generally doesn’t need to reallocate during levels. I’ve switched the data representation for the underlying trapezoids from numbers to bytes in a buffer which reduced the data size from 48 bytes to 8 bytes.

The overall memory usage seems to be holding steady around 40kB, but I’m not sure if that’s representative of what it looks like in hardware.

Out of curiosity, is there a way to force a RAM limit, for example making a PyGamer pretend it only has 96 kB? That would make it easier to verify that games still work on low-memory devices.

That is very cool, I clearly need to read up on advanced TypeScript. I wasn’t aware that it’s possible to make no-overhead abstractions like this. Thank you again for the feedback!

6 Likes

Cool! I decided that I wanted to make my own cockpit, so here it is!

6 Likes

:smile:

Wow, I love it! It works on my meowbit hardware too.

Are you planning on making an accelerometer-controls version? I see a hint of that at line 238 in your code. That could be cool!

@edubsky, it already has accelerometer controls - use the B button to cycle through the four control schemes. The first post has a description. I prefer “tilt roll/pitch” myself, and I think it’s easier to play with analog controls.

@GameGod, your cockpit looks great, though it unfortunately blocks the radar display. It should be possible to move that into a separate image instead of drawing it on the background, but I’m not sure how big the performance impact would be. Also, maybe try making half the pixels in the top panel transparent in a checkerboard pattern to get a partially see-through roof? The restricted peripheral vision makes the game a bit harder. Edit: Also, new waves don’t get any asteroids in your version, did you make other changes also?

Hey kwx,
That version works much better on MeowBit, I played til Level 7 then I was hit by a boulder for the third time and died. It crashed right in the moment when I was hit.
I checked if that was coincidence, but no! Even if I let 3 boulders hit me right in the beginning of level 1 I get error 021.
Performance was really good, a little lag at the beginning of level 6 and 7, but much better than the last version. Impressive :slight_smile:

1 Like

@GameGod, here’s a version using your awesome cockpit, slightly modified to add semitransparent panels and fixing the radar display:

I am getting occasional garbage collection pauses on this one, though I’m not sure if that’s caused by the extra radar layer. It may be less Meowbit-compatible as a result.

Interesting, maybe the “game over” screen needs more memory than it has left at that time? I added code in v4 to reset some cached data before triggering the game over, that might help if that’s the case.

3 Likes

Here’s one more update. Unfortunately the semitransparent panels caused a rather unpleasant flickering effect for the starfield background, so I switched to fully transparent windows. (@GameGod, sorry about the radical modifications, but I found the fully enclosed cockpit a bit too claustrophobic.)

Out of curiosity, is there an extension that supports a settings screen with persistent storage? It would be nice to give the user a choice of cockpits, control scheme, and difficulty settings, but it’s a bit clunky to implement that from scratch.

6 Likes