Added aliens and glow on the numbers
This commit is contained in:
230
Dunkanoid.gd
230
Dunkanoid.gd
@@ -3,6 +3,27 @@ extends Node2D
|
||||
var _Brick = preload("res://Brick/Brick.tscn")
|
||||
var _Ball = preload("res://Ball/Ball.tscn")
|
||||
var _Upgrade = preload("res://Upgrade/Upgrade.tscn")
|
||||
var _Alien = preload("res://Alien.tscn")
|
||||
|
||||
@onready var ScoreNode = $ScoreCard/Score/ScoreBox
|
||||
@onready var LivesNode = $ScoreCard/Lives/LivesBox
|
||||
@onready var RunTimeNode = $ScoreCard/RunTime/RunTime
|
||||
@onready var BestTimeNode = $ScoreCard/BestTime/BestTime
|
||||
@onready var BricksNode = $Bricks
|
||||
@onready var BackgroundNode = $Background
|
||||
@onready var PaddleNode = $Paddle
|
||||
@onready var PipesNode = $Pipes
|
||||
@onready var AliensNode = $Aliens
|
||||
@onready var RunTimerNode = $RunTimer
|
||||
@onready var NewBestNode = $NewBestTime
|
||||
@onready var NewBestTimeNode = $NewBestTime/HBoxContainer/BestTime
|
||||
@onready var StartTitleNode = $Start/VBoxContainer/PanelContainer/VBoxContainer/Title
|
||||
@onready var StartRoundNode = $Start/VBoxContainer/PanelContainer/VBoxContainer/Round
|
||||
@onready var StartNode = $Start
|
||||
@onready var PowerballTimerNode = $PowerBallTimer
|
||||
@onready var FloorSoundNode = $Sounds/FloorSound
|
||||
@onready var UpgradeSoundNode = $Sounds/UpgradeCollected
|
||||
@onready var AlienDieSoundNode = $Sounds/AlienDie
|
||||
|
||||
var bricks : Array = []
|
||||
var balls : Array[Node] = []
|
||||
@@ -42,44 +63,51 @@ func _ready() -> void:
|
||||
new_level()
|
||||
Music.play_game()
|
||||
|
||||
var opened: bool = false
|
||||
|
||||
func _process(delta : float) -> void:
|
||||
|
||||
if OS.has_feature("editor"):
|
||||
if Input.is_action_just_pressed("cheat"):
|
||||
for i in 10:
|
||||
add_ball()
|
||||
spawn_alien()
|
||||
for i in 50:
|
||||
add_ball()
|
||||
|
||||
if mode == MODE_EXIT:
|
||||
if $Paddle.global_position.x - ($Paddle.width / 2) <= 20:
|
||||
if PaddleNode.global_position.x - (PaddleNode.width / 2) <= 20:
|
||||
level = level_data.left
|
||||
leave(-1)
|
||||
if $Paddle.global_position.x + ($Paddle.width / 2) >= 412:
|
||||
if PaddleNode.global_position.x + (PaddleNode.width / 2) >= 412:
|
||||
level = level_data.right
|
||||
leave(+1)
|
||||
|
||||
if mode == MODE_LEAVE:
|
||||
$Paddle.global_position.x += (delta * leave_direction * 20.0)
|
||||
if $Paddle.global_position.x < -16 or $Paddle.global_position.x > 428:
|
||||
PaddleNode.global_position.x += (delta * leave_direction * 20.0)
|
||||
if PaddleNode.global_position.x < -16 or PaddleNode.global_position.x > 462:
|
||||
if opened:
|
||||
PipesNode.close_door(Pipes.BOTTOM_LEFT)
|
||||
PipesNode.close_door(Pipes.BOTTOM_RIGHT)
|
||||
opened = false
|
||||
if not Music.jingle_playing:
|
||||
new_level()
|
||||
else:
|
||||
if Input.is_action_pressed("left"):
|
||||
var leftmost = 16 + $Paddle.width / 2
|
||||
$Paddle.position.x -= delta * PADDLE_SPEED
|
||||
$Paddle.position.y = 340
|
||||
if $Paddle.position.x < leftmost:
|
||||
$Paddle.position.x = leftmost
|
||||
var leftmost = 16 + PaddleNode.width / 2
|
||||
PaddleNode.position.x -= delta * PADDLE_SPEED
|
||||
PaddleNode.position.y = 340
|
||||
if PaddleNode.position.x < leftmost:
|
||||
PaddleNode.position.x = leftmost
|
||||
if Input.is_action_pressed("right"):
|
||||
var rightmost = 432 - $Paddle.width / 2
|
||||
$Paddle.position.x += delta * PADDLE_SPEED
|
||||
$Paddle.position.y = 340
|
||||
if $Paddle.position.x > rightmost:
|
||||
$Paddle.position.x = rightmost
|
||||
var rightmost = 432 - PaddleNode.width / 2
|
||||
PaddleNode.position.x += delta * PADDLE_SPEED
|
||||
PaddleNode.position.y = 340
|
||||
if PaddleNode.position.x > rightmost:
|
||||
PaddleNode.position.x = rightmost
|
||||
if Input.is_action_just_pressed("fire"):
|
||||
if mode == MODE_PLAY:
|
||||
if level_starting:
|
||||
level_starting = false
|
||||
$RunTimer.start()
|
||||
RunTimerNode.start()
|
||||
time_run = true
|
||||
for ball in balls:
|
||||
if (ball.captured):
|
||||
@@ -87,7 +115,7 @@ func _process(delta : float) -> void:
|
||||
|
||||
|
||||
if time_run:
|
||||
$ScoreCard/RunTime.text = "%02d:%05.2f" % [$RunTimer.elapsed_time / 60000, $RunTimer.elapsed_time % 60000 / 1000.0]
|
||||
RunTimeNode.text = "%02d:%05.2f" % [RunTimerNode.elapsed_time / 60000, RunTimerNode.elapsed_time % 60000 / 1000.0]
|
||||
|
||||
|
||||
func leave(dir : int) -> void:
|
||||
@@ -95,37 +123,38 @@ func leave(dir : int) -> void:
|
||||
leave_direction = dir
|
||||
|
||||
func new_level() -> void:
|
||||
$NewBestTime.visible = false
|
||||
NewBestNode.visible = false
|
||||
time_run = false
|
||||
level_starting = true
|
||||
$Paddle.normal()
|
||||
$Paddle.position.x = 224
|
||||
PaddleNode.normal()
|
||||
PaddleNode.position.x = 224
|
||||
mode = MODE_WAIT
|
||||
$Exits.visible = false
|
||||
for ball in balls:
|
||||
if ball.get_parent() != self:
|
||||
print("For some reason this ball's parent has got lost")
|
||||
remove_child(ball)
|
||||
ball.queue_free()
|
||||
balls.clear()
|
||||
for brick in bricks:
|
||||
$Bricks.remove_child(brick)
|
||||
BricksNode.remove_child(brick)
|
||||
brick.queue_free()
|
||||
bricks.clear()
|
||||
chr += 1
|
||||
level_data = load_level_from_disk(level)
|
||||
$ScoreCard/BestTime.text = format_time(Global.get_best_time(level_data.name))
|
||||
$Start/VBoxContainer/PanelContainer/VBoxContainer/Title.text = level
|
||||
$Start/VBoxContainer/PanelContainer/VBoxContainer/Round.text = "ROUND %3d" % [chr]
|
||||
$Background.texture = load("res://Backgrounds/%s.png" % level_data.background)
|
||||
$Background.modulate = Color("#%s" % level_data.get("tint", "FFFFFF"))
|
||||
BestTimeNode.text = format_time(Global.get_best_time(level_data.name))
|
||||
StartTitleNode.text = level
|
||||
StartRoundNode.text = "ROUND %3d" % [chr]
|
||||
BackgroundNode.texture = load("res://Backgrounds/%s.png" % level_data.background)
|
||||
BackgroundNode.modulate = Color("#%s" % level_data.get("tint", "FFFFFF"))
|
||||
load_level(level_data.data)
|
||||
var ball = _Ball.instantiate()
|
||||
ball.capture($Paddle, Vector2((randf() * 32) - 16, 8))
|
||||
ball.capture(PaddleNode, Vector2((randf() * 32) - 16, 8))
|
||||
ball.hit_paddle.connect(_on_hit_paddle)
|
||||
ball.hit_floor.connect(_on_hit_floor)
|
||||
add_child(ball)
|
||||
balls.push_back(ball)
|
||||
|
||||
$Start.visible = true
|
||||
StartNode.visible = true
|
||||
Music.jingle_finished.connect(_on_start_round_finished)
|
||||
Music.jingle(Music.JINGLE_LEVEL_START)
|
||||
|
||||
@@ -148,7 +177,7 @@ func _brick_destroyed(brick) -> void:
|
||||
upgrade.set_upgrade("R", Color.LIGHT_CORAL)
|
||||
5:
|
||||
upgrade.set_upgrade("P", Color.AQUAMARINE)
|
||||
add_child(upgrade)
|
||||
call_deferred("add_child", upgrade)
|
||||
bricks.erase(brick)
|
||||
var brick_count = 0
|
||||
for abrick in bricks:
|
||||
@@ -157,30 +186,36 @@ func _brick_destroyed(brick) -> void:
|
||||
|
||||
if brick_count == 0:
|
||||
for ball in balls:
|
||||
remove_child(ball)
|
||||
ball.queue_free()
|
||||
call_deferred("remove_child", ball)
|
||||
ball.call_deferred("queue_free")
|
||||
balls.clear()
|
||||
|
||||
for c in get_children():
|
||||
if c is Upgrade:
|
||||
remove_child(c)
|
||||
c.queue_free()
|
||||
call_deferred("remove_child", c)
|
||||
c.call_deferred("queue_free")
|
||||
|
||||
for c in AliensNode.get_children():
|
||||
AliensNode.call_deferred("remove_child", c)
|
||||
c.call_deferred("queue_free")
|
||||
|
||||
mode = MODE_EXIT
|
||||
$Exits.visible = true
|
||||
PipesNode.open_door(Pipes.BOTTOM_LEFT)
|
||||
PipesNode.open_door(Pipes.BOTTOM_RIGHT)
|
||||
opened = true
|
||||
Music.jingle(Music.JINGLE_LEVEL_WON)
|
||||
var elapsed = $RunTimer.elapsed_time
|
||||
var elapsed = RunTimerNode.elapsed_time
|
||||
var best = Global.get_best_time(level_data.name)
|
||||
if elapsed < best:
|
||||
Global.set_best_time(level_data.name, elapsed)
|
||||
$RunTimer.pause()
|
||||
$NewBestTime/BestTime.text = format_time(elapsed)
|
||||
$NewBestTime.visible = true
|
||||
RunTimerNode.pause()
|
||||
NewBestTimeNode.text = format_time(elapsed)
|
||||
NewBestNode.visible = true
|
||||
|
||||
func format_time(time : int) -> String:
|
||||
if time > 3600000:
|
||||
return "--:--.--"
|
||||
return "%02d:%05.2f" % [time / 60000, time % 60000 / 1000.0]
|
||||
return "%02d:%05.2f" % [int(time / 60000.0), time % 60000 / 1000.0]
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if paused:
|
||||
@@ -188,20 +223,20 @@ func _input(event: InputEvent) -> void:
|
||||
if event is InputEventMouseMotion:
|
||||
if mode != MODE_LEAVE:
|
||||
if Global.relative_mouse:
|
||||
var leftmost = 16 + $Paddle.width / 2
|
||||
var rightmost = 432 - $Paddle.width / 2
|
||||
$Paddle.position.x += event.relative.x
|
||||
$Paddle.position.y = 340
|
||||
if $Paddle.position.x < leftmost:
|
||||
$Paddle.position.x = leftmost
|
||||
if $Paddle.position.x > rightmost:
|
||||
$Paddle.position.x = rightmost
|
||||
var leftmost = 16 + PaddleNode.width / 2
|
||||
var rightmost = 432 - PaddleNode.width / 2
|
||||
PaddleNode.position.x += event.relative.x
|
||||
PaddleNode.position.y = 340
|
||||
if PaddleNode.position.x < leftmost:
|
||||
PaddleNode.position.x = leftmost
|
||||
if PaddleNode.position.x > rightmost:
|
||||
PaddleNode.position.x = rightmost
|
||||
else:
|
||||
$Paddle.position = Vector2(min(max(16 + $Paddle.width/2, event.position.x), 432-$Paddle.width/2), 340)
|
||||
PaddleNode.position = Vector2(min(max(16 + PaddleNode.width/2, event.position.x), 432-PaddleNode.width/2), 340)
|
||||
if event is InputEventMouseButton:
|
||||
if mode == MODE_PLAY:
|
||||
if level_starting:
|
||||
$RunTimer.start()
|
||||
RunTimerNode.start()
|
||||
level_starting = false
|
||||
time_run = true
|
||||
|
||||
@@ -210,30 +245,30 @@ func _input(event: InputEvent) -> void:
|
||||
ball.release()
|
||||
|
||||
func _on_hit_paddle(ball) -> void:
|
||||
if $Paddle.is_capture():
|
||||
var diff = $Paddle.global_position.x - ball.global_position.x
|
||||
ball.capture($Paddle, Vector2(diff, 8))
|
||||
if PaddleNode.is_capture():
|
||||
var diff = PaddleNode.global_position.x - ball.global_position.x
|
||||
ball.capture(PaddleNode, Vector2(diff, 8))
|
||||
|
||||
func _on_hit_floor(ball) -> void:
|
||||
$Sounds/FloorSound.play()
|
||||
FloorSoundNode.play()
|
||||
balls.erase(ball)
|
||||
remove_child(ball)
|
||||
call_deferred("remove_child", ball)
|
||||
ball.call_deferred("queue_free")
|
||||
if balls.size() == 0:
|
||||
for c in get_children():
|
||||
if c is Upgrade:
|
||||
remove_child(c)
|
||||
c.queue_free()
|
||||
$Paddle.normal()
|
||||
PaddleNode.normal()
|
||||
ball = _Ball.instantiate()
|
||||
ball.capture($Paddle, Vector2((randf() * 32) - 16, 8))
|
||||
ball.capture(PaddleNode, Vector2((randf() * 32) - 16, 8))
|
||||
ball.hit_paddle.connect(_on_hit_paddle)
|
||||
ball.hit_floor.connect(_on_hit_floor)
|
||||
add_child(ball)
|
||||
balls.push_back(ball)
|
||||
Music.jingle_finished.connect(_on_start_round_finished)
|
||||
Music.jingle(Music.JINGLE_LEVEL_START)
|
||||
$Start.visible = true
|
||||
StartNode.visible = true
|
||||
mode = MODE_WAIT
|
||||
lives -= 1
|
||||
if lives <= 0:
|
||||
@@ -245,14 +280,14 @@ func _on_round_won_finished() -> void:
|
||||
|
||||
|
||||
func _on_update_score(score) -> void:
|
||||
$ScoreCard/ScoreBox.text = "%08d" % score
|
||||
ScoreNode.text = "%08d" % score
|
||||
pass # Replace with function body.
|
||||
|
||||
func _on_upgrade_collected(code : String) -> void:
|
||||
$Sounds/UpgradeCollected.play()
|
||||
UpgradeSoundNode.play()
|
||||
match code:
|
||||
"C":
|
||||
$Paddle.capture()
|
||||
PaddleNode.capture()
|
||||
"T":
|
||||
add_ball()
|
||||
add_ball()
|
||||
@@ -260,9 +295,9 @@ func _on_upgrade_collected(code : String) -> void:
|
||||
for ball in balls:
|
||||
ball.slowdown()
|
||||
"E":
|
||||
$Paddle.big()
|
||||
PaddleNode.big()
|
||||
"R":
|
||||
$Paddle.small()
|
||||
PaddleNode.small()
|
||||
"P":
|
||||
start_powerball()
|
||||
|
||||
@@ -276,9 +311,11 @@ func add_ball() -> void:
|
||||
newball.hit_paddle.connect(_on_hit_paddle)
|
||||
newball.hit_floor.connect(_on_hit_floor)
|
||||
newball.speed = balls[0].speed
|
||||
if balls[0].is_sparkles():
|
||||
newball.enable_sparkles()
|
||||
if balls[0].captured:
|
||||
newball.capture($Paddle, Vector2((randf() - 0.5) * 32, 8))
|
||||
add_child(newball)
|
||||
newball.capture(PaddleNode, Vector2((randf() - 0.5) * 32, 8))
|
||||
call_deferred("add_child", newball)
|
||||
balls.push_back(newball)
|
||||
|
||||
|
||||
@@ -319,21 +356,21 @@ func load_level(data) -> void:
|
||||
brick.position = Vector2(x * 32 + 16 + 16, y * 16 + 8 + 16)
|
||||
bricks.push_back(brick)
|
||||
brick.brick_destroyed.connect(_brick_destroyed)
|
||||
$Bricks.add_child(brick)
|
||||
BricksNode.add_child(brick)
|
||||
|
||||
func _on_start_round_finished(item : int) -> void:
|
||||
func _on_start_round_finished(_item : int) -> void:
|
||||
Music.jingle_finished.disconnect(_on_start_round_finished)
|
||||
$Start.visible = false
|
||||
StartNode.visible = false
|
||||
mode = MODE_PLAY
|
||||
|
||||
func _on_update_lives() -> void:
|
||||
$ScoreCard/LivesBox.text = "%d" % lives
|
||||
LivesNode.text = "%d" % lives
|
||||
|
||||
func load_level_from_disk(name : String) -> Dictionary:
|
||||
if FileAccess.file_exists("user://Levels/%s.json" % name):
|
||||
return JSON.parse_string(FileAccess.get_file_as_string("user://Levels/%s.json" % name))
|
||||
if FileAccess.file_exists("res://Levels/%s.json" % name):
|
||||
return JSON.parse_string(FileAccess.get_file_as_string("res://Levels/%s.json" % name))
|
||||
func load_level_from_disk(lname : String) -> Dictionary:
|
||||
if FileAccess.file_exists("user://Levels/%s.json" % lname):
|
||||
return JSON.parse_string(FileAccess.get_file_as_string("user://Levels/%s.json" % lname))
|
||||
if FileAccess.file_exists("res://Levels/%s.json" % lname):
|
||||
return JSON.parse_string(FileAccess.get_file_as_string("res://Levels/%s.json" % lname))
|
||||
return JSON.parse_string(FileAccess.get_file_as_string("res://Levels/NOTFOUND.json"))
|
||||
|
||||
func _on_paddle_effect_finished(effect: int) -> void:
|
||||
@@ -345,16 +382,53 @@ func _on_paddle_effect_finished(effect: int) -> void:
|
||||
func start_powerball() -> void:
|
||||
for ball in balls:
|
||||
ball.enable_sparkles()
|
||||
for brick in $Bricks.get_children():
|
||||
for brick in BricksNode.get_children():
|
||||
brick.enable_pass()
|
||||
$PowerBallTimer.start(10)
|
||||
PowerballTimerNode.start(10)
|
||||
|
||||
func stop_powerball() -> void:
|
||||
for ball in balls:
|
||||
ball.disable_sparkles()
|
||||
for brick in $Bricks.get_children():
|
||||
for brick in BricksNode.get_children():
|
||||
brick.disable_pass()
|
||||
|
||||
|
||||
func _on_power_ball_timer_timeout() -> void:
|
||||
stop_powerball()
|
||||
|
||||
func spawn_alien() -> void:
|
||||
if AliensNode.get_child_count() < 3:
|
||||
var door : int = Pipes.TOP_LEFT if randf() < 0.5 else Pipes.TOP_RIGHT
|
||||
PipesNode.open_door(door)
|
||||
|
||||
func _on_pipes_door_opened(door) -> void:
|
||||
match door:
|
||||
Pipes.TOP_LEFT:
|
||||
var alien = _Alien.instantiate()
|
||||
alien.position = Vector2(128, -12)
|
||||
alien.velocity = Vector2(0, 50)
|
||||
alien.alien_died.connect(_alien_died)
|
||||
AliensNode.add_child(alien)
|
||||
get_tree().create_timer(2).timeout.connect(_close_top_left)
|
||||
pass
|
||||
Pipes.TOP_RIGHT:
|
||||
var alien = _Alien.instantiate()
|
||||
alien.position = Vector2(320, -12)
|
||||
alien.velocity = Vector2(0, 50)
|
||||
alien.alien_died.connect(_alien_died)
|
||||
AliensNode.add_child(alien)
|
||||
get_tree().create_timer(2).timeout.connect(_close_top_right)
|
||||
pass
|
||||
|
||||
func _close_top_left() -> void:
|
||||
PipesNode.close_door(Pipes.TOP_LEFT)
|
||||
|
||||
func _close_top_right() -> void:
|
||||
PipesNode.close_door(Pipes.TOP_RIGHT)
|
||||
|
||||
func _on_alien_timer_timeout() -> void:
|
||||
spawn_alien()
|
||||
|
||||
func _alien_died(points : int) -> void:
|
||||
Global.score += points
|
||||
AlienDieSoundNode.play()
|
||||
|
||||
Reference in New Issue
Block a user