(Renamed Title) Help with custom walk for an ISO car driving system

Started by Knox, Mon 26/09/2011 17:28:40

Previous topic - Next topic

Knox

Hi,

I am slowly starting to put a driving module into my game. I was wondering how to solve this certain problem.

Right now, when I click my cursor (walk) to drive the player around (car sprite), even if I have the sprite setup OK (up, down, left, right, diagonal down-left, diagonal down-right, diagonal up-right, diagonal up-left)...if I click, for example, up-left of the car to move it diagonal up-left. it will move up-left but it will display the "left" sprite...its not locked to the "diagonal up-left" sprite, know what I mean?

Also, how could one go about scripting this: say the mouse hovers over an intersection and you can go left or right...the mouse will change cursors when it is over that certain area where you can turn, then when you click on the mouse, the car will turn at the right spot. If you dont click anywhere, the car will just continue its present course.

(For example, say I click at a 4-way intersection and the car can continue up, turn left or right...if your mouse is over the intersection but hovering more to the left, the cursor changes to a left turn-arrow, if its more to the right, turn-right arrow, and if your mouse hovers above the intersection, just display up arrow.)

I looked at the Taxi Demo source, and its pretty cool, I  got it to work and everything, but I feel for this kind of game I dont want the car to be "free" to drive at any angle, nor do I need an physics other than hit-detection on other cars, like in Police Quest 1 ega (check out the youtube video). I just want the car movements  to be locked to the 8 directions only, and the player can use the keyboard or the mouse to move it around.
http://www.youtube.com/watch?v=D7Mcdbg8LqI

As you know Im not particularly gifted in scripting, although I can hack my way through, so any help is really appreciated!!
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

Ill try to see if I can get the car to move in the diagonal positions with the proper angled sprite "locked" while moving diagonally...right now its always using the left/right sprite while moving diagonally...any ideas why its doing that?
--All that is necessary for evil to triumph is for good men to do nothing.

steptoe

In the Manual: DiagonalLoops property


bool Character.DiagonalLoops

Gets/sets whether diagonal walking loops are used for the character. If this is set to true, then loops 4-7 will be used as diagonal walking loops. If this is set to false, then the character will only face in 4 directions and you can use loops 4-7 for other purposes.

Example:

cEgo.DiagonalLoops = true;




Knox

Hi steptoe,

I'm aware of the diagonal loops property in the manual, but if you test it out with a simple sprite (like in the example pic below), it doesnt "lock" to the diagonal loop while moving...it actually uses the wrong loop for some reason:



http://www.youtube.com/watch?v=tbZFDe3V7HA
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

Geeze I just found out if your loop only has one sprite in it, it wont travel along the diagonal...as soon as I put in 2 sprites per loop, it moves diagonally like it should.
--All that is necessary for evil to triumph is for good men to do nothing.

steptoe

I assumed you had more than 2 frames per view... but glad its solved.

;D

Knox

Thanks steptoe, that part is solved (Im wondering if its anywhere in the manual that you need 2 sprites per loop for the diagonals to work?)

I renamed the title because I didnt want to bother you all with yet another thread  :=

Ok, Im getting a bit further in trying to do a driving module...however I think I would need help on this part:

Check the video, I made a place-holder template with an Iso-grid, the streets will always be at this angle. I only need the up/down/left/right loops when the car is turning...other than that, the car should never use those loops...as you can see in the video, that's not the case: sometimes, when I click on a walkable area, the car will slide in the wrong loop while moving diagonally...how can I make those 4 loops only accessible when the car is turning, but other than that the car will always move with the diagonal loops?

http://www.youtube.com/watch?v=SKIMyVcgLjQ


Ill check out the other threads on isometric maps + movement (if any), to see if  I can get some pointers there, but in the meantime, any help is appreciated!

**Edit :I guess Im looking for what this person asked here: http://www.adventuregamestudio.co.uk/yabb/index.php?PHPSESSID=6ve262cd3e75q7svke88rgrs74&topic=30325.0
--All that is necessary for evil to triumph is for good men to do nothing.

steptoe

Did you solve your issue?

Possibly TurnBeforeWalking property option from manual?

Knox

I think its more than that (Ive got that option checked)... browsing the threads on isometric maps, I believe there is more than meets the eye. Lots of math I dont understand, geeze maybe Im way over my head here for this!! Perhaps I need to rethink the angle (like just do a top-down), but I asked someone here who is really good to help me out, hopefully something can be worked out :)

