Jump to content

Recommended Posts

I was helping someone with IntyBASIC, and suggested they use GRAM card cycling for sprite animations -- that way they can make the animation sequence as long as necessary without consuming too much GRAM at once.

 

However, I then realized that this is not as straightforward in IntyBASIC because the DEFINE statement to update GRAM can only be called once per frame (or twice, with DEFINE ALTERNATE).  Each call will only accept a label or a VARPTR to a label for the source, and a card number for the target, and the number of cards to copy -- which means that the sequence of cards to update at any one time must be fixed, precluding updating the animations of multiple sprites at once. :(

 

To me the most direct solution would be to forgo the use of DEFINE for this purpose and implement a GRAM Block-Copy routine in Assembly Language, then call it from the ON FRAME event.  However, this is not really the "IntyBASIC way."

 

I wanted to know if someone else has tried to address this, of if anybody has any ideas on how to solve this.

 

The biggest limitation is that, for the copy to be efficient, it needs to unpack 16-bit words into individual bytes, and probably also unroll the loops for even more speed, which the DEFINE implementation does.  However, this is not exposed in the language, and there is no way to replicate the "MVI@, MVO@, SWAP, MVO@" optimized sequence from IntyBASIC.

 

One idea I have is to still use DEFINE, but to stagger the sprite updates, one per frame.  This will necessitate that I load not just one card per frame, but a set of cards to allow the animation to continue until its next chance comes to update.  This still consumes more GRAM, but perhaps not as much as pre-loading the entire animation sequence.  (For reference, each sprite animation sequence in Christmas Carol could take anywhere from 8 to 30+ frames of double-resolution cards.)

 

Any other ideas?

 

      -dZ.

Edited by DZ-Jay
  • Like 1

I'd love to hear if anybody has a suggestion.  It doesn't have to be code or a fully fleshed out algorithm; even some vague notion of potential approach will do. :)

 

For starters, I will experiment with the approach I mentioned before.  The idea I have is to do something like this:

  • Consider a game with 4 active objects to be animated, "A" to "D" (just to put a ceiling for my test).
  • Each animation sequence will be updated on its own frame, so each sprite gets an updated sequence on every 4th frame:
    • Frame #0: sprite A - sequence has 10 frames
    • Frame #1: sprite B - sequence has 20 frames
    • Frame #2: sprite C - sequence has 8 frames
    • Frame #3: sprite D - sequence has 32 frames
  • Let us also assume that each sprite animates at a different frame-rate, so advancing the current active card in their sequence occurs at different frames.
  • On every frame, the next 4 cards in the animation sequence for a sprite are loaded into GRAM using DEFINE, cycling through the four sprites each frame.
  • DEFINE ALTERNATE can be reserved to load other incidentals not related to sprite animation (e.g., score, status, background objects, etc.)

This is all from the top of my head, trying to work through the algorithm, so the logic may be faulty.  I would appreciate any feedback you may have.

 

 

STAGGERED SPRITE ANIMATION EXAMPLE:

 

Let us consider the execution of sprite A's animation.  The same will apply to each sprite in turn, so it should serve as an example.  We will use GRAM cards #0..3 for sprite A.

SequenceCount      = 10   ' Number of cards in animation sequence.
SequenceIndex      = 0    ' Current active animation card for sprite (from entire sequence).
SpriteCardIndex    = 0    ' Current active animation card for sprite (from GRAM set).

AnimationFrameRate = $80  ' Animation frame-rate (0.5 in Q8.8 fixed-point)
AnimationCurrSpeed = 0    ' The current animation speed accumulator

 

  • Frame #0:  (Update sprite A's GRAM)
    • Load 4 cards starting at SequenceIndex (0..3) for sprite A into GRAM using DEFINE.
    • Reset sprite card index attribute to first card in GRAM set:  SpriteCardIndex = 0
  • Frame #1:
    • Increment animation speed:  AnimationCurrSpeed = $0080
    • Check if we advance:  (AnimationCurrSpeed AND $FF00) = $0000
      • It hasn't crossed a pixel so we do not advance the sequence.
  • Frame #2:
    • Increment animation speed:  AnimationCurrSpeed = $0100
    • Check if we advance:  (AnimationCurrSpeed AND $FF00) = $0100
      • It crossed a pixel so we advance the sequence:  SequenceIndex = 1
      • We also advance the sprite's card index attribute:  SpriteCardIndex + 1 + GRAM
      • Reset speed accumulator but keep fractional part:  (AnimationCurrSpeed AND $00FF) = $0000
  • Frame #3:
    • Increment animation speed:  AnimationCurrSpeed = $080
    • Check if we advance:  (AnimationCurrSpeed AND $FF00) = $0000
      • It hasn't crossed a pixel so we do not advance the sequence.

 

  • Frame #4:  (Update sprite A's GRAM)
    • Load 4 cards starting at SequenceIndex (1..4) for sprite A into GRAM using DEFINE.
    • Reset sprite card index attribute to first card in GRAM set:  SpriteCardIndex = 0

 

And so it goes, cycling through the entire animation sequence, loading four cards at a time every 4th frame, and updating the sprite card index attribute in-between.

 

Any thoughts?

 

    -dZ.

Edited by DZ-Jay

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...