Skip to content

Commit

Permalink
feat: Introduced fleets and enemy ship formations
Browse files Browse the repository at this point in the history
  • Loading branch information
simone-lungarella authored and Lincoln-Ab committed Jul 20, 2024
1 parent 1e001f4 commit dd83faf
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 86 deletions.
28 changes: 28 additions & 0 deletions assets/json_data/json_wave_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"formations": [
{
"formation_name": "x",
"odds": 1.0,
"steps": {
"0": [
1,
2,
5,
7
],
"1": [
3,
4,
5,
7
],
"2": [
7,
8,
5,
7
]
}
}
]
}
6 changes: 6 additions & 0 deletions scenes/enemy/Fleet.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[gd_scene load_steps=2 format=3 uid="uid://ri0gdlnfdj42"]

[ext_resource type="Script" path="res://scripts/fleet.gd" id="1_eboqq"]

[node name="Fleet" type="Area2D"]
script = ExtResource("1_eboqq")
40 changes: 29 additions & 11 deletions scripts/enemy/enemy.gd
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ extends Area2D
@onready var animated_sprite_2d = $AnimatedSprite2D
@onready var collision_shape_2d = $CollisionShape2D

const ENEMY_REWARD: PackedScene = preload("res://scenes/enemy/Rewards.tscn")
const BULLET: PackedScene = preload("res://scenes/enemy/EnemyBullet.tscn")
const ENEMY_SHOOT_SFX = preload("res://assets/audio/enemy_shoot.wav")


class Animations:
const IDLE := "idle"
const DEATH := "death"


const BULLET: PackedScene = preload("res://scenes/enemy/EnemyBullet.tscn")
const ENEMY_SHOOT = preload("res://assets/audio/enemy_shoot.wav")

signal death(enemy_name: String, enemy_pos: Vector2)
signal shoot(bullet: PackedScene, direction: float, location: Vector2, audio_clip: AudioStream)

var _enemy_stats = StaticData.enemy_data[Enums.EnemyType.keys()[enemy_type]]
var _health: int
Expand All @@ -24,6 +24,13 @@ var _burst: int
var _rate: float
var _ammo_count: int

var direction: Vector2 = Vector2.DOWN


func init(steps: Array):
print(steps)
pass


func _ready():
animated_sprite_2d.animation = Animations.IDLE
Expand All @@ -36,8 +43,7 @@ func _ready():


func _physics_process(delta):
position += Vector2.DOWN * _velocity * delta

# position += Vector2.DOWN * 35 * delta
if _can_shoot:
var space_state = get_world_2d().direct_space_state
var start = self.position
Expand All @@ -51,10 +57,18 @@ func _physics_process(delta):
func get_hurt(damage: int):
_health -= damage
if _health <= 0:
collision_shape_2d.set_deferred("disabled", true)
var enemy_name = Enums.EnemyType.keys()[enemy_type]
death.emit(enemy_name, self.position)
animated_sprite_2d.play(Animations.DEATH)
_on_enemy_death()


func _on_enemy_death():
collision_shape_2d.set_deferred("disabled", true)
var reward = ENEMY_REWARD.instantiate()
reward.position = position
reward.init_reward(Enums.EnemyType.keys()[enemy_type])
call_deferred("add_child", reward)
SceneManager.on_enemy_death()
collision_shape_2d.set_deferred("disabled", true)
animated_sprite_2d.play(Animations.DEATH)


func _on_body_entered(body):
Expand All @@ -71,7 +85,11 @@ func _on_animated_sprite_2d_animation_finished():

func _shoot():
_can_shoot = false
shoot.emit(BULLET, rotation, position, ENEMY_SHOOT)
var spawned_bullet = BULLET.instantiate()
get_parent().add_child(spawned_bullet)
spawned_bullet.rotation = rotation
spawned_bullet.position = position
SoundManager.play_sound_effect_random_pitch(ENEMY_SHOOT_SFX)

if _burst > 0:
_ammo_count -= 1
Expand Down
112 changes: 48 additions & 64 deletions scripts/enemy/nemesis.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,88 +3,72 @@ extends Node
##
## Every logic that involve enemy attacks will be handled here.

const ENEMY_SHIP: PackedScene = preload("res://scenes/enemy/Enemy.tscn")
const ENEMY_REWARD: PackedScene = preload("res://scenes/enemy/Rewards.tscn")
const FLEET: PackedScene = preload("res://scenes/enemy/Fleet.tscn")
const NUM_SPAWN_COLUMNS := 5
const NUM_SPAWN_ROWS := 3

var level_name: String
var enemies_left: int
var waves: Array

var viewport: Vector2
var formations = StaticData.wave_data[Literals.Waves.FORMATIONS]


func clean_restart(l_name: String, wave_info: Array):
level_name = l_name
waves = wave_info

func clean_restart():
# Starting to spawn enemies
_start_wave(0)


## Setup wave to start spawning enemies.
func _start_wave(index: int):
if waves.size() == 0:
push_warning("No waves found in %s" % level_name)
pass
# TODO: decomment
# const START_DELAY: int = 3
# await get_tree().create_timer(START_DELAY, false).timeout

var delay: int = 3
await get_tree().create_timer(delay, false).timeout
print("[Nemesis] Wave %s started" % [index + 1])
# Pick random formation with given odds
var steps = select_random_formation()
# Select spawn area from center, left and right
var position: Enums.Position = Enums.Position.TOP
# randi_range(0, 2) as Enums.Position
# Spawn an enemy in each position indicated by the array index

var num_enemies: int = waves[index]
await _spawn_enemies(num_enemies)
print("[Nemesis] Wave %s spawning in position [%s]" % [index + 1, position])
await _spawn_enemies(steps, position)

