shifted from proprietary ascii rawlevel to LDTK (using ldtkgo@master)
This commit is contained in:
parent
a2ed7782b2
commit
af19ccb833
8
TODO.md
8
TODO.md
@ -22,6 +22,14 @@
|
||||
slog.Debug("get observer", "minmoves", observer.LevelScore,
|
||||
"file", source.File, "line", source.Line)
|
||||
|
||||
- LDTK:
|
||||
- to each level add these properties:
|
||||
- level (num)
|
||||
- name
|
||||
- description
|
||||
- background (image name w/o .png)
|
||||
- min-moves (num, moves required to win)
|
||||
|
||||
## Collider Rework [abandoned: see branch collider-system, fails]
|
||||
|
||||
- do not use the map anymore for collision detection
|
||||
|
||||
686
assets/levels/openquell.ldtk
Normal file
686
assets/levels/openquell.ldtk
Normal file
@ -0,0 +1,686 @@
|
||||
{
|
||||
"__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.5.3",
|
||||
"url": "https://ldtk.io"
|
||||
},
|
||||
"iid": "267e9380-d7b0-11ee-a97e-35bec9c19d52",
|
||||
"jsonVersion": "1.5.3",
|
||||
"appBuildId": 473703,
|
||||
"nextUid": 11,
|
||||
"identifierStyle": "Capitalize",
|
||||
"toc": [],
|
||||
"worldLayout": "Free",
|
||||
"worldGridWidth": 256,
|
||||
"worldGridHeight": 256,
|
||||
"defaultLevelWidth": 256,
|
||||
"defaultLevelHeight": 256,
|
||||
"defaultPivotX": 0,
|
||||
"defaultPivotY": 0,
|
||||
"defaultGridSize": 32,
|
||||
"defaultEntityWidth": 32,
|
||||
"defaultEntityHeight": 32,
|
||||
"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": 5,
|
||||
"doc": null,
|
||||
"uiColor": null,
|
||||
"gridSize": 32,
|
||||
"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": [],
|
||||
"autoTilesKilledByOtherLayerUid": null,
|
||||
"uiFilterTags": [],
|
||||
"useAsyncRender": false,
|
||||
"intGridValues": [],
|
||||
"intGridValuesGroups": [],
|
||||
"autoRuleGroups": [],
|
||||
"autoSourceLayerDefUid": null,
|
||||
"tilesetDefUid": null,
|
||||
"tilePivotX": 0,
|
||||
"tilePivotY": 0,
|
||||
"biomeFieldUid": null
|
||||
},
|
||||
{
|
||||
"__type": "Tiles",
|
||||
"identifier": "Tiles",
|
||||
"type": "Tiles",
|
||||
"uid": 2,
|
||||
"doc": null,
|
||||
"uiColor": null,
|
||||
"gridSize": 32,
|
||||
"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": [],
|
||||
"autoTilesKilledByOtherLayerUid": null,
|
||||
"uiFilterTags": [],
|
||||
"useAsyncRender": false,
|
||||
"intGridValues": [],
|
||||
"intGridValuesGroups": [],
|
||||
"autoRuleGroups": [],
|
||||
"autoSourceLayerDefUid": null,
|
||||
"tilesetDefUid": 1,
|
||||
"tilePivotX": 0,
|
||||
"tilePivotY": 0,
|
||||
"biomeFieldUid": null
|
||||
}
|
||||
], "entities": [
|
||||
{
|
||||
"identifier": "Player_Primary",
|
||||
"uid": 3,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"resizableX": false,
|
||||
"resizableY": false,
|
||||
"minWidth": null,
|
||||
"maxWidth": null,
|
||||
"minHeight": null,
|
||||
"maxHeight": null,
|
||||
"keepAspectRatio": false,
|
||||
"tileOpacity": 1,
|
||||
"fillOpacity": 0.08,
|
||||
"lineOpacity": 0,
|
||||
"hollow": false,
|
||||
"color": "#2F3BBE",
|
||||
"renderMode": "Tile",
|
||||
"showName": true,
|
||||
"tilesetId": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 32, "y": 96, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
},
|
||||
{
|
||||
"identifier": "Collectible",
|
||||
"uid": 4,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"resizableX": false,
|
||||
"resizableY": false,
|
||||
"minWidth": null,
|
||||
"maxWidth": null,
|
||||
"minHeight": null,
|
||||
"maxHeight": null,
|
||||
"keepAspectRatio": false,
|
||||
"tileOpacity": 1,
|
||||
"fillOpacity": 0.08,
|
||||
"lineOpacity": 0,
|
||||
"hollow": false,
|
||||
"color": "#FEAE34",
|
||||
"renderMode": "Tile",
|
||||
"showName": true,
|
||||
"tilesetId": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
},
|
||||
{
|
||||
"identifier": "Obstacle_West",
|
||||
"uid": 7,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"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": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 0, "y": 96, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
},
|
||||
{
|
||||
"identifier": "Obstacle_East",
|
||||
"uid": 8,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"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": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 64, "y": 32, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
},
|
||||
{
|
||||
"identifier": "Obstacle_North",
|
||||
"uid": 9,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"resizableX": false,
|
||||
"resizableY": false,
|
||||
"minWidth": null,
|
||||
"maxWidth": null,
|
||||
"minHeight": null,
|
||||
"maxHeight": null,
|
||||
"keepAspectRatio": false,
|
||||
"tileOpacity": 1,
|
||||
"fillOpacity": 0.08,
|
||||
"lineOpacity": 0,
|
||||
"hollow": false,
|
||||
"color": "#F77622",
|
||||
"renderMode": "Tile",
|
||||
"showName": true,
|
||||
"tilesetId": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 0, "y": 64, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
},
|
||||
{
|
||||
"identifier": "Obstacle_South",
|
||||
"uid": 10,
|
||||
"tags": [],
|
||||
"exportToToc": false,
|
||||
"allowOutOfBounds": false,
|
||||
"doc": null,
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"resizableX": false,
|
||||
"resizableY": false,
|
||||
"minWidth": null,
|
||||
"maxWidth": null,
|
||||
"minHeight": null,
|
||||
"maxHeight": null,
|
||||
"keepAspectRatio": false,
|
||||
"tileOpacity": 1,
|
||||
"fillOpacity": 0.08,
|
||||
"lineOpacity": 0,
|
||||
"hollow": false,
|
||||
"color": "#E43B44",
|
||||
"renderMode": "Tile",
|
||||
"showName": true,
|
||||
"tilesetId": 1,
|
||||
"tileRenderMode": "FitInside",
|
||||
"tileRect": { "tilesetUid": 1, "x": 32, "y": 64, "w": 32, "h": 32 },
|
||||
"uiTileRect": null,
|
||||
"nineSliceBorders": [],
|
||||
"maxCount": 0,
|
||||
"limitScope": "PerLevel",
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
}
|
||||
], "tilesets": [
|
||||
{
|
||||
"__cWid": 3,
|
||||
"__cHei": 5,
|
||||
"identifier": "Map2",
|
||||
"uid": 1,
|
||||
"relPath": "../sprites/map.png",
|
||||
"embedAtlas": null,
|
||||
"pxWid": 96,
|
||||
"pxHei": 160,
|
||||
"tileGridSize": 32,
|
||||
"spacing": 0,
|
||||
"padding": 0,
|
||||
"tags": [],
|
||||
"tagsSourceEnumUid": null,
|
||||
"enumTags": [],
|
||||
"customData": [],
|
||||
"savedSelections": [],
|
||||
"cachedPixelData": { "opaqueTiles": "110000000000000", "averageColors": "f777f766f766f9533c965c355c355c354b355c35987d687d1b4700000000" }
|
||||
}
|
||||
], "enums": [], "externalEnums": [], "levelFields": [] },
|
||||
"levels": [
|
||||
{
|
||||
"identifier": "Level_0",
|
||||
"iid": "267fa4f0-d7b0-11ee-a97e-d90512e08363",
|
||||
"uid": 0,
|
||||
"worldX": -224,
|
||||
"worldY": 0,
|
||||
"worldDepth": 0,
|
||||
"pxWid": 640,
|
||||
"pxHei": 480,
|
||||
"__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": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "99cd5060-d7b0-11ee-a97e-3f143b461cd1",
|
||||
"levelId": 0,
|
||||
"layerDefUid": 5,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 1148260,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": [
|
||||
{
|
||||
"__identifier": "Player_Primary",
|
||||
"__grid": [7,5],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 96, "w": 32, "h": 32 },
|
||||
"__smartColor": "#2F3BBE",
|
||||
"iid": "c33a2c20-d7b0-11ee-a97e-03409aba0392",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 3,
|
||||
"px": [224,160],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 0,
|
||||
"__worldY": 160
|
||||
},
|
||||
{
|
||||
"__identifier": "Collectible",
|
||||
"__grid": [11,7],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 },
|
||||
"__smartColor": "#FEAE34",
|
||||
"iid": "f2b2ff50-d7b0-11ee-98fb-b34c447bc14d",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,224],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 128,
|
||||
"__worldY": 224
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__identifier": "Tiles",
|
||||
"__type": "Tiles",
|
||||
"__cWid": 20,
|
||||
"__cHei": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": 1,
|
||||
"__tilesetRelPath": "../sprites/map.png",
|
||||
"iid": "3f368c70-d7b0-11ee-a97e-65a98b860ebf",
|
||||
"levelId": 0,
|
||||
"layerDefUid": 2,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 4985586,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [
|
||||
{ "px": [192,128], "src": [64,0], "f": 0, "t": 2, "d": [86], "a": 1 },
|
||||
{ "px": [224,128], "src": [64,0], "f": 0, "t": 2, "d": [87], "a": 1 },
|
||||
{ "px": [256,128], "src": [64,0], "f": 0, "t": 2, "d": [88], "a": 1 },
|
||||
{ "px": [288,128], "src": [64,0], "f": 0, "t": 2, "d": [89], "a": 1 },
|
||||
{ "px": [320,128], "src": [64,0], "f": 0, "t": 2, "d": [90], "a": 1 },
|
||||
{ "px": [352,128], "src": [64,0], "f": 0, "t": 2, "d": [91], "a": 1 },
|
||||
{ "px": [384,128], "src": [64,0], "f": 0, "t": 2, "d": [92], "a": 1 },
|
||||
{ "px": [416,128], "src": [0,0], "f": 0, "t": 0, "d": [93], "a": 1 },
|
||||
{ "px": [416,128], "src": [64,0], "f": 0, "t": 2, "d": [93], "a": 1 },
|
||||
{ "px": [192,160], "src": [64,0], "f": 0, "t": 2, "d": [106], "a": 1 },
|
||||
{ "px": [256,160], "src": [64,0], "f": 0, "t": 2, "d": [108], "a": 1 },
|
||||
{ "px": [416,160], "src": [64,0], "f": 0, "t": 2, "d": [113], "a": 1 },
|
||||
{ "px": [192,192], "src": [64,0], "f": 0, "t": 2, "d": [126], "a": 1 },
|
||||
{ "px": [256,192], "src": [64,0], "f": 0, "t": 2, "d": [128], "a": 1 },
|
||||
{ "px": [320,192], "src": [64,0], "f": 0, "t": 2, "d": [130], "a": 1 },
|
||||
{ "px": [352,192], "src": [64,0], "f": 0, "t": 2, "d": [131], "a": 1 },
|
||||
{ "px": [416,192], "src": [64,0], "f": 0, "t": 2, "d": [133], "a": 1 },
|
||||
{ "px": [192,224], "src": [64,0], "f": 0, "t": 2, "d": [146], "a": 1 },
|
||||
{ "px": [256,224], "src": [64,0], "f": 0, "t": 2, "d": [148], "a": 1 },
|
||||
{ "px": [320,224], "src": [64,0], "f": 0, "t": 2, "d": [150], "a": 1 },
|
||||
{ "px": [416,224], "src": [64,0], "f": 0, "t": 2, "d": [153], "a": 1 },
|
||||
{ "px": [192,256], "src": [64,0], "f": 0, "t": 2, "d": [166], "a": 1 },
|
||||
{ "px": [256,256], "src": [64,0], "f": 0, "t": 2, "d": [168], "a": 1 },
|
||||
{ "px": [320,256], "src": [64,0], "f": 0, "t": 2, "d": [170], "a": 1 },
|
||||
{ "px": [416,256], "src": [64,0], "f": 0, "t": 2, "d": [173], "a": 1 },
|
||||
{ "px": [192,288], "src": [64,0], "f": 0, "t": 2, "d": [186], "a": 1 },
|
||||
{ "px": [320,288], "src": [64,0], "f": 0, "t": 2, "d": [190], "a": 1 },
|
||||
{ "px": [416,288], "src": [64,0], "f": 0, "t": 2, "d": [193], "a": 1 },
|
||||
{ "px": [192,320], "src": [64,0], "f": 0, "t": 2, "d": [206], "a": 1 },
|
||||
{ "px": [224,320], "src": [64,0], "f": 0, "t": 2, "d": [207], "a": 1 },
|
||||
{ "px": [256,320], "src": [64,0], "f": 0, "t": 2, "d": [208], "a": 1 },
|
||||
{ "px": [288,320], "src": [64,0], "f": 0, "t": 2, "d": [209], "a": 1 },
|
||||
{ "px": [320,320], "src": [64,0], "f": 0, "t": 2, "d": [210], "a": 1 },
|
||||
{ "px": [352,320], "src": [64,0], "f": 0, "t": 2, "d": [211], "a": 1 },
|
||||
{ "px": [384,320], "src": [64,0], "f": 0, "t": 2, "d": [212], "a": 1 },
|
||||
{ "px": [416,320], "src": [64,0], "f": 0, "t": 2, "d": [213], "a": 1 }
|
||||
],
|
||||
"entityInstances": []
|
||||
}
|
||||
],
|
||||
"__neighbours": []
|
||||
},
|
||||
{
|
||||
"identifier": "_First_Try",
|
||||
"iid": "024390f0-d7b0-11ee-98fb-1bc6ad7e4172",
|
||||
"uid": 6,
|
||||
"worldX": 480,
|
||||
"worldY": 0,
|
||||
"worldDepth": 0,
|
||||
"pxWid": 640,
|
||||
"pxHei": 480,
|
||||
"__bgColor": "#696A79",
|
||||
"bgColor": null,
|
||||
"useAutoIdentifier": false,
|
||||
"bgRelPath": "../sprites/background-lila.png",
|
||||
"bgPos": "Cover",
|
||||
"bgPivotX": 0.5,
|
||||
"bgPivotY": 0.5,
|
||||
"__smartColor": "#ADADB5",
|
||||
"__bgPos": { "topLeftPx": [0,0], "scale": [1,1], "cropRect": [0,0,640,480] },
|
||||
"externalRelPath": null,
|
||||
"fieldInstances": [],
|
||||
"layerInstances": [
|
||||
{
|
||||
"__identifier": "Entities",
|
||||
"__type": "Entities",
|
||||
"__cWid": 20,
|
||||
"__cHei": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "0243b800-d7b0-11ee-98fb-f1914bde56c8",
|
||||
"levelId": 6,
|
||||
"layerDefUid": 5,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 2072933,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": [
|
||||
{
|
||||
"__identifier": "Obstacle_West",
|
||||
"__grid": [6,8],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 0, "y": 96, "w": 32, "h": 32 },
|
||||
"__smartColor": "#BE4A2F",
|
||||
"iid": "8aab4e10-d7b0-11ee-98fb-2171f9170515",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 7,
|
||||
"px": [192,256],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 672,
|
||||
"__worldY": 256
|
||||
},
|
||||
{
|
||||
"__identifier": "Player_Primary",
|
||||
"__grid": [4,5],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 96, "w": 32, "h": 32 },
|
||||
"__smartColor": "#2F3BBE",
|
||||
"iid": "8d2c2c90-d7b0-11ee-98fb-d523a27935ba",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 3,
|
||||
"px": [128,160],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 608,
|
||||
"__worldY": 160
|
||||
},
|
||||
{
|
||||
"__identifier": "Collectible",
|
||||
"__grid": [4,9],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 },
|
||||
"__smartColor": "#FEAE34",
|
||||
"iid": "a1dfb440-d7b0-11ee-98fb-933f35aeb72b",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [128,288],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 608,
|
||||
"__worldY": 288
|
||||
},
|
||||
{
|
||||
"__identifier": "Collectible",
|
||||
"__grid": [14,6],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 32, "w": 32, "h": 32 },
|
||||
"__smartColor": "#FEAE34",
|
||||
"iid": "f7ec8340-d7b0-11ee-98fb-1fa75c7ce959",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [448,192],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 928,
|
||||
"__worldY": 192
|
||||
},
|
||||
{
|
||||
"__identifier": "Obstacle_South",
|
||||
"__grid": [15,6],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 64, "w": 32, "h": 32 },
|
||||
"__smartColor": "#E43B44",
|
||||
"iid": "45c2d010-d7b0-11ee-98fb-13d8f32ffff0",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 10,
|
||||
"px": [480,192],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 960,
|
||||
"__worldY": 192
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__identifier": "Tiles",
|
||||
"__type": "Tiles",
|
||||
"__cWid": 20,
|
||||
"__cHei": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": 1,
|
||||
"__tilesetRelPath": "../sprites/map.png",
|
||||
"iid": "0243b801-d7b0-11ee-98fb-79b1102fb094",
|
||||
"levelId": 6,
|
||||
"layerDefUid": 2,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 2952425,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [
|
||||
{ "px": [96,128], "src": [64,0], "f": 0, "t": 2, "d": [83], "a": 1 },
|
||||
{ "px": [128,128], "src": [64,0], "f": 0, "t": 2, "d": [84], "a": 1 },
|
||||
{ "px": [160,128], "src": [64,0], "f": 0, "t": 2, "d": [85], "a": 1 },
|
||||
{ "px": [192,128], "src": [64,0], "f": 0, "t": 2, "d": [86], "a": 1 },
|
||||
{ "px": [224,128], "src": [64,0], "f": 0, "t": 2, "d": [87], "a": 1 },
|
||||
{ "px": [384,128], "src": [64,0], "f": 0, "t": 2, "d": [92], "a": 1 },
|
||||
{ "px": [416,128], "src": [64,0], "f": 0, "t": 2, "d": [93], "a": 1 },
|
||||
{ "px": [448,128], "src": [64,0], "f": 0, "t": 2, "d": [94], "a": 1 },
|
||||
{ "px": [480,128], "src": [64,0], "f": 0, "t": 2, "d": [95], "a": 1 },
|
||||
{ "px": [512,128], "src": [64,0], "f": 0, "t": 2, "d": [96], "a": 1 },
|
||||
{ "px": [96,160], "src": [64,0], "f": 0, "t": 2, "d": [103], "a": 1 },
|
||||
{ "px": [224,160], "src": [64,0], "f": 0, "t": 2, "d": [107], "a": 1 },
|
||||
{ "px": [384,160], "src": [64,0], "f": 0, "t": 2, "d": [112], "a": 1 },
|
||||
{ "px": [512,160], "src": [64,0], "f": 0, "t": 2, "d": [116], "a": 1 },
|
||||
{ "px": [96,192], "src": [64,0], "f": 0, "t": 2, "d": [123], "a": 1 },
|
||||
{ "px": [224,192], "src": [64,0], "f": 0, "t": 2, "d": [127], "a": 1 },
|
||||
{ "px": [384,192], "src": [64,0], "f": 0, "t": 2, "d": [132], "a": 1 },
|
||||
{ "px": [512,192], "src": [64,0], "f": 0, "t": 2, "d": [136], "a": 1 },
|
||||
{ "px": [224,224], "src": [64,0], "f": 0, "t": 2, "d": [147], "a": 1 },
|
||||
{ "px": [384,224], "src": [64,0], "f": 0, "t": 2, "d": [152], "a": 1 },
|
||||
{ "px": [224,256], "src": [64,0], "f": 0, "t": 2, "d": [167], "a": 1 },
|
||||
{ "px": [384,256], "src": [64,0], "f": 0, "t": 2, "d": [172], "a": 1 },
|
||||
{ "px": [448,256], "src": [64,0], "f": 0, "t": 2, "d": [174], "a": 1 },
|
||||
{ "px": [224,288], "src": [64,0], "f": 0, "t": 2, "d": [187], "a": 1 },
|
||||
{ "px": [384,288], "src": [64,0], "f": 0, "t": 2, "d": [192], "a": 1 },
|
||||
{ "px": [448,288], "src": [64,0], "f": 0, "t": 2, "d": [194], "a": 1 },
|
||||
{ "px": [96,320], "src": [64,0], "f": 0, "t": 2, "d": [203], "a": 1 },
|
||||
{ "px": [128,320], "src": [64,0], "f": 0, "t": 2, "d": [204], "a": 1 },
|
||||
{ "px": [160,320], "src": [64,0], "f": 0, "t": 2, "d": [205], "a": 1 },
|
||||
{ "px": [192,320], "src": [64,0], "f": 0, "t": 2, "d": [206], "a": 1 },
|
||||
{ "px": [224,320], "src": [64,0], "f": 0, "t": 2, "d": [207], "a": 1 },
|
||||
{ "px": [384,320], "src": [64,0], "f": 0, "t": 2, "d": [212], "a": 1 },
|
||||
{ "px": [416,320], "src": [64,0], "f": 0, "t": 2, "d": [213], "a": 1 },
|
||||
{ "px": [448,320], "src": [64,0], "f": 0, "t": 2, "d": [214], "a": 1 },
|
||||
{ "px": [480,320], "src": [64,0], "f": 0, "t": 2, "d": [215], "a": 1 },
|
||||
{ "px": [512,320], "src": [64,0], "f": 0, "t": 2, "d": [216], "a": 1 }
|
||||
],
|
||||
"entityInstances": []
|
||||
}
|
||||
],
|
||||
"__neighbours": []
|
||||
}
|
||||
],
|
||||
"worlds": [],
|
||||
"dummyWorldIid": "267ee1a0-d7b0-11ee-a97e-53f0a359eae1"
|
||||
}
|
||||
@ -1,23 +1,17 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
_ "image/png"
|
||||
"io/fs"
|
||||
"log"
|
||||
"log/slog"
|
||||
"openquell/config"
|
||||
"openquell/util"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/solarlune/ldtkgo"
|
||||
)
|
||||
|
||||
var Levels = LoadLevels("levels")
|
||||
var Project = LoadLDTK("levels")
|
||||
var Tiles = InitTiles()
|
||||
|
||||
// Tile: contains image, identifier (as used in level data) and
|
||||
@ -186,44 +180,22 @@ func NewTileHiddenDoor(class []string) *Tile {
|
||||
}
|
||||
|
||||
// used to map level data bytes to actual tiles
|
||||
type TileRegistry map[byte]*Tile
|
||||
|
||||
// holds a raw level spec:
|
||||
//
|
||||
// Name: the name of the level file w/o the .lvl extension
|
||||
// Background: an image name used as game background for this level
|
||||
// Description: text to display on top
|
||||
// Data: a level spec consisting of chars of the above mapping and spaces, e.g.:
|
||||
// ####
|
||||
// # #
|
||||
// ####
|
||||
//
|
||||
// Each level data must be 20 chars wide (= 640 px width) and 15 chars
|
||||
// high (=480 px height).
|
||||
type RawLevel struct {
|
||||
Number int
|
||||
Name string
|
||||
Description string
|
||||
Background *ebiten.Image
|
||||
Data []byte
|
||||
MinMoves int
|
||||
}
|
||||
type TileRegistry map[string]*Tile
|
||||
|
||||
func InitTiles() TileRegistry {
|
||||
return TileRegistry{
|
||||
' ': {Id: ' ', Class: "floor", Renderable: false},
|
||||
//'#': NewTileBlock("block-grey32"),
|
||||
'#': NewTileBlock("block-greycolored"),
|
||||
'B': NewTileBlock("block-orange-32"),
|
||||
'S': NewTilePlayer(Primary),
|
||||
's': NewTilePlayer(Secondary),
|
||||
'o': NewTileCollectible("collectible-orange"),
|
||||
'+': NewTileObstacle("obstacle-star", config.All),
|
||||
'^': NewTileObstacle("obstacle-north", config.North),
|
||||
'v': NewTileObstacle("obstacle-south", config.South),
|
||||
'<': NewTileObstacle("obstacle-west", config.West),
|
||||
'>': NewTileObstacle("obstacle-east", config.East),
|
||||
'*': NewTileParticle([]string{
|
||||
"floor": {Id: ' ', Class: "floor", Renderable: false},
|
||||
"default": NewTileBlock("block-greycolored"),
|
||||
"solidorange": NewTileBlock("block-orange-32"),
|
||||
"player-primary": NewTilePlayer(Primary),
|
||||
"player-secondary": NewTilePlayer(Secondary),
|
||||
"collectible": NewTileCollectible("collectible-orange"),
|
||||
"obstacle-star": NewTileObstacle("obstacle-star", config.All),
|
||||
"obstacle-north": NewTileObstacle("obstacle-north", config.North),
|
||||
"obstacle-south": NewTileObstacle("obstacle-south", config.South),
|
||||
"obstacle-west": NewTileObstacle("obstacle-west", config.West),
|
||||
"obstacle-east": NewTileObstacle("obstacle-east", config.East),
|
||||
"particle": NewTileParticle([]string{
|
||||
//"particle-ring-1",
|
||||
"particle-ring-2",
|
||||
"particle-ring-3",
|
||||
@ -231,91 +203,56 @@ func InitTiles() TileRegistry {
|
||||
"particle-ring-5",
|
||||
"particle-ring-6",
|
||||
}),
|
||||
't': NewTileTranswall([]string{"transwall", "block-orange-32"}),
|
||||
'W': NewTileHiddenDoor([]string{"block-greycolored", "block-greycolored-damaged"}),
|
||||
"transient": NewTileTranswall([]string{"transwall", "block-orange-32"}),
|
||||
"hiddendoor": NewTileHiddenDoor([]string{"block-greycolored", "block-greycolored-damaged"}),
|
||||
}
|
||||
}
|
||||
|
||||
// load levels at compile time into ram, creates a slice of raw levels
|
||||
func LoadLevels(dir string) []RawLevel {
|
||||
levels := []RawLevel{}
|
||||
|
||||
// we use embed.FS to iterate over all files in ./levels/
|
||||
entries, err := assetfs.ReadDir(dir)
|
||||
// load LDTK project at compile time into ram
|
||||
func LoadLDTK(dir string) *ldtkgo.Project {
|
||||
fd, err := assetfs.Open("levels/openquell.ldtk")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read level dir %s: %s", dir, err)
|
||||
}
|
||||
|
||||
sort.Slice(entries, func(i, j int) bool {
|
||||
return entries[i].Name() < entries[j].Name()
|
||||
})
|
||||
|
||||
for idx, levelfile := range entries {
|
||||
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
|
||||
path := filepath.Join("assets", dir)
|
||||
level := ParseRawLevel(path, levelfile)
|
||||
level.Number = idx
|
||||
|
||||
levels = append(levels, level)
|
||||
|
||||
slog.Debug("loaded level", "path", path, "file", levelfile)
|
||||
}
|
||||
}
|
||||
|
||||
return levels
|
||||
}
|
||||
|
||||
func ParseRawLevel(dir string, levelfile fs.DirEntry) RawLevel {
|
||||
fd, err := os.Open(filepath.Join(dir, levelfile.Name()))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read level file %s: %s", levelfile.Name(), err)
|
||||
log.Fatalf("failed to open LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
name := strings.TrimSuffix(levelfile.Name(), ".lvl")
|
||||
name = name[3:]
|
||||
des := ""
|
||||
background := &ebiten.Image{}
|
||||
data := []byte{}
|
||||
minmoves := 0
|
||||
fileinfo, err := fd.Stat()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to stat() LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(fd)
|
||||
for scanner.Scan() {
|
||||
// ignore any whitespace
|
||||
line := scanner.Text()
|
||||
filesize := fileinfo.Size()
|
||||
buffer := make([]byte, filesize)
|
||||
|
||||
// ignore empty lines
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
_, err = fd.Read(buffer)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to read bytes from LDTK file levels/openquell.ldtk: %s", err)
|
||||
}
|
||||
|
||||
project, err := ldtkgo.Read(buffer)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// do some sanity checks
|
||||
properties := []string{"min-moves", "background", "level", "name", "descrption"}
|
||||
need := len(properties)
|
||||
|
||||
for idx, level := range project.Levels {
|
||||
have := 0
|
||||
|
||||
for _, property := range level.Properties {
|
||||
if util.Contains(properties, property.Identifier) {
|
||||
have++
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.Contains(line, "Background:"):
|
||||
haveit := strings.Split(line, ": ")
|
||||
if util.Exists(Assets, haveit[1]) {
|
||||
background = Assets[haveit[1]]
|
||||
}
|
||||
case strings.Contains(line, "Description:"):
|
||||
haveit := strings.Split(line, ": ")
|
||||
des = haveit[1]
|
||||
case strings.Contains(line, "MinMoves:"):
|
||||
haveit := strings.Split(line, ": ")
|
||||
minmoves, err = strconv.Atoi(haveit[1])
|
||||
if err != nil {
|
||||
log.Fatal("Failed to convert MinMoves to int: %w", err)
|
||||
}
|
||||
default:
|
||||
// all other non-empty and non-equalsign lines are
|
||||
// level definition matrix data, merge thes into data
|
||||
data = append(data, line+"\n"...)
|
||||
if have != need {
|
||||
log.Fatalf("level definition for level %d (%s) invalid: %d missing properties\n required: %s",
|
||||
idx, level.Identifier, need-have, strings.Join(properties, ", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return RawLevel{
|
||||
Name: name,
|
||||
Data: data,
|
||||
Background: background,
|
||||
Description: des,
|
||||
MinMoves: minmoves,
|
||||
}
|
||||
return project
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import (
|
||||
// Maps image name to image data
|
||||
type AssetRegistry map[string]*ebiten.Image
|
||||
|
||||
//go:embed levels/*.lvl sprites/*.png fonts/*.ttf
|
||||
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk
|
||||
var assetfs embed.FS
|
||||
|
||||
var Assets = LoadImages("sprites")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 584 B |
2
assets/sprites/makemap.sh
Normal file
2
assets/sprites/makemap.sh
Normal file
@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
montage -tile 4x0 -geometry +0+0 block* collectible-orange.png obstacle-* sphere-blue* transwall.png map.png && okular map.png
|
||||
BIN
assets/sprites/map.png
Normal file
BIN
assets/sprites/map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@ -28,10 +28,11 @@ func NewLevelScene(game *Game, startlevel int) Scene {
|
||||
|
||||
func (scene *LevelScene) GenerateLevels(game *Game) {
|
||||
min := []int{}
|
||||
for _, level := range assets.Levels {
|
||||
for _, level := range assets.Project.Levels {
|
||||
level := level
|
||||
scene.Levels = append(scene.Levels, NewLevel(game, 32, &level))
|
||||
min = append(min, level.MinMoves)
|
||||
scene.Levels = append(scene.Levels, NewLevel(game, 32, level))
|
||||
level.PropertyByIdentifier("min-moves")
|
||||
min = append(min, level.PropertyByIdentifier("min-moves").AsInt())
|
||||
}
|
||||
|
||||
scene.Game.Observer.SetupLevelScore(min)
|
||||
|
||||
@ -2,18 +2,17 @@ package game
|
||||
|
||||
import (
|
||||
"image"
|
||||
"log"
|
||||
"log/slog"
|
||||
"openquell/assets"
|
||||
"openquell/components"
|
||||
"openquell/grid"
|
||||
"openquell/observers"
|
||||
"openquell/systems"
|
||||
"openquell/util"
|
||||
"strings"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/mlange-42/arche/ecs"
|
||||
"github.com/solarlune/ldtkgo"
|
||||
)
|
||||
|
||||
type Map map[image.Point]*assets.Tile
|
||||
@ -31,13 +30,14 @@ type Level struct {
|
||||
Grid *grid.Grid
|
||||
}
|
||||
|
||||
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||
func NewLevel(game *Game, cellsize int, plan *ldtkgo.Level) *Level {
|
||||
systemlist := []systems.System{}
|
||||
|
||||
gridcontainer := &grid.GridContainer{}
|
||||
|
||||
systemlist = append(systemlist,
|
||||
systems.NewGridSystem(game.World, game.ScreenWidth, game.ScreenHeight, cellsize, plan.Background))
|
||||
systems.NewGridSystem(game.World, game.ScreenWidth, game.ScreenHeight, cellsize,
|
||||
assets.Assets[plan.PropertyByIdentifier("background").AsString()]))
|
||||
|
||||
systemlist = append(systemlist, systems.NewCollectibleSystem(game.World))
|
||||
|
||||
@ -63,8 +63,8 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||
World: game.World,
|
||||
Width: game.ScreenWidth,
|
||||
Height: game.ScreenHeight,
|
||||
Description: plan.Description,
|
||||
Name: plan.Name,
|
||||
Description: plan.PropertyByIdentifier("description").AsString(),
|
||||
Name: plan.Identifier,
|
||||
GridContainer: gridcontainer,
|
||||
Systems: systemlist,
|
||||
}
|
||||
@ -113,25 +113,51 @@ func (level *Level) SetupGrid(game *Game) {
|
||||
}
|
||||
|
||||
// parses a RawLevel and generates a mapslice from it, which is being used as grid
|
||||
func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) (Map, Map) {
|
||||
func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) {
|
||||
size := game.ScreenWidth * game.ScreenHeight
|
||||
mapslice := make(Map, size)
|
||||
backupmap := make(Map, size)
|
||||
|
||||
for y, line := range strings.Split(string(level.Data), "\n") {
|
||||
if len(line) != game.ScreenWidth/tilesize && y < game.ScreenHeight/tilesize {
|
||||
log.Fatalf("line %d doesn't contain %d tiles, but %d",
|
||||
y, game.ScreenWidth/tilesize, len(line))
|
||||
}
|
||||
for _, layer := range level.Layers {
|
||||
switch layer.Type {
|
||||
case ldtkgo.LayerTypeTile:
|
||||
// load tile from LDTK tile layer, use sprites from associated map.
|
||||
|
||||
for x, char := range line {
|
||||
if !util.Exists(assets.Tiles, byte(char)) {
|
||||
log.Fatalf("unregistered tile type %c encountered", char)
|
||||
if tiles := layer.AllTiles(); len(tiles) > 0 {
|
||||
for _, tileData := range tiles {
|
||||
// Subimage the Tile from the already loaded map,
|
||||
// but referenced from LDTK file, that way we
|
||||
// could use multiple tileset images
|
||||
tile := assets.Tiles["default"]
|
||||
tile.Sprite = assets.Assets[strings.TrimSuffix(layer.Tileset.Path, ".png")].SubImage(
|
||||
image.Rect(tileData.Src[0],
|
||||
tileData.Src[1],
|
||||
tileData.Src[0]+layer.GridSize,
|
||||
tileData.Src[1]+layer.GridSize)).(*ebiten.Image)
|
||||
|
||||
mapslice[image.Point{tileData.Position[0], tileData.Position[1]}] = tile
|
||||
backupmap[image.Point{tileData.Position[0], tileData.Position[1]}] = tile.Clone()
|
||||
}
|
||||
}
|
||||
|
||||
tile := assets.Tiles[byte(char)]
|
||||
mapslice[image.Point{x, y}] = tile
|
||||
backupmap[image.Point{x, y}] = tile.Clone()
|
||||
case ldtkgo.LayerTypeEntity:
|
||||
// load mobile tiles (they call them entities) using static map map.png.
|
||||
tileset := assets.Assets["map"]
|
||||
|
||||
for _, entity := range layer.Entities {
|
||||
if entity.TileRect != nil {
|
||||
tile := assets.Tiles[entity.Identifier]
|
||||
|
||||
tileRect := entity.TileRect
|
||||
tile.Sprite = tileset.SubImage(
|
||||
image.Rect(tileRect.X, tileRect.Y,
|
||||
tileRect.X+tileRect.W,
|
||||
tileRect.Y+tileRect.H)).(*ebiten.Image)
|
||||
|
||||
mapslice[image.Point{entity.Position[0], entity.Position[1]}] = tile
|
||||
backupmap[image.Point{entity.Position[0], entity.Position[1]}] = tile.Clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@ -22,7 +22,11 @@ require (
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/solarlune/ldtkgo v0.9.4-0.20240310011150-66aa15c2ab56 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tidwall/gjson v1.9.3 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
github.com/tinne26/etxt v0.0.8 // indirect
|
||||
github.com/tlinden/yadu v0.1.3 // indirect
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
|
||||
|
||||
8
go.sum
8
go.sum
@ -253,6 +253,8 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/solarlune/ldtkgo v0.9.4-0.20240310011150-66aa15c2ab56 h1:QW8w9YQbIlIW053jM2SfBKAFGyd4maoq0AawZsb9rO4=
|
||||
github.com/solarlune/ldtkgo v0.9.4-0.20240310011150-66aa15c2ab56/go.mod h1:PP4XtlnCSwWo7iexI/NJ3aS3INmiT42o066o6Dx52rs=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -262,6 +264,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E=
|
||||
github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tinne26/etxt v0.0.8 h1:rjb58jkMkapRGLmhBMWnT76E/nMTXC5P1Q956BRZkoc=
|
||||
github.com/tinne26/etxt v0.0.8/go.mod h1:QM/hlNkstsKC39elTFNKAR34xsMb9QoVosf+g9wlYxM=
|
||||
github.com/tlinden/yadu v0.1.2 h1:TYYVnUJwziRJ9YPbIbRf9ikmDw0Q8Ifixm+J/kBQFh8=
|
||||
|
||||
@ -158,7 +158,7 @@ func (grid *Grid) RemoveTile(point image.Point) {
|
||||
}
|
||||
|
||||
func (grid *Grid) SetFloorTile(point image.Point) {
|
||||
grid.Map[point] = assets.Tiles[' ']
|
||||
grid.Map[point] = assets.Tiles["floor"]
|
||||
}
|
||||
|
||||
func (grid *Grid) SetSolidTile(tile *assets.Tile, point image.Point) {
|
||||
|
||||
@ -114,8 +114,8 @@ func (system *CollectibleSystem) AddParticle(position *components.Position) {
|
||||
pos, particle, timer := ptmapper.Get(entity)
|
||||
observer.AddEntity(entity, particleID)
|
||||
|
||||
particle.Index = assets.Tiles['*'].Particle
|
||||
particle.Tiles = assets.Tiles['*'].Tiles
|
||||
particle.Index = assets.Tiles["particle"].Particle
|
||||
particle.Tiles = assets.Tiles["particle"].Tiles
|
||||
|
||||
pos.Update(
|
||||
position.X-(16), // FIXME: use global tilesize!
|
||||
|
||||
@ -8,16 +8,17 @@ import (
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/mlange-42/arche/ecs"
|
||||
"github.com/solarlune/ldtkgo"
|
||||
)
|
||||
|
||||
type HudSystem struct {
|
||||
World *ecs.World
|
||||
Cellsize int
|
||||
Observer *observers.GameObserver
|
||||
Plan *assets.RawLevel
|
||||
Plan *ldtkgo.Level
|
||||
}
|
||||
|
||||
func NewHudSystem(world *ecs.World, plan *assets.RawLevel) System {
|
||||
func NewHudSystem(world *ecs.World, plan *ldtkgo.Level) System {
|
||||
system := &HudSystem{
|
||||
Observer: observers.GetGameObserver(world),
|
||||
World: world,
|
||||
@ -45,13 +46,14 @@ func (system *HudSystem) Draw(screen *ebiten.Image) {
|
||||
*/
|
||||
|
||||
score := fmt.Sprintf("Score: %d", system.Observer.GetScore())
|
||||
level := fmt.Sprintf("Level %d %s", system.Plan.Number, system.Plan.Name)
|
||||
level := fmt.Sprintf("Level %d %s", system.Plan.PropertyByIdentifier("level").AsInt(),
|
||||
system.Plan.PropertyByIdentifier("name").AsString())
|
||||
|
||||
assets.FontRenderer.Renderer.SetSizePx(20)
|
||||
assets.FontRenderer.Renderer.SetTarget(screen)
|
||||
|
||||
system.Print(score, 515, 22)
|
||||
system.Print(system.Plan.Description, 10, 470)
|
||||
system.Print(system.Plan.PropertyByIdentifier("description").AsString(), 10, 470)
|
||||
system.Print(level, 10, 22)
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package systems
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"openquell/assets"
|
||||
"openquell/components"
|
||||
. "openquell/components"
|
||||
. "openquell/config"
|
||||
@ -146,33 +145,6 @@ func (system *ObstacleSystem) Draw(screen *ebiten.Image) {
|
||||
}
|
||||
}
|
||||
|
||||
func (system *ObstacleSystem) AddParticle(position *components.Position) {
|
||||
observer := observers.GetGameObserver(system.World)
|
||||
|
||||
ptmapper := generic.NewMap3[
|
||||
components.Position,
|
||||
components.Particle,
|
||||
components.Timer,
|
||||
](system.World)
|
||||
|
||||
particleID := ecs.ComponentID[components.Particle](system.World)
|
||||
|
||||
entity := ptmapper.New()
|
||||
pos, particle, timer := ptmapper.Get(entity)
|
||||
observer.AddEntity(entity, particleID)
|
||||
|
||||
particle.Index = assets.Tiles['*'].Particle
|
||||
particle.Tiles = assets.Tiles['*'].Tiles
|
||||
|
||||
pos.Update(
|
||||
position.X-(16), // FIXME: use global tilesize!
|
||||
position.Y-(16),
|
||||
64,
|
||||
)
|
||||
|
||||
timer.Start(PARTICLE_LOOPWAIT)
|
||||
}
|
||||
|
||||
// return true if obstacle weapon points into the direction the player is moving
|
||||
func CheckObstacleSide(playervelocity *Velocity, obsdirection int) bool {
|
||||
movingdirection := playervelocity.InvertDirection()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user