switched to go coded animation system, LDTK is not used for this anymore
This commit is contained in:
parent
2793710819
commit
f23bdaf121
@ -14,62 +14,66 @@ import (
|
|||||||
var Project = LoadLDTK("levels")
|
var Project = LoadLDTK("levels")
|
||||||
var Tiles = InitTiles()
|
var Tiles = InitTiles()
|
||||||
|
|
||||||
|
type TileAnimation struct {
|
||||||
|
OnCollision bool // wether to animate a collision
|
||||||
|
OnDestruction bool // wether to animate destruction
|
||||||
|
OnIdle bool // wether to animate during idling
|
||||||
|
|
||||||
|
CollisionSheet AnimationSet // an entry in assets.Animations[name]
|
||||||
|
DestructionSheet AnimationSet
|
||||||
|
IdleSheet AnimationSet
|
||||||
|
}
|
||||||
|
|
||||||
// Tile: contains image, identifier (as used in level data) and
|
// Tile: contains image, identifier (as used in level data) and
|
||||||
// additional properties
|
// additional properties
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
Id, Ref string
|
Id, Ref string
|
||||||
Sprite *ebiten.Image
|
Sprite *ebiten.Image
|
||||||
ToggleSprite *ebiten.Image
|
ToggleSprite *ebiten.Image
|
||||||
Solid bool // wall brick
|
Solid bool // wall brick
|
||||||
Player bool // player sphere
|
Player bool // player sphere
|
||||||
IsPrimary bool // primary player sphere
|
IsPrimary bool // primary player sphere
|
||||||
Renderable bool // visible, has sprite
|
Renderable bool // visible, has sprite
|
||||||
Velocity bool // movable
|
Velocity bool // movable
|
||||||
Collectible bool // collectible, vanishes once collected
|
Collectible bool // collectible, vanishes once collected
|
||||||
Transient bool // turns into brick wall when traversed
|
Transient bool // turns into brick wall when traversed
|
||||||
Destroyable bool // turns into empty floor when bumped into twice
|
Destroyable bool // turns into empty floor when bumped into twice
|
||||||
Animation int // -1=unused, 0-3 = show image of slice
|
Tiles []*ebiten.Image // has N sprites
|
||||||
Tiles []*ebiten.Image // has N sprites
|
TileNames []string // same thing, only the names
|
||||||
TileNames []string // same thing, only the names
|
Obstacle bool // is an obstacle/enemy
|
||||||
Obstacle bool // is an obstacle/enemy
|
Direction int // obstacle business end shows into this direction
|
||||||
Direction int // obstacle business end shows into this direction
|
Shader *ebiten.Shader
|
||||||
Shader *ebiten.Shader
|
Alpha *ebiten.Image
|
||||||
Alpha *ebiten.Image
|
Bond bool // denotes an entity which can have a relation to another
|
||||||
Bond bool // denotes an entity which can have a relation to another
|
Door bool // a door, can be manipulated by a switch
|
||||||
Door bool // a door, can be manipulated by a switch
|
Switch bool // opens|closes a door
|
||||||
Switch bool // opens|closes a door
|
Animation TileAnimation
|
||||||
AnimateOnDestruct bool // wether to animate destruction
|
|
||||||
AnimationTrigger string // dynamically configured via LDTP
|
|
||||||
AnimationSpriteSheet AnimationSet // which sprites to use (refers to an entry in assets.Animations[name])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tile *Tile) Clone() *Tile {
|
func (tile *Tile) Clone() *Tile {
|
||||||
newtile := &Tile{
|
newtile := &Tile{
|
||||||
Id: tile.Id,
|
Id: tile.Id,
|
||||||
Ref: tile.Ref,
|
Ref: tile.Ref,
|
||||||
Sprite: tile.Sprite,
|
Sprite: tile.Sprite,
|
||||||
ToggleSprite: tile.ToggleSprite,
|
ToggleSprite: tile.ToggleSprite,
|
||||||
Solid: tile.Solid,
|
Solid: tile.Solid,
|
||||||
Player: tile.Player,
|
Player: tile.Player,
|
||||||
IsPrimary: tile.IsPrimary,
|
IsPrimary: tile.IsPrimary,
|
||||||
Renderable: tile.Renderable,
|
Renderable: tile.Renderable,
|
||||||
Velocity: tile.Velocity,
|
Velocity: tile.Velocity,
|
||||||
Collectible: tile.Collectible,
|
Collectible: tile.Collectible,
|
||||||
Transient: tile.Transient,
|
Transient: tile.Transient,
|
||||||
Destroyable: tile.Destroyable,
|
Destroyable: tile.Destroyable,
|
||||||
Animation: tile.Animation,
|
Tiles: tile.Tiles,
|
||||||
Tiles: tile.Tiles,
|
TileNames: tile.TileNames,
|
||||||
TileNames: tile.TileNames,
|
Obstacle: tile.Obstacle,
|
||||||
Obstacle: tile.Obstacle,
|
Direction: tile.Direction,
|
||||||
Direction: tile.Direction,
|
Alpha: tile.Alpha,
|
||||||
Alpha: tile.Alpha,
|
Shader: tile.Shader,
|
||||||
Shader: tile.Shader,
|
Bond: tile.Bond,
|
||||||
Bond: tile.Bond,
|
Door: tile.Door,
|
||||||
Door: tile.Door,
|
Switch: tile.Switch,
|
||||||
Switch: tile.Switch,
|
Animation: tile.Animation,
|
||||||
AnimateOnDestruct: tile.AnimateOnDestruct,
|
|
||||||
AnimationSpriteSheet: tile.AnimationSpriteSheet,
|
|
||||||
AnimationTrigger: tile.AnimationTrigger,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newtile
|
return newtile
|
||||||
@ -115,6 +119,12 @@ func NewTileCollectible() *Tile {
|
|||||||
Solid: false,
|
Solid: false,
|
||||||
Renderable: true,
|
Renderable: true,
|
||||||
Collectible: true,
|
Collectible: true,
|
||||||
|
Animation: TileAnimation{
|
||||||
|
OnDestruction: true,
|
||||||
|
DestructionSheet: Animations["collectible-detonating"],
|
||||||
|
OnIdle: true,
|
||||||
|
IdleSheet: Animations["collectible-idle"],
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,17 +138,6 @@ func NewTileObstacle(direction int) *Tile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTileAnimation(class []string) *Tile {
|
|
||||||
sprites := GetSprites(class)
|
|
||||||
|
|
||||||
return &Tile{
|
|
||||||
Solid: false,
|
|
||||||
Renderable: false,
|
|
||||||
Animation: 0,
|
|
||||||
Tiles: sprites,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTileTranswall() *Tile {
|
func NewTileTranswall() *Tile {
|
||||||
return &Tile{
|
return &Tile{
|
||||||
Solid: false,
|
Solid: false,
|
||||||
@ -191,39 +190,22 @@ func InitTiles() TileRegistry {
|
|||||||
"ObstacleSouth": NewTileObstacle(config.South),
|
"ObstacleSouth": NewTileObstacle(config.South),
|
||||||
"ObstacleWest": NewTileObstacle(config.West),
|
"ObstacleWest": NewTileObstacle(config.West),
|
||||||
"ObstacleEast": NewTileObstacle(config.East),
|
"ObstacleEast": NewTileObstacle(config.East),
|
||||||
"Animation": NewTileAnimation([]string{
|
"Transient": NewTileTranswall(),
|
||||||
"collectible-detonating1",
|
"HiddenDoor": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating2",
|
"HiddenDoor2": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating3",
|
"HiddenDoor3": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating4",
|
"HiddenDoor4": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating5",
|
"HiddenDoor5": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating6",
|
"HiddenDoor6": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating7",
|
"HiddenDoor7": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating8",
|
"HiddenDoor8": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating9",
|
"HiddenDoor9": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating10",
|
"HiddenDoor10": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating11",
|
"HiddenDoor11": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating12",
|
"HiddenDoor12": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating13",
|
"HiddenDoor13": NewTileHiddenDoor("damage"),
|
||||||
"collectible-detonating14",
|
"Switch": NewTileSwitch(),
|
||||||
"collectible-detonating15",
|
"Door": NewTileDoor(),
|
||||||
}),
|
|
||||||
"Transient": NewTileTranswall(),
|
|
||||||
"HiddenDoor": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor2": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor3": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor4": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor5": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor6": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor7": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor8": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor9": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor10": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor11": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor12": NewTileHiddenDoor("damage"),
|
|
||||||
"HiddenDoor13": NewTileHiddenDoor("damage"),
|
|
||||||
"Switch": NewTileSwitch(),
|
|
||||||
"Door": NewTileDoor(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,6 +60,9 @@ type AnimationSet struct {
|
|||||||
File string
|
File string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// names in the registry match the sprite set png file name, the JSON
|
||||||
|
// file names are irrelevant as they point to the matching file using
|
||||||
|
// the "image" field.
|
||||||
type AnimationRegistry map[string]AnimationSet
|
type AnimationRegistry map[string]AnimationSet
|
||||||
|
|
||||||
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk shaders/*.kg sprites/*.json
|
//go:embed sprites/*.png fonts/*.ttf levels/*.ldtk shaders/*.kg sprites/*.json
|
||||||
|
|||||||
@ -1,42 +1,42 @@
|
|||||||
{ "frames": [
|
{ "frames": [
|
||||||
{
|
{
|
||||||
"filename": "collectible 0.ase",
|
"filename": "collectible #Detonation 0.ase",
|
||||||
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 64, "h": 64 },
|
||||||
"duration": 100
|
"duration": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 1.ase",
|
"filename": "collectible #Detonation 1.ase",
|
||||||
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 64, "h": 64 },
|
||||||
"duration": 100
|
"duration": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 2.ase",
|
"filename": "collectible #Detonation 2.ase",
|
||||||
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 64, "h": 64 },
|
||||||
"duration": 100
|
"duration": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 3.ase",
|
"filename": "collectible #Detonation 3.ase",
|
||||||
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 64, "h": 64 },
|
||||||
"duration": 100
|
"duration": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 4.ase",
|
"filename": "collectible #Detonation 4.ase",
|
||||||
"frame": { "x": 256, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 256, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -45,7 +45,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 5.ase",
|
"filename": "collectible #Detonation 5.ase",
|
||||||
"frame": { "x": 320, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 320, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -54,7 +54,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 6.ase",
|
"filename": "collectible #Detonation 6.ase",
|
||||||
"frame": { "x": 384, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 384, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -63,7 +63,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 7.ase",
|
"filename": "collectible #Detonation 7.ase",
|
||||||
"frame": { "x": 448, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 448, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -72,7 +72,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 8.ase",
|
"filename": "collectible #Detonation 8.ase",
|
||||||
"frame": { "x": 512, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 512, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -81,7 +81,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 9.ase",
|
"filename": "collectible #Detonation 9.ase",
|
||||||
"frame": { "x": 576, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 576, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -90,7 +90,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 10.ase",
|
"filename": "collectible #Detonation 10.ase",
|
||||||
"frame": { "x": 640, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 640, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 11.ase",
|
"filename": "collectible #Detonation 11.ase",
|
||||||
"frame": { "x": 704, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 704, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -108,7 +108,7 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 12.ase",
|
"filename": "collectible #Detonation 12.ase",
|
||||||
"frame": { "x": 768, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 768, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
@ -117,22 +117,13 @@
|
|||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible 13.ase",
|
"filename": "collectible #Detonation 13.ase",
|
||||||
"frame": { "x": 832, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 832, "y": 0, "w": 64, "h": 64 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 64, "h": 64 },
|
||||||
"duration": 100
|
"duration": 100
|
||||||
},
|
|
||||||
{
|
|
||||||
"filename": "collectible 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": {
|
"meta": {
|
||||||
@ -140,9 +131,10 @@
|
|||||||
"version": "1.x-dev",
|
"version": "1.x-dev",
|
||||||
"image": "collectible-detonating.png",
|
"image": "collectible-detonating.png",
|
||||||
"format": "I8",
|
"format": "I8",
|
||||||
"size": { "w": 960, "h": 64 },
|
"size": { "w": 896, "h": 64 },
|
||||||
"scale": "1",
|
"scale": "1",
|
||||||
"frameTags": [
|
"frameTags": [
|
||||||
|
{ "name": "Detonation", "from": 1, "to": 14, "direction": "forward" }
|
||||||
],
|
],
|
||||||
"layers": [
|
"layers": [
|
||||||
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.1 KiB |
BIN
assets/sprites/collectible-idle.ase
Normal file
BIN
assets/sprites/collectible-idle.ase
Normal file
Binary file not shown.
@ -1,38 +1,38 @@
|
|||||||
{ "frames": [
|
{ "frames": [
|
||||||
{
|
{
|
||||||
"filename": "collectible #Idle 0.ase",
|
"filename": "collectible-idle 0.ase",
|
||||||
"frame": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 32, "h": 32 },
|
||||||
"duration": 200
|
"duration": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible #Idle 1.ase",
|
"filename": "collectible-idle 1.ase",
|
||||||
"frame": { "x": 64, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 32, "y": 0, "w": 32, "h": 32 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 32, "h": 32 },
|
||||||
"duration": 200
|
"duration": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible #Idle 2.ase",
|
"filename": "collectible-idle 2.ase",
|
||||||
"frame": { "x": 128, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 64, "y": 0, "w": 32, "h": 32 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 32, "h": 32 },
|
||||||
"duration": 200
|
"duration": 200
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"filename": "collectible #Idle 3.ase",
|
"filename": "collectible-idle 3.ase",
|
||||||
"frame": { "x": 192, "y": 0, "w": 64, "h": 64 },
|
"frame": { "x": 96, "y": 0, "w": 32, "h": 32 },
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"trimmed": false,
|
"trimmed": false,
|
||||||
"spriteSourceSize": { "x": 0, "y": 0, "w": 64, "h": 64 },
|
"spriteSourceSize": { "x": 0, "y": 0, "w": 32, "h": 32 },
|
||||||
"sourceSize": { "w": 64, "h": 64 },
|
"sourceSize": { "w": 32, "h": 32 },
|
||||||
"duration": 200
|
"duration": 200
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -40,26 +40,13 @@
|
|||||||
"app": "http://www.aseprite.org/",
|
"app": "http://www.aseprite.org/",
|
||||||
"version": "1.x-dev",
|
"version": "1.x-dev",
|
||||||
"image": "collectible-idle.png",
|
"image": "collectible-idle.png",
|
||||||
"format": "I8",
|
"format": "RGBA8888",
|
||||||
"size": { "w": 256, "h": 64 },
|
"size": { "w": 128, "h": 32 },
|
||||||
"scale": "1",
|
"scale": "1",
|
||||||
"frameTags": [
|
"frameTags": [
|
||||||
{ "name": "Detonation", "from": 1, "to": 14, "direction": "forward" },
|
|
||||||
{ "name": "Idle", "from": 15, "to": 18, "direction": "forward" }
|
|
||||||
],
|
],
|
||||||
"layers": [
|
"layers": [
|
||||||
{ "name": "Yellow Sphere", "opacity": 255, "blendMode": "normal" },
|
{ "name": "Layer 1", "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": [
|
"slices": [
|
||||||
]
|
]
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 685 B After Width: | Height: | Size: 931 B |
Binary file not shown.
@ -4,7 +4,9 @@ package components
|
|||||||
type Tilish struct{}
|
type Tilish struct{}
|
||||||
type Solid struct{}
|
type Solid struct{}
|
||||||
type Floor struct{}
|
type Floor struct{}
|
||||||
type Collectible struct{}
|
type Collectible struct {
|
||||||
|
Hit bool
|
||||||
|
}
|
||||||
|
|
||||||
type Obstacle struct {
|
type Obstacle struct {
|
||||||
Direction int
|
Direction int
|
||||||
|
|||||||
@ -8,40 +8,66 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Destruction = iota
|
||||||
|
Idle
|
||||||
|
Collision
|
||||||
|
)
|
||||||
|
|
||||||
// virtual location, aka tile address
|
// virtual location, aka tile address
|
||||||
type Animation struct {
|
type Animation struct {
|
||||||
Active bool // animation is running
|
Active bool // animation is running
|
||||||
Loop bool // remove the entity if false, loop endless otherwise
|
Loop bool // remove the entity if false, loop endless otherwise
|
||||||
Index int // where we are currently
|
Index int // where we are currently
|
||||||
Sprites []assets.AnimationSprite
|
Sprites []assets.AnimationSprite // each element contains the sprite and duration
|
||||||
Width, Height int // single sprite measurements
|
Width, Height int // single sprite measurements
|
||||||
Timer Timer
|
Timer Timer
|
||||||
Trigger string
|
Trigger string
|
||||||
|
Data assets.TileAnimation
|
||||||
}
|
}
|
||||||
|
|
||||||
type Renderable struct {
|
type Renderable struct {
|
||||||
Pos *Position // just for debugging, will not used as positiion!
|
Pos *Position // just for debugging, will not used as positiion!
|
||||||
Image *ebiten.Image
|
Image *ebiten.Image
|
||||||
DamageImage *ebiten.Image // FIXME: put into its own struct
|
DamageImage *ebiten.Image // FIXME: put into its own struct
|
||||||
Damaged int
|
Damaged int
|
||||||
Shader *ebiten.Shader
|
Shader *ebiten.Shader
|
||||||
Animate Animation
|
DestructionAnimate Animation
|
||||||
IdleAnimate Animation
|
IdleAnimate Animation
|
||||||
Hidden bool
|
CollisionAnimate Animation
|
||||||
|
Hidden bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (render *Renderable) StartAnimation() {
|
func (render *Renderable) StartAnimation(which int) {
|
||||||
render.Hidden = true
|
switch which {
|
||||||
render.Animate.Active = true
|
case Collision:
|
||||||
render.Animate.Timer.Start(config.ANIMATION_STARTWAIT)
|
|
||||||
|
|
||||||
switch render.Animate.Trigger {
|
|
||||||
case "OnCollision":
|
|
||||||
fallthrough
|
fallthrough
|
||||||
case "OnDestruct":
|
case Destruction:
|
||||||
render.Animate.Loop = false
|
render.Hidden = true
|
||||||
case "OnIdle":
|
render.DestructionAnimate.Active = true
|
||||||
render.Animate.Loop = true
|
render.DestructionAnimate.Timer.Start(config.ANIMATION_STARTWAIT)
|
||||||
|
render.IdleAnimate.Active = false
|
||||||
|
case Idle:
|
||||||
|
render.IdleAnimate.Active = true
|
||||||
|
render.IdleAnimate.Loop = true
|
||||||
|
render.IdleAnimate.Timer.Start(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (render *Renderable) StopAnimation(which int) {
|
||||||
|
switch which {
|
||||||
|
case Collision:
|
||||||
|
render.CollisionAnimate.Active = false
|
||||||
|
case Idle:
|
||||||
|
render.IdleAnimate.Active = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (render *Renderable) Animations() map[int]*Animation {
|
||||||
|
return map[int]*Animation{
|
||||||
|
Collision: &render.CollisionAnimate,
|
||||||
|
Destruction: &render.DestructionAnimate,
|
||||||
|
Idle: &render.IdleAnimate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,8 @@ const (
|
|||||||
PLAYERSPEED int = 5
|
PLAYERSPEED int = 5
|
||||||
ANIMATION_STARTWAIT time.Duration = 30 * time.Millisecond // how long to wait to start collectible animation
|
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
|
ANIMATION_LOOPWAIT time.Duration = 40 * time.Millisecond // how much time to wait between the sprites
|
||||||
LEVEL_END_WAIT time.Duration = 500 * time.Millisecond
|
LEVEL_END_WAIT time.Duration = 100 * time.Millisecond
|
||||||
version string = "1.3.0"
|
version string = "1.4.0"
|
||||||
|
|
||||||
MenuRectX int = 600
|
MenuRectX int = 600
|
||||||
MenuRectY int = 0
|
MenuRectY int = 0
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package game
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"image"
|
"image"
|
||||||
"log"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"openquell/assets"
|
"openquell/assets"
|
||||||
"openquell/components"
|
"openquell/components"
|
||||||
@ -198,27 +197,6 @@ func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) {
|
|||||||
}
|
}
|
||||||
tileRect := entity.TileRect
|
tileRect := entity.TileRect
|
||||||
|
|
||||||
animationtrigger := util.GetPropertyString(entity, "AnimationTrigger")
|
|
||||||
slog.Debug("got trigger", "trigger", animationtrigger)
|
|
||||||
|
|
||||||
//animateondestruct := util.GetPropertyBool(entity, "AnimateOnDestruct")
|
|
||||||
// FIXME: also check for AnimationLoop and other animation reasons
|
|
||||||
// if animateondestruct {
|
|
||||||
if animationtrigger != "" {
|
|
||||||
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.AnimationTrigger = animationtrigger
|
|
||||||
}
|
|
||||||
|
|
||||||
tile.Sprite = tileset.SubImage(
|
tile.Sprite = tileset.SubImage(
|
||||||
image.Rect(tileRect.X, tileRect.Y,
|
image.Rect(tileRect.X, tileRect.Y,
|
||||||
tileRect.X+tileRect.W,
|
tileRect.X+tileRect.W,
|
||||||
|
|||||||
25
grid/grid.go
25
grid/grid.go
@ -159,13 +159,24 @@ func NewGrid(world *ecs.World,
|
|||||||
render.Image = tile.Sprite
|
render.Image = tile.Sprite
|
||||||
render.Pos = pos
|
render.Pos = pos
|
||||||
|
|
||||||
//if tile.AnimateOnDestruct {
|
if tile.Animation.OnCollision {
|
||||||
if tile.AnimationTrigger != "" {
|
render.CollisionAnimate.Sprites = tile.Animation.CollisionSheet.Sprites
|
||||||
// FIXME: be more generic, use LDTK enum
|
render.CollisionAnimate.Width = tile.Animation.CollisionSheet.Width
|
||||||
render.Animate.Sprites = tile.AnimationSpriteSheet.Sprites
|
render.CollisionAnimate.Height = tile.Animation.CollisionSheet.Height
|
||||||
render.Animate.Width = tile.AnimationSpriteSheet.Width
|
}
|
||||||
render.Animate.Height = tile.AnimationSpriteSheet.Height
|
|
||||||
render.Animate.Trigger = tile.AnimationTrigger
|
if tile.Animation.OnDestruction {
|
||||||
|
render.DestructionAnimate.Sprites = tile.Animation.DestructionSheet.Sprites
|
||||||
|
render.DestructionAnimate.Width = tile.Animation.DestructionSheet.Width
|
||||||
|
render.DestructionAnimate.Height = tile.Animation.DestructionSheet.Height
|
||||||
|
}
|
||||||
|
|
||||||
|
if tile.Animation.OnIdle {
|
||||||
|
render.IdleAnimate.Sprites = tile.Animation.IdleSheet.Sprites
|
||||||
|
render.IdleAnimate.Width = tile.Animation.IdleSheet.Width
|
||||||
|
render.IdleAnimate.Height = tile.Animation.IdleSheet.Height
|
||||||
|
render.StartAnimation(components.Idle)
|
||||||
|
render.Hidden = true // we do NOT render the sprite, but the idle animation instead
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
package systems
|
package systems
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"openquell/components"
|
||||||
. "openquell/components"
|
. "openquell/components"
|
||||||
"openquell/config"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/mlange-42/arche/ecs"
|
"github.com/mlange-42/arche/ecs"
|
||||||
@ -32,28 +33,35 @@ func (system *AnimationSystem) Update() error {
|
|||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
_, render := query.Get()
|
_, render := query.Get()
|
||||||
if render.Animate.Active {
|
|
||||||
if render.Animate.Timer.IsReady() {
|
for animationtype, animate := range render.Animations() {
|
||||||
switch {
|
if animate.Active {
|
||||||
// animation shows from earlier tick, animate
|
if animate.Timer.IsReady() {
|
||||||
case render.Animate.Index > -1 && render.Animate.Index < len(render.Animate.Sprites)-1:
|
switch {
|
||||||
render.Animate.Index += 1
|
// animation shows from earlier tick, animate
|
||||||
render.Animate.Timer.Start(config.ANIMATION_LOOPWAIT)
|
case animate.Index > -1 && animate.Index < len(animate.Sprites)-1:
|
||||||
default:
|
animate.Index += 1
|
||||||
// last sprite reached
|
animate.Timer.Start(animate.GetDuration())
|
||||||
if render.Animate.Loop {
|
default:
|
||||||
render.Animate.Index = 0
|
// last sprite reached
|
||||||
} else {
|
if animate.Loop {
|
||||||
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
|
animate.Index = 0
|
||||||
|
animate.Timer.Start(animate.GetDuration())
|
||||||
|
}
|
||||||
|
|
||||||
|
if animationtype == components.Destruction {
|
||||||
|
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
animate.Timer.Update()
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
render.Animate.Timer.Update()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entity := range EntitiesToRemove {
|
for _, entity := range EntitiesToRemove {
|
||||||
|
slog.Debug("remove collectible")
|
||||||
system.World.RemoveEntity(entity)
|
system.World.RemoveEntity(entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,10 +76,13 @@ func (system *AnimationSystem) Draw(screen *ebiten.Image) {
|
|||||||
for query.Next() {
|
for query.Next() {
|
||||||
pos, render := query.Get()
|
pos, render := query.Get()
|
||||||
|
|
||||||
if render.Animate.Active {
|
for _, animate := range render.Animations() {
|
||||||
op.GeoM.Reset()
|
if animate.Active {
|
||||||
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
op.GeoM.Reset()
|
||||||
screen.DrawImage(render.Animate.GetSprite(), op)
|
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||||
|
sprite := animate.GetSprite()
|
||||||
|
screen.DrawImage(sprite, op)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"openquell/components"
|
"openquell/components"
|
||||||
. "openquell/components"
|
. "openquell/components"
|
||||||
|
|
||||||
. "openquell/config"
|
. "openquell/config"
|
||||||
"openquell/observers"
|
"openquell/observers"
|
||||||
|
|
||||||
@ -38,12 +39,18 @@ func (system *CollectibleSystem) Update() error {
|
|||||||
numcollectibles := query.Count()
|
numcollectibles := query.Count()
|
||||||
|
|
||||||
if numcollectibles == 0 || observer.Lost {
|
if numcollectibles == 0 || observer.Lost {
|
||||||
|
slog.Debug("WON")
|
||||||
|
timer := observers.GetGameObserver(system.World).StopTimer
|
||||||
|
if !timer.Running {
|
||||||
|
timer.Start(LEVEL_END_WAIT)
|
||||||
|
|
||||||
|
}
|
||||||
query.Close()
|
query.Close()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
colposition, _, render := query.Get()
|
colposition, collectible, render := query.Get()
|
||||||
|
|
||||||
for _, player := range observer.GetPlayers() {
|
for _, player := range observer.GetPlayers() {
|
||||||
if !system.World.Alive(player) {
|
if !system.World.Alive(player) {
|
||||||
@ -54,10 +61,10 @@ func (system *CollectibleSystem) Update() error {
|
|||||||
playervelocity := (*Velocity)(system.World.Get(player, veloID))
|
playervelocity := (*Velocity)(system.World.Get(player, veloID))
|
||||||
|
|
||||||
ok, _ := colposition.Intersects(playerposition, playervelocity)
|
ok, _ := colposition.Intersects(playerposition, playervelocity)
|
||||||
if ok && !render.Hidden {
|
if ok && !collectible.Hit {
|
||||||
slog.Debug("bumped into collectible", "colpos", colposition)
|
slog.Debug("bumped into collectible", "colpos", colposition)
|
||||||
|
|
||||||
render.StartAnimation()
|
render.StartAnimation(components.Destruction)
|
||||||
|
|
||||||
// position the animation relative to the middle of the current entity
|
// position the animation relative to the middle of the current entity
|
||||||
colposition.Update(
|
colposition.Update(
|
||||||
@ -65,19 +72,13 @@ func (system *CollectibleSystem) Update() error {
|
|||||||
colposition.Y-(system.Cellsize/2),
|
colposition.Y-(system.Cellsize/2),
|
||||||
64,
|
64,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
collectible.Hit = true
|
||||||
numcollectibles--
|
numcollectibles--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if numcollectibles == 0 {
|
|
||||||
// winner, winner, chicken dinner!
|
|
||||||
timer := observers.GetGameObserver(system.World).StopTimer
|
|
||||||
if !timer.Running {
|
|
||||||
timer.Start(LEVEL_END_WAIT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user