SOLVED [SOLVED] How to do water and ice physics in GameMaker 8.1?

Arlan64

Member
Hi guys,

I want to create a swim gameplay for my character, but I don't know how to makes this posible...

I give you my codes (many parts have been copied from Shaun with his tutorials)

Code:
Blooby (the player) >> Create Event

grav = 0.50;
hsp = 0;
vsp = 0;

jumps = 0;
jumpsmax = 1;
jumps_outside = 0;

jumpspeed_normal = 10;
jumpspeed_powerup = 13.8;
jumpspeed_water = 1
jumpspeed = jumpspeed_normal

movespeed_normal = 6;
movespeed_powerup = 10;
movespeed = movespeed_normal

touch_ennemies = 0;

Blooby >> Step

key_right = keyboard_check(vk_right);
key_left = -keyboard_check(vk_left);
key_jump = keyboard_check(vk_up);
key_jump_held = keyboard_check(vk_up);
key_down = -keyboard_check_pressed(vk_down);

move = key_left + key_right;
hsp = move * movespeed;
if (vsp < 10)
{
    vsp += grav;
}

{if (place_meeting(x,y+1,obj_floor))
    {
    vsp = key_jump * -jumpspeed;
    }

if (place_empty(x,y+1))
    {
    vsp += key_down * -jumpspeed
    }

if (place_meeting(x,y,obj_water))
    {
    vsp += key_down * -jumpspeed
    }

if (place_meeting(x,y+1,obj_water))
{
    jumps = jumpsmax;
    jumpspeed_normal = jumpspeed_water;
}

if (key_jump) && (jumps > 0)
{
    jumps -= 1;
    vsp = -jumpspeed = 0;
}

/*if (place_meeting(x,y,obj_water))
{
    grav = 0
}*/

///No jumps outside
if (place_empty(x,y))
{
    jumps = jumps_outside
    grav = 0.50
    jumpspeed_water = jumpspeed_normal
}

if (vsp < 0) && (!key_jump_held)
{
    vsp = max(vsp,-jumpspeed/4)
}

if (place_meeting(x,y,obj_water)) && vsp = max(vsp,-jumpspeed/4)
{
    vsp = 4
}

if place_meeting(x,y,obj_water)
{
    jumpspeed_normal = 1
}

if place_meeting(x,y,obj_water) && key_jump
{
    vsp = min(vsp,-jumpspeed/1.50)
    key_jump_held = key_jump
}

if place_meeting(x,y,obj_water) && key_jump_held = key_jump
{
    vsp = -4
}
if place_meeting(x,y,obj_water) && ((vsp < 0 && (key_jump_held)))
{
    vsp += grav;
}

}

//------------------------------------------------------------------------------------------------------------------------------

