├── README.md ├── apply_friction.gml ├── camera_default.gml ├── collision.gml ├── get_input.gml ├── jump.gml ├── ledge_grab_check.gml ├── move.gml ├── player_ledge_climb_state.gml ├── player_ledge_grab_state.gml ├── player_move_state.gml ├── player_roll_state.gml ├── player_wall_jump_state.gml ├── player_wall_slide.gml └── wall_slide_check.gml /README.md: -------------------------------------------------------------------------------- 1 | # GameMakerPlatformingScripts 2 | Basic platforming scripts that can be used for a basic platforming engine in Game Maker Studio 1 and Game Maker Studio 2. These were created and inspired through the Heartbest youtube tutorial series. 3 | -------------------------------------------------------------------------------- /apply_friction.gml: -------------------------------------------------------------------------------- 1 | ///apply_friction(amount) 2 | // gradually slow player when they are not inputing a movement 3 | // input and are on the ground until they come to a stop 4 | 5 | var amount = argument[0]; 6 | 7 | //check to make sure that we are moving 8 | if (hspd != 0) 9 | { 10 | //make sure that we are moving a substantial amount to even add the friction to 11 | if ((abs(hspd) - amount) > 0) 12 | { 13 | //apply the friction 14 | hspd -= amount * image_xscale; 15 | } 16 | //if our movement is too small, set hspd to 0 17 | else 18 | { 19 | hspd = 0; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /camera_default.gml: -------------------------------------------------------------------------------- 1 | ///camera_default(); 2 | // call this function inside of the Camera object state update. 3 | // gradually move camera to follow the player instead 4 | // of immediately snapping to them to give a more natural feel. 5 | 6 | if (instance_exists(obj_player)) 7 | { 8 | x += (obj_player.x - x) * 0.05; 9 | y += (obj_player.y - y) * 0.05; 10 | } 11 | -------------------------------------------------------------------------------- /collision.gml: -------------------------------------------------------------------------------- 1 | ///collision(obj1, obj2, dir) 2 | 3 | //check collisions using place_meeting 4 | var obj1 = argument[0]; 5 | var obj2 = argument[1]; 6 | var dir = argument[2]; 7 | 8 | //we want to check collisoins with the place_meeting function, 9 | //this can only be called on itself and not on another object, 10 | //so we do all of this in relation to one of our two objects. 11 | with (obj1) 12 | { 13 | //check directions 14 | switch (dir) 15 | { 16 | //check to the right 17 | case RIGHT: 18 | if (place_meeting(x + 1, y, obj2)) 19 | { 20 | return true; 21 | } 22 | break; 23 | 24 | //check above 25 | case UP: 26 | if (place_meeting(x, y - 1, obj2)) 27 | { 28 | return true; 29 | } 30 | break; 31 | 32 | //check to the left 33 | case LEFT: 34 | if (place_meeting(x - 1, y, obj2)) 35 | { 36 | return true; 37 | } 38 | break; 39 | 40 | //check down 41 | case DOWN: 42 | if (place_meeting(x, y + 1, obj2)) 43 | { 44 | return true; 45 | } 46 | break; 47 | //check center 48 | case CENTER: 49 | if (place_meeting(x, y, obj2)) 50 | { 51 | return true; 52 | } 53 | break; 54 | default: 55 | return false; 56 | } 57 | } 58 | 59 | //if we reach this point of the code, then none of the 60 | //above code was true, so we return false 61 | return false; 62 | -------------------------------------------------------------------------------- /get_input.gml: -------------------------------------------------------------------------------- 1 | ///get_input 2 | 3 | //------------------------------------------------------------------- 4 | //keyboard----------------------------------------------------------- 5 | //------------------------------------------------------------------- 6 | 7 | //right 8 | right = keyboard_check(ord('D')); 9 | right_pressed = keyboard_check_pressed(ord('D')); 10 | right_released = keyboard_check_released(ord('D')); 11 | 12 | //left 13 | left = keyboard_check(ord('A')); 14 | left_pressed = keyboard_check_pressed(ord('A')); 15 | left_released = keyboard_check_released(ord('A')); 16 | 17 | //up 18 | up = keyboard_check(ord('W')); 19 | up_pressed = keyboard_check_pressed(ord('W')); 20 | up_released = keyboard_check_released(ord('W')); 21 | 22 | //down 23 | down = keyboard_check(ord('S')); 24 | down_pressed = keyboard_check_pressed(ord('S')); 25 | down_released = keyboard_check_released(ord('S')); 26 | 27 | //other inputs 28 | j = keyboard_check(ord('J')); 29 | j_pressed = keyboard_check_pressed(ord('J')); 30 | j_released = keyboard_check_released(ord('J')); 31 | k = keyboard_check(ord('K')); 32 | k_pressed = keyboard_check_pressed(ord('K')); 33 | k_released = keyboard_check_released(ord('K')); 34 | l = keyboard_check(ord('L')); 35 | l_pressed = keyboard_check_pressed(ord('L')); 36 | l_released = keyboard_check_released(ord('L')); 37 | space = keyboard_check(vk_space); 38 | space_pressed = keyboard_check_pressed(vk_space); 39 | space_released = keyboard_check_released(vk_space); 40 | 41 | nokey = keyboard_check(vk_nokey); 42 | 43 | //------------------------------------------------------------------- 44 | //gamepad------------------------------------------------------------ 45 | //------------------------------------------------------------------- 46 | 47 | //override controls for a gamepad 48 | var gp_id = 0; 49 | var thresh = .5; 50 | 51 | //still needs configuring once i get a gamepad... 52 | if (gamepad_is_connected(gp_id)) 53 | { 54 | right = gamepad_axis_value(gp_id, gp_axislh) > thresh; 55 | left = gamepad_axis_value(gp_id, gp_axislh) < -thresh; 56 | up = gamepad_button_check_pressed(gp_id, gp_face1); 57 | up_release = gamepad_button_check_released(gp_id, gp_face1); 58 | down = gamepad_axis_value(gp_id, gp_axislv) > thresh; 59 | } 60 | -------------------------------------------------------------------------------- /jump.gml: -------------------------------------------------------------------------------- 1 | ///jump(condition) 2 | // create different attributes for jumping such as normal jumps 3 | // wall jumps and other special jumps 4 | 5 | //condition: normal jump, wall jump, etc... 6 | cond = argument[0]; 7 | 8 | //normal jump 9 | if (cond == "norm") 10 | { 11 | //jumping sprite 12 | sprite_index = spr_player_jump; 13 | image_speed = 0; 14 | 15 | //control the jump height 16 | if (up_released && vspd < -2) 17 | { 18 | vspd = -2; 19 | } 20 | } 21 | 22 | //wall jump 23 | if (cond == "wall") 24 | { 25 | //jumping sprite 26 | sprite_index = spr_player_wall_jump; 27 | image_speed = 0; 28 | 29 | //control the jump height 30 | if (up_released && vspd < -2) 31 | { 32 | vspd = -2; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ledge_grab_check.gml: -------------------------------------------------------------------------------- 1 | ///ledge_grab_check() 2 | // check for platform edge while falling to determine if we 3 | // should snap to the edge 4 | 5 | //check that we are falling 6 | var falling = y > yprevious; 7 | //check that there wasnt a wall where we were 8 | var wasnt_wall = !position_meeting(x + 17 * image_xscale, yprevious - 16, obj_solid); 9 | //and that there is a wall where we are 10 | var is_wall = position_meeting(x + 17 * image_xscale, y, obj_solid); 11 | 12 | //ledge grab 13 | if (falling && wasnt_wall && is_wall && up && !collision(id, obj_water, CENTER)) 14 | { 15 | //reset hspd and vspd to prevent weird speed issues 16 | hspd = 0; 17 | vspd = 0; 18 | 19 | //move against the ledge so that there is no awkward space 20 | while (!place_meeting(x + image_xscale, y, obj_solid)) 21 | { 22 | //again, this is either 1 or -1 23 | x += image_xscale; 24 | } 25 | 26 | //make sure we are the right height so that our ledge grab doesnt look awkward 27 | while (position_meeting(x + 17 * image_xscale, y - 1, obj_solid)) 28 | { 29 | y -= 1; 30 | } 31 | 32 | //now switch to ledge grab state 33 | state = player_ledge_grab_state; 34 | } 35 | -------------------------------------------------------------------------------- /move.gml: -------------------------------------------------------------------------------- 1 | ///move(collision_object) 2 | 3 | //set the object that we are going to collide with/checking for collisions with 4 | var collision_object = argument0; 5 | 6 | //horizontal collisions 7 | if (place_meeting(x + hspd, y, collision_object)) 8 | { 9 | while (!place_meeting(x + sign(hspd), y, collision_object)) 10 | { 11 | x += sign(hspd); 12 | } 13 | hspd = 0; 14 | } 15 | x += hspd; 16 | 17 | //vertical collisions 18 | if (place_meeting(x, y + vspd, collision_object)) 19 | { 20 | while (!place_meeting(x, y + sign(vspd), collision_object)) 21 | { 22 | y += sign(vspd); 23 | } 24 | vspd = 0; 25 | } 26 | y += vspd; 27 | -------------------------------------------------------------------------------- /player_ledge_climb_state.gml: -------------------------------------------------------------------------------- 1 | ///player_ledge_climb_state() 2 | // after player has snapped to the edge, trigger the 3 | // appropriate animation sequence and then move the player 4 | // up onto the platfrom. The rest of this code is executed 5 | // in the Animation End trigger. 6 | 7 | //set sprite 8 | sprite_index = spr_pboy_ledge_climb; 9 | image_speed = 0.2; 10 | 11 | //wait until end of animation to set to move state 12 | -------------------------------------------------------------------------------- /player_ledge_grab_state.gml: -------------------------------------------------------------------------------- 1 | ///player_ledge_grab_state() 2 | // what to do once the player has snapped to 3 | // the edge of a platform 4 | 5 | //ledge grab sprite 6 | sprite_index = spr_pboy_ledge_grab; 7 | image_speed = 0.05; 8 | 9 | //let go of ledge 10 | if (down_released) 11 | { 12 | //slide down 13 | state = player_wall_slide; 14 | } 15 | 16 | //climb up ledge 17 | if ((right_released && image_xscale == 1) || (left_released && image_xscale == -1) || up_released) 18 | { 19 | if (!k) 20 | { 21 | state = player_ledge_climb_state; 22 | } 23 | else 24 | { 25 | state = player_wall_slide; 26 | } 27 | } 28 | 29 | //hang low from ledge 30 | if (k) 31 | { 32 | sprite_index = spr_pboy_ledge_grab_low; 33 | image_speed = 0; 34 | } 35 | -------------------------------------------------------------------------------- /player_move_state.gml: -------------------------------------------------------------------------------- 1 | ///player_move_state() 2 | // general player movement state. this is the default state 3 | // that the player is in until switched 4 | 5 | //change player mask 6 | mask_index = asset_get_index(string(character) + "_idle"); 7 | 8 | // asset_get_index(string(character) + "xxx"); 9 | // this line of code gets the character's name and looks for the sprite image 10 | // with the same name. This makes for easier sprite management and less hard 11 | // coding of each character that the player might transform into throughout the process 12 | // of the game. this can, and should, be applied to all other segments of code as well. 13 | 14 | //set spd 15 | var spd = walk_spd; 16 | 17 | //if the player is in the air 18 | if (!collision(id, obj_solid, DOWN)) 19 | { 20 | //apply gravity 21 | vspd += grav; 22 | 23 | //falling sprite 24 | if (vspd > 6 && !place_meeting(x, y + 8, obj_water)) 25 | { 26 | sprite_index = asset_get_index(string(character) + "_fall"); 27 | image_speed = 0.2; 28 | } 29 | 30 | //jumping sprite 31 | if (!place_meeting(x, y + 8, obj_water)) 32 | { 33 | sprite_index = asset_get_index(string(character) + "_jump"); 34 | image_speed = 0; 35 | } 36 | 37 | //control the jump height 38 | if (up_released && vspd < -2) 39 | { 40 | vspd = -2; 41 | } 42 | } 43 | //if the player is touchign the ground 44 | else 45 | { 46 | //set the vspd to 0 47 | vspd = 0; 48 | 49 | //jump! 50 | if (up_pressed) 51 | { 52 | vspd = -8; 53 | } 54 | 55 | //if player is sitting still 56 | if (hspd == 0) 57 | { 58 | //check for crouching 59 | if (down) 60 | { 61 | //crouch idle 62 | sprite_index = asset_get_index(string(character) + "_crouch_idle"); 63 | image_speed = 0.075; 64 | } 65 | else 66 | { 67 | //normal idle 68 | sprite_index = asset_get_index(string(character) + "_idle"); 69 | image_speed = 0.1; 70 | } 71 | } 72 | //player is moving left or right 73 | else 74 | { 75 | //check for crouching 76 | if (down) 77 | { 78 | //crouch walking 79 | sprite_index = asset_get_index(string(character) + "_crouch_walk"); 80 | image_speed = 0.1; 81 | spd = walk_spd / 4; 82 | } 83 | else 84 | { 85 | //normal walking 86 | sprite_index = asset_get_index(string(obj_player.character) + "_run"); 87 | image_speed = 0.2; 88 | spd = walk_spd; 89 | } 90 | } 91 | } 92 | 93 | //moving left or right 94 | if (right || left) 95 | { 96 | //right and left return 1 or 0, so this gets direction and moves it 97 | //we also apply the acc variable to it, so that we gain speed gradually 98 | hspd += (right - left) * acc; 99 | 100 | //get the direction of our horizontal movement 101 | hspd_dir = right - left; 102 | 103 | //put an upper limit on our hspd 104 | //runnning speed 105 | if (j && !down && hspd != 0) 106 | { 107 | image_speed = 0.3; 108 | spd = run_spd; 109 | } 110 | //walking speed 111 | else if(!j && !down && hspd != 0) 112 | { 113 | image_speed = 0.2; 114 | spd = walk_spd; 115 | } 116 | 117 | //actually move 118 | if (hspd > spd) 119 | { 120 | hspd = spd; 121 | } 122 | if (hspd < -spd) 123 | { 124 | hspd = -spd; 125 | } 126 | } 127 | //if we are not moving left or right 128 | else 129 | { 130 | //see apply friction script 131 | apply_friction(acc); 132 | } 133 | 134 | //dive if running and pressing action key 135 | if (j && k_pressed && !down && hspd != 0 && collision(id, obj_solid, DOWN) && !collision(id, obj_water, CENTER)) 136 | { 137 | //jump a little and move forward 138 | hspd += image_xscale; 139 | vspd -= 5; 140 | 141 | //set start sprite index 142 | image_index = 0; 143 | 144 | state = player_dive_state; 145 | } 146 | 147 | //set swimming state 148 | if (position_meeting(x, y + 1, obj_water)) 149 | { 150 | state = player_water_state; 151 | } 152 | 153 | //this sets the sprite to face the correct way based on hspd 154 | //sign of hspd returns 1 or -1, and image_xscale(-1) flips the image horizontally 155 | if (hspd != 0) 156 | { 157 | image_xscale = sign(hspd); 158 | } 159 | 160 | //apply collision checking 161 | move(obj_solid); 162 | 163 | // check for other states 164 | ledge_grab_check(); 165 | wall_slide_check(); 166 | -------------------------------------------------------------------------------- /player_roll_state.gml: -------------------------------------------------------------------------------- 1 | ///player_roll_state() 2 | // after the player is running and then dives forward, 3 | // they enter a rolling state 4 | 5 | sprite_index = spr_pboy_roll; 6 | image_speed = 0.3; 7 | 8 | //if the player is in the air 9 | if (!collision(id, obj_solid, DOWN)) 10 | { 11 | //apply gravity 12 | vspd += grav; 13 | } 14 | 15 | move(obj_solid); 16 | -------------------------------------------------------------------------------- /player_wall_jump_state.gml: -------------------------------------------------------------------------------- 1 | ///player_wall_jump_state() 2 | 3 | //set sprite 4 | sprite_index = spr_pboy_wall_jump; 5 | image_speed = 0; 6 | 7 | //if the player is in the air 8 | if (!collision(id, obj_solid, DOWN)) 9 | { 10 | //apply gravity 11 | vspd += grav; 12 | } 13 | 14 | //move with collisions 15 | move(obj_solid); 16 | 17 | //check for normal move state 18 | if (vspd >= 0) 19 | { 20 | state = player_move_state; 21 | } 22 | -------------------------------------------------------------------------------- /player_wall_slide.gml: -------------------------------------------------------------------------------- 1 | ///player_wall_slide() 2 | 3 | //set sprite 4 | sprite_index = spr_pboy_wall_slide; 5 | image_speed = 0; 6 | image_index = 0; 7 | 8 | //set the new gravity value 9 | var new_grav = grav / 4; 10 | 11 | //check if touching the wall 12 | if (collision(id, obj_solid, abs(image_xscale - 1))) 13 | { 14 | //if the player is in the air 15 | if (!collision(id, obj_solid, DOWN)) 16 | { 17 | //apply gravity 18 | vspd += new_grav; 19 | } 20 | move(obj_solid); 21 | } 22 | //check if the wall dissapears 23 | else 24 | { 25 | state = player_move_state; 26 | } 27 | 28 | //check if we touch the ground 29 | if (collision(id, obj_solid, DOWN)) 30 | { 31 | state = player_move_state; 32 | } 33 | 34 | //check if we press down 35 | get_input(); 36 | if (down) 37 | { 38 | state = player_move_state; 39 | } 40 | 41 | //check for wall jump 42 | if (up_pressed) 43 | { 44 | //check that we are jumping and pressing away from the wall 45 | if ((right && collision(id, obj_solid, LEFT)) || (left && collision(id, obj_solid, RIGHT))) 46 | { 47 | //wall jump 48 | state = player_wall_jump_state; 49 | 50 | //jump up the wall 51 | vspd = -10; 52 | 53 | //push against the wall 54 | hspd = 6 * -image_xscale; 55 | } 56 | else 57 | { 58 | //normal wall jump 59 | state = player_move_state; 60 | 61 | //jump up the wall 62 | vspd = -10; 63 | 64 | //push against the wall with each jump 65 | hspd = 6 * -image_xscale; 66 | } 67 | } 68 | 69 | //check if we should grab edge 70 | if (k && ledge_grab_check()) 71 | { 72 | state = player_ledge_grab_state; 73 | } 74 | -------------------------------------------------------------------------------- /wall_slide_check.gml: -------------------------------------------------------------------------------- 1 | ///wall_slide_check() 2 | 3 | //check that we are not in a ledge grab state 4 | if (state != player_ledge_grab_state) 5 | { 6 | //check that we are meeting a wall 7 | if (collision(id, obj_solid, abs(image_xscale - 1)) && !collision(id, obj_water, CENTER)) 8 | { 9 | //check that we are not touching the ground 10 | if (!collision(id, obj_solid, DOWN)) 11 | { 12 | //check that we are falling down 13 | if (vspd >= 0) 14 | { 15 | //first get input 16 | get_input(); 17 | 18 | //check that we are pressing into the wall 19 | if (right && image_xscale == 1) 20 | { 21 | state = player_wall_slide; 22 | } 23 | else if (left && image_xscale == -1) 24 | { 25 | state = player_wall_slide; 26 | } 27 | //otherwise, switch to a normal move state 28 | else 29 | { 30 | state = player_move_state; 31 | } 32 | } 33 | } 34 | } 35 | } 36 | --------------------------------------------------------------------------------