Mode 3 Scrolling Game Engine Demo (WIP)

Use this forum to share and discuss Uzebox games and demos.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by Artcfox »

CunningFellow wrote: Sat Feb 04, 2023 1:00 am nice. I am terrible at platform games but this is very very polished.
Thank you! I used to be terrible at T2K, but improved so much by play testing it. Soon you will be good at platformers. ;)
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by Artcfox »

Another update, attached to this post. :geek:

I've been testing out the newest officially supported avr-gcc version 7.3.0 from Microchip. When you use -Os, it typically generates smaller code than the Debian-provided avr-gcc 5.4.0, and it gives much nicer warnings.

I went on a size and speed optimization spree, shaving over 1000 clocks off the vertical moving platform implementation, and some off the horizontal moving platform code, some across the board improvements with the physics models, and eliminated some unnecessary sprite tiles and added the ability for entities to get their sprite data from the normal tileset if they set a bitflag. I also fixed a few minor bugs that I had discovered along the way, like the charging turtle could charge in the wrong direction if it saw you just before it turned around. The fix for that made the code smaller and faster, so another win. Attempting to optimize the horizontal moving platform code the same way as I did for the vertical moving platform ended up making it larger and slower, so I #if 0'd that code out, but haven't had the heart to delete it just yet. :P Another bug fixed was a regression caused by a horizontal moving platform fix to avoid clipping into a wall if you are moonwalking on the platform. That went through several iterations before it worked and didn't cause a similar wall sticking bug while on a vertical moving platform immediately adjacent to a wall, or cause the unicorn to clip vertically into a wall if you positioned yourself halfway off the edge of the platform as if the wall was a guillotine.

Deep dive into a hard to reproduce bug

About a week ago I ran into a nasty bug while testing on real hardware, where a moving platform marked as "never despawn" completely vanished, but I hadn't been able to reproduce it on an emulator while recording my inputs until last night. The weird thing is I captured it under uzem, but the issue didn't show up under cuzebox when playing back the same input capture file. There must be some ever so slight timing difference between the emulators. I enabled some of my debugging options, and narrowed it down to when the conditions were just right, and you strayed too far away from some entities so they despawned after having sprite flickered just enough to leave the iteration order backwards. The despawning code, when iterating backwards, had a bug in it where if you despawned multiple things in a row in the same frame, the entity list would get corrupted when it tried to despawn the same entity twice, which caused a different entity to be silently despawned. In this very-hard-to-reproduce case, I think I only noticed it because it ended up being the moving platform that was marked as "never despawn", whereas if it was another entity, I might have mistakenly thought I had killed it. I can't believe it took a week just to get a second repro, though knowing the conditions to trigger it, maybe I'm not surprised.

That was a fun one to track down, but thankfully I record my emulator inputs 100% of the time, so when I do run into any bug, it ensures that I can reproduce it after adding debugging prints to the console. I ended up fixing it using a naive memmove approach to "remove an element" from the entity array, which was inefficient, but it maintained the order of the list so the double-mixer rotation algorithm should work better. The only downside was it used way too many clocks (~1800), but it did lead me to an optimized solution, which had been in front of me the entire time, I could just use the same forward iteration deletion code, but skip the last two steps of modifying the iteration and end condition. So bug squashed, and the code is smaller and runs faster!

New Features

I added a new mechanic that I'm calling "cloud insurance". It technically was always there, but it was super short-lived and mostly invisible. There is a grace period (6 frames) where you can be falling, but still make a jump as if you were on solid ground. This "coyote-time" is something that most platformers allow, so if a player intends to run and jump off the edge of a cliff, they get some wiggle room if they are a few frames too late with the button press. I wondered what would happen if I extended that grace period indefinitely.

What I ended up with is something that I'm calling "cloud insurance" because: It can only protect you from a fall (it's not a double-jump!) Since you are a magical unicorn, if you are falling you get one attempt at saving yourself by manifesting a tiny quickly dissolving cloud directly underneath you that you can jump off of. Once you jump though, you lose your cloud insurance until you land on solid ground again.

I'm not sure yet if it should be an all-the-time thing, or a power-up, or an ability you have to earn and equip, but it should make the level design way more interesting, so I'm leaning towards it being an all-the-time thing.

