fixed basic movement, now add world loading
This commit is contained in:
parent
34ba37312a
commit
50f37ebc5f
23 changed files with 482 additions and 27 deletions
146
scripts/world/ChunkManager.cs
Normal file
146
scripts/world/ChunkManager.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
using Godot;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
|
||||
public partial class ChunkManager : Node2D
|
||||
{
|
||||
[Export] public NodePath PlayerPath;
|
||||
[Export] public int LoadRadius = 1; // 1 -> 3x3
|
||||
|
||||
private CharacterBody2D? _player;
|
||||
private PackManager? _packs;
|
||||
|
||||
private WorldIndex? _world;
|
||||
private Dictionary<(int x, int y), string> _chunkMap = new();
|
||||
private readonly Dictionary<(int x, int y), Node2D> _loaded = new();
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
_player = GetNodeOrNull<CharacterBody2D>(PlayerPath);
|
||||
if (_player == null)
|
||||
{
|
||||
GD.PrintErr("ChunkManager: PlayerPath not set or invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
_packs = GetNodeOrNull<PackManager>("/root/Main/PackManager");
|
||||
if (_packs == null)
|
||||
{
|
||||
// fallback: search up the tree for PackManager
|
||||
_packs = GetParent()?.GetNodeOrNull<PackManager>("PackManager");
|
||||
}
|
||||
|
||||
if (_packs == null)
|
||||
{
|
||||
GD.PrintErr("ChunkManager: PackManager not found. Add it to your Main scene.");
|
||||
return;
|
||||
}
|
||||
|
||||
LoadWorldIndex();
|
||||
}
|
||||
|
||||
private void LoadWorldIndex()
|
||||
{
|
||||
var worldPath = _packs.Resolve("data/world/world_main.json");
|
||||
if (worldPath == null)
|
||||
{
|
||||
GD.PrintErr("ChunkManager: Could not resolve data/world/world_main.json from packs.");
|
||||
return;
|
||||
}
|
||||
|
||||
var json = FileAccess.GetFileAsString(worldPath);
|
||||
_world = JsonSerializer.Deserialize<WorldIndex>(json);
|
||||
if (_world == null)
|
||||
{
|
||||
GD.PrintErr("ChunkManager: Failed to parse world index.");
|
||||
return;
|
||||
}
|
||||
|
||||
_chunkMap = _world.BuildChunkMap();
|
||||
GD.Print($"World loaded: {_world.world_id}, chunks: {_chunkMap.Count}, chunk_size_px={_world.chunk_size_px}");
|
||||
}
|
||||
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
if (_player == null || _world == null) return;
|
||||
|
||||
var (cx, cy) = WorldPosToChunk(_player.GlobalPosition, _world.chunk_size_px);
|
||||
|
||||
for (int dy = -LoadRadius; dy <= LoadRadius; dy++)
|
||||
for (int dx = -LoadRadius; dx <= LoadRadius; dx++)
|
||||
{
|
||||
var key = (cx + dx, cy + dy);
|
||||
EnsureLoaded(key.x, key.y);
|
||||
}
|
||||
|
||||
// Unload chunks that are too far
|
||||
var keysToRemove = new List<(int x, int y)>();
|
||||
foreach (var kv in _loaded)
|
||||
{
|
||||
var (x, y) = kv.Key;
|
||||
if (Math.Abs(x - cx) > LoadRadius || Math.Abs(y - cy) > LoadRadius)
|
||||
keysToRemove.Add((x, y));
|
||||
}
|
||||
foreach (var k in keysToRemove)
|
||||
{
|
||||
_loaded[k].QueueFree();
|
||||
_loaded.Remove(k);
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureLoaded(int x, int y)
|
||||
{
|
||||
var key = (x, y);
|
||||
if (_loaded.ContainsKey(key)) return;
|
||||
if (!_chunkMap.TryGetValue(key, out var relPath)) return;
|
||||
|
||||
// Use pack resolve for the chunk file itself
|
||||
var chunkPath = _packs!.Resolve(relPath);
|
||||
if (chunkPath == null)
|
||||
{
|
||||
GD.PrintErr($"Chunk missing in packs: {relPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
// For now, we don't parse chunk contents yet; we just visualize existence + biome by file naming/placeholder.
|
||||
// Next step: parse biome from JSON and use it to color.
|
||||
var chunkJson = FileAccess.GetFileAsString(chunkPath);
|
||||
using var doc = JsonDocument.Parse(chunkJson);
|
||||
var biome = doc.RootElement.TryGetProperty("biome", out var b) ? b.GetString() : "biome:unknown";
|
||||
|
||||
var node = CreateDebugChunkNode(x, y, _world!.chunk_size_px, biome ?? "biome:unknown");
|
||||
AddChild(node);
|
||||
_loaded[key] = node;
|
||||
}
|
||||
|
||||
private static (int cx, int cy) WorldPosToChunk(Vector2 pos, int chunkSizePx)
|
||||
{
|
||||
int cx = Mathf.FloorToInt(pos.X / chunkSizePx);
|
||||
int cy = Mathf.FloorToInt(pos.Y / chunkSizePx);
|
||||
return (cx, cy);
|
||||
}
|
||||
|
||||
private static Node2D CreateDebugChunkNode(int cx, int cy, int chunkSizePx, string biome)
|
||||
{
|
||||
var n = new Node2D();
|
||||
n.Name = $"Chunk_{cx}_{cy}";
|
||||
n.Position = new Vector2(cx * chunkSizePx, cy * chunkSizePx);
|
||||
|
||||
var rect = new ColorRect();
|
||||
rect.Size = new Vector2(chunkSizePx, chunkSizePx);
|
||||
rect.MouseFilter = Control.MouseFilterEnum.Ignore;
|
||||
|
||||
rect.Color = biome switch
|
||||
{
|
||||
"biome:forest" => new Color(0.1f, 0.35f, 0.1f, 0.25f),
|
||||
"biome:plains" => new Color(0.35f, 0.35f, 0.1f, 0.25f),
|
||||
"biome:town" => new Color(0.25f, 0.25f, 0.25f, 0.25f),
|
||||
_ => new Color(0.2f, 0.2f, 0.2f, 0.25f)
|
||||
};
|
||||
|
||||
// Add an outline using a Panel (cheap) or just rely on transparency for now
|
||||
n.AddChild(rect);
|
||||
return n;
|
||||
}
|
||||
}
|
||||
1
scripts/world/ChunkManager.cs.uid
Normal file
1
scripts/world/ChunkManager.cs.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://cqdq8fslu7cyp
|
||||
15
scripts/world/WorldIndex.cs
Normal file
15
scripts/world/WorldIndex.cs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
|
||||
public record WorldIndex(int schema, string world_id, string display_name, int chunk_size_px, int tile_size_px, int[] start_pos_px, List<WorldIndexChunk> chunks)
|
||||
{
|
||||
public Dictionary<(int x, int y), string> BuildChunkMap()
|
||||
{
|
||||
var map = new Dictionary<(int, int), string>();
|
||||
foreach (var c in chunks)
|
||||
map[(c.x, c.y)] = c.path;
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
public record WorldIndexChunk(int x, int y, string path);
|
||||
1
scripts/world/WorldIndex.cs.uid
Normal file
1
scripts/world/WorldIndex.cs.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bgtmfbm4qg0l5
|
||||
Loading…
Add table
Add a link
Reference in a new issue