Initial files
This commit is contained in:
40
scripts/asteroid.gd
Normal file
40
scripts/asteroid.gd
Normal file
@@ -0,0 +1,40 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
var explosion = preload("res://scenes/explosion.tscn")
|
||||
var velocity = Vector2()
|
||||
export var speed_min = 10
|
||||
export var speed_max = 50
|
||||
|
||||
func _ready():
|
||||
randomize()
|
||||
var rand_x = rand_range(0, get_viewport_rect().size.width)
|
||||
set_global_pos(Vector2(rand_x, rand_range(-5, -60))) #random offset for easy "random timing"
|
||||
|
||||
rand_x = rand_range(0, get_viewport_rect().size.width)
|
||||
var target = Vector2(rand_x, get_viewport_rect().size.height)
|
||||
|
||||
set_rot(get_global_pos().angle_to_point(target)+deg2rad(180))
|
||||
velocity = Vector2(0, rand_range(speed_min, speed_max))
|
||||
get_node("Sprite").set_rotd(rand_range(0,360))
|
||||
set_process(true)
|
||||
|
||||
func _process(delta):
|
||||
move(velocity.rotated(get_rot())*delta)
|
||||
check_bounds()
|
||||
|
||||
func check_bounds():
|
||||
if get_pos().y > get_viewport_rect().size.y - 5:
|
||||
print("Asteroid out of bounds")
|
||||
game_manager.get_node_from_root("Node/Base").damage(10)
|
||||
destroy()
|
||||
|
||||
func destroy():
|
||||
get_node("CollisionArea").queue_free()
|
||||
game_manager.remove_asteroid()
|
||||
var new_explosion = explosion.instance()
|
||||
new_explosion.set_pos(get_pos())
|
||||
game_manager.get_node_from_root("Node").add_child(new_explosion)
|
||||
queue_free()
|
||||
|
||||
func on_rocket_hit():
|
||||
destroy()
|
||||
110
scripts/base.gd
Normal file
110
scripts/base.gd
Normal file
@@ -0,0 +1,110 @@
|
||||
extends StaticBody2D
|
||||
|
||||
var state
|
||||
var local_health
|
||||
var missile_scn = preload("res://scenes/missile.tscn")
|
||||
var states = {"STATE_AIMING": StateAiming, "STATE_FIRING": StateFiring}
|
||||
var cannon_rotation = 90
|
||||
var cannon_rot_dir = 0
|
||||
export var health = 100
|
||||
export var reload_time = 0.8
|
||||
|
||||
signal state_change
|
||||
|
||||
func _ready():
|
||||
set_state("STATE_AIMING")
|
||||
set_process_input(true)
|
||||
set_process(true)
|
||||
local_health = health
|
||||
|
||||
func _process(delta):
|
||||
state.update(delta)
|
||||
|
||||
|
||||
func _input(event):
|
||||
if state.has_method("input"):
|
||||
state.input(event)
|
||||
|
||||
func damage(dmg):
|
||||
local_health -= dmg
|
||||
if local_health <= 0 and not game_manager.state == game_manager.STATE_GAMEOVER:
|
||||
game_manager.game_over()
|
||||
|
||||
func set_state(new_state):
|
||||
if state: state._exit()
|
||||
emit_signal("state_change", self, new_state)
|
||||
print("State change to %s" % new_state)
|
||||
var new_state_instance = states[new_state].new(self)
|
||||
self.state = new_state_instance
|
||||
|
||||
|
||||
func get_state():
|
||||
return state.to_string()
|
||||
|
||||
class StateFiring:
|
||||
func to_string():
|
||||
return "STATE_FIRING"
|
||||
var base
|
||||
var missile_spawn
|
||||
var missile_rot
|
||||
func _init(_base):
|
||||
self.base = _base
|
||||
missile_spawn = base.get_node("CannonSprite/CannonTip")
|
||||
missile_rot = base.get_node("CannonSprite").get_global_rot()
|
||||
|
||||
func update(delta):
|
||||
shoot_missile()
|
||||
|
||||
func shoot_missile():
|
||||
var missile = base.missile_scn.instance()
|
||||
missile.init(base)
|
||||
base.add_child(missile)
|
||||
missile.set_global_rot(missile_rot)
|
||||
missile.set_global_pos(missile_spawn.get_global_pos())
|
||||
print("Fired")
|
||||
base.set_state("STATE_AIMING")
|
||||
|
||||
|
||||
func _exit():
|
||||
pass
|
||||
|
||||
class StateAiming:
|
||||
func to_string():
|
||||
return "STATE_AIMING"
|
||||
var base
|
||||
var cannon
|
||||
var ray
|
||||
var reload_timer
|
||||
func _init(_base):
|
||||
self.base = _base
|
||||
reload_timer = base.reload_time
|
||||
cannon = base.get_node("CannonSprite")
|
||||
ray = cannon.get_node("Ray")
|
||||
|
||||
func update(delta):
|
||||
if reload_timer > 0:
|
||||
reload_timer -= delta
|
||||
ray.ray_color = ray.colors.red
|
||||
else: ray.ray_color = ray.colors.green
|
||||
#var mouse_pos = base.get_global_mouse_pos()
|
||||
#cannon.look_at(mouse_pos)
|
||||
#cannon.set_rot(cannon.get_global_pos().angle_to_point(mouse_pos))
|
||||
base.cannon_rotation += base.cannon_rot_dir
|
||||
cannon.set_rot(deg2rad(base.cannon_rotation))
|
||||
|
||||
func input(event):
|
||||
if event.is_action_pressed("slow_motion"):
|
||||
OS.set_time_scale(0.15)
|
||||
if event.is_action_released("fire") or event.is_action_released("A") and reload_timer <= 0:
|
||||
print("We fire")
|
||||
base.set_state("STATE_FIRING")
|
||||
if event.is_action("ui_left") or event.is_action("J_left"):
|
||||
base.cannon_rot_dir = 1
|
||||
if event.is_action("ui_right") or event.is_action("J_right"):
|
||||
base.cannon_rot_dir = -1
|
||||
if event.is_action_released("ui_right") or event.is_action_released("ui_left") or event.is_action_released("J_right") or event.is_action_released("J_left"):
|
||||
base.cannon_rot_dir = 0
|
||||
|
||||
func _exit():
|
||||
pass
|
||||
|
||||
21
scripts/explosion.gd
Normal file
21
scripts/explosion.gd
Normal file
@@ -0,0 +1,21 @@
|
||||
extends Sprite
|
||||
|
||||
var ttl = 4
|
||||
|
||||
func _ready():
|
||||
set_process(true)
|
||||
get_node("AnimationPlayer").connect("finished", self, "anim_finished")
|
||||
get_node("ExplosionArea").connect("body_enter", self, "on_collision")
|
||||
|
||||
func anim_finished():
|
||||
get_node("ExplosionArea").queue_free()
|
||||
|
||||
func on_collision(other):
|
||||
if other != null and other.has_method("on_rocket_hit"):
|
||||
other.on_rocket_hit()
|
||||
print("R ON R")
|
||||
|
||||
func _process(delta):
|
||||
if ttl <= 0:
|
||||
get_parent().queue_free()
|
||||
else: ttl -= delta
|
||||
86
scripts/game_manager.gd
Normal file
86
scripts/game_manager.gd
Normal file
@@ -0,0 +1,86 @@
|
||||
extends Node
|
||||
const STATE_STARTUP = 0
|
||||
const STATE_PLAYING = 1
|
||||
const STATE_GAMEOVER = 2
|
||||
const STAGE_TIME = 30
|
||||
var active_asteroids = 0
|
||||
var stage = 1
|
||||
var total_time = 0
|
||||
var slowmo_time = 5
|
||||
var score = 0
|
||||
var time_next_stage = 25
|
||||
var state = STATE_STARTUP
|
||||
func _ready():
|
||||
set_fixed_process(true)
|
||||
update_ui()
|
||||
|
||||
func game_over():
|
||||
state = STATE_GAMEOVER
|
||||
var restart_btn = game_manager.get_node_from_root("Node/UI/Restart")
|
||||
restart_btn.show()
|
||||
restart_btn.get_node("AnimationPlayer").connect("finished", self, "game_over_ts")
|
||||
restart_btn.get_node("AnimationPlayer").play("anim_in")
|
||||
func game_over_ts():
|
||||
OS.set_time_scale(0.03)
|
||||
|
||||
func reset():
|
||||
get_tree().reload_current_scene()
|
||||
stage = 1
|
||||
active_asteroids = 0
|
||||
total_time = 0
|
||||
slowmo_time = 0
|
||||
score = 0
|
||||
time_next_stage = 25
|
||||
OS.set_time_scale(1)
|
||||
state = STATE_PLAYING
|
||||
update_ui()
|
||||
|
||||
func get_node_from_root(node_name):
|
||||
return get_tree().get_root().get_node(node_name)
|
||||
|
||||
func _fixed_process(delta):
|
||||
total_time += delta
|
||||
if not state == STATE_GAMEOVER: slowmo_update(delta)
|
||||
stage_update(delta)
|
||||
|
||||
func stage_update(delta):
|
||||
time_next_stage -= delta
|
||||
if time_next_stage <= 0:
|
||||
get_node_from_root("Node/WorldAudio").play("level_up")
|
||||
stage += 1
|
||||
update_ui()
|
||||
time_next_stage = STAGE_TIME
|
||||
|
||||
func slowmo_update(delta):
|
||||
if slowmo_time >= 0:
|
||||
slowmo_time -= delta / OS.get_time_scale()
|
||||
else: set_slowmo(false)
|
||||
if OS.get_time_scale() != 1.0: get_node_from_root("Node/UI/SlowmoBar").update_value(slowmo_time)
|
||||
|
||||
func set_slowmo(slowmo, time=5, scale=0.5):
|
||||
if slowmo:
|
||||
slowmo_time = time
|
||||
OS.set_time_scale(scale)
|
||||
get_node_from_root("Node/UI/SlowmoBar").set_max_val(time)
|
||||
else:
|
||||
OS.set_time_scale(1)
|
||||
|
||||
func update_ui():
|
||||
var health = get_node_from_root("Node/Base").local_health
|
||||
get_node_from_root("Node/UI/ScoreLabel").update_text(stage, active_asteroids, health)
|
||||
|
||||
func get_active_asteroids():
|
||||
return active_asteroids
|
||||
|
||||
func add_asteroid():
|
||||
active_asteroids += 1
|
||||
update_ui()
|
||||
if active_asteroids > stage + 7:
|
||||
game_manager.set_slowmo(true, 15, 0.2)
|
||||
elif active_asteroids > stage + 5:
|
||||
game_manager.set_slowmo(true, 10, 0.25)
|
||||
elif active_asteroids > stage + 3:
|
||||
game_manager.set_slowmo(true, 10, 0.5)
|
||||
func remove_asteroid():
|
||||
active_asteroids -= 1
|
||||
update_ui()
|
||||
47
scripts/missile.gd
Normal file
47
scripts/missile.gd
Normal file
@@ -0,0 +1,47 @@
|
||||
extends KinematicBody2D
|
||||
|
||||
export var speed_mult = 100
|
||||
var speed = Vector2(0,-1)
|
||||
var origin
|
||||
var exploded = false
|
||||
|
||||
func init(_origin):
|
||||
randomize()
|
||||
origin = _origin
|
||||
speed = speed * speed_mult
|
||||
|
||||
func _ready():
|
||||
#OS.set_time_scale(0.21)
|
||||
get_node("Audio").play("missile_launch")
|
||||
set_process(true)
|
||||
get_node("CollisionArea").connect("area_enter", self, "_on_collision")
|
||||
randomize()
|
||||
|
||||
func _process(delta):
|
||||
move_forward(delta)
|
||||
if origin: check_bounds()
|
||||
if exploded and not get_node("Audio").is_voice_active(2): queue_free()
|
||||
|
||||
func move_forward(delta):
|
||||
move(speed.rotated(get_rot())*delta)
|
||||
|
||||
func _on_collision(other):
|
||||
if other.get_owner().has_method("on_rocket_hit"):
|
||||
other.get_owner().on_rocket_hit()
|
||||
var explosion_audio = "explosion_%s" % ceil(rand_range(1, 5))
|
||||
print("Playing %s" % explosion_audio)
|
||||
get_node("Audio").play(explosion_audio, 2)
|
||||
print("target destroyed")
|
||||
hide()
|
||||
get_node("CollisionArea").queue_free()
|
||||
exploded = true
|
||||
|
||||
func check_bounds():
|
||||
var origin_pos = origin.get_global_pos()
|
||||
var max_dist = origin_pos.distance_to(Vector2(0,0))
|
||||
var current_dist = get_global_pos().distance_to(origin_pos)
|
||||
if current_dist > max_dist:
|
||||
print("Missile out of bounds")
|
||||
queue_free()
|
||||
|
||||
|
||||
15
scripts/ray.gd
Normal file
15
scripts/ray.gd
Normal file
@@ -0,0 +1,15 @@
|
||||
extends Node2D
|
||||
|
||||
var colors = {
|
||||
"red" : Color(255,0,0, 0.5),
|
||||
"green":Color(0,255,0, 0.5)
|
||||
}
|
||||
var ray_color = colors.red
|
||||
func _ready():
|
||||
set_process(true)
|
||||
|
||||
func _process(delta):
|
||||
update()
|
||||
|
||||
func _draw():
|
||||
draw_line(get_pos(), get_pos()+Vector2(0,-1) * 10000, ray_color, 2.5)
|
||||
23
scripts/spawner_asteroids.gd
Normal file
23
scripts/spawner_asteroids.gd
Normal file
@@ -0,0 +1,23 @@
|
||||
extends Node
|
||||
|
||||
const WAVE_TIME = 12
|
||||
onready var asteroid_scn = preload("res://scenes/asteroid.tscn")
|
||||
export var amount = 2
|
||||
var timer = 5
|
||||
|
||||
func _ready():
|
||||
set_process(true)
|
||||
|
||||
|
||||
func _process(delta):
|
||||
if game_manager.state == game_manager.STATE_GAMEOVER: return
|
||||
timer -= delta
|
||||
if timer <= 0:
|
||||
for i in range(amount + game_manager.stage):
|
||||
spawn_asteroid()
|
||||
timer = WAVE_TIME
|
||||
|
||||
func spawn_asteroid():
|
||||
var new_asteroid = asteroid_scn.instance()
|
||||
add_child(new_asteroid)
|
||||
game_manager.add_asteroid()
|
||||
Reference in New Issue
Block a user