Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411573 Posts in 69386 Topics- by 58444 Members - Latest Member: darkcitien

May 04, 2024, 03:57:16 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)hopping
Pages: [1] 2
Print
Author Topic: hopping  (Read 6154 times)
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« on: May 11, 2009, 01:59:43 PM »

This is again an overly simple/obvious question which I can't figure out after some amount of trial and experimentation, but how would you code a hopping motion from an overhead perspective?

As an example, the motion of the Pol's Voice or Tektites in Zelda 1. They don't move straight, but instead hop from location to location.





For those who haven't played Zelda 1, the movement of the enemies between 12 and 15 seconds in and between 25 and 28 seconds in this video is what I mean. I know it happens quick, but it's a speedrun.
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #1 on: May 11, 2009, 02:12:22 PM »

1)Pick a nearby (valid) point.
2)Hop to it.
3)Repeat
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #2 on: May 11, 2009, 02:19:32 PM »

I'm not sure how to apply that -- would x be one side of the equation and y the other side? How would the target location and starting location be involved so that you could be sure it'd land on that spot?
Logged

Matt Thorson
Level 7
**

c'est la vie


View Profile WWW
« Reply #3 on: May 11, 2009, 02:22:00 PM »

You might be able to use a sine wave to add to the y position as the x/y move to where you're hopping to.
Logged

ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #4 on: May 11, 2009, 02:25:37 PM »

I tried correlating the vspeed with a sine wave, yes, but that didn't turn out that well (they just seemed to move up and down like a wave rather than hop). Perhaps the absolute value of a sine wave? cause right now all I get with it is like ~~~~~
Logged

Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #5 on: May 11, 2009, 02:27:32 PM »

your x would be an arbitrary value that you would advance in the direction vector and your y would be y. It would make the most sense to just use a normalized (0-1) value and multiply your distance by it when moving, so that you're always dealing with the same numbers.

You could also use an arc of the sine wave to do it, or just do a very simple gravity/velocity simulation and just apply a Y velocity and let gravity take care of the curve.
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
nihilocrat
Level 10
*****


Full of stars.


View Profile WWW
« Reply #6 on: May 11, 2009, 04:40:08 PM »

or just do a very simple gravity/velocity simulation and just apply a Y velocity and let gravity take care of the curve.

Many moons ago, I didn't really know that a quadratic equation ended up looking like this, but got the desired effect through doing it this way which is quite a bit simpler from a math standpoint.
Logged

pgil
Guest
« Reply #7 on: May 11, 2009, 04:41:25 PM »

How about giving the character's position a z-component? 0 means the character is on the ground. Then give it a variable zspeed, and create some gravity (increasing zspeed until z >= 0)..

Then when drawing the sprite, do something like:
sprite_draw(x,y+z,.....)

Of course, that's just the cosmetic part...

As for making a hop to a specific location.. well I failed trigonometry...
but if you're using Game Maker, it does have a couple of functions that could help you figure out the movement:

something like
Code:
var dist = point_distance(xfrom,yfrom,xto,yto)
var dir  = point_direction(xfrom,yfrom,xto,yto)

hspeed = .4 * lengthdir_x(dist,dir)
vspeed = .4 * lengthdir_y(dist,dir)

What this does is give you the x and y speed that you need to hop to a particular position.

Sorry if I'm totally incoherent...  Beer!
« Last Edit: May 11, 2009, 04:54:31 PM by pgil » Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #8 on: May 11, 2009, 04:44:13 PM »

That zspeed idea actually sounds the most common sense to me, and easiest to code, I'll try that first, thanks!
Logged

nihilocrat
Level 10
*****


Full of stars.


View Profile WWW
« Reply #9 on: May 11, 2009, 04:52:26 PM »

As for making a hop to a specific location.. well I failed trigonometry...
but if you're using Game Maker, it does have a couple of functions that could help you figure out the movement:

Code:
lengthdir_x(len,dir) Returns the horizontal x-component of the vector determined by the indicated length and direction.
lengthdir_y(len,dir) Returns the vertical y-component of the vector determined by the indicated length and direction.

I believe the incantation you want is this:

x = sin(dir) * len
y = cos(dir) * len

For a 'normal' coordinate system where 10,10 is 10 pixels right, 10 pixels up.
For a 'sinking' coordinate system, seen in many graphics libraries, that would mean 10 pixels right, 10 pixels down. You have to make this adjustment:

x = cos(dir) * len
y = sin(dir) * len

This is the first bit of gaming-related math I ever learned, in order to move a triangle in an Asteroids-like game.
Logged

pgil
Guest
« Reply #10 on: May 11, 2009, 04:56:43 PM »

