Walking distance

Started by Vincent, Sat 30/07/2016 15:35:04

Previous topic - Next topic

Vincent

Good Evening to all AGSer.

I am trying to build a statistic which refers to how much distance the player walks in the game.
I'd like to show you how roughly might seem the script but I hope someone can suggest me what is the best way to achieve something like this (roll)
Code: ags
//GLOBAL VARIABLES
String measure, dis;

int /*float*/ steps, // use for tracking the steps performed
              steps_counter; // use for tracking the next goal


function AddValue (int value) {steps_counter += value;} // ...


function TrackingSteps()
{
   if (steps >= steps_counter) // steps value has just reach his goal
   {
      AddValue( ); // might be a costant one...
      

      // check measure to display 
      if (steps < 1250) {measure = "Meters";}
      else 
      {
        if (steps < 2000) {measure = "Km";}
        else {measure = "Miles";}
      }
   }   

  dis = String.Format("Walking Distance : %d %s", steps, measure); 
}


Thank you in advance for the time held to read :)
Somehow, I am not sure why this is posted in the Advanced Tech :)

Slasher

#1
Something like this could work (Results on a label)

Code: ags

// function top Global asc
 
int walktimer;
 
function Walking()
{
    if(player.Moving)
      {
          walktimer=0;
      }  
    else if (walktimer > GetGameSpeed ())
      {
          Stopped_Moving += 1;
          LNotMoving.Text = String.Format("%d", Stopped_Moving);
          walktimer = 0;
      }
    else walktimer++;
}
 



try it... you never know ;)


Crimson Wizard

#2
I am not sure counting steps is correct, because every character may have different moving speed and step length.
Probably keeping track of coordinate changes over time may be better solution?

Code: ags

int old_player_x;
int old_player_y;
float distance_walked;

function on_event (EventType event, int data) 
{
  // reset old player coords when room changes
  if (event == eEventEnterRoomBeforeFadein)
  {
    old_player_x = player.x;
    old_player_y = player.y;
  }
}

function repeatedly_execute()
{
  // if player moved since last time, calculate and add distance
  if (old_player_x != player.x || old_player_y != player.y)
  {
    int dx = player.x - old_player_x;
    int dy = player.y - old_player_y;
    distance_walked += Math::Sqrt(Maths.IntToFloat(dx * dx) + Maths.IntToFloat(dy * dy));
    old_player_x = player.x;
    old_player_y = player.y;
  }
}

Snarky

The problem with x/y coordinates is that they vary depending on perspective (i.e. an up- or down-view step moves a smaller on-screen distance than a side-view step) and scaling.

Time spent walking is not a bad idea. You can incorporate the animation speed into the calculation if necessary. Another approach would be to check the character's animation frame, and increment the step counter each time it reaches the frame (or frames) that represents a full step. This method might also work better if you have a separate run-cycle or other special type of movement for the character that should be calculated differently.

Then you simply multiply the number of steps with the step length to get the distance. If you need to support multiple different characters with different step lengths, you can read it from a custom character property.

Of course, "realistically" much of the distance walked by a character will usually be off-screen, since screens rarely connect directly. If you want to account for this, add some code to increment the step counter whenever the character leaves the room (depending on where they're going).

Note, BTW, that your initial code is completely wrong when it comes to units. You switch the unit ("measure") depending on the length, but you never actually convert to the appropriate unit, so it will go from 1249 meters to 1250 kilometers, and from 1999 kilometers to 2000 miles. (I also don't think it makes sense to mix kilometers and miles, particularly since the length of a mile differs in different places.)

Crimson Wizard

#4
Quote from: Snarky on Sat 30/07/2016 22:18:47
The problem with x/y coordinates is that they vary depending on perspective (i.e. an up- or down-view step moves a smaller on-screen distance than a side-view step) and scaling.
But you may simply apply some factor, for example instead of "int dy = player.y - old_player_y;" do "int dy = (player.y - old_player_y) * K;" where K is a coefficient for Y distance. This may even be room dependent.

This however won't work for areas with gradual scaling, and also for "far distance" simulated areas.

Vincent

Many thanks guys for the help was very much appreciated.

Previously, I forget to mention that I am using the module "Alt Keyboard Movement" to keep track on how many steps the player has performed, in this way.

Code: ags
void AdvanceFrame(int xa, int ya, int l) 
{    
  int sca = GetScalingAt(player.x, player.y);
  
  int sgn;
  if (player.ScaleMoveSpeed) 
  {
    sgn = Sgn(xa);
    xa = (xa*sca)/100; if (xa == 0) xa = sgn;
    sgn = Sgn(ya);
    ya = (ya*sca)/100; if (ya == 0) ya = sgn;
  }

  bool free = PathFree(player.x - GetViewportX(), player.y - GetViewportY(), xa, ya);
  int x = player.x + xfree;
  int y = player.y + yfree;
    
  int pf = player.Frame;
  int pl = player.Loop;
  
  // advance frame
  pf++;
  
  // roll around
  if (pf >= Game.GetFrameCountForLoop(player.View, pl)) pf = 1;
  if (l != pl) //player changes loop
  {
    // translate frame to new loop
    // frame is 1-x
    // old last frame and new last frame
    int olf = Game.GetFrameCountForLoop(player.View, pl)-1;
    int nlf = Game.GetFrameCountForLoop(player.View, l)-1;
    if (olf != 1) pf = (pf*(nlf-1))/(olf-1);
    if (pf == 0) pf = 1;
  }
  
  // change loop
  if (free || TurnIfBlocked) { player.Loop = l; }
  
  // advance frame
  Animating = false;
  if (free || AnimateAtEdge) 
  {
    steps ++; // <------------------------------------------------------------- that represents a full step
    Animating = true;
    player.Frame = pf;
  }
  else player.Frame = 0;
  
  // move player
  Moving = false;
  if (free) 
  {
    Moving = true;
    player.x = x;
    player.y = y;
  }
}


So I am going to do something like this because it's working just as I wish :
Quote from: Snarky on Sat 30/07/2016 22:18:47
You can incorporate the animation speed into the calculation if necessary. Another approach would be to check the character's animation frame, and increment the step counter each time it reaches the frame (or frames) that represents a full step.


Quote from: Snarky on Sat 30/07/2016 22:18:47
Then you simply multiply the number of steps with the step length to get the distance.

I am not sure if I still could do that with my roughly script ?
Code: ags
function TrackingSteps()
{
   if (steps >= steps_counter) // steps value has just reach his (new) goal 
   {
      AddValue( ); // simply multiply the number of steps with the step length to get the distance.


Then I am not sure how do I should keep track properly of the 'steps_counter' and lately how do I can convert it to the appropriate unit ? (roll)
Many thanks guys again for your replies and supports.

SMF spam blocked by CleanTalk