diff --git a/assets/atlas/SunnyLand-player.png b/assets/atlas/SunnyLand-player.png new file mode 100644 index 00000000..7fbbe07d Binary files /dev/null and b/assets/atlas/SunnyLand-player.png differ diff --git a/assets/tile-based-game.ldtk b/assets/tile-based-game.ldtk new file mode 100644 index 00000000..b330e699 --- /dev/null +++ b/assets/tile-based-game.ldtk @@ -0,0 +1,1673 @@ +{ + "__header__": { + "fileType": "LDtk Project JSON", + "app": "LDtk", + "doc": "https://ldtk.io/json", + "schema": "https://ldtk.io/files/JSON_SCHEMA.json", + "appAuthor": "Sebastien 'deepnight' Benard", + "appVersion": "1.4.1", + "url": "https://ldtk.io" + }, + "iid": "96b74480-6280-11ee-9465-71258fcae37f", + "jsonVersion": "1.4.1", + "appBuildId": 471698, + "nextUid": 68, + "identifierStyle": "Capitalize", + "toc": [], + "worldLayout": "LinearHorizontal", + "worldGridWidth": 256, + "worldGridHeight": 256, + "defaultLevelWidth": 256, + "defaultLevelHeight": 256, + "defaultPivotX": 0, + "defaultPivotY": 0, + "defaultGridSize": 16, + "defaultEntityWidth": 16, + "defaultEntityHeight": 16, + "bgColor": "#40465B", + "defaultLevelBgColor": "#696A79", + "minifyJson": false, + "externalLevels": false, + "exportTiled": false, + "simplifiedExport": false, + "imageExportMode": "None", + "exportLevelBg": true, + "pngFilePattern": null, + "backupOnSave": false, + "backupLimit": 10, + "backupRelPath": null, + "levelNamePattern": "Level_%idx", + "tutorialDesc": null, + "customCommands": [], + "flags": [], + "defs": { "layers": [ + { + "__type": "Entities", + "identifier": "Entities", + "type": "Entities", + "uid": 60, + "doc": null, + "uiColor": null, + "gridSize": 16, + "guideGridWid": 0, + "guideGridHei": 0, + "displayOpacity": 1, + "inactiveOpacity": 0.6, + "hideInList": false, + "hideFieldsWhenInactive": true, + "canSelectWhenInactive": true, + "renderInWorldView": true, + "pxOffsetX": 0, + "pxOffsetY": 0, + "parallaxFactorX": 0, + "parallaxFactorY": 0, + "parallaxScaling": true, + "requiredTags": [], + "excludedTags": [], + "intGridValues": [], + "intGridValuesGroups": [], + "autoRuleGroups": [], + "autoSourceLayerDefUid": null, + "tilesetDefUid": null, + "tilePivotX": 0, + "tilePivotY": 0 + }, + { + "__type": "IntGrid", + "identifier": "Walls", + "type": "IntGrid", + "uid": 7, + "doc": null, + "uiColor": null, + "gridSize": 16, + "guideGridWid": 0, + "guideGridHei": 0, + "displayOpacity": 1, + "inactiveOpacity": 1, + "hideInList": false, + "hideFieldsWhenInactive": false, + "canSelectWhenInactive": true, + "renderInWorldView": true, + "pxOffsetX": 0, + "pxOffsetY": 0, + "parallaxFactorX": 0, + "parallaxFactorY": 0, + "parallaxScaling": true, + "requiredTags": [], + "excludedTags": [], + "intGridValues": [{ "value": 1, "identifier": "Wall", "color": "#000000", "tile": null, "groupUid": 0 }], + "intGridValuesGroups": [], + "autoRuleGroups": [ + { "uid": 53, "name": "Walls", "color": null, "icon": null, "active": true, "isOptional": false, "rules": [ + { + "uid": 59, + "active": true, + "size": 3, + "tileIds": [437], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [-1,1,0,1,1,0,0,0,0], + "flipX": true, + "flipY": true, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 6005184, + "perlinScale": 0.2, + "perlinOctaves": 2 + }, + { + "uid": 58, + "active": true, + "size": 3, + "tileIds": [152], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [0,-1,0,-1,1,0,0,0,0], + "flipX": true, + "flipY": true, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 937555, + "perlinScale": 0.2, + "perlinOctaves": 2 + }, + { + "uid": 57, + "active": true, + "size": 3, + "tileIds": [154], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [0,-1,0,0,1,0,0,0,0], + "flipX": false, + "flipY": true, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 1506794, + "perlinScale": 0.2, + "perlinOctaves": 2 + }, + { + "uid": 56, + "active": true, + "size": 3, + "tileIds": [198], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [0,0,0,-1,1,0,0,0,0], + "flipX": true, + "flipY": false, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 8366343, + "perlinScale": 0.2, + "perlinOctaves": 2 + }, + { + "uid": 54, + "active": true, + "size": 1, + "tileIds": [200], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [1], + "flipX": false, + "flipY": false, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 8230281, + "perlinScale": 0.2, + "perlinOctaves": 2 + } + ], "usesWizard": false }, + { "uid": 51, "name": "Background", "color": null, "icon": null, "active": true, "isOptional": false, "rules": [ + { + "uid": 52, + "active": true, + "size": 1, + "tileIds": [411], + "alpha": 1, + "chance": 1, + "breakOnMatch": true, + "pattern": [0], + "flipX": false, + "flipY": false, + "xModulo": 1, + "yModulo": 1, + "xOffset": 0, + "yOffset": 0, + "tileXOffset": 0, + "tileYOffset": 0, + "tileRandomXMin": 0, + "tileRandomXMax": 0, + "tileRandomYMin": 0, + "tileRandomYMax": 0, + "checker": "None", + "tileMode": "Single", + "pivotX": 0, + "pivotY": 0, + "outOfBoundsValue": null, + "perlinActive": false, + "perlinSeed": 6868818, + "perlinScale": 0.2, + "perlinOctaves": 2 + } + ], "usesWizard": false } + ], + "autoSourceLayerDefUid": null, + "tilesetDefUid": 4, + "tilePivotX": 0, + "tilePivotY": 0 + } + ], "entities": [ + { + "identifier": "Player", + "uid": 62, + "tags": [], + "exportToToc": false, + "doc": null, + "width": 16, + "height": 16, + "resizableX": false, + "resizableY": false, + "minWidth": null, + "maxWidth": null, + "minHeight": null, + "maxHeight": null, + "keepAspectRatio": false, + "tileOpacity": 1, + "fillOpacity": 0.08, + "lineOpacity": 0, + "hollow": false, + "color": "#BE4A2F", + "renderMode": "Tile", + "showName": true, + "tilesetId": 3, + "tileRenderMode": "FitInside", + "tileRect": { "tilesetUid": 3, "x": 0, "y": 0, "w": 32, "h": 32 }, + "uiTileRect": null, + "nineSliceBorders": [], + "maxCount": 0, + "limitScope": "PerLevel", + "limitBehavior": "MoveLastOne", + "pivotX": 0, + "pivotY": 0, + "fieldDefs": [] + }, + { + "identifier": "Goal", + "uid": 64, + "tags": [], + "exportToToc": false, + "doc": null, + "width": 16, + "height": 16, + "resizableX": false, + "resizableY": false, + "minWidth": null, + "maxWidth": null, + "minHeight": null, + "maxHeight": null, + "keepAspectRatio": false, + "tileOpacity": 1, + "fillOpacity": 0.08, + "lineOpacity": 0, + "hollow": false, + "color": "#D77643", + "renderMode": "Tile", + "showName": true, + "tilesetId": 4, + "tileRenderMode": "FitInside", + "tileRect": { "tilesetUid": 4, "x": 256, "y": 304, "w": 16, "h": 16 }, + "uiTileRect": null, + "nineSliceBorders": [], + "maxCount": 0, + "limitScope": "PerLevel", + "limitBehavior": "MoveLastOne", + "pivotX": 0, + "pivotY": 0, + "fieldDefs": [] + } + ], "tilesets": [ + { + "__cWid": 7, + "__cHei": 6, + "identifier": "Player", + "uid": 3, + "relPath": "atlas/SunnyLand-player.png", + "embedAtlas": null, + "pxWid": 198, + "pxHei": 192, + "tileGridSize": 32, + "spacing": 0, + "padding": 0, + "tags": [], + "tagsSourceEnumUid": null, + "enumTags": [], + "customData": [], + "savedSelections": [], + "cachedPixelData": { + "opaqueTiles": "000000100000010000001000000100000010000001", + "averageColors": "49654965496549650000000000004a65596549654955495449650000585459545854595400000000000049654965496500000000000000005a775a87000000000000000000004965596500000000000000000000" + } + }, + { + "__cWid": 23, + "__cHei": 21, + "identifier": "Environment", + "uid": 4, + "relPath": "atlas/SunnyLand_by_Ansimuz-extended.png", + "embedAtlas": null, + "pxWid": 368, + "pxHei": 336, + "tileGridSize": 16, + "spacing": 0, + "padding": 0, + "tags": [], + "tagsSourceEnumUid": null, + "enumTags": [], + "customData": [], + "savedSelections": [], + "cachedPixelData": { + "opaqueTiles": "101010100010110110000000000000000001101101101110101010001000000000000000000000000010100000001010101000000101000101000000000000000000000000000010100000001010100000000000000000000000000000000000000000101010000010100100000000000000000000000000000010101010000000000000000000000100000000101010100000000000000001010100000100000001010000100000000000000010100000010011011100000101000000100110000000011011000011101101010100000000000000000000000001011000011101110100000000110000111011100000000", + "averageColors": "f9850000f9850000f9850000fa65000069557a65f8450000f644f9650000f965f644000049b5c9950000c99549b5000000000000000000000000000000000000000000000000f955f7450000f745f9550000f865f7450000f745f865f9550000f6450000f9550000f845695500006955f8450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f8550000f85500000000000079a5000079a50000f9550000f8550000f9550000f8457a6569550000ab8500000000f8550000f855000000000000f7550000f75500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000077a5000078b50000f8450000f7450000947400009474000000000000fa650000f9550000fa6500002000000000000000459534953595000000000000000000000000000000000000000000000000000000000000000020006000000000000000000000000000000000000000000000000000000088550000f9550000f6450000f9550000900000000000a955f8450000f845a9550000f85500000000ca65b9650000000000000000000000000000000000000000000000000000a9550000a9550000000000000000000000000000000000000000fa650000f9550000fa650000f4880000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f47700000000000000000000000000000000f7450000f8550000f8550000f8550000000000000000000000000000000000000000000000000000000000000000f3440000f3450000f534000000000000e9950000f9950000e9950000000000000000b855f5340000f534b855000000000000f334000000000000000000000000000000000000000000000000000000000000f7440000f744000000000000000000000000f43500000000f435f4350000f334f436f3350000000000000000b955f5340000f534b95500000000000000000000f34500000000f335f33500000000000000000000000000000000f744f3340000f334f7440000000000000000f344f345f3440000f335f3350000f5340000f4350000f3340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fa650000f955f9550000000000000000f334f335f3450000f345f335f3340000f75500000000000000000000000000000000f955f9550000000000000000f335f344f3440000f344f344f33500000000000000000000000000000000" + } + } + ], "enums": [], "externalEnums": [], "levelFields": [] }, + "levels": [ + { + "identifier": "Level_0", + "iid": "96b7b9b0-6280-11ee-9465-8f86ab88cf6c", + "uid": 0, + "worldX": -1, + "worldY": -1, + "worldDepth": 0, + "pxWid": 272, + "pxHei": 176, + "__bgColor": "#696A79", + "bgColor": null, + "useAutoIdentifier": true, + "bgRelPath": null, + "bgPos": null, + "bgPivotX": 0.5, + "bgPivotY": 0.5, + "__smartColor": "#ADADB5", + "__bgPos": null, + "externalRelPath": null, + "fieldInstances": [], + "layerInstances": [ + { + "__identifier": "Entities", + "__type": "Entities", + "__cWid": 17, + "__cHei": 11, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": null, + "__tilesetRelPath": null, + "iid": "377fd470-6280-11ee-9d82-d17a3e9ca1d9", + "levelId": 0, + "layerDefUid": 60, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [], + "autoLayerTiles": [], + "seed": 151756, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [ + { + "__identifier": "Player", + "__grid": [5,5], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 3, "x": 0, "y": 0, "w": 32, "h": 32 }, + "__smartColor": "#BE4A2F", + "__worldX": 80, + "__worldY": 80, + "iid": "034c9520-6280-11ee-9d82-c3b80e0b470c", + "width": 16, + "height": 16, + "defUid": 62, + "px": [80,80], + "fieldInstances": [] + }, + { + "__identifier": "Goal", + "__grid": [11,5], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 4, "x": 256, "y": 304, "w": 16, "h": 16 }, + "__smartColor": "#D77643", + "__worldX": 176, + "__worldY": 80, + "iid": "041f7580-6280-11ee-9d82-4bf8c045fa4e", + "width": 16, + "height": 16, + "defUid": 64, + "px": [176,80], + "fieldInstances": [] + } + ] + }, + { + "__identifier": "Walls", + "__type": "IntGrid", + "__cWid": 17, + "__cHei": 11, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": 4, + "__tilesetRelPath": "atlas/SunnyLand_by_Ansimuz-extended.png", + "iid": "83fc8a20-6280-11ee-9465-6f4cc0b0fbf3", + "levelId": 0, + "layerDefUid": 7, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1, + 1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1 + ], + "autoLayerTiles": [ + { "px": [48,48], "src": [320,272], "f": 0, "t": 411, "d": [52,54], "a": 1 }, + { "px": [64,48], "src": [320,272], "f": 0, "t": 411, "d": [52,55], "a": 1 }, + { "px": [80,48], "src": [320,272], "f": 0, "t": 411, "d": [52,56], "a": 1 }, + { "px": [96,48], "src": [320,272], "f": 0, "t": 411, "d": [52,57], "a": 1 }, + { "px": [112,48], "src": [320,272], "f": 0, "t": 411, "d": [52,58], "a": 1 }, + { "px": [128,48], "src": [320,272], "f": 0, "t": 411, "d": [52,59], "a": 1 }, + { "px": [144,48], "src": [320,272], "f": 0, "t": 411, "d": [52,60], "a": 1 }, + { "px": [160,48], "src": [320,272], "f": 0, "t": 411, "d": [52,61], "a": 1 }, + { "px": [176,48], "src": [320,272], "f": 0, "t": 411, "d": [52,62], "a": 1 }, + { "px": [192,48], "src": [320,272], "f": 0, "t": 411, "d": [52,63], "a": 1 }, + { "px": [208,48], "src": [320,272], "f": 0, "t": 411, "d": [52,64], "a": 1 }, + { "px": [48,64], "src": [320,272], "f": 0, "t": 411, "d": [52,71], "a": 1 }, + { "px": [64,64], "src": [320,272], "f": 0, "t": 411, "d": [52,72], "a": 1 }, + { "px": [80,64], "src": [320,272], "f": 0, "t": 411, "d": [52,73], "a": 1 }, + { "px": [96,64], "src": [320,272], "f": 0, "t": 411, "d": [52,74], "a": 1 }, + { "px": [112,64], "src": [320,272], "f": 0, "t": 411, "d": [52,75], "a": 1 }, + { "px": [128,64], "src": [320,272], "f": 0, "t": 411, "d": [52,76], "a": 1 }, + { "px": [144,64], "src": [320,272], "f": 0, "t": 411, "d": [52,77], "a": 1 }, + { "px": [160,64], "src": [320,272], "f": 0, "t": 411, "d": [52,78], "a": 1 }, + { "px": [176,64], "src": [320,272], "f": 0, "t": 411, "d": [52,79], "a": 1 }, + { "px": [192,64], "src": [320,272], "f": 0, "t": 411, "d": [52,80], "a": 1 }, + { "px": [208,64], "src": [320,272], "f": 0, "t": 411, "d": [52,81], "a": 1 }, + { "px": [48,80], "src": [320,272], "f": 0, "t": 411, "d": [52,88], "a": 1 }, + { "px": [64,80], "src": [320,272], "f": 0, "t": 411, "d": [52,89], "a": 1 }, + { "px": [80,80], "src": [320,272], "f": 0, "t": 411, "d": [52,90], "a": 1 }, + { "px": [96,80], "src": [320,272], "f": 0, "t": 411, "d": [52,91], "a": 1 }, + { "px": [112,80], "src": [320,272], "f": 0, "t": 411, "d": [52,92], "a": 1 }, + { "px": [128,80], "src": [320,272], "f": 0, "t": 411, "d": [52,93], "a": 1 }, + { "px": [144,80], "src": [320,272], "f": 0, "t": 411, "d": [52,94], "a": 1 }, + { "px": [160,80], "src": [320,272], "f": 0, "t": 411, "d": [52,95], "a": 1 }, + { "px": [176,80], "src": [320,272], "f": 0, "t": 411, "d": [52,96], "a": 1 }, + { "px": [192,80], "src": [320,272], "f": 0, "t": 411, "d": [52,97], "a": 1 }, + { "px": [208,80], "src": [320,272], "f": 0, "t": 411, "d": [52,98], "a": 1 }, + { "px": [48,96], "src": [320,272], "f": 0, "t": 411, "d": [52,105], "a": 1 }, + { "px": [64,96], "src": [320,272], "f": 0, "t": 411, "d": [52,106], "a": 1 }, + { "px": [80,96], "src": [320,272], "f": 0, "t": 411, "d": [52,107], "a": 1 }, + { "px": [96,96], "src": [320,272], "f": 0, "t": 411, "d": [52,108], "a": 1 }, + { "px": [112,96], "src": [320,272], "f": 0, "t": 411, "d": [52,109], "a": 1 }, + { "px": [128,96], "src": [320,272], "f": 0, "t": 411, "d": [52,110], "a": 1 }, + { "px": [144,96], "src": [320,272], "f": 0, "t": 411, "d": [52,111], "a": 1 }, + { "px": [160,96], "src": [320,272], "f": 0, "t": 411, "d": [52,112], "a": 1 }, + { "px": [176,96], "src": [320,272], "f": 0, "t": 411, "d": [52,113], "a": 1 }, + { "px": [192,96], "src": [320,272], "f": 0, "t": 411, "d": [52,114], "a": 1 }, + { "px": [208,96], "src": [320,272], "f": 0, "t": 411, "d": [52,115], "a": 1 }, + { "px": [48,112], "src": [320,272], "f": 0, "t": 411, "d": [52,122], "a": 1 }, + { "px": [64,112], "src": [320,272], "f": 0, "t": 411, "d": [52,123], "a": 1 }, + { "px": [80,112], "src": [320,272], "f": 0, "t": 411, "d": [52,124], "a": 1 }, + { "px": [96,112], "src": [320,272], "f": 0, "t": 411, "d": [52,125], "a": 1 }, + { "px": [112,112], "src": [320,272], "f": 0, "t": 411, "d": [52,126], "a": 1 }, + { "px": [128,112], "src": [320,272], "f": 0, "t": 411, "d": [52,127], "a": 1 }, + { "px": [144,112], "src": [320,272], "f": 0, "t": 411, "d": [52,128], "a": 1 }, + { "px": [160,112], "src": [320,272], "f": 0, "t": 411, "d": [52,129], "a": 1 }, + { "px": [176,112], "src": [320,272], "f": 0, "t": 411, "d": [52,130], "a": 1 }, + { "px": [192,112], "src": [320,272], "f": 0, "t": 411, "d": [52,131], "a": 1 }, + { "px": [208,112], "src": [320,272], "f": 0, "t": 411, "d": [52,132], "a": 1 }, + { "px": [0,0], "src": [256,128], "f": 0, "t": 200, "d": [54,0], "a": 1 }, + { "px": [16,0], "src": [256,128], "f": 0, "t": 200, "d": [54,1], "a": 1 }, + { "px": [32,0], "src": [256,128], "f": 0, "t": 200, "d": [54,2], "a": 1 }, + { "px": [48,0], "src": [256,128], "f": 0, "t": 200, "d": [54,3], "a": 1 }, + { "px": [64,0], "src": [256,128], "f": 0, "t": 200, "d": [54,4], "a": 1 }, + { "px": [80,0], "src": [256,128], "f": 0, "t": 200, "d": [54,5], "a": 1 }, + { "px": [96,0], "src": [256,128], "f": 0, "t": 200, "d": [54,6], "a": 1 }, + { "px": [112,0], "src": [256,128], "f": 0, "t": 200, "d": [54,7], "a": 1 }, + { "px": [128,0], "src": [256,128], "f": 0, "t": 200, "d": [54,8], "a": 1 }, + { "px": [144,0], "src": [256,128], "f": 0, "t": 200, "d": [54,9], "a": 1 }, + { "px": [160,0], "src": [256,128], "f": 0, "t": 200, "d": [54,10], "a": 1 }, + { "px": [176,0], "src": [256,128], "f": 0, "t": 200, "d": [54,11], "a": 1 }, + { "px": [192,0], "src": [256,128], "f": 0, "t": 200, "d": [54,12], "a": 1 }, + { "px": [208,0], "src": [256,128], "f": 0, "t": 200, "d": [54,13], "a": 1 }, + { "px": [224,0], "src": [256,128], "f": 0, "t": 200, "d": [54,14], "a": 1 }, + { "px": [240,0], "src": [256,128], "f": 0, "t": 200, "d": [54,15], "a": 1 }, + { "px": [256,0], "src": [256,128], "f": 0, "t": 200, "d": [54,16], "a": 1 }, + { "px": [0,16], "src": [256,128], "f": 0, "t": 200, "d": [54,17], "a": 1 }, + { "px": [16,16], "src": [256,128], "f": 0, "t": 200, "d": [54,18], "a": 1 }, + { "px": [32,16], "src": [256,128], "f": 0, "t": 200, "d": [54,19], "a": 1 }, + { "px": [48,16], "src": [256,128], "f": 0, "t": 200, "d": [54,20], "a": 1 }, + { "px": [64,16], "src": [256,128], "f": 0, "t": 200, "d": [54,21], "a": 1 }, + { "px": [80,16], "src": [256,128], "f": 0, "t": 200, "d": [54,22], "a": 1 }, + { "px": [96,16], "src": [256,128], "f": 0, "t": 200, "d": [54,23], "a": 1 }, + { "px": [112,16], "src": [256,128], "f": 0, "t": 200, "d": [54,24], "a": 1 }, + { "px": [128,16], "src": [256,128], "f": 0, "t": 200, "d": [54,25], "a": 1 }, + { "px": [144,16], "src": [256,128], "f": 0, "t": 200, "d": [54,26], "a": 1 }, + { "px": [160,16], "src": [256,128], "f": 0, "t": 200, "d": [54,27], "a": 1 }, + { "px": [176,16], "src": [256,128], "f": 0, "t": 200, "d": [54,28], "a": 1 }, + { "px": [192,16], "src": [256,128], "f": 0, "t": 200, "d": [54,29], "a": 1 }, + { "px": [208,16], "src": [256,128], "f": 0, "t": 200, "d": [54,30], "a": 1 }, + { "px": [224,16], "src": [256,128], "f": 0, "t": 200, "d": [54,31], "a": 1 }, + { "px": [240,16], "src": [256,128], "f": 0, "t": 200, "d": [54,32], "a": 1 }, + { "px": [256,16], "src": [256,128], "f": 0, "t": 200, "d": [54,33], "a": 1 }, + { "px": [0,32], "src": [256,128], "f": 0, "t": 200, "d": [54,34], "a": 1 }, + { "px": [16,32], "src": [256,128], "f": 0, "t": 200, "d": [54,35], "a": 1 }, + { "px": [240,32], "src": [256,128], "f": 0, "t": 200, "d": [54,49], "a": 1 }, + { "px": [256,32], "src": [256,128], "f": 0, "t": 200, "d": [54,50], "a": 1 }, + { "px": [0,48], "src": [256,128], "f": 0, "t": 200, "d": [54,51], "a": 1 }, + { "px": [16,48], "src": [256,128], "f": 0, "t": 200, "d": [54,52], "a": 1 }, + { "px": [240,48], "src": [256,128], "f": 0, "t": 200, "d": [54,66], "a": 1 }, + { "px": [256,48], "src": [256,128], "f": 0, "t": 200, "d": [54,67], "a": 1 }, + { "px": [0,64], "src": [256,128], "f": 0, "t": 200, "d": [54,68], "a": 1 }, + { "px": [16,64], "src": [256,128], "f": 0, "t": 200, "d": [54,69], "a": 1 }, + { "px": [240,64], "src": [256,128], "f": 0, "t": 200, "d": [54,83], "a": 1 }, + { "px": [256,64], "src": [256,128], "f": 0, "t": 200, "d": [54,84], "a": 1 }, + { "px": [0,80], "src": [256,128], "f": 0, "t": 200, "d": [54,85], "a": 1 }, + { "px": [16,80], "src": [256,128], "f": 0, "t": 200, "d": [54,86], "a": 1 }, + { "px": [240,80], "src": [256,128], "f": 0, "t": 200, "d": [54,100], "a": 1 }, + { "px": [256,80], "src": [256,128], "f": 0, "t": 200, "d": [54,101], "a": 1 }, + { "px": [0,96], "src": [256,128], "f": 0, "t": 200, "d": [54,102], "a": 1 }, + { "px": [16,96], "src": [256,128], "f": 0, "t": 200, "d": [54,103], "a": 1 }, + { "px": [240,96], "src": [256,128], "f": 0, "t": 200, "d": [54,117], "a": 1 }, + { "px": [256,96], "src": [256,128], "f": 0, "t": 200, "d": [54,118], "a": 1 }, + { "px": [0,112], "src": [256,128], "f": 0, "t": 200, "d": [54,119], "a": 1 }, + { "px": [16,112], "src": [256,128], "f": 0, "t": 200, "d": [54,120], "a": 1 }, + { "px": [240,112], "src": [256,128], "f": 0, "t": 200, "d": [54,134], "a": 1 }, + { "px": [256,112], "src": [256,128], "f": 0, "t": 200, "d": [54,135], "a": 1 }, + { "px": [0,128], "src": [256,128], "f": 0, "t": 200, "d": [54,136], "a": 1 }, + { "px": [16,128], "src": [256,128], "f": 0, "t": 200, "d": [54,137], "a": 1 }, + { "px": [240,128], "src": [256,128], "f": 0, "t": 200, "d": [54,151], "a": 1 }, + { "px": [256,128], "src": [256,128], "f": 0, "t": 200, "d": [54,152], "a": 1 }, + { "px": [0,144], "src": [256,128], "f": 0, "t": 200, "d": [54,153], "a": 1 }, + { "px": [16,144], "src": [256,128], "f": 0, "t": 200, "d": [54,154], "a": 1 }, + { "px": [32,144], "src": [256,128], "f": 0, "t": 200, "d": [54,155], "a": 1 }, + { "px": [48,144], "src": [256,128], "f": 0, "t": 200, "d": [54,156], "a": 1 }, + { "px": [64,144], "src": [256,128], "f": 0, "t": 200, "d": [54,157], "a": 1 }, + { "px": [80,144], "src": [256,128], "f": 0, "t": 200, "d": [54,158], "a": 1 }, + { "px": [96,144], "src": [256,128], "f": 0, "t": 200, "d": [54,159], "a": 1 }, + { "px": [112,144], "src": [256,128], "f": 0, "t": 200, "d": [54,160], "a": 1 }, + { "px": [128,144], "src": [256,128], "f": 0, "t": 200, "d": [54,161], "a": 1 }, + { "px": [144,144], "src": [256,128], "f": 0, "t": 200, "d": [54,162], "a": 1 }, + { "px": [160,144], "src": [256,128], "f": 0, "t": 200, "d": [54,163], "a": 1 }, + { "px": [176,144], "src": [256,128], "f": 0, "t": 200, "d": [54,164], "a": 1 }, + { "px": [192,144], "src": [256,128], "f": 0, "t": 200, "d": [54,165], "a": 1 }, + { "px": [208,144], "src": [256,128], "f": 0, "t": 200, "d": [54,166], "a": 1 }, + { "px": [224,144], "src": [256,128], "f": 0, "t": 200, "d": [54,167], "a": 1 }, + { "px": [240,144], "src": [256,128], "f": 0, "t": 200, "d": [54,168], "a": 1 }, + { "px": [256,144], "src": [256,128], "f": 0, "t": 200, "d": [54,169], "a": 1 }, + { "px": [0,160], "src": [256,128], "f": 0, "t": 200, "d": [54,170], "a": 1 }, + { "px": [16,160], "src": [256,128], "f": 0, "t": 200, "d": [54,171], "a": 1 }, + { "px": [32,160], "src": [256,128], "f": 0, "t": 200, "d": [54,172], "a": 1 }, + { "px": [48,160], "src": [256,128], "f": 0, "t": 200, "d": [54,173], "a": 1 }, + { "px": [64,160], "src": [256,128], "f": 0, "t": 200, "d": [54,174], "a": 1 }, + { "px": [80,160], "src": [256,128], "f": 0, "t": 200, "d": [54,175], "a": 1 }, + { "px": [96,160], "src": [256,128], "f": 0, "t": 200, "d": [54,176], "a": 1 }, + { "px": [112,160], "src": [256,128], "f": 0, "t": 200, "d": [54,177], "a": 1 }, + { "px": [128,160], "src": [256,128], "f": 0, "t": 200, "d": [54,178], "a": 1 }, + { "px": [144,160], "src": [256,128], "f": 0, "t": 200, "d": [54,179], "a": 1 }, + { "px": [160,160], "src": [256,128], "f": 0, "t": 200, "d": [54,180], "a": 1 }, + { "px": [176,160], "src": [256,128], "f": 0, "t": 200, "d": [54,181], "a": 1 }, + { "px": [192,160], "src": [256,128], "f": 0, "t": 200, "d": [54,182], "a": 1 }, + { "px": [208,160], "src": [256,128], "f": 0, "t": 200, "d": [54,183], "a": 1 }, + { "px": [224,160], "src": [256,128], "f": 0, "t": 200, "d": [54,184], "a": 1 }, + { "px": [240,160], "src": [256,128], "f": 0, "t": 200, "d": [54,185], "a": 1 }, + { "px": [256,160], "src": [256,128], "f": 0, "t": 200, "d": [54,186], "a": 1 }, + { "px": [32,48], "src": [224,128], "f": 1, "t": 198, "d": [56,53], "a": 1 }, + { "px": [224,48], "src": [224,128], "f": 0, "t": 198, "d": [56,65], "a": 1 }, + { "px": [32,64], "src": [224,128], "f": 1, "t": 198, "d": [56,70], "a": 1 }, + { "px": [224,64], "src": [224,128], "f": 0, "t": 198, "d": [56,82], "a": 1 }, + { "px": [32,80], "src": [224,128], "f": 1, "t": 198, "d": [56,87], "a": 1 }, + { "px": [224,80], "src": [224,128], "f": 0, "t": 198, "d": [56,99], "a": 1 }, + { "px": [32,96], "src": [224,128], "f": 1, "t": 198, "d": [56,104], "a": 1 }, + { "px": [224,96], "src": [224,128], "f": 0, "t": 198, "d": [56,116], "a": 1 }, + { "px": [32,112], "src": [224,128], "f": 1, "t": 198, "d": [56,121], "a": 1 }, + { "px": [224,112], "src": [224,128], "f": 0, "t": 198, "d": [56,133], "a": 1 }, + { "px": [48,32], "src": [256,96], "f": 2, "t": 154, "d": [57,37], "a": 1 }, + { "px": [64,32], "src": [256,96], "f": 2, "t": 154, "d": [57,38], "a": 1 }, + { "px": [80,32], "src": [256,96], "f": 2, "t": 154, "d": [57,39], "a": 1 }, + { "px": [96,32], "src": [256,96], "f": 2, "t": 154, "d": [57,40], "a": 1 }, + { "px": [112,32], "src": [256,96], "f": 2, "t": 154, "d": [57,41], "a": 1 }, + { "px": [128,32], "src": [256,96], "f": 2, "t": 154, "d": [57,42], "a": 1 }, + { "px": [144,32], "src": [256,96], "f": 2, "t": 154, "d": [57,43], "a": 1 }, + { "px": [160,32], "src": [256,96], "f": 2, "t": 154, "d": [57,44], "a": 1 }, + { "px": [176,32], "src": [256,96], "f": 2, "t": 154, "d": [57,45], "a": 1 }, + { "px": [192,32], "src": [256,96], "f": 2, "t": 154, "d": [57,46], "a": 1 }, + { "px": [208,32], "src": [256,96], "f": 2, "t": 154, "d": [57,47], "a": 1 }, + { "px": [48,128], "src": [256,96], "f": 0, "t": 154, "d": [57,139], "a": 1 }, + { "px": [64,128], "src": [256,96], "f": 0, "t": 154, "d": [57,140], "a": 1 }, + { "px": [80,128], "src": [256,96], "f": 0, "t": 154, "d": [57,141], "a": 1 }, + { "px": [96,128], "src": [256,96], "f": 0, "t": 154, "d": [57,142], "a": 1 }, + { "px": [112,128], "src": [256,96], "f": 0, "t": 154, "d": [57,143], "a": 1 }, + { "px": [128,128], "src": [256,96], "f": 0, "t": 154, "d": [57,144], "a": 1 }, + { "px": [144,128], "src": [256,96], "f": 0, "t": 154, "d": [57,145], "a": 1 }, + { "px": [160,128], "src": [256,96], "f": 0, "t": 154, "d": [57,146], "a": 1 }, + { "px": [176,128], "src": [256,96], "f": 0, "t": 154, "d": [57,147], "a": 1 }, + { "px": [192,128], "src": [256,96], "f": 0, "t": 154, "d": [57,148], "a": 1 }, + { "px": [208,128], "src": [256,96], "f": 0, "t": 154, "d": [57,149], "a": 1 }, + { "px": [32,32], "src": [0,304], "f": 3, "t": 437, "d": [59,36], "a": 1 }, + { "px": [224,32], "src": [0,304], "f": 2, "t": 437, "d": [59,48], "a": 1 }, + { "px": [32,128], "src": [0,304], "f": 1, "t": 437, "d": [59,138], "a": 1 }, + { "px": [224,128], "src": [0,304], "f": 0, "t": 437, "d": [59,150], "a": 1 } + ], + "seed": 8131641, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [] + } + ], + "__neighbours": [] + }, + { + "identifier": "Level_1", + "iid": "d256bfd0-6280-11ee-9d82-b11687712c4d", + "uid": 65, + "worldX": -1, + "worldY": -1, + "worldDepth": 0, + "pxWid": 144, + "pxHei": 128, + "__bgColor": "#696A79", + "bgColor": null, + "useAutoIdentifier": true, + "bgRelPath": null, + "bgPos": null, + "bgPivotX": 0.5, + "bgPivotY": 0.5, + "__smartColor": "#ADADB5", + "__bgPos": null, + "externalRelPath": null, + "fieldInstances": [], + "layerInstances": [ + { + "__identifier": "Entities", + "__type": "Entities", + "__cWid": 9, + "__cHei": 8, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": null, + "__tilesetRelPath": null, + "iid": "d256bfd1-6280-11ee-9d82-339860f57293", + "levelId": 65, + "layerDefUid": 60, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [], + "autoLayerTiles": [], + "seed": 3799793, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [ + { + "__identifier": "Player", + "__grid": [4,4], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 3, "x": 0, "y": 0, "w": 32, "h": 32 }, + "__smartColor": "#BE4A2F", + "__worldX": 384, + "__worldY": 64, + "iid": "2e682060-6280-11ee-9d82-69b5a3382d99", + "width": 16, + "height": 16, + "defUid": 62, + "px": [64,64], + "fieldInstances": [] + }, + { + "__identifier": "Goal", + "__grid": [8,7], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 4, "x": 256, "y": 304, "w": 16, "h": 16 }, + "__smartColor": "#D77643", + "__worldX": 448, + "__worldY": 112, + "iid": "2f8b43a0-6280-11ee-9d82-b9d9109a7c7b", + "width": 16, + "height": 16, + "defUid": 64, + "px": [128,112], + "fieldInstances": [] + } + ] + }, + { + "__identifier": "Walls", + "__type": "IntGrid", + "__cWid": 9, + "__cHei": 8, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": 4, + "__tilesetRelPath": "atlas/SunnyLand_by_Ansimuz-extended.png", + "iid": "d256bfd2-6280-11ee-9d82-77c0a528b632", + "levelId": 65, + "layerDefUid": 7, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 1, + 0, + 1, + 1, + 1, + 0, + 1, + 0, + 0, + 1, + 0, + 1, + 0, + 1, + 0, + 1, + 0, + 0, + 1, + 0, + 0, + 0, + 1, + 0, + 1, + 0, + 0, + 1, + 1, + 1, + 1, + 1, + 0, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1, + 0 + ], + "autoLayerTiles": [ + { "px": [0,0], "src": [320,272], "f": 0, "t": 411, "d": [52,0], "a": 1 }, + { "px": [16,0], "src": [320,272], "f": 0, "t": 411, "d": [52,1], "a": 1 }, + { "px": [32,0], "src": [320,272], "f": 0, "t": 411, "d": [52,2], "a": 1 }, + { "px": [48,0], "src": [320,272], "f": 0, "t": 411, "d": [52,3], "a": 1 }, + { "px": [64,0], "src": [320,272], "f": 0, "t": 411, "d": [52,4], "a": 1 }, + { "px": [80,0], "src": [320,272], "f": 0, "t": 411, "d": [52,5], "a": 1 }, + { "px": [96,0], "src": [320,272], "f": 0, "t": 411, "d": [52,6], "a": 1 }, + { "px": [112,0], "src": [320,272], "f": 0, "t": 411, "d": [52,7], "a": 1 }, + { "px": [128,0], "src": [320,272], "f": 0, "t": 411, "d": [52,8], "a": 1 }, + { "px": [0,16], "src": [320,272], "f": 0, "t": 411, "d": [52,9], "a": 1 }, + { "px": [128,16], "src": [320,272], "f": 0, "t": 411, "d": [52,17], "a": 1 }, + { "px": [0,32], "src": [320,272], "f": 0, "t": 411, "d": [52,18], "a": 1 }, + { "px": [32,32], "src": [320,272], "f": 0, "t": 411, "d": [52,20], "a": 1 }, + { "px": [48,32], "src": [320,272], "f": 0, "t": 411, "d": [52,21], "a": 1 }, + { "px": [64,32], "src": [320,272], "f": 0, "t": 411, "d": [52,22], "a": 1 }, + { "px": [80,32], "src": [320,272], "f": 0, "t": 411, "d": [52,23], "a": 1 }, + { "px": [96,32], "src": [320,272], "f": 0, "t": 411, "d": [52,24], "a": 1 }, + { "px": [128,32], "src": [320,272], "f": 0, "t": 411, "d": [52,26], "a": 1 }, + { "px": [0,48], "src": [320,272], "f": 0, "t": 411, "d": [52,27], "a": 1 }, + { "px": [32,48], "src": [320,272], "f": 0, "t": 411, "d": [52,29], "a": 1 }, + { "px": [96,48], "src": [320,272], "f": 0, "t": 411, "d": [52,33], "a": 1 }, + { "px": [128,48], "src": [320,272], "f": 0, "t": 411, "d": [52,35], "a": 1 }, + { "px": [0,64], "src": [320,272], "f": 0, "t": 411, "d": [52,36], "a": 1 }, + { "px": [32,64], "src": [320,272], "f": 0, "t": 411, "d": [52,38], "a": 1 }, + { "px": [64,64], "src": [320,272], "f": 0, "t": 411, "d": [52,40], "a": 1 }, + { "px": [96,64], "src": [320,272], "f": 0, "t": 411, "d": [52,42], "a": 1 }, + { "px": [128,64], "src": [320,272], "f": 0, "t": 411, "d": [52,44], "a": 1 }, + { "px": [0,80], "src": [320,272], "f": 0, "t": 411, "d": [52,45], "a": 1 }, + { "px": [32,80], "src": [320,272], "f": 0, "t": 411, "d": [52,47], "a": 1 }, + { "px": [48,80], "src": [320,272], "f": 0, "t": 411, "d": [52,48], "a": 1 }, + { "px": [64,80], "src": [320,272], "f": 0, "t": 411, "d": [52,49], "a": 1 }, + { "px": [96,80], "src": [320,272], "f": 0, "t": 411, "d": [52,51], "a": 1 }, + { "px": [128,80], "src": [320,272], "f": 0, "t": 411, "d": [52,53], "a": 1 }, + { "px": [0,96], "src": [320,272], "f": 0, "t": 411, "d": [52,54], "a": 1 }, + { "px": [96,96], "src": [320,272], "f": 0, "t": 411, "d": [52,60], "a": 1 }, + { "px": [128,96], "src": [320,272], "f": 0, "t": 411, "d": [52,62], "a": 1 }, + { "px": [0,112], "src": [320,272], "f": 0, "t": 411, "d": [52,63], "a": 1 }, + { "px": [16,112], "src": [320,272], "f": 0, "t": 411, "d": [52,64], "a": 1 }, + { "px": [32,112], "src": [320,272], "f": 0, "t": 411, "d": [52,65], "a": 1 }, + { "px": [48,112], "src": [320,272], "f": 0, "t": 411, "d": [52,66], "a": 1 }, + { "px": [64,112], "src": [320,272], "f": 0, "t": 411, "d": [52,67], "a": 1 }, + { "px": [80,112], "src": [320,272], "f": 0, "t": 411, "d": [52,68], "a": 1 }, + { "px": [96,112], "src": [320,272], "f": 0, "t": 411, "d": [52,69], "a": 1 }, + { "px": [128,112], "src": [320,272], "f": 0, "t": 411, "d": [52,71], "a": 1 }, + { "px": [16,32], "src": [224,128], "f": 0, "t": 198, "d": [56,19], "a": 1 }, + { "px": [112,32], "src": [224,128], "f": 0, "t": 198, "d": [56,25], "a": 1 }, + { "px": [16,48], "src": [224,128], "f": 0, "t": 198, "d": [56,28], "a": 1 }, + { "px": [112,48], "src": [224,128], "f": 0, "t": 198, "d": [56,34], "a": 1 }, + { "px": [16,64], "src": [224,128], "f": 0, "t": 198, "d": [56,37], "a": 1 }, + { "px": [80,64], "src": [224,128], "f": 0, "t": 198, "d": [56,41], "a": 1 }, + { "px": [112,64], "src": [224,128], "f": 0, "t": 198, "d": [56,43], "a": 1 }, + { "px": [16,80], "src": [224,128], "f": 0, "t": 198, "d": [56,46], "a": 1 }, + { "px": [80,80], "src": [224,128], "f": 0, "t": 198, "d": [56,50], "a": 1 }, + { "px": [112,80], "src": [224,128], "f": 0, "t": 198, "d": [56,52], "a": 1 }, + { "px": [112,96], "src": [224,128], "f": 0, "t": 198, "d": [56,61], "a": 1 }, + { "px": [112,112], "src": [224,128], "f": 0, "t": 198, "d": [56,70], "a": 1 }, + { "px": [32,16], "src": [256,96], "f": 0, "t": 154, "d": [57,11], "a": 1 }, + { "px": [48,16], "src": [256,96], "f": 0, "t": 154, "d": [57,12], "a": 1 }, + { "px": [64,16], "src": [256,96], "f": 0, "t": 154, "d": [57,13], "a": 1 }, + { "px": [80,16], "src": [256,96], "f": 0, "t": 154, "d": [57,14], "a": 1 }, + { "px": [96,16], "src": [256,96], "f": 0, "t": 154, "d": [57,15], "a": 1 }, + { "px": [64,48], "src": [256,96], "f": 0, "t": 154, "d": [57,31], "a": 1 }, + { "px": [32,96], "src": [256,96], "f": 0, "t": 154, "d": [57,56], "a": 1 }, + { "px": [48,96], "src": [256,96], "f": 0, "t": 154, "d": [57,57], "a": 1 }, + { "px": [64,96], "src": [256,96], "f": 0, "t": 154, "d": [57,58], "a": 1 }, + { "px": [48,64], "src": [224,96], "f": 2, "t": 152, "d": [58,39], "a": 1 }, + { "px": [16,16], "src": [0,304], "f": 3, "t": 437, "d": [59,10], "a": 1 }, + { "px": [112,16], "src": [0,304], "f": 2, "t": 437, "d": [59,16], "a": 1 }, + { "px": [48,48], "src": [0,304], "f": 3, "t": 437, "d": [59,30], "a": 1 }, + { "px": [80,48], "src": [0,304], "f": 2, "t": 437, "d": [59,32], "a": 1 }, + { "px": [16,96], "src": [0,304], "f": 1, "t": 437, "d": [59,55], "a": 1 }, + { "px": [80,96], "src": [0,304], "f": 0, "t": 437, "d": [59,59], "a": 1 } + ], + "seed": 2123058, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [] + } + ], + "__neighbours": [] + }, + { + "identifier": "Level_2", + "iid": "ffd63da0-6280-11ee-9d82-33bc4a3f7c31", + "uid": 66, + "worldX": -1, + "worldY": -1, + "worldDepth": 0, + "pxWid": 240, + "pxHei": 240, + "__bgColor": "#696A79", + "bgColor": null, + "useAutoIdentifier": true, + "bgRelPath": null, + "bgPos": null, + "bgPivotX": 0.5, + "bgPivotY": 0.5, + "__smartColor": "#ADADB5", + "__bgPos": null, + "externalRelPath": null, + "fieldInstances": [], + "layerInstances": [ + { + "__identifier": "Entities", + "__type": "Entities", + "__cWid": 15, + "__cHei": 15, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": null, + "__tilesetRelPath": null, + "iid": "ffd63da1-6280-11ee-9d82-b1384772dbf1", + "levelId": 66, + "layerDefUid": 60, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [], + "autoLayerTiles": [], + "seed": 7964091, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [ + { + "__identifier": "Player", + "__grid": [0,0], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 3, "x": 0, "y": 0, "w": 32, "h": 32 }, + "__smartColor": "#BE4A2F", + "__worldX": 512, + "__worldY": 0, + "iid": "174cc070-6280-11ee-9d82-177ac78b4a85", + "width": 16, + "height": 16, + "defUid": 62, + "px": [0,0], + "fieldInstances": [] + }, + { + "__identifier": "Goal", + "__grid": [14,14], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 4, "x": 256, "y": 304, "w": 16, "h": 16 }, + "__smartColor": "#D77643", + "__worldX": 736, + "__worldY": 224, + "iid": "1eecf610-6280-11ee-9d82-c7993145cad1", + "width": 16, + "height": 16, + "defUid": 64, + "px": [224,224], + "fieldInstances": [] + } + ] + }, + { + "__identifier": "Walls", + "__type": "IntGrid", + "__cWid": 15, + "__cHei": 15, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": 4, + "__tilesetRelPath": "atlas/SunnyLand_by_Ansimuz-extended.png", + "iid": "ffd63da2-6280-11ee-9d82-7d66ce1b4bd2", + "levelId": 66, + "layerDefUid": 7, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [ + 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1,1,1,0,0,1,0,0,0, + 1,0,1,0,0,0,1,0,1,0,0,1,0,1,1,1,0,1,1,1,0,1,0,1,0,0,1,0,1,0,0,0,0,0,1, + 0,1,0,0,0,0,1,0,1,0,1,0,1,1,1,0,1,0,1,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0, + 0,1,1,1,0,1,0,1,0,1,1,1,1,1,0,0,0,0,0,0,1,0,1,0,1,0,0,0,1,0,1,1,0,1,1, + 1,1,1,0,1,0,1,0,1,0,0,0,0,1,0,0,0,0,0,1,0,1,0,1,0,0,1,1,1,0,1,1,1,1,1, + 0,1,1,1,0,0,1,0,0,0,1,0,1,0,0,0,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,1,0,1,1, + 0,0,0,1,0,0,0,0,0,1,0,0,0,0,0 + ], + "autoLayerTiles": [ + { "px": [0,0], "src": [320,272], "f": 0, "t": 411, "d": [52,0], "a": 1 }, + { "px": [16,0], "src": [320,272], "f": 0, "t": 411, "d": [52,1], "a": 1 }, + { "px": [32,0], "src": [320,272], "f": 0, "t": 411, "d": [52,2], "a": 1 }, + { "px": [64,0], "src": [320,272], "f": 0, "t": 411, "d": [52,4], "a": 1 }, + { "px": [80,0], "src": [320,272], "f": 0, "t": 411, "d": [52,5], "a": 1 }, + { "px": [96,0], "src": [320,272], "f": 0, "t": 411, "d": [52,6], "a": 1 }, + { "px": [112,0], "src": [320,272], "f": 0, "t": 411, "d": [52,7], "a": 1 }, + { "px": [128,0], "src": [320,272], "f": 0, "t": 411, "d": [52,8], "a": 1 }, + { "px": [144,0], "src": [320,272], "f": 0, "t": 411, "d": [52,9], "a": 1 }, + { "px": [160,0], "src": [320,272], "f": 0, "t": 411, "d": [52,10], "a": 1 }, + { "px": [176,0], "src": [320,272], "f": 0, "t": 411, "d": [52,11], "a": 1 }, + { "px": [192,0], "src": [320,272], "f": 0, "t": 411, "d": [52,12], "a": 1 }, + { "px": [208,0], "src": [320,272], "f": 0, "t": 411, "d": [52,13], "a": 1 }, + { "px": [224,0], "src": [320,272], "f": 0, "t": 411, "d": [52,14], "a": 1 }, + { "px": [0,16], "src": [320,272], "f": 0, "t": 411, "d": [52,15], "a": 1 }, + { "px": [64,16], "src": [320,272], "f": 0, "t": 411, "d": [52,19], "a": 1 }, + { "px": [128,16], "src": [320,272], "f": 0, "t": 411, "d": [52,23], "a": 1 }, + { "px": [224,16], "src": [320,272], "f": 0, "t": 411, "d": [52,29], "a": 1 }, + { "px": [0,32], "src": [320,272], "f": 0, "t": 411, "d": [52,30], "a": 1 }, + { "px": [32,32], "src": [320,272], "f": 0, "t": 411, "d": [52,32], "a": 1 }, + { "px": [48,32], "src": [320,272], "f": 0, "t": 411, "d": [52,33], "a": 1 }, + { "px": [64,32], "src": [320,272], "f": 0, "t": 411, "d": [52,34], "a": 1 }, + { "px": [96,32], "src": [320,272], "f": 0, "t": 411, "d": [52,36], "a": 1 }, + { "px": [128,32], "src": [320,272], "f": 0, "t": 411, "d": [52,38], "a": 1 }, + { "px": [144,32], "src": [320,272], "f": 0, "t": 411, "d": [52,39], "a": 1 }, + { "px": [160,32], "src": [320,272], "f": 0, "t": 411, "d": [52,40], "a": 1 }, + { "px": [192,32], "src": [320,272], "f": 0, "t": 411, "d": [52,42], "a": 1 }, + { "px": [224,32], "src": [320,272], "f": 0, "t": 411, "d": [52,44], "a": 1 }, + { "px": [0,48], "src": [320,272], "f": 0, "t": 411, "d": [52,45], "a": 1 }, + { "px": [32,48], "src": [320,272], "f": 0, "t": 411, "d": [52,47], "a": 1 }, + { "px": [96,48], "src": [320,272], "f": 0, "t": 411, "d": [52,51], "a": 1 }, + { "px": [160,48], "src": [320,272], "f": 0, "t": 411, "d": [52,55], "a": 1 }, + { "px": [192,48], "src": [320,272], "f": 0, "t": 411, "d": [52,57], "a": 1 }, + { "px": [224,48], "src": [320,272], "f": 0, "t": 411, "d": [52,59], "a": 1 }, + { "px": [0,64], "src": [320,272], "f": 0, "t": 411, "d": [52,60], "a": 1 }, + { "px": [32,64], "src": [320,272], "f": 0, "t": 411, "d": [52,62], "a": 1 }, + { "px": [64,64], "src": [320,272], "f": 0, "t": 411, "d": [52,64], "a": 1 }, + { "px": [80,64], "src": [320,272], "f": 0, "t": 411, "d": [52,65], "a": 1 }, + { "px": [96,64], "src": [320,272], "f": 0, "t": 411, "d": [52,66], "a": 1 }, + { "px": [112,64], "src": [320,272], "f": 0, "t": 411, "d": [52,67], "a": 1 }, + { "px": [128,64], "src": [320,272], "f": 0, "t": 411, "d": [52,68], "a": 1 }, + { "px": [160,64], "src": [320,272], "f": 0, "t": 411, "d": [52,70], "a": 1 }, + { "px": [192,64], "src": [320,272], "f": 0, "t": 411, "d": [52,72], "a": 1 }, + { "px": [208,64], "src": [320,272], "f": 0, "t": 411, "d": [52,73], "a": 1 }, + { "px": [224,64], "src": [320,272], "f": 0, "t": 411, "d": [52,74], "a": 1 }, + { "px": [0,80], "src": [320,272], "f": 0, "t": 411, "d": [52,75], "a": 1 }, + { "px": [32,80], "src": [320,272], "f": 0, "t": 411, "d": [52,77], "a": 1 }, + { "px": [64,80], "src": [320,272], "f": 0, "t": 411, "d": [52,79], "a": 1 }, + { "px": [96,80], "src": [320,272], "f": 0, "t": 411, "d": [52,81], "a": 1 }, + { "px": [160,80], "src": [320,272], "f": 0, "t": 411, "d": [52,85], "a": 1 }, + { "px": [192,80], "src": [320,272], "f": 0, "t": 411, "d": [52,87], "a": 1 }, + { "px": [0,96], "src": [320,272], "f": 0, "t": 411, "d": [52,90], "a": 1 }, + { "px": [16,96], "src": [320,272], "f": 0, "t": 411, "d": [52,91], "a": 1 }, + { "px": [32,96], "src": [320,272], "f": 0, "t": 411, "d": [52,92], "a": 1 }, + { "px": [64,96], "src": [320,272], "f": 0, "t": 411, "d": [52,94], "a": 1 }, + { "px": [96,96], "src": [320,272], "f": 0, "t": 411, "d": [52,96], "a": 1 }, + { "px": [128,96], "src": [320,272], "f": 0, "t": 411, "d": [52,98], "a": 1 }, + { "px": [144,96], "src": [320,272], "f": 0, "t": 411, "d": [52,99], "a": 1 }, + { "px": [160,96], "src": [320,272], "f": 0, "t": 411, "d": [52,100], "a": 1 }, + { "px": [192,96], "src": [320,272], "f": 0, "t": 411, "d": [52,102], "a": 1 }, + { "px": [208,96], "src": [320,272], "f": 0, "t": 411, "d": [52,103], "a": 1 }, + { "px": [224,96], "src": [320,272], "f": 0, "t": 411, "d": [52,104], "a": 1 }, + { "px": [0,112], "src": [320,272], "f": 0, "t": 411, "d": [52,105], "a": 1 }, + { "px": [64,112], "src": [320,272], "f": 0, "t": 411, "d": [52,109], "a": 1 }, + { "px": [96,112], "src": [320,272], "f": 0, "t": 411, "d": [52,111], "a": 1 }, + { "px": [128,112], "src": [320,272], "f": 0, "t": 411, "d": [52,113], "a": 1 }, + { "px": [224,112], "src": [320,272], "f": 0, "t": 411, "d": [52,119], "a": 1 }, + { "px": [0,128], "src": [320,272], "f": 0, "t": 411, "d": [52,120], "a": 1 }, + { "px": [16,128], "src": [320,272], "f": 0, "t": 411, "d": [52,121], "a": 1 }, + { "px": [32,128], "src": [320,272], "f": 0, "t": 411, "d": [52,122], "a": 1 }, + { "px": [48,128], "src": [320,272], "f": 0, "t": 411, "d": [52,123], "a": 1 }, + { "px": [64,128], "src": [320,272], "f": 0, "t": 411, "d": [52,124], "a": 1 }, + { "px": [96,128], "src": [320,272], "f": 0, "t": 411, "d": [52,126], "a": 1 }, + { "px": [128,128], "src": [320,272], "f": 0, "t": 411, "d": [52,128], "a": 1 }, + { "px": [160,128], "src": [320,272], "f": 0, "t": 411, "d": [52,130], "a": 1 }, + { "px": [176,128], "src": [320,272], "f": 0, "t": 411, "d": [52,131], "a": 1 }, + { "px": [192,128], "src": [320,272], "f": 0, "t": 411, "d": [52,132], "a": 1 }, + { "px": [224,128], "src": [320,272], "f": 0, "t": 411, "d": [52,134], "a": 1 }, + { "px": [32,144], "src": [320,272], "f": 0, "t": 411, "d": [52,137], "a": 1 }, + { "px": [128,144], "src": [320,272], "f": 0, "t": 411, "d": [52,143], "a": 1 }, + { "px": [160,144], "src": [320,272], "f": 0, "t": 411, "d": [52,145], "a": 1 }, + { "px": [192,144], "src": [320,272], "f": 0, "t": 411, "d": [52,147], "a": 1 }, + { "px": [224,144], "src": [320,272], "f": 0, "t": 411, "d": [52,149], "a": 1 }, + { "px": [0,160], "src": [320,272], "f": 0, "t": 411, "d": [52,150], "a": 1 }, + { "px": [16,160], "src": [320,272], "f": 0, "t": 411, "d": [52,151], "a": 1 }, + { "px": [32,160], "src": [320,272], "f": 0, "t": 411, "d": [52,152], "a": 1 }, + { "px": [64,160], "src": [320,272], "f": 0, "t": 411, "d": [52,154], "a": 1 }, + { "px": [80,160], "src": [320,272], "f": 0, "t": 411, "d": [52,155], "a": 1 }, + { "px": [96,160], "src": [320,272], "f": 0, "t": 411, "d": [52,156], "a": 1 }, + { "px": [112,160], "src": [320,272], "f": 0, "t": 411, "d": [52,157], "a": 1 }, + { "px": [128,160], "src": [320,272], "f": 0, "t": 411, "d": [52,158], "a": 1 }, + { "px": [160,160], "src": [320,272], "f": 0, "t": 411, "d": [52,160], "a": 1 }, + { "px": [192,160], "src": [320,272], "f": 0, "t": 411, "d": [52,162], "a": 1 }, + { "px": [224,160], "src": [320,272], "f": 0, "t": 411, "d": [52,164], "a": 1 }, + { "px": [0,176], "src": [320,272], "f": 0, "t": 411, "d": [52,165], "a": 1 }, + { "px": [64,176], "src": [320,272], "f": 0, "t": 411, "d": [52,169], "a": 1 }, + { "px": [160,176], "src": [320,272], "f": 0, "t": 411, "d": [52,175], "a": 1 }, + { "px": [224,176], "src": [320,272], "f": 0, "t": 411, "d": [52,179], "a": 1 }, + { "px": [0,192], "src": [320,272], "f": 0, "t": 411, "d": [52,180], "a": 1 }, + { "px": [32,192], "src": [320,272], "f": 0, "t": 411, "d": [52,182], "a": 1 }, + { "px": [48,192], "src": [320,272], "f": 0, "t": 411, "d": [52,183], "a": 1 }, + { "px": [64,192], "src": [320,272], "f": 0, "t": 411, "d": [52,184], "a": 1 }, + { "px": [96,192], "src": [320,272], "f": 0, "t": 411, "d": [52,186], "a": 1 }, + { "px": [128,192], "src": [320,272], "f": 0, "t": 411, "d": [52,188], "a": 1 }, + { "px": [144,192], "src": [320,272], "f": 0, "t": 411, "d": [52,189], "a": 1 }, + { "px": [160,192], "src": [320,272], "f": 0, "t": 411, "d": [52,190], "a": 1 }, + { "px": [192,192], "src": [320,272], "f": 0, "t": 411, "d": [52,192], "a": 1 }, + { "px": [208,192], "src": [320,272], "f": 0, "t": 411, "d": [52,193], "a": 1 }, + { "px": [224,192], "src": [320,272], "f": 0, "t": 411, "d": [52,194], "a": 1 }, + { "px": [32,208], "src": [320,272], "f": 0, "t": 411, "d": [52,197], "a": 1 }, + { "px": [96,208], "src": [320,272], "f": 0, "t": 411, "d": [52,201], "a": 1 }, + { "px": [128,208], "src": [320,272], "f": 0, "t": 411, "d": [52,203], "a": 1 }, + { "px": [160,208], "src": [320,272], "f": 0, "t": 411, "d": [52,205], "a": 1 }, + { "px": [192,208], "src": [320,272], "f": 0, "t": 411, "d": [52,207], "a": 1 }, + { "px": [0,224], "src": [320,272], "f": 0, "t": 411, "d": [52,210], "a": 1 }, + { "px": [16,224], "src": [320,272], "f": 0, "t": 411, "d": [52,211], "a": 1 }, + { "px": [32,224], "src": [320,272], "f": 0, "t": 411, "d": [52,212], "a": 1 }, + { "px": [64,224], "src": [320,272], "f": 0, "t": 411, "d": [52,214], "a": 1 }, + { "px": [80,224], "src": [320,272], "f": 0, "t": 411, "d": [52,215], "a": 1 }, + { "px": [96,224], "src": [320,272], "f": 0, "t": 411, "d": [52,216], "a": 1 }, + { "px": [112,224], "src": [320,272], "f": 0, "t": 411, "d": [52,217], "a": 1 }, + { "px": [128,224], "src": [320,272], "f": 0, "t": 411, "d": [52,218], "a": 1 }, + { "px": [160,224], "src": [320,272], "f": 0, "t": 411, "d": [52,220], "a": 1 }, + { "px": [176,224], "src": [320,272], "f": 0, "t": 411, "d": [52,221], "a": 1 }, + { "px": [192,224], "src": [320,272], "f": 0, "t": 411, "d": [52,222], "a": 1 }, + { "px": [208,224], "src": [320,272], "f": 0, "t": 411, "d": [52,223], "a": 1 }, + { "px": [224,224], "src": [320,272], "f": 0, "t": 411, "d": [52,224], "a": 1 }, + { "px": [48,0], "src": [224,128], "f": 0, "t": 198, "d": [56,3], "a": 1 }, + { "px": [16,32], "src": [224,128], "f": 0, "t": 198, "d": [56,31], "a": 1 }, + { "px": [80,32], "src": [224,128], "f": 0, "t": 198, "d": [56,35], "a": 1 }, + { "px": [112,32], "src": [224,128], "f": 0, "t": 198, "d": [56,37], "a": 1 }, + { "px": [176,32], "src": [224,128], "f": 0, "t": 198, "d": [56,41], "a": 1 }, + { "px": [208,32], "src": [224,128], "f": 0, "t": 198, "d": [56,43], "a": 1 }, + { "px": [16,48], "src": [224,128], "f": 0, "t": 198, "d": [56,46], "a": 1 }, + { "px": [176,48], "src": [224,128], "f": 0, "t": 198, "d": [56,56], "a": 1 }, + { "px": [16,64], "src": [224,128], "f": 0, "t": 198, "d": [56,61], "a": 1 }, + { "px": [48,64], "src": [224,128], "f": 0, "t": 198, "d": [56,63], "a": 1 }, + { "px": [144,64], "src": [224,128], "f": 0, "t": 198, "d": [56,69], "a": 1 }, + { "px": [176,64], "src": [224,128], "f": 0, "t": 198, "d": [56,71], "a": 1 }, + { "px": [48,80], "src": [224,128], "f": 0, "t": 198, "d": [56,78], "a": 1 }, + { "px": [176,80], "src": [224,128], "f": 0, "t": 198, "d": [56,86], "a": 1 }, + { "px": [48,96], "src": [224,128], "f": 0, "t": 198, "d": [56,93], "a": 1 }, + { "px": [80,96], "src": [224,128], "f": 0, "t": 198, "d": [56,95], "a": 1 }, + { "px": [112,96], "src": [224,128], "f": 0, "t": 198, "d": [56,97], "a": 1 }, + { "px": [176,96], "src": [224,128], "f": 0, "t": 198, "d": [56,101], "a": 1 }, + { "px": [80,112], "src": [224,128], "f": 0, "t": 198, "d": [56,110], "a": 1 }, + { "px": [112,112], "src": [224,128], "f": 0, "t": 198, "d": [56,112], "a": 1 }, + { "px": [80,128], "src": [224,128], "f": 0, "t": 198, "d": [56,125], "a": 1 }, + { "px": [112,128], "src": [224,128], "f": 0, "t": 198, "d": [56,127], "a": 1 }, + { "px": [144,128], "src": [224,128], "f": 0, "t": 198, "d": [56,129], "a": 1 }, + { "px": [208,128], "src": [224,128], "f": 0, "t": 198, "d": [56,133], "a": 1 }, + { "px": [144,144], "src": [224,128], "f": 0, "t": 198, "d": [56,144], "a": 1 }, + { "px": [208,144], "src": [224,128], "f": 0, "t": 198, "d": [56,148], "a": 1 }, + { "px": [48,160], "src": [224,128], "f": 0, "t": 198, "d": [56,153], "a": 1 }, + { "px": [144,160], "src": [224,128], "f": 0, "t": 198, "d": [56,159], "a": 1 }, + { "px": [176,160], "src": [224,128], "f": 0, "t": 198, "d": [56,161], "a": 1 }, + { "px": [208,160], "src": [224,128], "f": 0, "t": 198, "d": [56,163], "a": 1 }, + { "px": [16,192], "src": [224,128], "f": 0, "t": 198, "d": [56,181], "a": 1 }, + { "px": [80,192], "src": [224,128], "f": 0, "t": 198, "d": [56,185], "a": 1 }, + { "px": [112,192], "src": [224,128], "f": 0, "t": 198, "d": [56,187], "a": 1 }, + { "px": [176,192], "src": [224,128], "f": 0, "t": 198, "d": [56,191], "a": 1 }, + { "px": [48,224], "src": [224,128], "f": 0, "t": 198, "d": [56,213], "a": 1 }, + { "px": [144,224], "src": [224,128], "f": 0, "t": 198, "d": [56,219], "a": 1 }, + { "px": [32,16], "src": [256,96], "f": 0, "t": 154, "d": [57,17], "a": 1 }, + { "px": [96,16], "src": [256,96], "f": 0, "t": 154, "d": [57,21], "a": 1 }, + { "px": [160,16], "src": [256,96], "f": 0, "t": 154, "d": [57,25], "a": 1 }, + { "px": [192,16], "src": [256,96], "f": 0, "t": 154, "d": [57,27], "a": 1 }, + { "px": [64,48], "src": [256,96], "f": 0, "t": 154, "d": [57,49], "a": 1 }, + { "px": [128,48], "src": [256,96], "f": 0, "t": 154, "d": [57,53], "a": 1 }, + { "px": [128,80], "src": [256,96], "f": 0, "t": 154, "d": [57,83], "a": 1 }, + { "px": [224,80], "src": [256,96], "f": 0, "t": 154, "d": [57,89], "a": 1 }, + { "px": [32,112], "src": [256,96], "f": 0, "t": 154, "d": [57,107], "a": 1 }, + { "px": [160,112], "src": [256,96], "f": 0, "t": 154, "d": [57,115], "a": 1 }, + { "px": [192,112], "src": [256,96], "f": 0, "t": 154, "d": [57,117], "a": 1 }, + { "px": [0,144], "src": [256,96], "f": 0, "t": 154, "d": [57,135], "a": 1 }, + { "px": [64,144], "src": [256,96], "f": 0, "t": 154, "d": [57,139], "a": 1 }, + { "px": [96,144], "src": [256,96], "f": 0, "t": 154, "d": [57,141], "a": 1 }, + { "px": [32,176], "src": [256,96], "f": 0, "t": 154, "d": [57,167], "a": 1 }, + { "px": [96,176], "src": [256,96], "f": 0, "t": 154, "d": [57,171], "a": 1 }, + { "px": [128,176], "src": [256,96], "f": 0, "t": 154, "d": [57,173], "a": 1 }, + { "px": [192,176], "src": [256,96], "f": 0, "t": 154, "d": [57,177], "a": 1 }, + { "px": [0,208], "src": [256,96], "f": 0, "t": 154, "d": [57,195], "a": 1 }, + { "px": [64,208], "src": [256,96], "f": 0, "t": 154, "d": [57,199], "a": 1 }, + { "px": [224,208], "src": [256,96], "f": 0, "t": 154, "d": [57,209], "a": 1 }, + { "px": [144,16], "src": [224,96], "f": 0, "t": 152, "d": [58,24], "a": 1 }, + { "px": [208,48], "src": [224,96], "f": 2, "t": 152, "d": [58,58], "a": 1 }, + { "px": [16,80], "src": [224,96], "f": 2, "t": 152, "d": [58,76], "a": 1 }, + { "px": [80,80], "src": [224,96], "f": 0, "t": 152, "d": [58,80], "a": 1 }, + { "px": [208,80], "src": [224,96], "f": 0, "t": 152, "d": [58,88], "a": 1 }, + { "px": [16,112], "src": [224,96], "f": 0, "t": 152, "d": [58,106], "a": 1 }, + { "px": [16,144], "src": [224,96], "f": 1, "t": 152, "d": [58,136], "a": 1 }, + { "px": [176,144], "src": [224,96], "f": 0, "t": 152, "d": [58,146], "a": 1 }, + { "px": [112,208], "src": [224,96], "f": 2, "t": 152, "d": [58,202], "a": 1 }, + { "px": [144,208], "src": [224,96], "f": 0, "t": 152, "d": [58,204], "a": 1 }, + { "px": [176,208], "src": [224,96], "f": 2, "t": 152, "d": [58,206], "a": 1 }, + { "px": [208,208], "src": [224,96], "f": 0, "t": 152, "d": [58,208], "a": 1 }, + { "px": [16,16], "src": [0,304], "f": 3, "t": 437, "d": [59,16], "a": 1 }, + { "px": [48,16], "src": [0,304], "f": 0, "t": 437, "d": [59,18], "a": 1 }, + { "px": [80,16], "src": [0,304], "f": 3, "t": 437, "d": [59,20], "a": 1 }, + { "px": [112,16], "src": [0,304], "f": 2, "t": 437, "d": [59,22], "a": 1 }, + { "px": [176,16], "src": [0,304], "f": 2, "t": 437, "d": [59,26], "a": 1 }, + { "px": [208,16], "src": [0,304], "f": 2, "t": 437, "d": [59,28], "a": 1 }, + { "px": [48,48], "src": [0,304], "f": 3, "t": 437, "d": [59,48], "a": 1 }, + { "px": [80,48], "src": [0,304], "f": 0, "t": 437, "d": [59,50], "a": 1 }, + { "px": [112,48], "src": [0,304], "f": 1, "t": 437, "d": [59,52], "a": 1 }, + { "px": [144,48], "src": [0,304], "f": 2, "t": 437, "d": [59,54], "a": 1 }, + { "px": [112,80], "src": [0,304], "f": 3, "t": 437, "d": [59,82], "a": 1 }, + { "px": [144,80], "src": [0,304], "f": 0, "t": 437, "d": [59,84], "a": 1 }, + { "px": [48,112], "src": [0,304], "f": 0, "t": 437, "d": [59,108], "a": 1 }, + { "px": [144,112], "src": [0,304], "f": 3, "t": 437, "d": [59,114], "a": 1 }, + { "px": [176,112], "src": [0,304], "f": 0, "t": 437, "d": [59,116], "a": 1 }, + { "px": [208,112], "src": [0,304], "f": 2, "t": 437, "d": [59,118], "a": 1 }, + { "px": [48,144], "src": [0,304], "f": 3, "t": 437, "d": [59,138], "a": 1 }, + { "px": [80,144], "src": [0,304], "f": 0, "t": 437, "d": [59,140], "a": 1 }, + { "px": [112,144], "src": [0,304], "f": 0, "t": 437, "d": [59,142], "a": 1 }, + { "px": [16,176], "src": [0,304], "f": 3, "t": 437, "d": [59,166], "a": 1 }, + { "px": [48,176], "src": [0,304], "f": 0, "t": 437, "d": [59,168], "a": 1 }, + { "px": [80,176], "src": [0,304], "f": 3, "t": 437, "d": [59,170], "a": 1 }, + { "px": [112,176], "src": [0,304], "f": 2, "t": 437, "d": [59,172], "a": 1 }, + { "px": [144,176], "src": [0,304], "f": 0, "t": 437, "d": [59,174], "a": 1 }, + { "px": [176,176], "src": [0,304], "f": 1, "t": 437, "d": [59,176], "a": 1 }, + { "px": [208,176], "src": [0,304], "f": 0, "t": 437, "d": [59,178], "a": 1 }, + { "px": [16,208], "src": [0,304], "f": 0, "t": 437, "d": [59,196], "a": 1 }, + { "px": [48,208], "src": [0,304], "f": 3, "t": 437, "d": [59,198], "a": 1 }, + { "px": [80,208], "src": [0,304], "f": 0, "t": 437, "d": [59,200], "a": 1 } + ], + "seed": 3275063, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [] + } + ], + "__neighbours": [] + }, + { + "identifier": "Level_3", + "iid": "ed46e220-8990-11ee-9d82-9f8809be02fe", + "uid": 67, + "worldX": -1, + "worldY": -1, + "worldDepth": 0, + "pxWid": 320, + "pxHei": 208, + "__bgColor": "#696A79", + "bgColor": null, + "useAutoIdentifier": true, + "bgRelPath": null, + "bgPos": null, + "bgPivotX": 0.5, + "bgPivotY": 0.5, + "__smartColor": "#ADADB5", + "__bgPos": null, + "externalRelPath": null, + "fieldInstances": [], + "layerInstances": [ + { + "__identifier": "Entities", + "__type": "Entities", + "__cWid": 20, + "__cHei": 13, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": null, + "__tilesetRelPath": null, + "iid": "ed46e221-8990-11ee-9d82-f1591789ff15", + "levelId": 67, + "layerDefUid": 60, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [], + "autoLayerTiles": [], + "seed": 8110233, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [ + { + "__identifier": "Player", + "__grid": [9,6], + "__pivot": [0,0], + "__tags": [], + "__tile": { "tilesetUid": 3, "x": 0, "y": 0, "w": 32, "h": 32 }, + "__smartColor": "#BE4A2F", + "__worldX": 944, + "__worldY": 96, + "iid": "2760d880-8990-11ee-9d82-d960c095a886", + "width": 16, + "height": 16, + "defUid": 62, + "px": [144,96], + "fieldInstances": [] + } + ] + }, + { + "__identifier": "Walls", + "__type": "IntGrid", + "__cWid": 20, + "__cHei": 13, + "__gridSize": 16, + "__opacity": 1, + "__pxTotalOffsetX": 0, + "__pxTotalOffsetY": 0, + "__tilesetDefUid": 4, + "__tilesetRelPath": "atlas/SunnyLand_by_Ansimuz-extended.png", + "iid": "ed46e222-8990-11ee-9d82-77bd202b92c3", + "levelId": 67, + "layerDefUid": 7, + "pxOffsetX": 0, + "pxOffsetY": 0, + "visible": true, + "optionalRules": [], + "intGridCsv": [ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1,1,1, + 0,1,1,1,0,0,1,0,0,0,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,1,0,1,0,0,1,1,1,0, + 1,0,1,0,1,0,1,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,0,0,0,1,1,1, + 0,1,0,1,0,1,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,0,1,0,1,0,1,1,1,0,1,1,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,0,0,0,1, + 0,1,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,0,0,1,1,0,0,0,0,0,0,1,0,1,0,1,0,1,0, + 1,0,0,0,1,0,1,0,0,0,0,0,1,1,1,0,0,1,0,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ], + "autoLayerTiles": [ + { "px": [0,0], "src": [320,272], "f": 0, "t": 411, "d": [52,0], "a": 1 }, + { "px": [16,0], "src": [320,272], "f": 0, "t": 411, "d": [52,1], "a": 1 }, + { "px": [32,0], "src": [320,272], "f": 0, "t": 411, "d": [52,2], "a": 1 }, + { "px": [48,0], "src": [320,272], "f": 0, "t": 411, "d": [52,3], "a": 1 }, + { "px": [64,0], "src": [320,272], "f": 0, "t": 411, "d": [52,4], "a": 1 }, + { "px": [80,0], "src": [320,272], "f": 0, "t": 411, "d": [52,5], "a": 1 }, + { "px": [96,0], "src": [320,272], "f": 0, "t": 411, "d": [52,6], "a": 1 }, + { "px": [112,0], "src": [320,272], "f": 0, "t": 411, "d": [52,7], "a": 1 }, + { "px": [128,0], "src": [320,272], "f": 0, "t": 411, "d": [52,8], "a": 1 }, + { "px": [144,0], "src": [320,272], "f": 0, "t": 411, "d": [52,9], "a": 1 }, + { "px": [160,0], "src": [320,272], "f": 0, "t": 411, "d": [52,10], "a": 1 }, + { "px": [176,0], "src": [320,272], "f": 0, "t": 411, "d": [52,11], "a": 1 }, + { "px": [192,0], "src": [320,272], "f": 0, "t": 411, "d": [52,12], "a": 1 }, + { "px": [208,0], "src": [320,272], "f": 0, "t": 411, "d": [52,13], "a": 1 }, + { "px": [224,0], "src": [320,272], "f": 0, "t": 411, "d": [52,14], "a": 1 }, + { "px": [240,0], "src": [320,272], "f": 0, "t": 411, "d": [52,15], "a": 1 }, + { "px": [256,0], "src": [320,272], "f": 0, "t": 411, "d": [52,16], "a": 1 }, + { "px": [272,0], "src": [320,272], "f": 0, "t": 411, "d": [52,17], "a": 1 }, + { "px": [288,0], "src": [320,272], "f": 0, "t": 411, "d": [52,18], "a": 1 }, + { "px": [304,0], "src": [320,272], "f": 0, "t": 411, "d": [52,19], "a": 1 }, + { "px": [0,16], "src": [320,272], "f": 0, "t": 411, "d": [52,20], "a": 1 }, + { "px": [16,16], "src": [320,272], "f": 0, "t": 411, "d": [52,21], "a": 1 }, + { "px": [80,16], "src": [320,272], "f": 0, "t": 411, "d": [52,25], "a": 1 }, + { "px": [144,16], "src": [320,272], "f": 0, "t": 411, "d": [52,29], "a": 1 }, + { "px": [240,16], "src": [320,272], "f": 0, "t": 411, "d": [52,35], "a": 1 }, + { "px": [304,16], "src": [320,272], "f": 0, "t": 411, "d": [52,39], "a": 1 }, + { "px": [0,32], "src": [320,272], "f": 0, "t": 411, "d": [52,40], "a": 1 }, + { "px": [32,32], "src": [320,272], "f": 0, "t": 411, "d": [52,42], "a": 1 }, + { "px": [48,32], "src": [320,272], "f": 0, "t": 411, "d": [52,43], "a": 1 }, + { "px": [64,32], "src": [320,272], "f": 0, "t": 411, "d": [52,44], "a": 1 }, + { "px": [80,32], "src": [320,272], "f": 0, "t": 411, "d": [52,45], "a": 1 }, + { "px": [112,32], "src": [320,272], "f": 0, "t": 411, "d": [52,47], "a": 1 }, + { "px": [144,32], "src": [320,272], "f": 0, "t": 411, "d": [52,49], "a": 1 }, + { "px": [176,32], "src": [320,272], "f": 0, "t": 411, "d": [52,51], "a": 1 }, + { "px": [208,32], "src": [320,272], "f": 0, "t": 411, "d": [52,53], "a": 1 }, + { "px": [240,32], "src": [320,272], "f": 0, "t": 411, "d": [52,55], "a": 1 }, + { "px": [272,32], "src": [320,272], "f": 0, "t": 411, "d": [52,57], "a": 1 }, + { "px": [288,32], "src": [320,272], "f": 0, "t": 411, "d": [52,58], "a": 1 }, + { "px": [304,32], "src": [320,272], "f": 0, "t": 411, "d": [52,59], "a": 1 }, + { "px": [0,48], "src": [320,272], "f": 0, "t": 411, "d": [52,60], "a": 1 }, + { "px": [32,48], "src": [320,272], "f": 0, "t": 411, "d": [52,62], "a": 1 }, + { "px": [64,48], "src": [320,272], "f": 0, "t": 411, "d": [52,64], "a": 1 }, + { "px": [80,48], "src": [320,272], "f": 0, "t": 411, "d": [52,65], "a": 1 }, + { "px": [144,48], "src": [320,272], "f": 0, "t": 411, "d": [52,69], "a": 1 }, + { "px": [176,48], "src": [320,272], "f": 0, "t": 411, "d": [52,71], "a": 1 }, + { "px": [208,48], "src": [320,272], "f": 0, "t": 411, "d": [52,73], "a": 1 }, + { "px": [240,48], "src": [320,272], "f": 0, "t": 411, "d": [52,75], "a": 1 }, + { "px": [288,48], "src": [320,272], "f": 0, "t": 411, "d": [52,78], "a": 1 }, + { "px": [304,48], "src": [320,272], "f": 0, "t": 411, "d": [52,79], "a": 1 }, + { "px": [0,64], "src": [320,272], "f": 0, "t": 411, "d": [52,80], "a": 1 }, + { "px": [32,64], "src": [320,272], "f": 0, "t": 411, "d": [52,82], "a": 1 }, + { "px": [48,64], "src": [320,272], "f": 0, "t": 411, "d": [52,83], "a": 1 }, + { "px": [80,64], "src": [320,272], "f": 0, "t": 411, "d": [52,85], "a": 1 }, + { "px": [112,64], "src": [320,272], "f": 0, "t": 411, "d": [52,87], "a": 1 }, + { "px": [144,64], "src": [320,272], "f": 0, "t": 411, "d": [52,89], "a": 1 }, + { "px": [176,64], "src": [320,272], "f": 0, "t": 411, "d": [52,91], "a": 1 }, + { "px": [208,64], "src": [320,272], "f": 0, "t": 411, "d": [52,93], "a": 1 }, + { "px": [240,64], "src": [320,272], "f": 0, "t": 411, "d": [52,95], "a": 1 }, + { "px": [272,64], "src": [320,272], "f": 0, "t": 411, "d": [52,97], "a": 1 }, + { "px": [288,64], "src": [320,272], "f": 0, "t": 411, "d": [52,98], "a": 1 }, + { "px": [304,64], "src": [320,272], "f": 0, "t": 411, "d": [52,99], "a": 1 }, + { "px": [0,80], "src": [320,272], "f": 0, "t": 411, "d": [52,100], "a": 1 }, + { "px": [16,80], "src": [320,272], "f": 0, "t": 411, "d": [52,101], "a": 1 }, + { "px": [80,80], "src": [320,272], "f": 0, "t": 411, "d": [52,105], "a": 1 }, + { "px": [112,80], "src": [320,272], "f": 0, "t": 411, "d": [52,107], "a": 1 }, + { "px": [144,80], "src": [320,272], "f": 0, "t": 411, "d": [52,109], "a": 1 }, + { "px": [176,80], "src": [320,272], "f": 0, "t": 411, "d": [52,111], "a": 1 }, + { "px": [208,80], "src": [320,272], "f": 0, "t": 411, "d": [52,113], "a": 1 }, + { "px": [240,80], "src": [320,272], "f": 0, "t": 411, "d": [52,115], "a": 1 }, + { "px": [304,80], "src": [320,272], "f": 0, "t": 411, "d": [52,119], "a": 1 }, + { "px": [0,96], "src": [320,272], "f": 0, "t": 411, "d": [52,120], "a": 1 }, + { "px": [16,96], "src": [320,272], "f": 0, "t": 411, "d": [52,121], "a": 1 }, + { "px": [32,96], "src": [320,272], "f": 0, "t": 411, "d": [52,122], "a": 1 }, + { "px": [48,96], "src": [320,272], "f": 0, "t": 411, "d": [52,123], "a": 1 }, + { "px": [64,96], "src": [320,272], "f": 0, "t": 411, "d": [52,124], "a": 1 }, + { "px": [80,96], "src": [320,272], "f": 0, "t": 411, "d": [52,125], "a": 1 }, + { "px": [96,96], "src": [320,272], "f": 0, "t": 411, "d": [52,126], "a": 1 }, + { "px": [112,96], "src": [320,272], "f": 0, "t": 411, "d": [52,127], "a": 1 }, + { "px": [128,96], "src": [320,272], "f": 0, "t": 411, "d": [52,128], "a": 1 }, + { "px": [144,96], "src": [320,272], "f": 0, "t": 411, "d": [52,129], "a": 1 }, + { "px": [160,96], "src": [320,272], "f": 0, "t": 411, "d": [52,130], "a": 1 }, + { "px": [176,96], "src": [320,272], "f": 0, "t": 411, "d": [52,131], "a": 1 }, + { "px": [192,96], "src": [320,272], "f": 0, "t": 411, "d": [52,132], "a": 1 }, + { "px": [208,96], "src": [320,272], "f": 0, "t": 411, "d": [52,133], "a": 1 }, + { "px": [224,96], "src": [320,272], "f": 0, "t": 411, "d": [52,134], "a": 1 }, + { "px": [240,96], "src": [320,272], "f": 0, "t": 411, "d": [52,135], "a": 1 }, + { "px": [256,96], "src": [320,272], "f": 0, "t": 411, "d": [52,136], "a": 1 }, + { "px": [272,96], "src": [320,272], "f": 0, "t": 411, "d": [52,137], "a": 1 }, + { "px": [288,96], "src": [320,272], "f": 0, "t": 411, "d": [52,138], "a": 1 }, + { "px": [304,96], "src": [320,272], "f": 0, "t": 411, "d": [52,139], "a": 1 }, + { "px": [0,112], "src": [320,272], "f": 0, "t": 411, "d": [52,140], "a": 1 }, + { "px": [16,112], "src": [320,272], "f": 0, "t": 411, "d": [52,141], "a": 1 }, + { "px": [80,112], "src": [320,272], "f": 0, "t": 411, "d": [52,145], "a": 1 }, + { "px": [112,112], "src": [320,272], "f": 0, "t": 411, "d": [52,147], "a": 1 }, + { "px": [144,112], "src": [320,272], "f": 0, "t": 411, "d": [52,149], "a": 1 }, + { "px": [208,112], "src": [320,272], "f": 0, "t": 411, "d": [52,153], "a": 1 }, + { "px": [272,112], "src": [320,272], "f": 0, "t": 411, "d": [52,157], "a": 1 }, + { "px": [288,112], "src": [320,272], "f": 0, "t": 411, "d": [52,158], "a": 1 }, + { "px": [304,112], "src": [320,272], "f": 0, "t": 411, "d": [52,159], "a": 1 }, + { "px": [0,128], "src": [320,272], "f": 0, "t": 411, "d": [52,160], "a": 1 }, + { "px": [16,128], "src": [320,272], "f": 0, "t": 411, "d": [52,161], "a": 1 }, + { "px": [48,128], "src": [320,272], "f": 0, "t": 411, "d": [52,163], "a": 1 }, + { "px": [80,128], "src": [320,272], "f": 0, "t": 411, "d": [52,165], "a": 1 }, + { "px": [112,128], "src": [320,272], "f": 0, "t": 411, "d": [52,167], "a": 1 }, + { "px": [144,128], "src": [320,272], "f": 0, "t": 411, "d": [52,169], "a": 1 }, + { "px": [176,128], "src": [320,272], "f": 0, "t": 411, "d": [52,171], "a": 1 }, + { "px": [192,128], "src": [320,272], "f": 0, "t": 411, "d": [52,172], "a": 1 }, + { "px": [208,128], "src": [320,272], "f": 0, "t": 411, "d": [52,173], "a": 1 }, + { "px": [240,128], "src": [320,272], "f": 0, "t": 411, "d": [52,175], "a": 1 }, + { "px": [272,128], "src": [320,272], "f": 0, "t": 411, "d": [52,177], "a": 1 }, + { "px": [288,128], "src": [320,272], "f": 0, "t": 411, "d": [52,178], "a": 1 }, + { "px": [304,128], "src": [320,272], "f": 0, "t": 411, "d": [52,179], "a": 1 }, + { "px": [0,144], "src": [320,272], "f": 0, "t": 411, "d": [52,180], "a": 1 }, + { "px": [16,144], "src": [320,272], "f": 0, "t": 411, "d": [52,181], "a": 1 }, + { "px": [48,144], "src": [320,272], "f": 0, "t": 411, "d": [52,183], "a": 1 }, + { "px": [80,144], "src": [320,272], "f": 0, "t": 411, "d": [52,185], "a": 1 }, + { "px": [112,144], "src": [320,272], "f": 0, "t": 411, "d": [52,187], "a": 1 }, + { "px": [144,144], "src": [320,272], "f": 0, "t": 411, "d": [52,189], "a": 1 }, + { "px": [192,144], "src": [320,272], "f": 0, "t": 411, "d": [52,192], "a": 1 }, + { "px": [208,144], "src": [320,272], "f": 0, "t": 411, "d": [52,193], "a": 1 }, + { "px": [256,144], "src": [320,272], "f": 0, "t": 411, "d": [52,196], "a": 1 }, + { "px": [272,144], "src": [320,272], "f": 0, "t": 411, "d": [52,197], "a": 1 }, + { "px": [288,144], "src": [320,272], "f": 0, "t": 411, "d": [52,198], "a": 1 }, + { "px": [304,144], "src": [320,272], "f": 0, "t": 411, "d": [52,199], "a": 1 }, + { "px": [0,160], "src": [320,272], "f": 0, "t": 411, "d": [52,200], "a": 1 }, + { "px": [16,160], "src": [320,272], "f": 0, "t": 411, "d": [52,201], "a": 1 }, + { "px": [48,160], "src": [320,272], "f": 0, "t": 411, "d": [52,203], "a": 1 }, + { "px": [80,160], "src": [320,272], "f": 0, "t": 411, "d": [52,205], "a": 1 }, + { "px": [112,160], "src": [320,272], "f": 0, "t": 411, "d": [52,207], "a": 1 }, + { "px": [144,160], "src": [320,272], "f": 0, "t": 411, "d": [52,209], "a": 1 }, + { "px": [176,160], "src": [320,272], "f": 0, "t": 411, "d": [52,211], "a": 1 }, + { "px": [192,160], "src": [320,272], "f": 0, "t": 411, "d": [52,212], "a": 1 }, + { "px": [208,160], "src": [320,272], "f": 0, "t": 411, "d": [52,213], "a": 1 }, + { "px": [240,160], "src": [320,272], "f": 0, "t": 411, "d": [52,215], "a": 1 }, + { "px": [272,160], "src": [320,272], "f": 0, "t": 411, "d": [52,217], "a": 1 }, + { "px": [288,160], "src": [320,272], "f": 0, "t": 411, "d": [52,218], "a": 1 }, + { "px": [304,160], "src": [320,272], "f": 0, "t": 411, "d": [52,219], "a": 1 }, + { "px": [0,176], "src": [320,272], "f": 0, "t": 411, "d": [52,220], "a": 1 }, + { "px": [16,176], "src": [320,272], "f": 0, "t": 411, "d": [52,221], "a": 1 }, + { "px": [80,176], "src": [320,272], "f": 0, "t": 411, "d": [52,225], "a": 1 }, + { "px": [96,176], "src": [320,272], "f": 0, "t": 411, "d": [52,226], "a": 1 }, + { "px": [128,176], "src": [320,272], "f": 0, "t": 411, "d": [52,228], "a": 1 }, + { "px": [144,176], "src": [320,272], "f": 0, "t": 411, "d": [52,229], "a": 1 }, + { "px": [208,176], "src": [320,272], "f": 0, "t": 411, "d": [52,233], "a": 1 }, + { "px": [240,176], "src": [320,272], "f": 0, "t": 411, "d": [52,235], "a": 1 }, + { "px": [272,176], "src": [320,272], "f": 0, "t": 411, "d": [52,237], "a": 1 }, + { "px": [288,176], "src": [320,272], "f": 0, "t": 411, "d": [52,238], "a": 1 }, + { "px": [304,176], "src": [320,272], "f": 0, "t": 411, "d": [52,239], "a": 1 }, + { "px": [0,192], "src": [320,272], "f": 0, "t": 411, "d": [52,240], "a": 1 }, + { "px": [16,192], "src": [320,272], "f": 0, "t": 411, "d": [52,241], "a": 1 }, + { "px": [32,192], "src": [320,272], "f": 0, "t": 411, "d": [52,242], "a": 1 }, + { "px": [48,192], "src": [320,272], "f": 0, "t": 411, "d": [52,243], "a": 1 }, + { "px": [64,192], "src": [320,272], "f": 0, "t": 411, "d": [52,244], "a": 1 }, + { "px": [80,192], "src": [320,272], "f": 0, "t": 411, "d": [52,245], "a": 1 }, + { "px": [96,192], "src": [320,272], "f": 0, "t": 411, "d": [52,246], "a": 1 }, + { "px": [112,192], "src": [320,272], "f": 0, "t": 411, "d": [52,247], "a": 1 }, + { "px": [128,192], "src": [320,272], "f": 0, "t": 411, "d": [52,248], "a": 1 }, + { "px": [144,192], "src": [320,272], "f": 0, "t": 411, "d": [52,249], "a": 1 }, + { "px": [160,192], "src": [320,272], "f": 0, "t": 411, "d": [52,250], "a": 1 }, + { "px": [176,192], "src": [320,272], "f": 0, "t": 411, "d": [52,251], "a": 1 }, + { "px": [192,192], "src": [320,272], "f": 0, "t": 411, "d": [52,252], "a": 1 }, + { "px": [208,192], "src": [320,272], "f": 0, "t": 411, "d": [52,253], "a": 1 }, + { "px": [224,192], "src": [320,272], "f": 0, "t": 411, "d": [52,254], "a": 1 }, + { "px": [240,192], "src": [320,272], "f": 0, "t": 411, "d": [52,255], "a": 1 }, + { "px": [256,192], "src": [320,272], "f": 0, "t": 411, "d": [52,256], "a": 1 }, + { "px": [272,192], "src": [320,272], "f": 0, "t": 411, "d": [52,257], "a": 1 }, + { "px": [288,192], "src": [320,272], "f": 0, "t": 411, "d": [52,258], "a": 1 }, + { "px": [304,192], "src": [320,272], "f": 0, "t": 411, "d": [52,259], "a": 1 }, + { "px": [96,32], "src": [224,128], "f": 0, "t": 198, "d": [56,46], "a": 1 }, + { "px": [128,32], "src": [224,128], "f": 0, "t": 198, "d": [56,48], "a": 1 }, + { "px": [160,32], "src": [224,128], "f": 0, "t": 198, "d": [56,50], "a": 1 }, + { "px": [192,32], "src": [224,128], "f": 0, "t": 198, "d": [56,52], "a": 1 }, + { "px": [224,32], "src": [224,128], "f": 0, "t": 198, "d": [56,54], "a": 1 }, + { "px": [256,32], "src": [224,128], "f": 0, "t": 198, "d": [56,56], "a": 1 }, + { "px": [16,48], "src": [224,128], "f": 0, "t": 198, "d": [56,61], "a": 1 }, + { "px": [160,48], "src": [224,128], "f": 0, "t": 198, "d": [56,70], "a": 1 }, + { "px": [192,48], "src": [224,128], "f": 0, "t": 198, "d": [56,72], "a": 1 }, + { "px": [224,48], "src": [224,128], "f": 0, "t": 198, "d": [56,74], "a": 1 }, + { "px": [96,64], "src": [224,128], "f": 0, "t": 198, "d": [56,86], "a": 1 }, + { "px": [128,64], "src": [224,128], "f": 0, "t": 198, "d": [56,88], "a": 1 }, + { "px": [160,64], "src": [224,128], "f": 0, "t": 198, "d": [56,90], "a": 1 }, + { "px": [192,64], "src": [224,128], "f": 0, "t": 198, "d": [56,92], "a": 1 }, + { "px": [224,64], "src": [224,128], "f": 0, "t": 198, "d": [56,94], "a": 1 }, + { "px": [256,64], "src": [224,128], "f": 0, "t": 198, "d": [56,96], "a": 1 }, + { "px": [32,128], "src": [224,128], "f": 0, "t": 198, "d": [56,162], "a": 1 }, + { "px": [64,128], "src": [224,128], "f": 0, "t": 198, "d": [56,164], "a": 1 }, + { "px": [96,128], "src": [224,128], "f": 0, "t": 198, "d": [56,166], "a": 1 }, + { "px": [128,128], "src": [224,128], "f": 0, "t": 198, "d": [56,168], "a": 1 }, + { "px": [160,128], "src": [224,128], "f": 0, "t": 198, "d": [56,170], "a": 1 }, + { "px": [224,128], "src": [224,128], "f": 0, "t": 198, "d": [56,174], "a": 1 }, + { "px": [32,144], "src": [224,128], "f": 0, "t": 198, "d": [56,182], "a": 1 }, + { "px": [64,144], "src": [224,128], "f": 0, "t": 198, "d": [56,184], "a": 1 }, + { "px": [96,144], "src": [224,128], "f": 0, "t": 198, "d": [56,186], "a": 1 }, + { "px": [128,144], "src": [224,128], "f": 0, "t": 198, "d": [56,188], "a": 1 }, + { "px": [32,160], "src": [224,128], "f": 0, "t": 198, "d": [56,202], "a": 1 }, + { "px": [64,160], "src": [224,128], "f": 0, "t": 198, "d": [56,204], "a": 1 }, + { "px": [160,160], "src": [224,128], "f": 0, "t": 198, "d": [56,210], "a": 1 }, + { "px": [224,160], "src": [224,128], "f": 0, "t": 198, "d": [56,214], "a": 1 }, + { "px": [48,16], "src": [256,96], "f": 0, "t": 154, "d": [57,23], "a": 1 }, + { "px": [112,16], "src": [256,96], "f": 0, "t": 154, "d": [57,27], "a": 1 }, + { "px": [176,16], "src": [256,96], "f": 0, "t": 154, "d": [57,31], "a": 1 }, + { "px": [208,16], "src": [256,96], "f": 0, "t": 154, "d": [57,33], "a": 1 }, + { "px": [272,16], "src": [256,96], "f": 0, "t": 154, "d": [57,37], "a": 1 }, + { "px": [112,48], "src": [256,96], "f": 0, "t": 154, "d": [57,67], "a": 1 }, + { "px": [48,80], "src": [256,96], "f": 0, "t": 154, "d": [57,103], "a": 1 }, + { "px": [272,80], "src": [256,96], "f": 0, "t": 154, "d": [57,117], "a": 1 }, + { "px": [48,112], "src": [256,96], "f": 0, "t": 154, "d": [57,143], "a": 1 }, + { "px": [176,112], "src": [256,96], "f": 0, "t": 154, "d": [57,151], "a": 1 }, + { "px": [240,112], "src": [256,96], "f": 0, "t": 154, "d": [57,155], "a": 1 }, + { "px": [48,176], "src": [256,96], "f": 0, "t": 154, "d": [57,223], "a": 1 }, + { "px": [176,176], "src": [256,96], "f": 0, "t": 154, "d": [57,231], "a": 1 }, + { "px": [32,16], "src": [224,96], "f": 0, "t": 152, "d": [58,22], "a": 1 }, + { "px": [64,16], "src": [224,96], "f": 1, "t": 152, "d": [58,24], "a": 1 }, + { "px": [288,16], "src": [224,96], "f": 1, "t": 152, "d": [58,38], "a": 1 }, + { "px": [16,32], "src": [224,96], "f": 0, "t": 152, "d": [58,41], "a": 1 }, + { "px": [48,48], "src": [224,96], "f": 0, "t": 152, "d": [58,63], "a": 1 }, + { "px": [272,48], "src": [224,96], "f": 1, "t": 152, "d": [58,77], "a": 1 }, + { "px": [16,64], "src": [224,96], "f": 2, "t": 152, "d": [58,81], "a": 1 }, + { "px": [64,64], "src": [224,96], "f": 0, "t": 152, "d": [58,84], "a": 1 }, + { "px": [32,80], "src": [224,96], "f": 0, "t": 152, "d": [58,102], "a": 1 }, + { "px": [96,80], "src": [224,96], "f": 2, "t": 152, "d": [58,106], "a": 1 }, + { "px": [128,80], "src": [224,96], "f": 2, "t": 152, "d": [58,108], "a": 1 }, + { "px": [160,80], "src": [224,96], "f": 2, "t": 152, "d": [58,110], "a": 1 }, + { "px": [192,80], "src": [224,96], "f": 2, "t": 152, "d": [58,112], "a": 1 }, + { "px": [224,80], "src": [224,96], "f": 2, "t": 152, "d": [58,114], "a": 1 }, + { "px": [288,80], "src": [224,96], "f": 1, "t": 152, "d": [58,118], "a": 1 }, + { "px": [96,112], "src": [224,96], "f": 0, "t": 152, "d": [58,146], "a": 1 }, + { "px": [128,112], "src": [224,96], "f": 0, "t": 152, "d": [58,148], "a": 1 }, + { "px": [192,112], "src": [224,96], "f": 1, "t": 152, "d": [58,152], "a": 1 }, + { "px": [256,128], "src": [224,96], "f": 2, "t": 152, "d": [58,176], "a": 1 }, + { "px": [176,144], "src": [224,96], "f": 1, "t": 152, "d": [58,191], "a": 1 }, + { "px": [240,144], "src": [224,96], "f": 1, "t": 152, "d": [58,195], "a": 1 }, + { "px": [96,160], "src": [224,96], "f": 2, "t": 152, "d": [58,206], "a": 1 }, + { "px": [128,160], "src": [224,96], "f": 2, "t": 152, "d": [58,208], "a": 1 }, + { "px": [256,160], "src": [224,96], "f": 0, "t": 152, "d": [58,216], "a": 1 }, + { "px": [112,176], "src": [224,96], "f": 0, "t": 152, "d": [58,227], "a": 1 }, + { "px": [192,176], "src": [224,96], "f": 1, "t": 152, "d": [58,232], "a": 1 }, + { "px": [224,176], "src": [224,96], "f": 2, "t": 152, "d": [58,234], "a": 1 }, + { "px": [256,176], "src": [224,96], "f": 2, "t": 152, "d": [58,236], "a": 1 }, + { "px": [96,16], "src": [0,304], "f": 3, "t": 437, "d": [59,26], "a": 1 }, + { "px": [128,16], "src": [0,304], "f": 2, "t": 437, "d": [59,28], "a": 1 }, + { "px": [160,16], "src": [0,304], "f": 3, "t": 437, "d": [59,30], "a": 1 }, + { "px": [192,16], "src": [0,304], "f": 2, "t": 437, "d": [59,32], "a": 1 }, + { "px": [224,16], "src": [0,304], "f": 2, "t": 437, "d": [59,34], "a": 1 }, + { "px": [256,16], "src": [0,304], "f": 3, "t": 437, "d": [59,36], "a": 1 }, + { "px": [96,48], "src": [0,304], "f": 1, "t": 437, "d": [59,66], "a": 1 }, + { "px": [128,48], "src": [0,304], "f": 0, "t": 437, "d": [59,68], "a": 1 }, + { "px": [256,48], "src": [0,304], "f": 1, "t": 437, "d": [59,76], "a": 1 }, + { "px": [64,80], "src": [0,304], "f": 0, "t": 437, "d": [59,104], "a": 1 }, + { "px": [256,80], "src": [0,304], "f": 1, "t": 437, "d": [59,116], "a": 1 }, + { "px": [32,112], "src": [0,304], "f": 3, "t": 437, "d": [59,142], "a": 1 }, + { "px": [64,112], "src": [0,304], "f": 2, "t": 437, "d": [59,144], "a": 1 }, + { "px": [160,112], "src": [0,304], "f": 3, "t": 437, "d": [59,150], "a": 1 }, + { "px": [224,112], "src": [0,304], "f": 3, "t": 437, "d": [59,154], "a": 1 }, + { "px": [256,112], "src": [0,304], "f": 2, "t": 437, "d": [59,156], "a": 1 }, + { "px": [160,144], "src": [0,304], "f": 1, "t": 437, "d": [59,190], "a": 1 }, + { "px": [224,144], "src": [0,304], "f": 1, "t": 437, "d": [59,194], "a": 1 }, + { "px": [32,176], "src": [0,304], "f": 1, "t": 437, "d": [59,222], "a": 1 }, + { "px": [64,176], "src": [0,304], "f": 0, "t": 437, "d": [59,224], "a": 1 }, + { "px": [160,176], "src": [0,304], "f": 1, "t": 437, "d": [59,230], "a": 1 } + ], + "seed": 2710914, + "overrideTilesetUid": null, + "gridTiles": [], + "entityInstances": [] + } + ], + "__neighbours": [] + } + ], + "worlds": [], + "dummyWorldIid": "96b76b90-6280-11ee-9465-b1de1cebcc94" +} \ No newline at end of file diff --git a/book/src/README.md b/book/src/README.md index 95a56eeb..951970be 100644 --- a/book/src/README.md +++ b/book/src/README.md @@ -26,7 +26,7 @@ Deployment of this book to github pages is also performed by `bevy_ecs_ldtk`'s C Splitting the documentation up this way means that this book is not necessarily meant to be read in order. Some chapters are intended to be read while working on your own project, while others are meant to be more like studying material. The following chapters are good jumping-off points for beginners: -- [*Getting Started* tutorial](getting-started.md) +- [*Tile-based Game* tutorial](tutorials/tile-based-game/index.html) - [*Game Logic Integration* explanation]() ## Other resources diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 8637474c..00c85dd1 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -2,8 +2,10 @@ [Introduction](README.md) # Tutorials -- [Getting Started](tutorials/getting-started.md) -- [Sokoban]() +- [Tile-based Game](tutorials/tile-based-game/README.md) + - [Create your LDtk project](tutorials/tile-based-game/create-your-ldtk-project.md) + - [Spawn your LDtk project in Bevy](tutorials/tile-based-game/spawn-your-ldtk-project-in-bevy.md) + - [Add gameplay to your project](tutorials/tile-based-game/add-gameplay-to-your-project.md) - [Platformer]() # Explanation - [Game Logic Integration]() diff --git a/book/src/tutorials/getting-started.md b/book/src/tutorials/getting-started.md deleted file mode 100644 index bd0f1df7..00000000 --- a/book/src/tutorials/getting-started.md +++ /dev/null @@ -1,28 +0,0 @@ -# Getting Started - -The goal of this plugin is to make it as easy as possible to use LDtk with Bevy -for common use cases, while providing solutions to handle more difficult cases. -You only need a few things to get started: -1. Add the `LdtkPlugin` to the `App` -2. Insert the `LevelSelection` resource into the `App` to pick your level -3. Spawn an `LdtkWorldBundle` -4. Optionally, use `#[derive(LdtkEntity)]` and `#[derive(LdtkIntCell)]` on - bundles and register them to the `App` to automatically spawn those bundles - on Entity and IntGrid layers. - -```rust,no_run -{{ #include ../../../examples/basic.rs }} -``` - -There are other attributes available to `#[derive(LdtkEntity)]` and `#[derive(LdtkIntCell)]`, see the documentation for more details. - -By default, LDtk Entities and IntGrid tiles get spawned with `EntityInstance` -and `IntGridCell` components respectfully. -So, you can flesh out these entities in a system that queries for -`Added` or `Added` if you need more access to the -world, or if you just don't want to use the `LdtkEntity` and `LdtkIntCell` -traits. - -To load a new level, you can just update the `LevelSelection` resource. -Be sure to check out the `LdtkSettings` resource and the `LevelSet` component -for additional level-loading options. diff --git a/book/src/tutorials/tile-based-game/README.md b/book/src/tutorials/tile-based-game/README.md new file mode 100644 index 00000000..13aa9526 --- /dev/null +++ b/book/src/tutorials/tile-based-game/README.md @@ -0,0 +1,21 @@ +# Tile-based Game +In this tutorial you will make a tile-based game with LDtk levels. +Game entities will be locked to a grid of tiles like sokoban, or snake. +You will go through the process of creating an LDtk project, loading the project into bevy, and adding gameplay. + +This tutorial does have an example associated with it in the [`bevy_ecs_ldtk` repository](https://github.com/trouv/bevy_ecs_ldtk): +```bash +$ cargo run --example tile_based_game --release +``` + +## Prerequisites +You will need to perform the following setup/installations: +- [Bevy project setup](https://bevyengine.org/learn/book/getting-started/setup/) for the version specified in the [compatibility chart](https://github.com/Trouv/bevy_ecs_ldtk#compatibility). +- [LDtk installation](https://ldtk.io/versions/), for the version specified in the [compatibility chart](https://github.com/Trouv/bevy_ecs_ldtk#compatibility). + +You will also need some simple assets: +- A tileset for the environment with at least a background tile, a wall tile, and a "goal"-ish tile. +- A tileset for the the player. + +For these purposes this tutorial will use the `environment/tileset.png` and `spritesheets/player.png` assets respectively from [SunnyLand by Ansimuz](https://ansimuz.itch.io/sunny-land-pixel-game-art), licensed under [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/). +However, you will be able to follow this tutorial using any tilesets, so long as they have tiles appropriate for the above purposes. diff --git a/book/src/tutorials/tile-based-game/add-gameplay-to-your-project.md b/book/src/tutorials/tile-based-game/add-gameplay-to-your-project.md new file mode 100644 index 00000000..5eefd39c --- /dev/null +++ b/book/src/tutorials/tile-based-game/add-gameplay-to-your-project.md @@ -0,0 +1,221 @@ +# Add gameplay to your project +In this section, you will integrate gameplay to the Bevy/LDtk project created in the previous sections. +This includes tile-based movement, collision, and level transitions. +You are welcome to bring your own tile-based LDtk project to this tutorial, but some of the values specified in here are specific to the LDtk project created in this tutorial, such as... +- the IntGrid value of walls (1) + +For details about the tutorial in general, including prerequisites, please see the parent page. + +## Add marker component and `GridCoords` to the player +In order to implement tile-based movement and tile-based mechanics, you'll need to deal with an entity's position in tile-space rather than just Bevy world translation. +`bevy_ecs_ldtk` provides a component that is suitable for this, and it has integration with the `LdtkEntity` derive. +Add the `GridCoords` component to the `PlayerBundle`, and give it the `#[grid_coords]` attribute. +The player entity will then be spawned with a `GridCoords` component whose value matches the entity's position in grid-space. + +Also give it a `Player` marker component so that you can query for it more easily in future systems. +Derive `Default` for this component. +`bevy_ecs_ldtk` will use this default implementation when spawning the component unless otherwise specified. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +{{#include ../../../../examples/tile_based_game.rs:42:52}} +``` + +## Implement tile-based movement +The player now has the components you will need to implement tile-based movement. +Write a system that checks for just-pressed WASD input and converts it to a `GridCoords` direction. +I.e., `(0,1)` for W, `(-1,0)` for A, `(0,-1)` for S, and `(1,0)` for D. +Then, add the new direction to the player entity's `GridCoords` component. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +# #[derive(Component)] +# struct Player; +fn main() { + App::new() + // other App builders + .add_systems(Update, move_player_from_input) + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:91:93}} +{{#include ../../../../examples/tile_based_game.rs:95:109}} + *player_grid_coords = destination; + } +} +``` + +## Update translation from `GridCoords` value +If you play the game at this point, you'll notice that the player entity doesn't appear to be moving at all. +The `GridCoords` component may be updating correctly, but the entity's `Transform` is what determines where it is rendered. +`bevy_ecs_ldtk` does not maintain the `Transform` of `GridCoords` entities automatically. +This is left up to the user, which allows you to implement custom tweening or animation of the transform as you please. + +Write a system that updates the `Transform` of `GridCoords` entities when their `GridCoords` value changes. +`bevy_ecs_ldtk` does provide a utility function to help calculate the resulting translation - provided you know the size of the cells of the grid. +For the LDtk project set up in this tutorial using the `SunnyLand` tilesets, this grid size is 16. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +# fn move_player_from_input() {} +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:15:19}} + ), + ) + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:116:126}} +``` + +## Prevent tile-based movement into walls +Movement works logically *and* visually now. +However, you might notice that you can move *into* the walls of the level. +To implement tile-based collision, you will need to add components to the walls to identify their locations, and check against these locations when trying to move the player. + +Create a new bundle for the wall entities, and give them a marker component. +Derive `LdtkIntCell` for this bundle, and register it to the app with `register_ldtk_int_cell` and the wall's intgrid value. +This bundle actually only needs this one marker component - IntGrid entities spawn with a `GridCoords` without requesting it. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:24}} + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:66:72}} +``` + +There are a lot of ways to go about implementing the collision systems. +Naively, you could query for all of the `Wall` entities every time the player tries to move and check their `GridCoords` values. +In this tutorial, you will implement something a little more optimized: caching the wall locations into a resource when levels spawn. + +Create a `LevelWalls` resource for storing the current wall locations that can be looked up by-value. +Give it a `HashSet` field for the wall locations. +Give it fields for the level's width and height as well so you can prevent the player from moving out-of-bounds. +Then, implement a method `fn in_wall(&self, grid_coords: &GridCoords) -> bool` that returns true if the provided `grid_coords` is outside the level bounds or contained in the `HashSet`. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +use std::collections::HashSet; + +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:25}} + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:74:89}} +``` + +Now, add a system that listens for `LevelEvent::Spawned` and populates this resource. +It will need access to all of the wall locations to populate the `HashSet` (`Query<&GridCoords, With>`). +It will also need access to the `LdtkProject` data to find the current level's width/height (`Query<&Handle>` and `Res>`). +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +# use std::collections::HashSet; +# const GRID_SIZE: i32 = 16; +# #[derive(Default, Resource)] +# struct LevelWalls { +# wall_locations: HashSet, +# level_width: i32, +# level_height: i32, +# } +# impl LevelWalls { +# fn in_wall(&self, grid_coords: &GridCoords) -> bool { +# grid_coords.x < 0 +# || grid_coords.y < 0 +# || grid_coords.x >= self.level_width +# || grid_coords.y >= self.level_height +# || self.wall_locations.contains(grid_coords) +# } +# } +# #[derive(Component)] +# struct Wall; +# fn move_player_from_input() {} +# fn translate_grid_coords_entities() {} +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:15:20}} + ) + ) + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:128:155}} +``` + +Finally, update the `move_player_from_input` system to access the `LevelWalls` resource and check whether or not the player's destination is in a wall. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +# use std::collections::HashSet; +# #[derive(Component)] +# struct Player; +# #[derive(Default, Resource)] +# struct LevelWalls { +# wall_locations: HashSet, +# level_width: i32, +# level_height: i32, +# } +# impl LevelWalls { +# fn in_wall(&self, grid_coords: &GridCoords) -> bool { +# grid_coords.x < 0 +# || grid_coords.y < 0 +# || grid_coords.x >= self.level_width +# || grid_coords.y >= self.level_height +# || self.wall_locations.contains(grid_coords) +# } +# } +{{#include ../../../../examples/tile_based_game.rs:91:114}} +``` + +With this check in place, the player should now be unable to move into walls! + +## Trigger level transitions on victory +The final step is to implement the goal functionality. +When the player reaches the goal, the next level should spawn until there are no levels remaining. + +Similar to the `PlayerBundle`, give the `GoalBundle` its own marker component and `GridCoords`. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +{{#include ../../../../examples/tile_based_game.rs:54:64}} +``` + +Then, write a system that checks if the player's `GridCoords` and the goal's `GridCoords` match. +For a small optimization, filter the player query for `Changed` so it's only populated if the player moves. +If they do match, update the `LevelSelection` resource, increasing its level index by 1. +`bevy_ecs_ldtk` will automatically despawn the current level and spawn the next one when this resource is updated. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +# #[derive(Component)] +# struct Player; +# #[derive(Component)] +# struct Goal; +# fn move_player_from_input() {} +# fn translate_grid_coords_entities() {} +# fn cache_wall_locations() {} +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:15:23}} + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:157::}} +``` + +With this, the simple tile-based game is complete. +When you navigate the player to the goal, the next level will begin until there are no levels remaining. + +
diff --git a/book/src/tutorials/tile-based-game/create-your-ldtk-project.md b/book/src/tutorials/tile-based-game/create-your-ldtk-project.md new file mode 100644 index 00000000..0c8141ea --- /dev/null +++ b/book/src/tutorials/tile-based-game/create-your-ldtk-project.md @@ -0,0 +1,118 @@ +# Create your LDtk project +In this section, you will create a simple LDtk project suitable for tile-based gameplay. +This project will have an IntGrid layer of walls, and an Entity layer for placing Player and Goal entities. +It will also have AutoTile rules on top of the IntGrid layer defining the visuals of walls and backgrounds. +If you already have an LDtk project suitable for tile-based gameplay - feel free to skip this section. +However, note that some of the values specified in here will be used in the tutorial going forward, such as... +- the name/location of the file (`assets/tile-based-game.ldtk`) +- the identifiers of the Player and Goal entities (Player, Goal) +- the IntGrid value of walls (1) + +For details about the tutorial in general, including prerequisites, please see the parent page. + +## Create empty project +Open the LDtk app and create a new project. +For this tutorial, name the project `tile-based-game.ldtk`, and save it to your Bevy project's `assets` directory. + +## Set the World layout +In the **World** tab - set the **World layout** to Horizontal. +This will make levels have a clear linear relationship in the editor, rather than a geographical one. + +![world-layout](images/world-layout.png) + +## Import tilesets +Add your environment/player tilesets to the project, in the **Tilesets** tab. +Make sure that the source image files for these tilesets are also in your Bevy project's `assets` directory. +Name the tilesets "Environment" and "Player" respectively. +For the SunnyLand assets - the Player tileset needs to have a tile size of 32 and the environment asset a tile size of 16. + +![tilesets](images/tilesets.png) + +## Add IntGrid layer for walls +Add an IntGrid layer to the project, in the **Layers** tab. +This layer will be used to define where the collisions are in the level. +Call this layer "Walls". +Make sure its grid size is 16. +Finally, give it an **Auto-layer tileset** - pointing to the Environment tileset. + +![wall-layer](images/wall-layer.png) + +## Define autotiling for walls and backgrounds +From the Walls layer definition, select **EDIT RULES** for the Auto-layer tileset. +This is where you will define how LDtk should dynamically render the Walls layer of your levels based off the level's IntGrid values. + +First, define a catch-all rule that will place the background tile if no other rules are matched first. +1. Select **+ GROUP** to add a new empty rule group, and name it Background. +2. On the new group, select **+** to define the first rule. +3. In the top-right of the rule definition - select the tile you want to use as the background. +4. Since this is a catch-all rule, no changes to the rule-pattern are necessary. + +![background-rule](images/background-rule.png) + +Next, define a rule that will catch any wall tile. +You will be able to define more complex rules on top of this to make walls prettier, but it's good to start with a generic one first. +1. Create another new group, and name it Walls. +2. Click **+** on the Walls group to create its first rule. +3. Select the tile you want to use as a generic wall tile in the top-right. +4. Set the rule to be 1x1, and left-click the rule-pattern to place a wall tile. + +![all-walls-rule](images/all-walls-rule.png) + +Now you will be able to place walls in your level and they will be automatically rendered using this tile. + +The following rule is optional, and will define the tile used for the edges of walls - specifically horizontal edges. +1. Create a new rule in the Walls group. +2. Select the tile you want to use as the left edges of a wall. +3. Use a 3x3 pattern, and place a wall tile in the center and a negative wall tile on the left (by right clicking the left-center tile). +This will match any wall tiles that don't have a wall tile to their left. +4. On this new rule inside the group, enable the **X** option. +This mirrors the rule in the x-direction, so that it works for the right edges of walls as well. + +![horizontal-wall-edge-rule](images/horizontal-wall-edge-rule.png) + +You are welcome to add more rules to the Walls group with more complex patterns for defining the vertical edges or corners. +This tutorial will not go into painstaking detail about creating these, but their definitions are shown below. +One general recommendation is to order these rules from most-specific to least-specific, so that the rule matcher will resort to the catch-all rules last. + +A vertical wall edge rule - mirrored in the **Y** direction: + +![vertical-wall-edge-rule](images/vertical-wall-edge-rule.png) + +An outer corner wall rule - mirrored in the **X** and **Y** directions: + +![wall-outer-corner-rule](images/wall-outer-corner-rule.png) + +An inner corner wall rule - mirrored in the **X** and **Y** directions: + +![wall-inner-corner-rule](images/wall-inner-corner-rule.png) + +Now you can enjoy placing walls in your level and watching LDtk auto-tile them for you! + +
+ +## Add Entity layer +Add an Entity layer to the project, again, in the **Layers** tab. +This will be used to place less tiling-oriented game objects, like the player, or the goal. +You do not need to make any modifications to the default entity layer for this tutorial, it should be called "Entities" and match the grid size of the Walls layer. + +![entity-layer](images/entities-layer.png) + +Then, in the **Entities** tab, add a Player entity. +Be sure to name it "Player" and set its editor visual to use a tile from the Player tileset. +This will be important in the next section of the tutorial. +For the SunnyLand assets - you will need to manually set its size to 16x16 so that it fits in a single tile on the grid. + +![player-entity](images/player-entity.png) + +Lastly, add a Goal entity. +Name it "Goal" and set its editor visual from a tileset as well. +Again, this will be important in the next section of the tutorial. + +![goal-entity](images/goal-entity.png) + +## Design some levels +In the following chapters, you will spawn this project in Bevy and implement gameplay code for it. +The game will be simple - move the player around the grid, navigating the walls, and start the next level once they reach the goal. +With this in mind, design a few levels for this game using the tools you have set up thus far. + +![levels](images/levels.png) diff --git a/book/src/tutorials/tile-based-game/images/all-walls-rule.png b/book/src/tutorials/tile-based-game/images/all-walls-rule.png new file mode 100644 index 00000000..b58062ee Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/all-walls-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/auto-tile-walls.png b/book/src/tutorials/tile-based-game/images/auto-tile-walls.png new file mode 100644 index 00000000..57a72d31 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/auto-tile-walls.png differ diff --git a/book/src/tutorials/tile-based-game/images/background-rule.png b/book/src/tutorials/tile-based-game/images/background-rule.png new file mode 100644 index 00000000..1df42f9d Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/background-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/bevy-setup.png b/book/src/tutorials/tile-based-game/images/bevy-setup.png new file mode 100644 index 00000000..f78fa805 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/bevy-setup.png differ diff --git a/book/src/tutorials/tile-based-game/images/bevy-sprites.png b/book/src/tutorials/tile-based-game/images/bevy-sprites.png new file mode 100644 index 00000000..107137f2 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/bevy-sprites.png differ diff --git a/book/src/tutorials/tile-based-game/images/entities-layer.png b/book/src/tutorials/tile-based-game/images/entities-layer.png new file mode 100644 index 00000000..d685b202 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/entities-layer.png differ diff --git a/book/src/tutorials/tile-based-game/images/goal-entity.png b/book/src/tutorials/tile-based-game/images/goal-entity.png new file mode 100644 index 00000000..c2569bf4 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/goal-entity.png differ diff --git a/book/src/tutorials/tile-based-game/images/horizontal-wall-edge-rule.png b/book/src/tutorials/tile-based-game/images/horizontal-wall-edge-rule.png new file mode 100644 index 00000000..6f18a486 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/horizontal-wall-edge-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/levels.png b/book/src/tutorials/tile-based-game/images/levels.png new file mode 100644 index 00000000..bc9cd458 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/levels.png differ diff --git a/book/src/tutorials/tile-based-game/images/player-entity.png b/book/src/tutorials/tile-based-game/images/player-entity.png new file mode 100644 index 00000000..e1202d54 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/player-entity.png differ diff --git a/book/src/tutorials/tile-based-game/images/tilesets.png b/book/src/tutorials/tile-based-game/images/tilesets.png new file mode 100644 index 00000000..3dd679c7 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/tilesets.png differ diff --git a/book/src/tutorials/tile-based-game/images/vertical-wall-edge-rule.png b/book/src/tutorials/tile-based-game/images/vertical-wall-edge-rule.png new file mode 100644 index 00000000..bf65f783 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/vertical-wall-edge-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/wall-inner-corner-rule.png b/book/src/tutorials/tile-based-game/images/wall-inner-corner-rule.png new file mode 100644 index 00000000..9d0ee8e2 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/wall-inner-corner-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/wall-layer.png b/book/src/tutorials/tile-based-game/images/wall-layer.png new file mode 100644 index 00000000..8af4250c Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/wall-layer.png differ diff --git a/book/src/tutorials/tile-based-game/images/wall-outer-corner-rule.png b/book/src/tutorials/tile-based-game/images/wall-outer-corner-rule.png new file mode 100644 index 00000000..18040853 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/wall-outer-corner-rule.png differ diff --git a/book/src/tutorials/tile-based-game/images/world-layout.png b/book/src/tutorials/tile-based-game/images/world-layout.png new file mode 100644 index 00000000..35472909 Binary files /dev/null and b/book/src/tutorials/tile-based-game/images/world-layout.png differ diff --git a/book/src/tutorials/tile-based-game/spawn-your-ldtk-project-in-bevy.md b/book/src/tutorials/tile-based-game/spawn-your-ldtk-project-in-bevy.md new file mode 100644 index 00000000..d7e60d21 --- /dev/null +++ b/book/src/tutorials/tile-based-game/spawn-your-ldtk-project-in-bevy.md @@ -0,0 +1,109 @@ +# Spawn your LDtk project in Bevy +In this section, you will load/spawn your LDtk project in Bevy, including spawning sprites for the LDtk entities. +This tutorial will use the LDtk project created in the previous section. +You are welcome to bring your own tile-based LDtk project to this tutorial, but some of the values specified in here are specific to the previous section, such as... +- the name/location of the file (`assets/tile-based-game.ldtk`) +- the identifiers of the Player and Goal entities (Player, Goal) + +For details about the tutorial in general, including prerequisites, please see the parent page. + +## Set up minimal Bevy App +In the `main` function of your game, create a Bevy `App` with `DefaultPlugins` and `LdtkPlugin`. +This code snippet also sets bevy's texture filtering to "nearest", which is good for pixelated games. +```rust,no_run +use bevy::prelude::*; +use bevy_ecs_ldtk::prelude::*; + +fn main() { + App::new() + .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) + .add_plugins(LdtkPlugin) + .run(); +} +``` + +## Spawn the camera and LdtkWorldBundle on startup +Create a startup system that spawns a camera entity and a `LdtkWorldBundle` entity. +The latter requires a `Handle`, which can be obtained by loading your LDtk project from the Bevy `AssetServer` resource. +This code snippet also doubles the scale of the camera and adjusts its transform to make the level slightly easier to view in 720p. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:11}} + .run(); +} + +{{#include ../../../../examples/tile_based_game.rs:29:40}} +``` + +Finally, insert the `LevelSelection` resource to tell the plugin to spawn the first level. +Construct the `LevelSelection` using its `index` method to select the first level (0-indexed). +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:12}} + .run(); +} +``` + +Now, run the game with `$ cargo run --release` to see your first level spawning in Bevy! + +![bevy-setup](images/bevy-setup.png) + +## Spawn sprites for your LDtk entities +You may have noticed that the Player and Goal are not rendered here. +They are there, but they require a little more work to become visible. + +Create a `PlayerBundle` and `GoalBundle`, each with a `SpriteSheetBundle` field. +You will develop these bundles a little bit more in the next chapter, but for now they will be similar. +Derive `LdtkEntity` for these bundles, and give the field a `#[sprite_sheet_bundle]` attribute. +This trait implementation defines how these bundles should be spawned by the plugin. +More specifically - they should be spawned as sprites identical to the entity's editor visual. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +#[derive(Default, Bundle, LdtkEntity)] +struct PlayerBundle { + #[sprite_sheet_bundle] + sprite_sheet_bundle: SpriteSheetBundle, +} + +#[derive(Default, Bundle, LdtkEntity)] +struct GoalBundle { + #[sprite_sheet_bundle] + sprite_sheet_bundle: SpriteSheetBundle, +} +``` + +Finally, register these bundles to the app using `register_ldtk_entity`, and provide their LDtk identifier. +When the plugin spawns entities with these identifiers, it will use the registered bundle. +```rust,no_run +# use bevy::prelude::*; +# use bevy_ecs_ldtk::prelude::*; +fn main() { + App::new() + // other App builders +{{#include ../../../../examples/tile_based_game.rs:13:14}} + .run(); +} +# #[derive(Default, Bundle, LdtkEntity)] +# struct PlayerBundle { +# #[sprite_sheet_bundle] +# sprite_sheet_bundle: SpriteSheetBundle, +# } +# #[derive(Default, Bundle, LdtkEntity)] +# struct GoalBundle { +# #[sprite_sheet_bundle] +# sprite_sheet_bundle: SpriteSheetBundle, +# } +``` + +Now run the game again - the sprites will appear this time. + +![bevy-sprites](images/bevy-sprites.png) diff --git a/examples/tile_based_game.rs b/examples/tile_based_game.rs new file mode 100644 index 00000000..b20fbe9a --- /dev/null +++ b/examples/tile_based_game.rs @@ -0,0 +1,174 @@ +// This example has a tutorial in the bevy_ecs_ldtk book associated with it: +// +use bevy::prelude::*; +use bevy_ecs_ldtk::prelude::*; +use std::collections::HashSet; + +fn main() { + App::new() + .add_plugins(DefaultPlugins.set(ImagePlugin::default_nearest())) + .add_plugins(LdtkPlugin) + .add_systems(Startup, setup) + .insert_resource(LevelSelection::index(0)) + .register_ldtk_entity::("Player") + .register_ldtk_entity::("Goal") + .add_systems( + Update, + ( + move_player_from_input, + translate_grid_coords_entities, + cache_wall_locations, + check_goal, + ), + ) + .register_ldtk_int_cell::(1) + .init_resource::() + .run(); +} + +fn setup(mut commands: Commands, asset_server: Res) { + let mut camera = Camera2dBundle::default(); + camera.projection.scale = 0.5; + camera.transform.translation.x += 1280.0 / 4.0; + camera.transform.translation.y += 720.0 / 4.0; + commands.spawn(camera); + + commands.spawn(LdtkWorldBundle { + ldtk_handle: asset_server.load("tile-based-game.ldtk"), + ..Default::default() + }); +} + +#[derive(Default, Component)] +struct Player; + +#[derive(Default, Bundle, LdtkEntity)] +struct PlayerBundle { + player: Player, + #[sprite_sheet_bundle] + sprite_bundle: SpriteSheetBundle, + #[grid_coords] + grid_coords: GridCoords, +} + +#[derive(Default, Component)] +struct Goal; + +#[derive(Default, Bundle, LdtkEntity)] +struct GoalBundle { + goal: Goal, + #[sprite_sheet_bundle] + sprite_bundle: SpriteSheetBundle, + #[grid_coords] + grid_coords: GridCoords, +} + +#[derive(Default, Component)] +struct Wall; + +#[derive(Default, Bundle, LdtkIntCell)] +struct WallBundle { + wall: Wall, +} + +#[derive(Default, Resource)] +struct LevelWalls { + wall_locations: HashSet, + level_width: i32, + level_height: i32, +} + +impl LevelWalls { + fn in_wall(&self, grid_coords: &GridCoords) -> bool { + grid_coords.x < 0 + || grid_coords.y < 0 + || grid_coords.x >= self.level_width + || grid_coords.y >= self.level_height + || self.wall_locations.contains(grid_coords) + } +} + +fn move_player_from_input( + mut players: Query<&mut GridCoords, With>, + input: Res>, + level_walls: Res, +) { + let movement_direction = if input.just_pressed(KeyCode::W) { + GridCoords::new(0, 1) + } else if input.just_pressed(KeyCode::A) { + GridCoords::new(-1, 0) + } else if input.just_pressed(KeyCode::S) { + GridCoords::new(0, -1) + } else if input.just_pressed(KeyCode::D) { + GridCoords::new(1, 0) + } else { + return; + }; + + for mut player_grid_coords in players.iter_mut() { + let destination = *player_grid_coords + movement_direction; + if !level_walls.in_wall(&destination) { + *player_grid_coords = destination; + } + } +} + +const GRID_SIZE: i32 = 16; + +fn translate_grid_coords_entities( + mut grid_coords_entities: Query<(&mut Transform, &GridCoords), Changed>, +) { + for (mut transform, grid_coords) in grid_coords_entities.iter_mut() { + transform.translation = + bevy_ecs_ldtk::utils::grid_coords_to_translation(*grid_coords, IVec2::splat(GRID_SIZE)) + .extend(transform.translation.z); + } +} + +fn cache_wall_locations( + mut level_walls: ResMut, + mut level_events: EventReader, + walls: Query<&GridCoords, With>, + ldtk_project_entities: Query<&Handle>, + ldtk_project_assets: Res>, +) { + for level_event in level_events.iter() { + if let LevelEvent::Spawned(level_iid) = level_event { + let ldtk_project = ldtk_project_assets + .get(ldtk_project_entities.single()) + .expect("LdtkProject should be loaded when level is spawned"); + let level = ldtk_project + .get_raw_level_by_iid(level_iid.get()) + .expect("spawned level should exist in project"); + + let wall_locations = walls.iter().copied().collect(); + + let new_level_walls = LevelWalls { + wall_locations, + level_width: level.px_wid / GRID_SIZE, + level_height: level.px_hei / GRID_SIZE, + }; + + *level_walls = new_level_walls; + } + } +} + +fn check_goal( + level_selection: ResMut, + players: Query<&GridCoords, (With, Changed)>, + goals: Query<&GridCoords, With>, +) { + if players + .iter() + .zip(goals.iter()) + .any(|(player_grid_coords, goal_grid_coords)| player_grid_coords == goal_grid_coords) + { + let indices = match level_selection.into_inner() { + LevelSelection::Indices(indices) => indices, + _ => panic!("level selection should always be Indices in this game"), + }; + + indices.level += 1; + } +}