///Horizontal Collision
if (place_meeting(x+hsp,y,obj_floor))
{
    while(!place_meeting(x+sign(hsp),y,obj_floor))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

///Vertical Collision
if (place_meeting(x,y+vsp,obj_floor))
{
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
Sorry if I delete the comments of the code, and sorry if there is a lot of codes that are off topic... (i'm french too... so..)

Help me, please, thanks!

PS: The "/* [...] */", this is to cancel the code when I testing my game... ^^'
 
O

Obj_Neil

Guest
I would make an object to place over my water and when player collides with it, change players jump speed, gravity, and hsp vsp. Adjusting those will make it feel like swimming.
 

3dgeminis

Member
What I would do in this case, is to use 2 objects, one when it is in the water and another for when it is not.
That way I just have to be changing objects and keep each object simpler when programming.
 

Arlan64

Member
I do not think it's the best of things ... but I let people give their opinion again a little...
In fact, what I want to do is to reproduce the same physics as in Super Mario Bros., when we press "A", Mario will make a slight jump in the water. Well, I want to do more or less the same thing.
 

GMWolf

aka fel666
What's wrong with switching objects?
An object really describes the behaviour of an instance. If you need different behaviour, use a different object...
 

Arlan64

Member
What's wrong with switching objects?
An object really describes the behaviour of an instance. If you need different behaviour, use a different object...
Okay I see! So... How can I make this possible? (I'm very bad sorry...)
 

GMWolf

aka fel666
From what I gather, you dont understand the code you posted up above.
the first step would be to fully understand what it is the code you have is doing.
Really there is no other way to learn.
 

Arlan64

Member
From what I gather, you dont understand the code you posted up above.
the first step would be to fully understand what it is the code you have is doing.
Really there is no other way to learn.
But yes I understand all the codes I posted, except those who are concerned with swimming. You see that I tried full codes that only work half, and I can not find any help on the internet So that's why I came here ...
 

Arlan64

Member
The codes with the comments (but it's french)

Code:
///Initialisation des variables

//Saisir la gravité initiale
grav = 0.50;
//Saisir la vitesse horizontale initiale
hsp = 0;
//Saisir la vitesse verticale initiale
vsp = 0;
//Saisir le nombre de sauts initial au sol
jumps = 0;

//Saisir le nombre de sauts maximum initiaux
jumpsmax = 1;
//Saisir le nombre de sauts dans les airs
jumps_outside = 0;

//Saisir la vitesse du saut initial (la hauteur plutôt)
jumpspeed_normal = 10;
//Saisir la vitesse du saut avec le HighJump PowerUp (la hauteur plutôt)
jumpspeed_powerup = 13.8;
//Saisir la vitesse de nage vertical initiale
jumpspeed_water = 1

//Saisir la vitesse de saut qui est égale à la vitesse de saut normale
jumpspeed = jumpspeed_normal

//Saisir la vitesse de déplacement initiale
movespeed_normal = 6;
//Saisir la vitesse de déplacement avec le HighSpeed PowerUp
movespeed_powerup = 10;

//Saisir la vitesse de déplacement qui est égale à la vitesse de déplacement normale
movespeed = movespeed_normal

//Saisir la collision initiale avec les ennemis
touch_ennemies = 0;
Code:
///Les déplacements de Blooby

///Les commandes de déplacement
key_right = keyboard_check(vk_right);
key_left = -keyboard_check(vk_left);
key_jump = keyboard_check(vk_up);
key_jump_held = keyboard_check(vk_up);
key_down = -keyboard_check_pressed(vk_down);

///Réactions aux déplacements
move = key_left + key_right;
hsp = move * movespeed;
if (vsp < 10)
{
    vsp += grav;
}

///Prise d'appui au sol pour sauter
{if (place_meeting(x,y+1,obj_floor))
    {
    vsp = key_jump * -jumpspeed;
    }

///Dash en l'air
if (place_empty(x,y+1))
    {
    vsp += key_down * -jumpspeed
    }

///Dash dans l'eau
if (place_meeting(x,y,obj_water))
    {
    vsp += key_down * -jumpspeed
    }

///Sauts dans l'eau
if (place_meeting(x,y+1,obj_water))
{
    jumps = jumpsmax;
    jumpspeed_normal = jumpspeed_water;
}

if (key_jump) && (jumps > 0)
{
    jumps -= 1;
    vsp = -jumpspeed = 0;
}

///Déplacements libres dans l'eau
/*if (place_meeting(x,y,obj_water))
{
    grav = 0
}*/

///Pas de sauts en dehors de l'eau
if (place_empty(x,y))
{
    jumps = jumps_outside
    grav = 0.50
    jumpspeed_water = jumpspeed_normal
}

///Hauteurs de sauts limités à 4 hauteurs
if (vsp < 0) && (!key_jump_held)
{
    vsp = max(vsp,-jumpspeed/4)
}
//Ralentissements dans l'eau
if (place_meeting(x,y,obj_water)) && vsp = max(vsp,-jumpspeed/4)
{
    vsp = 4
}
///Même physique sur terre mais dans l'eau version /4 (test)
if place_meeting(x,y,obj_water)
{
    jumpspeed_normal = 1
}

if place_meeting(x,y,obj_water) && key_jump
{
    vsp = min(vsp,-jumpspeed/1.50)
    key_jump_held = key_jump
}

if place_meeting(x,y,obj_water) && key_jump_held = key_jump
{
    vsp = -4
}
if place_meeting(x,y,obj_water) && ((vsp < 0 && (key_jump_held)))
{
    vsp += grav;
}

}

//------------------------------------------------------------------------------------------------------------------------------

///Horizontal Collision
if (place_meeting(x+hsp,y,obj_floor))
{
    while(!place_meeting(x+sign(hsp),y,obj_floor))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

///Vertical Collision
if (place_meeting(x,y+vsp,obj_floor))
{
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
 

Roa

Member
just check if you are colliding with a water object and change your movement attributes. IE, less gravity, less jump height, and horizontal movement slows over time. Make jumping reset that slowing over time value
 

Arlan64

Member
just check if you are colliding with a water object and change your movement attributes. IE, less gravity, less jump height, and horizontal movement slows over time. Make jumping reset that slowing over time value
Yeah I see what you want to do, basically we change the attributes in the variables involved!
 

Arlan64

Member
Finally I find the good code for the less jump height.
Now, I want to reduce the gravity in the water (vertical and horizontal speed) but idk to do that...

Code:
///Les déplacements de Blooby

///Les commandes de déplacement
key_right = keyboard_check(vk_right);
key_left = -keyboard_check(vk_left);
key_jump = keyboard_check(vk_up);
key_jump_held = keyboard_check(vk_up);
key_jump_pressed = keyboard_check_pressed(vk_up);
key_down = -keyboard_check_pressed(vk_down);

///Réactions aux déplacements
move = key_left + key_right;
hsp = move * movespeed_normal;
if (vsp < 10)
{
    vsp += grav_normal;
}

///Prise d'appui au sol pour sauter
{if (place_meeting(x,y+1,obj_floor))
    {
    vsp = key_jump * -jumpspeed_normal;
    }

///Dash en l'air
if (place_empty(x,y+1))
    {
    vsp += key_down * -jumpspeed
    }

///Sauts dans l'eau

if place_meeting(x,y,obj_water) && key_jump_pressed
{
    vsp = key_jump_pressed * -jumpspeed_water;
}

///Pas de sauts en dehors de l'eau
if (place_empty(x,y))
{
    jumps = jumps_outside;
    grav_water = grav_normal;
}

///Hauteurs de sauts limités à 4 hauteurs
if (vsp < 0) && (!key_jump_held)
{
    vsp = max(vsp,-jumpspeed/4)
}
//Ralentissements dans l'eau

THE CODE FOR THE LESS GRAVITY HERE!

}

//------------------------------------------------------------------------------------------------------------------------------

///Horizontal Collision
if (place_meeting(x+hsp,y,obj_floor))
{
    while(!place_meeting(x+sign(hsp),y,obj_floor))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

///Vertical Collision
if (place_meeting(x,y+vsp,obj_floor))
{
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
Thanks.
 

Arlan64

Member
I've succeded to set the hsp in the water.
But the last part, the most difficult part... the vsp.
I have a lot of bugs with my stupid codes that never work as I want...

I give you again my codes, hoping that I receive a minimum of help to finish programming this water, your help will be nice to you! :)

Blooby >> Create
Code:
///Initialisation des variables

//Saisir la gravité initiale
grav_normal = 0.50;
grav_water = 0.40;

grav = grav_normal;
//Saisir la vitesse horizontale initiale
hsp = 0;
//Saisir la vitesse verticale initiale
vsp = 0;
//Saisir le nombre de sauts initial au sol
jumps = 0;

//Saisir le nombre de sauts maximum initiaux
jumpsmax = 1;
jumpsmax_water = 999999;
//Saisir le nombre de sauts dans les airs
jumps_outside = 0;

//Saisir la vitesse du saut initial (la hauteur plutôt)
jumpspeed_normal = 10;
//Saisir la vitesse du saut avec le HighJump PowerUp (la hauteur plutôt)
jumpspeed_powerup = 13.8;
//Saisir la vitesse de nage verticale initiale
jumpspeed_water = 7.2;

//Saisir la vitesse de saut qui est égale à la vitesse de saut normale
jumpspeed = jumpspeed_normal

//Saisir la vitesse de déplacement initiale
movespeed_normal = 6;
//Saisir la vitesse de déplacement avec le HighSpeed PowerUp
movespeed_powerup = 10;
//Saisir la vitesse de nage horizontale initiale
movespeed_water = 4

//Saisir la vitesse de déplacement qui est égale à la vitesse de déplacement normale
movespeed = movespeed_normal

//Saisir la collision initiale avec les ennemis
touch_ennemies = 0;
Blooby >> Step
Code:
///Les déplacements de Blooby

//Les commandes de déplacement
key_right = keyboard_check(vk_right);
key_left = -keyboard_check(vk_left);
key_jump = keyboard_check(vk_up);
key_jump_held = keyboard_check(vk_up);
key_jump_pressed = keyboard_check_pressed(vk_up);
key_down = -keyboard_check_pressed(vk_down);

//Réactions aux déplacements basiques
move = key_left + key_right;
hsp = move * movespeed_normal;
if (vsp < 10)
{
    vsp += grav_normal;
}

//Prise d'appui au sol pour sauter
{if (place_meeting(x,y+1,obj_floor))
    {
    vsp = key_jump * -jumpspeed_normal;
    }

//Dash en l'air
if (place_empty(x,y+1))
    {
    vsp += key_down * -jumpspeed
    }

//Sauts dans l'eau

if place_meeting(x,y,obj_water) && key_jump_pressed
{
    vsp = key_jump_pressed * -jumpspeed_water;
}

//Pas de sauts en dehors de l'eau
if (place_empty(x,y))
{
    jumps = jumps_outside;
    grav_water = grav_normal;
}

//Hauteurs de sauts limités à 4 hauteurs
if (vsp < 0) && (!key_jump_held)
{
    vsp = max(vsp,-jumpspeed/4)
}
//Ralentissements dans l'eau

if (place_meeting(x,y,obj_water))
{
    hsp = move * movespeed_water
    // vsp = ??? <----------------------------------------------------------------------------------
}

}

///Collisions avec le sol/mur

//Collision horizontale
if (place_meeting(x+hsp,y,obj_floor))
{
    while(!place_meeting(x+sign(hsp),y,obj_floor))
    {
        x += sign(hsp);
    }
    hsp = 0;
}
x += hsp;

//Collision verticale
if (place_meeting(x,y+vsp,obj_floor))
{
    while(!place_meeting(x,y+sign(vsp),obj_floor))
    {
        y += sign(vsp);
    }
    vsp = 0;
}
y += vsp;
 
T

Tidbit

Guest
So ideally, you don't want to create different movement code for when your character is in the water/out of the water. Instead, you can create a variable that your hspeed and vspeed variables will be multiplied by so that your movement speed changes.
In the create event, make two new variables:
Code:
swim  = 0; // this is to establish when you're in water
_mod = 1; // this will always be set to 1 unless we're in the water, in which case we'll make it a smaller value
Now, in our step event we'll want to make the proper checks, and we can do some pretty neat tricks too.
Code:
swim = place_meeting(x, y, objWater);
_mod = swim ? .8 : 1;
You'll notice that mod is being set strangely. This is because we're using whats known as a ternary function. Basically, _mod = .8 if swim is true and 1 if swim is false.


when you handle your horizontal speed or your vertical speed you can now multiply the normal variable by "_mod" which is now changed based on whether or not swim is true or false (1 or 0). This way you dont need a bunch of different variables, just these three. You'd put this at the bottom of your code:
Code:
hsp = move * _mod;
vsp = move * _mod;
Now.... as it stands your code is really kind of messy and a bit all over the place so setting the variables in this way might not quite work all that well. Here's how I would set things up.
Create event:
Code:
xspd = 0;
jspd = -10;
yspd = 0;
yspdmax = 12;
grav = 1;
air = 0;
swim = 0;
_mod = 0
Step:
Code:
left   = keyboard_check_direct(vk_left);
right   = keyboard_check_direct(vk_right);
bt_a   = keyboard_check_pressed(ord("A")); //jump

// Set the swim and _mod variables
swim = place_meeting(x, y, oWater) // we can do this because place meeting returns a boolean (1/0)
_mod = swim ? .8 : 1;

// Falling /////////////////////////////////////////////
if (place_meeting(x, y + 1, oSolid)) {
   yspd = 0;
   air  = 0;
} else {
   if (yspd < yspdmax) {
       yspd += grav;
       air = 1;
   }
}

// Moving left and right ////////////////////////////////
if (right) {
   xspd = 3;
   if (place_meeting(x + 2, y, oSlope)) {
       y--
   }
}

if (left) {
   xspd = -3;
   if (place_meeting(x - 2, y, oSlope)) {
       y--
   }
}

if ((!right && !left) || (right && left)) {
   xspd = 0;
}

// Jumping ////////////////////////////////////////////
if (!air && bt_a) {
   yspd = jspd;
}

// Horizontal Collision ///////////////////////////////
if (place_meeting(x + xspd, y, oSolid)) {
   while (!place_meeting(x + sign(xspd), y, oSolid)) {
       x += sign(xspd);
   }
   xspd = 0;
}

// Veritcal Collision /////////////////////////////////
if (place_meeting(x, y + yspd, oSolid)) {
   while (!place_meeting(x, y + sign(yspd), oSolid)) {
       y += sign(yspd);
   }
   yspd = 0;
}

// Move the character ////////////////////////////
x += xspd*_mod;
y += yspd*_mod;
The only thing this doesn't have is the variable jumping stuff but that'd be easy to implement and if you want to change the speed for when you have a powerup, you would just have a condition that checks if powerup is true and then set _mod to a value higher than 1, just remember to set it back to 1 if powerup is false.

If you have any issues, I'll do my best to explain :)
 
Last edited by a moderator:

Arlan64

Member
So ideally, you don't want to create different movement code for when your character is in the water/out of the water. Instead, you can create a variable that your hspeed and vspeed variables will be multiplied by so that your movement speed changes.
In the create event, make two new variables:
Code:
swim  = 0; // this is to establish when you're in water
_mod = 1; // this will always be set to 1 unless we're in the water, in which case we'll make it a smaller value
Now, in our step event we'll want to make the proper checks, and we can do some pretty neat tricks too.
Code:
swim = place_meeting(x, y, objWater);
_mod = swim ? .8 : 1;
You'll notice that mod is being set strangely. This is because we're using whats known as a ternary function. Basically, _mod = .8 if swim is true and 1 if swim is false.


when you handle your horizontal speed or your vertical speed you can now multiply the normal variable by "_mod" which is now changed based on whether or not swim is true or false (1 or 0). This way you dont need a bunch of different variables, just these three. You'd put this at the bottom of your code:
Code:
hsp = move * _mod;
vsp = move * _mod;
Now.... as it stands your code is really kind of messy and a bit all over the place so setting the variables in this way might not quite work all that well. Here's how I would set things up.
Create event:
Code:
xspd = 0;
jspd = -10;
yspd = 0;
yspdmax = 12;
grav = 1;
air = 0;
swim = 0;
_mod = 0
Step:
Code:
left   = keyboard_check_direct(vk_left);
right   = keyboard_check_direct(vk_right);
bt_a   = keyboard_check_pressed(ord("A")); //jump

// Set the swim and _mod variables
swim = place_meeting(x, y, oWater) // we can do this because place meeting returns a boolean (1/0)
_mod = swim ? .8 : 1;

// Falling /////////////////////////////////////////////
if (place_meeting(x, y + 1, oSolid)) {
   yspd = 0;
   air  = 0;
} else {
   if (yspd < yspdmax) {
       yspd += grav;
       air = 1;
   }
}

// Moving left and right ////////////////////////////////
if (right) {
   xspd = 3;
   if (place_meeting(x + 2, y, oSlope)) {
       y--
   }
}

if (left) {
   xspd = -3;
   if (place_meeting(x - 2, y, oSlope)) {
       y--
   }
}

if ((!right && !left) || (right && left)) {
   xspd = 0;
}

// Jumping ////////////////////////////////////////////
if (!air && bt_a) {
   yspd = jspd;
}

// Horizontal Collision ///////////////////////////////
if (place_meeting(x + xspd, y, oSolid)) {
   while (!place_meeting(x + sign(xspd), y, oSolid)) {
       x += sign(xspd);
   }
   xspd = 0;
}

// Veritcal Collision /////////////////////////////////
if (place_meeting(x, y + yspd, oSolid)) {
   while (!place_meeting(x, y + sign(yspd), oSolid)) {
       y += sign(yspd);
   }
   yspd = 0;
}

// Move the character ////////////////////////////
x += xspd*_mod;
y += yspd*_mod;
The only thing this doesn't have is the variable jumping stuff but that'd be easy to implement and if you want to change the speed for when you have a powerup, you would just have a condition that checks if powerup is true and then set _mod to a value higher than 1, just remember to set it back to 1 if powerup is false.

If you have any issues, I'll do my best to explain :)
Okay, thank you very much for your help ^^... but I have problems...:
- What means "?"? <<_mod = swim ? .8 : 1;>>;
- Why <<_mod = 1;>>, and after <<_mod = 0;>> in the same event?

An example of my problem:
Code:
FATAL ERROR in
action number 1
of  Step Event
for object obj_player:

COMPILATION ERROR in code action
Error in code at line 88:
   _mod = swim ? .8 : 1;
               ^
at position 14: Unexpected symbol.
And for the slope, is it to raise the player without the key to jump in the air? If that's it, genius x')
 
Last edited:
T

Tidbit

Guest
So the "?" means we're using something called a "ternary operator".
A ternary operator basically states "Is the condition true? If yes, do something; if no, do another thing". So in this case _mod is checking if water is true or false, and setting it to .8 or 1 depending on the result. It's basically the same as doing this:
Code:
if (water) {
   _mod = .8;
} else {
  _mod = 1;
}
But instead of writing 5 lines of code, we can basically just put it all into 1 line and get the exact same result.
I'm pretty sure earlier versions other than Studio 1 and 2 support ternary operators but if they don't that would be why you're running into that error. Which would mean that you would have to use the above block of code.

As for the comment on slopes, yeah, that's more or less all there is to slope code at the base level... though it might be a bit buggy so you might want to find a better solution.
 

Arlan64

Member
Okay so it's GML from GMS2, because i'm in the legacy version, in 8.1.

So I changed the <<_mod = swim ? .8 : 1;>>, now, I have an another problem: the "y--"...

Code:
120      // Moving left and right ////////////////////////////////
121     if (right) {xspd = 3;}
122     if (right) && (place_meeting(x + 2, y, obj_slope)) {y--}
123    
124     if (left) {xspd = -3;}
125     if (left) && (place_meeting(x - 2, y, obj_slope)) {y--}

ERROR at line 122 pos 55: Assignement operator expected. (the "y--")
And yes I changed a little the code with two "&&".
 
T

Tidbit

Guest
That's odd, ++ and -- should be operators that GM 8.1 recongizes, I guess you could just do y = y + 1;
That ought to work the same way. I'm not sure why you're breaking up the if statements and including multiple conditionals for key presses, makes things more redundant.
 

Arlan64

Member
Code:
___________________________________________
ERROR in
action number 1
of  Step Event
for object obj_player:

Error in code at line 88:
   if (water) {
       ^
at position 6: Unknown variable water
 
T

Tidbit

Guest
Water is throwing an error because I was just writing a bit of code off the top of my head. I explained what I was doing pretty clearly in the post, so try and figure out what you should be replacing that "water" variable with ;)
While programming can be frustrating at times, a lot of the fun is the problem solving and coming to understand how to break down big complicated issues into easier to manage smaller sized ones. If you're unable to work through it then I'll help a bit more heavily but I believe in you!
 

Arlan64

Member
Water is throwing an error because I was just writing a bit of code off the top of my head. I explained what I was doing pretty clearly in the post, so try and figure out what you should be replacing that "water" variable with ;)
While programming can be frustrating at times, a lot of the fun is the problem solving and coming to understand how to break down big complicated issues into easier to manage smaller sized ones. If you're unable to work through it then I'll help a bit more heavily but I believe in you!
Hey! I tried to understand the best I could and I still can not understand the code... A little help would be welcome...? ^^'
 

TsukaYuriko

☄️
Forum Staff
Moderator
That "code" was not meant to be taken literally and copy-pasted into your project (no code is meant to be copy-pasted). It's something we call "pseudocode" - a code example that follows the logic, but not the letter, of the code you should be writing, so basically: "If in water, set variable to lower value, otherwise set it to higher value."
 

Arlan64

Member
That "code" was not meant to be taken literally and copy-pasted into your project (no code is meant to be copy-pasted). It's something we call "pseudocode" - a code example that follows the logic, but not the letter, of the code you should be writing, so basically: "If in water, set variable to lower value, otherwise set it to higher value."
Yes I know, but after many days and weeks, I don't understand... But I'll try again.
 

FrostyCat

Redemption Seeker
Hey! I tried to understand the best I could and I still can not understand the code... A little help would be welcome...? ^^'
Did you forget this line from post #17?
Code:
swim = place_meeting(x, y, oWater) // we can do this because place meeting returns a boolean (1/0)
If this is what you used, check this variable instead of water.
That's odd, ++ and -- should be operators that GM 8.1 recongizes, I guess you could just do y = y + 1;
That ought to work the same way. I'm not sure why you're breaking up the if statements and including multiple conditionals for key presses, makes things more redundant.
Before you write any more GML advice for GM 8.1, you need to learn what syntax features are actually NOT legacy. Here are some of the most common ones I can think of at the moment:
  • The ternary operator (introduced in GMS 2)
  • The % operator (introduced in GMS 2 as an alternative to the mod operator)
  • Accessors (introduced in GMS 1.3)
  • Arrays as a primitive type (introduced in GMS 1.3)
  • The increment and decrement operators (introduced in GMS 1.3)
  • var on the same line as the initial assignment (e.g. GMS accepts both var i = 5; and var i; i = 5;, but GM legacy only accepts the latter) (introduced in GMS 1.3)
 

Arlan64

Member
I changed something

Before:
Code:
_mod = swim ? .8 : 1;
After:
Code:
if swim = 1
   {_mod = 8};
if swim = 0
   {_mod = 1};
But when the player enter collision with the water, the player move very fast...

(And sorry for my bad english I'm french..)
 

FrostyCat

Redemption Seeker
I changed something

Before:
Code:
_mod = swim ? .8 : 1;
After:
Code:
if swim = 1
   {_mod = 8};
if swim = 0
   {_mod = 1};
But when the player enter collision with the water, the player move very fast...

(And sorry for my bad english I'm french..)
Do you know the difference between 0.8 and 8?
 

Arlan64

Member
Edit: The slopes are okay! But I didn't know how to slow down the player when it plunges into the water, I don't want it to keep the same vsp as on the surface it would'nt make sense..
 
O

Obj_Neil

Guest
I'm not sure if you ever figured out how to do this, but you need to change your player's gravity and jump speed when in the water. For example, I use a finite state machine in my game, and when I collide with water, I switch to a swimming state, where I have different movement code, gravity, etc, which makes it feel like you are in the water.

Imagine you are creating a new swimming game. How would you code the movement so it feels like you are underwater? Slower gravity, less jump, slower movement. Different animations so it looks like swimming. That is how why Super Mario swimming feels that way.

You can create a new object o_player_swim. Make it so only the new movement code and gravity and such affect the new object. Then when you touch water, switch objects from player to player_swim. That would be easier, I think, than updating all your variables for if you are in or out of water.
 

Arlan64

Member
Hi!

It's been a long time since I was in this thread, more than two years anyway!

I'm back here to tell you that I finally got to do what I wanted to do: create the physics of water (and of ice too).

I took a long break from my game to focus on my studies, and recently thought it might be fun to recreate a GM8.1 prototype to test stuff.

So I thought to myself that I could try again from the beggining to recreate the physics of water and ice that I wanted to have.

After just a few days, I got what I wanted to do, it looks like I got better at programming, I'm pretty proud of myself! And I thought to myself that it might be interesting if I publish my code here, if ever other people have difficulties to create physics, or just for all of you who have tried to help me (thank you btw), I have to show you my code!

Here's a video that I shot to show you that it works well. I also spent about twenty minutes to set up this system of directional arrows that light up when we press a key on our keyboard, I thought to myself that it could be useful for you to analyze the physics of the game by comparing what happens with the keys pressed!

obj_player -> Create Event

GML:
///Initialization of variables

//Gravity
grav = 0.50;

//Default Speed
hsp = 0;
vsp = 0;

//Conditions
isFloor = true; //If the player is on the floor or not
isWater = false; //If the player is in the water or not
isIce = false; //If the player is on the ice or not

//Jump Speed
jumpspeed_normal = 10; //Floor Jump Speed
jumpspeed_water = 7.2; //Water Jump Speed
jumpspeed = jumpspeed_normal; //Default Jump Speed

//Movement Speed
movespeed = 6; //Only on the floor and in the air

//Friction
fric_ice = 0.05;
fric_water = 0.1;
fric_floor = 0.001;
obj_player -> Step Event (I did 2 seperated code blocks)

GML:
///Player's Movements

//Controls
key_right = keyboard_check(vk_right); //Right key
key_left = -keyboard_check(vk_left); //Left key (bugged, idk why)
key_jump = keyboard_check(vk_up); //Up key
key_jump_pressed = keyboard_check_pressed(vk_up); //Up key pressed
key_down_pressed = -keyboard_check_pressed(vk_down); //Down key pressed

//Floor support for jumping
if place_meeting(x,y+1,obj_floor) //If the player is on the floor
   {
    if (key_jump) vsp = -jumpspeed; //If the up key is pressed, boost the player to the up to make them jump
   }

//Dash to the down
if !place_meeting(x,y+1,obj_floor) //If the player doesn't touch the floor
   {
    vsp += key_down_pressed * -jumpspeed; //The player can press down to boost himself to the down faster
    if vsp > 30 {vsp = 30;} //If the vertical speed is greater than 30, set the vertical speed to 30 (I set a limit so that the player doesn't go too fast to the down, this is important if you don't want the character to clip the floor by going too fast.)
   }

//Jump heights at every 4 pixels
if (vsp < 0) && (!key_jump) //If the vertical speed is less than 0 and if the up key is not pressed
   {
    vsp = max(vsp,-jumpspeed/4); //The player will be stopped: The player can jump a little or jump heigher.
   }
GML:
///Blooby's Physics (Floor / Water / Ice)

//Gravity
if (vsp < 10) {vsp += grav;} //If the vertical speed is less than 10, the vertical speed will increase with the gravity value.

//Conditions
if !place_meeting(x,y,obj_water) || !place_meeting(x,y,obj_wave) && !place_meeting(x,y+1,obj_ice) { //If the player doesn't touch the water (or the waves) and the ice
   isFloor = true; //The player is on the floor
   isWater = false ; //The player isn't in the water
   isIce = false ; //The player isn't on the ice
   }

if place_meeting(x,y,obj_water) || place_meeting(x,y,obj_wave) && !place_meeting(x,y+1,obj_ice) { //If the player does touch the water (or the waves) and doesn't touch the ice
   isFloor = false; //The player isn't on the floor
   isWater = true; //The player is in the water
   isIce = false; //The player isn't on the ice
   }

if !place_meeting(x,y,obj_water) || !place_meeting(x,y,obj_wave) && place_meeting(x,y+1,obj_ice) { //If the player doesn't touch the water (or the waves) and does touch the ice
   isFloor = false; //The player isn't on the floor
   isWater = false; //The player isn't in the water
   isIce = true; //The player is on the ice
   }

//Ice
if isIce = true { //If the player is on the ice
   if (key_right) {hsp += 0.1;} //If the right key is helded, the horizontal speed will be increase (the player will go faster and faster to the right on each step/frame)
   if keyboard_check(vk_left) {hsp += -0.1;} //If the left key is helded, the horizontal speed will be decrease (the player will go faster and faster to the left on each step/frame (and yeah there's a bug with the left key detection, I can't use a variable to set the left button))
   if hsp > 10 {hsp = 10} //If the horizontal speed is greater than 10, set the horizontal speed to 10 (I set a limit so that the player doesn't go too fast to the right on the ice)
   if hsp < -10 {hsp = -10} //If the horizontal speed is less than 10, set the horizontal speed to 10 (Same here but to the left)
   if ((!keyboard_check(vk_left) && !keyboard_check(vk_right))){ //If the left and right key aren't pressed
      hsp -= fric_ice * sign(hsp); //The player will slow down on each step/frame until the horizontal speed is null
      if place_meeting(x,y,obj_floor){ //If the player is on the ground after being on the ice
         hsp -= fric_floor * sign(hsp); //The player will slow down at each step. Basically I wanted if we go too fast on the ice and then go to the floor, that we don't stop directly. But I don't really know how to do this, but it doesn't matter it's not very important.
         }
      }
   }

//Water
if isWater = true { //If the player is in the water
   jumpspeed = jumpspeed_water; //The jump height will be lower than if the player is on the surface (or the jump height is on "Water" mode)
   vsp -= 0.01; //The vertical speed will decrase on each step/frame (to slow the player when he's enter to the water)
   if (key_down_pressed) {vsp += key_down_pressed * jumpspeed_water;} //If the down key is pressed, the vertical speed will increase with the same speed than the jump height (the player will be pushed down)
   if (key_jump_pressed) {vsp = -jumpspeed;} //If the up key is pressed, the vertical speed will be negative so the player will jump or go up (but with gravity, the player will go down after reaching vsp = 0)
   if (key_right) {hsp += 0.4;} //If the right key is helded, the horizontal speed will be increase (the player will go faster and faster to the right)
   if keyboard_check(vk_left) {hsp += -0.4;} //If the left key is helded, the horizontal speed will be decrease (the player will go faster and faster to the left (and yeah there's a bug with the left key detection, I can't use a variable to set the left button))
   if hsp > 4 {hsp = 4} //If the horizontal speed is greater than 4, set the horizontal speed to 4 (I set a limit so that the player doesn't go too fast to the right in the water)
   if hsp < -4 {hsp = -4} //If the horizontal speed is less than 4, set the horizontal speed to 4 (Same here but to the left)
   if((!keyboard_check(vk_left) && !keyboard_check(vk_right))){hsp -= fric_water * sign(hsp);} //If the left and right key aren't pressed, the player will slow down on each step/frame until the horizontal speed is null
   if vsp > 4 {vsp -= sign(vsp);} //If the vertical speed is greater than 4, the player will slow down on each step/frame
   if vsp > 10 {vsp -= sign(vsp) * 2;} //If the vertical speed is greater than 10, the player will slow down 2 times on each step/frame
   if vsp > 20 {vsp -= sign(vsp) * 3;} //If the vertical speed is greater than 20, the player will slow down 3 times on each step/frame
   if vsp = 30 {vsp -= sign(vsp) * 4;} //If the vertical speed is greater than 30, the player will slow down 4 times on each step/frame (before, we set the max vsp value for the player, this is 30, to avoid clipping floor)
   if vsp = 4 {vsp = 4;} //If the vertical speed is equal to 4, keep this value
   }

//Floor
if isFloor = true { //If the player is on the floor
   jumpspeed = jumpspeed_normal; //Switch to the normal jump height
   move = key_left + key_right; //Reset to the default movement
   hsp = move * movespeed; //Reset to the default horizontal speed
   }

//Horizontal Collision with the floor (wall)
if place_meeting(x+hsp,y,obj_floor) { //If the player touch the floor by the left or the right
   while (!place_meeting(x+sign(hsp),y,obj_floor)) //While the player doesn't stop when he collide with the floor by the left or the right
         {
         x += sign(hsp); //The player will slow down
         }
   hsp = 0; //The player will be stopped
   }
x += hsp; //If this line of code isn't here, the player can't move on the left or on the right

//Vertical Collision with the floor
if place_meeting(x,y+vsp,obj_floor) { //If the player touch the floor by the top or the bottom
     while (!place_meeting(x,y+sign(vsp),obj_floor)) //While the player doesn't stop when he collide with the floor by the top or the bottom
           {
           y += sign(vsp); //The player will slow down
           }
     vsp = 0; //The player will be stopped
   }
y += vsp; //If this line of code isn't here, the player can't jump or dash to the down and the gravity will no longer be applied to the player
obj_floor has to be a solid object
obj_ice has to be the child of obj_floor

That's it, I think I say everything, and sorry if my english is sometimes illogical, i'm french 😅
 
Last edited:
Top