0002 - Kinematic character controlling / (not) getting it perfect

·

0 min read

Let's talk about character controllers a little. That might be the most important part of a 2D platform game - if the movement of your character feels odd it wont be enjoyable. For coop purposes I plan to include multiple character controllers which support different play styles - but that is a topic for (way) later. For now we see what we can come up with to get some stuff done, shall we?

I made one in the beta of Godot, Godot 1, Godot 2, 2.2, and now I made one in Godot 3(.1) and hell stuff changed a lot. In the good-ol-days, you needed to access your nodes in the constructor, nowadays it is as simple as defining var sprite = $CharacterSpriteSheet as an instance variable of your class, but I digress.

Well. Characters. Yes. What should they look like? If you have no time or no talent to design own assets (or in my case both) you might want to check pages like OpenGameArt to see if somebody offers you something with a license fit to your requirements. For this project I will use the Platformer Pack Redux from kenney.nl. Kenney offers everything I could wish for and their assets are just fantastic (well, I changes the gamma values a little, 'cause I found the contrast to be a liiiitlle to low, but don't tell anybody). p1_05_jump.png

While working on the character controller, I noticed that I am getting too deep into tiny details way too early. I basically ditched my custom slope detection, edge detection and wall jump logic since it was getting out of hand and did not feel as perfect as I wanted it to feel. I remember working on a top-down-RPG a littler over a year ago. I spend an entire week on learning about 2D shaders, because I wanted my sprites to reflect in the surface of a water tile. Details like that are nice, but they will keep you from advancing in your project (but damn that was some great water shader). For now I decided to simply go for Godots build in move_and_slide_with_snap function, to keep my code clean for now. Build-in engine functions can help you with slopes, pixel perfect platform movement, snapping to the ground and so on. Even though it's not yet perfect, especially if the character lands on a slope, most stuff works pretty well.

Godots move_and_slide_with_snap tries to make your character stick to a platform "as good as it can". Logically, that makes it pretty hard to jump at first glance. I solved this problem by using the floor detection after I calculated the movement of the character for the given physics frame.

# hardly snaps 16px to the ground
const SNAP = Vector2(0, 16)
# empty vector, will hold SNAP later
var snapping = Vector2()

func _physics_process(delta):
    [ ... ]
    linear_vel = move_and_slide_with_snap(linear_vel, snapping, 
    FLOOR_NORMAL, true, 4, deg2rad(46))
    linear_vel.x += delta
    if is_on_floor():
        snapping = SNAP
    else:
        linear_vel.y += delta * GRAVITY_VEC.y
    [ ... ]
    # Jump
    if is_on_floor() and input_jump:
        snapping = Vector2.ZERO
        linear_vel.y = -JUMP_SPEED

That solves a lot of problems. It allows the character to

  • run over slopes
  • jump and land on moving platforms
  • stand on platforms that a moving up and down without hopping up and down like a rubber ball

Oh, and I made a little screencast from my current progress, so you can actually see what I am talking about.