This also made me realize how awesome it is to be able to just blit special effects, and now that I have a decent sprite flickering implementation I don't have to be as shy about tossing in a few special effects here and there. Since I thought the "cloud insurance" effect looked pretty awesome, I took some inspiration from the 1960's animated Batman series, and added a KAPOW!-style spiky balloon to some of the entity-kills-player interactions. Just a brief flash coinciding with the sound effect seems to make the sound effect way more "punchy".

What's next?

I may or may not add one more enemy class before I switch over to converting the levels to stream from the SD card. I hope that I've left myself enough clock cycles to do that! I know I can queue up a sector (but not read it) in one frame, and by the time the next frame rolls around, most cards should be ready to immediately hand me data bytes when I do attempt the read. It's just after I read the small amount of data I want from the beginning of the sector, I need to either cancel the read or clock out the rest of the bytes in the sector that I don't need. Ideally I could just clock the unnecessary byes out, dropping them on the floor from inside the spare cycles of the HSYNC code, but I might need an ASM guru to help me with that. If all I'm reading are the first 40 or so bytes from a sector when a new row and/or column is scrolled into hidden VRAM, that won't add too much CPU overhead as long as I'm not forced to waste "user time" clocking out the rest of that 512 byte sector.

If anyone has any ideas on how to do a "dumb" clocking out of the leftover bytes in an HSYNC, please let me know.
Attachments
bigmap.c
(173.22 KiB) Downloaded 58 times
unicorn8.hex
(135.64 KiB) Downloaded 65 times
unicorn8.uze
(48.72 KiB) Downloaded 62 times
User avatar
uze6666
Site Admin
Posts: 4801
Joined: Tue Aug 12, 2008 9:13 pm
Location: Montreal, Canada
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by uze6666 »

Wow, amazing progress since January! Love all the smoothness, rainbow farts and those SMB-style fire things. I can't seem to see any flicker (in Cuzebox at least). Have yet to flash it on my hardware to play it through. Let me know when you think if officially done, I'll post about it.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by Artcfox »

uze6666 wrote: Fri Feb 10, 2023 1:54 am Wow, amazing progress since January! Love all the smoothness, rainbow farts and those SMB-style fire things. I can't seem to see any flicker (in Cuzebox at least). Have yet to flash it on my hardware to play it through. Let me know when you think if officially done, I'll post about it.
Thanks!

I haven't even started building the levels yet, this is really just my "playground" level to test out the various game mechanics. It started out life as an upscaled version of the first level of my Bugz game. If you disable the merge frames in Cuzebox, and then single-step it with 2 butterflies and the firebar on screen, while jumping, farting, and manifesting a cloud, you can see a bit of flicker spread out across a couple corners of the sprites. The RAM tile striping algorithm prevents unaligned sprites from ever using consecutive RAM tiles, so the only time you should be able to flicker an entire 8x8 sprite in a single frame is if it only used 1 RAM tile in the first place, and the shuffling algorithm should prevent that sprite from being flickered again for a long time.

My ultimate plan (once I get all of the game mechanics finished) is to get it to stream the levels from the SD card, and then build out a bunch of big levels.

At some point, maybe I should "cut a demo" for easy learning purposes after all the game mechanics are complete, before things get overly complicated with the SD level streaming? That would also give me a chance to walk through and document the conversion of the game from reading level data from flash to streaming it from the SD card. I'm hoping to do it without having to create a separate conversion program. I would love for the game itself to spit out its own SD card level file on the whisper port. The bin2hex tool that's part of the Uzebox repository has a command line option -r to turn a hex encoded file into a binary file, and that's what I'm hoping to use to make the SD card files, though that might only work for levels small enough to fit into flash memory.

New Update

Changes in this version (small update):
  • Reduced size of PLAYER structure by splitting counters, prototyped using bitfields to further combine counters if it ever comes down to needing a few more bytes of RAM vs code size and speed.
  • Added blink animation that can occur in any pose
  • Added slight y-flip delay when player is killed
  • Better positioning of kapow bubble to more accurately show where the player got hit by the enemy (midpoint of overlap)
  • Unicorn gets a black eye when killed.
  • Bugfix for uninitialized spritebank value in ENTITY struct
  • More code cleanup
Attachments
bigmap.c
(171.61 KiB) Downloaded 71 times
unicorn9.hex
(136.5 KiB) Downloaded 63 times
unicorn9.uze
(49.03 KiB) Downloaded 78 times
User avatar
mapes
Posts: 174
Joined: Sun Feb 13, 2011 7:04 am
Location: Seattle

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by mapes »

