Please login or register.

Login with username, password and session length
Advanced search  

News:

This forum provides RSS feed. To query recent posts use this url. More...


Author Topic: Moving non-actor entities towards an XY position  (Read 9108 times)

0 Members and 1 Guest are viewing this topic.

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Moving non-actor entities towards an XY position
« on: March 01, 2012, 09:26:39 AM »

Hi all,

I have a puzzle set up with a few objects (entities) and hotspots (regional entities). When you click on an object, I enable the vacant hotspots that the object can move in to.

Instead of simply skipping to the new location, I would like the objects to "slide" over to the new XY positions. I need something similar to the GoTo method for actors, but for entities.

I tried the following, but the object doesn't move smoothly a straight path, which I can understand why is happening. (It's reaching it's new X position before the Y position, or vice versa)

To explain the code:
EyesActivePiece = the puzzle piece that needs to move
this = the hotspot you click on that contains the object's new XY coordinates
cpX and cpY = the hardcoded X and Y coordinates of the hotspot that the object must move towards

I really appreciate your help. Thanks!

Code: [Select]
var moving = true;
while (moving)
{
if (this.cpX > EyesActivePiece.X)
EyesActivePiece.X = EyesActivePiece.X + 1;
else
EyesActivePiece.X = EyesActivePiece.X - 1;

if (this.cpY > EyesActivePiece.Y)
EyesActivePiece.Y = EyesActivePiece.Y + 1;
else
EyesActivePiece.Y = EyesActivePiece.Y - 1;

if ((EyesActivePiece.X == this.cpX) && (EyesActivePiece.Y == this.cpY))
moving = false;

Sleep(5);
}
Logged

jackslawed

  • Lurker
  • *
  • Karma: 4
  • Offline Offline
  • Posts: 23
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #1 on: March 01, 2012, 01:13:27 PM »

I use "for" loops for this rather than if statements. Something like this example:
Code: [Select]

//this moves the object from -75 to 1100 (x coordinate)
for (i = -75; 1<1100; i=i+3)
{
this.X = i;
this.Y = this.Y -1;
Sleep(25);
}

The i=i+3 and the Sleep(number) can be tweaked to alter the speed.

You could also make a custom method, and then call that whenever you need to.

I realize that you need to move smoothly in both axes... so you will need a slightly more complicated equation in your for loop... but I hope this is helpful.
Logged

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #2 on: March 02, 2012, 02:12:08 AM »

Thanks jackslawed, though I think I would still need an if statement to check if X or Y is greater/less than to make sure the object is moving in the correct direction (+ / -)

But yes, I need some equation to get the object moving at equal speeds on both axis!
Logged

metamorphium

  • Global Moderator
  • Addicted to WME forum
  • *
  • Karma: 12
  • Offline Offline
  • Gender: Male
  • Posts: 1511
  • Vampires!
    • View Profile
    • CBE  software s.r.o.
Re: Moving non-actor entities towards an XY position
« Reply #3 on: March 02, 2012, 09:02:28 AM »

you are looking for standard linear movement.

To help you out, I threw together a quick, untested example.

Code: WME Script
  1. method LinearMovement(movingEntity, startX, startY, endX, endY)
  2. {
  3.     var dX = Math.Abs(endX - startX);
  4.     var dY = Math.Abs(endY - startY);
  5.    
  6.     var dirX = 1;
  7.     if (startX > endX) dirX = -1;
  8.  
  9.     var dirY = 1;
  10.     if (startY > endY) dirY = -1;
  11.  
  12.     var diff = dirX - dirY;
  13.    
  14.     var posX = startX;
  15.     var posY = startY;
  16.    
  17.     while (posX != endX && posY != endY)
  18.     {
  19.          movingEntity.X = posX;
  20.          movingEntity.Y = posY;
  21.          
  22.          var dblDiff = 2 * diff;
  23.          
  24.          if (dblDiff > (-1 * dY))
  25.          {
  26.               diff = diff - dY;
  27.               posX = posX + dirX;
  28.          }
  29.  
  30.          if (dblDiff < dX)
  31.          {
  32.               diff = diff +dX;
  33.               posY = posY + dirY;
  34.          }
  35.  
  36.          Sleep(20);
  37.     }
  38.  
  39. }
  40.  

It's the standard error correction approach used in many algorithms, this is particulary implementation of ancient Brensenham.

Keep in mind that it might contain some slight errors you need to fix yourself since I can't test it here. :)
« Last Edit: March 03, 2012, 12:29:12 PM by metamorphium »
Logged
J.U.L.I.A. Enhanced Edition, Vampires!, J.U.L.I.A., J.U.L.I.A. Untold, Ghost in the Sheet

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #4 on: March 03, 2012, 05:38:47 AM »

Thank you so much, metamorphium! This worked  :D

The only thing I had to change was a slight typo: var posY = startY;
Logged