Yeah.. I think that's pretty much what those two functions in Game Maker do. Just without all that scary math  Durr...?
Logged
Xion
Pixelhead
Level 10
******



View Profile WWW
« Reply #11 on: May 11, 2009, 05:00:08 PM »

yar, I was gunna suggest the zspeed thing but you beat me to it. I've done this before and that was pretty much how I ended up going about it.
Logged

Sam
Level 3
***



View Profile WWW
« Reply #12 on: May 11, 2009, 05:28:40 PM »

I haven't written any code in a month!  Hope it makes sense.

Code:
//local variables:
var x:number;
var y:number;
var targetX:number;
var targetY:number;
var hopYChange:number;
var hopXChange:number;
var hopCount:int;
var hopStepNum:int;
var hopping:boolean = false;
const hopHeight:number = 200;

function hopTo(tarX:number, tarY:number, durationOfHop:int):void
{
   if (!hopping)
   {
      targetX = tarX;
      targetY = tarY;
      hopStepNum = durationOfHop;
      //what net change in X and Y value needs to take place over this hop?
      hopXChange = targetX - x;
      hopYChange = targetY - y;
      hopping = true;
      hopCount = 0;
   }
}

function update():void
{
   if (hopping)
   {
      //check for having finished this hop
      if (hopCount >= hopStepNum)
      {
         //finish off this hop by making sure we're at the correct target position
         //  hopefully we're there already, but good to be sure I guess.
         x = targetX;
         y = targetY;
         hopping = false;
      }
      else
      {
         //the horizontal part of the hop:
         //   velX is constant throughout the hop, so could calculate it just once.
         var velX:number = hopXChange / hopStepNum;
         x = x + velX;

         //the vertical part of the hop:
         //   adding velY to y each frame should form a nice arc
         var velY:Number = (hopHeight - (hopHeight*2 * hopCount/hopStepNum) - hopYChange) / hopStepNum;
         y = y - velY;

         //increment the hop's frame counter.
         hopCount = hopCount + 1;
   }
}

Something like this would work (vaguely written in Actionscript.)  Assuming this is in a class definition for something that's going to do some hopping.  The update() function would be called every frame, and the hopTo() called whenever you want to start a new hopping action.

The idea is it can cope with hopping to any position you desire, and take however many 'frames' (where one frame is one call to update()) you like.

I'm too sleepy to explain the calculation of velY.  But it works, which is nice.

I tidied up the code a little to make it actually compile.  Clicky!  Click anywhere and the circle will 'hop' over to it, taking 30 frames (1 second) to do it, and jumping 'up' 150 pixels.

I see I missed a million replies whilst typing this, so who knows if this fits in the thread any more!
Logged
Sam
Level 3
***



View Profile WWW
« Reply #13 on: May 12, 2009, 01:47:38 AM »

For fun, I implemented the z-movement method described above.  I think it makes more sense than the way I used, and lets you do things like draw a shadow very easily.  I'm also more confident that it's actually doing exactly as I wanted it to.  Clicky!

When a hop begins:
Code:
velX = (targetX - x) / numberOfFramesToTake;
velY = (targetY - y) / numberOfFramesToTake;
velZ = -10;

Then each frame during the hop:
Code:
x += velX;
y += velY;
//apply just enough "gravity" for z to return to 0 at the end of the hop
velZ += (20 / (numberOfFramesToTake + 1));
z += velZ;

when I detect that the jump is over (when a frame counter is equal to or greater than numberOfFramesToTake) I force the x,y,z values to be as they should be.  That corrects for any floating point errors, or my code being slightly off Durr...?
Code:
x = targetX;
y = targetY;
z = 0;

Draw the shadow at
Code:
(x, y)

..and the object itself at
Code:
(x, y + z)

Very neat!

edit:
Thinking about it, it would be better to apply the same gravity force for all hops (no matter how many frames they take) and instead vary the initial value of velZ so that the hop lasts the correct number of frames.  That way if you have many things hopping with different hop durations, they'll seem to be being influenced by the same physics.
« Last Edit: May 12, 2009, 01:54:06 AM by Salt » Logged
ChevyRay
Guest
« Reply #14 on: May 12, 2009, 03:44:07 AM »

This is the formula you want, if you want a nice smooth sin curve:
Code:
z = sin((dist_hopped / hop_length) * pi) * hop_height;
Where dist_hopped is the distance from your start point and current position, and hop_length is the distance from your start point to the landing point, and hop_height is the peak z height of the current hop.

I made an example in Game Maker, since I'm assuming this is for SD? Here it is: http://properundead.com/examples/hopexample.zip.

This was my approach, and it worked just fine (though you'd have to tweak it to get the behaviour how you wanted it. eg: prevent object from hopping too many times in one general direction, etc.)

creation event:
Code:
z = 0;            // height from ground
move_spd = 2;     // movement speed

hopping = false;  // if the player is hopping
hop_min = 20;     // minimum distance that can be hopped
hop_max = 80;     // maximum distance that can be hopped
hop_x = x;        // x position of the landing point
hop_y = y;        // y position of the landing point
hop_height = 0;   // the peak z value of the current hop
hop_timer = 60;   // how long to wait between hops (frames)
hop_at = 0;       // how far we are in the hop
hop_dist = 0;     // how long the total hop is
hop_dir = 0;      // the direction from the start point to the landing point

alarm[0] = hop_timer;

In the alarm[0] event...
Code:
// CHOOSE A DIRECTION AND DISTANCE TO HOP

hop_dist = hop_min + random(hop_max);
hop_dir = random(360);

// DETERMINE THE LANDING POINT

hop_x = x + lengthdir_x(hop_dist, hop_dir);
hop_y = y + lengthdir_y(hop_dist, hop_dir);

// START HOPPING

hop_height = hop_dist;
hopping = true;

And in the step event...
Code:
if (hopping){

// DETERMINE THE CURRENT HEIGHT

hop_at += move_spd;
z = sin((hop_at / hop_dist) * pi) * hop_height;

// MOVE TOWARDS THE LANDING POINT

x += lengthdir_x(move_spd, hop_dir);
y += lengthdir_y(move_spd, hop_dir);

// CHECK IF WE'VE LANDED AND RESET THE TIMER IF SO

if (hop_at >= hop_dist){
  hopping = false;
  x = hop_x;
  y = hop_y;
  z = 0;
  alarm[0] = hop_timer;
}

}

And this is how you would draw it:
Code:
var X, Y, Z;
X = round(x);
Y = round(Y);
Z = round(Z);

draw_sprite(spr_shadow, -1, X, Y);
draw_sprite(spr_character, -1, X, Y - Z);

Here are some other tricks you can do with it:

When (hop_at < hop_dist/2) it means you are moving upwards.
When (hop_at > hop_dist/2) it means you are moving downwards.
You could also set a hop_ratio, which would be a ratio of the hopping height to the distance to be hopped. So if it was set to 2, you would jump twice as high as the hop length. If it was .5 you'd jump half the hop length. A low ratio would end up in shallow, low jumps, while a high ratio would end up in steep arcing jumps. You'd apply it like this, in the last part of the alarm[0] event:
Code:
// START HOPPING

hop_height = hop_dist * hop_ratio;
hopping = true;
« Last Edit: May 12, 2009, 03:59:10 AM by ChevyRay » Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #15 on: May 12, 2009, 04:38:39 AM »

yep, for SD. will look at the example, thanks for it and for the other code people have written.
Logged

ChevyRay
Guest
« Reply #16 on: May 12, 2009, 04:44:01 AM »

Oh, and I forgot to mention. If you want to make every hop take the same amount of time, set the movement speed to a division of the hop_dist... so when you jump, setting move_spd to hop_dist / 60 will make every jump take 60 frames. Etc.

Also, you can use the sine ratio [sin((hop_at / hop_dist) * pi)] (which is equal to 0-1, 1 at the peak of your jump and 0 at either end) to scale your object as well. So you could set image_xscale and image_yscale to 1 + s / 2 (where s is the ratio), so your objects appear bigger the higher they are up.

I don't know if that'll look good or not, though.
Logged
ChevyRay
Guest
« Reply #17 on: May 12, 2009, 04:52:24 AM »

Oh damn, I just realized Embarrassed if you're using a static speed, you don't have to calculate the lengthdir_x and lengthdir_y movement every step. Just calculate those values when the jump initiates in alarm[0], and save them into variables (like hop_h and hop_v), then just move by those values. Otherwise you're making extra calculations, because it's gonna be the same every time Tongue and I know you're trying to keep the FPS up with SD.
Logged
salade
Level 4
****



View Profile
« Reply #18 on: May 12, 2009, 10:53:21 AM »

sin curve? wouldn't it be much more realistic(and easier) to set up a quadratic?

ah, it has already been suggested.

the only question now: which one is faster to calculate?
Logged
ஒழுக்கின்மை (Paul Eres)
Level 10
*****


Also known as रिंकू.


View Profile WWW
« Reply #19 on: May 12, 2009, 11:20:04 AM »

Nobody really explained what it means to "set up a quadratic" though.
Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic