fixed observers, added GameObserver

This commit is contained in:
Thomas von Dein 2024-02-11 14:24:30 +01:00
parent 72f0aa7691
commit 65ddec3fa4
18 changed files with 122 additions and 53 deletions

17
assets/levels/0-own.lvl Normal file
View File

@ -0,0 +1,17 @@
Description: win
Background: background-lila
########
# #o#
# S # #
# #### #
# #### #
# #
# o #
########

View File

@ -1,6 +1,6 @@
#!/bin/sh
width=$(grep "width int" ../main.go | awk '{print $4}')
height=$(grep "height int" ../main.go | awk '{print $4}')
#!/bin/bash
width=$(grep "width " ../../main.go | awk '{print $4}')
height=$(grep "height " ../../main.go | awk '{print $4}')
read -p " Enter level name: " name
read -p " Enter background: " background
@ -14,11 +14,12 @@ if test -z "$bbackground"; then
background="background-lila"
fi
w=$(($width/32))
h=$(($height/32))
(
echo "Description: $des"
echo "Background: $background"
w=$(($width / 32))
h=$(($height / 32))
for x in $(seq 1 $h); do
for y in $(seq 1 $w); do

View File

@ -1,17 +0,0 @@
Description: Introduction: collect the goods by moving the ball onto them
Background: background-lila
####################
# #
# #
# #
# #
# #
# #
# ######
#
#
#
#
#
#
####################

View File

@ -10,14 +10,18 @@ type Renderable struct {
Image *ebiten.Image
}
type Particle struct {
Index int
Particles []*ebiten.Image
}
type Speed struct {
Value int
}
// only tile entities will have those
type Tilish struct{}
type Solid struct{}
type Floor struct{}
type Player struct{}
type Collectible struct{}
type Particle struct {
Index int
Particles []*ebiten.Image
}

View File

@ -70,8 +70,8 @@ func (position *Position) String() string {
)
}
func (position *Position) Move(velocity *Velocity) {
position.Update(position.X+velocity.Data.X, position.Y+velocity.Data.Y)
func (position *Position) Move(velocity *Velocity, speed *Speed) {
position.Update(position.X+(velocity.Data.X*speed.Value), position.Y+(velocity.Data.Y*speed.Value))
}
func (position *Position) Set(newpos *Position) {

View File

@ -11,21 +11,19 @@ type Velocity struct {
}
func (velocity *Velocity) Change(direction int) {
ticks := 4
switch direction {
case East:
velocity.Data.X = ticks
velocity.Data.X = 1
velocity.Data.Y = 0
case West:
velocity.Data.X = ticks - (ticks * 2)
velocity.Data.X = -1
velocity.Data.Y = 0
case South:
velocity.Data.X = 0
velocity.Data.Y = ticks
velocity.Data.Y = 1
case North:
velocity.Data.X = 0
velocity.Data.Y = ticks - (ticks * 2)
velocity.Data.Y = -1
case Stop:
velocity.Data.X = 0
velocity.Data.Y = 0

View File

@ -7,3 +7,5 @@ const (
South
North
)
const PLAYERSPEED int = 4

View File

@ -13,16 +13,15 @@ type Game struct {
World *ecs.World
Bounds image.Rectangle
ScreenWidth, ScreenHeight int
CurrentLevel int
Scenes map[int]Scene
Observer *observers.GameObserver
}
func NewGame(width, height, startlevel int, startscene int) *Game {
func NewGame(width, height, cellsize, startlevel int, startscene int) *Game {
world := ecs.NewWorld()
game := &Game{
Bounds: image.Rectangle{},
CurrentLevel: startlevel,
World: &world,
ScreenWidth: width,
ScreenHeight: height,
@ -31,6 +30,7 @@ func NewGame(width, height, startlevel int, startscene int) *Game {
observers.NewPlayerObserver(&world)
observers.NewParticleObserver(&world)
game.Observer = observers.NewGameObserver(&world, startlevel, width, height, cellsize)
game.Scenes[Play] = NewLevelScene(game, startlevel)

View File

@ -6,6 +6,7 @@ import (
"openquell/assets"
"openquell/components"
"openquell/grid"
"openquell/observers"
"openquell/systems"
"strings"
@ -71,6 +72,10 @@ func (level *Level) SetupGrid(game *Game) {
selector := ecs.All(posID)
level.World.Batch().RemoveEntities(selector)
// get rid of any players on PlayerObserver. FIXME: remove them in grid.NewGrid()?
playerobserver := observers.GetPlayerObserver(level.World)
playerobserver.RemoveEntities()
// setup world
level.GridSystem.SetGrid(grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice))
}

View File

@ -1,12 +1,14 @@
package game
import (
"fmt"
"openquell/assets"
"github.com/hajimehoshi/ebiten/v2"
)
type LevelScene struct {
Game *Game
CurrentLevel int
Levels []*Level
Next int
@ -16,10 +18,10 @@ type LevelScene struct {
// Implements the actual playing Scene
func NewLevelScene(game *Game, startlevel int) Scene {
scene := &LevelScene{CurrentLevel: startlevel, Whoami: Play}
scene := &LevelScene{CurrentLevel: startlevel, Whoami: Play, Game: game}
scene.GenerateLevels(game)
scene.Levels[game.CurrentLevel].SetupGrid(game)
scene.Levels[scene.CurrentLevel].SetupGrid(game)
return scene
}
@ -40,6 +42,12 @@ func (scene *LevelScene) SetNext() int {
}
func (scene *LevelScene) Update() error {
if scene.CurrentLevel != scene.Game.Observer.CurrentLevel {
fmt.Printf("current: %d, next: %d\n", scene.CurrentLevel, scene.Game.Observer.CurrentLevel)
scene.CurrentLevel = scene.Game.Observer.CurrentLevel
scene.Levels[scene.CurrentLevel].SetupGrid(scene.Game)
}
scene.Levels[scene.CurrentLevel].Update()
return nil
}

View File

@ -6,6 +6,7 @@ import (
"log"
"openquell/assets"
"openquell/components"
"openquell/config"
"openquell/observers"
"github.com/mlange-42/arche/ecs"
@ -27,10 +28,11 @@ func NewGrid(world *ecs.World,
// we use this to turn our tiles into iterable entities, used for
// collision detection, transformation and other things
playermapper := generic.NewMap4[
playermapper := generic.NewMap5[
components.Position,
components.Velocity,
components.Renderable,
components.Speed,
components.Player](world)
solidmapper := generic.NewMap4[
@ -48,6 +50,7 @@ func NewGrid(world *ecs.World,
var pos *components.Position
var render *components.Renderable
var speed *components.Speed
playerobserver := observers.GetPlayerObserver(world)
@ -60,9 +63,9 @@ func NewGrid(world *ecs.World,
pos, render, _, _ = solidmapper.Get(entity)
case tile.Player:
entity := playermapper.New()
pos, _, render, _ = playermapper.Get(entity)
pos, _, render, speed, _ = playermapper.Get(entity)
playerobserver.AddEntity(entity)
speed.Value = config.PLAYERSPEED
fmt.Printf("player start pos: %d,%d\n", point.X*tilesize, point.Y*tilesize)
case tile.Collectible:
entity := colmapper.New()

View File

@ -8,15 +8,16 @@ import (
)
const (
width int = 640
height int = 480
width int = 640
height int = 480
cellsize int = 32
)
func main() {
ebiten.SetWindowSize(width, height)
ebiten.SetWindowTitle("openquell")
g := game.NewGame(width, height, 0, game.Play)
g := game.NewGame(width, height, cellsize, 0, game.Play)
err := ebiten.RunGame(g)
if err != nil {

View File

@ -0,0 +1,31 @@
package observers
import (
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
// Used for global game state
type GameObserver struct {
CurrentLevel, Width, Height, Cellsize, Score int
}
func NewGameObserver(world *ecs.World, startlevel, width, height, cellsize int) *GameObserver {
observer := &GameObserver{
CurrentLevel: startlevel,
Width: width,
Height: height,
Cellsize: cellsize,
}
resmanger := generic.NewResource[GameObserver](world)
resmanger.Add(observer)
return observer
}
func GetGameObserver(world *ecs.World) *GameObserver {
observerID := ecs.ResourceID[GameObserver](world)
observer := world.Resources().Get(observerID).(*GameObserver)
return observer
}

View File

@ -50,3 +50,7 @@ func (observer *PlayerObserver) AddEntity(entity ecs.Entity) {
func (observer *PlayerObserver) RemoveEntity(entity ecs.Entity) {
delete(observer.Entities, entity)
}
func (observer *PlayerObserver) RemoveEntities() {
observer.Entities = make(map[ecs.Entity]int)
}

View File

@ -35,6 +35,12 @@ func (system *CollectibleSystem) Update() {
EntitiesToRemove := []ecs.Entity{}
query := system.Selector.Query(system.World)
numcollectibles := query.Count()
if numcollectibles == 0 {
query.Close()
return
}
for query.Next() {
colposition, collectible, _ := query.Get()
@ -58,6 +64,14 @@ func (system *CollectibleSystem) Update() {
for _, entity := range EntitiesToRemove {
system.World.RemoveEntity(entity)
numcollectibles--
}
if numcollectibles == 0 {
// winner, winner, chicken dinner!
game := observers.GetGameObserver(system.World)
game.Score++
game.CurrentLevel++
}
}

View File

@ -9,7 +9,6 @@ import (
. "openquell/config"
"openquell/grid"
"github.com/alecthomas/repr"
"github.com/hajimehoshi/ebiten/v2"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
@ -119,7 +118,6 @@ func (system *GridSystem) GetSolidNeighborPosition(
}
newpos := components.NewPosition(neighborpos, system.Tilesize)
repr.Println(newpos)
if !edge && system.Grid.Map[neighborpos].Solid {
return true, newpos

View File

@ -12,7 +12,7 @@ import (
type PlayerSystem struct {
World *ecs.World
Selector *generic.Filter4[Position, Velocity, Player, Renderable]
Selector *generic.Filter5[Position, Velocity, Player, Renderable, Speed]
Particle *ParticleSystem
Collectible *CollectibleSystem
Grid *GridSystem
@ -20,7 +20,7 @@ type PlayerSystem struct {
func NewPlayerSystem(world *ecs.World, grid *GridSystem) *PlayerSystem {
system := &PlayerSystem{
Selector: generic.NewFilter4[Position, Velocity, Player, Renderable](),
Selector: generic.NewFilter5[Position, Velocity, Player, Renderable, Speed](),
Particle: NewParticleSystem(world, grid.Tilesize),
Collectible: NewCollectibleSystem(world),
Grid: grid,
@ -34,7 +34,7 @@ func (system PlayerSystem) Update() error {
query := system.Selector.Query(system.World)
for query.Next() {
playerposition, velocity, _, _ := query.Get()
playerposition, velocity, _, _, speed := query.Get()
if !velocity.Moving() {
switch {
@ -72,7 +72,7 @@ func (system PlayerSystem) Update() error {
}
}
playerposition.Move(velocity)
playerposition.Move(velocity, speed)
}
system.Particle.Update()
@ -87,7 +87,7 @@ func (system *PlayerSystem) Draw(screen *ebiten.Image) {
query := system.Selector.Query(system.World)
for query.Next() {
pos, _, _, sprite := query.Get()
pos, _, _, sprite, _ := query.Get()
op.GeoM.Reset()
op.GeoM.Translate(float64(pos.X), float64(pos.Y))