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
|
- Add some final message when the player reaches the last level, start
|
||||||
from scratch or a message to buy me some beer, whatever
|
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 # #
|
#v o #
|
||||||
# S # #
|
# S<# #
|
||||||
# #### #
|
# #### #
|
||||||
|
|
||||||
|
|
||||||
# #### #
|
# #### #
|
||||||
# #
|
# #
|
||||||
# #
|
#> ^#
|
||||||
########
|
########
|
||||||
|
|
||||||
|
|||||||
@ -6,9 +6,11 @@ import (
|
|||||||
"io/fs"
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"openquell/config"
|
||||||
"openquell/util"
|
"openquell/util"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
@ -28,9 +30,10 @@ type Tile struct {
|
|||||||
Renderable bool
|
Renderable bool
|
||||||
Velocity bool
|
Velocity bool
|
||||||
Collectible bool
|
Collectible bool
|
||||||
Obstacle bool
|
|
||||||
Particle int // -1=unused, 0-3 = show image of slice
|
Particle int // -1=unused, 0-3 = show image of slice
|
||||||
Particles []*ebiten.Image
|
Particles []*ebiten.Image
|
||||||
|
Obstacle bool
|
||||||
|
Direction int // obstacles
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTilePlayer() *Tile {
|
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{
|
return &Tile{
|
||||||
Id: '+',
|
Id: '+',
|
||||||
Sprite: Assets[class],
|
Sprite: Assets[class],
|
||||||
@ -73,6 +76,7 @@ func NewTileObstacle(class string) *Tile {
|
|||||||
Solid: false,
|
Solid: false,
|
||||||
Renderable: true,
|
Renderable: true,
|
||||||
Obstacle: true,
|
Obstacle: true,
|
||||||
|
Direction: direction,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +125,11 @@ func InitTiles() TileRegistry {
|
|||||||
'#': NewTileBlock("block-grey32"),
|
'#': NewTileBlock("block-grey32"),
|
||||||
'S': NewTilePlayer(),
|
'S': NewTilePlayer(),
|
||||||
'o': NewTileCollectible("collectible-orange"),
|
'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{
|
'*': NewTileParticle([]string{
|
||||||
//"particle-ring-1",
|
//"particle-ring-1",
|
||||||
"particle-ring-2",
|
"particle-ring-2",
|
||||||
@ -143,6 +151,10 @@ func LoadLevels(dir string) []RawLevel {
|
|||||||
log.Fatalf("failed to read level dir %s: %s", dir, err)
|
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 {
|
for _, levelfile := range entries {
|
||||||
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
|
if levelfile.Type().IsRegular() && strings.Contains(levelfile.Name(), ".lvl") {
|
||||||
path := filepath.Join("assets", dir)
|
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) {
|
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) {
|
func (position *Position) Set(newpos *Position) {
|
||||||
|
|||||||
@ -35,3 +35,21 @@ func (velocity *Velocity) Change(direction int) {
|
|||||||
func (velocity *Velocity) Moving() bool {
|
func (velocity *Velocity) Moving() bool {
|
||||||
return velocity.Data.X != 0 || velocity.Data.Y != 0
|
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
|
West
|
||||||
South
|
South
|
||||||
North
|
North
|
||||||
|
All
|
||||||
)
|
)
|
||||||
|
|
||||||
const PLAYERSPEED int = 4
|
const PLAYERSPEED int = 4
|
||||||
|
|||||||
@ -48,12 +48,14 @@ func NewGrid(world *ecs.World,
|
|||||||
components.Renderable,
|
components.Renderable,
|
||||||
components.Collectible](world)
|
components.Collectible](world)
|
||||||
|
|
||||||
obsmapper := generic.NewMap3[
|
obsmapper := generic.NewMap4[
|
||||||
components.Position,
|
components.Position,
|
||||||
|
components.Velocity,
|
||||||
components.Renderable,
|
components.Renderable,
|
||||||
components.Obstacle](world)
|
components.Obstacle](world)
|
||||||
|
|
||||||
var pos *components.Position
|
var pos *components.Position
|
||||||
|
var vel *components.Velocity
|
||||||
var render *components.Renderable
|
var render *components.Renderable
|
||||||
var speed *components.Speed
|
var speed *components.Speed
|
||||||
|
|
||||||
@ -78,7 +80,8 @@ func NewGrid(world *ecs.World,
|
|||||||
pos, render, _ = colmapper.Get(entity)
|
pos, render, _ = colmapper.Get(entity)
|
||||||
case tile.Obstacle:
|
case tile.Obstacle:
|
||||||
entity := obsmapper.New()
|
entity := obsmapper.New()
|
||||||
pos, render, _ = obsmapper.Get(entity)
|
pos, vel, render, _ = obsmapper.Get(entity)
|
||||||
|
vel.Direction = tile.Direction
|
||||||
default:
|
default:
|
||||||
log.Fatalln("unsupported tile type encountered")
|
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/assets"
|
||||||
"openquell/components"
|
"openquell/components"
|
||||||
. "openquell/components"
|
. "openquell/components"
|
||||||
"openquell/config"
|
|
||||||
. "openquell/config"
|
. "openquell/config"
|
||||||
"openquell/observers"
|
"openquell/observers"
|
||||||
|
"openquell/util"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/mlange-42/arche/ecs"
|
"github.com/mlange-42/arche/ecs"
|
||||||
@ -15,13 +15,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ObstacleSystem struct {
|
type ObstacleSystem struct {
|
||||||
World *ecs.World
|
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 {
|
func NewObstacleSystem(world *ecs.World) *ObstacleSystem {
|
||||||
system := &ObstacleSystem{
|
system := &ObstacleSystem{
|
||||||
Selector: generic.NewFilter3[Position, Obstacle, Renderable](),
|
Selector: generic.NewFilter4[Position, Velocity, Obstacle, Renderable](),
|
||||||
World: world,
|
World: world,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,17 +46,25 @@ func (system *ObstacleSystem) Update() {
|
|||||||
gameover := false
|
gameover := false
|
||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
obsposition, obstacle, _ := query.Get()
|
obsposition, obsvelocity, obstacle, _ := query.Get()
|
||||||
|
|
||||||
for player := range playerobserver.Entities {
|
for player := range playerobserver.Entities {
|
||||||
playerposition := (*Position)(system.World.Get(player, posID))
|
playerposition := (*Position)(system.World.Get(player, posID))
|
||||||
playervelocity := (*Velocity)(system.World.Get(player, veloID))
|
playervelocity := (*Velocity)(system.World.Get(player, veloID))
|
||||||
|
|
||||||
ok, _ := playerposition.Intersects(obsposition, playervelocity)
|
ok, newpos := playerposition.Intersects(obsposition, playervelocity)
|
||||||
if ok {
|
if ok {
|
||||||
slog.Debug("bumped into obstacle", "obstacle", obstacle)
|
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)
|
query := system.Selector.Query(system.World)
|
||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
pos, _, sprite := query.Get()
|
pos, _, _, sprite := query.Get()
|
||||||
|
|
||||||
op.GeoM.Reset()
|
op.GeoM.Reset()
|
||||||
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||||
@ -113,5 +122,21 @@ func (system *ObstacleSystem) AddParticle(position *components.Position) {
|
|||||||
64,
|
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.Particle.Update()
|
||||||
system.Collectible.Update()
|
|
||||||
system.Obstacle.Update()
|
system.Obstacle.Update()
|
||||||
|
system.Collectible.Update()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -96,7 +96,7 @@ func (system *PlayerSystem) Draw(screen *ebiten.Image) {
|
|||||||
screen.DrawImage(sprite.Image, op)
|
screen.DrawImage(sprite.Image, op)
|
||||||
}
|
}
|
||||||
|
|
||||||
system.Obstacle.Draw(screen)
|
|
||||||
system.Collectible.Draw(screen)
|
system.Collectible.Draw(screen)
|
||||||
system.Particle.Draw(screen)
|
system.Particle.Draw(screen)
|
||||||
|
system.Obstacle.Draw(screen)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "openquell/config"
|
||||||
|
)
|
||||||
|
|
||||||
// find an item in a list, generic variant
|
// find an item in a list, generic variant
|
||||||
func Contains[E comparable](s []E, v E) bool {
|
func Contains[E comparable](s []E, v E) bool {
|
||||||
for _, vs := range s {
|
for _, vs := range s {
|
||||||
@ -19,3 +23,21 @@ func Exists[K comparable, V any](m map[K]V, v K) bool {
|
|||||||
|
|
||||||
return false
|
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