[SOLVED] (Game Maker Classic) Moving Platforms Friction

Build Man

Member
I am back. So , here is the next problem I am stuck with. It's about platforms.

The thing is, I thought a certain tutorial could help me make a platform, but it uses entirely different movement and collision mechanics. And then there's Shaun Spaulding's platform tutorials. While one-way static platform tutorial proved helpful and worked almost perfectly, the moving platform one turned out to be a sham. So was not much helpful.

The main problem is with vertical platform one. When protagonist land s on it, he totally blocks it's upward movement. And when platform moves down, protagonist rapidly lands on a platform rather than standing still. I need Protagonist to... *computer noises* ..."stick" to the platform, moving up and down when platform does so.

Here are the codes:
In Create event, I have this piece of code.
Code:
//WARNING
//To change these, use "Generate Code" function on the object you placed in Room.
//Access "Generate Code" by CTRL+RMB on a desired object.

angle = 0
vel_increment = 0.1
velocity = 1

horizontal = 0
vertical = 0
"angle" is from first attempts at creating moving platform, and is not used, because in-room Creation Code for individual object does not account object's own Create event variables in. "vel_increment" was "angle_increment" before, and "velocity" was "angle_multiplier".

In the Step event, I have this.
Code:
//Allow Protagonist to jump through from below.
if ((Protagonist.bbox_bottom) < y)
mask_index = -1;
else
mask_index = platform_wood1_short
Code:
vel_increment = image_speed
gravity_direction += vel_increment

if hspeed != 0
{
event_perform(ev_other,ev_user0)
velocity = hspeed
hspeed = 0
}
if vspeed != 0
{
event_perform(ev_other,ev_user1)
velocity = vspeed
vspeed = 0
}
if horizontal = 1
x += cos(gravity_direction) * velocity
if vertical = 1
y += sin(gravity_direction) * velocity


//This code defines if it's Horizontal moving platform, or Vertical one.
//Speed is set via CTRL+RMB on a platform and choosing "Creation Code".
The result of trying to make platforms funct without relying on multiple copies of object(for Horizontal and Vertical movement).

if horizontal = 1
x += cos(gravity_direction) * velocity
if vertical = 1
y += sin(gravity_direction) * velocity

This part is taken from aforementioned(and linked) first tutorial. User defined events for this to work are...
Code:
horizontal = 1
Code:
vertical = 1
And this part is taken from platform_parent Object. The event of Collision with Protagonist.
Code:
with other
 {
 if (place_meeting(x,y+vspeed,platform_parent))
 {
     while(!place_meeting(x,y+sign(vspeed),platform_parent))
     {
         y += sign(vspeed);
     }
     vspeed = 0;
 }
 
 if(place_meeting(x+hspeed,y+vspeed,platform_parent))
 {
     while(!place_meeting(x+sign(hspeed),y+sign(vspeed),platform_parent))
     {
         x += sign(hspeed);
         y += sign(vspeed);
     }
     hspeed = 0;
     vspeed = 0;
 }
 }
I think I have covered everything. Now it is up to you to tell what needs to do.
The next topic of the thread is Horizontal Platforms(and Vertical ones when they go upward) having way more friction than they should, severely slowing Protagonist down. It is not in a separate thread because this problem followed immediately afterwards.
Everything solved. What a glorious day!
 
Last edited:

Xer0botXer0

Senpai
character step event

Code:
inst = instance_place(x,y,obj_v_plat)
if inst != noone
{
if inst.y > obj_character.y
{
obj_character.y = inst.y - inst.sprite_height;
}
}
This assumes your characters sprite origin is at the foot of the sprite.
so a better way is to just include the origin offset in the code above.

This doesn't use physics but can work WITH physics, how ...you ask.

Include yet another variable here..

obj_character.y = inst.y - inst.sprite_height - var_jump

right so as an example you would create a function that allows you to jump, causing var_jumps value to decrement to peek jump height then back right. This should allow you to jump while on the platform opposed to being stuck on the platform in the y axis.
 

Build Man

Member
character step event

Code:
inst = instance_place(x,y,obj_v_plat)
if inst != noone
{
if inst.y > obj_character.y
{
obj_character.y = inst.y - inst.sprite_height;
}
}
This assumes your characters sprite origin is at the foot of the sprite.
so a better way is to just include the origin offset in the code above.

This doesn't use physics but can work WITH physics, how ...you ask.

Include yet another variable here..

obj_character.y = inst.y - inst.sprite_height - var_jump

right so as an example you would create a function that allows you to jump, causing var_jumps value to decrement to peek jump height then back right. This should allow you to jump while on the platform opposed to being stuck on the platform in the y axis.
Your method does not seem to make it work as intended. Protagonist still block platform upward movement and still rapidly land on the platform when it goes down. Any modification of your suggested code was making it worse. And I do not use any var_jumps as you assumed. When player presses jump button, It calls for drag and drop event that instantly sets vertical speed to -18. Like so:

