fuzzyworld

godot-shooter / commit

Ship is now shooting automatically at the closest enemy.

f398dcb9c96d5b7084eaedf144945b74ac1792c7 · Pavel Safronov · 2023-11-01 21:03:26 -0700 · parents f108d95364af

Ship is now shooting automatically at the closest enemy.
Enemies now hurt the player for 2 points and self destruct when they contact the player.
 Bullet.gd     |  3 ++-
 Enemy.gd      | 20 ++++++++++++--------
 Enemy.tscn    |  1 +
 HUD.tscn      | 14 ++++++++------
 Player.gd     | 25 ++++++++++++++++++++-----
 Player.tscn   | 57 +++++++++++++++++++++++++++++++++++++++------------------
 World.gd      | 24 +++++++++++++++++++++---
 World.tscn    | 16 ++++++++++------
 project.godot | 22 ++++++++++++++++++++++
 9 files changed, 135 insertions(+), 47 deletions(-)

diff --git a/Bullet.gd b/Bullet.gd
index b3a5f8e..1cb6e6a 100644
--- a/Bullet.gd
+++ b/Bullet.gd
@@ -1,8 +1,9 @@
 extends Area2D
+class_name Bullet
 
 const Utils = preload("res://Utils.gd")
 const SmallExplosion = preload("res://SmallExplosion.tscn")
-export var lifetime_seconds = 2
+export var lifetime_seconds = .75
 export var speed = 300
 
 func _ready() -> void:
diff --git a/Enemy.gd b/Enemy.gd
index b775a39..1dc0986 100644
--- a/Enemy.gd
+++ b/Enemy.gd
@@ -1,4 +1,5 @@
 extends KinematicBody2D
+class_name Enemy
 
 onready var ray_cast_2d: RayCast2D = $RayCast2D
 const Utils = preload("res://Utils.gd")
@@ -20,13 +21,14 @@ func _process(_delta: float) -> void:
 	$Graphics/Alive/Container/HealthLabel.text = "%s / %s" % [health, max_health]
 	$Graphics/Alive/Container.global_rotation = 0
 
-func _physics_process(_delta: float) -> void:
+func _physics_process(delta: float) -> void:
 	if dead:
 		return
 	var players = get_tree().get_nodes_in_group("player")
-	var player: KinematicBody2D = players[0]
+	var player: Player = players[0]
+	if player.dead:
+		return
 	var dist_to_player = global_position.distance_to(player.global_position)
-
 	var dir_to_player = global_position.direction_to(player.global_position)
 	var angle_to_player = dir_to_player.angle() + PI / 2.0
 	var vel = dir_to_player * move_speed
@@ -34,11 +36,13 @@ func _physics_process(_delta: float) -> void:
 	velocity = move_and_slide(vel)
 	
 	var ray_length = ray_cast_2d.cast_to.length()
-	if ray_cast_2d.is_colliding() and ray_cast_2d.get_collider() == player and dist_to_player < (ray_length + 5):
-		player.hurt()
-		var push = to_global(ray_cast_2d.cast_to) - to_global(Vector2.ZERO)
-		player.position += (push * 2)
-		player.velocity = player.move_and_slide(player.velocity)
+	if ray_cast_2d.is_colliding():
+		if ray_cast_2d.get_collider() == player and dist_to_player < (ray_length + 5):
+			player.hurt(2)
+			var explosion = Explosion.instance()
+			explosion.transform = transform
+			get_parent().add_child(explosion)
+			kill()
 
 func hurt():
 	if dead:
diff --git a/Enemy.tscn b/Enemy.tscn
index ab69fcb..0cc1254 100644
--- a/Enemy.tscn
+++ b/Enemy.tscn
@@ -26,4 +26,5 @@ visible = false
 polygon = PoolVector2Array( 0, -23, -7, 5, -12, 9, -19, 9, -23, 14, -23, 19, -19, 23, -14, 23, -9, 18, -9, 14, -10, 12, -6, 9, 0, 15, 6, 9, 10, 12, 9, 14, 9, 19, 13, 23, 18, 23, 23, 18, 23, 14, 19, 10, 13, 10, 7, 5 )
 
 [node name="RayCast2D" type="RayCast2D" parent="."]