I've practiced enough that I can finally get the lollipops without getting killed. :D

I noticed that when going up past the end of the ladder you keep your momentum that you can coyote jump (off) from a position well above the ladder.

This maybe an unintended consequence, but could be used on levels you plan to make to get some hard to reach lollipops.
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by Artcfox »

mapes wrote: Sat Feb 11, 2023 11:13 pm I've practiced enough that I can finally get the lollipops without getting killed. :D
Awesome! :D
mapes wrote: Sat Feb 11, 2023 11:13 pm I noticed that when going up past the end of the ladder you keep your momentum that you can coyote jump (off) from a position well above the ladder.

This maybe an unintended consequence, but could be used on levels you plan to make to get some hard to reach lollipops.
Yep, that is a carry-over from the physics engine in my Bugz game where one of its levels forces you to learn how to carry your momentum off the top of a ladder in order to beat the level!

By coyote-jump, do you mean having a cloud manifest under your feet, and jumping off that at the peak of the momentum carry-over, because that won't get you as high as holding down the jump button while moving on a ladder, and then leaving the ladder. If you are holding jump while moving on a ladder, you will not jump until you either stop moving, or have moved off the ladder. That makes it easier to time your jumps to happen as soon as you leave the ladder (either top, or sideways, the bottom isn't very useful to jump off, because you will just immediately rejoin it).

The "cloud insurance" mechanic allows you to get to places you normally might not be able to get to (like deep underhangs) which I might work into some levels. You can still see the remnants of the fast-dissolving cloud underneath the unicorn.
jump-underhang.png
jump-underhang.png (78.96 KiB) Viewed 1125 times
If you walk (not jump!) off the edge of the cliff above you, you can turn around and use your "cloud insurance" to save yourself from falling by pressing jump while still falling, and maneuver yourself onto the cliff underneath (indicated by the red line).
User avatar
D3thAdd3r
Posts: 3221
Joined: Wed Apr 29, 2009 10:00 am
Location: Minneapolis, United States

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by D3thAdd3r »

I was woefully not caught up on the happenings here. Just played through each of the releases, and it's fun to see the steady progress that's been happening. Lots of good things going on, and a firebar should probably be in every platforming game. Hard not to feel some inspiration to get back into some development, this is really unique in style like all your games are. Great stuff, keep this going!
User avatar
Artcfox
Posts: 1382
Joined: Thu Jun 04, 2015 5:35 pm
Contact:

Re: Mode 3 Scrolling Game Engine Demo (WIP)

Post by Artcfox »

D3thAdd3r wrote: Sat Feb 18, 2023 11:25 pm I was woefully not caught up on the happenings here. Just played through each of the releases, and it's fun to see the steady progress that's been happening. Lots of good things going on, and a firebar should probably be in every platforming game. Hard not to feel some inspiration to get back into some development, this is really unique in style like all your games are. Great stuff, keep this going!
Thanks Lee! I also really do like that firebar. It takes up 6 entity slots, because it's really just 6 synchronized entities right next to each other, but I think that's okay. I'm still planning on adding more entities, I just want to know how much space I'm going to have left after the SD card conversion, so I'm trying to get that done first.

Last night I experimented with using dconvert so I could get the ball rolling on the SD card levels, but dconvert kept on crashing when trying to get it to read a map produced with gconvert. I think it's because the C arrays that gconvert produces are pretty haphazardly written. The commas aren't in the usual spots, the hex codes aren't zero padded to make them all two digits, and it mixes decimal numbers in with hex numbers for the map size.

It seems like an easy fix to gconvert, but in case someone is relying on its haphazardly formatted output, we should probably add a new optional attribute to the XML.

I'm not too familiar with XML parsing, but following the example in gconvert_1_0.xsd, it looks like adding something like:

Code: Select all

<xs:attribute name="format" use="optional" type="FormatType"/>

  	<xs:simpleType name="FormatType">
		<xs:restriction base="xs:string">
			<xs:enumeration value="default"/>
			<xs:enumeration value="pretty"/>
		</xs:restriction>
	</xs:simpleType>
might work.

Thanks for the encouragement. I know the last 10% of a project always takes a huge amount of work, so I really appreciate it. Typically I kept my projects relatively secret while in development, but I was hoping that I could liven things up around here by posting frequent updates. And I figured that it would hold me somewhat accountable.
Post Reply