Code:
Key Press Event for <Up> Key:
if relative position (0,1) gives a collision with Only solid objects
      set the vertical speed to -18
Also, if you wonder, this is what I have for the step event:

Code:
Step Event:
if relative position (0,1) gives a collision with Only solid objects
      set the friction to 0.6
      set the gravity to 0 in direction 270
      execute code:
if action = 0 && sprite_index != Mako_Weapon
 {
 if speed = 0
 sprite_index = Mako
 }
 
if health <= 0 && vspeed = 0
 {
 instance_create(x,y,KnockedOut_Mako)
 move_snap(x,640)
 speed = 0
 sprite_index = Mako_Damaged
 }
else
      set the friction to 0
      set the gravity to 1 in direction 270
      execute code:
if action = 0
 {
 if sprite_index != Mako_Damaged && sprite_index != Mako_Weapon
  {
  if vspeed < 0
  sprite_index = Mako_Jump
  if vspeed > 0
  sprite_index = Mako_Fall
  }
 if sprite_index = Mako_Damaged && vspeed >= 7 && health > 0
 sprite_index = Mako_Fall
 }
      execute code:
if sprite_index != Mako_Damaged
 {
 if !keyboard_check(vk_left) && !keyboard_check(vk_right)
  {
  if hspeed != 0
  hspeed -= hspeed*0.1
  }
 }
execute code:
if health > 100
health = 100
if mercy = 1 && health > 0 && !instance_exists(MercyShield)
instance_create(x,y,MercyShield)
execute code:
if y>512
 {
 if !instance_exists(KnockedOut_Mako)
  {
  instance_create(x,y+32,KnockedOut_Mako)
  health = 0
  sprite_index = Mako_Damaged
  hspeed = 0
  }
 }
execute code:
if charge_level = 1
 {
 if alarm[11] < 1
 alarm[11] = 3
 }
if charge_level = 2
instance_create(random_range(x-8,x+8),random_range(y-15,y+15),Magic_Charge)
if !keyboard_check(ord('X')) && charge_level > 0
event_perform(ev_keyrelease,ord('X'))
Omit "charge_level" code, it is for one of special weapons in my game.
 
W

Wild_West

Guest
Your method does not seem to make it work as intended. Protagonist still block platform upward movement and still rapidly land on the platform when it goes down. Any modification of your suggested code was making it worse. And I do not use any var_jumps as you assumed. When player presses jump button, It calls for drag and drop event that instantly sets vertical speed to -18. Like so:

Code:
Key Press Event for <Up> Key:
if relative position (0,1) gives a collision with Only solid objects
      set the vertical speed to -18
Also, if you wonder, this is what I have for the step event:

Code:
Step Event:
if relative position (0,1) gives a collision with Only solid objects
      set the friction to 0.6
      set the gravity to 0 in direction 270
      execute code:
if action = 0 && sprite_index != Mako_Weapon
 {
 if speed = 0
 sprite_index = Mako
 }
 
if health <= 0 && vspeed = 0
 {
 instance_create(x,y,KnockedOut_Mako)
 move_snap(x,640)
 speed = 0
 sprite_index = Mako_Damaged
 }
else
      set the friction to 0
      set the gravity to 1 in direction 270
      execute code:
if action = 0
 {
 if sprite_index != Mako_Damaged && sprite_index != Mako_Weapon
  {
  if vspeed < 0
  sprite_index = Mako_Jump
  if vspeed > 0
  sprite_index = Mako_Fall
  }
 if sprite_index = Mako_Damaged && vspeed >= 7 && health > 0
 sprite_index = Mako_Fall
 }
      execute code:
if sprite_index != Mako_Damaged
 {
 if !keyboard_check(vk_left) && !keyboard_check(vk_right)
  {
  if hspeed != 0
  hspeed -= hspeed*0.1
  }
 }
execute code:
if health > 100
health = 100
if mercy = 1 && health > 0 && !instance_exists(MercyShield)
instance_create(x,y,MercyShield)
execute code:
if y>512
 {
 if !instance_exists(KnockedOut_Mako)
  {
  instance_create(x,y+32,KnockedOut_Mako)
  health = 0
  sprite_index = Mako_Damaged
  hspeed = 0
  }
 }
execute code:
if charge_level = 1
 {
 if alarm[11] < 1
 alarm[11] = 3
 }