I know its beyond my capabilities, not only in scripting but in intelligence, hehe :P
--All that is necessary for evil to triumph is for good men to do nothing.

steptoe

I agree, running before walking.. but it does gives you an insight.

Up, down, left and right may be the way to start.

Once you are more experienced than you may well try again..

Good luck



Knox

--All that is necessary for evil to triumph is for good men to do nothing.

Wyz

The problem I guess is that the angles of the road in your game differ from the built-in angle AGS uses to determine what loop to show. Well I've heard more people talk about this issue but it's built in so I guess it is needed to do some calculations. I haven't tested it thorough but give this a shot:
Code: ags

#define THRESHOLD 2.0 // Play with this value when the view flickers

int x = 0;
int y = 0;

function room_RepExec()
{
  float vx = IntToFloat(player.x - x);
  float vy = IntToFloat(player.y - y);
  
  float d;
  float maxd = 0.0;
  int loop = -1;
  
  // North & south
  d = -vy;
  if      ( d > maxd) { maxd =  d; loop = 3; }
  else if (-d > maxd) { maxd = -d; loop = 0; }
  
  // West & east
  d = -vx;
  if      ( d > maxd) { maxd =  d; loop = 1; }
  else if (-d > maxd) { maxd = -d; loop = 2; }
  
  // North-east & South-west
  d = vx * 0.86602540 - vy * 0.5;
  if      ( d > maxd) { maxd =  d; loop = 5; }
  else if (-d > maxd) { maxd = -d; loop = 6; }
  
  // North-west & South-east
  d = -vx * 0.86602540 - vy * 0.5;
  if      ( d > maxd) { maxd =  d; loop = 7; }
  else if (-d > maxd) { maxd = -d; loop = 4; }
  
  // Set the view of the character
  if (loop >= 0)
    player.Loop = loop;
  
  // Cushion input
  if (vx > THRESHOLD || vy > THRESHOLD || vx < THRESHOLD || vy < THRESHOLD)
  {
    x = player.x;
    y = player.y;
  }
}
Life is like an adventure without the pixel hunts.

Knox

Awesome! Thnx Wyz!

Ok, Im going to try that thursday as soon as I can  :=

Ive gotten part of what I wanted, snapping at 30° intervals on the keyboard, I need to change the angle of my grid, it wasnt exactly 30° + tweeked the taxi module.

Ill post it all this weekend for sure...I hope the walkbehinds aren't too hard to do in an iso map :P
--All that is necessary for evil to triumph is for good men to do nothing.

Knox

Hi guys,

Ive been away for a while due to losing my job via "downsizing", so I had to put my hobby on hold until I got a new job...man that really sucked! Didnt have much time at all to work on this.

Anyways, Ive got a new job so Im back to my hobby :)

Ive been slowly trying to put together an isometric driving module for my  game with pretty good results so far. However, Ive tried a few things here and there by mixing some code snippets and using the source of Taxi Demo (a lot, actually). Im currently attempting to modify the Taxi Demo code to suit my needs. Ive decided to try a different approach than what I posted previously (thanks Wyz for the code, for now I will put that "driving mode" on hold)

Here is mostly the Taxi Demo code, but modified to get what I want...I put in "Display debug lines" to help explain what Im trying to do...SORRY for the LONG code...I hope I dont scare anyone away!
Code: ags

// room script file

//int iCar_1stSprite = 4090; //4181, 4090 -->angle plus the 1st sprite's number in the car's sprite list...
int iCar_1stSprite = 4181;

struct vector
{
	float x;
	float y;
};

vector car;
vector oldcar;
vector tires[4];
vector oldtires[4];
vector velocity;
vector acceleration;
vector velocity_world;
vector acceleration_world;
float Ftraction = 0.0;
float Fside = 0.0;
float Fside_friction = 15000.0; //15000
vector Fdrag;
vector Frr;
vector F;

vector screenoffset;
vector wanted_screenoffset;
#define screenoffset_step 1.0
#define half_screen_width 512
#define half_screen_height 384
#define screen_width 1024
#define screen_height 768

