Flying enemies: help adjust default script

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By verbaloid

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 (STATE_WOUNDED which triggers animation ‘wounded’), and after the second hit enters the STATE_DYING (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 STATE_WOUNDED, should it be equal 0 or 1? Plus, the script also uses MODE_RIGID, 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_WALKING = 0
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/bullet.gd")

 func _die():
 	queue_free()

  func _pre_explode():
#make sure nothing collides against this
$Shape1.queue_free()
$Shape2.queue_free()
$Shape3.queue_free()

# Stay there
mode = MODE_STATIC
($SoundExplode as AudioStreamPlayer2D).play()

func _bullet_collider(cc, s, dp):
mode = MODE_RIGID
state = STATE_DYING

s.set_angular_velocity(sign(dp.x) * 33.0)
set_friction(1)
cc.disable()
($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)
				break
		
		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)

s.set_linear_velocity(lv)

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.

lucaslcode | 2020-02-10 21:07

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

verbaloid | 2020-02-11 05:18