Need help with keyboard movement code [yet again]

Started by Kinoko, Mon 04/07/2005 15:29:55

Previous topic - Next topic

Rui 'Trovatore' Pires

This might involve recoding lots of stuff, but you can also simulate your own idle-state with a timer and some code. Would give you more control, and allow you to decide what triggers it and what doesn't. I can share how I did it, though my coding is infamously messy.
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Kinoko

Messy? I'll be the judge of that ^_- If you don't mind, share away!

Rui 'Trovatore' Pires

#42
Ok, let's see. I'll remove the bits that apply to my special "animate before/after the actual idle"...

Rep_Exec:
Code: ags
if (IsTimerExpired(2)) {
Ã,  if (player.Moving) SetTimer(2, 10*GetGameSpeed());
Ã,  else {
Ã,  Ã,  if (player.Animating==0 && idling==false && dialog==false) {
Ã,  Ã,  Ã,  idling=true;
Ã,  Ã,  Ã,  player.LockViewOffset(player.View+9,0,-1); //I had to do an offset here. I add 9 because this way I can have up to 10 normal views and respective idles, as long as the idle view animation equals the normal walkcycle view + 9.
Ã,  Ã,  Ã,  if (player.Loop==4) player.Animate(2, player.AnimationSpeed, eOnce, eNoBlock, eForwards); //Diagonals, which I had to adjust in my case. You might not need these four "ifs"
Ã,  Ã,  Ã,  else if (player.Loop==5) player.Animate(3, player.AnimationSpeed, eOnce, eNoBlock, eForwards);
Ã,  Ã,  Ã,  else if (player.Loop==6) player.Animate(1, player.AnimationSpeed, eOnce, eNoBlock, eForwards);
Ã,  Ã,  Ã,  else if (player.Loop==7) player.Animate(3, player.AnimationSpeed, eOnce, eNoBlock, eForwards);
Ã,  Ã,  Ã,  else player.Animate(player.Loop, player.AnimationSpeed, eOnce, eNoBlock, eForwards);
Ã,  Ã,  }
Ã,  }
}


Right, that makes idling active. You'll notice the bool "idling". I needed it for my own purposes, but I think you can scratch it plus the check I used. Now to disable it and generally make sure everything works out allright I made four custom functions. Instead of using player.Walk, I use:

Code: ags
function WalkTo(int dest2x, int dest2y, bool blocking2, bool walkonwalkables) {
Ã,  SetTimer(2, 10*40);
Ã,  if (idling==true){ //Again, this is for my extra purposes. I think you can ignore this check completely.
Ã,  Ã,  if (player.Loop>3) player.Animate(player.Loop+4, player.AnimationSpeed, eOnce, eBlock, eForwards);
Ã,  Ã,  else player.Animate(player.Loop+8, player.AnimationSpeed, eOnce, eBlock, eForwards);
Ã,  Ã,  idling=false;
Ã,  Ã,  player.Loop-=8;
Ã,  Ã,  player.UnlockView(); --> POST EDIT - This is important.
Ã,  } //This bit now is not in my code, but my code had many superfluos things for your case, so I changed it accordingly.
Ã,  if (blocking2==true && walkonwalkables==true)Ã,  player.WalkTo(dest2x,dest2y, eBlock, eWalkableAreas);
Ã,  if (blocking2==true && walkonwalkables==false)Ã,  player.WalkTo(dest2x,dest2y, eBlock, eAnywahere);
Ã,  if (blocking2==false && walkonwalkables==true)Ã,  player.WalkTo(dest2x,dest2y, eNoBlock, eWalkableAreas);
Ã,  Ã, if (blocking2==false && walkonwalkables==false)Ã,  player.WalkTo(dest2x,dest2y, eNoBlock, eAnywhere);
Ã,  Ã, }


And instead of calling Display (and I'm using LucasStyle speech and always display as speech, mind) I use:

Code: ags
function Say(string what) {
Ã,  SetTimer(2, 10*40);
Ã,  if (idling==true){ //That check again... I'm keeping it here so you know that it can be checked whether the player is idling, which is very useful
Ã,  Ã,  if (player.Loop>3) player.Animate(player.Loop+4, player.AnimationSpeed, eOnce, eBlock, eForwards);
Ã,  Ã,  else player.Animate(player.Loop+8, player.AnimationSpeed, eOnce, eBlock, eForwards);
Ã,  Ã,  idling=false;
Ã,  Ã,  player.Loop-=8;
Ã,  Ã,  player.UnlockView();--> POST EDIT - This is important.
Ã,  } 
Ã,  else if (player.Moving) { 
Ã,  Ã,  player.StopMoving();
Ã,  Ã,  stopwalk=false; //This is for my own dark purposes (bwahahaha)
Ã,  }
Ã,  Display(what);
}


If you're not using "always display as speech", you'd naturally put "character.Say" instead of "Display".

And I made the following very simple functions:

Code: ags
function StartTalking() {
Ã,  dialog=true;
Ã,  SetTimer(2, 0);
}

function StopTalking() {
Ã,  dialog=false;
Ã,  SetTimer(2, 10*GetGameSpeed());
}


This is to make sure that in a dialog the idle anim will not kick in, even if the player is not moving for 10 seconds or more. Of course, you may not use it - there IS a certain charm in seeing the player idling during a boring conversation. ;)

