First godot-ci commit
This commit is contained in:
7
scripts/Arena.gd
Executable file
7
scripts/Arena.gd
Executable file
@@ -0,0 +1,7 @@
|
||||
extends Node2D
|
||||
|
||||
func _ready():
|
||||
self.setup_arena()
|
||||
|
||||
func setup_arena() -> void:
|
||||
$Background.lowlight()
|
||||
22
scripts/Base.gd
Executable file
22
scripts/Base.gd
Executable file
@@ -0,0 +1,22 @@
|
||||
extends "res://scripts/ColoredEntity.gd"
|
||||
|
||||
const FULL_HEALTH: int = 3
|
||||
var health: int = self.FULL_HEALTH
|
||||
|
||||
func _ready():
|
||||
self.highlight()
|
||||
|
||||
func hit() -> void:
|
||||
if health > 1:
|
||||
self.health -= 1
|
||||
else:
|
||||
self.dead()
|
||||
|
||||
func dead() -> void:
|
||||
pass
|
||||
|
||||
# --- Signals ---
|
||||
|
||||
func _on_Body_body_entered(body: Node):
|
||||
body.queue_free()
|
||||
self.hit()
|
||||
48
scripts/Cannon.gd
Normal file
48
scripts/Cannon.gd
Normal file
@@ -0,0 +1,48 @@
|
||||
extends "res://scripts/ColoredEntity.gd"
|
||||
|
||||
@onready var Bullet: PackedScene = preload("res://scenes/Projectile.tscn")
|
||||
const RATE_OF_CHANGE: float = 0.9
|
||||
const UPPER_LIMIT: int = -89
|
||||
const LOWER_LIMIT: int = -5
|
||||
|
||||
var angle: float = -45.0
|
||||
|
||||
func _ready():
|
||||
self.highlight()
|
||||
|
||||
func _process(delta):
|
||||
$Sprite2D.set_rotation(deg_to_rad(self.angle))
|
||||
$Sprite2D.size.y = 24
|
||||
|
||||
func _input(event):
|
||||
if Input.is_action_pressed("ui_up"):
|
||||
if self.angle > UPPER_LIMIT:
|
||||
self.move_up()
|
||||
if Input.is_action_pressed("ui_down"):
|
||||
if self.angle < LOWER_LIMIT:
|
||||
self.move_down()
|
||||
|
||||
func move_up() -> void:
|
||||
self.angle -= RATE_OF_CHANGE
|
||||
|
||||
func move_down() -> void:
|
||||
self.angle += RATE_OF_CHANGE
|
||||
|
||||
func shoot() -> void:
|
||||
if $FireCooldown.time_left == 0:
|
||||
var NewBullet = Bullet.instantiate()
|
||||
NewBullet.global_position = $Sprite2D/CannonTip.global_position
|
||||
NewBullet.rotation_degrees = self.angle
|
||||
var at: Vector2 = $Sprite2D/CannonTip.global_position - $Sprite2D/CannonBase.global_position
|
||||
NewBullet.shoot(at)
|
||||
|
||||
var BulletSprite = NewBullet.get_node("Mask")
|
||||
if self.highlighted:
|
||||
BulletSprite.highlight()
|
||||
else:
|
||||
BulletSprite.lowlight()
|
||||
|
||||
NewBullet.setup(GLOBAL.SpriteType.BULLET, GLOBAL.BULLET_SPEED)
|
||||
NewBullet.update_collision_layer()
|
||||
$Projectiles.add_child(NewBullet)
|
||||
$FireCooldown.start()
|
||||
37
scripts/ColoredEntity.gd
Executable file
37
scripts/ColoredEntity.gd
Executable file
@@ -0,0 +1,37 @@
|
||||
# Class with common color switch operations.
|
||||
# Add to the group ColoredEntity if its color is not fixed and gets swapped with player input.
|
||||
extends Node2D
|
||||
|
||||
var current_color: Color = GLOBAL.LOWLIGHT
|
||||
var highlighted: bool = false
|
||||
|
||||
func _ready():
|
||||
self.update_color()
|
||||
|
||||
func update_color() -> void:
|
||||
if highlighted:
|
||||
self.current_color = GLOBAL.HIGHLIGHT
|
||||
else:
|
||||
self.current_color = GLOBAL.LOWLIGHT
|
||||
self.modulate = self.current_color
|
||||
|
||||
func swap_color() -> void:
|
||||
if current_color == GLOBAL.LOWLIGHT:
|
||||
self.highlight()
|
||||
else:
|
||||
self.lowlight()
|
||||
|
||||
func highlight():
|
||||
current_color = GLOBAL.HIGHLIGHT
|
||||
highlighted = true
|
||||
self.update_color()
|
||||
|
||||
func lowlight():
|
||||
current_color = GLOBAL.LOWLIGHT
|
||||
highlighted = false
|
||||
self.update_color()
|
||||
|
||||
func set_random_color() -> void:
|
||||
randomize()
|
||||
if randi() % 2 == 0:
|
||||
self.swap_color()
|
||||
40
scripts/EnemyGenerator.gd
Normal file
40
scripts/EnemyGenerator.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
extends Node2D
|
||||
|
||||
@onready var EnemyScene: PackedScene = preload("res://scenes/Projectile.tscn")
|
||||
signal start
|
||||
signal stop
|
||||
|
||||
var Enemy
|
||||
|
||||
func _ready():
|
||||
self.setup_enemy()
|
||||
self.emit_signal("stop")
|
||||
|
||||
func setup_enemy() -> void:
|
||||
self.Enemy = EnemyScene.instantiate()
|
||||
Enemy.setup(GLOBAL.SpriteType.MISSILE, GLOBAL.MISSILE_SPEED["max"])
|
||||
|
||||
func spawn_and_shoot_enemy() -> void:
|
||||
var Duplicate = Enemy.duplicate(Node.DUPLICATE_USE_INSTANTIATION)
|
||||
Duplicate.set_random_color()
|
||||
Duplicate.update_collision_layer()
|
||||
$Enemies.add_child(Duplicate)
|
||||
|
||||
$SpawnArea/SpawnLocation.set_h_offset(randi())
|
||||
Duplicate.global_position = $SpawnArea/SpawnLocation.position
|
||||
|
||||
var direction: Vector2 = (Vector2(0, 1080) - Duplicate.global_position).normalized()
|
||||
var angle: float = Vector2(1, 0).angle_to(direction)
|
||||
Duplicate.rotation = angle
|
||||
Duplicate.shoot_missile(direction)
|
||||
|
||||
# --- Signals ---
|
||||
|
||||
func _on_SpawnTimer_timeout():
|
||||
self.spawn_and_shoot_enemy()
|
||||
|
||||
func _on_EnemyGenerator_start():
|
||||
$SpawnTimer.start()
|
||||
|
||||
func _on_EnemyGenerator_stop():
|
||||
$SpawnTimer.stop()
|
||||
44
scripts/GLOBAL.gd
Executable file
44
scripts/GLOBAL.gd
Executable file
@@ -0,0 +1,44 @@
|
||||
extends Node
|
||||
|
||||
enum SpriteType { BULLET = 0, MISSILE = 1 }
|
||||
|
||||
var theme_index: int = 0
|
||||
var current_theme: Dictionary
|
||||
var HIGHLIGHT: Color
|
||||
var LOWLIGHT: Color
|
||||
|
||||
const COLORSET_PY: Dictionary = { "high": Color(1, 1, 0.25), "low": Color(0.50, 0, 1) }
|
||||
const COLORSET_OB: Dictionary = { "high": Color(1, 0.56, 0), "low": Color(0, 0.40, 1) }
|
||||
const COLORSET_PB: Dictionary = { "high": Color(1, 0.50, 1), "low": Color(0, 0.75, 1) }
|
||||
const COLORS: Array = [
|
||||
COLORSET_PY,
|
||||
COLORSET_OB,
|
||||
COLORSET_PB
|
||||
]
|
||||
|
||||
const DEF_SPEED: float = 5.0
|
||||
const MISSILE_SPEED: Dictionary = { "min": 30, "max": 60 }
|
||||
const BULLET_SPEED: float = 10.0
|
||||
|
||||
const LOW_COLLISION: int = 2
|
||||
const HIGH_COLLISION: int = 3
|
||||
|
||||
func _ready():
|
||||
self.update_global_theme(self.theme_index)
|
||||
|
||||
func update_global_theme(index: int):
|
||||
self.theme_index = index
|
||||
self.current_theme = COLORS[theme_index]
|
||||
self.HIGHLIGHT = self.current_theme["high"]
|
||||
self.LOWLIGHT = self.current_theme["low"]
|
||||
self.update_colored_entities()
|
||||
|
||||
func update_colored_entities() -> void:
|
||||
var nodes: Array = self.get_tree().get_nodes_in_group("ColoredEntity")
|
||||
for node in nodes:
|
||||
node.update_color()
|
||||
|
||||
func swap_nodes_color() -> void:
|
||||
var nodes: Array = self.get_tree().get_nodes_in_group("ColoredEntity")
|
||||
for node in nodes:
|
||||
node.swap_color()
|
||||
4
scripts/Game.gd
Executable file
4
scripts/Game.gd
Executable file
@@ -0,0 +1,4 @@
|
||||
extends Node2D
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
15
scripts/HUD.gd
Executable file
15
scripts/HUD.gd
Executable file
@@ -0,0 +1,15 @@
|
||||
extends Control
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
# --- Signals ---
|
||||
|
||||
func _on_Theme_Button_pressed(button_index: int) -> void:
|
||||
GLOBAL.update_global_theme(button_index)
|
||||
|
||||
func _on_StartButton_pressed():
|
||||
get_node("/root/Main").emit_signal("start_zoom_out")
|
||||
get_node("/root/Main/Game/EnemyGenerator").emit_signal("start")
|
||||
get_node("/root/Main/Game/Player").emit_signal("unblock")
|
||||
self.hide()
|
||||
25
scripts/Main.gd
Executable file
25
scripts/Main.gd
Executable file
@@ -0,0 +1,25 @@
|
||||
extends Node2D
|
||||
|
||||
signal start_zoom_out
|
||||
|
||||
const ZOOM_DELTA: float = 0.2
|
||||
const MOVE_DELTA: float = 0.353
|
||||
|
||||
@onready var camera: Camera2D = $Path2D/PathFollow2D/MenuCamera
|
||||
var camera_zooming: bool = false
|
||||
|
||||
func _process(delta: float):
|
||||
if camera_zooming:
|
||||
self.zoom_out_proccess(delta)
|
||||
|
||||
func zoom_out_proccess(delta: float) -> void:
|
||||
var delta_speed = delta * ZOOM_DELTA
|
||||
if camera.zoom < Vector2(1, 1):
|
||||
camera.zoom += Vector2(delta_speed, delta_speed)
|
||||
else:
|
||||
self.camera_zooming = false
|
||||
|
||||
$Path2D/PathFollow2D.progress_ratio += delta * MOVE_DELTA
|
||||
|
||||
func _on_Main_start_zoom_out():
|
||||
self.camera_zooming = true
|
||||
25
scripts/Player.gd
Executable file
25
scripts/Player.gd
Executable file
@@ -0,0 +1,25 @@
|
||||
extends "res://scripts/ColoredEntity.gd"
|
||||
|
||||
signal unblock
|
||||
|
||||
var blocked_controls: bool = true
|
||||
|
||||
func _ready():
|
||||
self.highlight()
|
||||
|
||||
func _input(event):
|
||||
if blocked_controls:
|
||||
return
|
||||
|
||||
if Input.is_action_just_pressed("swap"):
|
||||
GLOBAL.swap_nodes_color()
|
||||
if Input.is_action_pressed("fire"):
|
||||
self.shoot_bullet()
|
||||
|
||||
func shoot_bullet() -> void:
|
||||
$Cannon.shoot()
|
||||
|
||||
# --- Signals ---
|
||||
|
||||
func _on_Player_unblock():
|
||||
self.blocked_controls = false
|
||||
68
scripts/Projectile.gd
Normal file
68
scripts/Projectile.gd
Normal file
@@ -0,0 +1,68 @@
|
||||
extends RigidBody2D
|
||||
|
||||
var MissileSprite: Texture2D = load("res://resources/img/missile-placeholder.png")
|
||||
var BulletSprite: Texture2D = load("res://resources/img/bullet-placeholder.png")
|
||||
|
||||
var bodies_in_area: Array = []
|
||||
var sprite_type: int
|
||||
var speed: float = GLOBAL.DEF_SPEED
|
||||
var armed: bool = false
|
||||
|
||||
func _ready():
|
||||
self.gravity_scale = 0.0
|
||||
self.physics_material_override.friction = 0.0
|
||||
self.contact_monitor = true
|
||||
self.max_contacts_reported = 1
|
||||
|
||||
func setup(sprite_type: int, speed: float) -> void:
|
||||
self.sprite_type = sprite_type
|
||||
self.speed = speed
|
||||
|
||||
if sprite_type == GLOBAL.SpriteType.BULLET:
|
||||
$Mask/Sprite2D.set_texture(self.BulletSprite)
|
||||
self.armed = true
|
||||
$ExplosionArea/ExplosionShape.disabled = false
|
||||
else:
|
||||
$Mask/Sprite2D.set_texture(self.MissileSprite)
|
||||
|
||||
func shoot(at: Vector2) -> void:
|
||||
var direction = (at - self.global_position)
|
||||
self.linear_velocity = at * speed
|
||||
|
||||
func shoot_missile(at: Vector2) -> void:
|
||||
var direction = (at - self.global_position)
|
||||
self.apply_central_force(at * GLOBAL.MISSILE_SPEED["max"])
|
||||
|
||||
func set_random_color() -> void:
|
||||
$Mask.set_random_color()
|
||||
|
||||
func update_collision_layer() -> void:
|
||||
if $Mask.highlighted:
|
||||
self.set_collision_layer_value(GLOBAL.HIGH_COLLISION, 1)
|
||||
self.set_collision_mask_value(GLOBAL.HIGH_COLLISION, 1)
|
||||
$ExplosionArea.set_collision_layer_value(GLOBAL.HIGH_COLLISION, 1)
|
||||
$ExplosionArea.set_collision_mask_value(GLOBAL.HIGH_COLLISION, 1)
|
||||
else:
|
||||
self.set_collision_layer_value(GLOBAL.LOW_COLLISION, 1)
|
||||
self.set_collision_mask_value(GLOBAL.LOW_COLLISION, 1)
|
||||
$ExplosionArea.set_collision_layer_value(GLOBAL.LOW_COLLISION, 1)
|
||||
$ExplosionArea.set_collision_mask_value(GLOBAL.LOW_COLLISION, 1)
|
||||
|
||||
# --- Signals ---
|
||||
|
||||
func _on_VisibilityNotifier2D_screen_exited():
|
||||
self.queue_free()
|
||||
|
||||
func _on_Projectile_body_entered(body: PhysicsBody2D):
|
||||
if armed:
|
||||
for missile in bodies_in_area:
|
||||
missile.queue_free()
|
||||
self.queue_free()
|
||||
|
||||
func _on_ExplosionArea_body_entered(body: PhysicsBody2D):
|
||||
if armed and body.get_node("Mask").highlighted == $Mask.highlighted:
|
||||
bodies_in_area.push_front(body)
|
||||
|
||||
func _on_ExplosionArea_body_exited(body: PhysicsBody2D):
|
||||
if armed:
|
||||
bodies_in_area.erase(body)
|
||||
Reference in New Issue
Block a user