Add initial project files and implement core game features
- Created README.md with project description and setup instructions - Added project configuration files (TheGame.csproj, TheGame.sln, project.godot) - Implemented main game scenes (MainMenu.tscn, Game.tscn, LoadGameMenu.tscn) - Developed game logic in C# scripts (Game.cs, MainMenu.cs, LoadGameMenu.cs, PauseMenu.cs, SaveManager.cs) - Introduced save/load functionality and timer display - Included icon.svg for game branding
This commit is contained in:
76
scripts/Game.cs
Normal file
76
scripts/Game.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Godot;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public partial class Game : Control
|
||||
{
|
||||
private Label _timerLabel;
|
||||
private Control _pauseMenu;
|
||||
private float _gameTime = 0.0f;
|
||||
private bool _isPaused = false;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_timerLabel = GetNode<Label>("UI/TimerLabel");
|
||||
_pauseMenu = GetNode<Control>("PauseMenu");
|
||||
|
||||
// Om vi kommer från Load Game, försök ladda sparat tillstånd
|
||||
if (GameState.LoadedGameTime >= 0)
|
||||
{
|
||||
_gameTime = GameState.LoadedGameTime;
|
||||
GameState.LoadedGameTime = -1; // Reset efter användning
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (!_isPaused)
|
||||
{
|
||||
_gameTime += (float)delta;
|
||||
UpdateTimerDisplay();
|
||||
}
|
||||
}
|
||||
|
||||
public override void _Input(InputEvent @event)
|
||||
{
|
||||
if (@event.IsActionPressed("ui_cancel")) // ESC key
|
||||
{
|
||||
TogglePause();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTimerDisplay()
|
||||
{
|
||||
int hours = (int)(_gameTime / 3600);
|
||||
int minutes = (int)((_gameTime % 3600) / 60);
|
||||
int seconds = (int)(_gameTime % 60);
|
||||
|
||||
_timerLabel.Text = $"{hours:D2}:{minutes:D2}:{seconds:D2}";
|
||||
}
|
||||
|
||||
public void TogglePause()
|
||||
{
|
||||
_isPaused = !_isPaused;
|
||||
_pauseMenu.Visible = _isPaused;
|
||||
|
||||
if (_isPaused)
|
||||
{
|
||||
GetTree().Paused = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetTree().Paused = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void _on_pause_button_pressed()
|
||||
{
|
||||
TogglePause();
|
||||
}
|
||||
|
||||
public float GetGameTime()
|
||||
{
|
||||
return _gameTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
9
scripts/GameState.cs
Normal file
9
scripts/GameState.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Godot;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public static class GameState
|
||||
{
|
||||
public static float LoadedGameTime = -1;
|
||||
}
|
||||
}
|
||||
73
scripts/LoadGameMenu.cs
Normal file
73
scripts/LoadGameMenu.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using Godot;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public partial class LoadGameMenu : Control
|
||||
{
|
||||
private VBoxContainer _saveList;
|
||||
private SaveManager _saveManager;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_saveList = GetNode<VBoxContainer>("VBoxContainer/ScrollContainer/SaveList");
|
||||
_saveManager = new SaveManager();
|
||||
PopulateSaveList();
|
||||
}
|
||||
|
||||
private void PopulateSaveList()
|
||||
{
|
||||
// Rensa tidigare innehåll
|
||||
foreach (Node child in _saveList.GetChildren())
|
||||
{
|
||||
child.QueueFree();
|
||||
}
|
||||
|
||||
var savedGames = _saveManager.GetSavedGames();
|
||||
|
||||
if (savedGames.Count == 0)
|
||||
{
|
||||
var noSavesLabel = new Label();
|
||||
noSavesLabel.Text = "No saved games found";
|
||||
noSavesLabel.HorizontalAlignment = HorizontalAlignment.Center;
|
||||
_saveList.AddChild(noSavesLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var saveData in savedGames)
|
||||
{
|
||||
var saveButton = new Button();
|
||||
|
||||
// Formatera tid för visning
|
||||
int hours = (int)(saveData.GameTime / 3600);
|
||||
int minutes = (int)((saveData.GameTime % 3600) / 60);
|
||||
int seconds = (int)(saveData.GameTime % 60);
|
||||
string timeText = $"{hours:D2}:{minutes:D2}:{seconds:D2}";
|
||||
|
||||
saveButton.Text = $"{saveData.SaveName}\nTime: {timeText}\nSaved: {saveData.SaveDate:yyyy-MM-dd HH:mm:ss}";
|
||||
|
||||
// Anslut knapp-händelse
|
||||
saveButton.Pressed += () => LoadSelectedGame(saveData);
|
||||
|
||||
_saveList.AddChild(saveButton);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSelectedGame(SaveData saveData)
|
||||
{
|
||||
if (_saveManager.LoadGame(saveData))
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://scenes/Game.tscn");
|
||||
}
|
||||
else
|
||||
{
|
||||
GD.PrintErr("Failed to load selected game");
|
||||
}
|
||||
}
|
||||
|
||||
private void _on_back_button_pressed()
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://scenes/MainMenu.tscn");
|
||||
}
|
||||
}
|
||||
}
|
||||
38
scripts/MainMenu.cs
Normal file
38
scripts/MainMenu.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Godot;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public partial class MainMenu : Control
|
||||
{
|
||||
private Button _loadButton;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_loadButton = GetNode<Button>("VBoxContainer/LoadButton");
|
||||
UpdateLoadButtonState();
|
||||
}
|
||||
|
||||
private void UpdateLoadButtonState()
|
||||
{
|
||||
// Kontrollera om det finns sparade spel
|
||||
var saveManager = new SaveManager();
|
||||
var savedGames = saveManager.GetSavedGames();
|
||||
_loadButton.Disabled = savedGames.Count == 0;
|
||||
}
|
||||
|
||||
private void _on_start_button_pressed()
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://scenes/Game.tscn");
|
||||
}
|
||||
|
||||
private void _on_load_button_pressed()
|
||||
{
|
||||
GetTree().ChangeSceneToFile("res://scenes/LoadGameMenu.tscn");
|
||||
}
|
||||
|
||||
private void _on_exit_button_pressed()
|
||||
{
|
||||
GetTree().Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
40
scripts/PauseMenu.cs
Normal file
40
scripts/PauseMenu.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using Godot;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public partial class PauseMenu : Control
|
||||
{
|
||||
private Game _gameController;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_gameController = GetParent<Game>();
|
||||
}
|
||||
|
||||
private void _on_resume_button_pressed()
|
||||
{
|
||||
_gameController.TogglePause();
|
||||
}
|
||||
|
||||
private void _on_save_button_pressed()
|
||||
{
|
||||
var saveManager = new SaveManager();
|
||||
float currentTime = _gameController.GetGameTime();
|
||||
saveManager.SaveGame(currentTime);
|
||||
|
||||
// Visa bekräftelse eller gå tillbaka till spelet
|
||||
_gameController.TogglePause();
|
||||
}
|
||||
|
||||
private void _on_main_menu_button_pressed()
|
||||
{
|
||||
GetTree().Paused = false;
|
||||
GetTree().ChangeSceneToFile("res://scenes/MainMenu.tscn");
|
||||
}
|
||||
|
||||
private void _on_desktop_button_pressed()
|
||||
{
|
||||
GetTree().Quit();
|
||||
}
|
||||
}
|
||||
}
|
||||
111
scripts/SaveManager.cs
Normal file
111
scripts/SaveManager.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace TheGame
|
||||
{
|
||||
public class SaveData
|
||||
{
|
||||
public float GameTime { get; set; }
|
||||
public DateTime SaveDate { get; set; }
|
||||
public string SaveName { get; set; }
|
||||
}
|
||||
|
||||
public class SaveManager
|
||||
{
|
||||
private readonly string _saveDirectory;
|
||||
|
||||
public SaveManager()
|
||||
{
|
||||
_saveDirectory = Path.Combine(OS.GetExecutablePath().GetBaseDir(), "saves");
|
||||
|
||||
// Skapa saves mapp om den inte finns
|
||||
if (!Directory.Exists(_saveDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(_saveDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveGame(float gameTime)
|
||||
{
|
||||
var saveData = new SaveData
|
||||
{
|
||||
GameTime = gameTime,
|
||||
SaveDate = DateTime.Now,
|
||||
SaveName = $"Save_{DateTime.Now:yyyyMMdd_HHmmss}"
|
||||
};
|
||||
|
||||
string fileName = $"{saveData.SaveName}.json";
|
||||
string filePath = Path.Combine(_saveDirectory, fileName);
|
||||
|
||||
try
|
||||
{
|
||||
string jsonString = JsonSerializer.Serialize(saveData, new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
File.WriteAllText(filePath, jsonString);
|
||||
GD.Print($"Game saved successfully: {fileName}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"Failed to save game: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public List<SaveData> GetSavedGames()
|
||||
{
|
||||
var savedGames = new List<SaveData>();
|
||||
|
||||
if (!Directory.Exists(_saveDirectory))
|
||||
return savedGames;
|
||||
|
||||
try
|
||||
{
|
||||
var saveFiles = Directory.GetFiles(_saveDirectory, "*.json");
|
||||
|
||||
foreach (string filePath in saveFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
string jsonString = File.ReadAllText(filePath);
|
||||
var saveData = JsonSerializer.Deserialize<SaveData>(jsonString);
|
||||
if (saveData != null)
|
||||
{
|
||||
savedGames.Add(saveData);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"Failed to load save file {filePath}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
// Sortera efter datum (nyast först)
|
||||
savedGames.Sort((a, b) => b.SaveDate.CompareTo(a.SaveDate));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"Failed to read saves directory: {ex.Message}");
|
||||
}
|
||||
|
||||
return savedGames;
|
||||
}
|
||||
|
||||
public bool LoadGame(SaveData saveData)
|
||||
{
|
||||
try
|
||||
{
|
||||
GameState.LoadedGameTime = saveData.GameTime;
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GD.PrintErr($"Failed to load game: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user