Gameboy Development Forum

Discussion about software development for the old-school Gameboys, ranging from the "Gray brick" to Gameboy Color
(Launched in 2008)

You are not logged in.

Ads

#1 2019-08-17 18:57:22

Sin
New member
Registered: 2019-08-11
Posts: 8

Animation, Timing, and Delays

After a bit more working on my first simple game I have run into another issue which I did not find any solution for searching through the forums and Wiki.

My game includes a user moving a sprite left and right on the bottom of the screen in an attempt to catch falling food items. I am current using move_sprite for both the falling items and the player. However, my player also has an animation that changes depending on if the user moves left or right. The issue is that in order to delay the animation so that it actually shows (ie doesn't move too fast) I am using the delay() function. When the user moves, and thus the character animates, it delays the falling items as well. This causes the falling items to stop mid fall during the delay time of the character animation.

I have played around with it, and it appears that I can bypass this delay issue when I use scroll_sprite() for the falling items. However, I am unable to figure out how to track the x and y coordinates of the falling sprites so that I can do collision and reset functions when it hits the bottom of the screen.

So my questions are, is it possible use delay() for only one part of the program without delaying the entire game? Or perhaps there is another way to delay the timing of the animation and character movement that might work better in this instance? Or, if I decide to use scroll_sprite for the falling items, is there a good way to keep track of the x and y coordinates of these items for my other game functions?

Offline

 

#2 2019-08-18 07:32:06

Robbi_Blechdose
Member
Registered: 2017-12-10
Posts: 27

Re: Animation, Timing, and Delays

You shouldn't use delay() at all. It quite literally burns CPU cycles, a.k.a. waste battery power.
Instead, you should always put the CPU "to sleep" when your code for that frame is done.

For your problem: Utilize a counter, and only update your animation / movement whenever the counter hits a certain value, then reset it.

Offline

 

#3 2019-08-18 10:37:05

Sin
New member
Registered: 2019-08-11
Posts: 8

Re: Animation, Timing, and Delays

Robbi_Blechdose,

Thanks for that, wasn't aware of it! Do you happen to know of any examples of this being done? I'm wondering if utilizing a counter would also cause the animations to play to quickly still?

Offline

 

#4 2019-08-18 13:29:40

bbbbbr
Member
Registered: 2019-03-04
Posts: 23

Re: Animation, Timing, and Delays

Haven't checked that it compiles, but this is an example of the basic idea smile

With a counter, you can adjust the speed of each animation individually. For instance, below you might change the value of FRAMES_TILL_ANIM_UPDATE. A larger value will make the animation run more slowly.

You might also consider using ZGB. It provides a lot of these features built-in without having to write them.

Using a simplified version of this example:
https://github.com/mrombout/gbdk_playgr … nimation.c

From this :

Code:

    while(1) {
        set_sprite_tile(0, 4);
        delay(500);
        set_sprite_tile(0, 0);
        delay(500);
    }

To something like this:

Code:

    // Update animation every ten frames
    #define FRAMES_TILL_ANIM_UPDATE  10

     // Number of animation tiles
     // (could use sizeof(animation_tiles), but keeping this simple for now)
    #define ANIM_COUNT_TILES  2

    // List of tiles to rotate through
    unsigned char animation_tiles[ANIM_COUNT_TILES] = {4,0};

    int frame_count;
    int animation_counter;

    frame = 0;
    animation_counter = 0;

    // Set initial animation frame
    set_sprite_tile(0, animation_tile[animation_counter]);


    while(1) {

        frame_count++;

        // If the frame counter reached the threshold, update the animation
        if (frame_count >= FRAMES_TILL_ANIM_UPDATE) {

            // Reset frame counter
            frame_count = 0;

            // move to next animation tile, wrap around if at the end of the list (zero indexed)
            animation_counter++;
            if (animation_counter >= ANIM_COUNT_TILES)
                animation_counter = 0;

            // Set the animation frame
            set_sprite_tile(0, animation_tile[animation_counter]);
        }
    }

Last edited by bbbbbr (2019-08-18 13:36:37)

Offline

 

#5 2019-08-18 16:23:23

Sin
New member
Registered: 2019-08-11
Posts: 8

Re: Animation, Timing, and Delays

bbbbbr,

Thank you very much, that makes some sense! I failed to get ZGB to install correctly I think. I set my PATH and unzipped it but never got further than that. Might have to take another look into it.

Offline

 

#6 2019-08-18 16:34:35

bbbbbr
Member
Registered: 2019-03-04
Posts: 23

Re: Animation, Timing, and Delays

There is another simple game engine built on top of GBDK. I haven't seen mention of it's use, but perhaps it's worth as well:
https://kevind-portfolio.blogspot.com/2 … ed-on.html
https://bitbucket.org/HellSuffering/ret … rc/master/

Offline

 

#7 2019-08-24 15:41:34

Sin
New member
Registered: 2019-08-11
Posts: 8

Re: Animation, Timing, and Delays

I rewrote the code using delays based on looping and was able to get my character to animate roughly the same as I had with the delay function. However I am still having the same initial problem where my falling items stop midair during movement of my character.

If that doesn't make sense, here is a screen recording of it in action.

https://ufile.io/en0ttv6o

Offline

 

#8 2019-08-25 13:05:01

bbbbbr
Member
Registered: 2019-03-04
Posts: 23

Re: Animation, Timing, and Delays

Do you have your source posted anywhere online? That may make it easier to understand what is happening.

Offline

 

#9 2019-08-25 13:21:06

Sin
New member
Registered: 2019-08-11
Posts: 8

Re: Animation, Timing, and Delays

bbbbbr wrote:

Do you have your source posted anywhere online? That may make it easier to understand what is happening.

See below, I apologize for the lack of commenting at this time and there is some commented out duplication of code until I determined which worked best to prevent this issue (tried scroll_sprite and move_sprite)


Code:

#include <gb/gb.h>
#include <stdio.h>
#include <stdlib.h>
#include "kappa.c"
#include "drops.c"
#include "dropitems.c"
#include "backgroundtiles.c"
#include "fujimap.c"



void performantdelay(UINT8 numloops)
{
    UINT8 i;
    for(i = 0; i < numloops; i++)
    {
        wait_vbl_done();
    }
}


void main(){
   int i;
   int x = 55;
   int y = 136;
   int char_x = 55;
   int char_y = 136;
   int ax = 151;
   int ay = -100;
   int seeda[] = {5, 2, 9, 1, 4, 7, 6, 3, 0};
   int bx = 103;
   int by = 0;
   int seedb[] = {9, 0, 3, 1, 6, 2, 4, 7, 5};
   int n_count = 0;

set_bkg_data(0,103, backgroundtiles);
set_bkg_tiles(0,0, 20, 18, fujimap);

SHOW_BKG;
DISPLAY_ON;


   SPRITES_8x16;
   set_sprite_data(26,16,kappa);
   set_sprite_tile(0,26);
   move_sprite(0,char_x,char_y);
   set_sprite_tile(1,28);
   move_sprite(1,char_x+8, char_y);

    set_sprite_data(42,8,drops);

    set_sprite_tile(2,42);
   move_sprite(2,ax, ay);
    set_sprite_tile(3,44);
 move_sprite(3,ax + 8, ay);

 //  set_sprite_tile(4,42);
 //  move_sprite(4,bx, by);
  //  set_sprite_tile(5,44);
 //move_sprite(5,bx + 8, by);


   SHOW_SPRITES;

    while(1)
    {
              by += 5;
            //  ay += 17;
           // scroll_sprite(2,0,1);
           // scroll_sprite(3,0,1);
           // scroll_sprite(4,0,1);
           // scroll_sprite(5,0,1);
performantdelay(2);
              move_sprite(2,bx, by);
              move_sprite(3,bx + 8, by);
             // move_sprite(4,ax, ay);
             // move_sprite(5,ax + 8, ay);
             

          if (ay >= 144)
          {
              n_count++;
              ay = 0;
              ax = 151;
              ax -= (seeda[n_count] * 16);
              move_sprite(2,ax, 0);
              move_sprite(3,ax + 8, 0);
          }

          if (by >= 144)
          {
              n_count++;
              by = 0;
              bx = 151;
              bx -= (seedb[n_count] * 16);
              move_sprite(2,bx, 0);
              move_sprite(3,bx + 8, 0);
          }

      


switch(joypad())
            {
            case J_LEFT: 
                if(char_x > 10){
                for(i = 0; i < 1000; i++)
                    {
                        if (i == 10){
                            char_x -= 16;
                            move_sprite(0,char_x,char_y);
                            move_sprite(1,char_x+8,char_y); 
                            set_sprite_tile(0,26);
                            set_sprite_tile(1,28);
                        }

                            if (i > 11 && i <= 100){
                            set_sprite_tile(0,30);
                            set_sprite_tile(1,32);
                        }

                            if (i > 101 && i <= 20){
                            set_sprite_tile(0,30);
                            set_sprite_tile(1,32);
                        }

                        if (i >= 201 && i <= 300){
                            set_sprite_tile(0,38);
                            set_sprite_tile(1,40);
                        }
                        if (i >= 301 && i <= 400){
                            set_sprite_tile(0,26);
                            set_sprite_tile(1,28);
                        }

                    }
                }
                break;
             case J_RIGHT: 
                 if(char_x < 150){
                    for(i = 0; i < 1000; i++)
                    {
                        if (i == 10){
                            char_x += 16;
                            move_sprite(0,char_x,char_y);
                            move_sprite(1,char_x+8,char_y); 
                            set_sprite_tile(1,28);
                            set_sprite_tile(0,26);
                        }

                        
                            if (i > 11 && i <= 100){
                            set_sprite_tile(0,30);
                            set_sprite_tile(1,32);
                        }

                            if (i > 101 && i <= 20){
                            set_sprite_tile(0,30);
                            set_sprite_tile(1,32);
                        }

                        if (i >= 201 && i <= 300){
                            set_sprite_tile(0,38);
                            set_sprite_tile(1,40);
                        }
                        if (i >= 301 && i <= 400){
                            set_sprite_tile(0,26);
                            set_sprite_tile(1,28);
                        }

                    }

                 }
                break;  
             
            }//joypad



    }//while

}   //main

Offline

 

#10 2019-08-26 15:50:01

bbbbbr
Member
Registered: 2019-03-04
Posts: 23

Re: Animation, Timing, and Delays

It looks like you are starting the animation once the player presses Left or Right, then waiting until that animation has finished before returning to the main loop.

Code:

switch(joypad())
            {
            case J_LEFT: 
                if(char_x > 10){
                for(i = 0; i < 1000; i++)  // <---- This will block execution of everything else until it's done
                    {
                        if (i == 10){
                         .....
                         .....

In addition, the other sprite only gets moved during the main loop. So if execution of the main loop is blocked for the entire time your animation runs, then that will  cause the sprite in the main loop to stop during that the whole time.

What you want to do is move the animation so that it gets handled during the main loop without blocking it, a little bit each time the main loop cycles through. Which means some kind of incrementing counter in the main loop, then checking to see whether you need to update the animation based on the counter (you'll also want a way to determine when to start/stop the animation as well since the counter in the main loop will always run).

Last edited by bbbbbr (2019-08-26 16:10:10)

Offline

 

#11 2019-08-26 18:09:15

Sin
New member
Registered: 2019-08-11
Posts: 8

Re: Animation, Timing, and Delays

bbbbbr wrote:

It looks like you are starting the animation once the player presses Left or Right, then waiting until that animation has finished before returning to the main loop.

Code:

switch(joypad())
            {
            case J_LEFT: 
                if(char_x > 10){
                for(i = 0; i < 1000; i++)  // <---- This will block execution of everything else until it's done
                    {
                        if (i == 10){
                         .....
                         .....

In addition, the other sprite only gets moved during the main loop. So if execution of the main loop is blocked for the entire time your animation runs, then that will  cause the sprite in the main loop to stop during that the whole time.

What you want to do is move the animation so that it gets handled during the main loop without blocking it, a little bit each time the main loop cycles through. Which means some kind of incrementing counter in the main loop, then checking to see whether you need to update the animation based on the counter (you'll also want a way to determine when to start/stop the animation as well since the counter in the main loop will always run).

Moved everything out and modified the structure and it worked like a charm!

I really appreciate it!

Offline

 

Board footer

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson