New enemy type, a hopper who jumps back and forth. Invulnerability flag added to Stats, and a function to do so with a timer.

This commit is contained in:
Francois Belair 2019-09-25 11:06:12 -04:00
parent 0dfc7a7ca1
commit 6ac88fa2ee
11 changed files with 207 additions and 11 deletions

View file

@ -48,9 +48,6 @@ collision_layer = 16
collision_mask = 2
script = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 1 )
[node name="Hitbox" type="Area2D" parent="."]
monitorable = false
collision_layer = 16
@ -59,6 +56,9 @@ script = ExtResource( 2 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
shape = SubResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 1 )
[node name="HookTarget" parent="." instance=ExtResource( 3 )]
editor/display_folded = true
is_one_shot = true
@ -69,7 +69,6 @@ shape = SubResource( 2 )
[node name="Body" type="Node2D" parent="."]
script = ExtResource( 4 )
size = Vector2( 100, 40 )
outline = Vector2( 6, 6 )
color_fill = Color( 0.615686, 0, 1, 1 )
color_outline = Color( 0.270588, 0.0745098, 0.619608, 1 )
@ -86,7 +85,6 @@ hooked_color = Color( 0.886275, 0.415686, 0.133333, 1 )
[node name="Stunned" type="Node" parent="StateMachine"]
script = ExtResource( 8 )
next_state = "Destroyed"
[node name="Destroyed" type="Node" parent="StateMachine"]
script = ExtResource( 9 )

View file

@ -0,0 +1,13 @@
extends KinematicBody2D
onready var hitbox: Area2D = $Hitbox
onready var hook_target: HookTarget = $HookTarget
onready var collider: CollisionShape2D = $CollisionShape2D
onready var body: Node2D = $Body
export(int, 0, 360, 1) var jump_angle_left: = 45
export(int, 0, 360, 1) var jump_angle_right: = 45
export var jump_power_left: = 500
export var jump_power_right: = 500
export(int, -1, 1, 2) var direction: = 1
export var gravity: = 6000.0

View file