if charge_level = 2
instance_create(random_range(x-8,x+8),random_range(y-15,y+15),Magic_Charge)
if !keyboard_check(ord('X')) && charge_level > 0
event_perform(ev_keyrelease,ord('X'))
Omit "charge_level" code, it is for one of special weapons in my game.
I don't actually see you cancel the player's gravity anywhere. even if you set the vspeed to zero the gravity will still be moving the player against the platform's vertical motion upward. I had that same issue with my own game's vertical platforms, and cancelling falling in mid air too. so try setting gravity to zero when the player is on the platform and the platform is rising.
 

TheouAegis

Member
If the platform stops moving because the player is on top of it.... did you set the platform or the player to be solid?
 

Build Man

Member
If the platform stops moving because the player is on top of it.... did you set the platform or the player to be solid?
The platform is solid. The necessity because of this code for Collision with Protagonist.
Code:
with other
 {
 if (place_meeting(x,y+vspeed,platform_parent))
 {
     while(!place_meeting(x,y+sign(vspeed),platform_parent))
     {
         y += sign(vspeed);
     }
     vspeed = 0;
 }
 
 if(place_meeting(x+hspeed,y+vspeed,platform_parent))
 {
     while(!place_meeting(x+sign(hspeed),y+sign(vspeed),platform_parent))
     {
         x += sign(hspeed);
         y += sign(vspeed);
     }
     hspeed = 0;
     vspeed = 0;
 }
 }
 

TheouAegis

Member
You are not using place_free(), so it doesn't need to be solid.

The simple fact of the matter is moving objects are not solids, since collision events between any two objects when one is solid prevents further movement from either toward each other. In order for a moving object to be solid, collisions between it and other moving objects should be handled with proximity functions like place_meeting(), not with the collision event.

Without a collision event, the solid property does nothing except allow you to use place_free(). However, as soon as you add a collision event between two objects of which at least one is flagged solid, any movement that occurs prior to the End Step Event will be reversed and the instances will both appear to stop. They're not actually stopping, though, just being snapped back to their previous positions.

If upon collision one of those objects has its speed matched to the other object's speed, then the objects will appear to stop only at the moment of impact (a brief stutter in movement) because it is only at that point that their positions are reset -- once they're set to the same speed, there's no more collision.

However, if one object moves in the Step Event and the other object moves in the End Step Event, then only the object that moves in the Step Event will have its position reset and the object that moves in the End Step Event will keep moving as though there was never any collision.
 
Last edited:

TheouAegis

Member
I don't have an flv viewer on the PC i'm on right now.

If you're not going to mess with YouTube, could you at least describe what is happening in the video? But I'll take a gander -- your original code snaps the player to the platform after a collision with the platform because the solid flag snaps the player out of the collision prior to snapping the player. Now that the platform is not solid and the player is not snapped out of the collision, the player is not being snapped to the platform. Simple solution: do away with the collision event. Move that snapping code in the collision event to the Step Event and change platform_parent to other.id because you shouldn't even be using such a generalized collision check when you already have a specific instance focused.
 

TheouAegis

Member
So yeah, the solid attribute was making it so the player snapped out of the platform and the collision code snapped him to the platform. So now you need to take over the solid attribute's mechanics yourself. You can try changing the collision event to:

Code:
with other
 {
    //Move outside the collision
    y -= vspeed - other.vspeed;

 if (place_meeting(x,y+vspeed,platform_parent))
 {
    while(!place_meeting(x,y+sign(vspeed),platform_parent))
    {
        y += sign(vspeed);
    }
    vspeed = 0;
 }

 if(place_meeting(x+hspeed,y+vspeed,platform_parent))
 {
    while(!place_meeting(x+sign(hspeed),y+sign(vspeed),platform_parent))
    {
        x += sign(hspeed);
        y += sign(vspeed);
    }
    hspeed = 0;
    vspeed = 0;
 }
 }
 

Build Man

Member
So yeah, the solid attribute was making it so the player snapped out of the platform and the collision code snapped him to the platform. So now you need to take over the solid attribute's mechanics yourself. You can try changing the collision event to:

Code:
with other
 {
    //Move outside the collision
    y -= vspeed - other.vspeed;

 if (place_meeting(x,y+vspeed,platform_parent))
 {
    while(!place_meeting(x,y+sign(vspeed),platform_parent))
    {
        y += sign(vspeed);
    }
    vspeed = 0;
 }

 if(place_meeting(x+hspeed,y+vspeed,platform_parent))
 {
    while(!place_meeting(x+sign(hspeed),y+sign(vspeed),platform_parent))
    {
        x += sign(hspeed);
        y += sign(vspeed);
    }
    hspeed = 0;
    vspeed = 0;
 }
 }
I tried your method, and what I say, is that Protagonist's footing on the platform is still unstable. While he can kind of "stand" on the platform, whenever platform goes up, he always sink through it. In fact, I tried that idea already, before asking here, and the results were pretty much the same.
 
Last edited:

TheouAegis

