feat: add projectile feature + refactor
This commit is contained in:
parent
874a03a5fa
commit
15dc6acf68
19 changed files with 187 additions and 134 deletions
|
|
@ -1,26 +0,0 @@
|
|||
extends CharacterBody3D
|
||||
class_name Bullet
|
||||
|
||||
var target : CharacterBody3D
|
||||
@export var speed : int = 20
|
||||
var bullet_damage : int = 1
|
||||
var start_position
|
||||
|
||||
func _ready() -> void:
|
||||
global_position = start_position
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if is_instance_valid(target):
|
||||
velocity = global_position.direction_to(target.global_position) * speed
|
||||
look_at(target.global_position)
|
||||
|
||||
move_and_slide()
|
||||
else:
|
||||
queue_free()
|
||||
|
||||
func _on_impact_body_entered(body: Node3D) -> void:
|
||||
if body == target:
|
||||
var enemy : Enemy = body
|
||||
enemy.take_damage(bullet_damage)
|
||||
queue_free()
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://oykrff3g74eo"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b788twwo1o6l2" path="res://Bullets/bullet.gd" id="1_p5eas"]
|
||||
[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_46820"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_r5o86"]
|
||||
radius = 0.1
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_dsts2"]
|
||||
radius = 0.12
|
||||
|
||||
[node name="Arrow" type="CharacterBody3D"]
|
||||
script = ExtResource("1_p5eas")
|
||||
speed = 10
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0715332, 0)
|
||||
shape = SubResource("SphereShape3D_r5o86")
|
||||
|
||||
[node name="Sprite3D" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0)
|
||||
billboard = 2
|
||||
texture = ExtResource("2_46820")
|
||||
|
||||
[node name="Impact" type="Area3D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="CollisionShape3D2" type="CollisionShape3D" parent="Impact"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0714111, 0)
|
||||
shape = SubResource("SphereShape3D_dsts2")
|
||||
debug_color = Color(0.926858, 0.237749, 0.335021, 0.42)
|
||||
|
||||
[connection signal="body_entered" from="Impact" to="." method="_on_impact_body_entered"]
|
||||
|
|
@ -2,84 +2,84 @@
|
|||
extends Node
|
||||
|
||||
|
||||
#Emitter : TowerButton.gd
|
||||
#Subscriber : World.gd
|
||||
signal tower_selected(towerType : Tower.TYPES)
|
||||
## [b]Emitter[/b] : [method TowerButton._ready][br]
|
||||
## [b]Subscriber[/b] : [method PlayerManager._init]
|
||||
signal tower_selected(towerType : Tower.TYPE)
|
||||
|
||||
|
||||
#Emitter :
|
||||
#Subscriber :
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] hero_icon.gd:
|
||||
signal tower_builded(tower : Tower)
|
||||
|
||||
|
||||
#Emitter : UpgradeButton.gd
|
||||
#Subscriber : tower.gd
|
||||
## [b]Emitter[/b] : [UpgradeButton][br]
|
||||
## [b]Subscriber[/b] : [Tower]
|
||||
signal tower_upgraded(tower_to_upgrade : String, upgrade : TowerUpgrade)
|
||||
|
||||
|
||||
#Emitter : cube.gd
|
||||
#Subscriber : progress_bar_cube_integrity.gd
|
||||
## [b]Emitter[/b] : [TheCube][br]
|
||||
## [b]Subscriber[/b] : cube_integrity.gd
|
||||
signal cube_integrity_changed(_value : int, _max_value : int)
|
||||
|
||||
|
||||
#Emitter : cube.gd
|
||||
#Subscriber : label_money.gd
|
||||
## [b]Emitter[/b] : [TheCube][br]
|
||||
## [b]Subscriber[/b] : label_money.gd
|
||||
signal money_changed(_value : int)
|
||||
|
||||
|
||||
#Emitter : cube.gd
|
||||
#Subscriber : label_team.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : label_team.gd
|
||||
signal tower_count_changed(_value : int)
|
||||
|
||||
|
||||
#Emitter : PlayerManager.gd
|
||||
#Subscriber : label_team.gd, label_tower_on_terrain.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : label_team.gd, label_tower_on_terrain.gd
|
||||
signal team_in_action_changed(_value : int)
|
||||
|
||||
#Emitter : PlayerManager.gd
|
||||
#Subscriber : label_tower_in_cube.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : label_tower_in_cube[TheCube]
|
||||
signal team_in_rest_changed(_value : int)
|
||||
|
||||
|
||||
|
||||
#Emitter : bullet.gd
|
||||
#Subscriber : bullet_container.gd
|
||||
signal bullet_shooted(_value : Bullet)
|
||||
## [b]Emitter[/b] : [Projectile][br]
|
||||
## [b]Subscriber[/b] : [code]null[/code]
|
||||
signal projectile_shooted(_value : Projectile)
|
||||
|
||||
|
||||
#Emitter : enemy.gd
|
||||
#Subscriber : cube.gd
|
||||
## [b]Emitter[/b] : [Enemy][br]
|
||||
## [b]Subscriber[/b] : [TheCube]
|
||||
signal money_received(_value : int)
|
||||
|
||||
|
||||
#Emitter : world.gd
|
||||
#Subscriber : cube.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : [TheCube]
|
||||
signal money_spent(_value : int)
|
||||
|
||||
#Emitter : spawner.gd
|
||||
#Subscriber : cube.gd
|
||||
## [b]Emitter[/b] : [WaveManager][br]
|
||||
## [b]Subscriber[/b] : [TheCube]
|
||||
signal player_has_won()
|
||||
|
||||
#Emitter : WaveManager.gd
|
||||
#Subscriber : cube.gd
|
||||
## [b]Emitter[/b] : [TheCube][br]
|
||||
## [b]Subscriber[/b] : [WaveManager]
|
||||
signal player_defeated()
|
||||
|
||||
#Emitter : PlayerManager.gd
|
||||
#Subscriber : game_menu.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : [code]null[/code]
|
||||
signal open_shop()
|
||||
|
||||
#Emitter : PlayerManager.gd
|
||||
#Subscriber : game_menu.gd
|
||||
## [b]Emitter[/b] : [PlayerManager][br]
|
||||
## [b]Subscriber[/b] : [code]null[/code]
|
||||
signal close_shop()
|
||||
|
||||
#Emitter : tower.gd
|
||||
#Subscriber : tower button.gd
|
||||
## [b]Emitter[/b] : [Tower][br]
|
||||
## [b]Subscriber[/b] : [TowerButton]
|
||||
signal energy_has_changed(tower : Tower)
|
||||
|
||||
#Emitter : WaveManager.gd
|
||||
#Subscriber : gui.gd
|
||||
signal allowedTowerHasChange(allowedTowers : Array[Tower.TYPES])
|
||||
## [b]Emitter[/b] : [WaveManager], [Level][br]
|
||||
## [b]Subscriber[/b] : gui.gd
|
||||
signal allowedTowerHasChange(allowedTowers : Array[Tower.TYPE])
|
||||
|
||||
#Emitter : WaveManager.gd
|
||||
#Subscriber : gui.gd
|
||||
## [b]Emitter[/b] : [WaveManager][br]
|
||||
## [b]Subscriber[/b] : [code]null[/code]
|
||||
signal waveHasChange(waveNumber : int)
|
||||
|
|
|
|||
74
Projectiles/Projectile.gd
Normal file
74
Projectiles/Projectile.gd
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
extends CharacterBody3D
|
||||
class_name Projectile
|
||||
|
||||
const ENEMY : int = 1
|
||||
const ALLY : int = 2
|
||||
|
||||
const MINIMUN_AREA : float = .1
|
||||
|
||||
@export var speed : int = 20
|
||||
@export_range(MINIMUN_AREA, 1000) var radius : float = MINIMUN_AREA
|
||||
@export var isAOE := false
|
||||
@export_flags("Enemies", "Alliés") var allowedTargets : int = ENEMY
|
||||
|
||||
|
||||
@onready var projectileArea : CollisionShape3D = $Impact/ProjectileArea
|
||||
@onready var projectileSize : CollisionShape3D = $Impact/ProjectileSize
|
||||
|
||||
|
||||
var target : PhysicsBody3D
|
||||
var damage : int = 1
|
||||
var bodiesInRange : Array[Node3D]
|
||||
var enemiesInRange : Array[Enemy]
|
||||
var allyInRange : Array[Tower]
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
enemiesInRange.append(target)
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if is_instance_valid(target):
|
||||
velocity = global_position.direction_to(target.global_position) * speed
|
||||
look_at(target.global_position)
|
||||
|
||||
move_and_slide()
|
||||
else:
|
||||
queue_free()
|
||||
|
||||
|
||||
func onBodyEnteredDamageArea(body: Node3D) -> void:
|
||||
print(body.get_class())
|
||||
if isAOE && targetable(body):
|
||||
if body is Enemy:
|
||||
enemiesInRange.append(body)
|
||||
if body is Tower:
|
||||
allyInRange.append(body)
|
||||
|
||||
|
||||
func OnBodyExitedDamageArea(body: Node3D) -> void:
|
||||
if body is Enemy:
|
||||
enemiesInRange.erase(body)
|
||||
if body is Tower:
|
||||
allyInRange.erase(body)
|
||||
|
||||
|
||||
func onBodyCollideWithProjectile(body : Node3D) -> void:
|
||||
if body == target:
|
||||
resolveDamages()
|
||||
|
||||
|
||||
func targetable(body: Node3D) -> bool:
|
||||
if body is Enemy:
|
||||
return ENEMY & allowedTargets
|
||||
if body is Tower:
|
||||
return ALLY & allowedTargets
|
||||
|
||||
return false
|
||||
|
||||
|
||||
func resolveDamages() -> void:
|
||||
print(enemiesInRange)
|
||||
for enemy in enemiesInRange:
|
||||
enemy.take_damage(damage)
|
||||
queue_free()
|
||||
42
Projectiles/projectile.tscn
Normal file
42
Projectiles/projectile.tscn
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
[gd_scene load_steps=5 format=3 uid="uid://oykrff3g74eo"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b788twwo1o6l2" path="res://Projectiles/Projectile.gd" id="1_ggq0q"]
|
||||
[ext_resource type="Texture2D" uid="uid://dqyhhvxpwtpsy" path="res://Assets/Emotes/emote_star.png" id="2_08w86"]
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_r5o86"]
|
||||
radius = 0.1
|
||||
|
||||
[sub_resource type="SphereShape3D" id="SphereShape3D_dsts2"]
|
||||
radius = 1.5
|
||||
|
||||
[node name="Projectile" type="CharacterBody3D"]
|
||||
script = ExtResource("1_ggq0q")
|
||||
speed = 10
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
shape = SubResource("SphereShape3D_r5o86")
|
||||
|
||||
[node name="Sprite3D" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(2.5, 0, 0, 0, 2.5, 0, 0, 0, 2.5, 0, 0, 0)
|
||||
billboard = 2
|
||||
texture = ExtResource("2_08w86")
|
||||
|
||||
[node name="HitBox" type="Area3D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="ProjectileSize" type="CollisionShape3D" parent="HitBox"]
|
||||
shape = SubResource("SphereShape3D_dsts2")
|
||||
debug_color = Color(0.926858, 0.237749, 0.335021, 0.42)
|
||||
|
||||
[node name="DamageArea" type="Area3D" parent="."]
|
||||
collision_layer = 4
|
||||
collision_mask = 4
|
||||
|
||||
[node name="ProjectileArea" type="CollisionShape3D" parent="DamageArea"]
|
||||
shape = SubResource("SphereShape3D_dsts2")
|
||||
debug_color = Color(0.926858, 0.237749, 0.335021, 0.42)
|
||||
|
||||
[connection signal="body_entered" from="HitBox" to="." method="onBodyCollideWithProjectile" flags=3]
|
||||
[connection signal="body_entered" from="DamageArea" to="." method="onBodyEnteredDamageArea"]
|
||||
[connection signal="body_exited" from="DamageArea" to="." method="OnBodyExitedDamageArea"]
|
||||
|
|
@ -4,7 +4,7 @@ class_name Level
|
|||
|
||||
@export var waves : Array[Wave]
|
||||
@export var auto_start : bool = false
|
||||
@export var allowedTowers : Array[Tower.TYPES] : set = allowedTowersHasChanged
|
||||
@export var allowedTowers : Array[Tower.TYPE] : set = allowedTowersHasChanged
|
||||
|
||||
|
||||
func allowedTowersHasChanged(value) -> void:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ enum STATE { IDLE, PLACING }
|
|||
var _state := STATE.IDLE
|
||||
|
||||
@onready var selected_tower : Tower = null
|
||||
var selected_tower_type : Tower.TYPES = Tower.TYPES.NONE
|
||||
var selected_tower_type : Tower.TYPE = Tower.TYPE.NONE
|
||||
|
||||
@onready var cam : Camera3D = $"../Camera3D"
|
||||
@onready var the_cube : TheCube = %TheCube
|
||||
|
|
@ -114,13 +114,13 @@ func build_tower() -> void:
|
|||
emitTeamChanges()
|
||||
|
||||
|
||||
func selectTower(towerType : Tower.TYPES):
|
||||
func selectTower(towerType : Tower.TYPE):
|
||||
if selected_tower && not selected_tower.builded:
|
||||
selected_tower.visible = false
|
||||
|
||||
if towerType == selected_tower_type:
|
||||
selected_tower = null
|
||||
selected_tower_type = Tower.TYPES.NONE
|
||||
selected_tower_type = Tower.TYPE.NONE
|
||||
_state = STATE.IDLE
|
||||
return
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
[node name="Pierre" instance=ExtResource("1_7f7qx")]
|
||||
script = ExtResource("1_v16mf")
|
||||
tower_name = "Pierre"
|
||||
tower_type = 1
|
||||
icone = ExtResource("3_odfqx")
|
||||
bio = null
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ class_name TowerListResource
|
|||
|
||||
@export var towers : Array[TowerResource] : set = towersHasChanged
|
||||
|
||||
func getTowerSceneById(towerType : Tower.TYPES) -> PackedScene :
|
||||
func getTowerSceneById(towerType : Tower.TYPE) -> PackedScene :
|
||||
var towerIndex := towers.find_custom(func(towerResource): return towerResource.towerType == towerType)
|
||||
return towers[towerIndex].towerScene
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ extends Resource
|
|||
class_name TowerResource
|
||||
|
||||
@export var towerScene : PackedScene : set = towerSceneHasChanged
|
||||
var towerType : Tower.TYPES
|
||||
var towerType : Tower.TYPE
|
||||
|
||||
func towerSceneHasChanged(value) -> void :
|
||||
towerScene = value
|
||||
|
|
|
|||
|
|
@ -1,19 +1,20 @@
|
|||
extends StaticBody3D
|
||||
class_name Tower
|
||||
|
||||
# DANGER NONE Should always be first
|
||||
enum TYPES { NONE, PIERRE, ALINE, MAXENCE, VICTORIA, EVAN, ALEX, GERALDINE }
|
||||
|
||||
var bullet : PackedScene = preload("res://Bullets/bullet.tscn")
|
||||
@export var tower_name : String = "Pierre"
|
||||
@export var tower_type : TYPES
|
||||
# DANGER "NONE" Should always be first
|
||||
enum TYPE { NONE, PIERRE, ALINE, MAXENCE, VICTORIA, EVAN, ALEX, GERALDINE }
|
||||
|
||||
var projectile : PackedScene = preload("res://Projectiles/projectile.tscn")
|
||||
@export var tower_name : String = "None"
|
||||
@export var tower_type : TYPE
|
||||
@export var icone : Texture2D
|
||||
@export var bio : String
|
||||
|
||||
@export var price : int = 100
|
||||
|
||||
@export_group("Attack")
|
||||
@export var bullet_damage : int = 1
|
||||
@export var projectile_damage : int = 1
|
||||
@export var action_cooldown : float = 1.5:
|
||||
set(value):
|
||||
action_cooldown = clamp(value, 0.3, 999)
|
||||
|
|
@ -97,19 +98,16 @@ func _process(delta: float) -> void:
|
|||
shoot()
|
||||
can_shoot = false
|
||||
$Cooldown.start()
|
||||
else:
|
||||
for i in $BulletContainer.get_child_count():
|
||||
$BulletContainer.get_child(i).queue_free()
|
||||
|
||||
|
||||
func shoot() -> void:
|
||||
energy -= energy_cost
|
||||
|
||||
var temp_bullet : Bullet = bullet.instantiate()
|
||||
temp_bullet.target = current
|
||||
temp_bullet.bullet_damage = bullet_damage
|
||||
temp_bullet.start_position = $Aim.global_position
|
||||
EventBus.bullet_shooted.emit(temp_bullet)
|
||||
var projectile : Projectile = projectile.instantiate()
|
||||
projectile.target = current
|
||||
projectile.damage = projectile_damage
|
||||
projectile.global_position = $Aim.global_position
|
||||
EventBus.projectile_shooted.emit(projectile)
|
||||
|
||||
|
||||
func resting() -> void:
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ collision_mask = 4
|
|||
script = ExtResource("1_egfuc")
|
||||
icone = ExtResource("2_mnaic")
|
||||
bio = "Aime se promener dans l'herbe et manger des framboises. Sa petite bouille la rend trop mignonne."
|
||||
bullet_damage = 5
|
||||
projectile_damage = 5
|
||||
tower_shop = Array[ExtResource("3_5dr1v")]([ExtResource("3_jv31o"), ExtResource("4_5dr1v")])
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
|
||||
|
|
@ -39,8 +39,6 @@ shape = SubResource("SphereShape3D_pajr1")
|
|||
[node name="Aim" type="Marker3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.572046, 0)
|
||||
|
||||
[node name="BulletContainer" type="Node" parent="."]
|
||||
|
||||
[node name="Cooldown" type="Timer" parent="."]
|
||||
wait_time = 1.5
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ var towerListResource := preload("res://Towers/towers.tres")
|
|||
|
||||
@onready var buttonContainer = $HBoxContainer/ControlPanelBase/MarginContainer/GridContainer
|
||||
|
||||
var allowedTowers : Array[Tower.TYPES]
|
||||
var allowedTowers : Array[Tower.TYPE]
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
|
|
@ -30,7 +30,7 @@ func _on_button_quit_game_pressed() -> void:
|
|||
get_tree().quit()
|
||||
|
||||
|
||||
func allowedTowerHasChange(allowedTowers : Array[Tower.TYPES]) -> void:
|
||||
func allowedTowerHasChange(allowedTowers : Array[Tower.TYPE]) -> void:
|
||||
self.allowedTowers = allowedTowers
|
||||
if is_node_ready():
|
||||
addTowerButtonNodes()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
extends Button
|
||||
class_name TowerButton
|
||||
|
||||
var towerType : Tower.TYPES
|
||||
var towerType : Tower.TYPE
|
||||
|
||||
func _ready() -> void:
|
||||
#font_outline_color = Color.YELLOW
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@ func _ready() -> void:
|
|||
resetApp()
|
||||
|
||||
towerSelector.clear()
|
||||
towerSelector.max_columns = Tower.TYPES.size()
|
||||
for towerType : String in Tower.TYPES:
|
||||
if Tower.TYPES.NONE != Tower.TYPES.get(towerType):
|
||||
towerSelector.max_columns = Tower.TYPE.size()
|
||||
for towerType : String in Tower.TYPE:
|
||||
if Tower.TYPE.NONE != Tower.TYPE.get(towerType):
|
||||
towerSelector.add_item(" " + towerType + " ")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
extends Node3D
|
||||
|
||||
func _ready() -> void:
|
||||
EventBus.bullet_shooted.connect(_on_EventBus_bullet_shooted)
|
||||
EventBus.projectile_shooted.connect(_on_EventBus_projectile_shooted)
|
||||
|
||||
|
||||
func _on_EventBus_bullet_shooted(bullet : Bullet) -> void:
|
||||
add_child(bullet)
|
||||
func _on_EventBus_projectile_shooted(projectile : Projectile) -> void:
|
||||
add_child(projectile)
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ enabled=PackedStringArray("res://addons/LevelEditor/plugin.cfg", "res://addons/s
|
|||
|
||||
folder_colors={
|
||||
"res://Assets/": "green",
|
||||
"res://Bullets/": "orange",
|
||||
"res://Globals/": "blue",
|
||||
"res://Projectiles/": "orange",
|
||||
"res://Scripts/": "blue",
|
||||
"res://Tiles/": "orange",
|
||||
"res://Towers/": "orange",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue