godot-shooter / commit
Ship is now shooting automatically at the closest enemy.
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"