+enabled = true
 cast_to = Vector2( 0, -50 )
diff --git a/HUD.tscn b/HUD.tscn
index 22b05c7..9f3202a 100644
--- a/HUD.tscn
+++ b/HUD.tscn
@@ -4,7 +4,9 @@
 [ext_resource path="res://HUD.gd" type="Script" id=2]
 
 [sub_resource type="DynamicFont" id=1]
-size = 64
+size = 100
+outline_size = 1
+outline_color = Color( 1, 0, 0, 1 )
 font_data = ExtResource( 1 )
 
 [sub_resource type="Theme" id=2]
@@ -20,13 +22,13 @@ script = ExtResource( 2 )
 anchor_right = 1.0
 
 [node name="ScoreText" type="Label" parent="HBoxContainer"]
-margin_right = 192.0
-margin_bottom = 74.0
+margin_right = 296.0
+margin_bottom = 115.0
 text = "Score: "
 
 [node name="Score" type="Label" parent="HBoxContainer"]
-margin_left = 196.0
-margin_right = 278.0
-margin_bottom = 74.0
+margin_left = 300.0
+margin_right = 426.0
+margin_bottom = 115.0
 text = "100"
 uppercase = true
diff --git a/Player.gd b/Player.gd
index 6c672e1..b7aeab2 100644
--- a/Player.gd
+++ b/Player.gd
@@ -1,7 +1,8 @@
 extends KinematicBody2D
+class_name Player
 
 export var move_speed = 200
-export var health = 8
+export var health = 10
 export var max_health = 10
 export var shot_period_seconds = .1
 export var bullet: PackedScene
@@ -11,7 +12,8 @@ var PopupControl = preload("res://Popup.tscn")
 var dead = false
 var velocity = Vector2.ZERO
 var can_fire = true
-
+var destination: Vector2
+var is_destination_set = false
 
 func _process(_delta: float) -> void:
 	if Input.is_action_just_pressed("exit"):
@@ -28,7 +30,6 @@ func _process(_delta: float) -> void:
 	$Graphics/Alive/Control/HealthLabel.text = "%s / %s" % [health, max_health]
 	$Graphics/Alive/Control.global_rotation = 0
 
-
 func _physics_process(delta: float) -> void:
 	if dead:
 		return
@@ -54,10 +55,10 @@ func kill():
 	dead = true
 	$Graphics/Dead.show()
 	$Graphics/Alive.hide()
-	$CanvasLayer/DeathScreen.show()
+	$CanvasLayer/CenterContainer/DeathScreen.show()
 	z_index = -1
 
-func hurt():
+func hurt(damage_amount: int = 1):
 	if dead:
 		return
 	health -= 1
@@ -74,5 +75,19 @@ func shoot():
 	owner.add_child(b)
 	b.transform = $Barrel.global_transform
 	
+func shoot_at(pos: Vector2):
+	if !can_fire:
+		return
+	can_fire = false
+	$ShotTimer.wait_time = shot_period_seconds
+	$ShotTimer.start()
+	var b = bullet.instance() as Bullet
+	owner.add_child(b)
+	b.global_position = global_position
+	b.global_rotation = global_position.angle_to_point(pos) + PI / 2.0
+	
 func allow_fire():
 	can_fire = true
+
+func _on_Button_pressed() -> void:
+	restart()
diff --git a/Player.tscn b/Player.tscn
index ba55048..79ae907 100644
--- a/Player.tscn
+++ b/Player.tscn
@@ -1,7 +1,7 @@
 [gd_scene load_steps=5 format=2]
 
 [ext_resource path="res://assets/kenney_simple-space/PNG/Default/ship_C.png" type="Texture" id=1]