float drive_angle = 0.0;
float body_angle = 0.0;
float turn_speed = 0.0;
float max_turn_speed = 6.0; //7
float max_turn_speed_multiply = 3.0; //7
float body_turn_speed = 0.0;
float max_body_turn_speed = 8.0; //10
float steer_angle = 0.0;
float max_steer_angle = 0.2;

int wall_angles[16];
int wallareas[3];

#define Fthrottle 5000.0 //8000
#define Fbrake 8000.0
#define Cdrag 0.1
#define Crr 20.0
#define scale 7.5
#define mass 410.0//410
#define delta_time 0.025
#define half_sprite_size 22//22
#define half_wheel_base 1.5
#define half_rail_width 0.6

float pulsate = 0.0;

float fAbs(float in)
{
	if(in < 0.0) return -in;
	else return in;
}

float fMax(float a, float b)
{
	if(a < b) return b;
	else return a;
}

float fMin(float a, float b)
{
	if(a > b) return b;
	else return a;
}

function IsWalkable(int x, int y)
{
	intare = 0;
	whileare < 3)
  {
		if(GetWalkableAreaAt(x - GetViewportX(), y - GetViewportY()) == wallareas[r]) return false;
	are++;
	}	
	return true;
}

function GetWalkable(int x, int y)
{
	return GetWalkableAreaAt(x - GetViewportX(), y - GetViewportY());
}

function moveToWalkable()
{
  if (iDriveMode == 1)
  {
    intare = 0;
    whileare < 4)
    {
      int newx = FloatToInt(tires[r].x * scale, eRoundNearest);
      int newy = FloatToInt(tires[r].y * scale, eRoundNearest);
      int oldx = newx;
      int oldy = newy;
      bool onwalk = false;
      int movement = 1;
      while(!onwalk)
      {
        if (IsWalkable(newx, newy)) onwalk = true;
        else
        {
          if (IsWalkable(newx + movement, newy))
          {
            onwalk = true;
            newx += movement;
          }
          else if (IsWalkable(newx - movement, newy))
          {
            onwalk = true;
            newx -= movement;
          }
          else if (IsWalkable(newx, newy + movement))
          {
            onwalk = true;
            newy += movement;
          }
          else if (IsWalkable(newx, newy - movement))
          {
            onwalk = true;
            newy -= movement;
          }	
          movement++;
        }
      }
      if (oldx != newx|| oldy != newy)
      {
        car.x += IntToFloat(newx - oldx) / scale;
        car.y += IntToFloat(newy - oldy) / scale;
      }	
     are++;
    }
  }
}

void updateCarSprite()
{ 
	if (iDriveMode == 1)
  {

    //with 360 sprites
    int iAdd;
    int angle = FloatToInt(body_angle, eRoundNearest);
    if (angle == 0 || angle == 360) iAdd = 0;
    else if ((angle >= 29 && angle <= 31) || (angle >= 209 && angle <= 211)) iAdd = 11;
    else if ((angle >= 149 && angle <= 151) || (angle >= 329 && angle <= 331)) iAdd = -11;
    //else if (angle) iAdd = 11; //+ 5 increments
    else iAdd = 1;
    oCar.Graphic = angle+iCar_1stSprite+iAdd; //add 1 for the first sprite that is 0°
  }
}

function on_key_press(int keycode) 
{
  //rotate car's angle when immobile only:
  if (velocity.x == 0.0)
  {
    if (keycode == 375)
    {
      Display("Rotate Left");
      body_angle = body_angle-30.0;
      drive_angle = body_angle;
    }
    else if (keycode == 377)
    {
      Display("Rotate Right");
      body_angle = body_angle+30.0;
      drive_angle = body_angle;
    }
    else if (IsKeyPressed(380)) //Down 
    {
      
    }
    else if (IsKeyPressed(372)) //Up
    {
      
    }
  }
}

