diff --git a/TODO.md b/TODO.md index 88df884..ac98297 100644 --- a/TODO.md +++ b/TODO.md @@ -22,13 +22,7 @@ slog.Debug("get observer", "minmoves", observer.LevelScore, "file", source.File, "line", source.Line) -- LDTK: - - to each level add these properties: - - level (num) - - name - - description - - background (image name w/o .png) - - min-moves (num, moves required to win) +- BUG: last level, when dying, you get a congrats message ## Collider Rework [abandoned: see branch collider-system, fails] diff --git a/assets/levels/openquell.ldtk b/assets/levels/openquell.ldtk index 0bfa9a4..0e8bbfe 100644 --- a/assets/levels/openquell.ldtk +++ b/assets/levels/openquell.ldtk @@ -11,7 +11,7 @@ "iid": "267e9380-d7b0-11ee-a97e-35bec9c19d52", "jsonVersion": "1.5.3", "appBuildId": 473703, - "nextUid": 11, + "nextUid": 15, "identifierStyle": "Capitalize", "toc": [], "worldLayout": "Free", @@ -113,7 +113,7 @@ } ], "entities": [ { - "identifier": "Player_Primary", + "identifier": "PlayerPrimary", "uid": 3, "tags": [], "exportToToc": false, @@ -183,7 +183,7 @@ "fieldDefs": [] }, { - "identifier": "Obstacle_West", + "identifier": "ObstacleWest", "uid": 7, "tags": [], "exportToToc": false, @@ -218,7 +218,7 @@ "fieldDefs": [] }, { - "identifier": "Obstacle_East", + "identifier": "ObstacleEast", "uid": 8, "tags": [], "exportToToc": false, @@ -253,7 +253,7 @@ "fieldDefs": [] }, { - "identifier": "Obstacle_North", + "identifier": "ObstacleNorth", "uid": 9, "tags": [], "exportToToc": false, @@ -288,7 +288,7 @@ "fieldDefs": [] }, { - "identifier": "Obstacle_South", + "identifier": "ObstacleSouth", "uid": 10, "tags": [], "exportToToc": false, @@ -342,10 +342,165 @@ "savedSelections": [], "cachedPixelData": { "opaqueTiles": "110000000000000", "averageColors": "f777f766f766f9533c965c355c355c354b355c35987d687d1b4700000000" } } - ], "enums": [], "externalEnums": [], "levelFields": [] }, + ], "enums": [], "externalEnums": [], "levelFields": [ + { + "identifier": "level", + "doc": null, + "__type": "Int", + "uid": 11, + "type": "F_Int", + "isArray": false, + "canBeNull": false, + "arrayMinLength": null, + "arrayMaxLength": null, + "editorDisplayMode": "Hidden", + "editorDisplayScale": 1, + "editorDisplayPos": "Above", + "editorLinkStyle": "StraightArrow", + "editorDisplayColor": null, + "editorAlwaysShow": false, + "editorShowInWorld": true, + "editorCutLongValues": true, + "editorTextSuffix": null, + "editorTextPrefix": null, + "useForSmartColor": false, + "exportToToc": false, + "searchable": false, + "min": null, + "max": null, + "regex": null, + "acceptFileTypes": null, + "defaultOverride": { "id": "V_Int", "params": [1] }, + "textLanguageMode": null, + "symmetricalRef": false, + "autoChainRef": true, + "allowOutOfLevelRef": true, + "allowedRefs": "OnlySame", + "allowedRefsEntityUid": null, + "allowedRefTags": [], + "tilesetUid": null + }, + { + "identifier": "description", + "doc": null, + "__type": "String", + "uid": 12, + "type": "F_String", + "isArray": false, + "canBeNull": true, + "arrayMinLength": null, + "arrayMaxLength": null, + "editorDisplayMode": "Hidden", + "editorDisplayScale": 1, + "editorDisplayPos": "Above", + "editorLinkStyle": "StraightArrow", + "editorDisplayColor": null, + "editorAlwaysShow": false, + "editorShowInWorld": true, + "editorCutLongValues": true, + "editorTextSuffix": null, + "editorTextPrefix": null, + "useForSmartColor": false, + "exportToToc": false, + "searchable": false, + "min": null, + "max": null, + "regex": null, + "acceptFileTypes": null, + "defaultOverride": { + "id": "V_String", + "params": ["Collect the golden spheres by moving the blue one"] + }, + "textLanguageMode": null, + "symmetricalRef": false, + "autoChainRef": true, + "allowOutOfLevelRef": true, + "allowedRefs": "OnlySame", + "allowedRefsEntityUid": null, + "allowedRefTags": [], + "tilesetUid": null + }, + { + "identifier": "background", + "doc": null, + "__type": "String", + "uid": 13, + "type": "F_String", + "isArray": false, + "canBeNull": true, + "arrayMinLength": null, + "arrayMaxLength": null, + "editorDisplayMode": "Hidden", + "editorDisplayScale": 1, + "editorDisplayPos": "Above", + "editorLinkStyle": "StraightArrow", + "editorDisplayColor": null, + "editorAlwaysShow": false, + "editorShowInWorld": true, + "editorCutLongValues": true, + "editorTextSuffix": null, + "editorTextPrefix": null, + "useForSmartColor": false, + "exportToToc": false, + "searchable": false, + "min": null, + "max": null, + "regex": null, + "acceptFileTypes": null, + "defaultOverride": { + "id": "V_String", + "params": ["background-lila"] + }, + "textLanguageMode": null, + "symmetricalRef": false, + "autoChainRef": true, + "allowOutOfLevelRef": true, + "allowedRefs": "OnlySame", + "allowedRefsEntityUid": null, + "allowedRefTags": [], + "tilesetUid": null + }, + { + "identifier": "minmoves", + "doc": null, + "__type": "Int", + "uid": 14, + "type": "F_Int", + "isArray": false, + "canBeNull": false, + "arrayMinLength": null, + "arrayMaxLength": null, + "editorDisplayMode": "Hidden", + "editorDisplayScale": 1, + "editorDisplayPos": "Above", + "editorLinkStyle": "StraightArrow", + "editorDisplayColor": null, + "editorAlwaysShow": false, + "editorShowInWorld": true, + "editorCutLongValues": true, + "editorTextSuffix": null, + "editorTextPrefix": null, + "useForSmartColor": false, + "exportToToc": false, + "searchable": false, + "min": null, + "max": null, + "regex": null, + "acceptFileTypes": null, + "defaultOverride": { "id": "V_Int", "params": [6] }, + "textLanguageMode": null, + "symmetricalRef": false, + "autoChainRef": true, + "allowOutOfLevelRef": true, + "allowedRefs": "OnlySame", + "allowedRefsEntityUid": null, + "allowedRefTags": [], + "tilesetUid": null + } + ] }, "levels": [ { - "identifier": "Level_0", + "identifier": "Start", "iid": "267fa4f0-d7b0-11ee-a97e-d90512e08363", "uid": 0, "worldX": -224, @@ -355,7 +510,7 @@ "pxHei": 480, "__bgColor": "#696A79", "bgColor": null, - "useAutoIdentifier": true, + "useAutoIdentifier": false, "bgRelPath": null, "bgPos": null, "bgPivotX": 0.5, @@ -363,7 +518,12 @@ "__smartColor": "#ADADB5", "__bgPos": null, "externalRelPath": null, - "fieldInstances": [], + "fieldInstances": [ + { "__identifier": "level", "__type": "Int", "__value": 1, "__tile": null, "defUid": 11, "realEditorValues": [] }, + { "__identifier": "description", "__type": "String", "__value": "Collect the golden spheres by moving the blue one", "__tile": null, "defUid": 12, "realEditorValues": [] }, + { "__identifier": "background", "__type": "String", "__value": "background-lila", "__tile": null, "defUid": 13, "realEditorValues": [] }, + { "__identifier": "minmoves", "__type": "Int", "__value": 6, "__tile": null, "defUid": 14, "realEditorValues": [] } + ], "layerInstances": [ { "__identifier": "Entities", @@ -390,7 +550,7 @@ "gridTiles": [], "entityInstances": [ { - "__identifier": "Player_Primary", + "__identifier": "PlayerPrimary", "__grid": [7,5], "__pivot": [0,0], "__tags": [], @@ -420,6 +580,38 @@ "fieldInstances": [], "__worldX": 128, "__worldY": 224 + }, + { + "__identifier": "Collectible", + "__grid": [9,5], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 }, + "__smartColor": "#FEAE34", + "iid": "5dbb7c20-d7b0-11ee-84a6-d1c69ca7fab5", + "width": 32, + "height": 32, + "defUid": 4, + "px": [288,160], + "fieldInstances": [], + "__worldX": 64, + "__worldY": 160 + }, + { + "__identifier": "Collectible", + "__grid": [12,5], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 }, + "__smartColor": "#FEAE34", + "iid": "b3028a20-d7b0-11ee-84a6-e73fb360996b", + "width": 32, + "height": 32, + "defUid": 4, + "px": [384,160], + "fieldInstances": [], + "__worldX": 160, + "__worldY": 160 } ] }, @@ -489,7 +681,7 @@ "__neighbours": [] }, { - "identifier": "_First_Try", + "identifier": "Jump", "iid": "024390f0-d7b0-11ee-98fb-1bc6ad7e4172", "uid": 6, "worldX": 480, @@ -507,7 +699,15 @@ "__smartColor": "#ADADB5", "__bgPos": { "topLeftPx": [0,0], "scale": [1,1], "cropRect": [0,0,640,480] }, "externalRelPath": null, - "fieldInstances": [], + "fieldInstances": [ + { "__identifier": "level", "__type": "Int", "__value": 2, "__tile": null, "defUid": 11, "realEditorValues": [{ "id": "V_Int", "params": [2] }] }, + { "__identifier": "description", "__type": "String", "__value": "you can jump", "__tile": null, "defUid": 12, "realEditorValues": [{ + "id": "V_String", + "params": ["you can jump"] + }] }, + { "__identifier": "background", "__type": "String", "__value": "background-lila", "__tile": null, "defUid": 13, "realEditorValues": [] }, + { "__identifier": "minmoves", "__type": "Int", "__value": 4, "__tile": null, "defUid": 14, "realEditorValues": [{ "id": "V_Int", "params": [4] }] } + ], "layerInstances": [ { "__identifier": "Entities", @@ -534,7 +734,7 @@ "gridTiles": [], "entityInstances": [ { - "__identifier": "Obstacle_West", + "__identifier": "ObstacleWest", "__grid": [6,8], "__pivot": [0,0], "__tags": [], @@ -550,7 +750,7 @@ "__worldY": 256 }, { - "__identifier": "Player_Primary", + "__identifier": "PlayerPrimary", "__grid": [4,5], "__pivot": [0,0], "__tags": [], @@ -598,7 +798,7 @@ "__worldY": 192 }, { - "__identifier": "Obstacle_South", + "__identifier": "ObstacleSouth", "__grid": [15,6], "__pivot": [0,0], "__tags": [], diff --git a/assets/loader-levels.go b/assets/loader-levels.go index 3478994..ed8909b 100644 --- a/assets/loader-levels.go +++ b/assets/loader-levels.go @@ -184,18 +184,18 @@ type TileRegistry map[string]*Tile func InitTiles() TileRegistry { return TileRegistry{ - "floor": {Id: ' ', Class: "floor", Renderable: false}, - "default": NewTileBlock("block-greycolored"), - "solidorange": NewTileBlock("block-orange-32"), - "player-primary": NewTilePlayer(Primary), - "player-secondary": NewTilePlayer(Secondary), - "collectible": NewTileCollectible("collectible-orange"), - "obstacle-star": NewTileObstacle("obstacle-star", config.All), - "obstacle-north": NewTileObstacle("obstacle-north", config.North), - "obstacle-south": NewTileObstacle("obstacle-south", config.South), - "obstacle-west": NewTileObstacle("obstacle-west", config.West), - "obstacle-east": NewTileObstacle("obstacle-east", config.East), - "particle": NewTileParticle([]string{ + "floor": {Id: ' ', Class: "floor", Renderable: false}, + "default": NewTileBlock("block-greycolored"), + "solidorange": NewTileBlock("block-orange-32"), + "PlayerPrimary": NewTilePlayer(Primary), + "PlayerSecondary": NewTilePlayer(Secondary), + "Collectible": NewTileCollectible("collectible-orange"), + "ObstacleStar": NewTileObstacle("obstacle-star", config.All), + "ObstacleNorth": NewTileObstacle("obstacle-north", config.North), + "ObstacleSouth": NewTileObstacle("obstacle-south", config.South), + "ObstacleWest": NewTileObstacle("obstacle-west", config.West), + "ObstacleEast": NewTileObstacle("obstacle-east", config.East), + "Particle": NewTileParticle([]string{ //"particle-ring-1", "particle-ring-2", "particle-ring-3", @@ -235,7 +235,7 @@ func LoadLDTK(dir string) *ldtkgo.Project { } // do some sanity checks - properties := []string{"min-moves", "background", "level", "name", "descrption"} + properties := []string{"minmoves", "background", "level", "description"} need := len(properties) for idx, level := range project.Levels { diff --git a/game/level_scene.go b/game/level_scene.go index dc5a52e..33b8645 100644 --- a/game/level_scene.go +++ b/game/level_scene.go @@ -31,8 +31,7 @@ func (scene *LevelScene) GenerateLevels(game *Game) { for _, level := range assets.Project.Levels { level := level scene.Levels = append(scene.Levels, NewLevel(game, 32, level)) - level.PropertyByIdentifier("min-moves") - min = append(min, level.PropertyByIdentifier("min-moves").AsInt()) + min = append(min, level.PropertyByIdentifier("minmoves").AsInt()) } scene.Game.Observer.SetupLevelScore(min) diff --git a/game/levels.go b/game/levels.go index eb2bf62..e87f7d4 100644 --- a/game/levels.go +++ b/game/levels.go @@ -8,7 +8,6 @@ import ( "openquell/grid" "openquell/observers" "openquell/systems" - "strings" "github.com/hajimehoshi/ebiten/v2" "github.com/mlange-42/arche/ecs" @@ -35,6 +34,7 @@ func NewLevel(game *Game, cellsize int, plan *ldtkgo.Level) *Level { gridcontainer := &grid.GridContainer{} + // FIXME: use plan.BGImage.Path here? systemlist = append(systemlist, systems.NewGridSystem(game.World, game.ScreenWidth, game.ScreenHeight, cellsize, assets.Assets[plan.PropertyByIdentifier("background").AsString()])) @@ -112,11 +112,23 @@ func (level *Level) SetupGrid(game *Game) { grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice)) } -// parses a RawLevel and generates a mapslice from it, which is being used as grid -func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) { +func NewMapSlice(game *Game, tilesize int) Map { size := game.ScreenWidth * game.ScreenHeight mapslice := make(Map, size) - backupmap := make(Map, size) + + for y := 0; y < game.ScreenHeight; y += 32 { + for x := 0; x < game.ScreenWidth; x += 32 { + mapslice[image.Point{x / tilesize, y / tilesize}] = assets.Tiles["floor"] + } + } + + return mapslice +} + +// parses a RawLevel and generates a mapslice from it, which is being used as grid +func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) { + mapslice := NewMapSlice(game, tilesize) + backupmap := NewMapSlice(game, tilesize) for _, layer := range level.Layers { switch layer.Type { @@ -129,14 +141,19 @@ func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) { // but referenced from LDTK file, that way we // could use multiple tileset images tile := assets.Tiles["default"] - tile.Sprite = assets.Assets[strings.TrimSuffix(layer.Tileset.Path, ".png")].SubImage( + + tile.Sprite = assets.Assets["map"].SubImage( image.Rect(tileData.Src[0], tileData.Src[1], tileData.Src[0]+layer.GridSize, tileData.Src[1]+layer.GridSize)).(*ebiten.Image) - mapslice[image.Point{tileData.Position[0], tileData.Position[1]}] = tile - backupmap[image.Point{tileData.Position[0], tileData.Position[1]}] = tile.Clone() + point := image.Point{ + tileData.Position[0] / tilesize, + tileData.Position[1] / tilesize} + + mapslice[point] = tile + backupmap[point] = tile.Clone() } } @@ -149,13 +166,19 @@ func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) { tile := assets.Tiles[entity.Identifier] tileRect := entity.TileRect + //slog.Debug("tilerect", "x", tileRect.X, "y", tileRect.Y, "which", entity.Identifier) + tile.Sprite = tileset.SubImage( image.Rect(tileRect.X, tileRect.Y, tileRect.X+tileRect.W, tileRect.Y+tileRect.H)).(*ebiten.Image) - mapslice[image.Point{entity.Position[0], entity.Position[1]}] = tile - backupmap[image.Point{entity.Position[0], entity.Position[1]}] = tile.Clone() + point := image.Point{ + entity.Position[0] / tilesize, + entity.Position[1] / tilesize} + + mapslice[point] = tile + backupmap[point] = tile.Clone() } } } diff --git a/systems/collectible_system.go b/systems/collectible_system.go index 370a133..8699d34 100644 --- a/systems/collectible_system.go +++ b/systems/collectible_system.go @@ -114,8 +114,8 @@ func (system *CollectibleSystem) AddParticle(position *components.Position) { pos, particle, timer := ptmapper.Get(entity) observer.AddEntity(entity, particleID) - particle.Index = assets.Tiles["particle"].Particle - particle.Tiles = assets.Tiles["particle"].Tiles + particle.Index = assets.Tiles["Particle"].Particle + particle.Tiles = assets.Tiles["Particle"].Tiles pos.Update( position.X-(16), // FIXME: use global tilesize! diff --git a/systems/hud_system.go b/systems/hud_system.go index 698af9d..13c258b 100644 --- a/systems/hud_system.go +++ b/systems/hud_system.go @@ -47,7 +47,7 @@ func (system *HudSystem) Draw(screen *ebiten.Image) { score := fmt.Sprintf("Score: %d", system.Observer.GetScore()) level := fmt.Sprintf("Level %d %s", system.Plan.PropertyByIdentifier("level").AsInt(), - system.Plan.PropertyByIdentifier("name").AsString()) + system.Plan.Identifier) assets.FontRenderer.Renderer.SetSizePx(20) assets.FontRenderer.Renderer.SetTarget(screen)