-[ext_resource path="res://assets/kenney_simple-space/PNG/Default/star_large.png" type="Texture" id=2]
+[ext_resource path="res://Explosion.tscn" type="PackedScene" id=2]
 [ext_resource path="res://Player.gd" type="Script" id=3]
 [ext_resource path="res://Bullet.tscn" type="PackedScene" id=4]
 
@@ -30,36 +30,56 @@ text = "HEALTH"
 align = 1
 uppercase = true
 
-[node name="Dead" type="Sprite" parent="Graphics"]
+[node name="Dead" type="Node2D" parent="Graphics"]
 visible = false
-texture = ExtResource( 2 )
+
+[node name="Explosion" parent="Graphics/Dead" instance=ExtResource( 2 )]
 
 [node name="CanvasLayer" type="CanvasLayer" parent="."]
+layer = 100
+follow_viewport_enable = true
 
-[node name="DeathScreen" type="Control" parent="CanvasLayer"]
-visible = false
-margin_right = 40.0
-margin_bottom = 40.0
+[node name="CenterContainer" type="CenterContainer" parent="CanvasLayer"]
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_left = -1.0
+margin_right = -201.0
+margin_bottom = -200.0
+mouse_filter = 2
 
-[node name="ColorRect" type="ColorRect" parent="CanvasLayer/DeathScreen"]
+[node name="DeathScreen" type="Control" parent="CanvasLayer/CenterContainer"]
+visible = false
+margin_left = 412.0
+margin_top = 200.0
+margin_right = 412.0
+margin_bottom = 200.0
+mouse_filter = 2
+size_flags_horizontal = 5
+size_flags_vertical = 5
+
+[node name="ColorRect" type="ColorRect" parent="CanvasLayer/CenterContainer/DeathScreen"]
 margin_right = 40.0
 margin_bottom = 40.0
 color = Color( 0, 0, 0, 1 )
 
-[node name="Panel" type="Panel" parent="CanvasLayer/DeathScreen"]
-margin_right = 40.0
-margin_bottom = 40.0
+[node name="Panel" type="Panel" parent="CanvasLayer/CenterContainer/DeathScreen"]
+margin_right = 199.0
+margin_bottom = 115.0
+mouse_filter = 2
 
-[node name="Label" type="Label" parent="CanvasLayer/DeathScreen/Panel"]
-margin_right = 73.0
+[node name="Label" type="Label" parent="CanvasLayer/CenterContainer/DeathScreen/Panel"]
+anchor_right = 1.0
+margin_top = 50.0
 margin_bottom = 14.0
 text = "Game Over"
+align = 1
+valign = 1
 
-[node name="Button" type="Button" parent="CanvasLayer/DeathScreen/Panel"]
-margin_left = 14.0
-margin_top = 19.0
-margin_right = 26.0
-margin_bottom = 39.0
+[node name="Button" type="Button" parent="CanvasLayer/CenterContainer/DeathScreen/Panel"]
+anchor_top = 1.0
+anchor_right = 1.0
+anchor_bottom = 1.0
+margin_top = -20.0
 text = "Restart"
 
 [node name="Camera2D" type="Camera2D" parent="."]
@@ -84,4 +104,5 @@ __meta__ = {
 "_gizmo_extents_": 14.2
 }
 
+[connection signal="pressed" from="CanvasLayer/CenterContainer/DeathScreen/Panel/Button" to="." method="_on_Button_pressed"]
 [connection signal="timeout" from="ShotTimer" to="." method="allow_fire"]
diff --git a/World.gd b/World.gd
index ad1285f..22c3ba6 100644
--- a/World.gd
+++ b/World.gd
@@ -2,7 +2,7 @@ extends Node2D
 
 const Utils = preload("res://Utils.gd")
 const Enemy = preload("res://Enemy.tscn")
-export var enemy_count = 2
+export var enemy_count = 4
 var destination: Vector2
 var is_destination_set = false
 