function room_Load()
{
  //gTitleBar.Visible =false;
  //iDriveMode = 0; //mouse-iso style
  iDriveMode = 1; //taxi style (press keyboard once, the car will eventually slowly stop)
  //iDriveMode = 2; //keyboard tapping mode (press keyboard once, the car continues in that direction forever)
  cPatrolCar.SetAsPlayer();
  if (iDriveMode == 2) cPatrolCar.LockView(110);
  
  body_angle = 330.0;
  drive_angle = body_angle;
      
	System.VSync = true;

	if (iDriveMode == 1)
  {
    wallareas[0] = 0;
    wallareas[1] = 2;
    wallareas[2] = 0;

    screenoffset.x = 0.0;
    screenoffset.y = 0.0;
    wall_angles[2] = 0;
    wall_angles[3] = 90;
    wall_angles[6] = 0;
    wall_angles[7] = 90;
    Debug(4, 1);

    car.x = IntToFloat(oCar.X) / scale;
    car.y = IntToFloat(oCar.Y) / scale;
    oCar.X = FloatToInt(car.x * scale, eRoundNearest) - half_sprite_size;
    oCar.Y = FloatToInt(car.y * scale, eRoundNearest) + half_sprite_size;
    
    updateCarSprite();
    
    SetViewport(oCar.X - half_screen_width + half_sprite_size + FloatToInt(screenoffset.x, eRoundNearest), oCar.Y - half_screen_height - half_sprite_size + FloatToInt(screenoffset.y, eRoundNearest));
  }
}

function room_RepExec()
{
  if (iDriveMode == 1)
  {
    if (IsKeyPressed(375)) //Left key
    {
      if (velocity.x > 0.0) Display("Left Strafe key is pressed, car is moving forward, strafe car Left...");
      else
      {
        if (velocity.x < 0.0) Display("Left key pressed, car is in reverse, do nothing..."); //reverse
        else Display("Left key pressed, car is immobile, rotate car Left...");
      }
    }
    else if (IsKeyPressed(377)) //Right key
    {
      if (velocity.x > 0.0) Display("Right Strafe key is pressed, car is moving forward, strafe car right...");
      else
      {
        if (velocity.x < 0.0) Display("Right key pressed, car is in reverse, do nothing..."); //reverse
        else Display("Right key pressed, car is immobile, rotate car right...");
      }
    }

    if (IsKeyPressed(380)) //Down 
    {
      //Display("Down key pressed...");
      if (velocity.x > 0.0)
      {
        Display("Down key is pressed, car is moving forward, decelerate or brake car...");
        Ftraction = -Fbrake; // brake
      }
      else // reverse
      {	
        if (velocity.x > -25.0)
        {
          Ftraction += -Fthrottle / 16.0;
          if (Ftraction < -Fthrottle / 2.0) Ftraction = -Fthrottle / 2.0;
        }	
        else Ftraction = 0.0;
      }
    }
    else if (IsKeyPressed(372)) //Up
    {
      if (velocity.x < 0.0) 
      {
        Display("Up key pressed, car in reverse, brake car...");
        Ftraction = Fbrake;  // brake
      }
      else // throttle
      {
        if (velocity.x == 0.0) Display("Up key pressed, car is stopped...accelerate car...");
        else Display("Up key pressed, car is moving forward...accelerate to next speed level...");
        Ftraction += Fthrottle / 8.0;
        if (Ftraction > Fthrottle) Ftraction = Fthrottle;
      }
    }
    else //if nothing is pressed...slowly stop the car...
    {
      if (velocity.x == 0.0)
      {
        Ftraction = 0.0;
        velocity.x = 0.0;        
      }
      /*
      if (velocity.x > 0.1) //car is moving forward, come to a stop
      {
        Ftraction += -Fbrake / 32.0;
        if (Ftraction < -Fbrake / 4.0) Ftraction = -Fbrake / 4.0;
      }
      else if (velocity.x < -0.1) //car is moving backwards, come to a stop
      {
        Ftraction += Fbrake / 32.0;
        if (Ftraction > Fbrake / 4.0) Ftraction = Fbrake / 4.0;
      }
      else //if car is not moving, do nothing...
      {
        Ftraction = 0.0;
        velocity.x = 0.0;
      }*/
    }
  }
}

