Compare commits

...

19 Commits

Author SHA1 Message Date
817bd96433 Refactor HUD and MainMenu components to use Node attribute for better scene integration 2025-08-15 03:15:54 +02:00
2cc54f7b37 Add game scene and level catalog interfaces, and implement scene management in AppRoot 2025-08-15 03:04:21 +02:00
406036504a Implement core game functionality with AppRoot, SaveClient, PlayerRepository, and LevelRepository classes 2025-08-15 02:46:02 +02:00
173f0e5703 Add Chickensoft packages for enhanced functionality and dependency management 2025-08-15 00:58:19 +02:00
d84f7d1740 Csharp rewrite (#4)
* Implement BeamComponent in C# and enhance marketplace button functionality

* Add core game components including ConfigFileHandler, GameManager, SaveSystem, and UIManager

* cleanup

* Add new components: CanPickUpComponent, CollapsableComponent, DestroyableComponent, EffectInflictorComponent, StatusEffectComponent, and StatusEffectDataResource

* Add new components: EnemyDeathComponent, EnemyWaveTriggerComponent, and ExitDoorComponent

* Add new components: ExplosiveComponent, FadeAwayComponent, FireEffectComponent, FlipComponent, GravityMotionComponent, LaunchComponent, and update PlatformMovement with LastDirection property

* Add new components: HealComponent, HitComponent, HomingMissileMotionComponent, LeverComponent, and TriggerLeverComponent

* Refactor GameManager session state handling and add new components: CanBeLaunchedComponent, IceEffectComponent, JumpPadComponent, KillPlayerOutOfScreenComponent, KnockbackComponent, LifetimeComponent, MagneticSkillComponent, OutOfScreenComponent, PeriodicShootingComponent, PlayerDeathComponent, ProgressiveDamageComponent, ProjectileComponent, ProjectileInitComponent, RequirementComponent, ScoreComponent, ShipMovementComponent, ShipShooterComponent, and SideToSideMovementComponent

* Add new components: CannotStompComponent, SkillUnlockedComponent, SpaceshipEnterComponent, SpaceshipExitComponent, SpinComponent, StompDamageComponent, StraightMotionComponent, TerrainHitFx, TooltipComponent, TrailComponent, and UnlockOnRequirementComponent

* Add new components: BrickThrowComponent, BulletComponent, CageComponent, ChaseLevelComponent, CleanupComponent, and ThrowInputResource classes; implement game saving and loading logic in SaveSystem

* Add audio settings management and platform movement component

* Add ChargeProgressBar, Credits, and GameOverScreen components for UI management

* Add UID files for ConfigFileHandler, GameManager, SaveSystem, and UIManager components

* Add README.md file with game description and features; include project license and contribution guidelines

* Add Hud component for UI management; display health, coins, and lives

* Add MainMenu and Marketplace components; implement game management and skill unlocking features

* Add PauseMenu, SettingsMenu, and SkillButton components; enhance game management and UI functionality
2025-08-15 00:45:57 +02:00
2ad0fe26d2 Fix formatting in README.md for improved readability 2025-08-13 00:57:38 +02:00
c4f7be1b10 Remove license badge from README.md for cleaner presentation (#3) 2025-08-13 00:54:21 +02:00
b957b56567 Enhance README.md with project badges and statistics for improved visibility 2025-08-13 00:52:04 +02:00
cce93286be Update README.md with game story, mission, and features; enhance promotional content (#2) 2025-08-13 00:46:19 +02:00
58eeef60dc Refactor skill management and marketplace UI for improved functionality 2025-06-19 16:37:31 +02:00
d73931dad4 Update scene resources and improve health management logic 2025-06-12 23:36:34 +02:00
cc737f22cf Add marketplace button functionality and skill unlocker integration 2025-06-05 22:50:45 +02:00
87b85cae43 Add skill type enumeration and update skill management for throw skills 2025-06-05 01:54:32 +02:00
039dc1d5e5 Add screenshot functionality and new level scene to game manager 2025-06-05 01:00:10 +02:00
df154a786c Add minimum jump height, fire rate configuration, and improve throw input handling 2025-05-29 01:33:54 +02:00
9b6a4f38bd Refactor health management and collectable cleanup logic for improved functionality 2025-05-29 01:19:18 +02:00
a098155b0f Fix collectable fade away logic to ensure proper cleanup after sound effect finishes 2025-05-29 01:03:49 +02:00
26af7a591d Add terrain hit effects, progressive damage component, and update collectable signals 2025-05-29 01:00:19 +02:00
37b96c0f11 Add spaceship exit component, enemy wave trigger, and update various scene properties 2025-05-25 20:10:48 +02:00
320 changed files with 7431 additions and 218 deletions

View File

@@ -0,0 +1,27 @@
using Godot;
namespace Mr.BrickAdventures.Autoloads;
public partial class ConfigFileHandler : Node
{
private ConfigFile _settingsConfig = new();
public const string SettingsPath = "user://settings.ini";
public ConfigFile SettingsConfig => _settingsConfig;
public override void _Ready()
{
if (!FileAccess.FileExists(SettingsPath))
{
var err = _settingsConfig.Save(SettingsPath);
if (err != Error.Ok)
GD.PushError($"Failed to create settings file at {SettingsPath}: {err}");
}
else
{
var err = _settingsConfig.Load(SettingsPath);
if (err != Error.Ok)
GD.PushError($"Failed to load settings file at {SettingsPath}: {err}");
}
}
}

View File

@@ -0,0 +1 @@
uid://8cyvbeyd13cj

241
Autoloads/GameManager.cs Normal file
View File

@@ -0,0 +1,241 @@
using System.Collections.Generic;
using System.Linq;
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.scripts.components;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.Autoloads;
public partial class GameManager : Node
{
[Export] public Array<PackedScene> LevelScenes { get; set; } = new();
public PlayerController Player { get; set; }
private List<Node> _sceneNodes = new();
public Dictionary PlayerState { get; set; } = new()
{
{ "coins", 0 },
{ "lives", 3 },
{ "current_level", 0 },
{ "completed_levels", new Array<int>() },
{ "unlocked_levels", new Array<int>() {0}},
{ "unlocked_skills", new Array<SkillData>() }
};
public Dictionary CurrentSessionState { get; private set; } = new()
{
{ "coins_collected", 0 },
{ "skills_unlocked", new Array<SkillData>() }
};
public override void _EnterTree()
{
GetTree().NodeAdded += OnNodeAdded;
GetTree().NodeRemoved += OnNodeRemoved;
}
public override void _ExitTree()
{
GetTree().NodeAdded -= OnNodeAdded;
GetTree().NodeRemoved -= OnNodeRemoved;
_sceneNodes.Clear();
}
private void OnNodeAdded(Node node)
{
_sceneNodes.Add(node);
}
private void OnNodeRemoved(Node node)
{
_sceneNodes.Remove(node);
}
public void AddCoins(int amount)
{
PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"] + amount);
}
public void SetCoins(int amount) => PlayerState["coins"] = Mathf.Max(0, amount);
public int GetCoins() => (int)PlayerState["coins"] + (int)CurrentSessionState["coins_collected"];
public void RemoveCoins(int amount)
{
var sessionCoins = (int)CurrentSessionState["coins_collected"];
if (amount <= sessionCoins)
{
CurrentSessionState["coins_collected"] = sessionCoins - amount;
}
else
{
var remaining = amount - sessionCoins;
CurrentSessionState["coins_collected"] = 0;
PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"] - remaining);
}
PlayerState["coins"] = Mathf.Max(0, (int)PlayerState["coins"]);
}
public void AddLives(int amount) => PlayerState["lives"] = (int)PlayerState["lives"] + amount;
public void RemoveLives(int amount) => PlayerState["lives"] = (int)PlayerState["lives"] - amount;
public void SetLives(int amount) => PlayerState["lives"] = amount;
public int GetLives() => (int)PlayerState["lives"];
public bool IsSkillUnlocked(SkillData skill)
{
return ((Array)PlayerState["unlocked_skills"]).Contains(skill)
|| ((Array)CurrentSessionState["skills_unlocked"]).Contains(skill);
}
public void UnlockSkill(SkillData skill)
{
if (!IsSkillUnlocked(skill))
((Array)PlayerState["unlocked_skills"]).Add(skill);
}
public void RemoveSkill(string skillName)
{
var arr = (Array)PlayerState["unlocked_skills"];
foreach (SkillData s in arr)
{
if (s.Name != skillName) continue;
arr.Remove(s);
break;
}
}
public void UnlockSkills(Array<SkillData> skills)
{
foreach (var s in skills)
UnlockSkill(s);
}
public void ResetPlayerState()
{
PlayerState = new Dictionary
{
{ "coins", 0 },
{ "lives", 3 },
{ "current_level", 0 },
{ "completed_levels", new Array<int>() },
{ "unlocked_levels", new Array<int>() {0}},
{ "unlocked_skills", new Array<SkillData>() }
};
}
public void UnlockLevel(int levelIndex)
{
var unlocked = (Array)PlayerState["unlocked_levels"];
if (!unlocked.Contains(levelIndex)) unlocked.Add(levelIndex);
}
public void TryToGoToNextLevel()
{
var next = (int)PlayerState["current_level"] + 1;
var unlocked = (Array)PlayerState["unlocked_levels"];
if (next < LevelScenes.Count && unlocked.Contains(next))
{
PlayerState["current_level"] = next;
GetTree().ChangeSceneToPacked(LevelScenes[next]);
}
}
public void MarkLevelComplete(int levelIndex)
{
UnlockLevel(levelIndex + 1);
var completed = (Array)PlayerState["completed_levels"];
if (!completed.Contains(levelIndex)) completed.Add(levelIndex);
}
public void ResetCurrentSessionState()
{
CurrentSessionState = new Dictionary
{
{ "coins_collected", 0 },
{ "skills_unlocked", new Array<SkillData>() }
};
}
public void RestartGame()
{
ResetPlayerState();
ResetCurrentSessionState();
GetTree().ChangeSceneToPacked(LevelScenes[0]);
GetNode<SaveSystem>("/root/SaveSystem").SaveGame();
}
public void QuitGame() => GetTree().Quit();
public void PauseGame() => Engine.TimeScale = 0;
public void ResumeGame() => Engine.TimeScale = 1;
public void StartNewGame()
{
ResetPlayerState();
ResetCurrentSessionState();
GetTree().ChangeSceneToPacked(LevelScenes[0]);
GetNode<SaveSystem>("/root/SaveSystem").SaveGame();
}
public void ContinueGame()
{
var save = GetNode<SaveSystem>("/root/SaveSystem");
if (!save.LoadGame())
{
GD.PrintErr("Failed to load game. Starting a new game instead.");
StartNewGame();
return;
}
var idx = (int)PlayerState["current_level"];
if (idx < LevelScenes.Count)
GetTree().ChangeSceneToPacked(LevelScenes[idx]);
else
GD.PrintErr("No levels unlocked to continue.");
}
public void OnLevelComplete()
{
var levelIndex = (int)PlayerState["current_level"];
MarkLevelComplete(levelIndex);
AddCoins((int)CurrentSessionState["coins_collected"]);
foreach (var s in (Array)CurrentSessionState["skills_unlocked"])
UnlockSkill((SkillData)s);
ResetCurrentSessionState();
TryToGoToNextLevel();
GetNode<SaveSystem>("/root/SaveSystem").SaveGame();
}
public Array<SkillData> GetUnlockedSkills()
{
var unlocked = (Array<SkillData>)PlayerState["unlocked_skills"];
var session = (Array<SkillData>)CurrentSessionState["skills_unlocked"];
if (session!.Count == 0) return unlocked;
if (unlocked!.Count == 0) return session;
var joined = new Array<SkillData>();
joined.AddRange(unlocked);
joined.AddRange(session);
return joined;
}
public PlayerController GetPlayer()
{
if (Player != null) return Player;
foreach (var node in _sceneNodes)
{
if (node is not PlayerController player) continue;
Player = player;
return Player;
}
GD.PrintErr("PlayerController not found in the scene tree.");
return null;
}
}

View File

@@ -0,0 +1 @@
uid://c6eoi3ymefc0x

61
Autoloads/SaveSystem.cs Normal file
View File

@@ -0,0 +1,61 @@
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.scripts.Resources;
namespace Mr.BrickAdventures.Autoloads;
public partial class SaveSystem : Node
{
[Export] public string SavePath { get; set; } = "user://savegame.save";
[Export] public int Version { get; set; } = 1;
private GameManager _gameManager;
public override void _Ready()
{
_gameManager = GetNode<GameManager>("/root/GameManager");
}
public void SaveGame()
{
var saveData = new Dictionary
{
{ "player_state", _gameManager.PlayerState},
{ "version", Version}
};
using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Write);
file.StoreVar(saveData);
GD.Print("Game state saved to: ", SavePath);
}
public bool LoadGame()
{
if (!FileAccess.FileExists(SavePath))
return false;
using var file = FileAccess.Open(SavePath, FileAccess.ModeFlags.Read);
var saveDataObj = (Dictionary)file.GetVar();
if (saveDataObj.ContainsKey("version") && (int)saveDataObj["version"] != Version)
{
GD.Print($"Save file version mismatch. Expected: {Version}, Found: {saveDataObj["version"]}");
return false;
}
GD.Print("Game state loaded from: ", SavePath);
GD.Print("Player state: ", saveDataObj["player_state"]);
_gameManager.PlayerState = (Dictionary)saveDataObj["player_state"];
var skills = new Array<SkillData>();
foreach (var skill in (Array<SkillData>)_gameManager.PlayerState["unlocked_skills"])
{
skills.Add(skill);
}
_gameManager.UnlockSkills(skills);
return true;
}
public bool CheckSaveExists() => FileAccess.FileExists(SavePath);
}

View File

@@ -0,0 +1 @@
uid://bh20fqbyifidc

65
Autoloads/UIManager.cs Normal file
View File

@@ -0,0 +1,65 @@
using Godot;
using Godot.Collections;
namespace Mr.BrickAdventures.Autoloads;
public partial class UIManager : Node
{
[Export] public Array<Control> UiStack { get; set; } = new();
[Signal] public delegate void ScreenPushedEventHandler(Control screen);
[Signal] public delegate void ScreenPoppedEventHandler(Control screen);
public void PushScreen(Control screen)
{
if (screen == null)
{
GD.PushError($"Cannot push a null screen.");
return;
}
UiStack.Add(screen);
screen.Show();
screen.SetProcessInput(true);
screen.SetFocusMode(Control.FocusModeEnum.All);
screen.GrabFocus();
EmitSignalScreenPushed(screen);
}
public void PopScreen()
{
if (UiStack.Count == 0)
{
GD.PushError($"Cannot pop screen from an empty stack.");
return;
}
var top = (Control)UiStack[^1];
UiStack.RemoveAt(UiStack.Count - 1);
top.Hide();
top.SetProcessInput(false);
EmitSignalScreenPopped(top);
top.AcceptEvent();
if (UiStack.Count > 0) ((Control)UiStack[^1]).GrabFocus();
}
public Control TopScreen() => UiStack.Count > 0 ? (Control)UiStack[^1] : null;
public bool IsScreenOnTop(Control screen) => UiStack.Count > 0 && (Control)UiStack[^1] == screen;
public bool IsVisibleOnStack(Control screen) => UiStack.Contains(screen) && screen.Visible;
public void CloseAll()
{
while (UiStack.Count > 0)
PopScreen();
}
public static void HideAndDisable(Control screen)
{
screen.Hide();
screen.SetProcessInput(false);
}
}

View File

@@ -0,0 +1 @@
uid://c3ldmnrwperr4

View File

@@ -0,0 +1,13 @@
<Project Sdk="Godot.NET.Sdk/4.4.1">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>Mr.BrickAdventures</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Chickensoft.AutoInject" Version="2.8.21" />
<PackageReference Include="Chickensoft.GodotNodeInterfaces" Version="2.4.31" />
<PackageReference Include="Chickensoft.Introspection" Version="3.0.2" />
<PackageReference Include="Chickensoft.Introspection.Generator" Version="3.0.2" PrivateAssets="all" OutputItemType="analyzer" />
</ItemGroup>
</Project>

19
Mr. Brick Adventures.sln Normal file
View File

@@ -0,0 +1,19 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mr. Brick Adventures", "Mr. Brick Adventures.csproj", "{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
ExportDebug|Any CPU = ExportDebug|Any CPU
ExportRelease|Any CPU = ExportRelease|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU
{A1D482B9-207B-4D6C-A0A0-D9E6D1AE2356}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,6 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACanvasItem_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fef7b819b226fab796d1dfe66d415dd7510bcac87675020ddb8f03a828e763_003FCanvasItem_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACollisionShape2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F2ca9b7334678f5c97c7c2a9fbe4837be71cae11b6a30408dd4791b18f997e4a_003FCollisionShape2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F86db9cd834346aad02d74c1b66dd9c64d6ef3147435dd9c9c9477b48f7_003FNode2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ARectangleShape2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fa1cc98873548652da0c14ecefa4737431426fcbb24a7f0641e3d9c266c3_003FRectangleShape2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AShape2D_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F3671dbbd9b17cdf2bf9075b468b6bd7e3ab13fc3be7a116484085d3b6cc9fe_003FShape2D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String></wpf:ResourceDictionary>

72
README.md Normal file
View File

@@ -0,0 +1,72 @@
# Przygody Pana Cegły
[![Steam Wishlist](https://img.shields.io/badge/🎮%20PLAY%20NOW%20on%20Steam-FF4C4C?style=for-the-badge&logo=steam&logoColor=white)](https://store.steampowered.com/app/3575090/Mr_Brick_Adventures/)
![Made With Godot](https://img.shields.io/badge/Made%20With-Godot-478CBF?style=for-the-badge&logo=godot-engine&logoColor=white)
![Lines of Code](https://tokei.rs/b1/github/GKaszewski/ppc_v2?style=for-the-badge&category=code)
![Last Commit](https://img.shields.io/github/last-commit/GKaszewski/ppc_v2?style=for-the-badge)
![Stars](https://img.shields.io/github/stars/GKaszewski/ppc_v2?style=for-the-badge)
*"The worlds only brick-throwing dad simulator (probably)."*
---
## The Story
Disaster has struck!
Mr. Bricks kids have gone missing, scattered across mysterious lands filled with treacherous traps, cranky critters, and more collapsing bridges than an OSHA nightmare.
Armed with nothing but his legs, his wits, and an infinite supply of throwable bricks (dont ask where he keeps them), Mr. Brick will stop at nothing to bring his children home.
---
## The Mission
Run, jump, and hurl bricks with pinpoint accuracy as you navigate dangerous worlds. Smash enemies, trigger ancient mechanisms, and uncover hidden treasures, all while dodging hazards that seem designed specifically to ruin your day.
---
## Features Thatll Knock Your Bricks Off
* **Tight, Classic Platforming**
Leap over pits, time your jumps, and try not to land in something unpleasant.
* **Brick-Fu Combat**
Toss bricks to flatten foes, flip switches, and solve puzzles in the most dad-like way possible.
* **Secrets & Collectibles**
Hunt for coins, discover hidden rooms, and find upgrades to make you just a *little* less fragile.
* **NES-Inspired Pixel Art**
All the charm of an 8-bit classic, no cartridge blowing required.
---
## Play It Here
[**Wishlist on Steam**](https://store.steampowered.com/app/3575090/Mr_Brick_Adventures/) so youre ready for launch day.
---
## 📊 Project Stats
📦 **Lines of Code:**
![Lines of code](https://tokei.rs/b1/github/GKaszewski/ppc_v2)
📈 **Repo Activity:**
![Commit activity](https://img.shields.io/github/commit-activity/m/GKaszewski/ppc_v2)
---
## License
Check the [LICENSE](./LICENSE) for the legal stuff.
---
## Contributing
Not open to code contributions right now but you *can* help by:
* Reporting bugs
* Suggesting evil new trap ideas
* Spreading the word so Mr. Brick can find his kids faster

10
app/IGameScenes.cs Normal file
View File

@@ -0,0 +1,10 @@
using Godot;
namespace Mr.BrickAdventures.app;
public interface IGameScenes
{
void Load(PackedScene scene);
void Restart();
void ReturnToMain(PackedScene mainMenu);
}

1
app/IGameScenes.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://b7d1ospa5p4nx

11
app/ILevelCatalog.cs Normal file
View File

@@ -0,0 +1,11 @@
using Godot;
namespace Mr.BrickAdventures.app;
public interface ILevelCatalog
{
int Count { get; }
PackedScene? Get(int index);
PackedScene First { get; }
PackedScene MainMenu { get; }
}

1
app/ILevelCatalog.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://b2sxttgvk6nuq

View File

@@ -30,9 +30,9 @@ func load_game() -> bool:
print("Game state loaded from: ", save_path)
print("Player state: ", save_data["player_state"])
gm.player_state = save_data["player_state"]
var skills: Array[String] = []
for skill_name in gm.player_state["unlocked_skills"]:
skills.append(skill_name)
var skills: Array[SkillData] = []
for skill in gm.player_state["unlocked_skills"]:
skills.append(skill)
gm.unlock_skills(skills)
return true

View File

@@ -51,4 +51,4 @@ func close_all() -> void:
func hide_and_disable(screen: Control) -> void:
screen.hide()
screen.set_process_input(false)
screen.set_process_input(false)

70
common/AppRoot.cs Normal file
View File

@@ -0,0 +1,70 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.app;
using Mr.BrickAdventures.data;
using Mr.BrickAdventures.game.repositories;
using Mr.BrickAdventures.game.services;
namespace Mr.BrickAdventures.common;
[Meta(typeof(IAutoNode))]
public partial class AppRoot : Node2D,
IProvide<PlayerRepository>,
IProvide<LevelRepository>,
IProvide<SaveClient>,
IProvide<SaveService>,
IProvide<LevelService>,
IProvide<IGameScenes>,
IProvide<ILevelCatalog>,
IGameScenes
{
public override void _Notification(int what) => this.Notify(what);
[Export] private Array<PackedScene> _levels = [];
[Export] private PackedScene _mainMenu = null!;
private readonly SaveClient _save = new("user://savegame.save", version: 2);
private readonly PlayerRepository _players = new();
private readonly LevelRepository _levelsRepo = new();
private SaveService _saveService = null!;
private LevelService _levelService = null!;
private ILevelCatalog _catalog = null!;
PlayerRepository IProvide<PlayerRepository>.Value() => _players;
LevelRepository IProvide<LevelRepository>.Value() => _levelsRepo;
SaveClient IProvide<SaveClient>.Value() => _save;
SaveService IProvide<SaveService>.Value() => _saveService;
LevelService IProvide<LevelService>.Value() => _levelService;
ILevelCatalog IProvide<ILevelCatalog>.Value() => _catalog;
IGameScenes IProvide<IGameScenes>.Value() => this;
public void OnReady()
{
_saveService = new SaveService(_players, _levelsRepo, _save);
_levelService = new LevelService(_levelsRepo);
_catalog = new ExportedLevelCatalog(_levels, _mainMenu);
_saveService.TryLoad();
this.Provide();
}
public void Load(PackedScene scene) => GetTree().ChangeSceneToPacked(scene);
public void Restart() => GetTree().ReloadCurrentScene();
public void ReturnToMain(PackedScene mainMenu) => GetTree().ChangeSceneToPacked(mainMenu);
private sealed class ExportedLevelCatalog : ILevelCatalog
{
private readonly Array<PackedScene> _levels;
public PackedScene MainMenu { get; }
public ExportedLevelCatalog(Array<PackedScene> levels, PackedScene mainMenu) {
_levels = levels; MainMenu = mainMenu;
}
public int Count => _levels.Count;
public PackedScene? Get(int index) => (index >= 0 && index < _levels.Count) ? _levels[index] : null;
public PackedScene First => _levels.Count > 0 ? _levels[0] : MainMenu;
}
}

1
common/AppRoot.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://dg2l7cw6da4vb

6
data/ConfigClient.cs Normal file
View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.data;
public class ConfigClient
{
}

1
data/ConfigClient.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://d3s774lnoljcu

103
data/SaveClient.cs Normal file
View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
using Godot.Collections;
using Mr.BrickAdventures.game.repositories;
namespace Mr.BrickAdventures.data;
public sealed class SaveClient
{
private readonly string _path;
private readonly int _version;
public SaveClient(string path, int version) { _path = path; _version = version; }
public bool Exists() => FileAccess.FileExists(_path);
public bool TryLoad(out PlayerState player, out LevelState level) {
player = null!; level = null!;
if (!Exists()) return false;
using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Read);
var dict = (Dictionary)f.GetVar();
if ((int)dict.GetValueOrDefault("version", -1) != _version) return false;
player = ToPlayer((Dictionary)dict["player"]);
level = ToLevel((Dictionary)dict["level"]);
return true;
}
// Strict load: requires version + player_state + level_state.
// If anything is off, delete the file and act as "no save".
public bool TryLoadStrict(out PlayerState player, out LevelState level) {
player = default!;
level = default!;
if (!Exists()) return false;
try {
using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Read);
if (f == null) { Delete(); return false; }
var dictionary = (Dictionary)f.GetVar();
if (!dictionary.TryGetValue("version", out var v) || (int)v != _version) { Delete(); return false; }
if (!dictionary.TryGetValue("player_state", out var pObj) || (Dictionary)pObj is not { } p) { Delete(); return false; }
if (!dictionary.TryGetValue("level_state", out var lObj) || (Dictionary)lObj is not { } l) { Delete(); return false; }
player = ToPlayer(p);
level = ToLevel(l);
return true;
}
catch (Exception e) {
GD.PushWarning($"SaveClient: load failed — deleting bad save. {e.GetType().Name}: {e.Message}");
Delete();
return false;
}
}
public void Save(PlayerState player, LevelState level) {
using var f = FileAccess.Open(_path, FileAccess.ModeFlags.Write);
var dict = new Dictionary {
{ "version", _version },
{ "player", FromPlayer(player) },
{ "level", FromLevel(level) }
};
f.StoreVar(dict);
}
public void Delete() {
if (!Exists()) return;
var abs = ProjectSettings.GlobalizePath(_path);
var ok = DirAccess.RemoveAbsolute(abs);
if (ok != Error.Ok) GD.PushWarning($"SaveClient: failed to delete {_path}: {ok}");
}
private static Dictionary FromPlayer(PlayerState s) => new() { { "coins", s.Coins }, { "lives", s.Lives } };
private static PlayerState ToPlayer(Dictionary d) => new() {
Coins = d.TryGetValue("coins", out var c) ? (int)c : 0,
Lives = d.TryGetValue("lives", out var l) ? (int)l : 3
};
private static Dictionary FromLevel(LevelState s) => new() {
{ "current", s.Current },
{ "unlocked", new Array<int>(s.Unlocked) },
{ "completed", new Array<int>(s.Completed) },
};
private static LevelState ToLevel(Dictionary d) => new() {
Current = d.TryGetValue("current", out var cur) ? (int)cur : 0,
Unlocked = d.TryGetValue("unlocked", out var ul) && (Array<int>)ul is { } a1 ? a1.ToArray() : [0],
Completed = d.TryGetValue("completed", out var cl) && (Array<int>)cl is { } a2 ? a2.ToArray() : [],
};
}
public record SaveSnapshot {
public required PlayerState PlayerState { get; init; }
public required LevelState LevelState { get; init; }
}

1
data/SaveClient.cs.uid Normal file
View File

@@ -0,0 +1 @@
uid://bsf45t7m2wa07

View File

@@ -0,0 +1,40 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Mr.BrickAdventures.app;
using Mr.BrickAdventures.game.services;
namespace Mr.BrickAdventures.features.level;
[Meta(typeof(IAutoNode))]
public partial class ExitDoorComponent : Area2D
{
public override void _Notification(int what) => this.Notify(what);
[Export] public CollisionShape2D UnlockIndicator { get; set; } = null!;
[Export] public bool Unlocked { get; set; } = false;
[Dependency] public LevelService Levels => this.DependOn<LevelService>();
[Dependency] public ILevelCatalog Catalog => this.DependOn<ILevelCatalog>();
[Dependency] public IGameScenes Scenes => this.DependOn<IGameScenes>();
public void OnReady() {
BodyEntered += OnBodyEntered;
UpdateVisuals();
}
private void OnBodyEntered(Node body) {
if (!Unlocked) return;
if (body is not CharacterBody2D) return;
var nextIdx = Levels.CompleteAndAdvance();
var next = Catalog.Get(nextIdx);
if (next != null) Scenes.Load(next); else Scenes.ReturnToMain(Catalog.MainMenu);
}
private void UpdateVisuals() {
if (UnlockIndicator != null) UnlockIndicator.Disabled = !Unlocked;
}
public void SetUnlocked(bool value) { Unlocked = value; UpdateVisuals(); }
}

View File

@@ -0,0 +1 @@
uid://ddh0jm0heqtc3

34
features/ui/hud/Hud.cs Normal file
View File

@@ -0,0 +1,34 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Mr.BrickAdventures.game.repositories;
using Mr.BrickAdventures.scripts.components;
namespace Mr.BrickAdventures.features.ui.hud;
[Meta(typeof(IAutoNode))]
public partial class Hud : Node
{
public override void _Notification(int what) => this.Notify(what);
[Export] public HealthComponent Health { get; set; } = null!;
[Node] public Label CoinsLabel { get; set; } = null!;
[Node] public ProgressBar HealthBar { get; set; } = null!;
[Node] public Label LivesLabel { get; set; } = null!;
[Dependency] public PlayerRepository Player => this.DependOn<PlayerRepository>();
public void OnResolved() {
CoinsLabel.Text = $"{Tr("COINS_LABEL")}: {Player.Coins}";
LivesLabel.Text = $"{Tr("LIVES_LABEL")}: {Player.Lives}";
Player.CoinsChanged += c => CoinsLabel.Text = $"{Tr("COINS_LABEL")}: {c}";
Player.LivesChanged += l => LivesLabel.Text = $"{Tr("LIVES_LABEL")}: {l}";
if (Health != null) {
HealthBar.MaxValue = Health.MaxHealth;
HealthBar.Value = Health.Health;
Health.HealthChanged += (_, total) => { HealthBar.Value = total; };
}
}
}

View File

@@ -0,0 +1 @@
uid://c1uwe5e1cfdxl

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=8 format=3 uid="uid://byxf45ukq82pe"]
[ext_resource type="LabelSettings" uid="uid://rvn5ivivfvv6" path="res://resources/ui/hud_label_settings.tres" id="1_4dsh5"]
[ext_resource type="Script" uid="uid://c3pde84b3kdco" path="res://scripts/ui/hud.gd" id="1_ueofj"]
[ext_resource type="Script" uid="uid://c1uwe5e1cfdxl" path="res://features/ui/hud/Hud.cs" id="1_m4pq7"]
[ext_resource type="FontFile" uid="uid://xm0vbusjr7b7" path="res://fonts/PressStart2P-Regular.ttf" id="1_ygmwt"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_mmcdi"]
@@ -16,7 +16,7 @@ bg_color = Color(0.47451, 0.47451, 0.47451, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_22dp1"]
bg_color = Color(0.858824, 0.254902, 0.380392, 1)
[node name="HUD" type="Control" node_paths=PackedStringArray("coins_label", "health_progressbar", "lives_label")]
[node name="HUD" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
@@ -25,10 +25,7 @@ grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 4
size_flags_vertical = 4
script = ExtResource("1_ueofj")
coins_label = NodePath("PanelContainer/MarginContainer/HBoxContainer/Coins label")
health_progressbar = NodePath("PanelContainer/MarginContainer/HBoxContainer/ProgressBar")
lives_label = NodePath("PanelContainer/MarginContainer/HBoxContainer/Lives")
script = ExtResource("1_m4pq7")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1
@@ -48,14 +45,18 @@ theme_override_constants/margin_bottom = 8
[node name="HBoxContainer" type="HBoxContainer" parent="PanelContainer/MarginContainer"]
layout_mode = 2
theme_override_constants/separation = 8
alignment = 1
[node name="Health Label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer"]
visible = false
layout_mode = 2
text = "HEALTH_LABEL"
label_settings = ExtResource("1_4dsh5")
uppercase = true
[node name="ProgressBar" type="ProgressBar" parent="PanelContainer/MarginContainer/HBoxContainer"]
[node name="HealthBar" type="ProgressBar" parent="PanelContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
visible = false
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 1
@@ -66,14 +67,20 @@ step = 0.1
value = 60.0
show_percentage = false
[node name="Lives" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer"]
[node name="LivesLabel" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "LIVES_LABEL"
label_settings = ExtResource("1_4dsh5")
horizontal_alignment = 1
uppercase = true
[node name="Coins label" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer"]
[node name="CoinsLabel" type="Label" parent="PanelContainer/MarginContainer/HBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 3
text = "COINS_LABEL"
label_settings = ExtResource("1_4dsh5")
horizontal_alignment = 1
uppercase = true

View File

@@ -0,0 +1,26 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Mr.BrickAdventures.app;
namespace Mr.BrickAdventures.features.ui.menus;
[Meta(typeof(IAutoNode))]
public partial class GameOverScreen : Control
{
public override void _Notification(int what) => this.Notify(what);
[Export] public Button RestartButton { get; set; } = null!;
[Export] public Button MainMenuButton { get; set; } = null!;
[Export] public PackedScene MainMenuScene { get; set; } = null!;
[Dependency] public IGameScenes Scenes => this.DependOn<IGameScenes>();
public void OnReady() {
Visible = false;
RestartButton.Pressed += () => Scenes.Restart();
MainMenuButton.Pressed += () => Scenes.ReturnToMain(MainMenuScene);
}
public void ShowGameOver() => Show();
}

View File

@@ -0,0 +1 @@
uid://b36jv878751ta

View File

@@ -0,0 +1,57 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Mr.BrickAdventures.app;
using Mr.BrickAdventures.game.repositories;
using Mr.BrickAdventures.game.services;
namespace Mr.BrickAdventures.features.ui.menus;
[Meta(typeof(IAutoNode))]
public partial class MainMenu : Control
{
public override void _Notification(int what) => this.Notify(what);
[Node] public Button NewGameButton { get; set; } = null!;
[Node] public Button ContinueButton { get; set; } = null!;
[Node] public Button SettingsButton { get; set; } = null!;
[Node] public Button CreditsButton { get; set; } = null!;
[Node] public Button ExitButton { get; set; } = null!;
[Node] public Label VersionLabel { get; set; } = null!;
[Export] public Control SettingsControl { get; set; } = null!;
[Export] public Control CreditsControl { get; set; } = null!;
[Dependency] public SaveService Save => this.DependOn<SaveService>();
[Dependency] public LevelRepository Levels => this.DependOn<LevelRepository>();
[Dependency] public IGameScenes Scenes => this.DependOn<IGameScenes>();
[Dependency] public ILevelCatalog Catalog => this.DependOn<ILevelCatalog>();
public void OnReady() {
VersionLabel.Text = $"v. {ProjectSettings.GetSetting("application/config/version")}";
NewGameButton.Pressed += OnNewGamePressed;
ContinueButton.Pressed += OnContinuePressed;
SettingsButton.Pressed += () => SettingsControl.Show();
CreditsButton.Pressed += () => CreditsControl.Show();
ExitButton.Pressed += () => GetTree().Quit();
}
public void OnResolved()
{
ContinueButton.Disabled = !Save.Exists();
(ContinueButton.Disabled ? NewGameButton : ContinueButton).GrabFocus();
}
private void OnNewGamePressed() {
Save.NewGame();
Levels.SetCurrent(0);
var first = Catalog.First;
Scenes.Load(first);
}
private void OnContinuePressed() {
if (!Save.TryLoad()) { OnNewGamePressed(); return; }
var scene = Catalog.Get(Levels.Current) ?? Catalog.First;
Scenes.Load(scene);
}
}

View File

@@ -0,0 +1 @@
uid://fcsg0e8s36in

View File

@@ -0,0 +1,33 @@
using Chickensoft.AutoInject;
using Chickensoft.Introspection;
using Godot;
using Mr.BrickAdventures.app;
using Mr.BrickAdventures.game.services;
namespace Mr.BrickAdventures.features.ui.menus;
[Meta(typeof(IAutoNode))]
public partial class PauseMenu : Control
{
public override void _Notification(int what) => this.Notify(what);
[Export] public Button ResumeButton { get; set; } = null!;
[Export] public Button RestartButton { get; set; } = null!;
[Export] public Button MainMenuButton { get; set; } = null!;
[Dependency] public IGameScenes Scenes => this.DependOn<IGameScenes>();
[Dependency] public ILevelCatalog Catalog => this.DependOn<ILevelCatalog>();
[Dependency] public LevelService Levels => this.DependOn<LevelService>();
public void OnReady() {
Visible = false;
ResumeButton.Pressed += () => { GetTree().Paused = false; Hide(); };
RestartButton.Pressed += () => { GetTree().Paused = false; Scenes.Restart(); };
MainMenuButton.Pressed += () => { GetTree().Paused = false; Scenes.ReturnToMain(Catalog.MainMenu); };
}
public void Toggle() {
if (Visible) { GetTree().Paused = false; Hide(); }
else { Show(); GetTree().Paused = true; }
}
}

View File

@@ -0,0 +1 @@
uid://bwgs02wcfnm8u

View File

@@ -1,25 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://8b6ol5sssbgo"]
[ext_resource type="Script" uid="uid://hyfvthdbgjbc" path="res://scripts/ui/main_menu.gd" id="1_epxpl"]
[ext_resource type="Script" uid="uid://fcsg0e8s36in" path="res://features/ui/menus/MainMenu.cs" id="1_q8hru"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_qv2q0"]
bg_color = Color(0, 0, 0, 1)
[node name="MainMenu" type="Control" node_paths=PackedStringArray("main_menu_control", "new_game_button", "continue_button", "settings_button", "credits_button", "exit_button", "version_label")]
[node name="MainMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_epxpl")
main_menu_control = NodePath(".")
new_game_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/NewGameButton")
continue_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/ContinueButton")
settings_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/SettingsButton")
credits_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/CreditsButton")
exit_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/QuitButton")
version_label = NodePath("PanelContainer/MarginContainer/VBoxContainer/version")
script = ExtResource("1_q8hru")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1
@@ -53,31 +46,37 @@ layout_mode = 2
size_flags_vertical = 3
[node name="ContinueButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "CONTINUE_BUTTON"
flat = true
[node name="NewGameButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "NEW_GAME_BUTTON"
flat = true
[node name="SettingsButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "SETTINGS_BUTTON"
flat = true
[node name="CreditsButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "CREDITS_BUTTON"
flat = true
[node name="QuitButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
[node name="ExitButton" type="Button" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
text = "QUIT_BUTTON"
flat = true
[node name="version" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer"]
[node name="VersionLabel" type="Label" parent="PanelContainer/MarginContainer/VBoxContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 0
size_flags_vertical = 8

View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.features.ui.settings;
public class AudioSettings
{
}

View File

@@ -0,0 +1 @@
uid://bnj36dhskiem

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Mr.BrickAdventures.game.repositories;
public sealed class LevelRepository
{
public int Current { get; private set; } = 0;
public HashSet<int> Unlocked { get; } = new() { 0 };
public HashSet<int> Completed { get; } = new();
public event Action<int>? CurrentChanged;
public void SetCurrent(int idx) { Current = idx; CurrentChanged?.Invoke(Current); }
public void Unlock(int idx) => Unlocked.Add(idx);
public void Complete(int idx) { Completed.Add(idx); Unlock(idx + 1); }
public LevelState Export() => new() {
Current = Current, Unlocked = [..Unlocked], Completed = [..Completed]
};
public void Load(LevelState s) {
Current = s.Current;
Unlocked.Clear(); foreach (var i in s.Unlocked) Unlocked.Add(i);
Completed.Clear(); foreach (var i in s.Completed) Completed.Add(i);
CurrentChanged?.Invoke(Current);
}
}
public record LevelState {
public int Current;
public int[] Unlocked = [];
public int[] Completed = [];
}

View File

@@ -0,0 +1 @@
uid://d0604lmwpadt5

View File

@@ -0,0 +1,25 @@
using System;
namespace Mr.BrickAdventures.game.repositories;
public sealed class PlayerRepository
{
public int Coins { get; private set; } = 0;
public int Lives { get; private set; } = 3;
public event Action<int>? CoinsChanged;
public event Action<int>? LivesChanged;
public void SetCoins(int value) { Coins = Math.Max(0, value); CoinsChanged?.Invoke(Coins); }
public void AddCoins(int amount) { SetCoins(Coins + amount); }
public void RemoveCoins(int amount){ SetCoins(Coins - amount); }
public void SetLives(int value) { Lives = value; LivesChanged?.Invoke(Lives); }
public void AddLives(int amount) { SetLives(Lives + amount); }
public void RemoveLives(int amount){ SetLives(Lives - amount); }
public PlayerState Export() => new() { Coins = Coins, Lives = Lives };
public void Load(PlayerState s) { SetCoins(s.Coins); SetLives(s.Lives); }
}
public record PlayerState { public int Coins; public int Lives; }

View File

@@ -0,0 +1 @@
uid://d1dijkt574x4b

View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.game.repositories;
public sealed class SessionRepository
{
}

View File

@@ -0,0 +1 @@
uid://b550hcqugygv0

View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.game.repositories;
public class SettingsRepository
{
}

View File

@@ -0,0 +1 @@
uid://bk11iduo7bg2h

View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.game.repositories;
public class SkillsRepository
{
}

View File

@@ -0,0 +1 @@
uid://cymx7mtmdblun

View File

@@ -0,0 +1,21 @@
using Mr.BrickAdventures.game.repositories;
namespace Mr.BrickAdventures.game.services;
public sealed class LevelService
{
private readonly LevelRepository _levels;
public LevelService(LevelRepository levels) => _levels = levels;
public int CompleteAndAdvance() {
var cur = _levels.Current;
_levels.Complete(cur);
var next = cur + 1;
_levels.SetCurrent(next);
return next;
}
public void StartNew() {
_levels.Load(new LevelState { Current = 0, Unlocked = new [] { 0 }, Completed = [] });
}
}

View File

@@ -0,0 +1 @@
uid://b2tsi3cjnh5xq

View File

@@ -0,0 +1,32 @@
using Mr.BrickAdventures.data;
using Mr.BrickAdventures.game.repositories;
namespace Mr.BrickAdventures.game.services;
public sealed class SaveService
{
private readonly PlayerRepository _players;
private readonly LevelRepository _levels;
private readonly SaveClient _save;
public SaveService(PlayerRepository players, LevelRepository levels, SaveClient save) {
_players = players; _levels = levels; _save = save;
}
public bool TryLoad() {
if (!_save.TryLoad(out var p, out var l)) return false;
_players.Load(p);
_levels.Load(l);
return true;
}
public void Save() => _save.Save(_players.Export(), _levels.Export());
public bool Exists() => _save.Exists();
public void NewGame() {
_players.Load(new PlayerState { Coins = 0, Lives = 3 });
_levels.Load(new LevelState { Current = 0, Unlocked = [0], Completed = [] });
Save();
}
}

View File

@@ -0,0 +1 @@
uid://dxqkxlkkivxog

View File

@@ -0,0 +1,6 @@
namespace Mr.BrickAdventures.game.services;
public sealed class SkillService
{
}

View File

@@ -0,0 +1 @@
uid://dim21hs12wdi5

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=3 uid="uid://bymro4t7angv5"]
[gd_scene load_steps=10 format=3 uid="uid://bymro4t7angv5"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_1c3jb"]
[ext_resource type="Script" uid="uid://cdnwrn8v05qhi" path="res://scripts/components/bullet_component.gd" id="2_i6t5k"]
@@ -7,6 +7,7 @@
[ext_resource type="Script" uid="uid://bgty7040ams6s" path="res://scripts/components/projectile_init_component.gd" id="5_2vqt8"]
[ext_resource type="Script" uid="uid://873un8agkyja" path="res://scripts/components/launch_component.gd" id="6_d0tcd"]
[ext_resource type="Script" uid="uid://cvcnfrr1udco5" path="res://scripts/components/straight_motion_component.gd" id="7_r41xl"]
[ext_resource type="PackedScene" uid="uid://c1iorglk708g0" path="res://objects/fxs/terrain_hit_fx.tscn" id="8_d0tcd"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_ar0xf"]
size = Vector2(16, 10)
@@ -24,10 +25,12 @@ hframes = 12
vframes = 12
frame = 80
[node name="BulletComponent" type="Node" parent="." node_paths=PackedStringArray("root", "area2d")]
[node name="BulletComponent" type="Node" parent="." node_paths=PackedStringArray("root", "area2d", "hit_terrain_fx", "bullet_sprite")]
script = ExtResource("2_i6t5k")
root = NodePath("..")
area2d = NodePath("..")
hit_terrain_fx = NodePath("../TerrainHitFX")
bullet_sprite = NodePath("../Sprite2D")
[node name="VisibleOnScreenNotifier2D" type="VisibleOnScreenNotifier2D" parent="."]
position = Vector2(0, 2.38419e-07)
@@ -60,3 +63,5 @@ script = ExtResource("7_r41xl")
root = NodePath("..")
launch_component = NodePath("../LaunchComponent")
metadata/_custom_type_script = "uid://cvcnfrr1udco5"
[node name="TerrainHitFX" parent="." instance=ExtResource("8_d0tcd")]

View File

@@ -1,12 +1,12 @@
[gd_scene load_steps=47 format=3 uid="uid://bqi5s710xb1ju"]
[gd_scene load_steps=48 format=3 uid="uid://bqi5s710xb1ju"]
[ext_resource type="Script" uid="uid://ccuddyoakg04u" path="res://scripts/player.gd" id="1_8j4h4"]
[ext_resource type="Texture2D" uid="uid://b7gp0gqvkv8j4" path="res://sprites/MrBrick_base.png" id="2_bc55y"]
[ext_resource type="Shader" uid="uid://bs4xvm4qkurpr" path="res://shaders/hit_flash.tres" id="2_lgb3u"]
[ext_resource type="Texture2D" uid="uid://jl1gwqchhpdc" path="res://sprites/left_eye.png" id="3_2srrh"]
[ext_resource type="Script" uid="uid://b3mrdvre1y567" path="res://scripts/components/ship_movement.gd" id="3_p4n66"]
[ext_resource type="Texture2D" uid="uid://iiawtnwmeny3" path="res://sprites/right_eye.png" id="4_ccn81"]
[ext_resource type="Script" uid="uid://oxeqvxkgj87j" path="res://scripts/components/flip_player.gd" id="5_geu10"]
[ext_resource type="Texture2D" uid="uid://0l454rfplmqg" path="res://sprites/MrBrick_base-sheet.png" id="5_yysbb"]
[ext_resource type="Script" uid="uid://qeu80jy4vmuf" path="res://scripts/components/score.gd" id="6_fowa2"]
[ext_resource type="Script" uid="uid://btfsq0bvtrx3t" path="res://scripts/components/health.gd" id="7_tqjk8"]
[ext_resource type="Script" uid="uid://dkpu3121y88oo" path="res://scripts/components/player_death.gd" id="8_1v23d"]
@@ -32,11 +32,12 @@
[ext_resource type="PackedScene" uid="uid://bg76mtpcmfm2j" path="res://objects/ui/charging_bar_layer.tscn" id="28_3f5nm"]
[ext_resource type="PackedScene" uid="uid://b12tppjkkqpt4" path="res://objects/fxs/hit_particles.tscn" id="28_jh5m0"]
[ext_resource type="Script" uid="uid://ceq8n7yw7qxpi" path="res://scripts/components/hit_component.gd" id="29_jh5m0"]
[ext_resource type="Script" uid="uid://c1wtrgw0x77xo" path="res://scripts/components/platform_movement.gd" id="31_xoue7"]
[ext_resource type="Script" uid="uid://cflncpa377l8l" path="res://scripts/components/platform_movement.gd" id="31_xoue7"]
[ext_resource type="AudioStream" uid="uid://dyev46uqusimi" path="res://sfx/shoot.wav" id="32_x2b7c"]
[ext_resource type="Script" uid="uid://d1ctdx52gskv1" path="res://scripts/components/ship_shooter.gd" id="34_gwc8i"]
[ext_resource type="PackedScene" uid="uid://dtem8jgcyoqar" path="res://objects/entities/green_laser.tscn" id="36_oxudy"]
[ext_resource type="Script" uid="uid://cfeoalic0mu2j" path="res://scripts/components/kill_player_out_of_screen.gd" id="37_oxudy"]
[ext_resource type="Script" uid="uid://d32kd83lf86iy" path="res://scripts/components/progressive_damage_component.gd" id="38_o1ihh"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_xoue7"]
shader = ExtResource("2_lgb3u")
@@ -116,7 +117,8 @@ metadata/_custom_type_script = "uid://b3mrdvre1y567"
[node name="Base" type="Sprite2D" parent="Graphics/Root"]
material = SubResource("ShaderMaterial_xoue7")
texture = ExtResource("2_bc55y")
texture = ExtResource("5_yysbb")
hframes = 5
[node name="Left Eye" type="Sprite2D" parent="Graphics/Root"]
position = Vector2(-7, -6)
@@ -277,5 +279,13 @@ script = ExtResource("37_oxudy")
screen_notifier = NodePath("../VisibleOnScreenNotifier2D")
health_component = NodePath("../HealthComponent")
[node name="ProgressiveDamageComponent" type="Node" parent="." node_paths=PackedStringArray("health_component", "sprite", "platform_movement")]
script = ExtResource("38_o1ihh")
health_component = NodePath("../HealthComponent")
sprite = NodePath("../Graphics/Root/Base")
platform_movement = NodePath("../Movements/PlatformMovement")
min_jump_height = 100.0
jump_reduction_percentage = 0.15
[connection signal="on_death" from="HealthComponent" to="PlayerDeathComponent" method="_on_health_component_on_death"]
[connection signal="on_health_change" from="HealthComponent" to="KnockbackComponent" method="_on_health_component_on_health_change"]

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=3 uid="uid://bhc7y4xugu4q7"]
[gd_scene load_steps=10 format=3 uid="uid://bhc7y4xugu4q7"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_w543f"]
[ext_resource type="Script" uid="uid://dkmxhjtmu5xlb" path="res://scripts/components/damage_component.gd" id="2_ll0xw"]
@@ -7,6 +7,7 @@
[ext_resource type="Script" uid="uid://bvsgg8lu0a8m6" path="res://scripts/components/lifetime_component.gd" id="5_qsc5m"]
[ext_resource type="Script" uid="uid://873un8agkyja" path="res://scripts/components/launch_component.gd" id="6_6th6w"]
[ext_resource type="Script" uid="uid://cvcnfrr1udco5" path="res://scripts/components/straight_motion_component.gd" id="7_e0mqp"]
[ext_resource type="PackedScene" uid="uid://c1iorglk708g0" path="res://objects/fxs/terrain_hit_fx.tscn" id="8_6th6w"]
[sub_resource type="CircleShape2D" id="CircleShape2D_txsw8"]
radius = 4.0
@@ -59,8 +60,13 @@ script = ExtResource("7_e0mqp")
root = NodePath("..")
launch_component = NodePath("../LaunchComponent")
[node name="BulletComponent" type="Node" parent="." node_paths=PackedStringArray("root", "area2d")]
[node name="BulletComponent" type="Node" parent="." node_paths=PackedStringArray("root", "area2d", "hit_terrain_fx", "bullet_sprite")]
script = ExtResource("3_keogl")
root = NodePath("..")
area2d = NodePath("..")
hit_terrain_fx = NodePath("../TerrainHitFX")
bullet_sprite = NodePath("../Sprite2D")
metadata/_custom_type_script = "uid://cdnwrn8v05qhi"
[node name="TerrainHitFX" parent="." instance=ExtResource("8_6th6w")]
z_index = 3

View File

@@ -126,9 +126,11 @@ area2d = NodePath("../Hitbox")
[node name="PeriodicShootingComponent" type="Node" parent="." node_paths=PackedStringArray("root", "bullet_spawn_right", "bullet_spawn_left")]
script = ExtResource("6_4ajjm")
bullet_scene = ExtResource("7_4ajjm")
shoot_interval = 2.0
root = NodePath("..")
bullet_spawn_right = NodePath("../laser spawn point right")
bullet_spawn_left = NodePath("../laser spawn point left")
shooting_interval_variation = 0.5
[node name="EnemyDeathComponent" type="Node" parent="." node_paths=PackedStringArray("root", "collision_shape_2d", "health_component")]
script = ExtResource("7_uyhuj")

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=9 format=3 uid="uid://dtem8jgcyoqar"]
[gd_scene load_steps=10 format=3 uid="uid://dtem8jgcyoqar"]
[ext_resource type="Script" uid="uid://dkmxhjtmu5xlb" path="res://scripts/components/damage_component.gd" id="1_nuljg"]
[ext_resource type="Script" uid="uid://cdnwrn8v05qhi" path="res://scripts/components/bullet_component.gd" id="2_1gu8o"]
@@ -7,16 +7,18 @@
[ext_resource type="Script" uid="uid://873un8agkyja" path="res://scripts/components/launch_component.gd" id="5_772bd"]
[ext_resource type="Script" uid="uid://bvsgg8lu0a8m6" path="res://scripts/components/lifetime_component.gd" id="6_vd16u"]
[ext_resource type="Script" uid="uid://bgty7040ams6s" path="res://scripts/components/projectile_init_component.gd" id="7_1gu8o"]
[ext_resource type="Script" uid="uid://bpy6xtfm8l3hy" path="res://scripts/components/trigger_lever_component.gd" id="8_2vcrp"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_n4uav"]
size = Vector2(16, 2)
[node name="Red Laser" type="Area2D"]
[node name="Green Laser" type="Area2D"]
collision_layer = 16
collision_mask = 9
[node name="DamageComponent" type="Node" parent="." node_paths=PackedStringArray("area2d")]
script = ExtResource("1_nuljg")
damage = 1.0
area2d = NodePath("..")
metadata/_custom_type_script = "uid://dkmxhjtmu5xlb"
@@ -72,3 +74,7 @@ autostart = true
script = ExtResource("7_1gu8o")
launch_component = NodePath("../LaunchComponent")
metadata/_custom_type_script = "uid://bgty7040ams6s"
[node name="TriggerLeverComponent" type="Node" parent="."]
script = ExtResource("8_2vcrp")
metadata/_custom_type_script = "uid://bpy6xtfm8l3hy"

View File

@@ -9,7 +9,7 @@ size = Vector2(12, 13)
[node name="Lever" type="Area2D" groups=["levers"]]
collision_layer = 0
collision_mask = 4
collision_mask = 20
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2(0, 1.5)

View File

@@ -0,0 +1,32 @@
[gd_scene load_steps=6 format=3 uid="uid://t6h2ra7kjyq"]
[ext_resource type="Texture2D" uid="uid://1x4iq56rhc18" path="res://sprites/health_potions.png" id="1_p0sdo"]
[ext_resource type="Script" uid="uid://cegdd1sravi5m" path="res://scripts/components/heal_component.gd" id="2_piwlp"]
[ext_resource type="Script" uid="uid://pa1bwc4no08q" path="res://scripts/components/collectable.gd" id="3_k2tv6"]
[ext_resource type="Resource" uid="uid://2tl3yoh202no" path="res://resources/collectables/small_health_potion.tres" id="4_p0sdo"]
[sub_resource type="CircleShape2D" id="CircleShape2D_uj2v5"]
radius = 7.0
[node name="SmallHealPotion" type="Area2D"]
collision_layer = 0
collision_mask = 4
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("CircleShape2D_uj2v5")
[node name="Sprite2D" type="Sprite2D" parent="."]
texture = ExtResource("1_p0sdo")
hframes = 4
frame = 1
[node name="HealComponent" type="Node" parent="." node_paths=PackedStringArray("collectable")]
script = ExtResource("2_piwlp")
collectable = NodePath("../CollectableComponent")
[node name="CollectableComponent" type="Node" parent="." node_paths=PackedStringArray("area2d", "collision_shape")]
script = ExtResource("3_k2tv6")
area2d = NodePath("..")
collision_shape = NodePath("../CollisionShape2D")
collectable_data = ExtResource("4_p0sdo")
metadata/_custom_type_script = "uid://pa1bwc4no08q"

View File

@@ -0,0 +1,14 @@
[gd_scene load_steps=3 format=3 uid="uid://dkqa3q6j2gof4"]
[ext_resource type="Script" uid="uid://ybmwls7hv8j3" path="res://scripts/components/spaceship_exit_component.gd" id="1_1cmfv"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_njt46"]
[node name="Spaceship exit" type="Area2D" node_paths=PackedStringArray("area2d")]
collision_layer = 0
collision_mask = 4
script = ExtResource("1_1cmfv")
area2d = NodePath(".")
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
shape = SubResource("RectangleShape2D_njt46")

View File

@@ -0,0 +1,49 @@
[gd_scene load_steps=5 format=3 uid="uid://blpk55m4e7y3a"]
[ext_resource type="Texture2D" uid="uid://055an6f4wluo" path="res://sprites/backgrounds/forest/PS_Forest_01.png" id="1_vpdhu"]
[ext_resource type="Texture2D" uid="uid://dk8846ai1ht6i" path="res://sprites/backgrounds/forest/PS_Forest_02.png" id="2_11jh3"]
[ext_resource type="Texture2D" uid="uid://bl3iv071i34ge" path="res://sprites/backgrounds/forest/PS_Forest_03.png" id="3_j8xur"]
[ext_resource type="Texture2D" uid="uid://bcrqiyfk6fpgq" path="res://sprites/backgrounds/forest/PS_Forest_04.png" id="4_qdo8p"]
[node name="ParallaxBackground" type="ParallaxBackground"]
[node name="Sky" type="ParallaxLayer" parent="."]
motion_scale = Vector2(0, 0)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Sky"]
texture_repeat = 2
scale = Vector2(1.5, 1.013)
texture = ExtResource("1_vpdhu")
centered = false
[node name="Clouds" type="ParallaxLayer" parent="."]
motion_scale = Vector2(0.1, 0.1)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Clouds"]
texture_repeat = 2
scale = Vector2(1.5, 1.5)
texture = ExtResource("2_11jh3")
centered = false
[node name="Hills" type="ParallaxLayer" parent="."]
motion_scale = Vector2(0.2, 0.2)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Hills"]
texture_repeat = 2
scale = Vector2(1.5, 1.5)
texture = ExtResource("3_j8xur")
centered = false
[node name="Ground" type="ParallaxLayer" parent="."]
motion_scale = Vector2(0.4, 0.4)
motion_offset = Vector2(0.1, 0)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Ground"]
texture_repeat = 2
scale = Vector2(1.5, 1.5)
texture = ExtResource("4_qdo8p")
centered = false

View File

@@ -0,0 +1,80 @@
[gd_scene load_steps=8 format=3 uid="uid://c1iorglk708g0"]
[ext_resource type="Script" uid="uid://djfejwp6e402k" path="res://scripts/components/terrain_hit_fx.gd" id="1_22p6x"]
[sub_resource type="GradientTexture1D" id="GradientTexture1D_6dbny"]
[sub_resource type="Curve" id="Curve_22p6x"]
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.743682, 0.699254), -0.879484, -0.879484, 0, 0, Vector2(1, 0.0104477), 2.07887, 0.0, 0, 0]
point_count = 3
[sub_resource type="CurveTexture" id="CurveTexture_nm1g5"]
curve = SubResource("Curve_22p6x")
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_hryxg"]
lifetime_randomness = 0.1
particle_flag_disable_z = true
inherit_velocity_ratio = -0.5
direction = Vector3(0, 0, 0)
spread = 180.0
initial_velocity_max = 32.0
gravity = Vector3(0, 98, 0)
scale_curve = SubResource("CurveTexture_nm1g5")
color = Color(0.47451, 0.254902, 0, 1)
color_ramp = SubResource("GradientTexture1D_6dbny")
turbulence_noise_speed = Vector3(2.73, 5.225, 0)
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_hyh53"]
lifetime_randomness = 0.2
particle_flag_disable_z = true
inherit_velocity_ratio = -0.5
direction = Vector3(0, 0, 0)
spread = 180.0
initial_velocity_max = 32.0
gravity = Vector3(0, 98, 0)
scale_min = 0.8
scale_max = 0.9
scale_curve = SubResource("CurveTexture_nm1g5")
color = Color(0.47451, 0.254902, 0, 1)
turbulence_noise_speed = Vector3(2.73, 5.225, 0)
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_n5pa8"]
lifetime_randomness = 0.1
particle_flag_disable_z = true
inherit_velocity_ratio = -0.5
direction = Vector3(0, 0, 0)
spread = 180.0
initial_velocity_max = 32.0
gravity = Vector3(0, 98, 0)
scale_min = 0.9
scale_curve = SubResource("CurveTexture_nm1g5")
color = Color(0.764706, 0.443137, 0, 1)
turbulence_noise_speed = Vector3(2.73, 5.225, 0)
[node name="TerrainHitFX" type="GPUParticles2D"]
emitting = false
amount = 24
lifetime = 0.35
one_shot = true
explosiveness = 1.0
fixed_fps = 24
process_material = SubResource("ParticleProcessMaterial_hryxg")
script = ExtResource("1_22p6x")
[node name="TerrainHitFX2" type="GPUParticles2D" parent="."]
emitting = false
amount = 24
lifetime = 0.35
one_shot = true
explosiveness = 1.0
fixed_fps = 24
process_material = SubResource("ParticleProcessMaterial_hyh53")
[node name="TerrainHitFX" type="GPUParticles2D" parent="."]
emitting = false
amount = 24
lifetime = 0.35
one_shot = true
explosiveness = 1.0
fixed_fps = 24
process_material = SubResource("ParticleProcessMaterial_n5pa8")

View File

@@ -1,13 +1,15 @@
[gd_scene load_steps=5 format=3 uid="uid://b4eifkc31jsun"]
[gd_scene load_steps=7 format=3 uid="uid://b4eifkc31jsun"]
[ext_resource type="Script" uid="uid://dd30bgqiagi25" path="res://scripts/game_manager.gd" id="1_58t7u"]
[ext_resource type="PackedScene" uid="uid://bol7g83v2accs" path="res://scenes/level_village_1.tscn" id="2_bentb"]
[ext_resource type="PackedScene" uid="uid://chqb11pfoqmeb" path="res://scenes/level_village_2.tscn" id="3_ajlkg"]
[ext_resource type="PackedScene" uid="uid://h60obxmju6mo" path="res://scenes/level_village_3.tscn" id="4_se5tb"]
[ext_resource type="PackedScene" uid="uid://bhad760x3vvco" path="res://scenes/level_village_4.tscn" id="5_mnosh"]
[ext_resource type="Script" uid="uid://bydv4g1n5s3nf" path="res://scripts/screenshot.gd" id="6_t2tr6"]
[node name="GameManager" type="Node"]
script = ExtResource("1_58t7u")
level_scenes = Array[PackedScene]([ExtResource("2_bentb"), ExtResource("3_ajlkg"), ExtResource("4_se5tb")])
level_scenes = Array[PackedScene]([ExtResource("2_bentb"), ExtResource("3_ajlkg"), ExtResource("4_se5tb"), ExtResource("5_mnosh")])
player_state = {
"coins": 0,
"current_level": 0,
@@ -15,3 +17,6 @@ player_state = {
"unlocked_levels": [ExtResource("4_se5tb")],
"unlocked_skills": []
}
[node name="Node" type="Node" parent="."]
script = ExtResource("6_t2tr6")

View File

@@ -62,9 +62,6 @@ process_material = SubResource("ParticleProcessMaterial_lgb3u")
[node name="UI Layer" parent="." instance=ExtResource("2_lbnsn")]
[node name="HUD" parent="UI Layer" index="0" node_paths=PackedStringArray("player_health")]
player_health = NodePath("../../Brick Player/HealthComponent")
[node name="DeathScreen" parent="UI Layer" index="1" node_paths=PackedStringArray("nodes_to_disable")]
current_level = ExtResource("4_c2yv5")
nodes_to_disable = [NodePath("../../Brick Player")]

View File

@@ -1,8 +1,9 @@
[gd_scene load_steps=4 format=3 uid="uid://cb0mnye1ki5a6"]
[gd_scene load_steps=5 format=3 uid="uid://cb0mnye1ki5a6"]
[ext_resource type="Script" uid="uid://cie33tct7ehf0" path="res://addons/phantom_camera/scripts/phantom_camera_host/phantom_camera_host.gd" id="1_5abjq"]
[ext_resource type="PackedScene" uid="uid://dtjrpkhssq32a" path="res://objects/bg.tscn" id="2_nd58g"]
[ext_resource type="PackedScene" uid="uid://bva54p1fxomu2" path="res://objects/parallax_background.tscn" id="3_cdmor"]
[ext_resource type="PackedScene" uid="uid://bva54p1fxomu2" path="res://objects/village_parallax_background.tscn" id="3_cdmor"]
[ext_resource type="PackedScene" uid="uid://blpk55m4e7y3a" path="res://objects/forest_parallax_background.tscn" id="4_nd58g"]
[node name="Camera2D" type="Camera2D"]
limit_left = 320
@@ -22,4 +23,7 @@ z_index = -3
scale = Vector2(1.5, 1.5)
metadata/_edit_lock_ = true
[node name="ParallaxBackground" parent="." instance=ExtResource("3_cdmor")]
[node name="VillageParallaxBackground" parent="." instance=ExtResource("3_cdmor")]
[node name="ParallaxBackground" parent="." instance=ExtResource("4_nd58g")]
visible = false

View File

@@ -1,6 +1,6 @@
[gd_scene load_steps=11 format=3 uid="uid://6foggu31cu14"]
[ext_resource type="PackedScene" uid="uid://byxf45ukq82pe" path="res://objects/ui/hud.tscn" id="1_tgtfe"]
[ext_resource type="PackedScene" uid="uid://byxf45ukq82pe" path="res://features/ui/hud/hud.tscn" id="1_tgtfe"]
[ext_resource type="PackedScene" uid="uid://dulkm3ah4tm0u" path="res://objects/ui/death_screen.tscn" id="2_ln68j"]
[ext_resource type="Script" uid="uid://cp68km8bykymb" path="res://scripts/resources/level_resource.gd" id="3_5kt5k"]
[ext_resource type="PackedScene" uid="uid://wmw6gaisyrvx" path="res://objects/ui/game_over_screen.tscn" id="4_11xmk"]
@@ -34,9 +34,8 @@ visible = false
offset_top = 32.0
components_to_disable = [null]
[node name="Pause menu" parent="." node_paths=PackedStringArray("settings_menu") instance=ExtResource("6_1q4vn")]
[node name="Pause menu" parent="." instance=ExtResource("6_1q4vn")]
visible = false
settings_menu = NodePath("../Settings menu")
[node name="Settings menu" parent="." node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("7_hkjav")]
visible = false

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://dlm2ri562fynd"]
[gd_scene load_steps=12 format=3 uid="uid://dlm2ri562fynd"]
[ext_resource type="Script" uid="uid://duifmqjarjpuv" path="res://scripts/ui/marketplace.gd" id="1_ncpyg"]
[ext_resource type="FontFile" uid="uid://xm0vbusjr7b7" path="res://fonts/PressStart2P-Regular.ttf" id="2_ho1tm"]
@@ -9,11 +9,12 @@
[ext_resource type="Resource" uid="uid://cx5fsbexblp60" path="res://resources/skills/ice_brick.tres" id="6_6665y"]
[ext_resource type="Resource" uid="uid://d3bjre2etov1n" path="res://resources/skills/magnetic.tres" id="7_ukny6"]
[ext_resource type="PackedScene" uid="uid://dtl03rod7l2t0" path="res://objects/ui/marketplace_button.tscn" id="9_ode10"]
[ext_resource type="PackedScene" uid="uid://ceqjwmihj70lt" path="res://objects/ui/skill_button.tscn" id="10_c7w2b"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_ode10"]
bg_color = Color(0, 0, 0, 1)
[node name="Marketplace" type="Control" node_paths=PackedStringArray("root", "grid")]
[node name="Marketplace" type="Control" node_paths=PackedStringArray("root", "to_unlock_grid", "unlocked_grid")]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
@@ -23,9 +24,11 @@ grow_vertical = 2
script = ExtResource("1_ncpyg")
root = NodePath(".")
skill_data = Array[ExtResource("2_pg4mc")]([ExtResource("3_bk5yi"), ExtResource("4_tx0n3"), ExtResource("5_fqx8e"), ExtResource("6_6665y"), ExtResource("7_ukny6")])
grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/GridContainer")
to_unlock_grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/ToUnlockGridContainer")
unlocked_grid = NodePath("PanelContainer/MarginContainer/VBoxContainer/UnlockedGridContainer")
font = ExtResource("2_ho1tm")
marketplace_button = ExtResource("9_ode10")
skill_button = ExtResource("10_c7w2b")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1
@@ -55,7 +58,14 @@ vertical_alignment = 1
justification_flags = 162
uppercase = true
[node name="GridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
[node name="ToUnlockGridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 2
theme_override_constants/h_separation = 4
theme_override_constants/v_separation = 16
columns = 3
[node name="UnlockedGridContainer" type="GridContainer" parent="PanelContainer/MarginContainer/VBoxContainer"]
layout_mode = 2
size_flags_vertical = 2
theme_override_constants/h_separation = 4

View File

@@ -1,8 +1,11 @@
[gd_scene load_steps=2 format=3 uid="uid://dtl03rod7l2t0"]
[gd_scene load_steps=5 format=3 uid="uid://dtl03rod7l2t0"]
[ext_resource type="Texture2D" uid="uid://cvhoq7aubxlmq" path="res://sprites/ui/magnetic_skill_icon.png" id="1_5kqfg"]
[ext_resource type="Script" uid="uid://dx8lex40lotr5" path="res://scripts/ui/marketplace_button.gd" id="2_ulgvb"]
[ext_resource type="Texture2D" uid="uid://52adghxscdgy" path="res://sprites/locked_skill.png" id="2_vb2qn"]
[ext_resource type="Texture2D" uid="uid://rucyqmgrdld3" path="res://sprites/unlocked_skill.png" id="3_guyun"]
[node name="MarketplaceButton" type="Button"]
[node name="MarketplaceButton" type="Button" node_paths=PackedStringArray("skill_level_container")]
offset_right = 8.0
offset_bottom = 8.0
size_flags_horizontal = 3
@@ -12,3 +15,17 @@ text = "Fire brick 100"
icon = ExtResource("1_5kqfg")
flat = true
autowrap_mode = 2
script = ExtResource("2_ulgvb")
unlocked_skill_icon = ExtResource("3_guyun")
locked_skill_icon = ExtResource("2_vb2qn")
skill_level_container = NodePath("HBoxContainer")
[node name="HBoxContainer" type="HBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 12
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
offset_top = -8.0
grow_horizontal = 2
grow_vertical = 0

View File

@@ -1,12 +1,11 @@
[gd_scene load_steps=4 format=3 uid="uid://i6mnjbjcoqe5"]
[gd_scene load_steps=3 format=3 uid="uid://i6mnjbjcoqe5"]
[ext_resource type="Script" uid="uid://cugifchx6jhuk" path="res://scripts/ui/pause_menu.gd" id="1_aktha"]
[ext_resource type="PackedScene" uid="uid://cl00e2ocomk3m" path="res://scenes/main_menu.tscn" id="2_h4pd5"]
[ext_resource type="Script" uid="uid://bwgs02wcfnm8u" path="res://features/ui/menus/PauseMenu.cs" id="1_ljtns"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_g4ivv"]
bg_color = Color(0, 0, 0, 1)
[node name="Pause menu" type="Control" node_paths=PackedStringArray("pause_menu_control", "resume_button", "quit_button", "settings_button", "exit_to_menu_button")]
[node name="Pause menu" type="Control" node_paths=PackedStringArray("ResumeButton", "RestartButton", "MainMenuButton")]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
@@ -15,13 +14,10 @@ grow_horizontal = 2
grow_vertical = 2
size_flags_horizontal = 6
size_flags_vertical = 6
script = ExtResource("1_aktha")
pause_menu_control = NodePath(".")
resume_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Resume Button")
quit_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Quit game Button")
settings_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Settings Button")
exit_to_menu_button = NodePath("PanelContainer/MarginContainer/VBoxContainer/Exit to menu Button")
exit_to_menu_scene = ExtResource("2_h4pd5")
script = ExtResource("1_ljtns")
ResumeButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Resume Button")
RestartButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Settings Button")
MainMenuButton = NodePath("PanelContainer/MarginContainer/VBoxContainer/Exit to menu Button")
[node name="PanelContainer" type="PanelContainer" parent="."]
layout_mode = 1

View File

@@ -0,0 +1,16 @@
[gd_scene load_steps=3 format=3 uid="uid://ceqjwmihj70lt"]
[ext_resource type="Texture2D" uid="uid://cvhoq7aubxlmq" path="res://sprites/ui/magnetic_skill_icon.png" id="1_wnfk3"]
[ext_resource type="Script" uid="uid://0obbehfd8fki" path="res://scripts/ui/skill_button.gd" id="2_m2732"]
[node name="SkillButton" type="Button"]
offset_right = 8.0
offset_bottom = 8.0
size_flags_horizontal = 3
size_flags_vertical = 3
theme_override_font_sizes/font_size = 8
text = "Fire brick 100"
icon = ExtResource("1_wnfk3")
flat = true
autowrap_mode = 2
script = ExtResource("2_m2732")

View File

@@ -1,9 +1,9 @@
[gd_scene load_steps=5 format=3 uid="uid://bva54p1fxomu2"]
[ext_resource type="Texture2D" uid="uid://d2f4ooucvrjcc" path="res://sprites/backgrounds/plains/1.png" id="1_rfutu"]
[ext_resource type="Texture2D" uid="uid://cdgk3fi8owc6o" path="res://sprites/backgrounds/plains/2.png" id="2_uysv2"]
[ext_resource type="Texture2D" uid="uid://p0bt2k2lihlx" path="res://sprites/backgrounds/plains/3.png" id="3_l6n33"]
[ext_resource type="Texture2D" uid="uid://bcahm7wqdbn6n" path="res://sprites/backgrounds/plains/4.png" id="4_jkhju"]
[ext_resource type="Texture2D" uid="uid://d2f4ooucvrjcc" path="res://sprites/backgrounds/plains/1.png" id="1_kdcp8"]
[ext_resource type="Texture2D" uid="uid://cdgk3fi8owc6o" path="res://sprites/backgrounds/plains/2.png" id="2_ev808"]
[ext_resource type="Texture2D" uid="uid://p0bt2k2lihlx" path="res://sprites/backgrounds/plains/3.png" id="3_sfana"]
[ext_resource type="Texture2D" uid="uid://bcahm7wqdbn6n" path="res://sprites/backgrounds/plains/4.png" id="4_8eim1"]
[node name="ParallaxBackground" type="ParallaxBackground"]
@@ -12,7 +12,7 @@ motion_scale = Vector2(0, 0)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Sky"]
texture = ExtResource("1_rfutu")
texture = ExtResource("1_kdcp8")
centered = false
[node name="Clouds" type="ParallaxLayer" parent="."]
@@ -20,7 +20,7 @@ motion_scale = Vector2(0.1, 0.1)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Clouds"]
texture = ExtResource("2_uysv2")
texture = ExtResource("2_ev808")
centered = false
[node name="Hills" type="ParallaxLayer" parent="."]
@@ -28,7 +28,7 @@ motion_scale = Vector2(0.2, 0.2)
motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Hills"]
texture = ExtResource("3_l6n33")
texture = ExtResource("3_sfana")
centered = false
[node name="Ground" type="ParallaxLayer" parent="."]
@@ -37,5 +37,5 @@ motion_mirroring = Vector2(480, 0)
[node name="Sprite2D" type="Sprite2D" parent="Ground"]
scale = Vector2(1, 1.14074)
texture = ExtResource("4_jkhju")
texture = ExtResource("4_8eim1")
centered = false

View File

@@ -17,7 +17,9 @@ config/name_localized={
}
config/version="in-dev"
run/main_scene="uid://cl00e2ocomk3m"
config/features=PackedStringArray("4.4", "GL Compatibility")
config/use_custom_user_dir=true
config/custom_user_dir_name="MrBrickAdventures"
config/features=PackedStringArray("4.4", "C#", "GL Compatibility")
run/max_fps=180
boot_splash/bg_color=Color(0, 0, 0, 1)
boot_splash/show_image=false
@@ -153,6 +155,11 @@ pause={
}
switch_movement={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194336,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
screenshot={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194333,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
@@ -160,7 +167,6 @@ switch_movement={
[internationalization]
locale/translations=PackedStringArray("res://translations.en.translation", "res://translations.pl.translation")
locale/test="pl"
[layer_names]

View File

@@ -4,4 +4,5 @@
[resource]
script = ExtResource("1_fudbo")
amount = 5
amount = 5.0
type = 0

View File

@@ -4,4 +4,5 @@
[resource]
script = ExtResource("1_037vi")
amount = 100
amount = 100.0
type = 0

View File

@@ -4,5 +4,5 @@
[resource]
script = ExtResource("1_2d5tb")
amount = 1
amount = 1.0
type = 1

View File

@@ -4,4 +4,5 @@
[resource]
script = ExtResource("1_veemo")
amount = 1
amount = 1.0
type = 0

View File

@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="CollectableResource" load_steps=2 format=3 uid="uid://2tl3yoh202no"]
[ext_resource type="Script" uid="uid://cb5f0mx0hrt3b" path="res://scripts/resources/collectable_resource.gd" id="1_brkhb"]
[resource]
script = ExtResource("1_brkhb")
amount = 0.25
type = 2
metadata/_custom_type_script = "uid://cb5f0mx0hrt3b"

View File

@@ -4,5 +4,5 @@
[resource]
script = ExtResource("1_w50p5")
amount = 50
amount = 50.0
type = 0

View File

@@ -0,0 +1,9 @@
[gd_resource type="Resource" script_class="LevelResource" load_steps=2 format=3 uid="uid://dsq0y2iw7tfmk"]
[ext_resource type="Script" uid="uid://cp68km8bykymb" path="res://scripts/resources/level_resource.gd" id="1_8mmd7"]
[resource]
script = ExtResource("1_8mmd7")
level_name = "LEVEL_5_NAME"
scene_path = "res://scenes/level_forest_5.tscn"
metadata/_custom_type_script = "uid://cp68km8bykymb"

View File

@@ -11,9 +11,14 @@ name = "BRICK_POWER"
description = "BRICK_POWER_DESCRIPTION"
node = ExtResource("1_5gnea")
config = {
"fire_rate": 0.6,
"player_controller": NodePath("."),
"throw_input_behavior": ExtResource("1_xwijh"),
"timer": NodePath("ThrowTimer")
}
cost = 50
icon = ExtResource("2_yimbq")
type = 1
is_active = false
level = 0
max_level = 3

View File

@@ -19,3 +19,7 @@ config = {
}
cost = 180
icon = ExtResource("3_wkqmb")
type = 1
is_active = false
level = 0
max_level = 1

View File

@@ -19,3 +19,7 @@ config = {
}
cost = 150
icon = ExtResource("3_w87qb")
type = 1
is_active = false
level = 0
max_level = 3

View File

@@ -19,3 +19,7 @@ config = {
}
cost = 150
icon = ExtResource("3_6btth")
type = 1
is_active = false
level = 0
max_level = 3

View File

@@ -16,3 +16,7 @@ config = {
}
cost = 70
icon = ExtResource("1_16qcg")
type = 2
is_active = false
level = 1
max_level = 1

View File

@@ -131,7 +131,7 @@ texture = ExtResource("2_dfydr")
12:11/0 = 0
13:11/0 = 0
2:2/0 = 0
2:2/0/probability = 0.0
2:2/0/probability = 0.8
[resource]
sources/0 = SubResource("TileSetAtlasSource_cagp7")

View File

@@ -1,10 +1,11 @@
[gd_resource type="TileSet" load_steps=14 format=3 uid="uid://bc5a20s6kuy8e"]
[gd_resource type="TileSet" load_steps=15 format=3 uid="uid://bc5a20s6kuy8e"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_ej5iv"]
[ext_resource type="PackedScene" uid="uid://54w4wisfj8v8" path="res://objects/entities/coin.tscn" id="2_31a0q"]
[ext_resource type="PackedScene" uid="uid://c40r76qqacqie" path="res://objects/entities/collapsing_block.tscn" id="3_31a0q"]
[ext_resource type="PackedScene" uid="uid://ct8fim6mduyl3" path="res://objects/entities/collapsing_bridge.tscn" id="3_x63lh"]
[ext_resource type="PackedScene" uid="uid://bargnp4twtmxg" path="res://objects/entities/big_coin.tscn" id="4_ov0dn"]
[ext_resource type="PackedScene" uid="uid://buff711j0f2ph" path="res://objects/entities/spike_wheel.tscn" id="4_x63lh"]
[ext_resource type="PackedScene" uid="uid://d08dfqmirnd66" path="res://objects/entities/big_treasure.tscn" id="5_xxibl"]
[ext_resource type="PackedScene" uid="uid://073ts5cxtwbl" path="res://objects/entities/treasure.tscn" id="6_fmgww"]
[ext_resource type="PackedScene" uid="uid://cm3rixnnev1pg" path="res://objects/entities/jump_pad.tscn" id="7_0kjxj"]
@@ -147,6 +148,7 @@ scenes/7/scene = ExtResource("8_83o0w")
scenes/8/scene = ExtResource("9_at40q")
scenes/9/scene = ExtResource("10_ivcjr")
scenes/10/scene = ExtResource("3_31a0q")
scenes/11/scene = ExtResource("4_x63lh")
[resource]
physics_layer_0/collision_layer = 1

View File

@@ -1,7 +1,8 @@
[gd_resource type="TileSet" load_steps=5 format=3 uid="uid://bbppo0irxdmqy"]
[gd_resource type="TileSet" load_steps=7 format=3 uid="uid://bbppo0irxdmqy"]
[ext_resource type="Texture2D" uid="uid://djifxc5x0dyrw" path="res://sprites/ppc_tileset.png" id="1_6ec4i"]
[ext_resource type="Texture2D" uid="uid://cw42lvnqxubq2" path="res://sprites/PS_Tileset_10_nes.png" id="2_0dgh6"]
[ext_resource type="Texture2D" uid="uid://do6m4ry8ss01e" path="res://sprites/PS_Tileset_12_nes.png" id="3_0dgh6"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_8ljy4"]
texture = ExtResource("1_6ec4i")
@@ -183,6 +184,68 @@ texture = ExtResource("2_0dgh6")
15:9/0 = 0
15:9/0/texture_origin = Vector2i(0, 8)
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_a1mhh"]
texture = ExtResource("3_0dgh6")
13:5/0 = 0
14:5/0 = 0
15:5/0 = 0
15:6/0 = 0
14:7/0 = 0
13:7/0 = 0
13:8/0 = 0
14:8/0 = 0
14:6/0 = 0
13:6/0 = 0
17:6/0 = 0
17:7/0 = 0
19:5/0 = 0
20:5/0 = 0
21:5/0 = 0
21:6/0 = 0
20:6/0 = 0
19:6/0 = 0
20:7/0 = 0
21:7/0 = 0
21:8/0 = 0
20:8/0 = 0
18:9/0 = 0
17:9/0 = 0
16:9/0 = 0
15:9/0 = 0
14:9/0 = 0
13:9/0 = 0
12:9/0 = 0
13:11/0 = 0
12:11/0 = 0
12:12/0 = 0
13:12/0 = 0
14:10/0 = 0
15:10/0 = 0
15:11/0 = 0
15:12/0 = 0
14:12/0 = 0
14:11/0 = 0
16:10/0 = 0
17:10/0 = 0
17:11/0 = 0
17:12/0 = 0
16:12/0 = 0
16:11/0 = 0
18:10/0 = 0
19:10/0 = 0
19:11/0 = 0
18:11/0 = 0
18:12/0 = 0
19:12/0 = 0
21:10/0 = 0
20:10/0 = 0
20:11/0 = 0
21:12/0 = 0
21:11/0 = 0
22:11/0 = 0
22:10/0 = 0
[resource]
sources/0 = SubResource("TileSetAtlasSource_8ljy4")
sources/1 = SubResource("TileSetAtlasSource_jjobv")
sources/3 = SubResource("TileSetAtlasSource_a1mhh")

View File

@@ -1,7 +1,572 @@
[gd_resource type="TileSet" load_steps=3 format=3 uid="uid://cu2sx7qigrqnv"]
[gd_resource type="TileSet" load_steps=5 format=3 uid="uid://cu2sx7qigrqnv"]
[ext_resource type="Texture2D" uid="uid://do6m4ry8ss01e" path="res://sprites/PS_Tileset_12_nes.png" id="1_2p3w4"]
[ext_resource type="Texture2D" uid="uid://cw42lvnqxubq2" path="res://sprites/PS_Tileset_10_nes.png" id="2_43n76"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_43n76"]
texture = ExtResource("1_2p3w4")
1:0/0 = 0
1:0/0/terrain_set = 0
1:0/0/terrain = 2
1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:0/0/terrains_peering_bit/right_side = 2
1:0/0/terrains_peering_bit/bottom_right_corner = 2
1:0/0/terrains_peering_bit/bottom_side = 2
2:0/0 = 0
2:0/0/terrain_set = 0
2:0/0/terrain = 2
2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:0/0/terrains_peering_bit/right_side = 2
2:0/0/terrains_peering_bit/bottom_right_corner = 2
2:0/0/terrains_peering_bit/bottom_side = 2
2:0/0/terrains_peering_bit/bottom_left_corner = 2
2:0/0/terrains_peering_bit/left_side = 2
3:0/0 = 0
3:0/0/terrain_set = 0
3:0/0/terrain = 2
3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:0/0/terrains_peering_bit/bottom_side = 2
3:0/0/terrains_peering_bit/bottom_left_corner = 2
3:0/0/terrains_peering_bit/left_side = 2
6:0/0 = 0
6:0/0/terrain_set = 0
6:0/0/terrain = 2
6:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:0/0/terrains_peering_bit/right_side = 2
6:0/0/terrains_peering_bit/bottom_side = 2
7:0/0 = 0
7:0/0/terrain_set = 0
7:0/0/terrain = 2
7:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:0/0/terrains_peering_bit/right_side = 2
7:0/0/terrains_peering_bit/left_side = 2
8:0/0 = 0
8:0/0/terrain_set = 0
8:0/0/terrain = 2
8:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:0/0/terrains_peering_bit/bottom_side = 2
8:0/0/terrains_peering_bit/left_side = 2
13:0/0 = 0
15:0/0 = 0
15:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
20:0/0 = 0
21:0/0 = 0
22:0/0 = 0
0:1/0 = 0
0:1/0/terrain_set = 0
0:1/0/terrain = 2
0:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:1/0/terrains_peering_bit/right_side = 2
0:1/0/terrains_peering_bit/bottom_right_corner = 2
0:1/0/terrains_peering_bit/bottom_side = 2
1:1/0 = 0
1:1/0/terrain_set = 0
1:1/0/terrain = 2
1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:1/0/terrains_peering_bit/right_side = 2
1:1/0/terrains_peering_bit/bottom_right_corner = 2
1:1/0/terrains_peering_bit/bottom_side = 2
1:1/0/terrains_peering_bit/bottom_left_corner = 2
1:1/0/terrains_peering_bit/left_side = 2
1:1/0/terrains_peering_bit/top_side = 2
1:1/0/terrains_peering_bit/top_right_corner = 2
2:1/0 = 0
2:1/0/terrain_set = 0
2:1/0/terrain = 2
2:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:1/0/terrains_peering_bit/right_side = 2
2:1/0/terrains_peering_bit/bottom_right_corner = 2
2:1/0/terrains_peering_bit/bottom_side = 2
2:1/0/terrains_peering_bit/bottom_left_corner = 2
2:1/0/terrains_peering_bit/left_side = 2
2:1/0/terrains_peering_bit/top_left_corner = 2
2:1/0/terrains_peering_bit/top_side = 2
2:1/0/terrains_peering_bit/top_right_corner = 2
3:1/0 = 0
3:1/0/terrain_set = 0
3:1/0/terrain = 2
3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:1/0/terrains_peering_bit/right_side = 2
3:1/0/terrains_peering_bit/bottom_right_corner = 2
3:1/0/terrains_peering_bit/bottom_side = 2
3:1/0/terrains_peering_bit/bottom_left_corner = 2
3:1/0/terrains_peering_bit/left_side = 2
3:1/0/terrains_peering_bit/top_left_corner = 2
3:1/0/terrains_peering_bit/top_side = 2
4:1/0 = 0
4:1/0/terrain_set = 0
4:1/0/terrain = 2
4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:1/0/terrains_peering_bit/bottom_side = 2
4:1/0/terrains_peering_bit/bottom_left_corner = 2
4:1/0/terrains_peering_bit/left_side = 2
5:1/0 = 0
5:1/0/terrain_set = 0
5:1/0/terrain = 2
5:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
5:1/0/terrains_peering_bit/right_side = 2
5:1/0/terrains_peering_bit/bottom_side = 2
6:1/0 = 0
6:1/0/terrain_set = 0
6:1/0/terrain = 2
6:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:1/0/terrains_peering_bit/left_side = 2
6:1/0/terrains_peering_bit/top_side = 2
8:1/0 = 0
8:1/0/terrain_set = 0
8:1/0/terrain = 2
8:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:1/0/terrains_peering_bit/right_side = 2
8:1/0/terrains_peering_bit/top_side = 2
9:1/0 = 0
9:1/0/terrain_set = 0
9:1/0/terrain = 2
9:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:1/0/terrains_peering_bit/bottom_side = 2
9:1/0/terrains_peering_bit/left_side = 2
11:1/0 = 0
11:1/0/terrain_set = 0
11:1/0/terrain = 2
11:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:1/0/terrains_peering_bit/bottom_side = 2
13:1/0 = 0
14:1/0 = 0
14:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:1/0 = 0
15:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:1/0 = 0
17:1/0 = 0
18:1/0 = 0
18:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
19:1/0 = 0
19:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
20:1/0 = 0
21:1/0 = 0
22:1/0 = 0
0:2/0 = 0
0:2/0/terrain_set = 0
0:2/0/terrain = 2
0:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:2/0/terrains_peering_bit/right_side = 2
0:2/0/terrains_peering_bit/bottom_right_corner = 2
0:2/0/terrains_peering_bit/bottom_side = 2
0:2/0/terrains_peering_bit/top_side = 2
0:2/0/terrains_peering_bit/top_right_corner = 2
1:2/0 = 0
1:2/0/terrain_set = 0
1:2/0/terrain = 2
1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:2/0/terrains_peering_bit/right_side = 2
1:2/0/terrains_peering_bit/bottom_right_corner = 2
1:2/0/terrains_peering_bit/bottom_side = 2
1:2/0/terrains_peering_bit/bottom_left_corner = 2
1:2/0/terrains_peering_bit/left_side = 2
1:2/0/terrains_peering_bit/top_left_corner = 2
1:2/0/terrains_peering_bit/top_side = 2
1:2/0/terrains_peering_bit/top_right_corner = 2
2:2/0 = 0
2:2/0/terrain_set = 0
2:2/0/terrain = 2
2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:2/0/terrains_peering_bit/right_side = 2
2:2/0/terrains_peering_bit/bottom_right_corner = 2
2:2/0/terrains_peering_bit/bottom_side = 2
2:2/0/terrains_peering_bit/bottom_left_corner = 2
2:2/0/terrains_peering_bit/left_side = 2
2:2/0/terrains_peering_bit/top_left_corner = 2
2:2/0/terrains_peering_bit/top_side = 2
2:2/0/terrains_peering_bit/top_right_corner = 2
3:2/0 = 0
3:2/0/terrain_set = 0
3:2/0/terrain = 2
3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:2/0/terrains_peering_bit/right_side = 2
3:2/0/terrains_peering_bit/bottom_right_corner = 2
3:2/0/terrains_peering_bit/bottom_side = 2
3:2/0/terrains_peering_bit/bottom_left_corner = 2
3:2/0/terrains_peering_bit/left_side = 2
3:2/0/terrains_peering_bit/top_left_corner = 2
3:2/0/terrains_peering_bit/top_side = 2
3:2/0/terrains_peering_bit/top_right_corner = 2
4:2/0 = 0
4:2/0/terrain_set = 0
4:2/0/terrain = 2
4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:2/0/terrains_peering_bit/bottom_side = 2
4:2/0/terrains_peering_bit/bottom_left_corner = 2
4:2/0/terrains_peering_bit/left_side = 2
4:2/0/terrains_peering_bit/top_left_corner = 2
4:2/0/terrains_peering_bit/top_side = 2
5:2/0 = 0
5:2/0/terrain_set = 0
5:2/0/terrain = 2
5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
5:2/0/terrains_peering_bit/bottom_side = 2
5:2/0/terrains_peering_bit/top_side = 2
9:2/0 = 0
9:2/0/terrain_set = 0
9:2/0/terrain = 2
9:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:2/0/terrains_peering_bit/bottom_side = 2
9:2/0/terrains_peering_bit/top_side = 2
11:2/0 = 0
11:2/0/terrain_set = 0
11:2/0/terrain = 2
11:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:2/0/terrains_peering_bit/bottom_side = 2
11:2/0/terrains_peering_bit/top_side = 2
16:2/0 = 0
16:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
19:2/0 = 0
19:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
20:2/0 = 0
21:2/0 = 0
22:2/0 = 0
0:3/0 = 0
0:3/0/terrain_set = 0
0:3/0/terrain = 2
0:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:3/0/terrains_peering_bit/right_side = 2
0:3/0/terrains_peering_bit/top_side = 2
0:3/0/terrains_peering_bit/top_right_corner = 2
1:3/0 = 0
1:3/0/terrain_set = 0
1:3/0/terrain = 2
1:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:3/0/terrains_peering_bit/right_side = 2
1:3/0/terrains_peering_bit/bottom_right_corner = 2
1:3/0/terrains_peering_bit/bottom_side = 2
1:3/0/terrains_peering_bit/left_side = 2
1:3/0/terrains_peering_bit/top_left_corner = 2
1:3/0/terrains_peering_bit/top_side = 2
1:3/0/terrains_peering_bit/top_right_corner = 2
2:3/0 = 0
2:3/0/terrain_set = 0
2:3/0/terrain = 2
2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:3/0/terrains_peering_bit/right_side = 2
2:3/0/terrains_peering_bit/bottom_right_corner = 2
2:3/0/terrains_peering_bit/bottom_side = 2
2:3/0/terrains_peering_bit/bottom_left_corner = 2
2:3/0/terrains_peering_bit/left_side = 2
2:3/0/terrains_peering_bit/top_left_corner = 2
2:3/0/terrains_peering_bit/top_side = 2
2:3/0/terrains_peering_bit/top_right_corner = 2
3:3/0 = 0
3:3/0/terrain_set = 0
3:3/0/terrain = 2
3:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:3/0/terrains_peering_bit/right_side = 2
3:3/0/terrains_peering_bit/bottom_side = 2
3:3/0/terrains_peering_bit/bottom_left_corner = 2
3:3/0/terrains_peering_bit/left_side = 2
3:3/0/terrains_peering_bit/top_left_corner = 2
3:3/0/terrains_peering_bit/top_side = 2
3:3/0/terrains_peering_bit/top_right_corner = 2
4:3/0 = 0
4:3/0/terrain_set = 0
4:3/0/terrain = 2
4:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:3/0/terrains_peering_bit/left_side = 2
4:3/0/terrains_peering_bit/top_left_corner = 2
4:3/0/terrains_peering_bit/top_side = 2
5:3/0 = 0
5:3/0/terrain_set = 0
5:3/0/terrain = 2
5:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
5:3/0/terrains_peering_bit/right_side = 2
5:3/0/terrains_peering_bit/top_side = 2
6:3/0 = 0
6:3/0/terrain_set = 0
6:3/0/terrain = 2
6:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:3/0/terrains_peering_bit/bottom_side = 2
6:3/0/terrains_peering_bit/left_side = 2
8:3/0 = 0
8:3/0/terrain_set = 0
8:3/0/terrain = 2
8:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:3/0/terrains_peering_bit/right_side = 2
8:3/0/terrains_peering_bit/bottom_side = 2
9:3/0 = 0
9:3/0/terrain_set = 0
9:3/0/terrain = 2
9:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:3/0/terrains_peering_bit/left_side = 2
9:3/0/terrains_peering_bit/top_side = 2
11:3/0 = 0
11:3/0/terrain_set = 0
11:3/0/terrain = 2
11:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:3/0/terrains_peering_bit/top_side = 2
13:3/0 = 0
14:3/0 = 0
14:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:3/0 = 0
15:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:3/0 = 0
16:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
17:3/0 = 0
17:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
18:3/0 = 0
19:3/0 = 0
20:3/0 = 0
21:3/0 = 0
22:3/0 = 0
1:4/0 = 0
1:4/0/terrain_set = 0
1:4/0/terrain = 2
1:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:4/0/terrains_peering_bit/right_side = 2
1:4/0/terrains_peering_bit/top_side = 2
1:4/0/terrains_peering_bit/top_right_corner = 2
2:4/0 = 0
2:4/0/terrain_set = 0
2:4/0/terrain = 2
2:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:4/0/terrains_peering_bit/right_side = 2
2:4/0/terrains_peering_bit/left_side = 2
2:4/0/terrains_peering_bit/top_left_corner = 2
2:4/0/terrains_peering_bit/top_side = 2
2:4/0/terrains_peering_bit/top_right_corner = 2
3:4/0 = 0
3:4/0/terrain_set = 0
3:4/0/terrain = 2
3:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:4/0/terrains_peering_bit/left_side = 2
3:4/0/terrains_peering_bit/top_left_corner = 2
3:4/0/terrains_peering_bit/top_side = 2
6:4/0 = 0
6:4/0/terrain_set = 0
6:4/0/terrain = 2
6:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:4/0/terrains_peering_bit/right_side = 2
6:4/0/terrains_peering_bit/top_side = 2
7:4/0 = 0
7:4/0/terrain_set = 0
7:4/0/terrain = 2
7:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:4/0/terrains_peering_bit/right_side = 2
7:4/0/terrains_peering_bit/left_side = 2
8:4/0 = 0
8:4/0/terrain_set = 0
8:4/0/terrain = 2
8:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:4/0/terrains_peering_bit/left_side = 2
8:4/0/terrains_peering_bit/top_side = 2
13:4/0 = 0
15:4/0 = 0
15:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
20:4/0 = 0
21:4/0 = 0
22:4/0 = 0
11:5/0 = 0
11:5/0/terrain_set = 0
11:5/0/terrain = 2
11:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:5/0/terrains_peering_bit/bottom_side = 2
13:5/0 = 0
14:5/0 = 0
15:5/0 = 0
19:5/0 = 0
20:5/0 = 0
21:5/0 = 0
22:5/0 = 0
0:6/0 = 0
0:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:6/0 = 0
1:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:6/0 = 0
2:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:6/0 = 0
3:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:6/0 = 0
4:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:6/0 = 0
6:6/0/terrain_set = 0
6:6/0/terrain = 2
6:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:6/0/terrains_peering_bit/right_side = 2
7:6/0 = 0
7:6/0/terrain_set = 0
7:6/0/terrain = 2
7:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:6/0/terrains_peering_bit/right_side = 2
7:6/0/terrains_peering_bit/left_side = 2
8:6/0 = 0
8:6/0/terrain_set = 0
8:6/0/terrain = 2
8:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:6/0/terrains_peering_bit/left_side = 2
10:6/0 = 0
10:6/0/terrain_set = 0
10:6/0/terrain = 2
10:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:6/0/terrains_peering_bit/right_side = 2
11:6/0 = 0
11:6/0/terrain_set = 0
11:6/0/terrain = 2
11:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:6/0/terrains_peering_bit/bottom_side = 2
11:6/0/terrains_peering_bit/left_side = 2
11:6/0/terrains_peering_bit/top_side = 2
13:6/0 = 0
14:6/0 = 0
15:6/0 = 0
17:6/0 = 0
19:6/0 = 0
20:6/0 = 0
21:6/0 = 0
22:6/0 = 0
0:7/0 = 0
0:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:7/0 = 0
1:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, -8, -8, -8, -8, 8, 0, 0)
3:7/0 = 0
3:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, 0, 0)
4:7/0 = 0
4:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:7/0 = 0
11:7/0/terrain_set = 0
11:7/0/terrain = 2
11:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:7/0/terrains_peering_bit/top_side = 2
13:7/0 = 0
14:7/0 = 0
17:7/0 = 0
20:7/0 = 0
21:7/0 = 0
22:7/0 = 0
7:8/0 = 0
7:8/0/terrain_set = 0
7:8/0/terrain = 2
7:8/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:8/0/terrains_peering_bit/bottom_side = 2
13:8/0 = 0
14:8/0 = 0
20:8/0 = 0
21:8/0 = 0
0:9/0 = 0
0:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:9/0 = 0
1:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(8, 8, -8, 8, -8, -8, 0, 0)
3:9/0 = 0
3:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 8, 8, 8, 8, -8, 0, 0)
4:9/0 = 0
4:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:9/0 = 0
6:9/0/terrain_set = 0
6:9/0/terrain = 2
6:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:9/0/terrains_peering_bit/right_side = 2
7:9/0 = 0
7:9/0/terrain_set = 0
7:9/0/terrain = 2
7:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:9/0/terrains_peering_bit/right_side = 2
7:9/0/terrains_peering_bit/left_side = 2
7:9/0/terrains_peering_bit/top_side = 2
8:9/0 = 0
8:9/0/terrain_set = 0
8:9/0/terrain = 2
8:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:9/0/terrains_peering_bit/left_side = 2
10:9/0 = 0
10:9/0/terrain_set = 0
10:9/0/terrain = 2
10:9/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:9/0/terrains_peering_bit/bottom_side = 2
12:9/0 = 0
13:9/0 = 0
14:9/0 = 0
15:9/0 = 0
16:9/0 = 0
17:9/0 = 0
18:9/0 = 0
0:10/0 = 0
0:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:10/0 = 0
1:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:10/0 = 0
2:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:10/0 = 0
3:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:10/0 = 0
4:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:10/0 = 0
10:10/0/terrain_set = 0
10:10/0/terrain = 2
10:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:10/0/terrains_peering_bit/right_side = 2
10:10/0/terrains_peering_bit/bottom_side = 2
10:10/0/terrains_peering_bit/top_side = 2
11:10/0 = 0
11:10/0/terrain_set = 0
11:10/0/terrain = 2
11:10/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:10/0/terrains_peering_bit/left_side = 2
14:10/0 = 0
15:10/0 = 0
16:10/0 = 0
17:10/0 = 0
18:10/0 = 0
19:10/0 = 0
20:10/0 = 0
21:10/0 = 0
22:10/0 = 0
6:11/0 = 0
6:11/0/terrain_set = 0
6:11/0/terrain = 2
6:11/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:11/0/terrains_peering_bit/right_side = 2
7:11/0 = 0
7:11/0/terrain_set = 0
7:11/0/terrain = 2
7:11/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:11/0/terrains_peering_bit/right_side = 2
7:11/0/terrains_peering_bit/bottom_side = 2
7:11/0/terrains_peering_bit/left_side = 2
8:11/0 = 0
8:11/0/terrain_set = 0
8:11/0/terrain = 2
8:11/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:11/0/terrains_peering_bit/left_side = 2
10:11/0 = 0
10:11/0/terrain_set = 0
10:11/0/terrain = 2
10:11/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:11/0/terrains_peering_bit/top_side = 2
12:11/0 = 0
13:11/0 = 0
14:11/0 = 0
15:11/0 = 0
16:11/0 = 0
17:11/0 = 0
18:11/0 = 0
19:11/0 = 0
20:11/0 = 0
21:11/0 = 0
22:11/0 = 0
0:12/0 = 0
1:12/0 = 0
2:12/0 = 0
3:12/0 = 0
4:12/0 = 0
7:12/0 = 0
7:12/0/terrain_set = 0
7:12/0/terrain = 2
7:12/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:12/0/terrains_peering_bit/top_side = 2
12:12/0 = 0
13:12/0 = 0
14:12/0 = 0
15:12/0 = 0
16:12/0 = 0
17:12/0 = 0
18:12/0 = 0
19:12/0 = 0
21:12/0 = 0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_4xq2o"]
texture = ExtResource("2_43n76")
1:0/0 = 0
@@ -497,4 +1062,7 @@ terrain_set_0/terrain_0/name = "Village"
terrain_set_0/terrain_0/color = Color(1, 1, 1, 1)
terrain_set_0/terrain_1/name = "Platforms"
terrain_set_0/terrain_1/color = Color(0.46875, 0.5, 0.25, 1)
terrain_set_0/terrain_2/name = "Forest"
terrain_set_0/terrain_2/color = Color(0.536634, 0.836478, 0.371357, 1)
sources/1 = SubResource("TileSetAtlasSource_4xq2o")
sources/0 = SubResource("TileSetAtlasSource_43n76")

131
scenes/level_forest_5.tscn Normal file

File diff suppressed because one or more lines are too long

View File

@@ -66,9 +66,6 @@ process_material = SubResource("ParticleProcessMaterial_lgb3u")
[node name="UI Layer" parent="." instance=ExtResource("3_4fsls")]
[node name="HUD" parent="UI Layer" index="0" node_paths=PackedStringArray("player_health")]
player_health = NodePath("../../Brick Player/HealthComponent")
[node name="DeathScreen" parent="UI Layer" index="1" node_paths=PackedStringArray("nodes_to_disable")]
current_level = ExtResource("4_onnch")
nodes_to_disable = [NodePath("../../Brick Player")]

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=32 format=4 uid="uid://h60obxmju6mo"]
[gd_scene load_steps=33 format=4 uid="uid://h60obxmju6mo"]
[ext_resource type="PackedScene" uid="uid://dyp4i4ru2j2jh" path="res://objects/fxs/explosion_fx.tscn" id="1_p30ax"]
[ext_resource type="PackedScene" uid="uid://dx80ivlvuuew4" path="res://objects/fxs/fire_fx.tscn" id="2_a7yjf"]
@@ -22,6 +22,7 @@
[ext_resource type="Script" uid="uid://8r1y8elyw7kt" path="res://scripts/console_management.gd" id="19_0pba3"]
[ext_resource type="PackedScene" uid="uid://cawlpch2lk3a2" path="res://objects/level/world_environment.tscn" id="20_embdf"]
[ext_resource type="PackedScene" uid="uid://cywsu7yrtjdog" path="res://objects/level/global_light.tscn" id="21_fytod"]
[ext_resource type="PackedScene" uid="uid://t6h2ra7kjyq" path="res://objects/entities/small_heal_potion.tscn" id="23_m6h4x"]
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_j7bvy"]
texture = ExtResource("7_uvxky")
@@ -356,6 +357,15 @@ skill_manager = NodePath("../Brick Player/SkillManager")
[node name="Global Light" parent="." instance=ExtResource("21_fytod")]
[node name="SmallHealPotion" parent="." instance=ExtResource("23_m6h4x")]
position = Vector2(1074, -105)
[node name="SmallHealPotion2" parent="." instance=ExtResource("23_m6h4x")]
position = Vector2(1244, -41)
[node name="SmallHealPotion3" parent="." instance=ExtResource("23_m6h4x")]
position = Vector2(1359, -42)
[connection signal="on_death" from="Brick Player/HealthComponent" to="UI Layer/DeathScreen" method="on_player_death"]
[connection signal="on_death" from="Brick Player/HealthComponent" to="UI Layer/GameOverScreen" method="on_player_death"]

File diff suppressed because one or more lines are too long

View File

@@ -1,27 +1,38 @@
[gd_scene load_steps=6 format=3 uid="uid://cl00e2ocomk3m"]
[gd_scene load_steps=12 format=3 uid="uid://cl00e2ocomk3m"]
[ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://objects/ui/main_menu.tscn" id="1_ekxnf"]
[ext_resource type="PackedScene" uid="uid://8b6ol5sssbgo" path="res://features/ui/menus/main_menu.tscn" id="1_ekxnf"]
[ext_resource type="Script" uid="uid://dg2l7cw6da4vb" path="res://common/AppRoot.cs" id="1_rtw2f"]
[ext_resource type="PackedScene" uid="uid://y0ae6e7t70fj" path="res://objects/ui/settings_menu.tscn" id="2_bqqt6"]
[ext_resource type="PackedScene" uid="uid://bwgmrcyj4mvu" path="res://objects/ui/credits.tscn" id="3_bqqt6"]
[ext_resource type="PackedScene" uid="uid://chqb11pfoqmeb" path="res://scenes/level_village_2.tscn" id="3_lgwnu"]
[ext_resource type="PackedScene" uid="uid://bol7g83v2accs" path="res://scenes/level_village_1.tscn" id="3_oa1go"]
[ext_resource type="PackedScene" uid="uid://b5fx1vdfky307" path="res://objects/ui/audio_settings.tscn" id="4_8ln24"]
[ext_resource type="PackedScene" uid="uid://h60obxmju6mo" path="res://scenes/level_village_3.tscn" id="4_flqon"]
[ext_resource type="PackedScene" uid="uid://bhad760x3vvco" path="res://scenes/level_village_4.tscn" id="5_rcqid"]
[ext_resource type="PackedScene" uid="uid://cvfsbiy5ggrpg" path="res://objects/ui/input_settings.tscn" id="5_rtw2f"]
[ext_resource type="PackedScene" uid="uid://dagpmlgvr262d" path="res://scenes/level_forest_5.tscn" id="6_1ajci"]
[node name="Main menu" type="CanvasLayer"]
[node name="AppRoot" type="Node2D"]
script = ExtResource("1_rtw2f")
_levels = Array[PackedScene]([ExtResource("3_oa1go"), ExtResource("3_lgwnu"), ExtResource("4_flqon"), ExtResource("5_rcqid"), ExtResource("6_1ajci")])
_mainMenu = null
[node name="MainMenu" parent="." node_paths=PackedStringArray("settings_control", "credits_control") instance=ExtResource("1_ekxnf")]
settings_control = NodePath("../Settings menu")
credits_control = NodePath("../Credits")
[node name="Main menu" type="CanvasLayer" parent="."]
[node name="Settings menu" parent="." node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("2_bqqt6")]
[node name="MainMenu" parent="Main menu" node_paths=PackedStringArray("SettingsControl", "CreditsControl") instance=ExtResource("1_ekxnf")]
SettingsControl = NodePath("../Settings menu")
CreditsControl = NodePath("../Credits")
[node name="Settings menu" parent="Main menu" node_paths=PackedStringArray("input_settings", "audio_settings") instance=ExtResource("2_bqqt6")]
visible = false
input_settings = NodePath("../Input Settings")
audio_settings = NodePath("../Audio settings")
[node name="Credits" parent="." instance=ExtResource("3_bqqt6")]
[node name="Credits" parent="Main menu" instance=ExtResource("3_bqqt6")]
visible = false
[node name="Audio settings" parent="." instance=ExtResource("4_8ln24")]
[node name="Audio settings" parent="Main menu" instance=ExtResource("4_8ln24")]
visible = false
[node name="Input Settings" parent="." instance=ExtResource("5_rtw2f")]
[node name="Input Settings" parent="Main menu" instance=ExtResource("5_rtw2f")]
visible = false

View File

@@ -0,0 +1,70 @@
using Godot;
namespace Mr.BrickAdventures.scripts.Resources;
public partial class ChargeThrowInputResource : ThrowInputResource
{
[Export] public float MinPower { get; set; } = 0.5f;
[Export] public float MaxPower { get; set; } = 2.0f;
[Export] public float MaxChargeTime { get; set; } = 2.0f;
[Export] public float MinChargeDuration { get; set; } = 0.1f;
private bool _isCharging = false;
private float _chargeStartTime = 0f;
[Signal] public delegate void ChargeStartedEventHandler();
[Signal] public delegate void ChargeUpdatedEventHandler(float chargeRatio);
[Signal] public delegate void ChargeStoppedEventHandler();
public override void ProcessInput(InputEvent @event)
{
if (@event.IsActionPressed("attack"))
{
_isCharging = true;
_chargeStartTime = Time.GetTicksMsec() / 1000f;
EmitSignalChargeStarted();
}
if (@event.IsActionReleased("attack") && _isCharging)
{
var power = CalculatePower();
_isCharging = false;
EmitSignalThrowRequested(power);
EmitSignalChargeStopped();
}
}
public override void Update(double delta)
{
if (!_isCharging) return;
var t = Mathf.Clamp(GetChargeRatio(), MinPower, MaxPower);
EmitSignalChargeUpdated(t);
}
public override bool SupportsCharging()
{
return true;
}
private float CalculatePower()
{
var now = Time.GetTicksMsec() / 1000f;
var heldTime = now - _chargeStartTime;
if (heldTime < MinChargeDuration)
return MinPower;
var t = Mathf.Clamp(heldTime / MaxChargeTime, 0f, 1f);
return Mathf.Lerp(MinPower, MaxPower, t);
}
private float GetChargeRatio()
{
if (!_isCharging) return MinPower;
var now = Time.GetTicksMsec() / 1000f;
var heldTime = now - _chargeStartTime;
var t = Mathf.Clamp(heldTime / MaxChargeTime, 0f, 1f);
return Mathf.Lerp(MinPower, MaxPower, t);
}
}

View File

@@ -0,0 +1 @@
uid://dtpdh4jp51jis

View File

@@ -0,0 +1,9 @@
using Godot;
namespace Mr.BrickAdventures.scripts.Resources;
public partial class CollectableResource : Resource
{
[Export] public Variant Amount { get; set; } = 0.0;
[Export] public CollectableType Type { get; set; }
}

View File

@@ -0,0 +1 @@
uid://gptsgaw3agkf

View File

@@ -0,0 +1,8 @@
namespace Mr.BrickAdventures.scripts.Resources;
public enum CollectableType
{
Coin,
Kid,
Health,
}

Some files were not shown because too many files have changed in this diff Show More