+1 vote

I'm trying to make a Player (KinematicBody2D) jump when it lands on the Tileset, I can't figure it out without crashing. The code below has a comment indicating where I think the error starts. Any ideas? Sorry for the small brief, I'm tired.

PlayerMovement.gd:

    extends KinematicBody2D

const GRAVITY = 4000.0
#const WALK_SPEED = 2000
const JUMP_STRENGTH = 2500.0

const JUMP_LIMIT = 1.0
var jump_allowed_timer =  0

onready var sprite = get_tree().get_root().get_node("World/Player/CollisionShape2D/PlayerSprite")

func _ready():
    set_fixed_process(true)

var velocity = Vector2()

export var PlayerSpeed = 1920

export var Smoothness = 0.2

func _fixed_process(delta):

    velocity.y += delta * GRAVITY

    if(jump_allowed_timer > 0):
        jump_allowed_timer -= delta

    var direction = 0
    if (Input.is_action_pressed("ui_left")):
        direction = -1
        sprite.set_flip_h(true)
    elif (Input.is_action_pressed("ui_right")):
        direction = 1
        sprite.set_flip_h(false)
    velocity.x = lerp(velocity.x, PlayerSpeed * direction, Smoothness)

    var motion = velocity * delta
    motion = move(motion)

    if (is_colliding()):
        var normal = get_collision_normal()
        motion = normal.slide(motion)
        velocity = normal.slide(velocity)
        move(motion)

# Problems (most likely) start here.
    var collider = get_collider()

    if (Input.is_action_pressed("ui_jump")) && is_jump_allowed():# && collider.is_in_group("Tileset"):
        velocity.y -= JUMP_STRENGTH
        jump_allowed_timer = JUMP_LIMIT

func is_jump_allowed():
    return (jump_allowed_timer <= 0)
asked Oct 1, 2017 in Engine by HarryCourt (161 points)

Is the indentation that way or got broken when you wrote it? because the get_collider is outside the is_colliding check.

If that is wrong, try to fix it so you can get better answers.

No, it's correct

1 Answer

0 votes
Best answer

Solved.

Using Godot 2.1.4

 
I tried to approximate your setup using the info given
+ adding this TileMap kbscene.zip linked in this Kinematic Character (2D) tutorial

The kbscene.zip has a TileMap scene + a scene with Tilesets with collision objects
is described in the "Using tilemaps" Godot Docs tutorial

I used two scenes.

  1. Player.tscn
  2. map.scn -- from the kbscene.zip file
    (and used this as the main scene)

I named the root node in map.scn to "World" to match your code.
To get the TileMap node under that to work properly,
I had to

  1. Open tileset_edit.scn -- from kbscene.zip
  2. Didn't change anything here b/c each sprite node already has
    a StaticBody2D with a CollisionPolygon2D
  3. Scene -> Convert To... -> TileSet... -> saved under res://mytiles.res
  4. Clicked the map.scn's TileMap node under World
  5. Added "res://mytiles.res" -> TileMap's "Tile Set" in the Inspector
  6. I clicked TileMap node -> clicked Node panel -> Groups -> "Tileset" -> Add
    ( this makes any collision with anything drawn using this TileMap
    return true for your code
    if( collider.is_in_group("Tileset") ): )

I then drew a vertical wall + added a floor

Added an instance of Player.tscn under World

 

So the map.scn looks like this :
link to main map.scn picture
Main scene setup with TileMap + Player.tscn instance

 

This is how I set up the Player.tscn scene :
link to Player.tscn node tree picture
enter image description here

NODE TREE
-- a KinematicBody2D named "Player" (as the root)
-- -- a CollisionShape2D with a simple box shape
-- -- -- a Sprite named "PlayerSprite"

 

So onto the code.

here was the first clue as to what was going on :
link
enter image description here

Kept getting an error reading :

"Condition ' !colliding ' is true. returned: 0"

 

Changed the code a bit to debug :
Link
enter image description here

 


bug identified : move(motion) -> is bringing Player out of a collision

Following picture is identical to the last,
but commented out the line #move(motion)
link
enter image description here

 

So.

Basically you need var collider = get_collider()
to be placed in your if (is_colliding()): block
but before your move(motion) call.

 

 

Fixed func _fixed_process(delta):
(rest of the code unchanged)
link to picture
enter image description here

func _fixed_process(delta):

    velocity.y += delta * GRAVITY

    if(jump_allowed_timer > 0):
        jump_allowed_timer -= delta

    var direction = 0
    if (Input.is_action_pressed("ui_left")):
        direction = -1
        sprite.set_flip_h(true)
    elif (Input.is_action_pressed("ui_right")):
        direction = 1
        sprite.set_flip_h(false)
    velocity.x = lerp(velocity.x, PlayerSpeed * direction, Smoothness)

    var motion = velocity * delta
    motion = move(motion)

    if (is_colliding()):
        var normal = get_collision_normal()
        motion = normal.slide(motion)
        velocity = normal.slide(velocity)

        var collider = get_collider()
        move(motion)

        ###if you need to debug collision groups
        #
        #if collider.is_in_group("Tileset") :
        #   print("collider in group 'Tileset'")

        if ( Input.is_action_pressed("ui_jump") && is_jump_allowed() && collider.is_in_group("Tileset") ):
            velocity.y -= JUMP_STRENGTH
            jump_allowed_timer = JUMP_LIMIT

hint : you can copy paste code from this site into Godot
then ctrl+r to replace sets of 4 spaces ("    ") with the tab character
(type a TAB in Godot -> copy paste a single tab character into the replace menu)

answered Oct 7, 2017 by Grass H0PEr (106 points)
selected Oct 9, 2017 by HarryCourt

Hope this helps!

 

Also for future reference + study
download this folder as a .zip
and open the project files in Godot 2.1.4

https://github.com/godotengine/godot-demo-projects/tree/2.1/

It has a lot of examples + several different projects.

 

Note:
If you're using Godot 3.0 -- the 3.0 master branch of the demos
can be found here.

https://github.com/godotengine/godot-demo-projects/tree/master

IIRC it's still a work in progress and more will be added + polished.

Have fun!
Good learning.

Thank you! This worked perfectly.

I had to remove one bit of the code, since the game would break with it. Apart from that, it works perfectly! Thank you!

^___^

Glad to hear!

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.