added collectibles support
This commit is contained in:
parent
ce7fcd038a
commit
a0b40139c7
@ -9,9 +9,9 @@ Background: background-orange
|
|||||||
# ######## ###
|
# ######## ###
|
||||||
#
|
#
|
||||||
############ #
|
############ #
|
||||||
# # #
|
# o # #
|
||||||
# # ######## #
|
# # ######## #
|
||||||
# #
|
# # o
|
||||||
# ############
|
# ############
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,13 +20,14 @@ var Tiles = InitTiles()
|
|||||||
// Tile: contains image, identifier (as used in level data) and
|
// Tile: contains image, identifier (as used in level data) and
|
||||||
// additional properties
|
// additional properties
|
||||||
type Tile struct {
|
type Tile struct {
|
||||||
Id byte
|
Id byte
|
||||||
Sprite *ebiten.Image
|
Sprite *ebiten.Image
|
||||||
Class string
|
Class string
|
||||||
Solid bool
|
Solid bool
|
||||||
Player bool
|
Player bool
|
||||||
Renderable bool
|
Renderable bool
|
||||||
Velocity bool
|
Velocity bool
|
||||||
|
Collectible bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTilePlayer() *Tile {
|
func NewTilePlayer() *Tile {
|
||||||
@ -50,6 +51,17 @@ func NewTileBlock(class string) *Tile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewTileCollectible(class string) *Tile {
|
||||||
|
return &Tile{
|
||||||
|
Id: 'o',
|
||||||
|
Sprite: Assets[class],
|
||||||
|
Class: class,
|
||||||
|
Solid: false,
|
||||||
|
Renderable: true,
|
||||||
|
Collectible: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// used to map level data bytes to actual tiles
|
// used to map level data bytes to actual tiles
|
||||||
type TileRegistry map[byte]*Tile
|
type TileRegistry map[byte]*Tile
|
||||||
|
|
||||||
@ -77,6 +89,7 @@ func InitTiles() TileRegistry {
|
|||||||
' ': {Id: ' ', Class: "floor", Renderable: false},
|
' ': {Id: ' ', Class: "floor", Renderable: false},
|
||||||
'#': NewTileBlock("block-grey32"),
|
'#': NewTileBlock("block-grey32"),
|
||||||
'S': NewTilePlayer(),
|
'S': NewTilePlayer(),
|
||||||
|
'o': NewTileCollectible("collectible-orange"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,3 +15,4 @@ type Tilish struct{}
|
|||||||
type Solid struct{}
|
type Solid struct{}
|
||||||
type Floor struct{}
|
type Floor struct{}
|
||||||
type Player struct{}
|
type Player struct{}
|
||||||
|
type Collectible struct{}
|
||||||
|
|||||||
10
game/grid.go
10
game/grid.go
@ -32,13 +32,20 @@ func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *G
|
|||||||
components.Velocity,
|
components.Velocity,
|
||||||
components.Renderable,
|
components.Renderable,
|
||||||
components.Player](game.World)
|
components.Player](game.World)
|
||||||
|
|
||||||
solidmapper := generic.NewMap4[
|
solidmapper := generic.NewMap4[
|
||||||
components.Position,
|
components.Position,
|
||||||
components.Renderable,
|
components.Renderable,
|
||||||
components.Tilish,
|
components.Tilish,
|
||||||
components.Solid](game.World)
|
components.Solid](game.World)
|
||||||
|
|
||||||
emptymapper := generic.NewMap2[components.Position, components.Tilish](game.World)
|
emptymapper := generic.NewMap2[components.Position, components.Tilish](game.World)
|
||||||
|
|
||||||
|
colmapper := generic.NewMap3[
|
||||||
|
components.Position,
|
||||||
|
components.Renderable,
|
||||||
|
components.Collectible](game.World)
|
||||||
|
|
||||||
var pos *components.Position
|
var pos *components.Position
|
||||||
var render *components.Renderable
|
var render *components.Renderable
|
||||||
|
|
||||||
@ -53,6 +60,9 @@ func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *G
|
|||||||
entity := playermapper.New()
|
entity := playermapper.New()
|
||||||
pos, _, render, _ = playermapper.Get(entity)
|
pos, _, render, _ = playermapper.Get(entity)
|
||||||
fmt.Printf("player start pos: %d,%d\n", point.X*tilesize, point.Y*tilesize)
|
fmt.Printf("player start pos: %d,%d\n", point.X*tilesize, point.Y*tilesize)
|
||||||
|
case tile.Collectible:
|
||||||
|
entity := colmapper.New()
|
||||||
|
pos, render, _ = colmapper.Get(entity)
|
||||||
default:
|
default:
|
||||||
log.Fatalln("unsupported tile type encountered")
|
log.Fatalln("unsupported tile type encountered")
|
||||||
}
|
}
|
||||||
|
|||||||
126
game/levels.go
126
game/levels.go
@ -3,6 +3,7 @@ package game
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
|
"image/draw"
|
||||||
"log"
|
"log"
|
||||||
"openquell/assets"
|
"openquell/assets"
|
||||||
"openquell/components"
|
"openquell/components"
|
||||||
@ -22,9 +23,30 @@ type Level struct {
|
|||||||
Description string
|
Description string
|
||||||
Background *ebiten.Image
|
Background *ebiten.Image
|
||||||
Mapslice map[image.Point]*assets.Tile
|
Mapslice map[image.Point]*assets.Tile
|
||||||
|
UseCache bool
|
||||||
|
Cache *ebiten.Image
|
||||||
|
Selector map[string]ecs.Mask
|
||||||
|
Component map[string]ecs.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
||||||
|
cache := ebiten.NewImage(game.ScreenWidth, game.ScreenHeight)
|
||||||
|
|
||||||
|
positionid := ecs.ComponentID[components.Position](game.World)
|
||||||
|
velocityid := ecs.ComponentID[components.Velocity](game.World)
|
||||||
|
playerid := ecs.ComponentID[components.Player](game.World)
|
||||||
|
colid := ecs.ComponentID[components.Collectible](game.World)
|
||||||
|
|
||||||
|
selectors := map[string]ecs.Mask{}
|
||||||
|
selectors["player"] = filter.All(positionid, velocityid, playerid)
|
||||||
|
selectors["collectible"] = filter.All(positionid, colid)
|
||||||
|
|
||||||
|
components := map[string]ecs.ID{}
|
||||||
|
components["position"] = positionid
|
||||||
|
components["velocity"] = velocityid
|
||||||
|
components["player"] = playerid
|
||||||
|
components["collectible"] = colid
|
||||||
|
|
||||||
return &Level{
|
return &Level{
|
||||||
Mapslice: LevelToSlice(game, plan, cellsize),
|
Mapslice: LevelToSlice(game, plan, cellsize),
|
||||||
Cellsize: cellsize,
|
Cellsize: cellsize,
|
||||||
@ -33,53 +55,35 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
|
|||||||
Height: game.ScreenHeight,
|
Height: game.ScreenHeight,
|
||||||
Description: plan.Description,
|
Description: plan.Description,
|
||||||
Background: plan.Background,
|
Background: plan.Background,
|
||||||
|
UseCache: false,
|
||||||
|
Cache: cache,
|
||||||
|
Selector: selectors,
|
||||||
|
Component: components,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (level *Level) Update() {
|
func (level *Level) Update() {
|
||||||
positionid := ecs.ComponentID[components.Position](level.World)
|
query := level.World.Query(level.Selector["player"])
|
||||||
velocityid := ecs.ComponentID[components.Velocity](level.World)
|
colquery := level.World.Query(level.Selector["collectible"])
|
||||||
playerid := ecs.ComponentID[components.Player](level.World)
|
|
||||||
|
|
||||||
selector := filter.All(positionid, velocityid, playerid)
|
|
||||||
query := level.World.Query(selector)
|
|
||||||
|
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
playerposition := (*components.Position)(query.Get(positionid))
|
playerposition := (*components.Position)(query.Get(level.Component["position"]))
|
||||||
velocity := (*components.Velocity)(query.Get(velocityid))
|
velocity := (*components.Velocity)(query.Get(level.Component["velocity"]))
|
||||||
|
|
||||||
switch {
|
if !velocity.Moving() {
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyRight):
|
switch {
|
||||||
velocity.Change(East)
|
case ebiten.IsKeyPressed(ebiten.KeyRight):
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyLeft):
|
velocity.Change(East)
|
||||||
velocity.Change(West)
|
case ebiten.IsKeyPressed(ebiten.KeyLeft):
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyDown):
|
velocity.Change(West)
|
||||||
velocity.Change(South)
|
case ebiten.IsKeyPressed(ebiten.KeyDown):
|
||||||
case ebiten.IsKeyPressed(ebiten.KeyUp):
|
velocity.Change(South)
|
||||||
velocity.Change(North)
|
case ebiten.IsKeyPressed(ebiten.KeyUp):
|
||||||
// other keys: <tab>: switch player, etc
|
velocity.Change(North)
|
||||||
|
// other keys: <tab>: switch player, etc
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Use this to check against obstacles, collectibles etc
|
|
||||||
for tilequery.Next() {
|
|
||||||
tilepos := (*components.Position)(tilequery.Get(positionid))
|
|
||||||
|
|
||||||
if velocity.Moving() {
|
|
||||||
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)
|
|
||||||
fmt.Printf(" player new: %s\n", playerposition)
|
|
||||||
velocity.Change(Stop)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if velocity.Moving() {
|
if velocity.Moving() {
|
||||||
ok, newpos := level.Grid.BumpEdge(playerposition, velocity)
|
ok, newpos := level.Grid.BumpEdge(playerposition, velocity)
|
||||||
if ok {
|
if ok {
|
||||||
@ -100,6 +104,15 @@ func (level *Level) Update() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for colquery.Next() {
|
||||||
|
collectible := (*components.Collectible)(colquery.Get(level.Component["collectible"]))
|
||||||
|
colposition := (*components.Position)(colquery.Get(level.Component["position"]))
|
||||||
|
ok, _ := playerposition.Intersects(colposition, velocity)
|
||||||
|
if ok {
|
||||||
|
fmt.Printf("bumped into collectible %v\n", collectible)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
playerposition.Move(velocity)
|
playerposition.Move(velocity)
|
||||||
@ -125,16 +138,41 @@ func (level *Level) GetTile(position *components.Position, velocity *components.
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (level *Level) Draw(screen *ebiten.Image) {
|
func (level *Level) Draw(screen *ebiten.Image) {
|
||||||
// FIXME: move out
|
|
||||||
op := &ebiten.DrawImageOptions{}
|
|
||||||
screen.DrawImage(level.Background, op)
|
|
||||||
|
|
||||||
rid := ecs.ComponentID[components.Renderable](level.World)
|
rid := ecs.ComponentID[components.Renderable](level.World)
|
||||||
pid := ecs.ComponentID[components.Position](level.World)
|
pid := ecs.ComponentID[components.Position](level.World)
|
||||||
|
sid := ecs.ComponentID[components.Solid](level.World)
|
||||||
|
|
||||||
selector := filter.All(rid, pid)
|
if !level.UseCache {
|
||||||
|
// map not cached or cacheable, write it to the cache
|
||||||
|
draw.Draw(level.Cache, level.Background.Bounds(), level.Background, image.ZP, draw.Src)
|
||||||
|
|
||||||
query := level.World.Query(selector)
|
selector := filter.All(rid, pid, sid)
|
||||||
|
|
||||||
|
query := level.World.Query(selector)
|
||||||
|
for query.Next() {
|
||||||
|
pos := (*components.Position)(query.Get(pid))
|
||||||
|
sprite := (*components.Renderable)(query.Get(rid))
|
||||||
|
|
||||||
|
draw.Draw(
|
||||||
|
level.Cache,
|
||||||
|
image.Rect(pos.X, pos.Y, pos.X+pos.Cellsize, pos.Y+pos.Cellsize),
|
||||||
|
sprite.Image, image.ZP, draw.Over)
|
||||||
|
}
|
||||||
|
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
screen.DrawImage(level.Cache, op)
|
||||||
|
|
||||||
|
level.UseCache = true
|
||||||
|
} else {
|
||||||
|
// use the cached map
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
screen.DrawImage(level.Cache, op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// write the movable tiles
|
||||||
|
selector := filter.All(rid, pid).Without(sid)
|
||||||
|
|
||||||
|
query := level.World.Query(&selector)
|
||||||
for query.Next() {
|
for query.Next() {
|
||||||
pos := (*components.Position)(query.Get(pid))
|
pos := (*components.Position)(query.Get(pid))
|
||||||
sprite := (*components.Renderable)(query.Get(rid))
|
sprite := (*components.Renderable)(query.Get(rid))
|
||||||
|
|||||||
@ -11,6 +11,7 @@ type LevelScene struct {
|
|||||||
Levels []*Level
|
Levels []*Level
|
||||||
Next int
|
Next int
|
||||||
Whoami int
|
Whoami int
|
||||||
|
UseCache bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements the actual playing Scene
|
// Implements the actual playing Scene
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user