obstacle collission added, but not working yet
This commit is contained in:
parent
fd570216f0
commit
646b227b8e
4
TODO.md
4
TODO.md
@ -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
|
||||
|
||||
@ -5,13 +5,13 @@ Background: background-lila
|
||||
|
||||
|
||||
########
|
||||
# o # #
|
||||
# S # #
|
||||
#v o #
|
||||
# S<# #
|
||||
# #### #
|
||||
|
||||
|
||||
# #### #
|
||||
# #
|
||||
# #
|
||||
#> ^#
|
||||
########
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
BIN
assets/sprites/obstacle-east.png
Normal file
BIN
assets/sprites/obstacle-east.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/sprites/obstacle-north.png
Normal file
BIN
assets/sprites/obstacle-north.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/sprites/obstacle-south.png
Normal file
BIN
assets/sprites/obstacle-south.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
assets/sprites/obstacle-west.png
Normal file
BIN
assets/sprites/obstacle-west.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
@ -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) {
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ const (
|
||||
West
|
||||
South
|
||||
North
|
||||
All
|
||||
)
|
||||
|
||||
const PLAYERSPEED int = 4
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
BIN
src/star.xcf
BIN
src/star.xcf
Binary file not shown.
@ -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"
|
||||
@ -16,12 +16,13 @@ import (
|
||||
|
||||
type ObstacleSystem struct {
|
||||
World *ecs.World
|
||||
Selector *generic.Filter3[Position, Obstacle, Renderable]
|
||||
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)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user