@ -0,0 +1,92 @@
[gd_scene load_steps=13 format=2]
[ext_resource path="res://src/AI/HopperEnemy.gd" type="Script" id=1]
[ext_resource path="res://src/Combat/DamageSource.gd" type="Script" id=2]
[ext_resource path="res://src/Objects/HookTarget.tscn" type="PackedScene" id=3]
[ext_resource path="res://src/Player/Rectangle.gd" type="Script" id=4]
[ext_resource path="res://src/Main/StateMachine/StateMachine.gd" type="Script" id=5]
[ext_resource path="res://src/AI/States/Jump.gd" type="Script" id=6]
[ext_resource path="res://src/AI/States/Hooked.gd" type="Script" id=7]
[ext_resource path="res://src/AI/States/Stunned.gd" type="Script" id=8]
[ext_resource path="res://src/AI/States/Destroyed.gd" type="Script" id=9]
[sub_resource type="RectangleShape2D" id=2]
extents = Vector2( 25, 25 )
[sub_resource type="RectangleShape2D" id=1]
extents = Vector2( 25, 25 )
[sub_resource type="Animation" id=3]
resource_name = "FadeOut"
tracks/0/type = "value"
tracks/0/path = NodePath("../../Body:color_outline")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/keys = {
"times": PoolRealArray( 0, 1 ),
"transitions": PoolRealArray( 1, 1 ),
"update": 0,
"values": [ Color( 0.0352941, 0.176471, 0.372549, 1 ), Color( 0.0745098, 0.133333, 0.619608, 0 ) ]
}
tracks/1/type = "value"
tracks/1/path = NodePath("../../Body:color_fill")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/keys = {
"times": PoolRealArray( 0, 0.2, 1 ),
"transitions": PoolRealArray( 1, 1, 1 ),
"update": 0,
"values": [ Color( 0.760784, 0.203922, 0.658824, 1 ), Color( 1, 0, 0, 1 ), Color( 1, 0, 0, 0 ) ]
}
[node name="HopperEnemy" type="KinematicBody2D"]
collision_layer = 16
collision_mask = 2
script = ExtResource( 1 )
[node name="Hitbox" type="Area2D" parent="."]
collision_layer = 16
script = ExtResource( 2 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
shape = SubResource( 2 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource( 1 )
[node name="HookTarget" parent="." instance=ExtResource( 3 )]
[node name="Body" type="Node2D" parent="."]
script = ExtResource( 4 )
size = Vector2( 50, 50 )
color_fill = Color( 0.760784, 0.203922, 0.658824, 1 )
color_outline = Color( 0.0352941, 0.176471, 0.372549, 1 )
[node name="StateMachine" type="Node" parent="."]
script = ExtResource( 5 )
initial_state = NodePath("Jump")
[node name="Jump" type="Node" parent="StateMachine"]
script = ExtResource( 6 )
[node name="Cooldown" type="Timer" parent="StateMachine/Jump"]
wait_time = 0.6
one_shot = true
[node name="Hooked" type="Node" parent="StateMachine"]
script = ExtResource( 7 )
hooked_color = Color( 0.890196, 0.670588, 0.14902, 1 )
[node name="Stunned" type="Node" parent="StateMachine"]
script = ExtResource( 8 )
[node name="Destroyed" type="Node" parent="StateMachine"]
script = ExtResource( 9 )
hurt_color = Color( 1, 0, 0, 1 )
[node name="AnimationPlayer" type="AnimationPlayer" parent="StateMachine/Destroyed"]
anims/FadeOut = SubResource( 3 )

View file

@ -8,11 +8,14 @@ It simply waits until the player body collides with the hitbox, colors the body,
export var hooked_color: Color
var hook_position: Vector2
func enter(msg: Dictionary = {}) -> void:
owner.body.set_color_fill(hooked_color)
hook_position = msg.hook_position
owner.hitbox.connect("body_entered", self, "_on_Player_body_entered", [], CONNECT_ONESHOT)
func _on_Player_body_entered(body: Player) -> void:
_state_machine.transition_to("Stunned", {player = body})
_state_machine.transition_to("Stunned", {player = body, hook_position = hook_position})

View file

@ -26,7 +26,7 @@ func physics_process(delta: float) -> void:
func _on_Hook_hooked_onto_from(hook_position: Vector2) -> void:
_state_machine.transition_to("Hooked")
_state_machine.transition_to("Hooked", {hook_position = hook_position})
func _on_Player_body_entered(player: Player) -> void:

View file

@ -0,0 +1,59 @@
extends State
onready var timer: Timer = $Cooldown
onready var acceleration: = Vector2(0, owner.gravity)
onready var move_direction: = Vector2(-owner.direction, 1)
onready var jump_vector_right = Vector2(cos(deg2rad(owner.jump_angle_right)), -sin(deg2rad(owner.jump_angle_right)))
onready var jump_vector_left = Vector2(cos(deg2rad(owner.jump_angle_left)), -sin(deg2rad(owner.jump_angle_left)))
var _velocity: = Vector2.ZERO
var _jumping: = false
func enter(msg: Dictionary = {}) -> void:
owner.hitbox.connect("body_entered", self, "_on_Player_body_entered")
owner.hook_target.connect("hooked_onto_from", self, "_on_Player_hooked_onto_from", [], CONNECT_ONESHOT)
timer.connect("timeout", self, "_on_Cooldown_timeout")
timer.start()
func exit() -> void:
owner.hitbox.disconnect("body_entered", self, "_on_Player_body_entered")
func physics_process(delta: float) -> void:
if not _jumping and owner.is_on_floor():
return
_velocity = calculate_velocity(_velocity, acceleration, delta, move_direction)
owner.move_and_slide(_velocity, Vector2.UP)
if owner.is_on_floor():
_jumping = false
_velocity = Vector2.ZERO
move_direction.x *= -1
timer.start()
func _on_Player_body_entered(player: Player) -> void:
player.take_damage(Hit.new(owner.hitbox))
func _on_Player_hooked_onto_from(hook_position: Vector2) -> void:
_state_machine.transition_to("Hooked", {hook_position = hook_position})
func _on_Cooldown_timeout() -> void:
var jump_vector: Vector2 = jump_vector_right if move_direction.x > 0 else jump_vector_left
var jump_power: float = owner.jump_power_right if move_direction.x > 0 else owner.jump_power_left
_velocity += calculate_velocity(_velocity, jump_vector * jump_power * Vector2(1,-1), 1.0, jump_vector * move_direction)
_jumping = true
static func calculate_velocity(old_velocity: Vector2, acceleration: Vector2,
delta: float, move_direction: Vector2) -> Vector2:
var new_velocity: = old_velocity
new_velocity += move_direction * acceleration * delta
return new_velocity

View file

@ -6,15 +6,16 @@ State that connects to the player's signal about hopping off an entity,
export var knock_back_speed: = 450.0
export var next_state: String
var knocked_away: = false
var current_speed: float
var knock_back_direction: Vector2
var _player: Player
func enter(msg: Dictionary = {}) -> void:
knock_back_direction = (msg.hook_position - owner.global_position).normalized()
knocked_away = false
_player = msg.player
_player.connect("hopped_off_entity", self, "_on_Player_hopped_off_entity", [], CONNECT_ONESHOT)
@ -23,11 +24,11 @@ func enter(msg: Dictionary = {}) -> void:
func physics_process(delta: float) -> void:
if knocked_away:
owner.move_and_collide(Vector2.DOWN * delta * current_speed)
owner.move_and_collide(knock_back_direction * delta * current_speed)
current_speed *= 0.95
func _on_Player_hopped_off_entity() -> void:
knocked_away = true
yield(get_tree().create_timer(0.5), "timeout")
_state_machine.transition_to(next_state)
_state_machine.transition_to("Destroyed")

View file

@ -12,6 +12,8 @@ signal damage_taken()
var modifiers = {}
var invulnerable: = false
var health: int
export var max_health: int = 1 setget set_max_health
@ -24,6 +26,9 @@ func _ready() -> void:
func take_damage(hit: Hit) -> void:
if invulnerable:
return
var old_health = health
health -= hit.damage
emit_signal("damage_taken")
@ -51,3 +56,12 @@ func add_modifier(id: int, modifier) -> void:
func remove_modifier(id: int) -> void:
modifiers.erase(id)
func set_invulnerable_for_seconds(time: float) -> void:
invulnerable = true
var timer: = get_tree().create_timer(time)
yield(timer, "timeout")
invulnerable = false

View file

@ -1,4 +1,4 @@
[gd_scene load_steps=7 format=2]
[gd_scene load_steps=8 format=2]
[ext_resource path="res://assets/tilesets/valley.tres" type="TileSet" id=1]
[ext_resource path="res://assets/tilesets/prototype.tres" type="TileSet" id=2]
@ -6,6 +6,7 @@
[ext_resource path="res://src/Objects/Checkpoint.tscn" type="PackedScene" id=4]
[ext_resource path="res://src/Objects/Portal.tscn" type="PackedScene" id=5]
[ext_resource path="res://src/AI/EnemyPassivePatrol.tscn" type="PackedScene" id=6]
[ext_resource path="res://src/AI/HopperEnemy.tscn" type="PackedScene" id=7]
[node name="Level1" type="Node2D"]
@ -72,6 +73,9 @@ next_level_portal_name = ""
[node name="EnemyPassivePatrol" parent="Enemies" instance=ExtResource( 6 )]
position = Vector2( 1100.16, 370.077 )
[node name="EnemyPassivePatrol3" parent="Enemies" instance=ExtResource( 6 )]
position = Vector2( 1294.42, 370.077 )
[node name="EnemyPassivePatrol2" parent="Enemies" instance=ExtResource( 6 )]
position = Vector2( 1570.94, -229.096 )
direction = 0
@ -79,3 +83,10 @@ direction = 0
[node name="EnemyPassivePatrol7" parent="Enemies" instance=ExtResource( 6 )]
position = Vector2( 1412.34, -750.226 )
direction = 0
[node name="HopperEnemy" parent="Enemies" instance=ExtResource( 7 )]
position = Vector2( 1392.78, 942.911 )
jump_angle_left = 42
jump_angle_right = 60
jump_power_left = 1867
jump_power_right = 3000

View file

@ -11,7 +11,11 @@ export var wait_duration: = 0.6
func enter(msg: Dictionary = {}) -> void:
owner.stats.set_invulnerable_for_seconds(wait_duration*3)
var timer: = get_tree().create_timer(wait_duration)
yield(timer, "timeout")
owner.emit_signal("hopped_off_entity")
owner.state_machine.transition_to('Move/Air', {impulse = hop_impulse, velocity = Vector2.ZERO})

View file

@ -10,6 +10,7 @@ func _on_Player_animation_finished(anim_name: String) -> void:
func enter(msg: Dictionary = {}) -> void:
assert "last_checkpoint" in msg
owner.stats.set_invulnerable_for_seconds(2)
owner.global_position = msg.last_checkpoint.global_position
owner.is_active = false
owner.camera_rig.is_active = false