metamorphium

  • Global Moderator
  • Addicted to WME forum
  • *
  • Karma: 12
  • Offline Offline
  • Gender: Male
  • Posts: 1511
  • Vampires!
    • View Profile
    • CBE  software s.r.o.
Re: Moving non-actor entities towards an XY position
« Reply #5 on: March 03, 2012, 12:29:41 PM »

thanks for the catch. I repaired it in the original post for everyone to get the proper code :)
Logged
J.U.L.I.A. Enhanced Edition, Vampires!, J.U.L.I.A., J.U.L.I.A. Untold, Ghost in the Sheet

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #6 on: March 07, 2012, 12:17:28 AM »

I'm not sure how the Sleep function works. The pieces move very slowly when I enter any value greater than or equal to 1 (it was at 20 first). Just to experiment, I put 0.99 and the pieces moved very quickly. So they either move super fast or super slow.

Strangely, the Sleep function was working fine at first..
Logged

Mnemonic

  • WME developer
  • Administrator
  • Addicted to WME forum
  • *
  • Karma: 41
  • Offline Offline
  • Gender: Male
  • Posts: 5683
    • View Profile
    • Dead:Code Site
Re: Moving non-actor entities towards an XY position
« Reply #7 on: March 07, 2012, 07:26:22 AM »

Sleep accepts a number of milliseconds (therefore passing a decimal number to it is pointless). But since the script is updated once per frame, you need to take framerate of your game into account. For example, if your game runs at 60 frames per second (typical for LCD monitors), it means one frame takes 1000 / 60 = 16.666 milliseconds to be processed. That means using Sleep value lower than 16 has no effect, because the script cannot be updated faster than that anyway. Using low Sleep values makes your game speed dependent on framerate, which is a bad thing(tm).

The correct approach is to use the time elapsed since last frame (you can use Game.CurrentTime for that) and use it to multiply the movement speed. That way, if your game runs fast (frequent updates of the script), you will multiply the movement by a small number and you'll get smooth movement. If the game runs slowly, you'll be multiplying the movement by a larger number. You'll get jerkier movement, but the entity will be moving with constant speed, no matter what the game framerate is.
Logged
Yes, I do have a twitter account
Please don't send me technical questions in private messages, use the forum. ::wave

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #8 on: March 12, 2012, 03:03:24 AM »

Thanks for explaining the Sleep function. I need Sleep() inside of a while loop for Game.CurrentTime to be updated, correct? I tried this:

Code: [Select]
var timeLastFrame = Game.CurrentTime;
var timeElapsed = 0;
var loopCounter = 0;
while (loopCounter < 2)
{
timeElapsed = Game.CurrentTime - timeLastFrame;
loopCounter = loopCounter + 1;
Sleep(20);
}

Printing the output to the screen, timeElapsed is equal to 0 the first time, then about 30 the second time, depending on what number I use in the Sleep function.

How does timeElapsed relate to the while loop inside the LinearMovement function? My game runs at 56 - 60 FPS full screen.
Logged

metamorphium

  • Global Moderator
  • Addicted to WME forum
  • *
  • Karma: 12
  • Offline Offline
  • Gender: Male
  • Posts: 1511
  • Vampires!
    • View Profile
    • CBE  software s.r.o.
Re: Moving non-actor entities towards an XY position
« Reply #9 on: March 16, 2012, 08:53:11 PM »

You have length to traverse over x and y coordinate stored in dX and dY respectively.

If you take the longer length you know how many cycles you need for the line to be drawn.

if you want the line to be drawn at certain speed, you can calculate how much the increment should change.

If eg. I want the line to be drawn during 1 second and my sleep is 20ms, I need 50 cycles (50*20 = 1000).

The result increment is:

incX = dX / 50;
incY = dY / 50;

The whole code could look like this:


Code: WME Script
  1. method LinearMovement(movingEntity, startX, startY, endX, endY, timeInSeconds)
  2. {
  3.     var dX = Math.Abs(endX - startX);
  4.     var dY = Math.Abs(endY - startY);
  5.    
  6.     var dirX = 1;
  7.     if (startX > endX) dirX = -1;
  8.  
  9.     var dirY = 1;
  10.     if (startY > endY) dirY = -1;
  11.  
  12.  
  13.     var incX = dX / (timeInSeconds * 50); // 1sec = 1000ms / 20ms sleep
  14.     var incY = dY / (timeInSeconds * 50);
  15.     dirX = dirX * incX;
  16.     dirY = dirY * incY;
  17.  
  18.     var diff = dirX - dirY;
  19.    
  20.     var posX = startX;
  21.     var posY = startY;
  22.    
  23.  
  24.     while (posX != endX && posY != endY)
  25.     {
  26.          movingEntity.X = posX;
  27.          movingEntity.Y = posY;
  28.          
  29.          var dblDiff = 2 * diff;
  30.          
  31.          if (dblDiff > (-1 * dY))
  32.          {
  33.               diff = diff - dY;
  34.               posX = posX + dirX;
  35.          }
  36.  
  37.          if (dblDiff < dX)
  38.          {
  39.               diff = diff +dX;
  40.               posY = posY + dirY;
  41.          }
  42.  
  43.          Sleep(20);
  44.     }
  45.  
  46. }
  47.  
  48.  

