EDIT: OH WOW THIS IS TOTALLY OUT OF DATE AND A BIT RUBBISH
DON'T USE AREA2Ds TO CHECK COLLISION WITH GROUND AND CEILING USE THE COLLISION NORMALS RETURNED FROM MOVE_AND_COLLIDE (for 3.0) OR IT'S EQUIVALENT FUNCTION IN 2.0<br>
<br>
Intro
As a coder, I have certain standards and principle to follow...<br>One of them (which I suggest more people should follow) is that If I do not understand a particular system or piece of code...<br>I do not use it<br><br>This
is for a variety of reasons but to sum it up, It really helps debugging
and integration with the rest of the program if you understand what is
going on under the hood (and I also just like it out of principle)<br><br>This
is why I have made my own simple to follow platformer script, as I
found the demo platforming engines to be far too complicated for my puny
human mind<br><br>All that is required is basic knowledge of Godot<br>(KinematicBody2D, Signals, Input, GDScript etc.)<br><br>The Player<br><br><img alt="" src="http://i.imgur.com/3FTRV80.png" title="Image: http://i.imgur.com/3FTRV80.png" width="760" height="465"><br><br>Here is our Player! Let's dissect this!<br><br>The player in this tutorial consists of a KinematicBody2D, a Sprite and two Area2Ds<br><br>The
KinematicBody2D is just a huge 16x32 (32x64 in pixels, as
CollisionShape2D sizes are double for some presumably important reason)
rectangle (As dictated by it's CollisionShape2D and fully obscured by
the sprite which is it's exact size)<br><br>The bottom Area2D (Bottom)
is a 16x1 (32x2 pixels) area under the KinematicBody2D, it has it's
body_enter and body_exit signals linked to the KinematicBody2D (the root
node of the scene containing all the scripts) it acts as the player's
“feet”<br><br>The top Area2D (Top) is a 16x0.5 (32x1 pixels) area above
the KinematicBody2D and has it's body_enter signal linked to the
KinematicBody2D<br><br>Input<br><br><img alt="" src="http://i.imgur.com/jPpjQwt.png" width="306" height="148"><br><br>Don't forget to set up your input for this project! <br><br>(This is my setup)<br><br>The names are important however you can easily change them in the code...<br><br>The Code:<br>
extends KinematicBody2D <br><br>var grav=100<br>var speed=100<br>var grounded=0<br>var motion<br>var jspeed = 200 #jump power<br>var yspeed<br>var jumping = false<br><br>func _ready():<br> yspeed=grav<br> set_fixed_process(true)<br> set_process_input(true)<br> pass<br><br>func _fixed_process(delta):<br> if (grounded<0): #ensures that the grounded variable never goes under 0<br> grounded=0<br> motion=Vector2(0,0) #(basic movement stuff)<br> if (Input.is_action_pressed("move_left")):<br> motion+=Vector2(-1,0)<br> if (Input.is_action_pressed("move_right")):<br> motion+=Vector2(1,0)<br> if (jumping==1): #(if the player has pressed jump)<br> if (grounded>0): #(if the player is detected to be on the ground)<br> jump(jspeed) # sets yspeed to the value of jspeed, jumping<br> grounded=0<br> jumping=0<br> <br> motion = motion*speed*delta<br> move(motion)<br> <br> if (self.is_colliding()): #ensures that the character moves against walls properly<br> var n = get_collision_normal()<br> motion = n.slide(motion)<br> move(motion)<br> if (yspeed>grav): #ensures that the player does not exceed the speed of gravity<br> yspeed=grav<br> move(Vector2(0,1)*yspeed*delta) #moves the player vertically<br> if (yspeed<grav): #takes away 4 from the players yspeed every loop, making them fall in a curve<br> yspeed+=4<br> print(str(grounded))<br><br>func jump(jumpvar):<br> yspeed= -jumpvar<br><br>func _input(event): #fixed controls ensures consistant jump height as jump() is only called once<br> if (event.is_action_pressed("jump")):<br> jumping=1<br><br>#Area2D “Bottom”'s body_enter signal<br>func _on_Bottom_body_enter( body ): #adds one to grounded if player's "feet" touch a body<br> grounded+=1<br> pass # replace with function body<br><br>#Area2d “Bottom”'s body_exit signal<br>func _on_Bottom_body_exit( body ): #removes one from grounded whenever player's "feet" leave a body<br> grounded-=1<br> pass <br><br><br>#Area2D “Top”'s body_enter signal<br>func _on_Top_body_enter( body ): #ensures the player does not get stuck in ceiling when hitting a block above them, instead making them bump off<br> yspeed=grav<br> pass
<p><br></p>The Test Level<br><br><img alt="" src="http://i.imgur.com/4ASLDq5.png" width="618" height="368"><br><br>Here I have a tilemap set up (which just consists of a bunch of Sprites with StaticBody2D children)<br><br>It
has a floor, walls so you can't jump out into the void and a ceiling to
test that the collision works properly and the player doesn't get stuck<br><br>Useful Notes<br><br>The “grounded” system is important as the player's “feet” are usually touching more that one body at a time. <br><br>I
originally had a pseudo boolean system with 0 and 1 (because I was too
lazy to change everything to accept True and false) where a boy entering
your “feet” set grounded to 1 and a body leaving your “feet” set it to
0. <br><br>I had problems with jumping (character not jumping when
touching the floor, character jumping in the air) but I then realized
that a system that counts the number of bodies the player's feet and
could jump when it was more than 0 would solve all my problems.<br>(it's actually common for "coding genius" moments like this to stem from glitches or poor/lazy design)<br><br>Your Thoughts?<br><br>Hope you enjoyed reading!<br><br>If you have any comments or ideas on how I could improve this, please reply away!<br>