K, I think that's it. It's not that messy because I edited it a lot. ;) I hope you find a use for it. Mind you, you'd have to replace ALL your Walk and Say commands, unless you want to check that separately, which is possible, accourse.

EDIT - Mind you, I just noticed something. You might need that check after all. I forgot you have to unlock the view. I edited the code accordingly.

EDIT 2 - Forgot to say this - the advantage is that you now have total control of the idle animations, and you can do what the heck you want.

EDIT 3 - Oh, about that "LockView(player.View+9)" - I did that so I could have at least 10 views. If you only have one, you can just change it to a specific view; if not, then you can do the same adding trick, just make sure that the numerical difference between the idles and walkcycles views remains the same.

EDIT 4 - Duh, I keep forgetting to say stuff... I use StartTalking and StopTalking before and after every conversation.
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Kinoko

#43
I'm trying one other thing and if that doesn't work, I'll give your code a try, Rui. Thanks!

EDIT: I solved the idle problem by placing a cEgo.SetIdleView(-1,  30); line after the characterY += dyf*... lines in both the TryDiagonal and TryStraight functions, and then placing:

Code: ags

if ((character[EGO].Animating==0) && (cEgo.IdleView==-1)) {
     cEgo.SetIdleView(5,  30);
     SetLabelText(27, 0, "IDLE ON");
   }


in Repeatedly_execute. Works fine now (as far as I've tested so far).

I've also noticed one more problem. Even though the NPCs in my game are "solid", this walking code doesn't check for them so EGO walks right through them.

EDIT2: Is there any way to check if there's a character at a certain x/y position?
     

Rui 'Trovatore' Pires

Re EDIT2 - Character.GetAtScreen(x,y), or something? Or am I misunderstanding again?
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Kinoko

Well, it's a check to see if -any- character is in said position (gee, why does this sound familiar)...

I'd like my characters to be solid but because this walking code only checks whether there's a walkable area or not, I need it to also check if a character is on said x/y position too.

Rui 'Trovatore' Pires

Character.GetAtScreen(x,y)!=null and Character.GetAtScreen(x,y)==null? Or am I STILL misunderstanding?
Reach for the moon. Even if you miss, you'll land among the stars.

Kneel. Now.

Never throw chicken at a Leprechaun.

Kweepa

#47
I updated the code on page 1 to handle characters.
Rui's check will allow the characters to overlap significantly.

The basic idea is:
- find a list of solid characters near the player in the same room in rep_ex
- replace GetWalkableAreaAt() with PlayerCanMoveHere() which checks the list
Ã,  Ã, - if the player is colliding with the character and getting closer don't allow the move

Unfortunately it's difficult to find out the exact width and height required - it might be better to set these directly at the start of the game.

For example:
Code: ags

character.BlockingWidth = 16;
character.BlockingHeight = 8;


Unless someone has a better idea?
Still waiting for Purity of the Surf II

Kinoko


Kinoko

Im starting to play around with the game again after a break, so this code has come in question yet again for me.

Actually, I have lots of problems that all seem to stem from it, such as objects being walked through, FaceCharacter not working properly, the Character Collision plugin doesnt seem to work properly with it, EGO randomly appears at different coordinates on the screen when he walks sometimes... Im not sure if they all come from this code, but at the moment I`m wonderinf if maybe there isnt just another way to do what I was originally asking just by modifying my original code to check for edges, etc. Changing the entire system of walking just seems too messy at this stage.

Its probably asking the impossible, but does anyone have an idea of how it could be done?

Kweepa

Oh well, I tried.
Unfortunately I don't really have time to fix those last little issues.
Sorry 'bout dat.

Good luck!
Still waiting for Purity of the Surf II

Kinoko

Sorry Steve!!! It doesn't mean I don't really appreciate all your help... I hope you don't think that. I'm honestly just too lazy to anilyse the code and figure out ways  to make it work in every way I want it to. I'm really picky and fickle, and not very good at scripting.

SMF spam blocked by CleanTalk