added sphere bounce over the map borders
This commit is contained in:
parent
014209898f
commit
c9a57142e7
1
TODO.md
1
TODO.md
@ -7,3 +7,4 @@
|
|||||||
- use first line as background image name
|
- use first line as background image name
|
||||||
- ignore comments in lvl files
|
- ignore comments in lvl files
|
||||||
- add whitespace-mode flag in lvl files
|
- add whitespace-mode flag in lvl files
|
||||||
|
- check when sphere bounces from one end to the other endlessly w/o any solids in between. this is a game lock and equals game over
|
||||||
|
|||||||
@ -2,16 +2,16 @@ Description: find the fruit
|
|||||||
Background: background-orange
|
Background: background-orange
|
||||||
|
|
||||||
|
|
||||||
##############
|
|
||||||
# #
|
|
||||||
############ #
|
|
||||||
# S #
|
|
||||||
# ############
|
# ############
|
||||||
# #
|
# #
|
||||||
############ #
|
############ #
|
||||||
# # # #
|
# S #
|
||||||
# ##### # # #
|
# ######## ###
|
||||||
# # #
|
#
|
||||||
##############
|
############ #
|
||||||
|
# # #
|
||||||
|
# # ######## #
|
||||||
|
# #
|
||||||
|
# ############
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ func (position *Position) Update(x, y int, size ...int) {
|
|||||||
position.Rect = &rect
|
position.Rect = &rect
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPosition(point *image.Point, cellsize int) *Position {
|
func NewPosition(point image.Point, cellsize int) *Position {
|
||||||
position := &Position{}
|
position := &Position{}
|
||||||
position.Update(point.X*cellsize, point.Y*cellsize, cellsize)
|
position.Update(point.X*cellsize, point.Y*cellsize, cellsize)
|
||||||
return position
|
return position
|
||||||
@ -39,8 +39,8 @@ func (position *Position) GetMoved(velosity *Velocity) *Position {
|
|||||||
return pos
|
return pos
|
||||||
}
|
}
|
||||||
|
|
||||||
func (position *Position) Point() *image.Point {
|
func (position *Position) Point() image.Point {
|
||||||
return &image.Point{position.X / position.Cellsize, position.Y / position.Cellsize}
|
return image.Point{position.X / position.Cellsize, position.Y / position.Cellsize}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (position *Position) Left() int {
|
func (position *Position) Left() int {
|
||||||
|
|||||||
11
game/game.go
11
game/game.go
@ -1,6 +1,7 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
@ -12,10 +13,10 @@ type Game struct {
|
|||||||
Bounds image.Rectangle
|
Bounds image.Rectangle
|
||||||
ScreenWidth, ScreenHeight int
|
ScreenWidth, ScreenHeight int
|
||||||
CurrentLevel int
|
CurrentLevel int
|
||||||
Scenes []Scene
|
Scenes map[int]Scene
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGame(width, height, startlevel int) *Game {
|
func NewGame(width, height, startlevel int, startscene int) *Game {
|
||||||
world := ecs.NewWorld()
|
world := ecs.NewWorld()
|
||||||
|
|
||||||
game := &Game{
|
game := &Game{
|
||||||
@ -24,10 +25,12 @@ func NewGame(width, height, startlevel int) *Game {
|
|||||||
World: &world,
|
World: &world,
|
||||||
ScreenWidth: width,
|
ScreenWidth: width,
|
||||||
ScreenHeight: height,
|
ScreenHeight: height,
|
||||||
|
Scenes: map[int]Scene{},
|
||||||
}
|
}
|
||||||
|
|
||||||
levelscene := NewLevelScene(game, startlevel)
|
game.Scenes[Play] = NewLevelScene(game, startlevel)
|
||||||
game.Scenes = append(game.Scenes, levelscene)
|
|
||||||
|
fmt.Println(game.World.Stats().String())
|
||||||
|
|
||||||
return game
|
return game
|
||||||
}
|
}
|
||||||
|
|||||||
40
game/grid.go
40
game/grid.go
@ -8,6 +8,7 @@ import (
|
|||||||
"openquell/components"
|
"openquell/components"
|
||||||
. "openquell/config"
|
. "openquell/config"
|
||||||
|
|
||||||
|
"github.com/alecthomas/repr"
|
||||||
"github.com/mlange-42/arche/generic"
|
"github.com/mlange-42/arche/generic"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -90,7 +91,6 @@ func (grid *Grid) GetSolidNeighborPosition(
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(position)
|
|
||||||
// set to true, ifwe are already on the last tile in the current
|
// set to true, ifwe are already on the last tile in the current
|
||||||
// direction, i.e. on the edge of the grid
|
// direction, i.e. on the edge of the grid
|
||||||
edge := true
|
edge := true
|
||||||
@ -120,9 +120,43 @@ func (grid *Grid) GetSolidNeighborPosition(
|
|||||||
}
|
}
|
||||||
|
|
||||||
newpos := components.NewPosition(neighborpos, grid.Tilesize)
|
newpos := components.NewPosition(neighborpos, grid.Tilesize)
|
||||||
fmt.Println(newpos, edge)
|
repr.Println(newpos)
|
||||||
|
|
||||||
if !edge && grid.Map[*neighborpos].Solid {
|
if !edge && grid.Map[neighborpos].Solid {
|
||||||
|
return true, newpos
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (grid *Grid) BumpEdge(
|
||||||
|
pos *components.Position,
|
||||||
|
velocity *components.Velocity) (bool, *components.Position) {
|
||||||
|
|
||||||
|
x := pos.X + velocity.Data.X
|
||||||
|
y := pos.Y + velocity.Data.Y
|
||||||
|
|
||||||
|
if x < 0 || x > grid.Width-grid.Tilesize || y < 0 || y > grid.Height-grid.Tilesize {
|
||||||
|
newpos := &components.Position{}
|
||||||
|
X := pos.X
|
||||||
|
Y := pos.Y
|
||||||
|
|
||||||
|
switch velocity.Direction {
|
||||||
|
case East:
|
||||||
|
X = 0
|
||||||
|
fmt.Println("east X=0")
|
||||||
|
case West:
|
||||||
|
X = grid.Width - grid.Tilesize
|
||||||
|
fmt.Println("west X=max")
|
||||||
|
case South:
|
||||||
|
Y = 0
|
||||||
|
fmt.Println("south y=0")
|
||||||
|
case North:
|
||||||
|
Y = grid.Height - grid.Tilesize
|
||||||
|
fmt.Println("north y=max")
|
||||||
|
}
|
||||||
|
|
||||||
|
newpos.Update(X, Y, grid.Tilesize)
|
||||||
return true, newpos
|
return true, newpos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,10 +25,7 @@ type Level struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||||
//grid := NewGrid(game, cellsize, plan)
|
|
||||||
|
|
||||||
return &Level{
|
return &Level{
|
||||||
//Grid: grid,
|
|
||||||
Mapslice: LevelToSlice(game, plan, cellsize),
|
Mapslice: LevelToSlice(game, plan, cellsize),
|
||||||
Cellsize: cellsize,
|
Cellsize: cellsize,
|
||||||
World: game.World,
|
World: game.World,
|
||||||
@ -40,19 +37,13 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (level *Level) Update() {
|
func (level *Level) Update() {
|
||||||
//playermapper := generic.NewMap3[components.Position, components.Velocity, components.Renderable](level.World)
|
|
||||||
positionid := ecs.ComponentID[components.Position](level.World)
|
positionid := ecs.ComponentID[components.Position](level.World)
|
||||||
velocityid := ecs.ComponentID[components.Velocity](level.World)
|
velocityid := ecs.ComponentID[components.Velocity](level.World)
|
||||||
playerid := ecs.ComponentID[components.Player](level.World)
|
playerid := ecs.ComponentID[components.Player](level.World)
|
||||||
//solidid := ecs.ComponentID[components.Solid](level.World)
|
|
||||||
//renderid := ecs.ComponentID[components.Renderable](level.World)
|
|
||||||
|
|
||||||
selector := filter.All(positionid, velocityid, playerid)
|
selector := filter.All(positionid, velocityid, playerid)
|
||||||
query := level.World.Query(selector)
|
query := level.World.Query(selector)
|
||||||
|
|
||||||
//tileselector := filter.All(positionid, solidid, renderid)
|
|
||||||
//tilequery := level.World.Query(tileselector)
|
|
||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
playerposition := (*components.Position)(query.Get(positionid))
|
playerposition := (*components.Position)(query.Get(positionid))
|
||||||
velocity := (*components.Velocity)(query.Get(velocityid))
|
velocity := (*components.Velocity)(query.Get(velocityid))
|
||||||
@ -90,17 +81,23 @@ func (level *Level) Update() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if velocity.Moving() {
|
if velocity.Moving() {
|
||||||
ok, tilepos := level.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
|
ok, newpos := level.Grid.BumpEdge(playerposition, velocity)
|
||||||
if ok {
|
if ok {
|
||||||
intersects, newpos := tilepos.Intersects(playerposition, velocity)
|
fmt.Printf("falling off the edge, new pos: %v\n", newpos)
|
||||||
if intersects {
|
playerposition.Set(newpos)
|
||||||
fmt.Printf("collision detected. tile: %s\n", tilepos)
|
} else {
|
||||||
fmt.Printf(" player: %s\n", playerposition)
|
ok, tilepos := level.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
|
||||||
fmt.Printf(" new: %s\n", newpos)
|
if ok {
|
||||||
|
intersects, newpos := tilepos.Intersects(playerposition, velocity)
|
||||||
|
if intersects {
|
||||||
|
fmt.Printf("collision detected. tile: %s\n", tilepos)
|
||||||
|
fmt.Printf(" player: %s\n", playerposition)
|
||||||
|
fmt.Printf(" new: %s\n", newpos)
|
||||||
|
|
||||||
playerposition.Set(newpos)
|
playerposition.Set(newpos)
|
||||||
fmt.Printf(" player new: %s\n", playerposition)
|
fmt.Printf(" player new: %s\n", playerposition)
|
||||||
velocity.Change(Stop)
|
velocity.Change(Stop)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
49
game/levelscene.go
Normal file
49
game/levelscene.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package game
|
||||||
|
|
||||||
|
import (
|
||||||
|
"openquell/assets"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LevelScene struct {
|
||||||
|
CurrentLevel int
|
||||||
|
Levels []*Level
|
||||||
|
Next int
|
||||||
|
Whoami int
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements the actual playing Scene
|
||||||
|
func NewLevelScene(game *Game, startlevel int) Scene {
|
||||||
|
scene := &LevelScene{CurrentLevel: startlevel, Whoami: Play}
|
||||||
|
|
||||||
|
scene.GenerateLevels(game)
|
||||||
|
scene.Levels[game.CurrentLevel].SetupGrid(game)
|
||||||
|
|
||||||
|
return scene
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scene *LevelScene) GenerateLevels(game *Game) {
|
||||||
|
for _, level := range assets.Levels {
|
||||||
|
scene.Levels = append(scene.Levels, NewLevel(game, 32, &level))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface methods
|
||||||
|
func (scene *LevelScene) SetNext() int {
|
||||||
|
if scene.Whoami != scene.Next {
|
||||||
|
return scene.Next
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scene *LevelScene) Update() error {
|
||||||
|
scene.Levels[scene.CurrentLevel].Update()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scene *LevelScene) Draw(screen *ebiten.Image) {
|
||||||
|
screen.Clear()
|
||||||
|
scene.Levels[scene.CurrentLevel].Draw(screen)
|
||||||
|
}
|
||||||
@ -1,51 +1,24 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"openquell/assets"
|
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Welcome = iota
|
||||||
|
Select
|
||||||
|
Play
|
||||||
|
About
|
||||||
|
Settings
|
||||||
|
)
|
||||||
|
|
||||||
// Wrapper for different screens to be shown, as Welcome, Options,
|
// Wrapper for different screens to be shown, as Welcome, Options,
|
||||||
// About, Select Level and of course the actual Levels.
|
// About, Select Level and of course the actual Levels.
|
||||||
// Scenes are responsible for screen clearing! That way a scene is able
|
// Scenes are responsible for screen clearing! That way a scene is able
|
||||||
// to render its content onto the running level, e.g. the options scene
|
// to render its content onto the running level, e.g. the options scene
|
||||||
// etc.
|
// etc.
|
||||||
type Scene interface {
|
type Scene interface {
|
||||||
|
SetNext() int
|
||||||
Update() error
|
Update() error
|
||||||
Draw(screen *ebiten.Image)
|
Draw(screen *ebiten.Image)
|
||||||
}
|
}
|
||||||
|
|
||||||
type LevelScene struct {
|
|
||||||
Game *Game
|
|
||||||
CurrentLevel int
|
|
||||||
Levels []*Level
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implements the actual playing Scene
|
|
||||||
func NewLevelScene(game *Game, startlevel int) Scene {
|
|
||||||
scene := &LevelScene{Game: game, CurrentLevel: startlevel}
|
|
||||||
|
|
||||||
scene.GenerateLevels()
|
|
||||||
scene.Levels[game.CurrentLevel].SetupGrid(game)
|
|
||||||
fmt.Println(game.World.Stats().String())
|
|
||||||
|
|
||||||
return scene
|
|
||||||
}
|
|
||||||
|
|
||||||
func (scene *LevelScene) GenerateLevels() {
|
|
||||||
for _, level := range assets.Levels {
|
|
||||||
scene.Levels = append(scene.Levels, NewLevel(scene.Game, 32, &level))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (scene *LevelScene) Update() error {
|
|
||||||
scene.Levels[scene.CurrentLevel].Update()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (scene *LevelScene) Draw(screen *ebiten.Image) {
|
|
||||||
screen.Clear()
|
|
||||||
scene.Levels[scene.CurrentLevel].Draw(screen)
|
|
||||||
}
|
|
||||||
|
|||||||
2
main.go
2
main.go
@ -16,7 +16,7 @@ func main() {
|
|||||||
ebiten.SetWindowSize(width, height)
|
ebiten.SetWindowSize(width, height)
|
||||||
ebiten.SetWindowTitle("openquell")
|
ebiten.SetWindowTitle("openquell")
|
||||||
|
|
||||||
g := game.NewGame(width, height, 0)
|
g := game.NewGame(width, height, 0, game.Play)
|
||||||
|
|
||||||
err := ebiten.RunGame(g)
|
err := ebiten.RunGame(g)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user