added detonation particles after collectibles have been collected
This commit is contained in:
parent
d17594dc38
commit
006216398a
@ -28,6 +28,8 @@ type Tile struct {
|
||||
Renderable bool
|
||||
Velocity bool
|
||||
Collectible bool
|
||||
Particle int // -1=unused, 0-3 = show image of slice
|
||||
Particles []*ebiten.Image
|
||||
}
|
||||
|
||||
func NewTilePlayer() *Tile {
|
||||
@ -62,6 +64,23 @@ func NewTileCollectible(class string) *Tile {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTileParticle(class []string) *Tile {
|
||||
sprites := []*ebiten.Image{}
|
||||
|
||||
for _, sprite := range class {
|
||||
sprites = append(sprites, Assets[sprite])
|
||||
}
|
||||
|
||||
return &Tile{
|
||||
Id: '*',
|
||||
Class: "particle",
|
||||
Solid: false,
|
||||
Renderable: false,
|
||||
Particle: -1,
|
||||
Particles: sprites,
|
||||
}
|
||||
}
|
||||
|
||||
// used to map level data bytes to actual tiles
|
||||
type TileRegistry map[byte]*Tile
|
||||
|
||||
@ -90,6 +109,10 @@ func InitTiles() TileRegistry {
|
||||
'#': NewTileBlock("block-grey32"),
|
||||
'S': NewTilePlayer(),
|
||||
'o': NewTileCollectible("collectible-orange"),
|
||||
'*': NewTileParticle([]string{
|
||||
"particle-dust-0", "particle-dust-0", "particle-dust-1", "particle-dust-1",
|
||||
"particle-dust-0", "particle-dust-2", "particle-dust-3", "particle-dust-3",
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BIN
assets/sprites/particle-dust-0.png
Normal file
BIN
assets/sprites/particle-dust-0.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
BIN
assets/sprites/particle-dust-1.png
Normal file
BIN
assets/sprites/particle-dust-1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
BIN
assets/sprites/particle-dust-2.png
Normal file
BIN
assets/sprites/particle-dust-2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
BIN
assets/sprites/particle-dust-3.png
Normal file
BIN
assets/sprites/particle-dust-3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
@ -16,3 +16,8 @@ type Solid struct{}
|
||||
type Floor struct{}
|
||||
type Player struct{}
|
||||
type Collectible struct{}
|
||||
|
||||
type Particle struct {
|
||||
Index int
|
||||
Particles []*ebiten.Image
|
||||
}
|
||||
|
||||
11
game/grid.go
11
game/grid.go
@ -46,6 +46,11 @@ func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *G
|
||||
components.Renderable,
|
||||
components.Collectible](game.World)
|
||||
|
||||
ptmapper := generic.NewMap2[
|
||||
components.Position,
|
||||
components.Particle,
|
||||
](game.World)
|
||||
|
||||
var pos *components.Position
|
||||
var render *components.Renderable
|
||||
|
||||
@ -81,6 +86,12 @@ func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *G
|
||||
pos.Update(point.X*tilesize, point.Y*tilesize, tilesize)
|
||||
}
|
||||
|
||||
// not part of the grid, but add them as well
|
||||
entity := ptmapper.New()
|
||||
_, particle := ptmapper.Get(entity)
|
||||
particle.Index = assets.Tiles['*'].Particle
|
||||
particle.Particles = assets.Tiles['*'].Particles
|
||||
|
||||
return &Grid{
|
||||
Size: len(mapslice),
|
||||
Tilesize: tilesize,
|
||||
|
||||
102
game/levels.go
102
game/levels.go
@ -36,16 +36,25 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||
velocityid := ecs.ComponentID[components.Velocity](game.World)
|
||||
playerid := ecs.ComponentID[components.Player](game.World)
|
||||
colid := ecs.ComponentID[components.Collectible](game.World)
|
||||
ptid := ecs.ComponentID[components.Particle](game.World)
|
||||
sid := ecs.ComponentID[components.Solid](game.World)
|
||||
renderid := ecs.ComponentID[components.Renderable](game.World)
|
||||
|
||||
selectors := map[string]ecs.Mask{}
|
||||
selectors["player"] = filter.All(positionid, velocityid, playerid)
|
||||
selectors["tile"] = filter.All(renderid, positionid, sid)
|
||||
selectors["movable"] = filter.All(renderid, positionid)
|
||||
selectors["collectible"] = filter.All(positionid, colid)
|
||||
selectors["particle"] = filter.All(positionid, ptid)
|
||||
|
||||
components := map[string]ecs.ID{}
|
||||
components["position"] = positionid
|
||||
components["velocity"] = velocityid
|
||||
components["player"] = playerid
|
||||
components["collectible"] = colid
|
||||
components["particle"] = ptid
|
||||
components["solid"] = sid
|
||||
components["renderable"] = renderid
|
||||
|
||||
return &Level{
|
||||
Mapslice: LevelToSlice(game, plan, cellsize),
|
||||
@ -66,6 +75,7 @@ func (level *Level) Update() {
|
||||
query := level.World.Query(level.Selector["player"])
|
||||
|
||||
toRemove := []ecs.Entity{}
|
||||
particle_pos := image.Point{}
|
||||
|
||||
for query.Next() {
|
||||
playerposition := (*components.Position)(query.Get(level.Component["position"]))
|
||||
@ -114,6 +124,8 @@ func (level *Level) Update() {
|
||||
if ok {
|
||||
fmt.Printf("bumped into collectible %v\n", collectible)
|
||||
toRemove = append(toRemove, colquery.Entity())
|
||||
particle_pos.X = colposition.X
|
||||
particle_pos.Y = colposition.Y
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -121,11 +133,39 @@ func (level *Level) Update() {
|
||||
playerposition.Move(velocity)
|
||||
}
|
||||
|
||||
// remove collectible if collected
|
||||
for _, entity := range toRemove {
|
||||
// FIXME: or keep them and prepare an animated death
|
||||
level.World.RemoveEntity(entity)
|
||||
}
|
||||
|
||||
// display debris after collecting
|
||||
ptquery := level.World.Query(level.Selector["particle"])
|
||||
for ptquery.Next() {
|
||||
// we loop, but it's only one anyway
|
||||
particle := (*components.Particle)(ptquery.Get(level.Component["particle"]))
|
||||
colposition := (*components.Position)(ptquery.Get(level.Component["position"]))
|
||||
|
||||
if len(toRemove) > 0 {
|
||||
// particle appears
|
||||
colposition.Update(
|
||||
particle_pos.X-(level.Cellsize/2),
|
||||
particle_pos.Y-(level.Cellsize/2),
|
||||
64,
|
||||
)
|
||||
|
||||
particle.Index = 0 // start displaying the particle
|
||||
} else {
|
||||
switch {
|
||||
case particle.Index > -1 && particle.Index < len(particle.Particles)-1:
|
||||
particle.Index++
|
||||
default:
|
||||
// last sprite reached, remove it
|
||||
particle.Index = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (level *Level) Position2Point(position *components.Position) image.Point {
|
||||
@ -136,7 +176,10 @@ func (level *Level) Position2Point(position *components.Position) image.Point {
|
||||
}
|
||||
|
||||
// return the tile the moving object would end up on if indeed moving
|
||||
func (level *Level) GetTile(position *components.Position, velocity *components.Velocity) *assets.Tile {
|
||||
func (level *Level) GetTile(
|
||||
position *components.Position,
|
||||
velocity *components.Velocity) *assets.Tile {
|
||||
|
||||
newpoint := image.Point{
|
||||
int(position.X+velocity.Data.X) / level.Cellsize,
|
||||
int(position.Y+velocity.Data.Y) / level.Cellsize,
|
||||
@ -147,20 +190,22 @@ func (level *Level) GetTile(position *components.Position, velocity *components.
|
||||
}
|
||||
|
||||
func (level *Level) Draw(screen *ebiten.Image) {
|
||||
rid := ecs.ComponentID[components.Renderable](level.World)
|
||||
pid := ecs.ComponentID[components.Position](level.World)
|
||||
sid := ecs.ComponentID[components.Solid](level.World)
|
||||
level.DrawTiles(screen)
|
||||
level.DrawMovables(screen)
|
||||
level.DrawParticles(screen)
|
||||
}
|
||||
|
||||
func (level *Level) DrawTiles(screen *ebiten.Image) {
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
|
||||
if !level.UseCache {
|
||||
// map not cached or cacheable, write it to the cache
|
||||
draw.Draw(level.Cache, level.Background.Bounds(), level.Background, image.ZP, draw.Src)
|
||||
|
||||
selector := filter.All(rid, pid, sid)
|
||||
|
||||
query := level.World.Query(selector)
|
||||
query := level.World.Query(level.Selector["tile"])
|
||||
for query.Next() {
|
||||
pos := (*components.Position)(query.Get(pid))
|
||||
sprite := (*components.Renderable)(query.Get(rid))
|
||||
pos := (*components.Position)(query.Get(level.Component["position"]))
|
||||
sprite := (*components.Renderable)(query.Get(level.Component["renderable"]))
|
||||
|
||||
draw.Draw(
|
||||
level.Cache,
|
||||
@ -168,31 +213,52 @@ func (level *Level) Draw(screen *ebiten.Image) {
|
||||
sprite.Image, image.ZP, draw.Over)
|
||||
}
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Reset()
|
||||
screen.DrawImage(level.Cache, op)
|
||||
|
||||
level.UseCache = true
|
||||
} else {
|
||||
// use the cached map
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.GeoM.Reset()
|
||||
screen.DrawImage(level.Cache, op)
|
||||
}
|
||||
}
|
||||
|
||||
func (level *Level) DrawMovables(screen *ebiten.Image) {
|
||||
// write the movable tiles
|
||||
selector := filter.All(rid, pid).Without(sid)
|
||||
|
||||
query := level.World.Query(&selector)
|
||||
for query.Next() {
|
||||
pos := (*components.Position)(query.Get(pid))
|
||||
sprite := (*components.Renderable)(query.Get(rid))
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
selector := level.Selector["movable"].Without(level.Component["solid"])
|
||||
query := level.World.Query(&selector)
|
||||
|
||||
for query.Next() {
|
||||
pos := (*components.Position)(query.Get(level.Component["position"]))
|
||||
sprite := (*components.Renderable)(query.Get(level.Component["renderable"]))
|
||||
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||
|
||||
screen.DrawImage(sprite.Image, op)
|
||||
}
|
||||
}
|
||||
|
||||
func (level *Level) DrawParticles(screen *ebiten.Image) {
|
||||
// write particles (these are no tiles!)
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
query := level.World.Query(level.Selector["particle"])
|
||||
|
||||
for query.Next() {
|
||||
pos := (*components.Position)(query.Get(level.Component["position"]))
|
||||
particle := (*components.Particle)(query.Get(level.Component["particle"]))
|
||||
|
||||
if particle.Index > -1 {
|
||||
op.GeoM.Reset()
|
||||
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||
screen.DrawImage(particle.Particles[particle.Index], op)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (level *Level) SetupGrid(game *Game) {
|
||||
level.Grid = NewGrid(game, level.Cellsize, level.Mapslice)
|
||||
}
|
||||
|
||||
BIN
src/particle-dust.xcf
Normal file
BIN
src/particle-dust.xcf
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user