+1 vote

I have a Super Mario mechanic where you jump on the heads of certain enemies to kill them. I have an ok system that, when an enemy and the player collide, checks if the player is currently falling and is not on the ground.

# When coming into contact with something, check if Player
func _on_Area2D_body_entered(body):
if body.get_name() == "Player":
    # If Player is falling
    if body.motion.y > 0 and body.is_on_floor() == false:
        # Deduct health from self equal to Player's damage
        hp -= body.dmg
        # Make the player bounce
        body.motion.y = -body.bounceHeight
        # If health is less than or equal to 0, die
        if hp <= 0:
            body.getPoints(points)
            queue_free()
    else:
        body.takeDamage(dmg)

It works, but I'd like a more precise way to check if the player is actually on top of the enemy, as now you can be just a pixel off of the ground and if you touch the enemy it counts as a hit and the enemy dies.

Thanks for reading!

in Engine by (26 points)

Could you check to see whether the height of the player's jump is almost equal to the enemy's height? Maybe you could use that to figure out whether they played has hit the enemy.

Some ideas not sure if they archive what you want.
Well you could check if the y cordinate of the player is around the area of the head of the enemy area. AllĂ  body.position.y >= enemy.postion + enemy.height - offset

Or you could add a diffrent collision for the top part and see which one got activated first.

y not just add an area2d node on top of ur enemy make it collision one way and then
make use of the body_entered signal to check if a body enter the area
u can make it more precise by adding ur player to a group like"player" then when the signal is called check if the body belong to the group player and if it does your enemy is dead if not ur enemy lives and u dont worry about those pixel error

2 Answers

+3 votes
Best answer

One approach would be to use a raycast or multiple raycasts. I'm only familiar with 2d, so for 3d ymmv.

Depending on the size of your player and your enemies, add a single raycast or multiple raycasts pointing up from your enemies (or down from your player, wherever is more convenient). When you detect a player-enemy collision, use force_raycast_update and is_colliding to make sure the player is above the enemy.

To make sure the raycast doesn't detect things like the ground and other terrain objects, adjust it's collision mask to only interact with objects on the correct layer (enemies or player, depending).

Does that make sense / help?

by (629 points)
selected by

Yeah, that would work. Thanks.

(Sorry for taking so long to respond lol)

0 votes

After playing around a bit with raycast I figured out a way to solve this without messing around with collision masks (which you should probably learn but I think this is a great alternative for some reasons). Of course, I've only tested this in 2d.

I have a scene with a KinematicBody2D (Goomba or any other enemy) and in it's _ready function I've added the next line of code which will later be handy in the Mario scene:

add_to_group("enemy")

Now in my Mario scene with a KinematicBody2D node, to which I've attached a RayCast2D node (the "stomp detector"), I have the next code in the physicsprocess function:

$RayCast2D_Stomp.force_raycast_update()
if $RayCast2D_Stomp.is_colliding():
    var collider = $RayCast2D_Stomp.get_collider()
    if collider.is_in_group("enemy"):
        collider.die()
        jump(jump_speed * 0.75)

As you can see, you simply get the collider that the raycast has detected and check if it is in a certain group, if so, you go ahead and execute the code you want. This is very handy since you can even call functions from the collider, in this case, i called the die function from the Goomba node Mario has stomped on.

by (14 points)
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.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.