(Solved!) Question on an obscure character movement/turning scheme.

Started by Vault15, Tue 18/06/2013 21:53:20

Previous topic - Next topic

Vault15

I'm using the default KeyboardMovement script, and am completely stumped. This is for an arcade-style game that I'm working on as a side project.

The player facing down.

The Goal:
1. The player will use the left/right arrow keys to cycle through views. If facing down, then by pressing left arrow key, he would shift to the Southwest view. If facing Southwest, then by pressing the left arrow key, the character would now be facing Left. The same principle would apply by pressing the right arrow key. If you press the up arrow key, then the player begins walking in the current direction assigned by the left or right arrow keys (whether northeast, left, right, etc.).
2. I don't want the character to automatically move when an arrow is pressed. The only arrow for movement will be the up arrow. Keep in mind that the character is sitting in a chair, so the only way to move backwards would be via the spacebar (to kick).
3. The character shouldn't stop immediately after letting go of the up button. It should be a slow, gradual halt.

To clarify a bit, I want it where the left arrow will always rotate the character clockwise, while the right arrow would always rotate counter-clockwise. You move forward by pressing the up arrow, which moves you straight towards any direction you're facting (even down). I would program in the spacebar to cause the player to kick and propel himself backwards on the chair. Essentially, this makes it more ideal to travel backwards (you move much faster).

The obvious code changes so far:
Code: AGS

//Solves the automatic movement.
KeyboardMovement.SetMode(eKeyboardMovement_Pressing);


Semi-working Globalscript code (tweaked slightly)
Code: AGS

//View 0 is Down, View 6 is Southwest, View 1 is Left
  if(Jerry.Loop == 0 && IsKeyPressed(eKeyLeftArrow))
    Jerry.FaceLocation(player.x - 50,  player.y + 50);
  if(Jerry.Loop == 6 && IsKeyPressed(eKeyLeftArrow))
    Jerry.FaceLocation(player.x - 50,  player.y);
  if(Jerry.Loop == 1 && IsKeyPressed(eKeyRightArrow))
    Jerry.FaceLocation(player.x - 50,  player.y + 50);


Other failed ideas (This time in the KeyboardMovement_102 Script)
Code: AGS

  else if (IsKeyPressed(KeyboardMovement_KeyLeft) && Jerry.Loop == 0) newdirection = eKeyboardMovement_DownLeft; // Moves DownLeft (If Down)
  else if (IsKeyPressed(KeyboardMovement_KeyLeft) && Jerry.Loop == 6) newdirection = eKeyboardMovement_Left; // Moves Left (If DownLeft)
  else if (IsKeyPressed(KeyboardMovement_KeyLeft) && Jerry.Loop == 1) newdirection = eKeyboardMovement_UpLeft; // Moves UpLeft (If Left)
  else if (IsKeyPressed(KeyboardMovement_KeyLeft) && Jerry.Loop == 7) newdirection = eKeyboardMovement_Up; // Moves Up (If UpLeft)
  else if (IsKeyPressed(KeyboardMovement_KeyLeft) && Jerry.Loop == 3) newdirection = eKeyboardMovement_UpRight; // Moves UpRight (If Up)
  
  else if (IsKeyPressed(KeyboardMovement_KeyRight) && Jerry.Loop == 0) newdirection = eKeyboardMovement_DownRight; // Moves DownRight (If Down)
  else if (IsKeyPressed(KeyboardMovement_KeyRight) && Jerry.Loop == 6) newdirection = eKeyboardMovement_Down; // Moves Down (If DownLeft)
  else if (IsKeyPressed(KeyboardMovement_KeyRight) && Jerry.Loop == 1) newdirection = eKeyboardMovement_DownLeft; // Moves Down (If DownLeft)


Any thoughts or simple tricks to achieving this movement scheme? Thanks in advance!

Khris

You'll have to ditch the Keyboard movement module. As soon as you want smooth movement that changes speed without stopping in between, player.Walk() goes out the window.

Try this:
Code: ags
int rotate_left = eKeyLeftArrow;
int rotate_right = eKeyRightArrow;
int move_forward = eKeyUpArrow;
int move_back = eKeySpace;
float forward_speed = 3.0;
float backward_impulse = 5.0;
int back_blocked_frames = 80;  // kick back only possible every x frames
float laziness = 0.05;   // acceleration coefficient

// direction of forward movement
float dx, dy = 1.0;  // default: down
float px, py;

void on_event(EventType event, int data) {
  if (event == eEventEnterRoomBeforeFadein) {
    px = IntToFloat(player.x);
    py = IntToFloat(player.y);
  }
}

void on_key_press(eKeyCode k) {
  
  String loops = "061735240";
  int current_dir = loops.IndexOf(String.Format("%d", player.Loop));
  int old_dir = current_dir;
  
  if (k == rotate_left) current_dir--; if (current_dir == -1) current_dir = 7;
  if (k == rotate_right) current_dir++;

  if (current_dir != old_dir) {
    player.Loop = loops.Chars[current_dir] - 48;
    float angle = IntToFloat(current_dir + 2) * Maths.Pi / 4.0;
    dx = Maths.Cos(angle);
    dy = Maths.Sin(angle);
  }
}

float speed, target_speed;
int back_locked;

void repeatedly_execute() {
  
  if (back_locked) back_locked--;  // count down if locked
   
  if (IsKeyPressed(move_forward) && !IsKeyPressed(move_back)) target_speed = forward_speed;
  else if (IsKeyPressed(move_back) && !IsKeyPressed(move_forward)) {
    if (back_locked == 0) {
      speed = -backward_impulse;
      target_speed = 0.0;
      back_locked = back_blocked_frames; // 2 seconds
    }
  }
  else target_speed = 0.0;
  
  // change current speed
  speed += (target_speed - speed) * laziness;
  
  float xa = dx * speed, ya = dy * speed; // movement vector
  
  // move player
  int tpx = FloatToInt(px + xa, eRoundNearest) - GetViewportX();
  int tpy = FloatToInt(py + ya, eRoundNearest) - GetViewportY();
  if (GetWalkableAreaAt(tpx, tpy)) {
    px += xa;
    py += ya;
    player.x = FloatToInt(px, eRoundNearest);
    player.y = FloatToInt(py, eRoundNearest);
  }
  else speed = 0.0;
}


Tested and should work as-is. (Just put it in a fresh script.)

Vault15

Quote from: Khris on Wed 19/06/2013 01:43:56
You'll have to ditch the Keyboard movement module. As soon as you want smooth movement that changes speed without stopping in between, player.Walk() goes out the window.

Tested and should work as-is. (Just put it in a fresh script.)

Wow! Thanks for the incredible amount of help with this. I completely got sidetracked with work, so I just now logged in again. I'll give this code a shot and let you know =).

Edit: You're an absolute genius. I can't believe that everything fully worked the first time EXACTLY as I had wanted. I'm blown away. Even the spacebar function to move backwards worked great! I love how the character decelerates in the chair =]. My only tweaks will be to push away from a wall/border object quicker than when pushing on flat carpet. You did a phenomenal job. Major kudos for this one, Khris.

SMF spam blocked by CleanTalk