fuzzyworld

godot-shooter / commit

A number of changes:

969fd5af4a7c661ebbf3d8215257c953ce6ffa79 · Pavel Safronov · 2023-11-06 15:42:56 -0800 · parents 57783b1a8e5a

A number of changes:
- bullets last longer
- player now has a shooting range, which defines how far away an enemy has to be to be targeted
- changed how the Enemy animation works, fixed it and separated some actions
- implemented a scheme in World where items (enemies, health and speed powerups) will replace themselves when one of them leaves
- if any items are too far from the player (screen radius * 2), then that item will be removed, and due to the above scheme, it will be replaced with a closer version
 Bullet.gd  |  2 +-
 Enemy.gd   |  5 +++-
 Enemy.tscn | 36 +++++----------------------
 Player.gd  |  1 +
 World.gd   | 82 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 World.tscn | 23 +-----------------
 6 files changed, 74 insertions(+), 75 deletions(-)

diff --git a/Bullet.gd b/Bullet.gd
index 17d71d2..4b70d42 100644
--- a/Bullet.gd
+++ b/Bullet.gd
@@ -3,7 +3,7 @@ class_name Bullet
 
 const Utils = preload("res://Utils.gd")
 const SmallExplosion = preload("res://SmallExplosion.tscn")
-export var lifetime_seconds = .75
+export var lifetime_seconds = 1.5
 export var speed = 300
 
 func _ready() -> void:
diff --git a/Enemy.gd b/Enemy.gd
index 8b39fe1..5360bd4 100644
--- a/Enemy.gd
+++ b/Enemy.gd
@@ -75,7 +75,7 @@ func kill():
 		return
 	dead = true
 	$Graphics/Alive.hide()
-	$CollisionPolygon2D.queue_free()
+	$CollisionPolygon2D.set_deferred("disabled", true)
 	var explosion = Explosion.instance()
 	explosion.connect("explosion_done", self, "_on_death_explosion_finished")
 	$Graphics.add_child(explosion)
@@ -90,3 +90,6 @@ func get_damage_point_on_body() -> Vector2:
 	var random_index = randi() % child_count
 	var random_child: Position2D = damage_points.get_child(random_index)
 	return random_child.position
+
+func remove_thyself():
+	queue_free()
diff --git a/Enemy.tscn b/Enemy.tscn
index 1dbbe0e..0df69a1 100644
--- a/Enemy.tscn
+++ b/Enemy.tscn
@@ -7,6 +7,9 @@
 
 [sub_resource type="Animation" id=1]
 length = 3.0
+
+[sub_resource type="Animation" id=2]
+resource_name = "fade_out"
 tracks/0/type = "value"
 tracks/0/path = NodePath(".:modulate")
 tracks/0/interp = 1
