Isometric Platforming

Started by stepsoversnails, Fri 17/06/2011 04:11:42

Previous topic - Next topic

stepsoversnails

I'm currently toying around with the Keyboard Movement Module, trying to create an Isometric Platformer.
I am, however, horrible at programming.
I'm not looking to do anything too fancy, in fact all i need to achieve right now is Jumping.
I tried every theory i had and none of them worked.
I'm really hoping someone might be able to nip this problem in the butt for me as it would help me achieve making a game i've dreamt of making since i was a kid.

Ryan Timothy B

Well no one here will just program this for you. If you'd show some code that you've written and having issues with, someone might offer their help.
I'm also not familiar with an isometric platformer. Is it something like the final fantasy games?

stepsoversnails

I just meant a platformer on an isometric view. The best example i can provide is a game called Whizz, which was on the super nintendo.

The only code i've been able to figure out so far is
Code: ags
	if (keycode == eKeySpace) {
		cEgo.Move (cEgo.x-GetViewportX(), cEgo.y-GetViewportY()-70, eBlock, eAnywhere);
		cEgo.Move (cEgo.x-GetViewportX(), cEgo.y-GetViewportY()+70, eBlock, eAnywhere);
	}
	
	if ((keycode == eKeySpace) && (keycode== eKeyLeftArrow)) {
		cEgo.Move (cEgo.x-GetViewportX()-30, cEgo.y-GetViewportY()-70, eBlock, eAnywhere);
		cEgo.Move (cEgo.x-GetViewportX()-30, cEgo.y-GetViewportY()+70, eBlock, eAnywhere);
	}


It mimics jumping when pressing space. Though when pressing Space and Left Ego still just goes straight up and then down. But really the script obviously has more serious problems than that. I don't know how i could do this without blocking the entire game while he jumps or how i could stop ego from landing on non walkable areas or how ego could land on higher platforms.



Khris

First of all, detecting keypresses for an action game isn't usually done in on_key_press; among the reasons is that obviously keycode cannot have two different values at the same time.

What you need to do instead is use IsKeyPressed() inside repeatedly_execute.

I also highly recommend to use variables from the start and allow players to remap the controls. There are only a few things I hate even more than having to control a game with the cursor keys instead of WASD.

With that out of the way, I'm pretty sure that Character.Move requires room coordinates, not screen coordinates. Why did you put GetViewportX/Y() in there?

Regarding the actual jumping: to achieve a smooth arc and not block the game, what you do is use a bit of vector math. The cool thing about AGS characters is that we don't need to fiddle around with x and y for vertical jumps, characters have a z coordinate that'll have no effect on the characters position on the ground but draw them higher or lower; exactly what we need.

Here's the code:

header:
Code: ags
// header 

struct str_keys {
  eKeyCode Jump;
  eKeyCode Up;
  eKeyCode Left;
  eKeyCode Right;
  eKeyCode Down;
};

import str_keys keys;


main script:
Code: ags
str_keys keys;
export keys;

float px, py, pz, pmx, pmy, pmz;

void game_start() {
  keys.Jump = eKeySpace;
  keys.Up = eKeyW;
  keys.Left = eKeyA;
  keys.Right = eKeyD;
  keys.Down = eKeyS;
  
  px = 160.0;
  py = 160.0;
}

float gravity = -0.5;
bool on_ground = true;

void repeatedly_execute() {
  if (on_ground) {
    if (IsKeyPressed(keys.Jump)) {
      pmz = 8.0;  // jump force
      on_ground = false;
    }
    pmx = 0.0;
    pmy = 0.0;
    if (IsKeyPressed(keys.Up)) {
      pmx = 3.0;            // walk up and right
      pmy = -1.0;
    }
    if (IsKeyPressed(keys.Left)) {
      pmx = -3.0;         // walk up and left
      pmy = -1.0;
    }
    if (IsKeyPressed(keys.Right)) {
      pmx = 3.0;            // walk down and right
      pmy = 1.0;
    }
    if (IsKeyPressed(keys.Down)) {
      pmx = -3.0;         // walk down and left
      pmy = 1.0;
    }
  }
  else {  // in the air
    pmz += gravity;    // gravity changes z vector
  }
  
  px += pmx;
  py += pmy;
  pz += pmz;
  if (pz <= 0.0) {
    pz = 0.0;
    on_ground = true;
  }
  player.x = FloatToInt(px, eRoundNearest);
  player.y = FloatToInt(py, eRoundNearest);
  player.z = FloatToInt(pz, eRoundNearest);
}


pmx, pmy, pmz: floats storing movement vector of player
px, py, pz: floats storing player's position
on_ground: bool to track whether player is standing on ground or in the air

Right now, the player falls until z == 0.0.
In your game you'd have collision detection as in an array with z-values for the players current tile or what have you.

stepsoversnails

Thanks Khris. I think i even learnt a little.
The reason i used Getviewport was because it was the only thing i had any experience with.
I have the programming skills of a Bran Muffin.

