the damage system refactor!

killing is now done based on groups, the same way enemies already killed
the player.

these groups go on the entity's hitbox, not the entity itself.
enemies' hitboxes have all been put in "enemy_hitbox"

the arrow_projectile has a variable for the target group, so it could
easily be simply set to "player" for arrows shot by enemies

blocking is also done with groups. any hitbox with "blocks_arrow"
will block arrows, same with "blocks_sword" and "blocks_squash"
This commit is contained in:
Haze Weathers 2023-01-19 18:26:50 -05:00
parent 5a02d02ceb
commit a2974d8dd3
14 changed files with 102 additions and 66 deletions

View file

@ -30,7 +30,6 @@ extents = Vector2( 4, 4 )
[node name="Bat" type="Node2D" groups=["enemy"]]
script = ExtResource( 3 )
can_be_killed_by_sword = false
score_for_killing = 25
speed = 40
move_direction = 1
@ -42,9 +41,9 @@ frames = SubResource( 4 )
frame = 1
playing = true
[node name="Area2D" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["blocks_sword", "enemy_hitbox"]]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
shape = SubResource( 5 )
[connection signal="area_entered" from="Area2D" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -1,38 +1,27 @@
extends Node2D
###
### IMPORTANT: enemy's hitbox must be in the group "enemy_hitbox" to be killed
### it should also be named "Hitbox" for easier (2 click) signal connection
### as the reciever function has been renamed with that in mind
###
const DeathParticles = preload("res://objects/enemy/death_particles.tscn")
export var can_be_killed_by_sword = true
export var can_be_killed_by_arrow = true
export var can_be_squashed = true
### these variables have been replaced with groups to put on the hitbox
### - "blocks_arrow"
### - "blocks_sword"
### if an enemy's hitbox is not in those groups, it will be killed by them
#export var can_be_killed_by_sword = true
#export var can_be_killed_by_arrow = true
#export var can_be_squashed = true
export var score_for_killing = 0
func _on_Area2D_area_entered(area):
func _on_Hitbox_area_entered(area):
#Kill player
if area.is_in_group("player"):
area.get_parent().die()
#Die from sword
if area.is_in_group("sword"):
if can_be_killed_by_sword:
die()
else:
#Block text
Game.instance_node(Game.block_text,global_position.x,global_position.y,get_parent())
#Die from arrow
if area.is_in_group("arrow"):
if can_be_killed_by_arrow:
Game.arrows -= 1
area.get_parent().queue_free()
die()
else:
#Block text
Game.instance_node(Game.block_text,global_position.x,global_position.y,get_parent())
#Die from rock/ get squashed
if area.is_in_group("squash"):
Debug.print("squash")
var squasher = area.get_parent()
if squasher.global_position.y < global_position.y && squasher.velocity.y > 0:
die()
func die():
var death_particles = DeathParticles.instance()

View file

@ -13,7 +13,7 @@ export var flip_sprite = true
#Onreadys
onready var startpos = position
onready var sprite = $AnimatedSprite
onready var raycast = $Area2D/RayCast2D
onready var raycast = $Hitbox/RayCast2D
onready var timer = $Timer
var speed = 50

View file

@ -47,10 +47,10 @@ playing = true
position = Vector2( 4, 4 )
shape = SubResource( 8 )
[node name="Hitbox" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["enemy_hitbox"]]
position = Vector2( 4, 4 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
shape = SubResource( 4 )
[connection signal="area_entered" from="Hitbox" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -40,11 +40,11 @@ position = Vector2( 1, 3 )
frames = SubResource( 4 )
playing = true
[node name="Area2D" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["enemy_hitbox"]]
position = Vector2( -4, 0 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( 4.5, 3.5 )
shape = SubResource( 5 )
[connection signal="area_entered" from="Area2D" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -41,13 +41,13 @@ frames = SubResource( 4 )
frame = 1
playing = true
[node name="Area2D" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["enemy_hitbox"]]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( 4, 4 )
shape = SubResource( 5 )
[node name="RayCast2D" type="RayCast2D" parent="Area2D"]
[node name="RayCast2D" type="RayCast2D" parent="Hitbox"]
position = Vector2( 0, 4 )
enabled = true
cast_to = Vector2( 32, 0 )
@ -58,5 +58,5 @@ collide_with_areas = true
wait_time = 0.5
one_shot = true
[connection signal="area_entered" from="Area2D" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]
[connection signal="timeout" from="Timer" to="." method="_on_Timer_timeout"]

View file

@ -35,13 +35,12 @@ score_for_killing = 15
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
material = SubResource( 1 )
frames = SubResource( 4 )
frame = 1
playing = true
[node name="Area2D" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["enemy_hitbox"]]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( 0, 4 )
shape = SubResource( 5 )
[connection signal="area_entered" from="Area2D" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -28,12 +28,13 @@ script = ExtResource( 1 )
[node name="AnimatedSprite" type="AnimatedSprite" parent="."]
position = Vector2( 4, 12 )
frames = SubResource( 3 )
frame = 1
playing = true
[node name="Area2D" type="Area2D" parent="."]
[node name="Hitbox" type="Area2D" parent="." groups=["enemy_hitbox"]]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( 4, 12 )
shape = SubResource( 4 )
[connection signal="area_entered" from="Area2D" to="." method="_on_Area2D_area_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -14,3 +14,10 @@ func _physics_process(delta):
func push(direction):
velocity -= direction * 32
func _on_Hitbox_area_entered(area):
# do not squish if in "blocks_squash" group
if area.is_in_group("enemy_hitbox") && !area.is_in_group("blocks_squash"):
var enemy = area.get_parent()
if enemy.global_position.y > global_position.y && velocity.y > 0:
enemy.die()

View file

@ -29,12 +29,14 @@ centered = false
position = Vector2( 4, 4 )
shape = SubResource( 2 )
[node name="Area2D" type="Area2D" parent="." groups=["squash"]]
[node name="Hitbox" type="Area2D" parent="." groups=["squash"]]
position = Vector2( -1, 0 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( 5, 4 )
shape = SubResource( 3 )
[node name="Bottom" type="Position2D" parent="."]
position = Vector2( 4, 8 )
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]

View file

@ -1,16 +1,24 @@
extends Node2D
onready var cull_edge = Vector2(5 * scale.x,0) #Edge to check culling, if this edge is offscreen, delete the arrow
export var speed = 240.0
# group to kill
var target_group = "enemy_hitbox"
# direction to fly
var direction = 1.0
#Edge to check culling, if this edge is offscreen, delete the arrow
onready var cull_edge = Vector2(5 * direction,0)
onready var player = get_parent().get_node("Player")
onready var initial_sector = Game.get_sector(player.global_position)
func _ready():
#Flip depending on player facing
scale.x = player.sprite.scale.x
#Flip depending on direction
scale.x = direction
func _physics_process(delta):
#Move in flip direction
position.x += 4 * scale.x
#Move in right direction
position.x += speed * direction * delta
#Delete when offscreen
if Game.get_sector(global_position + cull_edge) != initial_sector:
queue_free()
@ -22,10 +30,24 @@ func _exit_tree():
particles.global_position = global_position
particles.emitting = false
get_parent().add_child(particles)
particles.get_node("DeathTimer").start()
get_tree().create_timer(particles.lifetime, false).connect("timeout", particles, "queue_free")
#Wall Collision
func _on_Area2D_body_entered(body):
func _on_Hitbox_body_entered(body):
if body is TileMap or body is StaticBody2D:
queue_free()
# kill entity if in target group
func _on_Hitbox_area_entered(area):
# block if collided area is in "blocks_arrow" group
if area.is_in_group(target_group):
var target = area.get_parent()
# create block text and return if blocked
if area.is_in_group("blocks_arrow"):
var pos = target.global_position
Game.instance_node(Game.block_text, pos.x, pos.y, target.get_parent())
else:
# kill targeted node
target.die()
Game.arrows = max(0, Game.arrows - 1) # clamp arrows above 0
queue_free()

View file

@ -52,15 +52,12 @@ local_coords = false
process_material = SubResource( 5 )
texture = ExtResource( 4 )
[node name="DeathTimer" type="Timer" parent="DustParticles"]
one_shot = true
[node name="Hitbox" type="Area2D" parent="." groups=["arrow"]]
collision_layer = 0
[node name="Area2D" type="Area2D" parent="." groups=["arrow"]]
visible = false
[node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"]
[node name="CollisionShape2D" type="CollisionShape2D" parent="Hitbox"]
position = Vector2( -0.5, -0.5 )
shape = SubResource( 2 )
[connection signal="timeout" from="DustParticles/DeathTimer" to="DustParticles" method="queue_free"]
[connection signal="body_entered" from="Area2D" to="." method="_on_Area2D_body_entered"]
[connection signal="area_entered" from="Hitbox" to="." method="_on_Hitbox_area_entered"]
[connection signal="body_entered" from="Hitbox" to="." method="_on_Hitbox_body_entered"]

View file

@ -1,5 +1,7 @@
extends KinematicBody2D
const ArrowProjectile = preload("res://objects/player/arrow_projectile.tscn")
##CLEAN UP CODE LATER
##Children
onready var sprite = $Sprite
@ -30,7 +32,6 @@ var can_move_in_air = false
#Positions
var arrowpos = Vector2(5,3)
##Preload
var pre_arrow = preload("res://objects/player/arrow_projectile.tscn")
#Set initial respawn point
func _ready():
@ -187,7 +188,13 @@ func _process_shoot():
func spawn_arrow():
Game.play_sound(Game.a_shoot,Game.ac_jump)
Game.instance_node(pre_arrow,global_position.x+(arrowpos.x*sprite.scale.x),global_position.y+arrowpos.y,map)
var arrow = ArrowProjectile.instance()
arrow.global_position = Vector2(
global_position.x + arrowpos.x * sprite.scale.x,
global_position.y + arrowpos.y
)
arrow.direction = sprite.scale.x
map.add_child(arrow)
func check_jump():
if Input.is_action_just_pressed("jump"):
@ -291,3 +298,15 @@ func _on_AnimationPlayer_animation_finished(anim_name):
else:
current_state = State.FALL
return
func _on_SwordArea_area_entered(area):
if area.is_in_group("enemy_hitbox"):
var target = area.get_parent()
# create block text and return if blocked
if area.is_in_group("blocks_sword"):
var pos = target.global_position
Game.instance_node(Game.block_text, pos.x, pos.y, target.get_parent())
return
else:
target.die()

View file

@ -731,3 +731,4 @@ process_material = SubResource( 45 )
texture = ExtResource( 16 )
[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_AnimationPlayer_animation_finished"]
[connection signal="area_entered" from="SwordArea" to="." method="_on_SwordArea_area_entered"]