function repeatedly_execute_always()
{
  if (iDriveMode == 1)
  {
    if (steer_angle > max_steer_angle) steer_angle = max_steer_angle;
    else if (steer_angle < -max_steer_angle) steer_angle = -max_steer_angle;
    
    turn_speed = steer_angle * velocity.x * 1.0; //2.0
    
    body_turn_speed = 0.0;
    if (Region.GetAtRoomXY(player.x, player.y) == region[1]) max_turn_speed = max_turn_speed_multiply - (fAbs(velocity.x) * 0.08); //0.08
    else max_turn_speed = max_turn_speed_multiply - (fAbs(velocity.x) * 0.05); //0.05
    
    if (acceleration.x * 0.1 > 0.0) max_turn_speed += acceleration.x * 0.1;
    if (turn_speed > max_turn_speed)
    {
      body_turn_speed = turn_speed + velocity.x * (turn_speed - max_turn_speed) * 0.025; //0.05
      turn_speed = max_turn_speed;
    }
    else if (turn_speed < -max_turn_speed)
    {
      body_turn_speed = turn_speed + velocity.x * (turn_speed + max_turn_speed) * 0.025; //0.05
      turn_speed = -max_turn_speed;
    }	
    if (velocity.y > 0.0)
    {
      Fside += -Fside_friction / 4.0; //4.0
      if (Fside < -Fside_friction) Fside = -Fside_friction;
    }
    else if (velocity.y < -0.0) 
    {
      Fside += Fside_friction / 4.0; //4.0
      if(Fside > Fside_friction) Fside = Fside_friction;
    }
    else Fside = 0.0;

    oldcar.x = car.x;
    oldcar.y = car.y;
    intare = 0;
    while are < 4)
    {
      oldtires[r].x = tires[r].x;
      oldtires[r].y = tires[r].y;
     are++;
    }
    
    drive_angle += turn_speed;
    body_angle = drive_angle + body_turn_speed;
    
    String debug = String.Format("drive angle:%1f graphic: %d", drive_angle, oCar.Graphic);
    lblHotspot.TextCheckLBL(debug);
    
    if (body_angle > 360.0) body_angle -= 360.0;
    else if (body_angle < 0.0) body_angle += 360.0;
    if (drive_angle > 360.0) drive_angle -= 360.0;
    else if (drive_angle < 0.0) drive_angle += 360.0;
    
    Fdrag.x = -Cdrag * velocity.x * velocity.x * velocity.x;
    Fdrag.y = -Cdrag * velocity.y * velocity.y * velocity.y;
    Frr.x = -Crr * velocity.x;
    Frr.y = -Crr * velocity.y;
    F.x = Ftraction + Fdrag.x + Frr.x;
    F.y = Fside;// + Fdrag.y + Frr.y;
    acceleration.x = F.x / mass;
    acceleration.y = F.y / mass;
    velocity.x += acceleration.x * delta_time;
    
    if(velocity.y > 0.0)
    {
      velocity.y += acceleration.y * delta_time;
      if (velocity.y < 0.0) velocity.y = 0.0;
    }	
    else 
    {
      velocity.y += acceleration.y * delta_time;
      if (velocity.y > 0.0) velocity.y = 0.0;
    }	
    float cos_drive = Maths.Cos(Maths.DegreesToRadians(drive_angle));
    float sin_drive = Maths.Sin(Maths.DegreesToRadians(drive_angle));
    float cos_body = Maths.Cos(Maths.DegreesToRadians(body_angle));
    float sin_body = Maths.Sin(Maths.DegreesToRadians(body_angle));
    velocity_world.x = cos_drive * velocity.x - sin_drive * velocity.y;
    velocity_world.y = sin_drive * velocity.x + cos_drive * velocity.y;
    Region *reg[4];
    int i = 0;
    
    // move car a time-slice at a time and check for collisions
    #define time_slice 50
    while (i < time_slice)
    {
      // move car
      car.x += velocity_world.x * delta_time / time_slice.0;
      car.y += velocity_world.y * delta_time / time_slice.0;
      
      // calculate tire coordinates
      tires[0].x = car.x - cos_body * half_wheel_base - sin_body * half_rail_width;
      tires[0].y = car.y - sin_body * half_wheel_base + cos_body * half_rail_width;
      tires[1].x = car.x - cos_body * half_wheel_base + sin_body * half_rail_width;
      tires[1].y = car.y - sin_body * half_wheel_base - cos_body * half_rail_width;
      tires[2].x = car.x + cos_body * half_wheel_base - sin_body * half_rail_width;
      tires[2].y = car.y + sin_body * half_wheel_base + cos_body * half_rail_width;
      tires[3].x = car.x + cos_body * half_wheel_base + sin_body * half_rail_width;
      tires[3].y = car.y + sin_body * half_wheel_base - cos_body * half_rail_width;

     are = 0;
      bool hitwall = false;
      while are < 4)
      {
        if(!IsWalkable(FloatToInt(tires[r].x * scale, eRoundNearest), FloatToInt(tires[r].y * scale, eRoundNearest))) hitwall = true;
       are++;
      }	
      if (hitwall)
      {
        // get the regions we are on hit
        int regionID;
       are = 0;
        while are < 4)
        {
          reg[r] = Region.GetAtRoomXY(FloatToInt(tires[r].x * scale, eRoundNearest), FloatToInt(tires[r].y * scale, eRoundNearest));
          if(reg[r] == region[2] || reg[r] == region[3] || reg[r] == region[6] || reg[r] == region[7]) regionID = reg[r].ID;
         are++;
        }	
      
        // go back to where we didn't hit the wall
        car.x -= velocity_world.x * delta_time / time_slice.0;
        car.y -= velocity_world.y * delta_time / time_slice.0;
        moveToWalkable();
        
        // reverse appropriate velocity component
        // vertical wall
        if (wall_angles[regionID] == 90)
        {
          velocity_world.x = -velocity_world.x * fMax(fAbs(sin_drive), 0.5); //0.5
          velocity_world.y = velocity_world.y * fMax(fAbs(sin_drive), 0.5);
        }
        // horizontal wall
        else
        {
          velocity_world.x = velocity_world.x * fMax(fAbs(cos_drive), 0.5);
          velocity_world.y = -velocity_world.y * fMax(fAbs(cos_drive), 0.5);
        }	
        // get back the velocity in car coordinates
        velocity.x = cos_drive * velocity_world.x + sin_drive * velocity_world.y;
        velocity.y = -sin_drive * velocity_world.x + cos_drive * velocity_world.y;
        
        // move car
        car.x += velocity_world.x * delta_time / time_slice.0;
        car.y += velocity_world.y * delta_time / time_slice.0;
        
        // calculate tire coordinates
        tires[0].x = car.x - cos_body * half_wheel_base - sin_body * half_rail_width;
        tires[0].y = car.y - sin_body * half_wheel_base + cos_body * half_rail_width;
        tires[1].x = car.x - cos_body * half_wheel_base + sin_body * half_rail_width;
        tires[1].y = car.y - sin_body * half_wheel_base - cos_body * half_rail_width;
        tires[2].x = car.x + cos_body * half_wheel_base - sin_body * half_rail_width;
        tires[2].y = car.y + sin_body * half_wheel_base + cos_body * half_rail_width;
        tires[3].x = car.x + cos_body * half_wheel_base + sin_body * half_rail_width;
        tires[3].y = car.y + sin_body * half_wheel_base - cos_body * half_rail_width;
      }
      i++;
    }	

    // move car to the walkable area
    moveToWalkable();
    
    // move car sprite
    oCar.X = FloatToInt(car.x * scale, eRoundNearest) - half_sprite_size;
    oCar.Y = FloatToInt(car.y * scale, eRoundNearest) + half_sprite_size;
    player.x = oCar.X + half_sprite_size;
    player.y = oCar.Y - half_sprite_size;
    
    updateCarSprite();   
    
    // set viewport scrolling
    wanted_screenoffset.x = cos_drive * (velocity.x * 1.5);
    wanted_screenoffset.y = sin_drive * (velocity.x * 1.5);
    
    if (wanted_screenoffset.x > screenoffset.x)
    {
      screenoffset.x += screenoffset_step;
      if (wanted_screenoffset.x < screenoffset.x) screenoffset.x = wanted_screenoffset.x;
    }
    else if (wanted_screenoffset.x < screenoffset.x)
    {
      screenoffset.x -= screenoffset_step;
      if (wanted_screenoffset.x > screenoffset.x) screenoffset.x = wanted_screenoffset.x;
    }
    if (wanted_screenoffset.y > screenoffset.y)
    {
      screenoffset.y += screenoffset_step;
      if(wanted_screenoffset.y < screenoffset.y) screenoffset.y = wanted_screenoffset.y;
    }
    else if (wanted_screenoffset.y < screenoffset.y)
    {
      screenoffset.y -= screenoffset_step;
      if(wanted_screenoffset.y > screenoffset.y) screenoffset.y = wanted_screenoffset.y;
    }
    SetViewport(oCar.X - half_screen_width + half_sprite_size + FloatToInt(screenoffset.x, eRoundNearest), oCar.Y - half_screen_height - half_sprite_size + FloatToInt(screenoffset.y, eRoundNearest));

    // calculate engine rpm
    int rpm = FloatToInt(fAbs(velocity.x) * 120.0);
    if (rpm > 5000) rpm = 5000;
    else if (rpm < 0) rpm = 0;
    rpm += 1000;

    //String infotext = String.Format("%dmph[%drpm", FloatToInt(velocity.x * 3600.0 / 1000.0), rpm);
    //lblHotspot.TextCheckLBL(infotext);
  }
}