@@ -25,10 +25,11 @@ func add_new_enemy(should_be_visible: bool = false) -> void:
 	var enemy = Enemy.instance()
 	enemy.connect("enemy_killed", self, "_on_enemy_killed")
 	enemy.position = pos
+	enemy.add_to_group("enemies")
 	add_child(enemy)
 
 func _process(delta: float) -> void:
-	if Input.is_action_just_pressed("click"):
+	if Input.is_action_just_pressed("click") and !$Player.dead:
 		var pos = get_global_mouse_position()
 		destination = pos
 		is_destination_set = true
@@ -42,7 +43,24 @@ func _process(delta: float) -> void:
 		$Destination.visible = true
 	else:
 		$Destination.visible = false
-
+		$Player.velocity = Vector2.ZERO
 
 func _on_Destination_body_entered(body: Node) -> void:
 	is_destination_set = false
+
+func sort_enemies_ascending_distance(a: Enemy,b: Enemy):
+	var distA = (a.global_position - $Player.global_position).length()
+	var distB = (b.global_position - $Player.global_position).length()
+	if distA < distB:
+		return true
+	return false
+
+func _on_ShootTimer_timeout() -> void:
+	if $Player.dead:
+		return
+	var enemies = get_tree().get_nodes_in_group("enemies")
+	if enemies.size() > 0:
+		enemies.sort_custom(self, "sort_enemies_ascending_distance")
+		var closest_enemy: Enemy = enemies[0]
+		$Player.shoot_at(closest_enemy.global_position)
+		
diff --git a/World.tscn b/World.tscn
index 3691585..79325f2 100644
--- a/World.tscn
+++ b/World.tscn
@@ -11,7 +11,6 @@ radius = 29.0172
 
 [node name="World" type="Node2D"]
 script = ExtResource( 4 )
-enemy_count = 4
 
 [node name="CanvasLayer2" type="CanvasLayer" parent="."]
 
@@ -39,17 +38,22 @@ __meta__ = {
 [node name="Player" parent="." groups=["player"] instance=ExtResource( 2 )]
 position = Vector2( 513, 302 )
 
-[node name="CanvasLayer" type="CanvasLayer" parent="."]
-
-[node name="HUD" parent="CanvasLayer" instance=ExtResource( 3 )]
-
 [node name="Destination" type="Area2D" parent="."]
 
 [node name="XSprite" type="Sprite" parent="Destination"]
-modulate = Color( 1, 0, 0, 1 )
+modulate = Color( 0.0784314, 0, 1, 1 )
 texture = ExtResource( 1 )
 
 [node name="CollisionShape2D" type="CollisionShape2D" parent="Destination"]
 shape = SubResource( 1 )
 
+[node name="CanvasLayer" type="CanvasLayer" parent="."]
+
+[node name="HUD" parent="CanvasLayer" instance=ExtResource( 3 )]
+
+[node name="ShootTimer" type="Timer" parent="."]
+process_mode = 0
+autostart = true
+
 [connection signal="body_entered" from="Destination" to="." method="_on_Destination_body_entered"]
+[connection signal="timeout" from="ShootTimer" to="." method="_on_ShootTimer_timeout"]
diff --git a/project.godot b/project.godot
index 40b2e69..55ff5e5 100644
--- a/project.godot
+++ b/project.godot
@@ -8,6 +8,28 @@
 
 config_version=4
 
+_global_script_classes=[ {
+"base": "Area2D",
+"class": "Bullet",
+"language": "GDScript",
+"path": "res://Bullet.gd"
+}, {
+"base": "KinematicBody2D",
+"class": "Enemy",
+"language": "GDScript",
+"path": "res://Enemy.gd"
+}, {
+"base": "KinematicBody2D",
+"class": "Player",
+"language": "GDScript",
+"path": "res://Player.gd"
+} ]
+_global_script_class_icons={
+"Bullet": "",
+"Enemy": "",
+"Player": ""
+}
+
 [application]
 
 config/name="shooter"