renamed particle* to animation*, added asesprite animation loading
This commit is contained in:
parent
20fa2639c6
commit
001b67f97a
11
TODO.md
11
TODO.md
@ -37,6 +37,17 @@
|
||||
"collectible-detonating*.png" or we could use an animation map and
|
||||
specify a list of coordinates, etcpp.
|
||||
|
||||
- Part I of the above: DONE.
|
||||
- Part II:
|
||||
- grid/grid.go:
|
||||
- add Animation component to mappers
|
||||
- check if the tile has tile.AnimateOnDestruct (or any other
|
||||
triggers) set and configure animation compontent accordingly
|
||||
- check if the tile has tile.AnimationSpriteSheet, assign to Animation.Tiles[]
|
||||
- do it for any entity not just collectible so that any entity can have an animation
|
||||
- rename Animation.Tiles to Sprites
|
||||
- change animation_system to use this stuff instead of any hardcoded values.
|
||||
|
||||
|
||||
## Collider Rework [abandoned: see branch collider-system, fails]
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"iid": "267e9380-d7b0-11ee-a97e-35bec9c19d52",
|
||||
"jsonVersion": "1.5.3",
|
||||
"appBuildId": 473703,
|
||||
"nextUid": 76,
|
||||
"nextUid": 78,
|
||||
"identifierStyle": "Capitalize",
|
||||
"toc": [],
|
||||
"worldLayout": "Free",
|
||||
@ -215,7 +215,88 @@
|
||||
"limitBehavior": "MoveLastOne",
|
||||
"pivotX": 0,
|
||||
"pivotY": 0,
|
||||
"fieldDefs": []
|
||||
"fieldDefs": [
|
||||
{
|
||||
"identifier": "AnimateOnDestruct",
|
||||
"doc": null,
|
||||
"__type": "Bool",
|
||||
"uid": 76,
|
||||
"type": "F_Bool",
|
||||
"isArray": false,
|
||||
"canBeNull": false,
|
||||
"arrayMinLength": null,
|
||||
"arrayMaxLength": null,
|
||||
"editorDisplayMode": "Hidden",
|
||||
"editorDisplayScale": 1,
|
||||
"editorDisplayPos": "Above",
|
||||
"editorLinkStyle": "StraightArrow",
|
||||
"editorDisplayColor": null,
|
||||
"editorAlwaysShow": false,
|
||||
"editorShowInWorld": true,
|
||||
"editorCutLongValues": true,
|
||||
"editorTextSuffix": null,
|
||||
"editorTextPrefix": null,
|
||||
"useForSmartColor": false,
|
||||
"exportToToc": false,
|
||||
"searchable": false,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"regex": null,
|
||||
"acceptFileTypes": null,
|
||||
"defaultOverride": {
|
||||
"id": "V_Bool",
|
||||
"params": [ true ]
|
||||
},
|
||||
"textLanguageMode": null,
|
||||
"symmetricalRef": false,
|
||||
"autoChainRef": true,
|
||||
"allowOutOfLevelRef": true,
|
||||
"allowedRefs": "OnlySame",
|
||||
"allowedRefsEntityUid": null,
|
||||
"allowedRefTags": [],
|
||||
"tilesetUid": null
|
||||
},
|
||||
{
|
||||
"identifier": "AnimateSpriteSheet",
|
||||
"doc": null,
|
||||
"__type": "String",
|
||||
"uid": 77,
|
||||
"type": "F_String",
|
||||
"isArray": false,
|
||||
"canBeNull": true,
|
||||
"arrayMinLength": null,
|
||||
"arrayMaxLength": null,
|
||||
"editorDisplayMode": "Hidden",
|
||||
"editorDisplayScale": 1,
|
||||
"editorDisplayPos": "Above",
|
||||
"editorLinkStyle": "StraightArrow",
|
||||
"editorDisplayColor": null,
|
||||
"editorAlwaysShow": false,
|
||||
"editorShowInWorld": true,
|
||||
"editorCutLongValues": true,
|
||||
"editorTextSuffix": null,
|
||||
"editorTextPrefix": null,
|
||||
"useForSmartColor": false,
|
||||
"exportToToc": false,
|
||||
"searchable": false,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"regex": null,
|
||||
"acceptFileTypes": null,
|
||||
"defaultOverride": {
|
||||
"id": "V_String",
|
||||
"params": ["collectible-detonating"]
|
||||
},
|
||||
"textLanguageMode": null,
|
||||
"symmetricalRef": false,
|
||||
"autoChainRef": true,
|
||||
"allowOutOfLevelRef": true,
|
||||
"allowedRefs": "OnlySame",
|
||||
"allowedRefsEntityUid": null,
|
||||
"allowedRefTags": [],
|
||||
"tilesetUid": null
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"identifier": "ObstacleWest",
|
||||
@ -1429,7 +1510,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 128,
|
||||
"__worldY": 224
|
||||
},
|
||||
@ -1445,7 +1529,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 64,
|
||||
"__worldY": 160
|
||||
},
|
||||
@ -1461,7 +1548,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [384,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 160,
|
||||
"__worldY": 160
|
||||
}
|
||||
@ -1613,7 +1703,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [128,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 608,
|
||||
"__worldY": 288
|
||||
},
|
||||
@ -1629,7 +1722,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [480,192],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 960,
|
||||
"__worldY": 192
|
||||
}
|
||||
@ -1786,7 +1882,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [96,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1280,
|
||||
"__worldY": 160
|
||||
}
|
||||
@ -1906,7 +2005,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [448,128],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2336,
|
||||
"__worldY": 128
|
||||
},
|
||||
@ -1922,7 +2024,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [128,384],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2016,
|
||||
"__worldY": 384
|
||||
}
|
||||
@ -2095,7 +2200,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 64,
|
||||
"__worldY": 768
|
||||
},
|
||||
@ -2159,7 +2267,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 128,
|
||||
"__worldY": 768
|
||||
},
|
||||
@ -2349,7 +2460,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 768,
|
||||
"__worldY": 768
|
||||
},
|
||||
@ -2571,7 +2685,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [96,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1280,
|
||||
"__worldY": 704
|
||||
},
|
||||
@ -2619,7 +2736,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [320,352],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1504,
|
||||
"__worldY": 896
|
||||
},
|
||||
@ -2651,7 +2771,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [128,128],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1312,
|
||||
"__worldY": 672
|
||||
},
|
||||
@ -2831,7 +2954,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [224,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2112,
|
||||
"__worldY": 704
|
||||
},
|
||||
@ -2863,7 +2989,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [416,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2304,
|
||||
"__worldY": 768
|
||||
},
|
||||
@ -2911,7 +3040,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2176,
|
||||
"__worldY": 832
|
||||
},
|
||||
@ -3089,7 +3221,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [160,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": -64,
|
||||
"__worldY": 1312
|
||||
},
|
||||
@ -3105,7 +3240,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [192,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": -32,
|
||||
"__worldY": 1376
|
||||
},
|
||||
@ -3309,7 +3447,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 832,
|
||||
"__worldY": 1376
|
||||
},
|
||||
@ -3561,7 +3702,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [416,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1600,
|
||||
"__worldY": 1376
|
||||
},
|
||||
@ -3609,7 +3753,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [416,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1600,
|
||||
"__worldY": 1248
|
||||
},
|
||||
@ -3917,7 +4064,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [192,256],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2080,
|
||||
"__worldY": 1344
|
||||
},
|
||||
@ -4113,7 +4263,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [320,192],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 96,
|
||||
"__worldY": 1824
|
||||
},
|
||||
@ -4129,7 +4282,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,256],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 64,
|
||||
"__worldY": 1888
|
||||
},
|
||||
@ -4145,7 +4301,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,256],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 128,
|
||||
"__worldY": 1888
|
||||
},
|
||||
@ -4369,7 +4528,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [160,320],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 640,
|
||||
"__worldY": 1952
|
||||
},
|
||||
@ -4385,7 +4547,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [192,320],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 672,
|
||||
"__worldY": 1952
|
||||
},
|
||||
@ -4417,7 +4582,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [416,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 896,
|
||||
"__worldY": 1856
|
||||
},
|
||||
@ -4623,7 +4791,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [480,320],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1664,
|
||||
"__worldY": 1952
|
||||
},
|
||||
@ -4655,7 +4826,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [288,192],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1472,
|
||||
"__worldY": 1824
|
||||
},
|
||||
@ -4687,7 +4861,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,128],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1536,
|
||||
"__worldY": 1760
|
||||
},
|
||||
@ -4703,7 +4880,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [192,288],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1376,
|
||||
"__worldY": 1920
|
||||
},
|
||||
@ -5106,7 +5286,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [224,192],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2112,
|
||||
"__worldY": 1824
|
||||
}
|
||||
@ -5269,7 +5452,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [256,224],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 32,
|
||||
"__worldY": 2432
|
||||
},
|
||||
@ -5525,7 +5711,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [384,256],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 896,
|
||||
"__worldY": 2464
|
||||
},
|
||||
@ -5605,7 +5794,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [352,192],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 864,
|
||||
"__worldY": 2400
|
||||
}
|
||||
@ -5767,7 +5959,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [320,256],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1536,
|
||||
"__worldY": 2464
|
||||
},
|
||||
@ -5783,7 +5978,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [224,128],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1440,
|
||||
"__worldY": 2336
|
||||
},
|
||||
@ -5799,7 +5997,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [384,320],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 1600,
|
||||
"__worldY": 2528
|
||||
}
|
||||
@ -5997,7 +6198,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [416,352],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2304,
|
||||
"__worldY": 2560
|
||||
},
|
||||
@ -6013,7 +6217,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [160,128],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": 2048,
|
||||
"__worldY": 2336
|
||||
},
|
||||
@ -6255,7 +6462,10 @@
|
||||
"height": 32,
|
||||
"defUid": 4,
|
||||
"px": [160,160],
|
||||
"fieldInstances": [],
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "AnimateOnDestruct", "__type": "Bool", "__value": true, "__tile": null, "defUid": 76, "realEditorValues": [] },
|
||||
{ "__identifier": "AnimateSpriteSheet", "__type": "String", "__value": "collectible-detonating", "__tile": null, "defUid": 77, "realEditorValues": [] }
|
||||
],
|
||||
"__worldX": -64,
|
||||
"__worldY": 2912
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ type Tile struct {
|
||||
Collectible bool // collectible, vanishes once collected
|
||||
Transient bool // turns into brick wall when traversed
|
||||
Destroyable bool // turns into empty floor when bumped into twice
|
||||
Particle int // -1=unused, 0-3 = show image of slice
|
||||
Animation int // -1=unused, 0-3 = show image of slice
|
||||
Tiles []*ebiten.Image // has N sprites
|
||||
TileNames []string // same thing, only the names
|
||||
Obstacle bool // is an obstacle/enemy
|
||||
@ -38,6 +38,8 @@ type Tile struct {
|
||||
Bond bool // denotes an entity which can have a relation to another
|
||||
Door bool // a door, can be manipulated by a switch
|
||||
Switch bool // opens|closes a door
|
||||
AnimateOnDestruct bool // wether to animate destruction
|
||||
AnimationSpriteSheet AnimationSet // which sprites to use (refers to an entry in assets.Animations[name])
|
||||
}
|
||||
|
||||
func (tile *Tile) Clone() *Tile {
|
||||
@ -54,7 +56,7 @@ func (tile *Tile) Clone() *Tile {
|
||||
Collectible: tile.Collectible,
|
||||
Transient: tile.Transient,
|
||||
Destroyable: tile.Destroyable,
|
||||
Particle: tile.Particle,
|
||||
Animation: tile.Animation,
|
||||
Tiles: tile.Tiles,
|
||||
TileNames: tile.TileNames,
|
||||
Obstacle: tile.Obstacle,
|
||||
@ -64,6 +66,8 @@ func (tile *Tile) Clone() *Tile {
|
||||
Bond: tile.Bond,
|
||||
Door: tile.Door,
|
||||
Switch: tile.Switch,
|
||||
AnimateOnDestruct: tile.AnimateOnDestruct,
|
||||
AnimationSpriteSheet: tile.AnimationSpriteSheet,
|
||||
}
|
||||
|
||||
return newtile
|
||||
@ -129,13 +133,13 @@ func NewTileObstacle(direction int) *Tile {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileParticle(class []string) *Tile {
|
||||
func NewTileAnimation(class []string) *Tile {
|
||||
sprites := GetSprites(class)
|
||||
|
||||
return &Tile{
|
||||
Solid: false,
|
||||
Renderable: false,
|
||||
Particle: 0,
|
||||
Animation: 0,
|
||||
Tiles: sprites,
|
||||
}
|
||||
}
|
||||
@ -192,7 +196,7 @@ func InitTiles() TileRegistry {
|
||||
"ObstacleSouth": NewTileObstacle(config.South),
|
||||
"ObstacleWest": NewTileObstacle(config.West),
|
||||
"ObstacleEast": NewTileObstacle(config.East),
|
||||
"Particle": NewTileParticle([]string{
|
||||
"Animation": NewTileAnimation([]string{
|
||||
"collectible-detonating1",
|
||||
"collectible-detonating2",
|
||||
"collectible-detonating3",
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"embed"
|
||||
"encoding/json"
|
||||
"image"
|
||||
_ "image/png"
|
||||
"log"
|
||||
@ -9,19 +11,55 @@ import (
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/alecthomas/repr"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
)
|
||||
|
||||
// Maps image name to image data
|
||||
type AssetRegistry map[string]*ebiten.Image
|
||||
|
||||
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk shaders/*.kg
|
||||
type AnimationGeo struct {
|
||||
X int `json:"x"`
|
||||
Y int `json:"y"`
|
||||
Width int `json:"w"`
|
||||
Height int `json:"h"`
|
||||
}
|
||||
|
||||
type AnimationFrame struct {
|
||||
Position AnimationGeo `json:"frame"`
|
||||
// FIXME: maybe also add delay etc? might be cool to tweak these things from LDTK
|
||||
}
|
||||
|
||||
type AnimationMeta struct {
|
||||
Name string `json:"image"`
|
||||
Geo AnimationGeo `json:"size"`
|
||||
}
|
||||
|
||||
// Needed to thaw sprite set written by asesprite
|
||||
type AnimationJSON struct {
|
||||
Meta AnimationMeta `json:"Meta"`
|
||||
Frames []AnimationFrame `json:"frames"`
|
||||
}
|
||||
|
||||
// Animation data
|
||||
type AnimationSet struct {
|
||||
Width, Height int
|
||||
Sprites []*ebiten.Image
|
||||
File string
|
||||
}
|
||||
|
||||
type AnimationRegistry map[string]AnimationSet
|
||||
|
||||
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk shaders/*.kg sprites/*.json
|
||||
var assetfs embed.FS
|
||||
|
||||
var Assets = LoadImages("sprites")
|
||||
var Assets, Animations = LoadImages()
|
||||
|
||||
func LoadImages(dir string) AssetRegistry {
|
||||
func LoadImages() (AssetRegistry, AnimationRegistry) {
|
||||
dir := "sprites"
|
||||
images := AssetRegistry{}
|
||||
rawanimations := []AnimationJSON{}
|
||||
animations := AnimationRegistry{}
|
||||
|
||||
// we use embed.FS to iterate over all files in ./assets/
|
||||
entries, err := assetfs.ReadDir(dir)
|
||||
@ -31,6 +69,9 @@ func LoadImages(dir string) AssetRegistry {
|
||||
|
||||
for _, imagefile := range entries {
|
||||
path := path.Join(dir, imagefile.Name())
|
||||
|
||||
switch {
|
||||
case strings.HasSuffix(path, ".png"):
|
||||
fd, err := assetfs.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open image file %s: %s", imagefile.Name(), err)
|
||||
@ -47,7 +88,50 @@ func LoadImages(dir string) AssetRegistry {
|
||||
images[name] = ebiten.NewImageFromImage(img)
|
||||
|
||||
slog.Debug("loaded asset", "path", path)
|
||||
case strings.HasSuffix(path, ".json"):
|
||||
fd, err := assetfs.Open(path)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open json file %s: %s", imagefile.Name(), err)
|
||||
}
|
||||
defer fd.Close()
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(fd)
|
||||
|
||||
animationjson := AnimationJSON{}
|
||||
|
||||
err = json.Unmarshal(buf.Bytes(), &animationjson)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to parse JSON: %s", err)
|
||||
}
|
||||
|
||||
return images
|
||||
rawanimations = append(rawanimations, animationjson)
|
||||
}
|
||||
}
|
||||
|
||||
// preprocess animation sprites
|
||||
for _, animation := range rawanimations {
|
||||
animationset := AnimationSet{}
|
||||
|
||||
animationset.File = strings.TrimSuffix(animation.Meta.Name, ".png")
|
||||
animationset.Width = animation.Meta.Geo.Width
|
||||
animationset.Height = animation.Meta.Geo.Height
|
||||
|
||||
for _, frame := range animation.Frames {
|
||||
sprite := images[animationset.File].SubImage(
|
||||
image.Rect(
|
||||
frame.Position.X,
|
||||
frame.Position.Y,
|
||||
frame.Position.Width,
|
||||
frame.Position.Height,
|
||||
)).(*ebiten.Image)
|
||||
|
||||
animationset.Sprites = append(animationset.Sprites, sprite)
|
||||
}
|
||||
|
||||
animations[animationset.File] = animationset
|
||||
}
|
||||
|
||||
repr.Println(animations)
|
||||
return images, animations
|
||||
}
|
||||
|
||||
164
assets/sprites/collectible-detonating.json
Normal file
164
assets/sprites/collectible-detonating.json
Normal file
@ -0,0 +1,164 @@
|
||||
{ "frames": [
|
||||
{
|
||||
"filename": "collectible-detonating 0.ase",
|
||||
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 1.ase",
|
||||
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 2.ase",
|
||||
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 3.ase",
|
||||
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 4.ase",
|
||||
"frame": { "x": 256, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 5.ase",
|
||||
"frame": { "x": 320, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 6.ase",
|
||||
"frame": { "x": 384, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 7.ase",
|
||||
"frame": { "x": 448, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 8.ase",
|
||||
"frame": { "x": 512, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 9.ase",
|
||||
"frame": { "x": 576, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 10.ase",
|
||||
"frame": { "x": 640, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 11.ase",
|
||||
"frame": { "x": 704, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 12.ase",
|
||||
"frame": { "x": 768, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 13.ase",
|
||||
"frame": { "x": 832, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
},
|
||||
{
|
||||
"filename": "collectible-detonating 14.ase",
|
||||
"frame": { "x": 896, "y": 0, "w": 64, "h": 64 },
|
||||
"rotated": false,
|
||||
"trimmed": false,
|
||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||
"sourceSize": { "w": 64, "h": 64 },
|
||||
"duration": 100
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"app": "http://www.aseprite.org/",
|
||||
"version": "1.x-dev",
|
||||
"image": "collectible-detonating.png",
|
||||
"format": "RGBA8888",
|
||||
"size": { "w": 960, "h": 64 },
|
||||
"scale": "1",
|
||||
"frameTags": [
|
||||
],
|
||||
"layers": [
|
||||
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 8", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 7", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 6", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 5", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 4", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 3", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 2", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Layer 1", "opacity": 255, "blendMode": "normal" },
|
||||
{ "name": "Blitz Outer", "opacity": 70, "blendMode": "normal" },
|
||||
{ "name": "Blitz Middle", "opacity": 84, "blendMode": "normal" },
|
||||
{ "name": "Blitz Inner", "opacity": 97, "blendMode": "normal" }
|
||||
],
|
||||
"slices": [
|
||||
]
|
||||
}
|
||||
}
|
||||
BIN
assets/sprites/collectible-detonating.png
Normal file
BIN
assets/sprites/collectible-detonating.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
11
components/animation.go
Normal file
11
components/animation.go
Normal file
@ -0,0 +1,11 @@
|
||||
package components
|
||||
|
||||
import "github.com/hajimehoshi/ebiten/v2"
|
||||
|
||||
type Animation struct {
|
||||
Show bool
|
||||
Index int
|
||||
Loop bool
|
||||
Tiles []*ebiten.Image
|
||||
Width, Height int // single sprite measurements
|
||||
}
|
||||
@ -14,12 +14,6 @@ type Renderable struct {
|
||||
Shader *ebiten.Shader
|
||||
}
|
||||
|
||||
type Particle struct {
|
||||
Show bool
|
||||
Index int
|
||||
Tiles []*ebiten.Image
|
||||
}
|
||||
|
||||
// only tile entities will have those
|
||||
type Tilish struct{}
|
||||
type Solid struct{}
|
||||
|
||||
@ -15,8 +15,8 @@ const (
|
||||
|
||||
const (
|
||||
PLAYERSPEED int = 5
|
||||
PARTICLE_STARTWAIT time.Duration = 30 * time.Millisecond // how long to wait to start collectible particle
|
||||
PARTICLE_LOOPWAIT time.Duration = 40 * time.Millisecond // how much time to wait between the sprites
|
||||
ANIMATION_STARTWAIT time.Duration = 30 * time.Millisecond // how long to wait to start collectible animation
|
||||
ANIMATION_LOOPWAIT time.Duration = 40 * time.Millisecond // how much time to wait between the sprites
|
||||
LEVEL_END_WAIT time.Duration = 500 * time.Millisecond
|
||||
version string = "1.2.3"
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ package game
|
||||
|
||||
import (
|
||||
"image"
|
||||
"log"
|
||||
"log/slog"
|
||||
"openquell/assets"
|
||||
"openquell/components"
|
||||
@ -51,7 +52,7 @@ func NewLevel(game *Game, cellsize int, plan *ldtkgo.Level) *Level {
|
||||
systemlist = append(systemlist,
|
||||
systems.NewPlayerSystem(game.World, gridcontainer, game.ScreenWidth, game.ScreenHeight))
|
||||
|
||||
systemlist = append(systemlist, systems.NewParticleSystem(game.World, game.Cellsize))
|
||||
systemlist = append(systemlist, systems.NewAnimationSystem(game.World, game.Cellsize))
|
||||
|
||||
systemlist = append(systemlist, systems.NewTransientSystem(game.World, gridcontainer))
|
||||
|
||||
@ -197,6 +198,22 @@ func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) {
|
||||
}
|
||||
tileRect := entity.TileRect
|
||||
|
||||
animateondestruct := util.GetPropertyBool(entity, "AnimateOnDestruct")
|
||||
// FIXME: also check for AnimationLoop and other animation reasons
|
||||
if animateondestruct {
|
||||
tile.AnimateOnDestruct = true
|
||||
|
||||
animation := util.GetPropertyString(entity, "AnimateSpriteSheet")
|
||||
if animation != "" {
|
||||
if !util.Exists(assets.Animations, animation) {
|
||||
log.Fatalf("entity %s refers to non existent animation set %s",
|
||||
entity.Identifier, animation)
|
||||
}
|
||||
}
|
||||
|
||||
tile.AnimationSpriteSheet = assets.Animations[animation]
|
||||
}
|
||||
|
||||
tile.Sprite = tileset.SubImage(
|
||||
image.Rect(tileRect.X, tileRect.Y,
|
||||
tileRect.X+tileRect.W,
|
||||
|
||||
@ -57,16 +57,16 @@ func NewGameObserver(
|
||||
|
||||
playerID := ecs.ComponentID[components.Player](world)
|
||||
obstacleID := ecs.ComponentID[components.Obstacle](world)
|
||||
particleID := ecs.ComponentID[components.Particle](world)
|
||||
animationID := ecs.ComponentID[components.Animation](world)
|
||||
|
||||
playerListener := observer.GetListenerCallback(playerID)
|
||||
obstacleListener := observer.GetListenerCallback(obstacleID)
|
||||
particleListener := observer.GetListenerCallback(particleID)
|
||||
animationListener := observer.GetListenerCallback(animationID)
|
||||
|
||||
listen := listener.NewDispatch(
|
||||
&playerListener,
|
||||
&obstacleListener,
|
||||
&particleListener,
|
||||
&animationListener,
|
||||
)
|
||||
|
||||
world.SetListener(&listen)
|
||||
@ -74,7 +74,7 @@ func NewGameObserver(
|
||||
observer.Entities = make(map[ecs.ID]map[ecs.Entity]int)
|
||||
observer.Entities[playerID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[obstacleID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[particleID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[animationID] = make(map[ecs.Entity]int)
|
||||
|
||||
resmanger := generic.NewResource[GameObserver](world)
|
||||
resmanger.Add(observer)
|
||||
@ -119,20 +119,20 @@ func (observer *GameObserver) GetObstacles() []ecs.Entity {
|
||||
return observer.GetEntities(obstacleID)
|
||||
}
|
||||
|
||||
func (observer *GameObserver) GetParticles() []ecs.Entity {
|
||||
particleID := ecs.ComponentID[components.Particle](observer.World)
|
||||
return observer.GetEntities(particleID)
|
||||
func (observer *GameObserver) GetAnimations() []ecs.Entity {
|
||||
animationID := ecs.ComponentID[components.Animation](observer.World)
|
||||
return observer.GetEntities(animationID)
|
||||
}
|
||||
|
||||
func (observer *GameObserver) RemoveEntities() {
|
||||
playerID := ecs.ComponentID[components.Player](observer.World)
|
||||
obstacleID := ecs.ComponentID[components.Obstacle](observer.World)
|
||||
particleID := ecs.ComponentID[components.Particle](observer.World)
|
||||
animationID := ecs.ComponentID[components.Animation](observer.World)
|
||||
|
||||
observer.Entities = make(map[ecs.ID]map[ecs.Entity]int)
|
||||
observer.Entities[playerID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[obstacleID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[particleID] = make(map[ecs.Entity]int)
|
||||
observer.Entities[animationID] = make(map[ecs.Entity]int)
|
||||
}
|
||||
|
||||
func (observer *GameObserver) SetupLevelScore(min []int) {
|
||||
|
||||
@ -9,15 +9,15 @@ import (
|
||||
"github.com/mlange-42/arche/generic"
|
||||
)
|
||||
|
||||
type ParticleSystem struct {
|
||||
type AnimationSystem struct {
|
||||
World *ecs.World
|
||||
Selector *generic.Filter3[Position, Particle, Timer]
|
||||
Selector *generic.Filter3[Position, Animation, Timer]
|
||||
Cellsize int
|
||||
}
|
||||
|
||||
func NewParticleSystem(world *ecs.World, cellsize int) System {
|
||||
system := &ParticleSystem{
|
||||
Selector: generic.NewFilter3[Position, Particle, Timer](),
|
||||
func NewAnimationSystem(world *ecs.World, cellsize int) System {
|
||||
system := &AnimationSystem{
|
||||
Selector: generic.NewFilter3[Position, Animation, Timer](),
|
||||
World: world,
|
||||
Cellsize: cellsize,
|
||||
}
|
||||
@ -25,7 +25,7 @@ func NewParticleSystem(world *ecs.World, cellsize int) System {
|
||||
return system
|
||||
}
|
||||
|
||||
func (system *ParticleSystem) Update() error {
|
||||
func (system *AnimationSystem) Update() error {
|
||||
// display debris after collecting
|
||||
EntitiesToRemove := []ecs.Entity{}
|
||||
|
||||
@ -33,16 +33,16 @@ func (system *ParticleSystem) Update() error {
|
||||
|
||||
for query.Next() {
|
||||
// we loop, but it's only one anyway
|
||||
_, particle, timer := query.Get()
|
||||
_, animation, timer := query.Get()
|
||||
|
||||
particle.Show = true
|
||||
animation.Show = true
|
||||
|
||||
if timer.IsReady() {
|
||||
switch {
|
||||
// particle shows from earlier tick, animate
|
||||
case particle.Index > -1 && particle.Index < len(particle.Tiles)-1:
|
||||
particle.Index++
|
||||
timer.Start(config.PARTICLE_LOOPWAIT)
|
||||
// animation shows from earlier tick, animate
|
||||
case animation.Index > -1 && animation.Index < len(animation.Tiles)-1:
|
||||
animation.Index++
|
||||
timer.Start(config.ANIMATION_LOOPWAIT)
|
||||
default:
|
||||
// last sprite reached, remove it
|
||||
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
|
||||
@ -60,18 +60,18 @@ func (system *ParticleSystem) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (system *ParticleSystem) Draw(screen *ebiten.Image) {
|
||||
// write particles (these are no tiles!)
|
||||
func (system *AnimationSystem) Draw(screen *ebiten.Image) {
|
||||
// write animations (these are no tiles!)
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
query := system.Selector.Query(system.World)
|
||||
|
||||
for query.Next() {
|
||||
pos, particle, _ := query.Get()
|
||||
pos, animation, _ := query.Get()
|
||||
|
||||
if particle.Show {
|
||||
if animation.Show {
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||
screen.DrawImage(particle.Tiles[particle.Index], op)
|
||||
screen.DrawImage(animation.Tiles[animation.Index], op)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -33,7 +33,7 @@ func (system *CollectibleSystem) Update() error {
|
||||
posID := ecs.ComponentID[components.Position](system.World)
|
||||
veloID := ecs.ComponentID[components.Velocity](system.World)
|
||||
|
||||
particlepositions := []*components.Position{}
|
||||
animationpositions := []*components.Position{}
|
||||
EntitiesToRemove := []ecs.Entity{}
|
||||
|
||||
query := system.Selector.Query(system.World)
|
||||
@ -58,14 +58,14 @@ func (system *CollectibleSystem) Update() error {
|
||||
ok, _ := colposition.Intersects(playerposition, playervelocity)
|
||||
if ok {
|
||||
//slog.Debug("bumped into collectible", "collectible", collectible)
|
||||
particlepositions = append(particlepositions, colposition)
|
||||
animationpositions = append(animationpositions, colposition)
|
||||
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, pos := range particlepositions {
|
||||
system.AddParticle(pos)
|
||||
for _, pos := range animationpositions {
|
||||
system.AddAnimation(pos)
|
||||
}
|
||||
|
||||
for _, entity := range EntitiesToRemove {
|
||||
@ -99,23 +99,23 @@ func (system *CollectibleSystem) Draw(screen *ebiten.Image) {
|
||||
}
|
||||
}
|
||||
|
||||
func (system *CollectibleSystem) AddParticle(position *components.Position) {
|
||||
func (system *CollectibleSystem) AddAnimation(position *components.Position) {
|
||||
observer := observers.GetGameObserver(system.World)
|
||||
|
||||
ptmapper := generic.NewMap3[
|
||||
components.Position,
|
||||
components.Particle,
|
||||
components.Animation,
|
||||
components.Timer,
|
||||
](system.World)
|
||||
|
||||
particleID := ecs.ComponentID[components.Particle](system.World)
|
||||
animationID := ecs.ComponentID[components.Animation](system.World)
|
||||
|
||||
entity := ptmapper.New()
|
||||
pos, particle, timer := ptmapper.Get(entity)
|
||||
observer.AddEntity(entity, particleID)
|
||||
pos, animation, timer := ptmapper.Get(entity)
|
||||
observer.AddEntity(entity, animationID)
|
||||
|
||||
particle.Index = assets.Tiles["Particle"].Particle
|
||||
particle.Tiles = assets.Tiles["Particle"].Tiles
|
||||
animation.Index = assets.Tiles["Animation"].Animation
|
||||
animation.Tiles = assets.Tiles["Animation"].Tiles
|
||||
|
||||
pos.Update(
|
||||
position.X-(16), // FIXME: use global tilesize!
|
||||
@ -123,5 +123,5 @@ func (system *CollectibleSystem) AddParticle(position *components.Position) {
|
||||
64,
|
||||
)
|
||||
|
||||
timer.Start(config.PARTICLE_STARTWAIT)
|
||||
timer.Start(config.ANIMATION_STARTWAIT)
|
||||
}
|
||||
|
||||
@ -11,7 +11,6 @@ type TileSetSubRect struct {
|
||||
}
|
||||
|
||||
func Map2Subrect(raw map[string]any) *TileSetSubRect {
|
||||
|
||||
// we need to translate this map for less typing
|
||||
return &TileSetSubRect{
|
||||
W: int(raw["w"].(float64)),
|
||||
@ -37,8 +36,25 @@ func GetPropertyRef(entity *ldtkgo.Entity) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetPropertyToggleTile(entity *ldtkgo.Entity) *TileSetSubRect {
|
||||
func GetPropertyString(entity *ldtkgo.Entity, property string) string {
|
||||
ref := entity.PropertyByIdentifier(property)
|
||||
if ref != nil {
|
||||
return ref.AsString()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func GetPropertyBool(entity *ldtkgo.Entity, property string) bool {
|
||||
ref := entity.PropertyByIdentifier(property)
|
||||
if ref != nil {
|
||||
return ref.AsBool()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func GetPropertyToggleTile(entity *ldtkgo.Entity) *TileSetSubRect {
|
||||
ref := entity.PropertyByIdentifier(config.LDTK_Toggle_Tile)
|
||||
if ref != nil {
|
||||
return Map2Subrect(ref.AsMap())
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user