Today, we are going to create a new scene(node) to handle enemy sprites overlapping on screen:
- Area2D root node
- and a collisionShape
Then attach a script to your Area2D. In this script, we're going to check if there are two sprites in the same position (overlapping), and if they are, one of them is going to receive a little push to separate them.
```
extends Area2D
func is_colliding():
var areas = get_overlapping_areas()
return areas.size() > 0
func get_push_vector():
var areas = get_overlapping_areas()
var push_vector = Vector2.ZERO
if is_colliding():
var area = areas[0]
push_vector = area.global_position.direction_to(global_position)
push_vector = push_vector.normalized()
return push_vector
```
For this to work, we also need to create a layer for this collision.
And then set it up to be used
Once the new Area2D scene is set up, instance it to your enemy nodes, and add their collision shapes
> I bet you think that's all, but you need to use those functions in your bat script for them to work
`onready var spriteOverlap = $SpriteOverlap`
and at the end of your physic_process:
```
if spriteOverlap.is_colliding():
velocity += spriteOverlap.get_push_vector() * delta * 400
velocity = move_and_slide(velocity)
```
In other words, your enemy script should be eventually something like this:
```
extends KinematicBody2D
const EnemyDeathEffect = preload("res://Effects/EnemyDeathEffect.tscn")
export var ACCELERATION = 300
export var MAX_SPEED = 50
export var FRICTION = 200
export var WANDER_TARGET_RANGE = 4
enum {
IDLE,
WANDER,
CHASE
}
var velocity = Vector2.ZERO
var knockback = Vector2.ZERO
var state = CHASE
onready var stats = $Stats
onready var playerDetectionZone = $PlayerDetectionZone
onready var spriteOverlap = $SpriteOverlap
func _physics_process(delta):
knockback = knockback.move_toward(Vector2.ZERO, FRICTION * delta)
knockback = move_and_slide(knockback)
match state:
IDLE:
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
seek_player()
WANDER:
pass
CHASE:
var player = playerDetectionZone.player
if player != null:
var direction = (player.global_position - global_position).normalized()
velocity = velocity.move_toward(direction * MAX_SPEED, ACCELERATION * delta)
else:
state = IDLE
if spriteOverlap.is_colliding():
velocity += spriteOverlap.get_push_vector() * delta * 400
velocity = move_and_slide(velocity)
func seek_player():
if playerDetectionZone.can_see_player():
state = CHASE
func _on_Hurtbox_area_entered(area):
stats.health -= area.damage
knockback = area.knockback_vector * 150
func _on_Stats_no_health():
queue_free()
var enemyDeathEffect = EnemyDeathEffect.instance()
get_parent().add_child(enemyDeathEffect)
enemyDeathEffect.global_position = global_position
```
And that's all for this entry
- Area2D root node
- and a collisionShape
Then attach a script to your Area2D. In this script, we're going to check if there are two sprites in the same position (overlapping), and if they are, one of them is going to receive a little push to separate them.
```
extends Area2D
func is_colliding():
var areas = get_overlapping_areas()
return areas.size() > 0
func get_push_vector():
var areas = get_overlapping_areas()
var push_vector = Vector2.ZERO
if is_colliding():
var area = areas[0]
push_vector = area.global_position.direction_to(global_position)
push_vector = push_vector.normalized()
return push_vector
```
For this to work, we also need to create a layer for this collision.
And then set it up to be used
Once the new Area2D scene is set up, instance it to your enemy nodes, and add their collision shapes
> I bet you think that's all, but you need to use those functions in your bat script for them to work
`onready var spriteOverlap = $SpriteOverlap`
and at the end of your physic_process:
```
if spriteOverlap.is_colliding():
velocity += spriteOverlap.get_push_vector() * delta * 400
velocity = move_and_slide(velocity)
```
In other words, your enemy script should be eventually something like this:
```
extends KinematicBody2D
const EnemyDeathEffect = preload("res://Effects/EnemyDeathEffect.tscn")
export var ACCELERATION = 300
export var MAX_SPEED = 50
export var FRICTION = 200
export var WANDER_TARGET_RANGE = 4
enum {
IDLE,
WANDER,
CHASE
}
var velocity = Vector2.ZERO
var knockback = Vector2.ZERO
var state = CHASE
onready var stats = $Stats
onready var playerDetectionZone = $PlayerDetectionZone
onready var spriteOverlap = $SpriteOverlap
func _physics_process(delta):
knockback = knockback.move_toward(Vector2.ZERO, FRICTION * delta)
knockback = move_and_slide(knockback)
match state:
IDLE:
velocity = velocity.move_toward(Vector2.ZERO, FRICTION * delta)
seek_player()
WANDER:
pass
CHASE:
var player = playerDetectionZone.player
if player != null:
var direction = (player.global_position - global_position).normalized()
velocity = velocity.move_toward(direction * MAX_SPEED, ACCELERATION * delta)
else:
state = IDLE
if spriteOverlap.is_colliding():
velocity += spriteOverlap.get_push_vector() * delta * 400
velocity = move_and_slide(velocity)
func seek_player():
if playerDetectionZone.can_see_player():
state = CHASE
func _on_Hurtbox_area_entered(area):
stats.health -= area.damage
knockback = area.knockback_vector * 150
func _on_Stats_no_health():
queue_free()
var enemyDeathEffect = EnemyDeathEffect.instance()
get_parent().add_child(enemyDeathEffect)
enemyDeathEffect.global_position = global_position
```
And that's all for this entry
No comments:
Post a Comment