Your code is great and i think i understand it well enough.
There are two main problems with it though. The Character doesn't animate while walking and it also doesn't obey walkable areas. I couldn't figure this out for myself without getting a bombardment of errors.
And another thing that isn't a problem but i feel i should mention, i still want the character to be able to move vertically and horizontally while only moving diagonally if the player presses up/left or down/right etc...

thank you for your time  ;D

Khris

#5
Replace the old repeatedly_execute function with this:

Code: ags
#define sideways 2.0
#define updown 1.0

int frame_timer;

void repeatedly_execute() {
  
  bool walking = true;
  
  if (on_ground) {
    if (IsKeyPressed(keys.Jump)) {
      pmz = 8.0;  // jump force
      on_ground = false;
    }
    pmx = 0.0;
    pmy = 0.0;
    if (IsKeyPressed(keys.Up)) pmy -= updown;
    if (IsKeyPressed(keys.Left)) pmx -= sideways;
    if (IsKeyPressed(keys.Right)) pmx += sideways;      
    if (IsKeyPressed(keys.Down)) pmy += updown;
    if (pmx == 0.0 && pmy == 0.0) walking = false;
  }
  else {  // in the air
    pmz += gravity;    // gravity changes z vector
  }
  
  int x = FloatToInt(px + pmx, eRoundNearest)-GetViewportX();
  int y = FloatToInt(py + pmy, eRoundNearest)-GetViewportY();
  if (GetWalkableAreaAt(x, y)) {
    px += pmx;
    py += pmy;
  }
  pz += pmz;
  if (pz <= 0.0) {
    pz = 0.0;
    on_ground = true;
  }
  player.x = FloatToInt(px, eRoundNearest);
  player.y = FloatToInt(py, eRoundNearest);
  player.z = FloatToInt(pz, eRoundNearest);
  
  if (pmx < 0.0) player.Loop = 1;
  else if (pmx > 0.0) player.Loop = 2;
  else if (pmy < 0.0) player.Loop = 3;
  else if (pmy > 0.0) player.Loop = 0;
  
  frame_timer++;
  
  if (frame_timer >= player.AnimationSpeed - 1) {  
  frame_timer = 0;
    int f = player.Frame;
    if (on_ground) {
      if (walking) {
        f++;
        if (f >= Game.GetFrameCountForLoop(player.NormalView, player.Loop)) f = 1;
      }
      else f = 0;
    }
    player.Frame = f;
  }
}


Edit: added defines

stepsoversnails

Hmmm. AGS comes up with an error saying "undefined Symbol 'updown'".
Am i meant to have initiated this at some point?

Khris

Sorry, my bad, put this above rep_ex:

Code: ags
#define sideways 2.0
#define updown 1.0

mode7

I'm currently working on a tile engine module that loads tiled-maps (tmx format)  and supports isometric and paralell tiles. It's in early stages however. Calin also has coded an iso engine I think but I don't know if he plans to release a module.

As for your error:
try adding an
int updown;
at the beginning of the script and see what happens

stepsoversnails

#9
thanks, that did the trick. This works great.
There are few things such as the character doesnt view his diagonal pose, he walks too slow and animates too fast and he cant jump onto higher platforms BUT i think i will have a tinker and try to figure out some of that stuff myself. Though don't hold your breath.
if i make this game someday you will be getting a big mention, Khris.

Khris

I haven't included diagonal loops but you can put them in there quite easily.

just replace this part:
Code: ags
  if (pmx < 0.0) player.Loop = 1;
  else if (pmx > 0.0) player.Loop = 2;
  else if (pmy < 0.0) player.Loop = 3;
  else if (pmy > 0.0) player.Loop = 0;


with:
Code: ags
  if (pmx < 0.0) {
    if (pmy < 0.0) player.Loop = 7;
    else if (pmy == 0.0) player.Loop = 1;
    else player.Loop = 6;
  }
  else if (pmx == 0.0) {
    if (pmy < 0.0) player.Loop = 3;
    else if (pmy > 0.0) player.Loop = 0;
  }
  else {
    if (pmy < 0.0) player.Loop = 5;
    else if (pmy == 0.0) player.Loop = 2;
    else player.Loop = 4;
  }


Slow walking:
change the values of the defines I forgot in the last block. They specify how far the character moves per frame. It's fine to use values like 2.4.
To change how fast they animate, just change the character's animation speed in the editor. My code uses that value.

You can change the height of a jump and how fast they fall by tinkering with the jump force line and gravity value, respectively.

Higher platforms:
Well, currently the code assumes that all ground is at z = 0. It's relatively easy to change that, since you're using walkable areas you could use area 1 for z = 0, area 2 for z = 10, etc.
It's a quick fix. It requires some additional code for walking off platforms though.

stepsoversnails

ah perfect. Except the animation speed. It seems if i set it to anything below 3 it doesn't animate and anything above 3 makes it move so fast it looks like a blur.

SMF spam blocked by CleanTalk