External Exam Download Resources Web Applications Games Recycle Bin

GML - Collision Correction




SpriteImages
sprStill

centre every player sprite you import shown below:

sprWalk
or as a zip (remember to keep centering all player sprites):
walk.zip
sprJumpUp
sprLanding
sprBlock
ObjectSpriteProperties
objPlayersprStillVisible
objBlocksprBlockVisible

Use the same room layout from the previous examples.. CHANGE BACKGROUND COLOUR TO WHITE (not explicitly shown in following image):



grav = 1; //our gravity
horiz = 0; //our desired horizontal speed
vert = 0; //our desired vertical speed
move_speed = 5;
jump_speed = -12;
frict = 0.95;
facing = 1; //start facing right
jumped = false; //controls jump animations
status = ""; //status of platform "stick"
// left and right movement inputs AND animations:

if (keyboard_check(vk_right)){ horiz = move_speed; facing = 1; };
if (keyboard_check(vk_left)){ horiz = -move_speed; facing = -1; };
if (horiz != 0 and not jumped)
  { sprite_index = sprWalk; }
if (keyboard_check(vk_nokey)){
	horiz = horiz * frict; //friction
	if (abs(horiz) < 1 and abs(vert) < 1) { sprite_index = sprStill };
}; 

// add constant force of gravity to our desired vert speed:

vert = vert + grav;

// only ALLOW jump IF the objBlock is 1 pixel BELOW the player,
// or in other words, if the player is EXACTLY standing on floor:

if (place_meeting(x, y+1, objBlock) and keyboard_check(vk_up))
  { vert = jump_speed; jumped = true; } 
  
// jump animations:

if (jumped) {
	// up down animations:
	if (vert > 0) { sprite_index = sprJumpUp; } 
    else { sprite_index = sprLanding; }
	// reset jump IF on ground again:
	if (place_meeting(x, y+1, objBlock)) { jumped = false; }
}

// check for a HORIZONTAL collision:

if (place_meeting(x+horiz, y, objBlock))
{
    // move AS CLOSE AS WE CAN to the HORIZONTAL collision object:
	// sign() can only return 1, -1, or 0.
	// sign(-7) == -1 (i.e. negative 1)
	// sign(7) == 1 (or +1 or positive 1)
	// sign(0) == 0
	
    while (!place_meeting(x+sign(horiz), y, objBlock))
    {
        x = x + sign(horiz); // move 1 pixel at a time towards object
    }
	
    horiz = 0; // no left right movement on HORIZONTAL collisions 
}

// we have worked out our horizontal speed, now APPLY the change:

x = x + horiz;

// check for a VERTICAL collision:

if (place_meeting(x, y+vert, objBlock))
{
    // move AS CLOSE AS WE CAN to the VERTICAL collision object:
	
    while (!place_meeting(x, y+sign(vert), objBlock))
    {
		// remember, sign() can only return 1, -1, or 0:
        y = y + sign(vert); // // move 1 pixel at a time towards object
    }
	
    vert = 0; // no up down movement on VERTICAL collisions 
}

// we have worked out our vertical speed, now APPLY the change:

y = y + vert;
// draw the image of the sprite to the screen:

draw_sprite_ext(
  sprite_index,
  image_index,
  x,
  y,
  facing, //instead of image_xscale
  image_yscale,
  image_angle,
  image_blend,
  image_alpha
);

// draw the status of platform stick to the screen:

draw_set_colour(c_black);
draw_text(x-(sprite_width/2), y-(sprite_height/2)-10, status)
// CHECK for a collision in our current location:
var colliding_object_id = instance_place(x, y, objBlock);

if (colliding_object_id != noone) { // IF we are stuck!	
	status = "stuck"
	
	// stuck below:
	while collision_point(x, bbox_bottom, objBlock, false, true)
	  { status = "stuck below"; y = y - 1; }

	// stuck above:
	while collision_point(x, bbox_top, objBlock, false, true)
	  { status = "stuck above"; y = y + 1; }
	
	// stuck on right:
	while collision_point(bbox_right, y, objBlock, false, true)
	   { status = "stuck right"; x = x - 1; }
	
	// stuck on left:
	while collision_point(bbox_left, y, objBlock, false, true)
	   { status = "stuck left"; x = x + 1; }
	
	// still stuck - maybe on a corner trying to unstick two ways?
	if (x == xprevious and y == yprevious){
	   { 
		  status = "still stuck";
		  
		  // this isn't great but will work for now. it functions like
		  // a CATCH ALL - meaning it will work out the direction of
		  // collision, and force the in-built SPEED of the object to 
		  // head backwards from the point of collision. There is potential
		  // for this to cause negative side effects later on:
		  
		  move_towards_point(colliding_object_id.x, colliding_object_id.y, -1);
	   }
	}
	
} else { status = "free"; speed = 0; } //if we applied speed above, remove it

really tough, and professionals take a long time to get this 'right' (translated: good enough). there are so many factors at play, including dimensions of collision masks, and whether or not they "match". when sprites animate, their masks can change size and shape.. consistency is key.