obstacle collission added, but not working yet

This commit is contained in:
Thomas von Dein 2024-02-20 18:47:32 +01:00
parent fd570216f0
commit 646b227b8e
15 changed files with 112 additions and 21 deletions

View File

@ -27,3 +27,7 @@ if inpututil.IsKeyJustPressed(ebiten.KeyS) {
- Add some final message when the player reaches the last level, start
from scratch or a message to buy me some beer, whatever
- Calculate obstacle collision the same as solid collision with future
velocity and included snap in so that the player ends up right on
the edge of the obstacle and not inside as it is now

View File

@ -5,13 +5,13 @@ Background: background-lila
########
# o # #
# S # #
#v o #
# S<# #
# #### #
# #### #
# #
# #
#> ^#
########

View File

@ -6,9 +6,11 @@ import (
"io/fs"
"log"
"log/slog"
"openquell/config"
"openquell/util"
"os"
"path/filepath"
"sort"
"strings"
"github.com/hajimehoshi/ebiten/v2"
@ -28,9 +30,10 @@ type Tile struct {
Renderable bool
Velocity bool
Collectible bool
Obstacle bool
Particle int // -1=unused, 0-3 = show image of slice
Particles []*ebiten.Image
Obstacle bool
Direction int // obstacles
}
func NewTilePlayer() *Tile {
@ -65,7 +68,7 @@ func NewTileCollectible(class string) *Tile {
}
}
func NewTileObstacle(class string) *Tile {
func NewTileObstacle(class string, direction int) *Tile {
return &Tile{
Id: '+',
Sprite: Assets[class],
@ -73,6 +76,7 @@ func NewTileObstacle(class string) *Tile {
Solid: false,
Renderable: true,
Obstacle: true,
Direction: direction,
}
}
@ -121,7 +125,11 @@ func InitTiles() TileRegistry {
'#': NewTileBlock("block-grey32"),
'S': NewTilePlayer(),
'o': NewTileCollectible("collectible-orange"),
'+': NewTileObstacle("obstacle-star"),
'+': NewTileObstacle("obstacle-star", config.All),
'^': NewTileObstacle("obstacle-north", config.North),
'v': NewTileObstacle("obstacle-south", config.South),
'<': NewTileObstacle("obstacle-east", config.East),
'>': NewTileObstacle("obstacle-west", config.West),
'*': NewTileParticle([]string{
//"particle-ring-1",
"particle-ring-2",
@ -143,6 +151,10 @@ func LoadLevels(dir string) []RawLevel {
log.Fatalf("failed to read level dir %s: %s", dir, err)
}
sort.Slice(entries, func(i, j int) bool {
return entries[i].Name() < entries[j].Name()
})
for _, levelfile := range entries {
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
path := filepath.Join("assets", dir)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -72,7 +72,13 @@ func (position *Position) String() string {
}
func (position *Position) Move(velocity *Velocity, speed *Speed) {
position.Update(position.X+(velocity.Data.X*speed.Value), position.Y+(velocity.Data.Y*speed.Value))
if velocity.Direction != 0 {
slog.Debug("moving", "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

@ -35,3 +35,21 @@ func (velocity *Velocity) Change(direction int) {
func (velocity *Velocity) Moving() bool {
return velocity.Data.X != 0 || velocity.Data.Y != 0
}
func (velocity *Velocity) InvertDirection() int {
switch velocity.Direction {
case East:
return West
case West:
return East
case South:
return North
case North:
return South
case All:
return Stop
}
// should not happen
return All
}

View File

@ -8,6 +8,7 @@ const (
West
South
North
All
)
const PLAYERSPEED int = 4

View File

@ -48,12 +48,14 @@ func NewGrid(world *ecs.World,
components.Renderable,
components.Collectible](world)
obsmapper := generic.NewMap3[
obsmapper := generic.NewMap4[
components.Position,
components.Velocity,
components.Renderable,
components.Obstacle](world)
var pos *components.Position
var vel *components.Velocity
var render *components.Renderable
var speed *components.Speed
@ -78,7 +80,8 @@ func NewGrid(world *ecs.World,
pos, render, _ = colmapper.Get(entity)
case tile.Obstacle:
entity := obsmapper.New()
pos, render, _ = obsmapper.Get(entity)
pos, vel, render, _ = obsmapper.Get(entity)
vel.Direction = tile.Direction
default:
log.Fatalln("unsupported tile type encountered")
}

Binary file not shown.

View File

@ -5,9 +5,9 @@ import (
"openquell/assets"
"openquell/components"
. "openquell/components"
"openquell/config"
. "openquell/config"
"openquell/observers"
"openquell/util"
"github.com/hajimehoshi/ebiten/v2"
"github.com/mlange-42/arche/ecs"
@ -15,13 +15,14 @@ import (
)
type ObstacleSystem struct {
World *ecs.World
Selector *generic.Filter3[Position, Obstacle, Renderable]
World *ecs.World
Selector *generic.Filter4[Position, Velocity, Obstacle, Renderable]
PreviousFreePos *components.Position
}
func NewObstacleSystem(world *ecs.World) *ObstacleSystem {
system := &ObstacleSystem{
Selector: generic.NewFilter3[Position, Obstacle, Renderable](),
Selector: generic.NewFilter4[Position, Velocity, Obstacle, Renderable](),
World: world,
}
@ -45,17 +46,25 @@ func (system *ObstacleSystem) Update() {
gameover := false
for query.Next() {
obsposition, obstacle, _ := query.Get()
obsposition, obsvelocity, obstacle, _ := query.Get()
for player := range playerobserver.Entities {
playerposition := (*Position)(system.World.Get(player, posID))
playervelocity := (*Velocity)(system.World.Get(player, veloID))
ok, _ := playerposition.Intersects(obsposition, playervelocity)
ok, newpos := playerposition.Intersects(obsposition, playervelocity)
if ok {
slog.Debug("bumped into obstacle", "obstacle", obstacle)
EntitiesToRemove = append(EntitiesToRemove, player)
gameover = true
if CheckObstacleSide(playervelocity, obsvelocity.Direction) {
EntitiesToRemove = append(EntitiesToRemove, player)
gameover = true
} else {
playervelocity.Change(Stop)
slog.Debug("bump not die", "originalpos", playerposition)
playerposition.Set(newpos)
slog.Debug("bump not die", "newpos", newpos)
}
}
}
}
@ -82,7 +91,7 @@ func (system *ObstacleSystem) 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))
@ -113,5 +122,21 @@ func (system *ObstacleSystem) AddParticle(position *components.Position) {
64,
)
timer.Start(config.PARTICLE_LOOPWAIT)
timer.Start(PARTICLE_LOOPWAIT)
}
// return true if obstacle weapon points into the direction the player is moving
func CheckObstacleSide(playervelocity *Velocity, obsdirection int) bool {
movingdirection := playervelocity.InvertDirection()
if movingdirection == Stop || movingdirection == obsdirection {
slog.Debug("Damaging obstacle collision",
"playerdirection", util.DirectionStr(playervelocity.Direction),
"obsdirection", util.DirectionStr(obsdirection),
"movingdirection", util.DirectionStr(movingdirection),
)
return true
}
return false
}

View File

@ -76,8 +76,8 @@ func (system PlayerSystem) Update() error {
}
system.Particle.Update()
system.Collectible.Update()
system.Obstacle.Update()
system.Collectible.Update()
return nil
}
@ -96,7 +96,7 @@ func (system *PlayerSystem) Draw(screen *ebiten.Image) {
screen.DrawImage(sprite.Image, op)
}
system.Obstacle.Draw(screen)
system.Collectible.Draw(screen)
system.Particle.Draw(screen)
system.Obstacle.Draw(screen)
}

View File

@ -1,5 +1,9 @@
package util
import (
. "openquell/config"
)
// find an item in a list, generic variant
func Contains[E comparable](s []E, v E) bool {
for _, vs := range s {
@ -19,3 +23,21 @@ func Exists[K comparable, V any](m map[K]V, v K) bool {
return false
}
func DirectionStr(dir int) string {
str := "Stop"
switch dir {
case East:
str = "East"
case West:
str = "West"
case South:
str = "South"
case North:
str = "North"
case All:
str = "All"
}
return str
}