Today I continued working on polishing frame-exact implementations of object interactions and animation.
The first thing I did was improve the behavior of inbox and outbox. Instead of being a continuous, fixed-frame blinking animation, the blinking is now properly implemented as an object state update which happens every frame (this behavior is confirmed on Krissz Engine and by looking at the GDash source). Not only this allows to properly "time" the blinking when it comes to frames, it also allows to avoid the side effect of having the inbox blink during the reveal demo, something that doesn't happen in the original games or in Krissz Engine.
Also, this allowed me to properly synchronize (up to a frame) Rockford's birth, making it frame-exact and time-exact when it comes to different values of Game Speed vs. the different values of Rockford Birth Time. For example, a Rockford Birth Time of 10 yields the following behavior:
Frame 0 (initial cave state) - inbox displayed in closed state
Frame 1 - inbox blinking, open state
Frame 2 - inbox blinking, closed state
Frame 3 - inbox blinking, open state
Frame 4 - inbox blinking, closed state
Frame 5 - inbox blinking, open state
Frame 6 - inbox blinking, closed state
Frame 7 - inbox blinking, open state
Frame 8 - inbox blinking, closed state
Frame 9 - inbox blinking, open state
Frame 10 - inbox blinking, closed state
Frame 11 - inbox blinking, open state, the "crack" sound for Rockford birth plays - Rockford birth stage 1
Frame 12 - Rockford birth animation is playing, Rockford birth stage 2
Frame 13 - Rockford birth animation is playing, Rockford birth stage 3
Frame 14 - Rockford birth animation is playing, Rockford birth stage 4
Frame 15 - Rockford stationary frame is displayed, can animate if the player pushes a movement button, but can't move this frame (scanned)
Frame 16 - Rockford can move, sequence complete
This behavior is now consistent in BoulderCaves+ and Krissz Engine. Also, the cave countdown timer is also synchronized with Krissz Engine and seems to behave consistently.
Another improvement was in the area of object animation speed in general. First of all, object animations are now properly synchronized with each other (thus, diamonds would animate consistently across the cave as opposed to being animated each from a different frame). Second, the speed of object animations now closely matches what is seen on Krissz Engine, though may not yet be completely cycle-accurate and needs a bit more testing. Then again, even if it's not 100% cycle-accurate, I don't think anyone will notice the minimal possible difference except in very thorough, possibly slow motion side-by-side comparisons.
Interestingly, I also found an alternative use for animation callbacks that I removed previously - instead of tying them into the cave scan order (a big no-no, as explained above), I wired them as a form of "fallback code" that would wrap up pending animations such as explosions after the game is over. When the cave is won, the regular cave scan stops - thus, if there are pending explosion animations happening, they will never end if they rely purely on the CSO update. Thus, animation callbacks will now be used as a form of fallback to catch those "dangling" animations and finish them correctly instead of looping them again and again. For example, it's possible in the rare corner case in Dustin's CSO 77 where Rockford blows up with the outbox right after triggering the outbox and winning the game. Unless this animation is "caught" and completed using a callback that would inform the animation system to stop animating the explosion and display an empty tile instead, it will repeat itself until the game is completely stopped.
Among other news, I started pondering over the possible Infinite Scroll implementation. It's a rather complex feature that might require quite a bit of refactoring/rewrite of the existing BoulderCaves code base, but I'm eventually figuring things out as to how they might work. Mechanically, at least so far, Infinite Scroll appears to be mostly a "view" thing where the cave scanning order remains the same and the "model" (e.g. the cave and its mechanics) is unaffected regardless of whether Infinite Scroll is active or not, but the playfield is displayed differently - essentially, in Infinite Scroll mode, it sort of "wraps around" on overflow or underflow, showing an extended view of the playfield. I haven't yet found any specific side effect workarounds that would work differently between Infinite Scroll and non-Infinite Scroll standard open border implementations, but I will test more things as I progress in figuring out this feature.
I also tested some more CSO effects and confirmed them to work. So far, so good. Stay tuned for more updates
- Agetian