Here is what I was hoping of achieving with the key presses...most of which Ive been able to achieve:

--LEFT/RIGHT ARROW:
a) While car is immobile, can orient the car's angle
b) While car is in forward movement and not in an intersection region, strafe the car left or right (blocking animation lane change)
c) While car is in reverse and not in an intersection region, these key presses do nothing
d) While car is in movement and over an intersection region, turn the car left or right (blocking animation to turn car on the proper street)

--UP ARROW:
a) While car is immobile, will start the car moving forward
b) While car is moving forward, can press the up arrow 3 more times to switch gears (4 speed modes)
c) While car is moving backwards, each press will decrease the car's reverse speed until full stop

--DOWN ARROW:
a) While car is immobile, will start the car moving backward
b) While car is moving backwards, press down again wont do anything
c) While car is moving forwards, each press will decrease the car's forward speed until full stop

Where I am stuck right now is Im having problems with these issues:

a) Currently when I press the down arrow while the car is moving forward, the car will immediatly go into reverse...it wont stop first. Id like it to come to a full stop if  the car is moving at the lowest speed mode. If the player then presses the down key once again while the car is fully stopped, THEN it will go into reverse.
b) I have no idea about the math involved to how to make the car "strafe" from left to right or right to left like if it was doing a lane change while it is moving forward.