You will probably need to tweak this code or change it altogether, but you should get some general idea. :)

Next step would be using the elapsed time instead of counting with constant 20ms and applying error correction if the elapsed time was bigger.

Logged
J.U.L.I.A. Enhanced Edition, Vampires!, J.U.L.I.A., J.U.L.I.A. Untold, Ghost in the Sheet

hex

  • Lurker
  • *
  • Karma: 0
  • Offline Offline
  • Posts: 10
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #10 on: June 21, 2012, 04:41:54 AM »

Hello again :)

I put this problem on hold while working on other parts of the game, but now it's become a showstopper.

Latest update: I'm going with the time-elapsed method since you both agree it's the right way. But won't the time elapsed always be 20, or whatever the number is in the Sleep function? In the game loop, I have two lines that store the last frame's time, and the time elapsed:

Code: WME Script
  1.   gTimeElapsedSinceLastFrame = Game.CurrentTime - gTimeLastFrame;
  2.   gTimeLastFrame = Game.CurrentTime;
  3.  

gTimeElapsedSinceLastFrame always equals 20.  Assuming this is correct (I'm guessing it isn't), the next step is to multiply gTimeElapsedSinceLastFrame by dirX and dirY (the speed), right? The resulting movement is very jittery and not smooth at all. Also, it never reaches its destination because it never meets the while loop's condition (although this is probably an easy fix).

Code: WME Script
  1. method LinearMovement(movingEntity, startX, startY, endX, endY)
  2. {
  3.         var dX = Math.Abs(endX - startX);
  4.         var dY = Math.Abs(endY - startY);
  5.        
  6.         var dirX = 1;
  7.         if (startX > endX)
  8.                 dirX = -1;
  9.                
  10.         var dirY = 1;
  11.         if (startY > endY)
  12.                 dirY = -1;
  13.        
  14.         dirX = dirX * gTimeElapsedSinceLastFrame;
  15.         dirY = dirY * gTimeElapsedSinceLastFrame;
  16.                
  17.         var diff = dirX - dirY;
  18.        
  19.         var posX = startX;
  20.         var posY = startY;
  21.        
  22.         while ((posX != endX) && (posY != endY))
  23.         {
  24.                 var dblDiff = 2 * diff;
  25.                
  26.                 if (dblDiff > (-1 * dY))
  27.                 {
  28.                         diff = diff - dY;
  29.                         posX = posX + dirX;
  30.                 }
  31.                
  32.                 if (dblDiff < dX)
  33.                 {
  34.                         diff = diff + dX;
  35.                         posY = posY + dirY;
  36.                 }
  37.                
  38.                 movingEntity.X = posX;
  39.                 movingEntity.Y = posY;
  40.                
  41.                 Sleep(20);
  42.         }
  43.        
  44.         movingEntity.X = endX;
  45.         movingEntity.Y = endY;
  46. }
  47.  
Logged

2.0

  • Regular poster
  • ***
  • Karma: 4
  • Offline Offline
  • Posts: 217
    • View Profile
Re: Moving non-actor entities towards an XY position
« Reply #11 on: June 21, 2012, 09:12:55 PM »

The problem with smooth movement can be corrected only by fixes of source codes, where need to replace type of entities coordinates from int to float.

Also if you've found that gTimeElapsedSinceLastFrame always equals 20 (as I think, the method of getting this value is more or less correct) - it means that you always have 50 fps.

And if you prefer to use gTimeElapsedSinceLastFrame in the algorythm of the moving - use it for calculate delay between movement iterations. The less gTimeElapsedSinceLastFrame, the more delay. Thus you will always have all coordinates are "met" :)
« Last Edit: June 21, 2012, 09:26:34 PM by 2.0 »
Logged

Mnemonic

  • WME developer
  • Administrator
  • Addicted to WME forum
  • *
  • Karma: 41
  • Offline Offline
  • Gender: Male
  • Posts: 5683
    • View Profile
    • Dead:Code Site
Re: Moving non-actor entities towards an XY position
« Reply #12 on: June 23, 2012, 01:16:11 PM »

The problem with smooth movement can be corrected only by fixes of source codes, where need to replace type of entities coordinates from int to float.
I disagree. In the end the screen position is integer anyway. If you need to store the position as floats, do so in variables and only convert to int when assigning the final position to the entity.
Logged
Yes, I do have a twitter account
Please don't send me technical questions in private messages, use the forum. ::wave
 

Page created in 0.234 seconds with 22 queries.