Member
Yeah, but at least the platform isn't getting stuck now. Now all you have to do is apply the platform's speed to the player. Personally, I prefer storing the ID of the platform in the player and then in the End Step event (so after the player and platform have both moved) set the player's position to that of the platform if an ID is stored in the player.
 

Build Man

Member
Yeah, but at least the platform isn't getting stuck now. Now all you have to do is apply the platform's speed to the player. Personally, I prefer storing the ID of the platform in the player and then in the End Step event (so after the player and platform have both moved) set the player's position to that of the platform if an ID is stored in the player.
I could not compute what did you said. Can you do more thorough speech on what needs to be done?
 

TheouAegis

Member
The player and the platform overlap because the player moves after the collision event and before the platform moves. So the collision event is really only going to help you when the player is falling toward the platform or when it is moving down at a speed less than or equal to gravity. If the platform is moving up, the collision event snaps the player to the top of the platform and then the platform moves up into the player after the collision has been handled. This means you need to snap the protagonist to the platform again in the End Step event.

Method 1)
Platform's collision event
Code:
with other
 {
   //Move outside the collision
   y -= vspeed - other.vspeed;
   plat = other.id;

 if (place_meeting(x,y+vspeed,plat))
 {
   while(!place_meeting(x,y+sign(vspeed),plat))
   {
       y += sign(vspeed);
   }
   vspeed = 0;
 }

 if(place_meeting(x+hspeed,y+vspeed,plat))
 {
   while(!place_meeting(x+sign(hspeed),y+sign(vspeed),plat))
   {
       x += sign(hspeed);
       y += sign(vspeed);
   }
   hspeed = 0;
   vspeed = 0;
 }
 }
Player's create event
Code:
plat = noone;
Player's end step event
Code:
if plat
y += bbox_bottom - plat.bbox_top;

Method 2)
Player's end step event
Code:
with instance_place(x,y, platform_parent)
    other.y += other.bbox_bottom - bbox_top;

The second method is easier for you to implement, but it's slower for the computer to process since it is executing an extra proximity check every step.

The formula A.y+=A.bbox_bottom-B.bbox_top is a quick and dirty way to snap object A to the top of object B. If you still have a pixel overlap, change the formula to A.y+=A.bbox_bottom-B.bbox_top-1
 

Build Man

Member
The player and the platform overlap because the player moves after the collision event and before the platform moves. So the collision event is really only going to help you when the player is falling toward the platform or when it is moving down at a speed less than or equal to gravity. If the platform is moving up, the collision event snaps the player to the top of the platform and then the platform moves up into the player after the collision has been handled. This means you need to snap the protagonist to the platform again in the End Step event.

Method 1)
Platform's collision event
Code:
with other
 {
   //Move outside the collision
   y -= vspeed - other.vspeed;
   plat = other.id;

 if (place_meeting(x,y+vspeed,plat))
 {
   while(!place_meeting(x,y+sign(vspeed),plat))
   {
       y += sign(vspeed);
   }
   vspeed = 0;
 }

 if(place_meeting(x+hspeed,y+vspeed,plat))
 {
   while(!place_meeting(x+sign(hspeed),y+sign(vspeed),plat))
   {
       x += sign(hspeed);
       y += sign(vspeed);
   }
   hspeed = 0;
   vspeed = 0;
 }
 }
Player's create event
Code:
plat = noone;
Player's end step event
Code:
if plat
y += bbox_bottom - plat.bbox_top;

Method 2)
Player's end step event
Code:
with instance_place(x,y, platform_parent)
    other.y += other.bbox_bottom - bbox_top;

The second method is easier for you to implement, but it's slower for the computer to process since it is executing an extra proximity check every step.

The formula A.y+=A.bbox_bottom-B.bbox_top is a quick and dirty way to snap object A to the top of object B. If you still have a pixel overlap, change the formula to A.y+=A.bbox_bottom-B.bbox_top-1
Your method(the second one) only works for small speeds of vertical platforms. But what if platform moves at speed equal to "vspeed = 3" or "vspeed = 5" or even higher? How can your method be tweaked in a way the Protagonist always has stable footing(by not rapidly landing on a platform) at any vertical speed?

Oh, and if Instance Creation Codes of individual platforms will be of any indication, here are some:
Code:
image_speed = 0.05
vspeed = 2
Code:
image_speed = 0.05
vspeed = 5
The platforms are set in motion differently, however, through this code in Step event:
Code:
vel_increment = image_speed
gravity_direction += vel_increment

if hspeed != 0
{
event_perform(ev_other,ev_user0)
velocity = hspeed
hspeed = 0
}
if vspeed != 0
{
event_perform(ev_other,ev_user1)
platform_speed = vspeed
velocity = vspeed
vspeed = 0
}
if horizontal = 1
x += cos(gravity_direction) * velocity
if vertical = 1
y += sin(gravity_direction) * velocity


