added systems (not used yet, see TODO)

This commit is contained in:
Thomas von Dein 2024-02-09 20:20:13 +01:00
parent 006216398a
commit bbbe873ff7
6 changed files with 215 additions and 0 deletions

View File

@ -8,3 +8,9 @@
- ignore comments in lvl files
- add whitespace-mode flag in lvl files
- check when sphere bounces from one end to the other endlessly w/o any solids in between. this is a game lock and equals game over
SYSTEM Stuff:
- initialize systems in NewLevel()
- replace level.Update() with systems update
- mv Draw() from level to systems

View File

@ -0,0 +1,54 @@
package game
import (
"fmt"
"image"
. "openquell/components"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
type CollectibleSystem struct {
World *ecs.World
Selector *generic.Filter2[Position, Collectible]
}
func NewCollectibleSystem(world *ecs.World) *CollectibleSystem {
system := &CollectibleSystem{
Selector: generic.NewFilter2[Position, Collectible](),
}
return system
}
func (system *CollectibleSystem) CheckPlayerCollision(
playerposition *Position,
playervelocity *Velocity) (bool, image.Point) {
toRemove := []ecs.Entity{}
particle_pos := image.Point{}
var bumped bool
query := system.Selector.Query(system.World)
for query.Next() {
colposition, collectible := query.Get()
ok, _ := playerposition.Intersects(colposition, playervelocity)
if ok {
fmt.Printf("bumped into collectible %v\n", collectible)
toRemove = append(toRemove, query.Entity())
particle_pos.X = colposition.X
particle_pos.Y = colposition.Y
bumped = true
}
}
// remove collectible if collected
for _, entity := range toRemove {
system.World.RemoveEntity(entity)
}
return bumped, particle_pos
}

View File

@ -260,6 +260,17 @@ func (level *Level) DrawParticles(screen *ebiten.Image) {
}
func (level *Level) SetupGrid(game *Game) {
// generic variant does not work here:
// selector := generic.NewFilter1[components.Position]()
// level.World.Batch().RemoveEntities(selector)
// missing argument in conversion to generic.Filter1[components.Position]
// erase all entities of previous level, if any
posID := ecs.ComponentID[components.Position](level.World)
selector := ecs.All(posID)
level.World.Batch().RemoveEntities(selector)
// setup world
level.Grid = NewGrid(game, level.Cellsize, level.Mapslice)
}

53
game/particle_system.go Normal file
View File

@ -0,0 +1,53 @@
package game
import (
"image"
. "openquell/components"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
type ParticleSystem struct {
World *ecs.World
Selector *generic.Filter2[Position, Particle]
Cellsize int
}
func NewParticleSystem(world *ecs.World) *ParticleSystem {
system := &ParticleSystem{
Selector: generic.NewFilter2[Position, Particle](),
}
return system
}
func (system *ParticleSystem) Update(detonate bool, position *image.Point) {
// display debris after collecting
query := system.Selector.Query(system.World)
for query.Next() {
// we loop, but it's only one anyway
ptposition, particle := query.Get()
if detonate {
// particle appears
ptposition.Update(
position.X-(system.Cellsize/2),
position.Y-(system.Cellsize/2),
64,
)
particle.Index = 0 // start displaying the particle
} else {
switch {
// particle shows from earlier tick, animate
case particle.Index > -1 && particle.Index < len(particle.Particles)-1:
particle.Index++
default:
// last sprite reached, remove it
particle.Index = -1
}
}
}
}

83
game/player_system.go Normal file
View File

@ -0,0 +1,83 @@
package game
import (
"fmt"
"image"
. "openquell/components"
. "openquell/config"
"github.com/hajimehoshi/ebiten/v2"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
type PlayerSystem struct {
World *ecs.World
Grid *Grid
Selector *generic.Filter3[Position, Velocity, Player]
Particle *ParticleSystem
Collectible *CollectibleSystem
}
func NewPlayerSystem(world *ecs.World) *PlayerSystem {
system := &PlayerSystem{
Selector: generic.NewFilter3[Position, Velocity, Player](),
}
return system
}
func (system PlayerSystem) Update() error {
query := system.Selector.Query(system.World)
var bumped bool
var particle_pos image.Point
for query.Next() {
playerposition, velocity, _ := query.Get()
if !velocity.Moving() {
switch {
case ebiten.IsKeyPressed(ebiten.KeyRight):
velocity.Change(East)
case ebiten.IsKeyPressed(ebiten.KeyLeft):
velocity.Change(West)
case ebiten.IsKeyPressed(ebiten.KeyDown):
velocity.Change(South)
case ebiten.IsKeyPressed(ebiten.KeyUp):
velocity.Change(North)
// other keys: <tab>: switch player, etc
}
}
if velocity.Moving() {
ok, newpos := system.Grid.BumpEdge(playerposition, velocity)
if ok {
fmt.Printf("falling off the edge, new pos: %v\n", newpos)
playerposition.Set(newpos)
} else {
ok, tilepos := system.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
if ok {
intersects, newpos := tilepos.Intersects(playerposition, velocity)
if intersects {
fmt.Printf("collision detected. tile: %s\n", tilepos)
fmt.Printf(" player: %s\n", playerposition)
fmt.Printf(" new: %s\n", newpos)
playerposition.Set(newpos)
fmt.Printf(" player new: %s\n", playerposition)
velocity.Change(Stop)
}
}
}
bumped, particle_pos = system.Collectible.CheckPlayerCollision(playerposition, velocity)
}
}
system.Particle.Update(bumped, &particle_pos)
return nil
}

8
systems/system.go Normal file
View File

@ -0,0 +1,8 @@
package system
import "github.com/hajimehoshi/ebiten/v2"
type System interface {
Update() error
Draw(screen *ebiten.Image)
}