From 4c614ef14ebf4c3cd16c1e96283dc3763b9b0d0a Mon Sep 17 00:00:00 2001 From: Physcik Date: Sun, 11 Jan 2026 20:43:46 +0500 Subject: World rendering --- engine/Components/ResourceManager.go | 36 +++++++++++++ engine/Components/TextureManager.go | 54 +++++++++++++++++++ engine/Components/World.go | 72 ++++++++++++++++++++++++++ engine/CoreObjects/ResourceManager.go | 11 ---- engine/Dynamic/Common.go | 22 -------- engine/Dynamic/Descriptors/Textures.go | 12 +++++ engine/Dynamic/Descriptors/World.go | 32 +++++++++++- engine/Dynamic/Manager.go | 14 +++-- engine/Dynamic/Package.go | 48 ++++++++++++----- engine/Dynamic/Validation.go | 4 +- engine/Packages/TestPackage/Textures/Meta.json | 3 +- engine/Packages/TestPackage/Worlds/Main.json | 2 +- engine/Render/initWindow.go | 9 +++- engine/Utils/Files.go | 34 ++++++++++++ engine/main.go | 11 ++-- 15 files changed, 305 insertions(+), 59 deletions(-) create mode 100644 engine/Components/ResourceManager.go create mode 100644 engine/Components/TextureManager.go create mode 100644 engine/Components/World.go delete mode 100644 engine/CoreObjects/ResourceManager.go create mode 100644 engine/Utils/Files.go (limited to 'engine') diff --git a/engine/Components/ResourceManager.go b/engine/Components/ResourceManager.go new file mode 100644 index 0000000..19f0315 --- /dev/null +++ b/engine/Components/ResourceManager.go @@ -0,0 +1,36 @@ +package components + +import ( + "encoding/json" + "fmt" + + settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings" + rl "github.com/gen2brain/raylib-go/raylib" +) + +var Resources ResourceManager + +type ResourceManager struct { + LoadedPackages map[string]*settings.AppVersion + Textures TextrueManager + Worlds map[string]*World +} + +func InitManager() { + Resources = ResourceManager{ + LoadedPackages: make(map[string]*settings.AppVersion), + Worlds: make(map[string]*World), + Textures: TextrueManager{ + Textures: make([]*rl.Texture2D, 0), + NameToId: make(map[string]uint64), + }, + } +} + +func (base *ResourceManager) String() string { + var outp, jsonErr = json.Marshal(base) + if jsonErr != nil { + return fmt.Sprintf("Failed to parse settings: %s", jsonErr.Error()) + } + return string(outp) +} diff --git a/engine/Components/TextureManager.go b/engine/Components/TextureManager.go new file mode 100644 index 0000000..27449b1 --- /dev/null +++ b/engine/Components/TextureManager.go @@ -0,0 +1,54 @@ +package components + +import ( + "encoding/json" + "fmt" + + rl "github.com/gen2brain/raylib-go/raylib" +) + + +type TextrueManager struct { + Textures []*rl.Texture2D + NameToId map[string]uint64 +} + +// Loads the texture in the VRAM +func (base *TextrueManager) LoadTexture(path string, displayName string) { + var image = rl.LoadImage(path) + var texture = rl.LoadTextureFromImage(image) + var id = len(base.Textures) + base.Textures = append(base.Textures, &texture) + base.NameToId[displayName] = uint64(id) + rl.UnloadImage(image) +} + +// Unloads all the textures from the VRAM +func (base *TextrueManager) UnloadAll() { + for _, v := range base.Textures { + rl.UnloadTexture(*v) + } +} + +func (base *TextrueManager) GetTexture(Id uint64) (*rl.Texture2D, error) { + if Id >= uint64(len(base.Textures)) { + return nil, fmt.Errorf("No texture loaded with that ID") + } + return base.Textures[Id], nil +} + +func (base *TextrueManager) GetTextureByName(textureName string) (*rl.Texture2D, error) { + var id, exists = base.NameToId[textureName] + if !exists { + return nil, fmt.Errorf("No such texture in the system") + } + return base.GetTexture(id) +} + +func (base *TextrueManager) String() string { + var outp, jsonErr = json.Marshal(base) + if jsonErr != nil { + return fmt.Sprintf("Failed to parse settings: %s", jsonErr.Error()) + } + return string(outp) +} diff --git a/engine/Components/World.go b/engine/Components/World.go new file mode 100644 index 0000000..0605703 --- /dev/null +++ b/engine/Components/World.go @@ -0,0 +1,72 @@ +package components + +import ( + coreobjects "github.com/DegustatorPonos/RuinesOfRafdolon/CoreObjects" + rl "github.com/gen2brain/raylib-go/raylib" +) + +// The scene implimetation that represents one playable scene +type World struct { + Manager coreobjects.SceneManager + Name string + Floor []FloorTile + + Camera *rl.Camera2D +} + +func (base *World) Create(manager coreobjects.SceneManager) { + base.Manager = manager +} + +func (base *World) Destroy() { +} + +func (base *World) Update() { + base.handleFreecam() +} + +func (base *World) handleFreecam() { + var speed = 150 * rl.GetFrameTime() + var zoomSpeed = 0.2 * rl.GetFrameTime() + if rl.IsKeyDown(rl.KeyW) { + base.Camera.Target.Y -= speed + } + if rl.IsKeyDown(rl.KeyS) { + base.Camera.Target.Y += speed + } + if rl.IsKeyDown(rl.KeyA) { + base.Camera.Target.X -= speed + } + if rl.IsKeyDown(rl.KeyD) { + base.Camera.Target.X += speed + } + if rl.IsKeyDown(rl.KeyEqual) { + base.Camera.Zoom += zoomSpeed + } + if rl.IsKeyDown(rl.KeyMinus) { + base.Camera.Zoom -= zoomSpeed + } +} + +func (base *World) Draw() { + rl.BeginMode2D(*base.Camera) + defer rl.EndMode2D() + for _, v := range base.Floor { + v.Draw() + } +} + +// The single texture drawn at level 0 of the world +type FloorTile struct { + Position rl.Vector2 + Texture *rl.Texture2D +} + +func (base *FloorTile) Draw() { + rl.DrawTexture( + *base.Texture, + int32(base.Position.X), + int32(base.Position.Y), + rl.White, + ) +} diff --git a/engine/CoreObjects/ResourceManager.go b/engine/CoreObjects/ResourceManager.go deleted file mode 100644 index d493bc2..0000000 --- a/engine/CoreObjects/ResourceManager.go +++ /dev/null @@ -1,11 +0,0 @@ -package coreobjects - -import rl "github.com/gen2brain/raylib-go/raylib" - -type ResourceManager struct { - Textures TextrueManager -} - -type TextrueManager struct { - Textures map[uint64]rl.Texture2D -} diff --git a/engine/Dynamic/Common.go b/engine/Dynamic/Common.go index 99cfdc2..4cd440b 100644 --- a/engine/Dynamic/Common.go +++ b/engine/Dynamic/Common.go @@ -1,23 +1 @@ package dynamic - -import ( - "encoding/json" - "fmt" - "os" -) - -func ReadJSONfromFile(fileLocation string, v any) error { - var file, openErr = os.ReadFile(fileLocation) - if openErr != nil { - return openErr - } - var jsonErr = json.Unmarshal(file, v) - if jsonErr != nil { - return jsonErr - } - return nil -} - -func ConcantinateFileLocation(baseDirLocation string, appendix string) string { - return fmt.Sprintf("%v/%v", baseDirLocation, appendix) -} diff --git a/engine/Dynamic/Descriptors/Textures.go b/engine/Dynamic/Descriptors/Textures.go index 9d480ee..f436575 100644 --- a/engine/Dynamic/Descriptors/Textures.go +++ b/engine/Dynamic/Descriptors/Textures.go @@ -1,5 +1,9 @@ package descriptors +import ( + utils "github.com/DegustatorPonos/RuinesOfRafdolon/Utils" +) + const TexturesDescriptorDirectoryName string = "Textures" const TexturesDescriptorFileName string = "Meta.json" @@ -7,6 +11,14 @@ type TexturesDescriptor struct { Avaliable []string } +func (base *TexturesDescriptor) GetTexturePath(packageLocation string, textureName string) string { + return utils.JoinFileLocations([]string { + packageLocation, + TexturesDescriptorDirectoryName, + textureName, + }) +} + func IsValid() error { return nil } diff --git a/engine/Dynamic/Descriptors/World.go b/engine/Dynamic/Descriptors/World.go index 5116a0d..25e52ef 100644 --- a/engine/Dynamic/Descriptors/World.go +++ b/engine/Dynamic/Descriptors/World.go @@ -1,6 +1,9 @@ package descriptors -import rl "github.com/gen2brain/raylib-go/raylib" +import ( + components "github.com/DegustatorPonos/RuinesOfRafdolon/Components" + rl "github.com/gen2brain/raylib-go/raylib" +) type WorldDescriptor struct { Name string @@ -26,3 +29,30 @@ type FloorPiece struct { Position rl.Vector2 Texture string } + +// Transforms the world descriptor into the game world +func (base WorldDescriptor) Parse() components.World { + var outp = components.World { + Name: base.Name, + Floor: make([]components.FloorTile, 0, len(base.FloorMap)), + + Camera: &rl.Camera2D{ + Offset: rl.Vector2 {X: 0, Y: 0}, + Target: rl.Vector2 {X: 0, Y: 0}, + Rotation: 0, + Zoom: 1, + }, + } + for _, v := range base.FloorMap { + var texture, textureErr = components.Resources.Textures.GetTextureByName(v.Texture) + if textureErr != nil { + continue + } + var new = components.FloorTile { + Position: v.Position, + Texture: texture, + } + outp.Floor = append(outp.Floor, new) + } + return outp +} diff --git a/engine/Dynamic/Manager.go b/engine/Dynamic/Manager.go index 7a6e341..7b7d6b4 100644 --- a/engine/Dynamic/Manager.go +++ b/engine/Dynamic/Manager.go @@ -5,6 +5,7 @@ import ( "os" settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings" + utils "github.com/DegustatorPonos/RuinesOfRafdolon/Utils" rl "github.com/gen2brain/raylib-go/raylib" ) @@ -24,7 +25,7 @@ func loadPackages() (*PackageManager, error) { AvaliablePackages: make(map[string]Package), } for _, v := range dir { - var packagePath = ConcantinateFileLocation(settings.Current.PackagesLocation, v.Name()) + var packagePath = utils.JoinFileLocation(settings.Current.PackagesLocation, v.Name()) var newPackage, packageErr = ReadPackage(v) if packageErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load the module %v: %s", packagePath, packageErr.Error()) @@ -32,9 +33,8 @@ func loadPackages() (*PackageManager, error) { } newPackage.location = packagePath - // newPackage.LoadTiles() - newPackage.LoadTextures() - newPackage.LoadWorlds() + newPackage.ReadTextures() + newPackage.ReadWorlds() outp.AvaliablePackages[newPackage.Description.Name] = *newPackage rl.TraceLog(rl.LogInfo, "Loaded the module %s", newPackage.Description.Name) @@ -50,3 +50,9 @@ func Init() { } Manager = manager } + +func (base *PackageManager) GetPackage(packageName string) (*Package, error) { + var pack, exists = base.AvaliablePackages[packageName] + if !exists { return nil, fmt.Errorf("Failed to load package: no such package") } + return &pack, nil +} diff --git a/engine/Dynamic/Package.go b/engine/Dynamic/Package.go index 2108d7b..2d8cc72 100644 --- a/engine/Dynamic/Package.go +++ b/engine/Dynamic/Package.go @@ -5,8 +5,10 @@ import ( "fmt" "os" + components "github.com/DegustatorPonos/RuinesOfRafdolon/Components" descriptors "github.com/DegustatorPonos/RuinesOfRafdolon/Dynamic/Descriptors" settings "github.com/DegustatorPonos/RuinesOfRafdolon/Settings" + utils "github.com/DegustatorPonos/RuinesOfRafdolon/Utils" rl "github.com/gen2brain/raylib-go/raylib" ) @@ -54,9 +56,9 @@ func (base *Package) String() string { } func ReadPackage(dir os.DirEntry) (*Package, error) { - var dirPath = ConcantinateFileLocation(settings.Current.PackagesLocation, dir.Name()) + var dirPath = utils.JoinFileLocation(settings.Current.PackagesLocation, dir.Name()) var desc = PackageDescription{} - if descErr := ReadValidJSONfromFile(ConcantinateFileLocation(dirPath, "Description.json"), &desc); descErr != nil { + if descErr := ReadValidJSONfromFile(utils.JoinFileLocation(dirPath, "Description.json"), &desc); descErr != nil { return nil, descErr } return &Package{ @@ -72,7 +74,7 @@ func loadAssetsFromDir[T Validatable](dirLocation string, InitializeFunc func()T var outp = make([]T, 0) for _, v := range files { var new = InitializeFunc() - var loadErr = ReadValidJSONfromFile(ConcantinateFileLocation(dirLocation, v.Name()), new) + var loadErr = ReadValidJSONfromFile(utils.JoinFileLocation(dirLocation, v.Name()), new) if loadErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load the asset %s: %s", v.Name(), loadErr) continue @@ -82,11 +84,31 @@ func loadAssetsFromDir[T Validatable](dirLocation string, InitializeFunc func()T return outp, nil } -func (base *Package) LoadWorlds() { +func (base *Package) ReadTextures() { + var textures = &descriptors.TexturesDescriptor{} + var texturesLocation = utils.JoinFileLocation(base.location, descriptors.TexturesDescriptorDirectoryName) + var loadErr = utils.ReadJSONfromFile(utils.JoinFileLocation(texturesLocation, descriptors.TexturesDescriptorFileName), textures) + if loadErr != nil { + rl.TraceLog(rl.LogWarning, "Failed to load texture description from the module %s: %s", base.location, loadErr) + } else { + base.Textures = textures + } +} + +// Loads textures in the resource manager +func (base *Package) LoadTextures() { + for _, v := range base.Textures.Avaliable { + var location = base.Textures.GetTexturePath(base.location, v) + var displayName = fmt.Sprintf("%v/%v", base.Description.Name, v) + components.Resources.Textures.LoadTexture(location, displayName) + } +} + +func (base *Package) ReadWorlds() { if base.Description.Type != "story" { return } - var worlds, loadErr = loadWorldsFromDir(ConcantinateFileLocation(base.location, "Worlds")) + var worlds, loadErr = loadWorldsFromDir(utils.JoinFileLocation(base.location, "Worlds")) if loadErr != nil { rl.TraceLog(rl.LogWarning, "Failed to load world from the module %s: %s", base.location, loadErr) } else { @@ -94,14 +116,13 @@ func (base *Package) LoadWorlds() { } } -func (base *Package) LoadTextures() { - var textures = &descriptors.TexturesDescriptor{} - var texturesLocation = ConcantinateFileLocation(base.location, descriptors.TexturesDescriptorDirectoryName) - var loadErr = ReadJSONfromFile(ConcantinateFileLocation(texturesLocation, descriptors.TexturesDescriptorFileName), textures) - if loadErr != nil { - rl.TraceLog(rl.LogWarning, "Failed to load texture description from the module %s: %s", base.location, loadErr) - } else { - base.Textures = textures +func (base *Package) LoadWorlds() { + if base.Description.Type != "story" { + return + } + for _, v := range base.Worlds { + var parsed = v.Parse() + components.Resources.Worlds[v.Name] = &parsed } } @@ -113,6 +134,7 @@ func loadWorldsFromDir(dirLocation string) (map[string]*descriptors.WorldDescrip return descriptors.MapWorldDescriptors(loaded), nil } +// Deprecated func loadTilesFromDir(dirLocation string) (map[uint64]*descriptors.TileDescriptor, error) { var loaded, err = loadAssetsFromDir(dirLocation, func() *descriptors.TileDescriptor{ return &descriptors.TileDescriptor{} }) if err != nil { diff --git a/engine/Dynamic/Validation.go b/engine/Dynamic/Validation.go index dfe1d5c..a7d24d5 100644 --- a/engine/Dynamic/Validation.go +++ b/engine/Dynamic/Validation.go @@ -1,5 +1,7 @@ package dynamic +import utils "github.com/DegustatorPonos/RuinesOfRafdolon/Utils" + type Validatable interface { // If the object is returned invalid this function should return the reason IsValid() error @@ -7,7 +9,7 @@ type Validatable interface { // Reads object fron the file and validates it func ReadValidJSONfromFile(fileLocation string, v Validatable) error { - var err = ReadJSONfromFile(fileLocation, v) + var err = utils.ReadJSONfromFile(fileLocation, v) if err != nil { return err } diff --git a/engine/Packages/TestPackage/Textures/Meta.json b/engine/Packages/TestPackage/Textures/Meta.json index f5eff7f..8a5a57b 100644 --- a/engine/Packages/TestPackage/Textures/Meta.json +++ b/engine/Packages/TestPackage/Textures/Meta.json @@ -1,5 +1,6 @@ { "Avaliable": [ - "common.png" + "common.png", + "water.png" ] } diff --git a/engine/Packages/TestPackage/Worlds/Main.json b/engine/Packages/TestPackage/Worlds/Main.json index aff684a..dc1637a 100644 --- a/engine/Packages/TestPackage/Worlds/Main.json +++ b/engine/Packages/TestPackage/Worlds/Main.json @@ -3,7 +3,7 @@ "FloorMap": [ { "Position": { "X": 1, "Y": 0 }, - "Texture": "testPackage/common" + "Texture": "testPackage/water.png" } ] } diff --git a/engine/Render/initWindow.go b/engine/Render/initWindow.go index 436beb6..37728db 100644 --- a/engine/Render/initWindow.go +++ b/engine/Render/initWindow.go @@ -5,12 +5,13 @@ import ( rl "github.com/gen2brain/raylib-go/raylib" ) -func InitWindow(manager coreobjects.SceneManager, startScene coreobjects.Scene) { +func InitWindow() { rl.SetConfigFlags(rl.FlagWindowResizable) rl.InitWindow(800, 450, "xdx") - defer rl.CloseWindow() +} +func StartLoop(manager coreobjects.SceneManager, startScene coreobjects.Scene) { manager.ChangeScene(startScene) for !rl.WindowShouldClose() { @@ -21,3 +22,7 @@ func InitWindow(manager coreobjects.SceneManager, startScene coreobjects.Scene) rl.EndDrawing() } } + +func DeinitWindow() { + rl.CloseWindow() +} diff --git a/engine/Utils/Files.go b/engine/Utils/Files.go new file mode 100644 index 0000000..fbdf1b7 --- /dev/null +++ b/engine/Utils/Files.go @@ -0,0 +1,34 @@ +package utils + +import ( + "encoding/json" + "fmt" + "os" +) + +func ReadJSONfromFile(fileLocation string, v any) error { + var file, openErr = os.ReadFile(fileLocation) + if openErr != nil { + return openErr + } + var jsonErr = json.Unmarshal(file, v) + if jsonErr != nil { + return jsonErr + } + return nil +} + +func JoinFileLocation(baseDirLocation string, appendix string) string { + return fmt.Sprintf("%v/%v", baseDirLocation, appendix) +} + +func JoinFileLocations(path []string) string { + if len(path) == 0 { + return "" + } + var outp = path[0] + for _, v := range path[1:] { + outp = JoinFileLocation(outp, v) + } + return outp +} diff --git a/engine/main.go b/engine/main.go index 5468217..96c4fa8 100644 --- a/engine/main.go +++ b/engine/main.go @@ -3,6 +3,7 @@ package main import ( "log" + components "github.com/DegustatorPonos/RuinesOfRafdolon/Components" coreobjects "github.com/DegustatorPonos/RuinesOfRafdolon/CoreObjects" dynamic "github.com/DegustatorPonos/RuinesOfRafdolon/Dynamic" render "github.com/DegustatorPonos/RuinesOfRafdolon/Render" @@ -11,17 +12,21 @@ import ( func main() { settings.ReadSettings() + components.InitManager() dynamic.Init() + render.InitWindow() + defer render.DeinitWindow() // TEMPORARY SECTION for k, v := range dynamic.Manager.AvaliablePackages { log.Printf("%s: %s", k, &v) + v.LoadTextures() + v.LoadWorlds() } - - return + log.Printf("Resource manager: %s", &components.Resources) // var field = descriptor.GenerateMap() var manager = coreobjects.InitSceneManager() - render.InitWindow(manager, nil) + render.StartLoop(manager, components.Resources.Worlds["MainWorld"]) } -- cgit v1.3