fixes:
- using 1 func for grid collision checking with func arguments in player and obstacle systems. - moving obstacles now kill player if business ends points toward him on contact - added retry in popup menu
This commit is contained in:
parent
1d16fcb73f
commit
e93c08f81f
8
TODO.md
8
TODO.md
@ -24,15 +24,7 @@
|
||||
|
||||
- Turn menu button in hud_system (events in level_scene!) into ebitenui button
|
||||
|
||||
- On level loose, do not offer "next level"
|
||||
|
||||
- Moving obstacles don't kill the player when they hit him, they just stop there.
|
||||
|
||||
- use grid/collider.CheckGridCollision() for players AND
|
||||
obstacles. Currenty if I use it with obstacles, the don't move
|
||||
anymore when a player bumps into it, for whatever strange reasons.
|
||||
Maybe add a func argument to it so that the function can respond to
|
||||
the event as the entity wishes.
|
||||
|
||||
## Collider Rework [abandoned: see branch collider-system, fails]
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"iid": "267e9380-d7b0-11ee-a97e-35bec9c19d52",
|
||||
"jsonVersion": "1.5.3",
|
||||
"appBuildId": 473703,
|
||||
"nextUid": 31,
|
||||
"nextUid": 33,
|
||||
"identifierStyle": "Capitalize",
|
||||
"toc": [],
|
||||
"worldLayout": "Free",
|
||||
@ -3502,6 +3502,121 @@
|
||||
}
|
||||
],
|
||||
"__neighbours": []
|
||||
},
|
||||
{
|
||||
"identifier": "Level_13",
|
||||
"iid": "df3a04b0-d7b0-11ee-b56f-5371345878c2",
|
||||
"uid": 32,
|
||||
"worldX": 480,
|
||||
"worldY": 1632,
|
||||
"worldDepth": 0,
|
||||
"pxWid": 640,
|
||||
"pxHei": 480,
|
||||
"__bgColor": "#696A79",
|
||||
"bgColor": null,
|
||||
"useAutoIdentifier": true,
|
||||
"bgRelPath": "../sprites/background-lila.png",
|
||||
"bgPos": "Cover",
|
||||
"bgPivotX": 0.5,
|
||||
"bgPivotY": 0.5,
|
||||
"__smartColor": "#ADADB5",
|
||||
"__bgPos": { "topLeftPx": [0,0], "scale": [1,1], "cropRect": [0,0,640,480] },
|
||||
"externalRelPath": null,
|
||||
"fieldInstances": [
|
||||
{ "__identifier": "level", "__type": "Int", "__value": 13, "__tile": null, "defUid": 11, "realEditorValues": [{ "id": "V_Int", "params": [13] }] },
|
||||
{ "__identifier": "description", "__type": "String", "__value": "test", "__tile": null, "defUid": 12, "realEditorValues": [{
|
||||
"id": "V_String",
|
||||
"params": ["test"]
|
||||
}] },
|
||||
{ "__identifier": "background", "__type": "String", "__value": "background-lila", "__tile": null, "defUid": 13, "realEditorValues": [] },
|
||||
{ "__identifier": "minmoves", "__type": "Int", "__value": 7, "__tile": null, "defUid": 14, "realEditorValues": [] }
|
||||
],
|
||||
"layerInstances": [
|
||||
{
|
||||
"__identifier": "Entities",
|
||||
"__type": "Entities",
|
||||
"__cWid": 20,
|
||||
"__cHei": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": null,
|
||||
"__tilesetRelPath": null,
|
||||
"iid": "df3a04b1-d7b0-11ee-b56f-31d2a4bd4c5c",
|
||||
"levelId": 32,
|
||||
"layerDefUid": 5,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 1934321,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [],
|
||||
"entityInstances": [
|
||||
{
|
||||
"__identifier": "PlayerPrimary",
|
||||
"__grid": [9,7],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 32, "y": 96, "w": 32, "h": 32 },
|
||||
"__smartColor": "#2F3BBE",
|
||||
"iid": "f00cf6d0-d7b0-11ee-b56f-4d0f006a98b4",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 3,
|
||||
"px": [288,224],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 768,
|
||||
"__worldY": 1856
|
||||
},
|
||||
{
|
||||
"__identifier": "ObstacleEast",
|
||||
"__grid": [12,7],
|
||||
"__pivot": [0,0],
|
||||
"__tags": [],
|
||||
"__tile": { "tilesetUid": 1, "x": 64, "y": 32, "w": 32, "h": 32 },
|
||||
"__smartColor": "#D77643",
|
||||
"iid": "f5429510-d7b0-11ee-b56f-4d263bc512ec",
|
||||
"width": 32,
|
||||
"height": 32,
|
||||
"defUid": 8,
|
||||
"px": [384,224],
|
||||
"fieldInstances": [],
|
||||
"__worldX": 864,
|
||||
"__worldY": 1856
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"__identifier": "Tiles",
|
||||
"__type": "Tiles",
|
||||
"__cWid": 20,
|
||||
"__cHei": 15,
|
||||
"__gridSize": 32,
|
||||
"__opacity": 1,
|
||||
"__pxTotalOffsetX": 0,
|
||||
"__pxTotalOffsetY": 0,
|
||||
"__tilesetDefUid": 1,
|
||||
"__tilesetRelPath": "../sprites/map.png",
|
||||
"iid": "df3a04b2-d7b0-11ee-b56f-99f67bd5211d",
|
||||
"levelId": 32,
|
||||
"layerDefUid": 2,
|
||||
"pxOffsetX": 0,
|
||||
"pxOffsetY": 0,
|
||||
"visible": true,
|
||||
"optionalRules": [],
|
||||
"intGridCsv": [],
|
||||
"autoLayerTiles": [],
|
||||
"seed": 2843103,
|
||||
"overrideTilesetUid": null,
|
||||
"gridTiles": [{ "px": [352,320], "src": [64,0], "f": 0, "t": 2, "d": [211], "a": 1 }],
|
||||
"entityInstances": []
|
||||
}
|
||||
],
|
||||
"__neighbours": []
|
||||
}
|
||||
],
|
||||
"worlds": [],
|
||||
|
||||
@ -61,6 +61,8 @@ func (velocity *Velocity) InvertDirection() int {
|
||||
return South
|
||||
case All:
|
||||
return Stop
|
||||
case Stop:
|
||||
return Stop
|
||||
}
|
||||
|
||||
// should not happen
|
||||
|
||||
@ -18,7 +18,7 @@ type Game struct {
|
||||
Scenes map[SceneName]Scene
|
||||
CurrentScene SceneName
|
||||
Observer *observers.GameObserver
|
||||
Levels []*Level // fed in LevelScene.GenerateLevels()
|
||||
Levels []*Level // fed in PlayScene.GenerateLevels()
|
||||
Config *config.Config
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ func NewGame(width, height, cellsize int, cfg *config.Config, startscene SceneNa
|
||||
game.Scenes[Menu] = NewMenuScene(game)
|
||||
game.Scenes[About] = NewAboutScene(game)
|
||||
game.Scenes[Popup] = NewPopupScene(game)
|
||||
game.Scenes[Play] = NewLevelScene(game, cfg.Startlevel)
|
||||
game.Scenes[Play] = NewPlayScene(game, cfg.Startlevel)
|
||||
game.Scenes[Select] = NewSelectScene(game)
|
||||
|
||||
game.CurrentScene = startscene
|
||||
|
||||
@ -10,7 +10,7 @@ import (
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
)
|
||||
|
||||
type LevelScene struct {
|
||||
type PlayScene struct {
|
||||
Game *Game
|
||||
CurrentLevel int
|
||||
Levels []*Level
|
||||
@ -21,8 +21,8 @@ type LevelScene struct {
|
||||
}
|
||||
|
||||
// Implements the actual playing Scene
|
||||
func NewLevelScene(game *Game, startlevel int) Scene {
|
||||
scene := &LevelScene{Whoami: Play, Next: Play, Game: game}
|
||||
func NewPlayScene(game *Game, startlevel int) Scene {
|
||||
scene := &PlayScene{Whoami: Play, Next: Play, Game: game}
|
||||
|
||||
scene.GenerateLevels(game)
|
||||
scene.SetLevel(startlevel)
|
||||
@ -33,7 +33,7 @@ func NewLevelScene(game *Game, startlevel int) Scene {
|
||||
return scene
|
||||
}
|
||||
|
||||
func (scene *LevelScene) GenerateLevels(game *Game) {
|
||||
func (scene *PlayScene) GenerateLevels(game *Game) {
|
||||
min := []int{}
|
||||
for _, level := range assets.Project.Levels {
|
||||
level := level
|
||||
@ -46,30 +46,30 @@ func (scene *LevelScene) GenerateLevels(game *Game) {
|
||||
scene.Game.Levels = scene.Levels
|
||||
}
|
||||
|
||||
func (scene *LevelScene) SetLevel(level int) {
|
||||
func (scene *PlayScene) SetLevel(level int) {
|
||||
scene.CurrentLevel = level
|
||||
scene.Levels[scene.CurrentLevel].SetupGrid(scene.Game)
|
||||
}
|
||||
|
||||
// Interface methods
|
||||
func (scene *LevelScene) SetNext(next SceneName) {
|
||||
func (scene *PlayScene) SetNext(next SceneName) {
|
||||
scene.Next = next
|
||||
}
|
||||
|
||||
func (scene *LevelScene) GetNext() SceneName {
|
||||
func (scene *PlayScene) GetNext() SceneName {
|
||||
// FIXME: set to winner or options screen
|
||||
return scene.Next
|
||||
}
|
||||
|
||||
func (scene *LevelScene) ResetNext() {
|
||||
func (scene *PlayScene) ResetNext() {
|
||||
scene.Next = scene.Whoami
|
||||
}
|
||||
|
||||
func (scene *LevelScene) Clearscreen() bool {
|
||||
func (scene *PlayScene) Clearscreen() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (scene *LevelScene) Update() error {
|
||||
func (scene *PlayScene) Update() error {
|
||||
scene.Levels[scene.CurrentLevel].Update()
|
||||
|
||||
switch {
|
||||
@ -87,7 +87,7 @@ func (scene *LevelScene) Update() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (scene *LevelScene) Draw(screen *ebiten.Image) {
|
||||
func (scene *PlayScene) Draw(screen *ebiten.Image) {
|
||||
// FIXME: why not in Update() ?!?!?!
|
||||
if scene.CurrentLevel != scene.Game.Observer.CurrentLevel {
|
||||
slog.Debug("level", "current", scene.CurrentLevel,
|
||||
@ -5,6 +5,7 @@ import (
|
||||
"log/slog"
|
||||
"openquell/assets"
|
||||
"openquell/gameui"
|
||||
"openquell/observers"
|
||||
|
||||
"github.com/ebitenui/ebitenui"
|
||||
"github.com/ebitenui/ebitenui/widget"
|
||||
@ -75,6 +76,7 @@ func (scene *PopupScene) Draw(screen *ebiten.Image) {
|
||||
|
||||
func (scene *PopupScene) SetupUI() {
|
||||
blue := color.RGBA{0, 255, 128, 255}
|
||||
observer := observers.GetGameObserver(scene.Game.World)
|
||||
|
||||
rowContainer := gameui.NewRowContainer(false)
|
||||
|
||||
@ -88,10 +90,11 @@ func (scene *PopupScene) SetupUI() {
|
||||
scene.SetNext(Menu)
|
||||
})
|
||||
|
||||
// buttonOptions := gameui.NewMenuButton("Options", *assets.FontRenderer.FontNormal,
|
||||
// func(args *widget.ButtonClickedEventArgs) {
|
||||
// scene.SetNext(Settings)
|
||||
// })
|
||||
buttonRetry := gameui.NewMenuButton("Retry", *assets.FontRenderer.FontNormal,
|
||||
func(args *widget.ButtonClickedEventArgs) {
|
||||
scene.SetNext(Play)
|
||||
observer.Retry = true
|
||||
})
|
||||
|
||||
label := widget.NewText(
|
||||
widget.TextOpts.Text("Menu", *assets.FontRenderer.FontBig, blue),
|
||||
@ -100,8 +103,8 @@ func (scene *PopupScene) SetupUI() {
|
||||
|
||||
rowContainer.AddChild(label)
|
||||
rowContainer.AddChild(buttonContinue)
|
||||
rowContainer.AddChild(buttonRetry)
|
||||
rowContainer.AddChild(buttonAbort)
|
||||
//rowContainer.AddChild(buttonOptions)
|
||||
|
||||
scene.Ui = &ebitenui.UI{
|
||||
Container: rowContainer.Container(),
|
||||
|
||||
@ -5,25 +5,30 @@ import (
|
||||
. "openquell/config"
|
||||
)
|
||||
|
||||
// FIXME: make available everywhere
|
||||
// Check a collision on the grid. We check if the entity in question
|
||||
// bumps into the egde of the grid or if it bumps onto a solid wall
|
||||
// tile. For both cases the user must provide responder funcs in which
|
||||
// it must be implemented how to react on those events.
|
||||
func (grid *Grid) CheckGridCollision(
|
||||
playerposition *components.Position,
|
||||
velocity *components.Velocity) {
|
||||
position *components.Position,
|
||||
velocity *components.Velocity,
|
||||
respond_edge func(*components.Position, *components.Velocity, *components.Position),
|
||||
respond_solid func(*components.Position, *components.Velocity, *components.Position),
|
||||
) {
|
||||
|
||||
if velocity.Moving() {
|
||||
ok, newpos := grid.BumpEdge(playerposition, velocity)
|
||||
ok, newpos := grid.BumpEdge(position, velocity)
|
||||
if ok {
|
||||
//slog.Debug("falling off the edge", "newpos", newpos)
|
||||
playerposition.Set(newpos)
|
||||
respond_edge(position, velocity, newpos)
|
||||
} else {
|
||||
ok, tilepos := grid.GetSolidNeighborPosition(playerposition, velocity, true)
|
||||
ok, tilepos := grid.GetSolidNeighborPosition(position, velocity, true)
|
||||
if ok {
|
||||
// slog.Debug("HaveSolidNeighbor", "ok", ok, "tilepos",
|
||||
// tilepos.Point(), "playerpos", playerposition)
|
||||
intersects, newpos := tilepos.Intersects(playerposition, velocity)
|
||||
intersects, newpos := tilepos.Intersects(position, velocity)
|
||||
if intersects {
|
||||
playerposition.Set(newpos)
|
||||
velocity.Change(Stop)
|
||||
respond_solid(position, velocity, newpos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +30,23 @@ func NewObstacleSystem(world *ecs.World, gridcontainer *grid.GridContainer) Syst
|
||||
return system
|
||||
}
|
||||
|
||||
func ObstacleBumpEdgeResponder(
|
||||
pos *components.Position,
|
||||
vel *components.Velocity,
|
||||
newpos *components.Position) {
|
||||
|
||||
pos.Set(newpos)
|
||||
}
|
||||
|
||||
func ObstacleBumpWallResponder(
|
||||
pos *components.Position,
|
||||
vel *components.Velocity,
|
||||
newpos *components.Position) {
|
||||
|
||||
pos.Set(newpos)
|
||||
vel.ResetDirectionAndStop()
|
||||
}
|
||||
|
||||
func (system *ObstacleSystem) Update() error {
|
||||
observer := observers.GetGameObserver(system.World)
|
||||
|
||||
@ -58,16 +75,15 @@ func (system *ObstacleSystem) Update() error {
|
||||
|
||||
ok, newpos := obsposition.Intersects(playerposition, playervelocity)
|
||||
if ok {
|
||||
// slog.Debug("bumped into obstacle", "obstacle", obstacle)
|
||||
|
||||
if CheckObstacleSide(playervelocity, obsvelocity.Direction) {
|
||||
if CheckObstacleSide(playervelocity, obsvelocity) {
|
||||
// player died
|
||||
EntitiesToRemove = append(EntitiesToRemove, player)
|
||||
} else {
|
||||
// bumped into nonlethal obstacle side, stop the
|
||||
// player, set the obstacle in motion, if possible
|
||||
//slog.Debug("bump not die", "originalpos", playerposition, "newpos", newpos, "obspos", obsposition)
|
||||
//slog.Debug("bump not die", "playervelo", playervelocity)
|
||||
obsvelocity.Set(playervelocity)
|
||||
//slog.Debug("bump not die", "obsvelo", obsvelocity)
|
||||
playervelocity.Change(Stop)
|
||||
playerposition.Set(newpos)
|
||||
}
|
||||
@ -91,31 +107,14 @@ func (system *ObstacleSystem) Update() error {
|
||||
}
|
||||
}
|
||||
|
||||
//system.GridContainer.Grid.CheckGridCollision(obsposition, obsvelocity)
|
||||
// FIXME: this is the same loop as in player_system, unite the
|
||||
// two, just iterate over all entities with pos,vel,render, dammit
|
||||
// check if [moving] obstacle collides with walls or edges
|
||||
system.GridContainer.Grid.CheckGridCollision(
|
||||
obsposition, obsvelocity, ObstacleBumpEdgeResponder, ObstacleBumpWallResponder)
|
||||
|
||||
if obsvelocity.Moving() {
|
||||
ok, newpos := system.GridContainer.Grid.BumpEdge(obsposition, obsvelocity)
|
||||
if ok {
|
||||
//slog.Debug("falling off the edge", "newpos", newpos)
|
||||
obsposition.Set(newpos)
|
||||
} else {
|
||||
ok, tilepos := system.GridContainer.Grid.GetSolidNeighborPosition(obsposition, obsvelocity, true)
|
||||
if ok {
|
||||
intersects, newpos := tilepos.Intersects(obsposition, obsvelocity)
|
||||
if intersects {
|
||||
// slog.Debug("collision with foreign obstacle detected", "tile",
|
||||
// tilepos, "obs", obsposition, "new", newpos)
|
||||
|
||||
obsposition.Set(newpos)
|
||||
obsvelocity.ResetDirectionAndStop()
|
||||
}
|
||||
}
|
||||
|
||||
obsposition.Move(obsvelocity)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, entity := range EntitiesToRemove {
|
||||
slog.Debug("remove player")
|
||||
@ -152,13 +151,14 @@ func (system *ObstacleSystem) Draw(screen *ebiten.Image) {
|
||||
}
|
||||
|
||||
// return true if obstacle weapon points into the direction the player is moving
|
||||
func CheckObstacleSide(playervelocity *Velocity, obsdirection int) bool {
|
||||
// OR if the weapon points towards a non-moving player
|
||||
func CheckObstacleSide(playervelocity *Velocity, obsvelocity *Velocity) bool {
|
||||
movingdirection := playervelocity.InvertDirection()
|
||||
|
||||
if movingdirection == Stop || movingdirection == obsdirection {
|
||||
if movingdirection == Stop || movingdirection == obsvelocity.PointingAt {
|
||||
slog.Debug("Damaging obstacle collision",
|
||||
"playerdirection", util.DirectionStr(playervelocity.Direction),
|
||||
"obsdirection", util.DirectionStr(obsdirection),
|
||||
"obsdirection", util.DirectionStr(obsvelocity.PointingAt),
|
||||
"movingdirection", util.DirectionStr(movingdirection),
|
||||
)
|
||||
return true
|
||||
|
||||
@ -33,6 +33,23 @@ func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer, width,
|
||||
return system
|
||||
}
|
||||
|
||||
func PlayerBumpEdgeResponder(
|
||||
pos *components.Position,
|
||||
vel *components.Velocity,
|
||||
newpos *components.Position) {
|
||||
|
||||
pos.Set(newpos)
|
||||
}
|
||||
|
||||
func PlayerBumpWallResponder(
|
||||
pos *components.Position,
|
||||
vel *components.Velocity,
|
||||
newpos *components.Position) {
|
||||
|
||||
pos.Set(newpos)
|
||||
vel.Change(Stop)
|
||||
}
|
||||
|
||||
func (system PlayerSystem) Update() error {
|
||||
var EntitiesToRemove []ecs.Entity
|
||||
|
||||
@ -54,7 +71,8 @@ func (system PlayerSystem) Update() error {
|
||||
system.CheckMovement(playerposition, velocity, player)
|
||||
|
||||
// check if player collides with walls or edges
|
||||
system.CheckGridCollision(playerposition, velocity)
|
||||
system.GridContainer.Grid.CheckGridCollision(
|
||||
playerposition, velocity, PlayerBumpEdgeResponder, PlayerBumpWallResponder)
|
||||
|
||||
if count > 1 {
|
||||
// check if player collides with another player, fuse them if any
|
||||
@ -175,30 +193,6 @@ func (system *PlayerSystem) CheckMovement(
|
||||
}
|
||||
}
|
||||
|
||||
func (system *PlayerSystem) CheckGridCollision(
|
||||
playerposition *components.Position,
|
||||
velocity *components.Velocity) {
|
||||
|
||||
if velocity.Moving() {
|
||||
ok, newpos := system.GridContainer.Grid.BumpEdge(playerposition, velocity)
|
||||
if ok {
|
||||
//slog.Debug("falling off the edge", "newpos", newpos)
|
||||
playerposition.Set(newpos)
|
||||
} else {
|
||||
ok, tilepos := system.GridContainer.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
|
||||
if ok {
|
||||
// slog.Debug("HaveSolidNeighbor", "ok", ok, "tilepos",
|
||||
// tilepos.Point(), "playerpos", playerposition)
|
||||
intersects, newpos := tilepos.Intersects(playerposition, velocity)
|
||||
if intersects {
|
||||
playerposition.Set(newpos)
|
||||
velocity.Change(Stop)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (system *PlayerSystem) CheckPlayerCollision(
|
||||
position *components.Position,
|
||||
velocity *components.Velocity,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user