|Attention||Topic was automatically imported from the old Question2Answer platform.|
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