ui; game saving and loading; bad guy movement; damage and death anims
This commit is contained in:
1 parent
f0fec8bfc7
commit
09a6140d15
45 files changed
+534
-183
No files matched your search
@@ -13,11 +13,16 @@ signal level_changed(level)
|
||||
signal destroyed(body)
|
||||
signal player_damaged(health, max_health)
|
||||
signal player_death
|
||||
signal game_loaded(stashed_data)
|
||||
signal game_saved(level, time_remaining, player_health, enemies_dictionary)
|
||||
signal timer_updated(time_remaining)
|
||||
signal coin_collected(coins_remaining)
|
||||
|
||||
var enemy_stats : CharacterStats
|
||||
var player_stats : CharacterStats
|
||||
var enemies_dict : Dictionary = {}
|
||||
var player_current_health : int = 0
|
||||
var stash_data : Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
# load in characters
|
||||
@@ -30,8 +35,17 @@ func _ready() -> void:
|
||||
timer.connect("timeout", second_counter)
|
||||
timer.start()
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if Input.is_action_just_pressed("save"):
|
||||
save_game()
|
||||
pass
|
||||
if Input.is_action_just_pressed("load"):
|
||||
load_game()
|
||||
pass
|
||||
|
||||
func second_counter() -> void:
|
||||
time_available -= 1
|
||||
timer_updated.emit(time_available)
|
||||
if time_available <= 0:
|
||||
print_debug("You ran out of time! Emitting level_changed signal")
|
||||
#get_tree().call_deferred("change_scene_to_file", levels[current_level])
|
||||
@@ -63,6 +77,7 @@ func on_coin_collected(_body, coin) -> void:
|
||||
destroyed.emit(coin)
|
||||
|
||||
func set_total_coins(value) -> void:
|
||||
coin_collected.emit(value)
|
||||
print_debug("Setting coin total to %s" % str(value))
|
||||
if value == 0:
|
||||
# You won!
|
||||
@@ -86,13 +101,20 @@ func on_player_slimed(_body, slime) -> void:
|
||||
player_damaged.emit(player_current_health, player_stats.starting_health)
|
||||
print_debug("Player Health: " + str(player_current_health) + " of " + str(player_stats.starting_health))
|
||||
|
||||
func add_enemy_to_level(enemy) -> void:
|
||||
func handle_player_death() -> void:
|
||||
level_changed.emit(levels[current_level])
|
||||
|
||||
func add_enemy_to_level(enemy, _stat = null) -> void:
|
||||
print_debug("GC adding %s to level" % enemy.name)
|
||||
var rand_damage : int = randi() % 10
|
||||
var this_enemy_stats : Dictionary = {
|
||||
"health": enemy_stats.health,
|
||||
"damage": enemy_stats.melee_damage + rand_damage
|
||||
}
|
||||
if _stat:
|
||||
this_enemy_stats.health = _stat.health
|
||||
this_enemy_stats.damage = _stat.damage
|
||||
print_debug("This enemy's health is %s and its damage is %s" % [this_enemy_stats.health, this_enemy_stats.damage])
|
||||
enemies_dict[enemy] = this_enemy_stats
|
||||
|
||||
func bullet_damage(thing_damaged, _bullet) -> void:
|
||||
@@ -109,3 +131,24 @@ func bullet_damage(thing_damaged, _bullet) -> void:
|
||||
|
||||
func remove_enemy_from_level(enemy) -> void:
|
||||
enemies_dict.erase(enemy)
|
||||
|
||||
func save_game() -> void:
|
||||
game_saved.emit(current_level, time_available, player_current_health, enemies_dict)
|
||||
|
||||
func load_game() -> void:
|
||||
if ResourceLoader.exists("res://resources/level" + str(current_level) + "_game_save_stats.tres"):
|
||||
var saved_game : SaveObject = load("res://resources/level" + str(current_level) + "_game_save_stats.tres")
|
||||
enemies_dict.clear()
|
||||
stash_data = saved_game.game_save
|
||||
game_loaded.emit(stash_data)
|
||||
|
||||
func stash_game(stash) -> void:
|
||||
print_debug("Stashing game state")
|
||||
stash_data = stash
|
||||
var stash_object = SaveObject.new()
|
||||
stash_object.game_save = stash
|
||||
ResourceSaver.save(stash_object, "res://resources/level" + str(current_level) + "_game_save_stats.tres")
|
||||
|
||||
func set_player_health(value: int) -> void:
|
||||
print_debug("Setting player health to %s" % str(value))
|
||||
player_current_health = value
|
||||
+27
-4
@@ -4,6 +4,8 @@ extends CharacterBody2D
|
||||
##
|
||||
## Controls the player character in this 2D side-scrolling platformer
|
||||
|
||||
signal player_died
|
||||
|
||||
enum FaceDirection {
|
||||
LEFT,
|
||||
RIGHT
|
||||
@@ -15,7 +17,9 @@ enum State {
|
||||
FALL,
|
||||
SHOOT_STILL,
|
||||
SHOOT_RUN,
|
||||
PUNCH
|
||||
PUNCH,
|
||||
HURT,
|
||||
DIE
|
||||
}
|
||||
|
||||
const JUMP_VELOCITY := -500.0 ## Power applied for jumping
|
||||
@@ -49,14 +53,21 @@ func _ready() -> void:
|
||||
add_child(shoot_cooldown_timer)
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
handle_input()
|
||||
if current_state != State.HURT and current_state != State.DIE:
|
||||
handle_input()
|
||||
move_and_slide()
|
||||
handle_movement(delta)
|
||||
move_and_slide()
|
||||
handle_collisions()
|
||||
update_state()
|
||||
update_animation()
|
||||
update_debug()
|
||||
|
||||
func handle_damage(_health, _max_health) -> void:
|
||||
current_state = State.HURT
|
||||
|
||||
func handle_death() -> void:
|
||||
current_state = State.DIE
|
||||
|
||||
func handle_input() -> void:
|
||||
|
||||
# Handle jumping.
|
||||
@@ -144,7 +155,7 @@ func handle_collisions() -> void:
|
||||
var collider = right_cast.get_collider()
|
||||
#print_debug("Colliding with %s " % collider.name)
|
||||
if collider is Node and collider is RigidBody2D and collider.is_in_group("punchable"):
|
||||
print_debug("We have a punch target")
|
||||
#print_debug("We have a punch target")
|
||||
punch_target = collider
|
||||
punch_enabled = true
|
||||
|
||||
@@ -201,6 +212,14 @@ func update_state() -> void:
|
||||
await player_sprite.animation_finished
|
||||
current_state = State.IDLE
|
||||
|
||||
State.HURT:
|
||||
await player_sprite.animation_finished
|
||||
current_state = State.IDLE
|
||||
|
||||
State.DIE:
|
||||
await player_sprite.animation_finished
|
||||
player_died.emit()
|
||||
|
||||
func update_animation() -> void:
|
||||
match facing:
|
||||
FaceDirection.LEFT:
|
||||
@@ -222,6 +241,10 @@ func update_animation() -> void:
|
||||
player_sprite.play("shoot_run")
|
||||
State.PUNCH:
|
||||
player_sprite.play("punch")
|
||||
State.HURT:
|
||||
player_sprite.play("hurt")
|
||||
State.DIE:
|
||||
player_sprite.play("die")
|
||||
|
||||
func update_debug():
|
||||
%StateLabel.text = "Current state: %s" % State.keys()[current_state]
|
||||
@@ -2,12 +2,18 @@ class_name SceneManager
|
||||
extends Node2D
|
||||
|
||||
var bullet = preload("res://scenes/bullet.tscn")
|
||||
var coin_scene = preload("res://scenes/coin.tscn")
|
||||
var crate_scene = preload("res://scenes/small_crate.tscn")
|
||||
var enemy_scene = preload("res://scenes/slimer.tscn")
|
||||
var grenade = preload("res://scenes/grenade.tscn")
|
||||
var bullet_array = []
|
||||
var total_allowed_bullets : int = 7
|
||||
|
||||
@onready var coins: Node = $"../Coins"
|
||||
@onready var crates: Node = $"../Crates"
|
||||
@onready var enemies: Node = $"../Enemies"
|
||||
@onready var player: Player = $"../Player"
|
||||
@onready var ui: UI = $"../CanvasLayer/UI"
|
||||
|
||||
func _ready() -> void:
|
||||
GameController.reset()
|
||||
@@ -23,6 +29,14 @@ func build_level() -> void:
|
||||
# Wire up signals from GameController
|
||||
GameController.level_changed.connect(change_scene)
|
||||
GameController.destroyed.connect(destroy)
|
||||
GameController.game_saved.connect(on_game_saved)
|
||||
GameController.game_loaded.connect(on_game_loaded)
|
||||
GameController.player_damaged.connect(player.handle_damage)
|
||||
GameController.player_damaged.connect(ui.update_health)
|
||||
GameController.player_death.connect(player.handle_death)
|
||||
player.player_died.connect(GameController.handle_player_death)
|
||||
GameController.timer_updated.connect(ui.update_timer)
|
||||
GameController.coin_collected.connect(ui.update_coins)
|
||||
|
||||
func update_enemies() -> void:
|
||||
var total_enemies : int = 0
|
||||
@@ -82,3 +96,77 @@ func change_scene(level) -> void:
|
||||
|
||||
func destroy(body) -> void:
|
||||
body.queue_free()
|
||||
|
||||
func on_game_loaded(stash) -> void:
|
||||
print_debug("Loading level with data %s" % str(stash))
|
||||
var player_data = stash.player_data
|
||||
var coins_data = stash.coins_data
|
||||
var crates_data = stash.crates_data
|
||||
var enemies_data = stash.enemies_data
|
||||
# get rid of existing coins
|
||||
if coins:
|
||||
for coin in coins.get_children():
|
||||
# remove listeners
|
||||
coin.tree_exited.disconnect(update_coins)
|
||||
coins.remove_child(coin)
|
||||
coin.queue_free()
|
||||
for coin_transform in coins_data:
|
||||
var coin_object : Coin = coin_scene.instantiate()
|
||||
coins.add_child(coin_object)
|
||||
coin_object.transform = coin_transform
|
||||
update_coins()
|
||||
if crates:
|
||||
for crate in crates.get_children():
|
||||
crates.remove_child(crate)
|
||||
crate.queue_free()
|
||||
for crate_transform in crates_data:
|
||||
var crate_object : RigidBody2D = crate_scene.instantiate()
|
||||
crates.add_child(crate_object)
|
||||
crate_object.transform = crate_transform
|
||||
if enemies:
|
||||
for enemy in enemies.get_children():
|
||||
enemies.remove_child(enemy)
|
||||
enemy.queue_free()
|
||||
for enemy_dict in enemies_data:
|
||||
var enemy_object : Slimer = enemy_scene.instantiate()
|
||||
enemies.add_child(enemy_object)
|
||||
enemy_object.transform = enemy_dict.position
|
||||
GameController.add_enemy_to_level(enemy_object, enemy_dict)
|
||||
player.transform = player_data.position
|
||||
|
||||
func on_game_saved(current_level: int, time_available: int, player_current_health: int, enemies_dict: Dictionary) -> void:
|
||||
print_debug("Saving game!")
|
||||
print_debug("Player health = %s" % str(player_current_health))
|
||||
print_debug("Player transforms = %s" % str(player.transform))
|
||||
var player_data = {
|
||||
"health": player_current_health,
|
||||
"position": player.transform,
|
||||
}
|
||||
var coin_data : Array ## Coin position(s)
|
||||
if coins:
|
||||
for coin in coins.get_children():
|
||||
print_debug("This coin is at %s" % str(coin.transform))
|
||||
coin_data.push_front(coin.transform)
|
||||
var crate_data : Array ## Crate position(s)
|
||||
if crates:
|
||||
for crate in crates.get_children():
|
||||
crate_data.push_front(crate.transform)
|
||||
var enemy_data : Array ## Array of enemies at savepoint
|
||||
for enemy_key in enemies_dict:
|
||||
print_debug("Enemy found at %s" % enemy_key.transform)
|
||||
print_debug("Enemy health is %s" % enemies_dict[enemy_key].damage)
|
||||
print_debug("Enemy damage is %s" % enemies_dict[enemy_key].health)
|
||||
var enemy = {
|
||||
"position": enemy_key.transform,
|
||||
"health": enemies_dict[enemy_key].health,
|
||||
"damage": enemies_dict[enemy_key].damage
|
||||
}
|
||||
enemy_data.push_front(enemy)
|
||||
|
||||
var stash = {
|
||||
"player_data": player_data,
|
||||
"coins_data": coin_data,
|
||||
"crates_data": crate_data,
|
||||
"enemies_data": enemy_data
|
||||
}
|
||||
GameController.stash_game(stash)
|
||||
+14
-1
@@ -5,13 +5,26 @@ extends Area2D
|
||||
@onready var left_cast: RayCast2D = $LeftCast
|
||||
@onready var right_down_cast: RayCast2D = $RightDownCast
|
||||
@onready var left_down_cast: RayCast2D = $LeftDownCast
|
||||
@onready var slime_sprite: AnimatedSprite2D = $SlimeSprite
|
||||
|
||||
var speed : int = 100
|
||||
var speed : int = 25
|
||||
var direction : int = 1
|
||||
|
||||
signal player_slimed(body, slime)
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if not right_down_cast.is_colliding():
|
||||
direction = -1
|
||||
slime_sprite.flip_h = true
|
||||
#if not left_down_cast.is_colliding():
|
||||
#direction = 1
|
||||
#slime_sprite.flip_h = false
|
||||
#if not right_cast.is_colliding():
|
||||
#direction = -1
|
||||
#slime_sprite.flip_h = true
|
||||
#if not left_cast.is_colliding():
|
||||
#direction = 1
|
||||
#slime_sprite.flip_h = false
|
||||
position.x += direction * speed * delta
|
||||
|
||||
func _on_body_entered(body: Node2D) -> void:
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class_name UI
|
||||
extends Control
|
||||
|
||||
@onready var health_label: Label = $VBoxContainer/HBoxContainer/MarginContainer/HealthLabel
|
||||
@onready var timer_label: Label = $VBoxContainer/HBoxContainer/MarginContainer2/TimerLabel
|
||||
@onready var coins_label: Label = $VBoxContainer/HBoxContainer/MarginContainer3/CoinsLabel
|
||||
|
||||
func update_health(current_health, max_health) -> void:
|
||||
health_label.text = "Health: " + str(current_health)
|
||||
|
||||
func update_timer(time_remaining) -> void:
|
||||
timer_label.text = "Time: " + str(time_remaining)
|
||||
|
||||
func update_coins(coins_remaining) -> void:
|
||||
coins_label.text = "Coins: " + str(coins_remaining)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bpyw8duggqhke
|
||||
Reference in new issue
Block a user