if index + 1 >= waves.size():
print("[Nemesis] All enemies in %s spawned" % [level_name])
else:
print("[Nemesis] Wave [%s/%s] surpassed" % [index + 1, waves.size()])
_start_wave(index + 1)
_start_wave(index + 1)


## Handles the spawn of enemies.
func _spawn_enemies(num_enemies: int):
viewport = get_viewport().size
var enemies: int = 5
var interval_x: int = int(viewport.x / enemies)
var interval_y: int = 200

for index in range(0, num_enemies):
var random_waiting_time: int = randi_range(1, 5)
await get_tree().create_timer(random_waiting_time, false).timeout
var enemy = ENEMY_SHIP.instantiate()

var next_position_x: int = (index % (enemies - 1)) + 1
if index == enemies - 1:
interval_y += 200
var x_position = next_position_x * interval_x
enemy.position = Vector2(x_position, interval_y)
enemy.connect(Literals.Signals.DEATH, _on_enemy_death)
enemy.connect(Literals.Signals.SHOOT, _on_enemy_shoot)
add_child(enemy)
pass


func _on_enemy_death(enemy_name: String, enemy_pos: Vector2):
var reward = ENEMY_REWARD.instantiate()
reward.position = enemy_pos
reward.init_reward(enemy_name)
call_deferred("add_child", reward)
SceneManager.on_enemy_death()

enemies_left = enemies_left - 1
if enemies_left == 0:
SceneManager._on_enemies_defeated()


func _on_enemy_shoot(
bullet: PackedScene, direction: float, location: Vector2, audio_clip: AudioStream
):
var spawned_bullet = bullet.instantiate()
add_child(spawned_bullet)
spawned_bullet.rotation = direction
spawned_bullet.position = location
SoundManager.play_sound_effect_random_pitch(audio_clip)
func _spawn_enemies(steps, spawn_side: Enums.Position):
var fleet: Fleet = FLEET.instantiate()

var viewport = get_viewport().size

match spawn_side:
Enums.Position.TOP:
fleet.position = Vector2(0, -viewport.y / NUM_SPAWN_ROWS)
Enums.Position.LEFT:
fleet.position = Vector2(-viewport.x, 0)
Enums.Position.RIGHT:
fleet.position = Vector2(viewport.x, 0)

add_child(fleet)
fleet.init(steps)

const START_DELAY: int = 15
await get_tree().create_timer(START_DELAY, false).timeout


func reset():
for child in get_children():
child.queue_free()


func select_random_formation():
var choice = randf_range(0, 1)
var sum: float = 0
for formation in formations:
sum += formation[Literals.Waves.ODDS]
if choice <= sum:
return formation[Literals.Waves.STEPS]

push_error("No waves select, the total odds does not adds up to 100%")
return []
2 changes: 2 additions & 0 deletions scripts/enums.gd
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ enum GameEvent {
enum EnemyType {
SHIP,
}

enum Position { TOP, LEFT, RIGHT }
44 changes: 44 additions & 0 deletions scripts/fleet.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
extends Area2D
class_name Fleet

const ENEMY_SHIP: PackedScene = preload("res://scenes/enemy/Enemy.tscn")

const NUM_SPAWN_COLUMNS := 5
const NUM_SPAWN_ROWS := 3

var long_side: float
var short_side: float


func _ready():
# Get viewport size
var viewport = get_viewport().size

long_side = viewport.x
short_side = viewport.y / NUM_SPAWN_ROWS


func init(steps):
for index in range(0, steps.size()):
var enemy_steps = steps[String.num(index)]
var enemy = ENEMY_SHIP.instantiate()

enemy.position = get_ship_position(enemy_steps[0])
# enemy.init(enemy_steps)
add_child(enemy)


func _physics_process(delta):
position += Vector2.DOWN * 35 * delta


func get_ship_position(piece_index: int) -> Vector2:
var slot_size := Vector2(long_side / NUM_SPAWN_COLUMNS, short_side / NUM_SPAWN_ROWS)

# Piece position coordinates
var side_x := slot_size.x * (piece_index % NUM_SPAWN_COLUMNS)
var side_y := slot_size.y * int(piece_index / float(NUM_SPAWN_COLUMNS))

var pos_x := side_x + slot_size.x / 2
var pos_y := side_y + slot_size.y / 2
return Vector2(pos_x, pos_y)
7 changes: 7 additions & 0 deletions scripts/literals.gd
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,10 @@ class EnemyGun:
const AMMO_DAMAGE := "ammo_damage"
const AMMO_SPEED := "ammo_speed"
const AMMO_BURST := "ammo_burst"


## Information on enemy waves
class Waves:
const FORMATIONS := "formations"
const STEPS := "steps"
const ODDS := "odds"
2 changes: 1 addition & 1 deletion scripts/sound_manager/sound_manager.gd
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extends Node
## The [code]Sound Manager[/code] is the handler of the all sound effects and background music.

## Handles constants playing of music in a loop without interrupting whenever a new level is loaded.
## Handles constants playing of music in a loop without interruptions.
@onready var music_player = $MusicPlayer

## Number of AudioStreamPlayer that will be created as starting pool to execute Sound effects.
Expand Down
4 changes: 4 additions & 0 deletions scripts/static_data.gd
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ extends Node
var enemy_data = {}
var enemy_data_path = "res://assets/json_data/json_enemy_data.json"

var wave_data = {}
var wave_data_path = "res://assets/json_data/json_wave_data.json"


func _ready():
enemy_data = load_json_file(enemy_data_path)
wave_data = load_json_file(wave_data_path)


func load_json_file(file_path: String):
Expand Down
Loading

0 comments on commit dd83faf

Please sign in to comment.