Here is an example of how Id like the car to make a lane change:

--All that is necessary for evil to triumph is for good men to do nothing.

Construed

I felt sorry for myself because I had no shoes.
Then I met the man with no feet.

Knox

I know, its long!

Ill still try to debug it myself in the meantime
--All that is necessary for evil to triumph is for good men to do nothing.

Ryan Timothy B

You're still better off not even touching Regions/Hotspots or anything of the sort.
Also with this method it looks like a rigid driving cutscene. Like you have to press the keys at the appropriate time or the car will crash. But there is no chance to correct your steering or go beyond what you see here.

I thought you were looking for a GTA type driving cutscene? Or are you moving more into the old school driving of the original Police Quest game(s)?

Knox

Hey Ryan,

Yeah, Ive decided to make it closer to the old police quest games...more like police quest 1 mixed in with police quest 3. It wont be like GTA (free roam)...its too much for me to handle so Id rather start small and see where it leads me.

Basically if you "miss" your intersection turn (not pressing the right keypress at the right time when you're over the hotspot/region), then you dont turn...heh. You have to go around the block like in PQ3...annoying, but I guess I always liked punishing players mUAAaa.

Also, if you do a lane change at the wrong time (say an oncoming car is in your lane)...well unless you have time to do another lane change back, you will crash and die a horrible death (like in PQ1 EGA).

Where it will differ from the old police quest games is the map will be detailed and isometric...not quite a cutscene, there will be more playability but not as much as GTA.

Why should I stay away from hotspots/regions? Im not too sure how else I can get the car to detect when its at an intersection without using those.
--All that is necessary for evil to triumph is for good men to do nothing.

Ryan Timothy B

Well the main issue with using a Region is that once you press the key to turn, when does it turn? The very second you press it and have it crash into a building? Or does it wait until it has the opportunity?

If it's waiting for the opportunity, then you're better off with an X,Y point for the center of the intersection. Then determine if you're within a circular radius of that X,Y point. If you're too far beyond that circular radius, it doesn't turn.

So there's two rings. The outside radius which determines if you're within that intersection and an inner radius which determines if you've pressed it too late.

You can then determine if the car is travelling towards the center of intersection or away from it. Then if it's travelling towards it and is within the two circles, then it turns but if it's travelling away, it won't turn.

Knox

Hmm, ok I see what you mean. Crap!!

Ok, I  think I remember you talking about the "circle solution" before with 2 radiuses...Ill see what I can manage, but it does seem over my head at first glance.

Ill try and see what I can come up with! Thnx Ryan
--All that is necessary for evil to triumph is for good men to do nothing.

SMF spam blocked by CleanTalk