@@ -14,7 +17,7 @@ tracks/0/loop_wrap = true
 tracks/0/imported = false
 tracks/0/enabled = true
 tracks/0/keys = {
-"times": PoolRealArray( 0, 3 ),
+"times": PoolRealArray( 0, 1 ),
 "transitions": PoolRealArray( 1, 1 ),
 "update": 0,
 "values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
@@ -26,40 +29,13 @@ tracks/1/loop_wrap = true
 tracks/1/imported = false
 tracks/1/enabled = true
 tracks/1/keys = {
-"times": PoolRealArray( 3 ),
+"times": PoolRealArray( 1 ),
 "transitions": PoolRealArray( 1 ),
 "values": [ {
 "args": [  ],
-"method": "queue_free"
+"method": "remove_thyself"
 } ]
 }
-tracks/2/type = "value"
-tracks/2/path = NodePath("CollisionPolygon2D:disabled")
-tracks/2/interp = 1
-tracks/2/loop_wrap = true
-tracks/2/imported = false
-tracks/2/enabled = true
-tracks/2/keys = {
-"times": PoolRealArray( 0 ),
-"transitions": PoolRealArray( 1 ),
-"update": 1,
-"values": [ true ]
-}
-
-[sub_resource type="Animation" id=2]
-resource_name = "fade_out"
-tracks/0/type = "value"
-tracks/0/path = NodePath(".:modulate")
-tracks/0/interp = 1
-tracks/0/loop_wrap = true
-tracks/0/imported = false
-tracks/0/enabled = true
-tracks/0/keys = {
-"times": PoolRealArray( 0, 1 ),
-"transitions": PoolRealArray( 1, 1 ),
-"update": 0,
-"values": [ Color( 1, 1, 1, 1 ), Color( 1, 1, 1, 0 ) ]
-}
 
 [node name="Enemy" type="KinematicBody2D"]
 script = ExtResource( 2 )
diff --git a/Player.gd b/Player.gd
index b1f037b..4c3e7ed 100644
--- a/Player.gd
+++ b/Player.gd
@@ -8,6 +8,7 @@ export var shot_period_seconds = .5
 export var bullet: PackedScene
 export var is_invincible = false
 export var turn_rate = 0.03
+export var shooting_range = 500
 
 var PopupControl = preload("res://Popup.tscn")
 
diff --git a/World.gd b/World.gd
index 3fdda0a..d825fc3 100644
--- a/World.gd
+++ b/World.gd
@@ -2,34 +2,59 @@ extends Node2D
 
 const Utils = preload("res://Utils.gd")
 const Enemy = preload("res://Enemy.tscn")
-export var enemy_count = 4
+const Health = preload("res://HealPowerUp.tscn")
+const Speed = preload("res://SpeedPowerUp.tscn")
 var destination: Vector2
 var is_destination_set = false
+var min_items_dict = {
+	"create_enemy": 10,
+	"create_health": 10,
+	"create_speed": 10,
+}
+
+func enemy_killed():
+	$CanvasLayer/HUD.score += 1
+	
+func create_enemy():
+	var enemy = Enemy.instance()
+	enemy.position = get_new_item_pos()
+	enemy.add_to_group("enemies")
+	enemy.connect("enemy_killed", self, "enemy_killed")
+	enemy.connect("tree_exiting", self, "create_enemy")
+	$Environment.add_child(enemy)
+	Utils.log("adding enemy at", enemy.global_position)
+
+func create_health():
+	var health = Health.instance()
+	health.position = get_new_item_pos()
+	health.connect("tree_exiting", self, "create_health")
+	$Environment.add_child(health)
+	Utils.log("adding health at", health.global_position)
+
+func create_speed():
+	var speed = Speed.instance()
+	speed.position = get_new_item_pos()
+	speed.connect("tree_exiting", self, "create_speed")
+	$Environment.add_child(speed)
+	Utils.log("adding speed at", speed.global_position)
 
 func _ready() -> void:
 	Input.mouse_mode = Input.MOUSE_MODE_HIDDEN
 	
-	# create enemies
-	for n in enemy_count:
-		add_new_enemy(true)
+	# create items
+	for creator in min_items_dict:
+		var count = min_items_dict[creator]
+		for n in count:
+			var function = funcref(self, creator)
+			function.call_func()
 
-func _on_enemy_killed() -> void:
-	$CanvasLayer/HUD.score += 1
-	# use call_deferred to ensure that this happens after the collision has been processed
-	call_deferred("add_new_enemy")
-
-func add_new_enemy(should_be_visible: bool = false) -> void:
+func get_new_item_pos() -> Vector2:
 	var pos_angle = randi() % 360
 	var unit_vector = Vector2.UP.rotated(pos_angle)
 	var screen_radius = get_viewport().get_visible_rect().size.length() / 2 + 10
-	var enemy_spawn_dist = 400 if should_be_visible else screen_radius
+	var enemy_spawn_dist = screen_radius
 	var pos = unit_vector * enemy_spawn_dist + $Player.global_position
-	
-	var enemy = Enemy.instance()
-	enemy.connect("enemy_killed", self, "_on_enemy_killed")
-	enemy.position = pos
-	enemy.add_to_group("enemies")
-	add_child(enemy)
+	return pos
 
 func _input(event: InputEvent) -> void:
 	if $Player.dead:
@@ -63,6 +88,19 @@ func _process(_delta: float) -> void:
 		var enemy: Enemy = e
 		enemy.turn_towards($Player.position)
 
+	# remove environment nodes that are too far away
+	# as they are removed, they should replace themselves
+	var screen_radius = get_viewport().get_visible_rect().size.length() / 2 + 10
+	var env_items = $Environment.get_children()
+	Utils.log("env items", env_items.size())
+	for i in env_items:
+		var item: Node2D = i
+		var diff = $Player.global_position - item.global_position
+		var dist = diff.length()
+		var is_too_far = dist > (2.0 * screen_radius)
+		if is_too_far:
+			item.queue_free()
+
 func set_destination(pos: Vector2) -> void:
 	destination = pos
 	is_destination_set = true
@@ -96,10 +134,12 @@ func _on_ShootTimer_timeout() -> void:
 	if filteredEnemies.size() > 0:
 		filteredEnemies.sort_custom(self, "sort_enemies_ascending_distance")
 		var closest_enemy: Enemy = filteredEnemies[0]
-		closest_enemy.is_targeted = true
-		$Player.shoot_at(closest_enemy.global_position)
-		$PlayerToTarget.points[0] = $Player.global_position
-		$PlayerToTarget.points[1] = closest_enemy.global_position
+		var dist = closest_enemy.global_position.distance_to($Player.global_position)
+		if dist < $Player.shooting_range:
+			closest_enemy.is_targeted = true
+			$Player.shoot_at(closest_enemy.global_position)
+			$PlayerToTarget.points[0] = $Player.global_position
+			$PlayerToTarget.points[1] = closest_enemy.global_position
 
 func _on_Button_pressed() -> void:
 	get_tree().paused = false
diff --git a/World.tscn b/World.tscn
index 2836a51..ed400be 100644
--- a/World.tscn
+++ b/World.tscn
@@ -1,4 +1,4 @@
-[gd_scene load_steps=10 format=2]
+[gd_scene load_steps=8 format=2]
 
 [ext_resource path="res://assets/kenney_simple-space/PNG/Default/icon_crossLarge.png" type="Texture" id=1]
 [ext_resource path="res://Player.tscn" type="PackedScene" id=2]
@@ -6,15 +6,12 @@
 [ext_resource path="res://World.gd" type="Script" id=4]
 [ext_resource path="res://StarField.tscn" type="PackedScene" id=5]
 [ext_resource path="res://CharacterTheme.tres" type="Theme" id=6]
-[ext_resource path="res://HealPowerUp.tscn" type="PackedScene" id=7]
-[ext_resource path="res://SpeedPowerUp.tscn" type="PackedScene" id=8]
 
 [sub_resource type="CircleShape2D" id=1]
 radius = 29.0172
 
 [node name="World" type="Node2D"]
 script = ExtResource( 4 )
-enemy_count = 3
 
 [node name="Player" parent="." groups=["player"] instance=ExtResource( 2 )]
 position = Vector2( 513, 302 )
@@ -53,24 +50,6 @@ visible = false
 
 [node name="Environment" type="Node2D" parent="."]
 
-[node name="HealPowerUp" parent="Environment" instance=ExtResource( 7 )]
-position = Vector2( 700, 514 )
-
-[node name="HealPowerUp2" parent="Environment" instance=ExtResource( 7 )]
-position = Vector2( 199, 534 )
-
-[node name="HealPowerUp3" parent="Environment" instance=ExtResource( 7 )]
-position = Vector2( 837, 158 )
-
-[node name="SpeedPowerUp" parent="Environment" instance=ExtResource( 8 )]
-position = Vector2( 747, 342 )
-
-[node name="SpeedPowerUp2" parent="Environment" instance=ExtResource( 8 )]
-position = Vector2( 123, 307 )
-
-[node name="SpeedPowerUp3" parent="Environment" instance=ExtResource( 8 )]
-position = Vector2( 450, 505 )
-
 [node name="CanvasLayer" type="CanvasLayer" parent="."]
 
 [node name="HUD" parent="CanvasLayer" instance=ExtResource( 3 )]