//This code defines if it's Horizontal moving platform, or Vertical one.
//Speed is set via CTRL+RMB on a platform and choosing "Creation Code".
If anything, I expected Protagonist to be glued firm to platform, but your methods don't seem to suggest that.
 

TheouAegis

Member
Oh yeah that only worked for upward movement. My bad. I was trying to take a shortcut to make it faster, but in the process ended up neglecting one direction of movement.

So then Implement method 1. The one thing I forgot to mention about method 1 is when you jump you set the platform back to noone and when you walk off of the platform reset it back to noone. But as long as you have the platform ID stored, it doesn't matter how fast the platform is moving up or down, the player will always be attached to it.

The other benefit of method one is it works for horizontal platforms as well.

x += plat.hspeed;
 

Build Man

Member
Oh yeah that only worked for upward movement. My bad. I was trying to take a shortcut to make it faster, but in the process ended up neglecting one direction of movement.

So then Implement method 1. The one thing I forgot to mention about method 1 is when you jump you set the platform back to noone and when you walk off of the platform reset it back to noone. But as long as you have the platform ID stored, it doesn't matter how fast the platform is moving up or down, the player will always be attached to it.

The other benefit of method one is it works for horizontal platforms as well.

x += plat.hspeed;
The thing is, I stopped using your method 1 first time, because it went VERY buggy.
And it still is.

http://www.mediafire.com/file/xdyuusiz6r8mqak/Movies.rar

(This contains 2 video in .avi format captured by fraps, so you must be able to watch them.)
 

Build Man

Member
Subject TheouAegis, you either think about a workaround plan, or I can always hear the suggestions from another subjects around here. If anyone here has better idea on how to implement vertical platform, I will be glad to hear.
 

TheouAegis

Member
Your videos were "encoded in an unsupported format". ... Curious what encoding you used. I haven't installed any codecs on this computer, so it could be a common codec. If you recorded in uncompressed AVI, I think that could be the issue.

I'll have to work it out tomorrow afternoon after work. It's almost bedtime now because they gave me a crappy schedule this week (close today, open tomorrow).

I'm going to kind of 'start over' and neglect most of your existent code.I am pretty sure GM runs the Collision Events between Begin Step and normal Step events, so that means you should be able to just have in the collision event (assuming you keep the mask_index=-1 when the player is below the platform):

Code:
//Player's Collision Event with Platform
myPlat = other.id;
There's no collision event in the platform. The platform's only code should just be its create event and step event. Just the stuff you need to move it.

In the protagonist's Create Event have:

Code:
myPlat = noone;
In the protagonist's End Step event have

Code:
with myPlat 
{
    other.y += other.bbox_bottom - bbox_top;
    var h; h = hspeed;
    with other
    {
        while place_meeting(x+h, y-1, platform_parent)
            h -= sign(h);
        x += h;
    }
}
Now, this is probably going to make it be a 1 pixel overlap, but pfft that happened in a lot of old Nintendo games anyway. It provides some modicum of depth, I always felt. So for vertical platforms, it just snaps the protagonist's bbox_bottom to the platform's bbox_top. For horizontal platforms, it adds the platform's hspeed to the protagonist's x as long as there's no collision in the way.

When you make your protagonist jump, set myPlat=noone; same with when the protagonist walks off the platform (however you want to do that).

I made it as clean as I could. Again, the platform should only have code concerned with its own movement, not that of the player or any collision info.
 

Build Man

Member
I recently tried this another solution, and pretty much done with attempts. Every your attempt at solving my problem turns out wrong in one way or another, and there is little I can do to properly explain what really is wrong.

So I decided I hand out one of my Experimental Versions of my platformer.

http://www.mediafire.com/file/d8pq42za4168b6q/Legend+of+Mako+Experimental+3.gmk

This one has, more or less, stable platform footing.

If you have Game Maker 8, you can try and solve this trouble yourself. If not, just send Private Message, and I will hand you Game Maker 8. I decided not to bother you with this. Here's Game Maker 8 - http://www.mediafire.com/file/bca92fzq4nfh5m0/Game_Maker8.rar - I hope I missed no core data folder.
 
Last edited:

TheouAegis

Member
First off, i wrote this backwards:

other.y += other.bbox_bottom - bbox_top;

It should be:

other.y -= other.bbox_bottom - bbox_top;



Edit: now I'm reminded why I dislike Sean's tutorials. by messing with the mask index, collision detection is thrown off drastically.
 
Last edited:

TheouAegis

