Okay, the idea is simple - force the player to collide with the object in front of him and the next draw cycle drag him back out the same xvelocity he travelled in.
Here are the instructions.
1. Add global variables cmove=1 and touch=0.
2. Add this code to Draw Actor:
- Code: Select all
float MSensor=1.2;
char*key=GetKeyState();
//xvelocity becomes either 2 or -2 depending on the key pressed
//if both or none are pressed it is 0
xvelocity=(key[KEY_RIGHT]-key[KEY_LEFT])*2;
//if there is nothing blocking the player
//we reset cmove
if(CollisionFree("Event Actor",x+xvelocity,y-5)) cmove=1;
//if the player was forced to collide previous draw cycle
//this code drags him back out
if(touch!=0){
x-=touch;
xvelocity=0;
touch=0;
}
//if we can walk
//but if we land too deep into ground, lift player up 2 pixels
if(abs(xvelocity)>0&&CollisionFree("Event Actor",x+xvelocity,y-5)&&
CollisionFree("Event Actor",x+xvelocity,y-2)==0){
y-=2;
}
//if floor too high or we face a wall, we cannot move
else if(CollisionFree("Event Actor",x+xvelocity,y-5)==0){
//if cmove (can move) is 1, then we force the player
//to collide with the object in front of him
if(cmove==1){
x+=xvelocity;
touch=xvelocity;
//by putting cmove to 0 we ensure the player
//is forced to collide just once and not repeatedly
cmove=0;
}
xvelocity=0;
}
//determine the direction of movement
//if "1" means key right is pressed, if "-1" key left
if(abs(xvelocity)>0)PlayerWD=xvelocity/abs(xvelocity);
//if xvelocity is larger-equal than movement sensor (we definitely move)
//and if yvelocity is smaller-equal to movement sensor (we are not falling too fast)
//we draw going right animation
if(xvelocity>=MSensor&&abs(yvelocity)<=MSensor)ChangeAnimation("cosmonaut", "goright1", NO_CHANGE);
//or if xvelocity is smaller-equal than negative movement sensor (we move another direction)
//and we are not falling too fast
//we draw going left animation
else if(xvelocity<=-MSensor&&abs(yvelocity)<=MSensor)ChangeAnimation("cosmonaut", "goleft1", NO_CHANGE);
//if we are not moving and not falling, we draw stand animation
if(abs(xvelocity)<MSensor&&abs(yvelocity)<=MSensor)
{
//here we choose which direction to draw
if(PlayerWD==1)ChangeAnimation("cosmonaut", "standright", NO_CHANGE);
else ChangeAnimation("cosmonaut", "standleft", NO_CHANGE);
}
//if we are definitely falling
//we draw falling animation
if(yvelocity>=MSensor)
{
if(PlayerWD==1)ChangeAnimation("cosmonaut", "standright", NO_CHANGE);
else ChangeAnimation("cosmonaut", "standleft", NO_CHANGE);
}
//if we are "falling" the other direction, means we are jumping
else if(yvelocity<=-MSensor)
{
if(Jump==1)PlaySound2("data/BUTTON01.WAV", 0.233333, 1, 0.000000);
if(PlayerWD==1)ChangeAnimation("cosmonaut", "jumpright", NO_CHANGE);
else ChangeAnimation("cosmonaut", "jumpleft", NO_CHANGE);
}
//if there is no collision immediately below us
//and no collision 1 pixel above where we will end after next draw cycle
//we turn gravity on and disallow jumping
if(CollisionFree("Event Actor",x,y+yvelocity)||
CollisionFree("Event Actor",x,y+yvelocity-1)){
yvelocity+=0.16;Jump=0;
}
//but if there is a collision, we turn gravity off
else {
//we turn off ability to jump if there is a
//collision near top of player;
if(CollisionFree("Event Actor",x,y+yvelocity-4)==0)Jump=0;
//if nothing is near top of player, we allow jumping
else {Jump=1;}
yvelocity=0;
}
yvelocity-=key['z']*Jump*jump_height;
What are the drawbacks?
A. If you encounter an item, which the player has to take, you will momentarily stop, since the code pushes you back from the object. This is not necessarily a bad effect, making taking objects being "felt". However, it is trivial to remove this effect if you want your player to just grab items and not have this affect his movement - just add a collision to the object and in a Script Editor write this: touch=0;
This will eliminate the effect completely - player will collide but not be pushed out. Don't do this with walls - or you'll stick to walls!
B. In the original code by Game A Gogo jumping is easier in a way - if the platform is a little bit higher than your jump, you sort of get smoothly dragged up. Not too realistic, but makes jumping effortless. Here, however, each time you encounter a wall, you collide with it and then get pushed back. So if your jump is not high enough - you won't get up. I did see a similar mechanic in a number of games and it feels fine. Also, since now you do collide with walls, it is possible to experiment and script the desired behaviour if necessary. I just began to place platforms at a different distance relative to each other.
C. This code does not deal with a vertical lift. I am yet to solve this problem.
All in all, I am very happy with this method, it works fine and I like it more than Physical Response, since it does not push the player from platform edges and generally requires less scripting and less events. Hope, this will be useful to someone else too.