Jump to content
New account registrations are disabed. This website is now an archive. Read more here.
  • 0
azdesign

How to properly runs animation without interfering with main loop

Question

Hello everyone, nice to meet you,

I made a custom class to display character portrait in RPGMaker XP Here is the class :

 

class Poser
 attr_accessor :images

 def initialize
   @images = Sprite.new
   @images.bitmap = RPG::Cache.picture('Character.png') #100x300
   @images.x = 540 #place it on the bottom right corner of the screen
   @images.y = 180
 end
end

 

Create an event on the map to create an instance as global variable, tada! image popped out. Ok nice. But Im not satisfied, Now I want it to have bobbing-head animation-like (just like when we breathe, sometimes bob our head up and down) so I added another method :

 

def move(x,y)
   @images.x += x
   @images.y += y
 end

 def animate(x,y,step,delay)
   forward = true
   2.times {
     step.times {
       wait(delay)
       if forward
         move(x/step,y/step)
       else
         move(-x/step,-y/step)
       end
     }
     wait(delay*3)
     forward = false
   }
 end

 def wait(time)
   while time > 0
     time -= 1[/color]
     Graphics.update
   end
 end

 

I called the method to run the animation and it works, so far so good, but the problem is, WHILE the portrait goes up and down, I cannot move my character until the animation is finished.

 

So that's it, I'm stuck in the loop block, what I want is to watch the portrait moving up and down while I walk around village, talk to npc, etc.

 

Anyone has suggestion for better logic for playing animation ?

Edited by azdesign

Share this post


Link to post
Share on other sites

6 answers to this question

Recommended Posts

  • 0

Instead of having a separate loop, you sync it with the main loop. Basically when you want it to do something, you simply set a "loop_count" or however you want to name it. The normal update method of the class you are working in can handle what to do when the loop_count is at certain values. Here's an example:

 


class MySprite : RPG:Sprite

 # This is the wrong way
 def fade_out(frames)
   while frames > 0
     self.opacity -= 1
     Graphics.update
     frames -= 1
   end
 end

#-------------------------------------------------------------

# This is the correct way

 def fade_out(frames)
   @fade_duration = frames
 end

 def update
   super
   if @fade_duration != nil
     self.opacity -= 1
     @fade_duration -= 1
     if @fade_duration <= 0
       @fade_duration = nil
     end
   end
 end
end

Share this post


Link to post
Share on other sites
  • 0

Wow thanks, it never crossed my mind to let the graphic update do the work instead of having my own loop. I'll try it, really, thanks for the input :D

Share this post


Link to post
Share on other sites
  • 0

@ForeverZero : I think I have a problem, the update method is not called automatically, here is the example code :

 

class MySprite < RPG::Sprite

 def initialize
super
@image = Sprite.new
@image.bitmap = RPG::Cache.picture('picture.png')
 end

 def fade_out(frames)
@fade_duration = frames
 end

 def update
super
if @fade_duration != nil
  self.opacity -= 1
  @fade_duration -= 1
  if @fade_duration <= 0
	@fade_duration = nil
  end
end
 end
end

 

then in a map, I create 2 events, one which create an instance of MySprite class in a global variable and the others calls fade_out movement

 

trigger the creation event, the image popped out, then when I trigger the fade_out method from another event, it does nothing

 

Do you have a solution ?

Edited by azdesign

Share this post


Link to post
Share on other sites
  • 0

The code I posted is in no way a working example, it was just a demonstration of the logic to do it in. Obviously you will have to update whatever it is that you are making.

 

Whatever scene or class your class deals with, create its instance within that class, and add its update to the parents update. For example, using the above example:

 

 

class Scene_Map

 alias setup_mySprite main
 def main
   @mySprite = MySprite.new
   init_mySprite
   @mySprite.dispose
 end

 alias update_mySprite update
 def update
   update_mySprite
   @mySprite.update
 end
end

 

If you look at the default scripts, you will see plenty of examples of this. For example, Scene_Map is a container for Spriteset_Map, which is in turn a container for all the map sprites. Spriteset_Map is updated by Scene_Map, and it in turn updates all the sprites within its update method.

Share this post


Link to post
Share on other sites
  • 0

Very nice, I create class instance in Scene_Map with the update call on its main's loop and the animation works just like how I want it to be. Thanks, I have so many things to learn yet. Oh, one question, between these scenario, which one is the most effective/proper for animation ?

 

1. Dispose the image, set the new coordinates, re-draw the image with the new coordinates

2. just change the existing image's attributes without redraw/clear

 

I wonder because there is 40 or 60 times in a second the program repeat this and I don't want the performance to drop (just like my first game-dev attempt making ping pong with openGL in java, re-draw ALL images per frame including the static images and its lag as hell, should only re-draw the moving one)

 

Btw, thanks really, you solved my problem :D

Share this post


Link to post
Share on other sites
  • 0

Just change the sprite coordinates there is no need to dispose until you are done with it, such as the scene ends, etc.

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...