Member
Ok, possibly good news (depending on the extent to which you'll work with it).

Platform's Step Event:
Code:
if Protagonist.bbox_bottom < y+1
    mask_index = -1;
else
    mask_index = empty;
The important part is I added 1 to the buffer before you disable the mask for the platform. This isn't an arbitrary value -- it's based on the speed of the platform in my test file. My platform moved up/down at 1 pixel per step.

Player's Step Event:
Code:
if !place_meeting(x,y+vspeed+1,platform_parent)
{
    myPlat = noone;
}

if JUMP_KEY
{
    myPlat = noone;
}

Now you don't have to use this code and I advise you not to. The point is the Step Event of the player you check if the Jump Key is pressed and if it is you set myPlat to noone. If there is no platform at vspeed+1, below the protagonist, you set myPlat to noone.

Player's End Step Event:
Code:
with myPlat
{
    other.y -= (other.bbox_bottom) - bbox_top;
}
And here is the algorithm as it was supposed to be written.
 

Build Man

Member
Alright, problem with vertical platforms is somewhat fixed. Now I have another one: The incredible stickiness of platforms. Horizontal Platforms(and also vertical ones when they go up) pretty much prevent all inertia(as opposed to solid ground where Protagonist slides a little) and significantly slow down Protagonist's movement. While they do carry Protagonist along the path, them restraining Protagonist's own movements is quite a problem.
 

TheouAegis

Member
I'm not sure why you're getting even more inertial dampening, but did you remember to alter your protagonist's friction since previously it was based on if he was on a solid but we changed the floating platforms to not be solid anymore.
 

Build Man

Member
I'm not sure why you're getting even more inertial dampening, but did you remember to alter your protagonist's friction since previously it was based on if he was on a solid but we changed the floating platforms to not be solid anymore.
The thing is, when Protagonist is on solid ground, the friction is 0.6, but while airborne, it becomes 0, and instead, this code kicks in:
Code:
if sprite_index != Mako_Damaged
 {
 if !keyboard_check(vk_left) && !keyboard_check(vk_right)
  {
  if hspeed != 0
  hspeed -= hspeed*0.1
  }
 }
It's some kind of horizontal friction for air.

Now that platforms are not solid, the latter method of friction should be working, and not the former. But for some reason, the friction is incredibly high for platforms. I do not why, but I suspect it is something to do with platforms.

Anyways, here: http://www.mediafire.com/file/d8pq42za4168b6q/Legend_of_Mako_Experimental_3.gmk (I just replaced the file with latest changes). You are free to try tinkering with it.
 

Build Man

Member
Any luck figuring out the friction? I want to get done with platforms already. They are the only thing that stands between me and finishing the preparations for demo.
 

TheouAegis

Member
I tried looking at it in Studio but it had too many obsolete functions are something, so I'll have to wait until I can get on my laptop still. Sorry.
 

TheouAegis

Member
The next topic of the thread is Horizontal Platforms(and Vertical ones when they go upward) having way more friction than they should, severely slowing Protagonist down. It is not in a separate thread because this problem followed immediately afterwards.
okay I will start this off by telling you not to be offended by anything I say from this point on. anything that might be construed as a harsh criticism is not directed towards you probably.

first off, you need to change your resource names. Nearly every single resource has a naming conflict. This is not something you can shrug off even in gm8. your Sprites have the same names as objects. This can and will cause issues down the road, if not already. yiu should name them such that you can tell what is a sprite and what is an object and what is a script, and so forth.

second, The mask_index altering method of jump-through platforms is crap. it is just as horrendous as the solid attribute toggling method. it was one of my biggest complaints about Shaun Spalding's tutorial. both methods are procentric, meaning they are only concerned with the player's character. Games need to be focused on everything around the player, not just the player. Procentric coding restricts core game mechanics to the player's character only and prevent NPCs from properly interacting with the game environment. Furthermore, anything that can be done with mask_index or solid attribute toggling can be done just as easily and more flexibly without toggling anything.

Still, even if the mask_index method was legit, you were doing it wrong. Setting the mask index to -1 doesn't mean there is no collision mask, it means the collision mask will be based on the sprite assigned to the object. You would need an empty sprite that has no collision mask at all and set the mask_index to that.

The proper method of handling jump-through platforms is to check if the player has positive vertical speed and either is above the platform (preemptive collision) or was previously above (post-collision). The mask-index method is essentially a post-collision check.

I deleted the player's collision event with the platform, but that didn't change anything at first (I left it deleted). Then I rewrote the platform's collision event so it checked if the player was falling first. Then I snapped the player (y-= part), set vspeed to 0, saved the platform's id, and changed the player's sprite. The rest of your collision code was causing the friction.

There's still an issue with the player's sprite I think when the platform moves down while he runs.
 

Build Man

Member
I deleted the player's collision event with the platform, but that didn't change anything at first (I left it deleted).
This code is here so Protagonist can be carried around by horizontal platforms, which you did not account in.
Then I rewrote the platform's collision event so it checked if the player was falling first. Then I snapped the player (y-= part), set vspeed to 0, saved the platform's id, and changed the player's sprite
Here, I want a piece of code for that.
 

TheouAegis

Member
Yeah I figured and you don't even need that code for horizontal platforms in a separate collision event. You could just update horizontal positioning in the End Step when you update vertical positioning.

All I did was remove the "while !place_meeting(..." codes from your collision event, I removed the jumping code from the collision event (that shouldn't be there), and at the very start of the collision event it was

"with other
if vspeed > 0
{
"

Which.... I don't know why that was being required for me, but it freed up some small glitch I was noticing. Then again, you could probably get away without it.
 

Build Man

Member
Yeah I figured and you don't even need that code for horizontal platforms in a separate collision event. You could just update horizontal positioning in the End Step when you update vertical positioning.

All I did was remove the "while !place_meeting(..." codes from your collision event, I removed the jumping code from the collision event (that shouldn't be there), and at the very start of the collision event it was

"with other
if vspeed > 0
{
"

Which.... I don't know why that was being required for me, but it freed up some small glitch I was noticing. Then again, you could probably get away without it.
Still, can you just paste here the whole codes of your solution? I am having a hard time understanding what exactly I need to do.

In this form, please:
Code:
whatever your code is supposed to be
 

Build Man

Member
I still have no idea what exactly you did with platforms. So I ask you again for a full code of your platform at it's current state.

Please send it in this form:
Code:
Whatever your code is supposed to be
 

TheouAegis

Member
@Build Man Your code could use a lot of cleaning up, but I worked with what I could.

First, I set wall_parent to be parented to platform_parent. I added a create event in wall_parent with just a comment containing " " so the platform_parent's create event wouldn't be run in the wall_parent.

Code:
Information about object: wall_parent

Sprite: <no sprite>
Solid: false
Visible: false
Depth: 0
Persistent: false
Parent: platform_parent
Mask: <same as sprite>

Create Event:
COMMENT:   // there's a space here
The platform_parent object only has its create event, nothing else.

The platform_wood_short object only has its create, step, and user events (not sure if I added the collision event originally or if you added it) and is parented to platform_parent. Furthermore, the step event no longer modifies the mask_index -- that entire block of code is gone. The only code in platform_wood_short is thus only that which concerns itself with movement.
Code:
Information about object: platform_wood1_short

Sprite: spr_platform_wood1_short
Solid: false
Visible: true
Depth: 0
Persistent: false
Parent: platform_parent
Mask: <same as sprite>

Create Event:
execute code:

//WARNING
//To change these, use "Generate Code" function on the object you placed in Room.
//Access "Generate Code" by CTRL+RMB on a desired object.

event_inherited();
platform_speed = 0


 Step Event:
execute code:

vel_increment = image_speed
gravity_direction += vel_increment

if hspeed != 0
{
event_perform(ev_other,ev_user0)
velocity = hspeed
hspeed = 0
}
if vspeed != 0
{
event_perform(ev_other,ev_user1)
platform_speed = vspeed
velocity = vspeed
vspeed = 0
}
if horizontal = 1
x += cos(gravity_direction) * velocity
if vertical = 1
y += sin(gravity_direction) * velocity


//This code defines if it's Horizontal moving platform, or Vertical one.
//Speed is set via CTRL+RMB on a platform and choosing "Creation Code".


Other Event: User Defined 0:
execute code:

horizontal = 1


Other Event: User Defined 1:
execute code:

vertical = 1
Now, the Protagonist needed a few changes. I kept most of your code intact, though.

First, I set friction to 0.6 and gravity to 1 in the create event. This was because I removed them being set to 0.6 from the step event.

The step event now looks like this:
Code:
if at relative position (0,1) there is object platform_parent
      execute code:

if action = 0 && sprite_index != Mako_Weapon
 {
 if speed = 0
 sprite_index = Mako
 }
if health <= 0 && vspeed = 0
 {
 instance_create(x,y,KnockedOut_Mako)
 move_snap(x,640)
 speed = 0
 sprite_index = Mako_Damaged
 }

else
      if plat is equal to noone
      set the friction to 0
      execute code:

if action = 0
 {
 if sprite_index != Mako_Damaged && sprite_index != Mako_Weapon
  {
  if vspeed < 0
  sprite_index = Mako_Jump
  if vspeed > 0
  sprite_index = Mako_Fall
  }
 if sprite_index = Mako_Damaged && vspeed >= 7 && health > 0
 sprite_index = Mako_Fall
 }

      execute code:

if sprite_index != Mako_Damaged
 {
 if !keyboard_check(vk_left) && !keyboard_check(vk_right)
  {
  if hspeed != 0
  hspeed -= hspeed*0.1
  }
 }

execute code:

if health > 100
health = 100

if mercy = 1 && health > 0 && !instance_exists(MercyShield)
instance_create(x,y,MercyShield)

execute code:

if y>512
 {
 if !instance_exists(KnockedOut_Mako)
  {
  instance_create(x,y+32,KnockedOut_Mako)
  health = 0
  sprite_index = Mako_Damaged
  hspeed = 0
  }
 }

execute code:

if charge_level = 1
 {
 if alarm[11] < 1
 alarm[11] = 3
 }
if charge_level = 2
instance_create(random_range(x-8,x+8),random_range(y-15,y+15),Magic_Charge)

if !keyboard_check(ord('X')) && charge_level > 0
event_perform(ev_keyrelease,ord('X'))
The most important changes are I removed friction=0.6 and gravity=0 from the first conditional block; the first conditional is now based on a collision with platform_parent since I removed the solid attribute from your platforms; and the "else" block was modified to check if plat==noone.

The end step now handles both types of platforms -- horizontal and vertical. It also detects when the player falls off the platform.
Code:
with plat
{
    other.y -= (other.bbox_bottom) - bbox_top;
    other.x += x - xprevious;
    if !place_meeting(x,y-1,other.id)
        other.plat = noone;
}
The up key event sets plat to noone (the end step doesn't suffice because it is handled too late). It also has been changed to check for collisions with platform_parent, not solids.
Code:
if at relative position (0,1) there is object platform_parent
      set the vertical speed to -18
      set variable plat to noone
The collision event with wall_parent was changed by adding friction to the end of it.
Code:
//Horizontal Collision
if (place_meeting(x+hspeed,y,wall_parent))
{
    while(!place_meeting(x+sign(hspeed),y,wall_parent))
    {
        x += sign(hspeed);
    }
    hspeed = 0;
}

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

//Diagonal Collision
if(place_meeting(x+hspeed,y+vspeed,wall_parent))
{
    while(!place_meeting(x+sign(hspeed),y+sign(vspeed),wall_parent))
    {
        x += sign(hspeed);
        y += sign(vspeed);
    }
    hspeed = 0;
    vspeed = 0;
}

friction = 0.6;
The collision event with platform_parent is pretty simple but has a few significant changes.
Code:
if vspeed > 0
if bbox_bottom-(y-yprevious) < other.bbox_top-(other.y-other.yprevious)
 {
    y -= (bbox_bottom)-other.bbox_top;
    vspeed = 0;
    plat = other.id;
    friction = 0.6;
 }
As you can see, the vspeed>0 condition was added. Second, a check was put in place to make sure the protagonist was above the platform in the previous step. It's a bit more complex than desired because your platform doesn't move with vspeed, so the difference traveled had to be calculated. Friction is also set here.

If you didn't notice, gravity is never set to 0 anywhere. Gravity is always present, so it need not be set more than once.
 

Build Man

Member
The platform_wood_short object only has its create, step, and user events (not sure if I added the collision event originally or if you added it)
Sorry, I could not locate any collision events in platform_wood1 objects, but there was collision event with Protagonist in platform_parent. However, you said that:
The platform_parent object only has its create event, nothing else.
So I assumed you deleted it. So I followed your actions and deleted it also. Send collision event of platform_wood1 when you are able to.
 

TheouAegis

Member
No collision event. It must have been code i put in when i first opened the project. That big code block is the entire code for platform_wood1. Like I said, all i did for it ultimately was delete the code that sets madk_index if the player is above or below.
 

Build Man

Member
I tried your pieces of code, and they are working great! Big thanks for a great helping hand on resolving the platform issue.

While trying out these new and improved platforms, I have also created their wrapping version - platforms that only move one way vertically at a fixed speed, wrapping around the screen. They are pretty much identical to those regular platforms, except "gravity_direction += vel_increment" line was removed from Step Event code, and additional Outside Room Event was added, which contains a piece of code consisting of "move_wrap(false,true,0). These platforms work very well... Except they are wrapping with Protagonist still on board, rather than him, well, "disfooting" when platform wraps.
 

TheouAegis

Member
You will need to disfoot the protagonist in the End Step code. Move the protagonist; if there's an illegal collision or if it moves him out of the screen, move him back. to his previous spot. Not 100% sure but in most cases that should cause him to be defooted on the next step.
 

Build Man

Member
You will need to disfoot the protagonist in the End Step code. Move the protagonist; if there's an illegal collision or if it moves him out of the screen, move him back. to his previous spot. Not 100% sure but in most cases that should cause him to be defooted on the next step.
Thank you, subject TheouAegis! Great advice as usual! Now, I can proceed and start finally working on actual for my project!
 
Top