From 628ad64eef75ed9f362d04608f44fb3ed55615e2 Mon Sep 17 00:00:00 2001 From: Sagi Dayan Date: Mon, 28 Sep 2020 21:36:57 -0400 Subject: [PATCH] Added GameState singleton + save data --- assets/HUD/lifes_icon.png | Bin 245 -> 1837 bytes project.godot | 1 + src/Actors/Player.gd | 1 + src/HUD/HUD.gd | 25 ++++++++-- src/HUD/HUD.tscn | 74 ++++++++++++++++++++++----- src/Intro/Intro.gd | 2 +- src/Items/Coin.gd | 3 +- src/Items/Coin.tscn | 4 +- src/Menu/MainMenu.gd | 3 +- src/Menu/PauseMenu.gd | 5 +- src/Singletons/GameState.gd | 96 ++++++++++++++++++++++++++++++++++++ 11 files changed, 188 insertions(+), 26 deletions(-) create mode 100644 src/Singletons/GameState.gd diff --git a/assets/HUD/lifes_icon.png b/assets/HUD/lifes_icon.png index 720c0085cbd3171a8c5b36bf48215ee95319ae4e..3bb3c17aaa5bac4fc69d2f1c78751d33740e8be1 100644 GIT binary patch delta 1754 zcmV<01||9R0j&;@BYy;BdQ@0+Qek%>aB^>EX>4U6ba`-PAZ2)IW&i+q+T~YSw&N%a z{bv=u1WOlnD}!U|ufLo53qPh1j1vt$dcWc4 zqKlj`2;2O{ai`6V`+C?egOl7G6AY0>Z|9??rJo>|tHC7(?SE&v32TPKazuyY@v}X0 zAD3H@kn@z2TaIF#10RFlLfx06yc7qNb-4r9?E14g2^3i>f6qjJEqeZl^r7eT=hfpS>|f2g_sX4G~&h) zFH=C|LQrLbGwL)yYv$GDH_fz`dx~faN3MX2dtC!YXMe8Wp#?&yE#71#_|g{r+fDtT zRKcK(GzTm&ZTobw3tel=4xTOa1pR!4$Y@y(kRrqufFTP8HcwW_)27Tygggcilz^PA z;~fl;2p524XRT+Wj8_J+VWTv3S=e(IV{ZZxV!c&xgZB$$IVY$ebpbV$#EKIUFDk)E zl;o{iZ^_)T&cauc|?#reK2$5`54QLJTQ#wAceB`lvC)7*k@C5GcV{f_{Qz z=iTmZm)-BWhdu5oqkOWi@kL80v7}0-VyCFCO7&H1sIjJoT5Gns zCe1f(p~aRC))uP|?F-guvBra`uBQiUkQ&vC3xDd{iFD4u7&`*v+8IDWbLVUelE6BGqqT4@wNt;)5vuL=<__EvyhrxU-TdXeD>F_cOlhOr7QpliW zW+ev)^?j}(Sz9&DHRIU0SUei|9=HErvoYfHAWyZj`7}fJe?I44OD+@5FkvrO6Mu8j zNqf0n-CQ^xZPt{ZdA{k*T}ZDtAwNR7EX;%TE#P~c6ffo{K02Z1mf2@LHHqbh@t=yr zy!G*8)r_J!)rE24jjO|D-ItS$+6wV5gXS$A?+amsG9O^MF7pMA=4&ud`u~C>#b+S? z-kW~_4>AXO<-^Lu0004mX+uL$Nq<8_AaHVTW@&6?004NLeUUv#!$2IxUsI(jl@4~0 z;*g;_Stu&vs8uLJg-|QB>R@u|7c^-|Qd}Gb*Mfr|i&X~~XI&j!1wrrw#L3Y~(M3x9 zUs`Ap|pWR>`wc-*855RA3`Ut4@lAH0>um{C^SGFOf?jR~d{P3#dYa?E1m~;CHuHVRE9C6ifiUFOKsu z3Iuk6X5DeVj~%CZ0{EYSE4|~dHh`H=((4^9dIW^Ffs5;ortATiJHYUhA)B%*`DqG; z0`PuD-;@J}Zh?WdR&VWnoIU^<>MC^u92^2;Mao|Hcz0iSZ~vZY_fGc%aO85P4x+5N z00006VoOIv0J#9Q0K+A0e(L}L010qNS#tmY3ljhU3ljkVnw%H_000McNliruvc|!mI0J=#;K~y-)kt-eo7F>}`EqnR@_1O$Q-Pu)j1q^LX z6Bw%M3Q+hs4LE!DEW?>48E`&KGqMX{hG7IEa@3i`%s?>+9UuoH6LKP1y?ZgjWX)9a wQX$$4M_013-#Fh1lbR{#J207*qoM6N<$f&p?b?f?J) delta 177 zcmV;i08am{4)p<$BPjs9NklKe@{2Ln^GcaI@i8D(wQ1}=r3s)k70puveY5>d- fTn1oE&I1boXu)6w3d;Zx00000NkvXXu0mjfXm3U$ diff --git a/project.godot b/project.godot index ce4070c..4816a2d 100644 --- a/project.godot +++ b/project.godot @@ -60,6 +60,7 @@ config/icon="res://icon.png" [autoload] AudioManager="*res://src/Singletons/AudioManager.tscn" +GameState="*res://src/Singletons/GameState.gd" [display] diff --git a/src/Actors/Player.gd b/src/Actors/Player.gd index 7cb2628..b66b819 100644 --- a/src/Actors/Player.gd +++ b/src/Actors/Player.gd @@ -188,6 +188,7 @@ func _on_die_animation_done(): func die(): _alive = false + GameState.player_died() $AnimationPlayer.play("die") func setAbility(ability:String, enabled:bool=false): diff --git a/src/HUD/HUD.gd b/src/HUD/HUD.gd index 152237c..74768c5 100644 --- a/src/HUD/HUD.gd +++ b/src/HUD/HUD.gd @@ -7,11 +7,28 @@ onready var Lable = get_node("CoinsContainer/Label") var _paused = false; var _pause_ref; -func on_coin_collected(amount:int): - coins_amount += amount - Lable.text = str(coins_amount) +var _data_ref = null; +func _ready() -> void: + _data_ref = GameState.get_run_data() func _physics_process(delta: float) -> void: + _handle_pause() + var fresh_data = GameState.get_run_data() + for key in fresh_data: + if not fresh_data[key] == _data_ref[key]: + print("[%s]: %s -> %s" % [str(key), str(_data_ref[key]), str(fresh_data[key])]) + match(str(key)): + "coins": + $UI/CoinLabel.text = str(fresh_data.coins) + $UI/CoinLabel/AnimationPlayer.seek(0) + $UI/CoinLabel/AnimationPlayer.play("updated") + "deaths": + $UI/DeathsLabel.text = str(fresh_data.deaths) + + pass + _data_ref = fresh_data + +func _handle_pause(): if Input.is_action_just_pressed("pause"): if _paused: _pause_ref.dismiss() @@ -21,7 +38,7 @@ func _physics_process(delta: float) -> void: add_child(_pause_ref) get_tree().paused = true _paused = true - + func _on_pause_menu_dismissed(): _paused = false get_tree().paused = false diff --git a/src/HUD/HUD.tscn b/src/HUD/HUD.tscn index f465e8b..cef3a4f 100644 --- a/src/HUD/HUD.tscn +++ b/src/HUD/HUD.tscn @@ -1,31 +1,79 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=7 format=2] [ext_resource path="res://src/HUD/HUD.gd" type="Script" id=1] [ext_resource path="res://src/Menu/PauseMenu.tscn" type="PackedScene" id=2] [ext_resource path="res://assets/Theme/Theme.tres" type="Theme" id=3] [ext_resource path="res://assets/HUD/coins_hud.png" type="Texture" id=4] +[ext_resource path="res://assets/HUD/lifes_icon.png" type="Texture" id=5] + +[sub_resource type="Animation" id=1] +resource_name = "updated" +length = 0.2 +tracks/0/type = "value" +tracks/0/path = NodePath(".:rect_scale") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/keys = { +"times": PoolRealArray( 0, 0.2 ), +"transitions": PoolRealArray( 0.466517, 1 ), +"update": 0, +"values": [ Vector2( 2, 2 ), Vector2( 1, 1 ) ] +} [node name="HUD" type="CanvasLayer"] script = ExtResource( 1 ) PauseMenu = ExtResource( 2 ) -[node name="CoinsContainer" type="HBoxContainer" parent="."] -margin_left = 18.0 -margin_top = 13.0 -margin_right = 87.0 -margin_bottom = 22.0 +[node name="UI" type="NinePatchRect" parent="."] +anchor_right = 1.0 +anchor_bottom = 1.0 __meta__ = { "_edit_use_anchors_": false } -[node name="TextureRect" type="TextureRect" parent="CoinsContainer"] -margin_right = 9.0 -margin_bottom = 9.0 +[node name="Coin" type="TextureRect" parent="UI"] +margin_left = 18.0 +margin_top = 13.0 +margin_right = 27.0 +margin_bottom = 22.0 texture = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} -[node name="Label" type="Label" parent="CoinsContainer"] -margin_left = 13.0 -margin_right = 19.0 -margin_bottom = 9.0 +[node name="CoinLabel" type="Label" parent="UI"] +margin_left = 38.0 +margin_top = 13.0 +margin_right = 44.0 +margin_bottom = 22.0 theme = ExtResource( 3 ) text = "0" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/CoinLabel"] +anims/updated = SubResource( 1 ) + +[node name="Deaths" type="TextureRect" parent="UI"] +margin_left = 11.0 +margin_top = 22.0 +margin_right = 33.0 +margin_bottom = 44.0 +texture = ExtResource( 5 ) +expand = true + +[node name="DeathsLabel" type="Label" parent="UI"] +margin_left = 38.0 +margin_top = 30.0 +margin_right = 78.0 +margin_bottom = 44.0 +theme = ExtResource( 3 ) +text = "0" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="AnimationPlayer" type="AnimationPlayer" parent="UI/DeathsLabel"] diff --git a/src/Intro/Intro.gd b/src/Intro/Intro.gd index 6ba654e..33c7449 100644 --- a/src/Intro/Intro.gd +++ b/src/Intro/Intro.gd @@ -10,7 +10,7 @@ func _ready() -> void: func load_next_scene(): # var next_scene = load("res://src/Levels/LevelTemplate/LevelTemplate.tscn") - get_tree().change_scene_to(next_scene) + GameState.go_to_main_menu() queue_free() func stop_splash_voice(): diff --git a/src/Items/Coin.gd b/src/Items/Coin.gd index 5dd7a26..9eb8c6d 100644 --- a/src/Items/Coin.gd +++ b/src/Items/Coin.gd @@ -10,6 +10,7 @@ func _on_body_entered(body: Node) -> void: if body.name == "Player": $Label.text = str(value) AudioManager.play_sfx(AudioManager.Sfx.COIN_COLLECTION) - emit_signal("collected", value) +# emit_signal("collected", value) + GameState.coin_collected() $AnimationPlayer.play("collected") pass # Replace with function body. diff --git a/src/Items/Coin.tscn b/src/Items/Coin.tscn index b5a5aef..71f27a6 100644 --- a/src/Items/Coin.tscn +++ b/src/Items/Coin.tscn @@ -190,11 +190,11 @@ collision_layer = 16 script = ExtResource( 2 ) [node name="Sprite" type="Sprite" parent="."] -position = Vector2( 0, -4 ) +position = Vector2( 0, -8 ) texture = ExtResource( 1 ) vframes = 2 hframes = 6 -frame = 6 +frame = 8 [node name="CollisionShape2D" type="CollisionShape2D" parent="."] visible = false diff --git a/src/Menu/MainMenu.gd b/src/Menu/MainMenu.gd index 52bd097..6e8fbd6 100644 --- a/src/Menu/MainMenu.gd +++ b/src/Menu/MainMenu.gd @@ -14,8 +14,7 @@ func _on_ControlsBtn_pressed() -> void: func _on_NewGameBtn_pressed() -> void: - var next_scene = load("res://src/Levels/LevelTemplate/LevelTemplate.tscn") - get_tree().change_scene_to(next_scene) + GameState.start_new_game() queue_free() func _input(event: InputEvent) -> void: diff --git a/src/Menu/PauseMenu.gd b/src/Menu/PauseMenu.gd index a4eb634..22503cc 100644 --- a/src/Menu/PauseMenu.gd +++ b/src/Menu/PauseMenu.gd @@ -28,10 +28,9 @@ func _on_ResumeBtn_pressed() -> void: func _on_ExitToMainMenuBtn_pressed() -> void: $AnimationPlayer.play_backwards("fade") yield($AnimationPlayer, "animation_finished"); - var next_scene = load("res://src/Menu/MainMenu.tscn") emit_signal("dismissed") AudioManager.play_music(AudioManager.Music.Intro, .2) - get_tree().change_scene_to(next_scene) + GameState.go_to_main_menu() queue_free() @@ -39,7 +38,7 @@ func _on_NewGameBtn_pressed() -> void: $AnimationPlayer.play_backwards("fade") yield($AnimationPlayer, "animation_finished"); emit_signal("dismissed") - get_tree().reload_current_scene() + GameState.start_new_game() pass # Replace with function body. diff --git a/src/Singletons/GameState.gd b/src/Singletons/GameState.gd new file mode 100644 index 0000000..a851290 --- /dev/null +++ b/src/Singletons/GameState.gd @@ -0,0 +1,96 @@ +extends Node + +enum States{ + INTRO, + MAIN_MENU, + GAME_OVER, + CONTROLS, + GAME, + PUSE, + STATS, + CUT_SCENE, +} +var _SAVE_FILE_PATH = "user://data" +# Change key in release +var _ENCRYPTION_KEY = "fas3uyf076HJsiUDs24dfI9" + +var _SCENES := { + States.MAIN_MENU: "res://src/Menu/MainMenu.tscn", + States.GAME: "res://src/Levels/LevelTemplate/LevelTemplate.tscn", +} + +var _data := { + "statistics": { + "deaths": 0, + "clears": 0, + "runs": 0, + "total_time_played": 0, + "orbs": 0, + "coins": 0, + }, + "heigh_score": { + "deaths": 0, + "score": 0, + "cleard": false, + "coins": 0, + "orbs": 0, + "time": 0, + } + } + +var _run_data:= { + "deaths": 0, + "coins": 0, + "orbs": 0, + "time": 0, + "score": 0 +} + +var _state = States.INTRO + +func _ready() -> void: + load_data() + print(get_statistics()) + +func load_data(): + var data_file = File.new() + var e = data_file.open_encrypted_with_pass(_SAVE_FILE_PATH, File.READ, _ENCRYPTION_KEY) + if e != 0: + data_file.close() + save_data() + else: + _data = data_file.get_var() + data_file.close() + pass + +func save_data(): + var data_file = File.new() + print(data_file.open_encrypted_with_pass(_SAVE_FILE_PATH, File.WRITE, _ENCRYPTION_KEY)) + print(data_file.store_var(_data)) + data_file.close() + pass + +func start_new_game(): + for key in _run_data.keys(): + _run_data[key] = 0 + _state = States.GAME + _data.statistics.runs += 1 + save_data() + get_tree().change_scene_to(load(_SCENES[_state])) +func get_heigh_score(): + return _data.heigh_score.duplicate() +func get_statistics(): + return _data.statistics.duplicate() +func get_run_data(): + return _run_data.duplicate() + +func go_to_main_menu(): + _state = States.MAIN_MENU + save_data() + get_tree().change_scene_to(load(_SCENES[_state])) +func player_died(): + _run_data.deaths += 1 + _data.statistics.deaths += 1 +func coin_collected(): + _run_data.coins += 10 + _data.statistics.coins += 10