platform | putting it all together so far | gml
refining what we have done in the previous tutorials, this brings together all the elements into one game level. Please note the following important notes:
- Only the objPlayer code is shown. Nothing has changed from any other objects that was completed previously.
- To make life easier when re-defining key inputs, variables were created to store the keys for the game in the player create event. This way re-defining keys is easy in the future - it can all be done 'in this one place'.
- This time i have used mostly centred origins. This may help with appearance, flipping sprites and using external sprite animations (in following activities).
| Sprite | Specifics |
|---|---|
| sprBlock | 64x64px, Origin: Middle Centre (32,32). |
| sprPlayer | 64x64px, Origin: Middle Centre (32,32). |
| sprRope | 200(W)x20(H)px, Origin: Middle Left (0,10). |
| sprLadder | 64x64px, Origin: Middle Centre (32,32). |
| sprProjectile | 200(W)x20(H)px, Origin: Middle Left (0,10). |
| sprPortalA / sprPortalB | 20(W)x64(H)px, Origin: Middle Centre (10,32). |
All objects default properties: Visible, but not Solid. Moving platforms (all directions) have objBlock set as parent object, and use the same sprBlock sprite.
objPlayer Create
grav = 1;
horiz = 0;
vert = 0;
move_speed = 7;
jump_speed = -15;
frict = 0.9;
//make life easier to re-define keys:
key_for_up = ord("W")
key_for_left = ord("A")
key_for_down = ord("S")
key_for_right = ord("D")
key_for_projectile = mb_any;
//new variables for adding ladders:
on_ladder = false;
ladder_climb_speed = move_speed div 2;
//new variables for adding ropes:
on_rope = false;
attach_timer = room_speed div 4; //quarter of a second to hold on
let_go_timer = 0;
//new variables for portals:
teleported = false;
portal_deactivate_timer = room_speed div 2; //half sec
objPlayer Step
// all regular movement applies when i'm not on a rope
// AND not on a ladder:
if not(on_rope) and not(on_ladder) {
// left and right movement inputs:
if (keyboard_check(key_for_right)){ horiz = move_speed; };
if (keyboard_check(key_for_left)){ horiz = -move_speed; };
if (keyboard_check(vk_nokey)){ horiz = horiz * frict; }; //friction
// 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(key_for_up))
{ vert = jump_speed; }
// 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
}
x = x + horiz; // affect calculated horizontal changes by APPLYING to x co-ord
// 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);
}
vert = 0; // no up down movement on VERTICAL collisions
}
y = y + vert; // affect calculated vertical changes by APPLYING to x co-ord
}
//---------------------------- CLIMB LADDERS:
// if i am on a ladder:
if place_meeting(x,y,objLadder) and not
// ... and im not going to go through the ground
// that the ladder has been placed on top of:
place_meeting(x,bbox_bottom+1,objBlock)
{
on_ladder = true;
vert = 0;
horiz = 0;
if keyboard_check(key_for_up) y -= ladder_climb_speed;
if keyboard_check(key_for_down) y += ladder_climb_speed;
if keyboard_check(key_for_left) x -= ladder_climb_speed;
if keyboard_check(key_for_right) x += ladder_climb_speed;
}
else {
on_ladder = false;
}
//---------------------------- SWING ON ROPES:
if let_go_timer > 0 let_go_timer -= 1;
var rope = instance_place(x,y,objRope);
if (rope != noone and let_go_timer < 1)
{
attach_timer -= 1;
if attach_timer < 1 attach_timer = 0;
on_rope = true;
/*------------------------------------------------------------------------
If objPlayer sprite origins were Top Left then use the following:
------------------------------------------------------------------------*/
// x = rope.x+lengthdir_x(rope.sprite_width,rope.direction) - sprite_width/2;
// y = rope.bbox_bottom-sprite_height/2;
/*--------------------------------------------------------------------
Because my objPlayer sprite origins are Middle Centre i am using the following:
--------------------------------------------------------------------*/
x = rope.x+lengthdir_x(rope.sprite_width,rope.direction);
y = rope.bbox_bottom;
if attach_timer < 1 {
//getting off rope:
if keyboard_check(key_for_up) {
let_go_timer = room_speed div 2; //half a sec to get off rope
vert = jump_speed;
}
if keyboard_check(key_for_left) {
let_go_timer = room_speed div 2;
horiz = -(move_speed);
}
if keyboard_check(key_for_right) {
let_go_timer = room_speed div 2;
horiz = move_speed;
}
}
}
else
{ on_rope = false; attach_timer = room_speed div 4; }
//---------------------------- PROECTILES:
if mouse_check_button(key_for_projectile){
var inst = instance_create_layer(x,y,"Instances",objProjectile);
with(inst){
inst.direction = point_direction(x,y,mouse_x,mouse_y);
inst.image_angle = direction;
inst.speed = 10;
}
}
//---------------------------- PORTALS:
if place_meeting(x, y, objPortalA) and !(teleported) {
teleported = true;
y = objPortalB.y;
x = objPortalB.x + (x-xprevious);
}
if place_meeting(x, y, objPortalB) and !(teleported) {
teleported = true;
y = objPortalA.y;
x = objPortalA.x + (x-xprevious);
}
if (teleported) portal_deactivate_timer -= 1;
if (portal_deactivate_timer < 1){
teleported = false;
portal_deactivate_timer = room_speed div 2; //half sec
}
test game so far here in the Games link above