The Godot Q&A is currently undergoing maintenance!

Your ability to ask and answer questions is temporarily disabled. You can browse existing threads in read-only mode.

We are working on bringing this community platform back to its full functionality, stay tuned for updates. | Twitter

0 votes

Snoozy in the Slumberland
I'm making an enemy from a demo template (Physics Controlled 2D Platformer) and here the enemy is a RigidBody2D which always walks on a surface.
I'm creating a flying enemy, which flies at an altitude that I set, and falls to the surface only when hit once (STATEWOUNDED which triggers animation 'wounded'), and after the second hit enters the STATEDYING (triggering animation 'dying' and the 'die' func).

I'm not quite sure how to do it properly. The script uses state machines which are somewhat difficult for me to wrap my head around at the moment. Maybe I should rewrite it without state machines? Like, if I declare STATEWOUNDED, should it be equal 0 or 1? Plus, the script also uses MODERIGID, MODE_STATIC and I don't understand what that does.
Right now If I set gravity to 0 the enemy just flies away into the opposite direction once hit with collision.
Here's the default scriipt:

extends RigidBody2D

class_name Enemy
const WALK_SPEED = 50
const STATE_DYING = 1
# state machine
var state = STATE_WALKING
var direction = -1
var anim = ""

onready var rc_left = $RaycastLeft 
onready var rc_right = $RaycastRight

var Bullet = preload("res://player/")

 func _die():

  func _pre_explode():
#make sure nothing collides against this

# Stay there
($SoundExplode as AudioStreamPlayer2D).play()

func _bullet_collider(cc, s, dp):

s.set_angular_velocity(sign(dp.x) * 33.0)
($SoundHit as AudioStreamPlayer2D).play()

func _integrate_forces(s):
var lv = s.get_linear_velocity()
var new_anim = anim

if state == STATE_DYING:
    new_anim = "explode"
elif state == STATE_WALKING:
    new_anim = "walk"

    var wall_side = 0.0

    for i in range(s.get_contact_count()):
        var cc = s.get_contact_collider_object(i)
        var dp = s.get_contact_local_normal(i)

        if cc:
            if cc is Bullet and not cc.disabled:
                # enqueue call
                call_deferred("_bullet_collider", cc, s, dp)

        if dp.x > 0.9:
            wall_side = 1.0
        elif dp.x < -0.9:
            wall_side = -1.0

    if wall_side != 0 and wall_side != direction:
        direction = -direction
        ($Sprite as Sprite).scale.x = -direction
    if direction < 0 and not rc_left.is_colliding() and rc_right.is_colliding():
        direction = -direction
        ($Sprite as Sprite).scale.x = -direction
    elif direction > 0 and not rc_right.is_colliding() and rc_left.is_colliding():
        direction = -direction
        ($Sprite as Sprite).scale.x = -direction

    lv.x = direction * WALK_SPEED

if anim != new_anim:
    anim = new_anim
    ($Anim as AnimationPlayer).play(anim)

in Engine by (53 points)
edited by

Rigid is a normal physics body. Static is one that is immovable, like a wall.

If you have a new state, you would set it to 2. It's just a shortcut for you to remember the state, so instead of your script thinking, "I'm in state 1 now" you can do "I'm in state STATE_DYING now", which is easier to remember. Then you add logic based on the current state

What behavior do you want? If you set gravity to 0, it won't fall to the ground.

The behavior I need is that the enemy doesn't fall down until the player hits it with a projectile.

Please log in or register to answer this question.

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 Frequently asked questions and 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 [email protected] with your username.