changes:
- exchanged switch+door sprites - added asesprite cheat sheet - implemented door toggle on switch toggle
23
asesprite.org
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
| key | sub key | function | hint |
|
||||||
|
|--------------+------------+-----------------------+----------------------------------|
|
||||||
|
| b | | brush | |
|
||||||
|
| | d | draw | |
|
||||||
|
| | s | shape | select color range before |
|
||||||
|
| | x | switch color order | |
|
||||||
|
| | a | alpha shape | |
|
||||||
|
| | ctrl+wheel | brush size | |
|
||||||
|
| c | | pick color | |
|
||||||
|
| e | | erase | |
|
||||||
|
| z | | zoom | click and drag, left+right click |
|
||||||
|
| middle mouse | | move canvas | |
|
||||||
|
| f | | fill | inside selection |
|
||||||
|
| ctrl-d | | no selection | |
|
||||||
|
| m | | marquee | rect selection |
|
||||||
|
| w | | select by color | contiguous: all or only region |
|
||||||
|
| q | | lasso select | |
|
||||||
|
| tab | | hide/show layers | |
|
||||||
|
| v | | switch layer | by click on region |
|
||||||
|
| alt-n | | new frame | |
|
||||||
|
| shift-n | | new layer | |
|
||||||
|
| ctrl-f | | hide/show ui elements | |
|
||||||
|
| shift-o | | outline tool | |
|
||||||
@ -6096,7 +6096,15 @@
|
|||||||
"height": 32,
|
"height": 32,
|
||||||
"defUid": 65,
|
"defUid": 65,
|
||||||
"px": [224,224],
|
"px": [224,224],
|
||||||
"fieldInstances": [{ "__identifier": "Entity_ref", "__type": "EntityRef", "__value": null, "__tile": null, "defUid": 68, "realEditorValues": [] }],
|
"fieldInstances": [{ "__identifier": "Entity_ref", "__type": "EntityRef", "__value": {
|
||||||
|
"entityIid": "7d975370-d7b0-11ee-9add-971995295000",
|
||||||
|
"layerIid": "50624190-d7b0-11ee-968e-3dbcbdc42f40",
|
||||||
|
"levelIid": "50621a80-d7b0-11ee-968e-a98c2d35fbdb",
|
||||||
|
"worldIid": "267ee1a0-d7b0-11ee-a97e-53f0a359eae1"
|
||||||
|
}, "__tile": null, "defUid": 68, "realEditorValues": [{
|
||||||
|
"id": "V_String",
|
||||||
|
"params": ["7d975370-d7b0-11ee-9add-971995295000"]
|
||||||
|
}] }],
|
||||||
"__worldX": 0,
|
"__worldX": 0,
|
||||||
"__worldY": 2976
|
"__worldY": 2976
|
||||||
},
|
},
|
||||||
|
|||||||
@ -240,8 +240,8 @@ func InitTiles() TileRegistry {
|
|||||||
"HiddenDoor11": NewTileHiddenDoor("block-greycolored", "damage"),
|
"HiddenDoor11": NewTileHiddenDoor("block-greycolored", "damage"),
|
||||||
"HiddenDoor12": NewTileHiddenDoor("block-greycolored", "damage"),
|
"HiddenDoor12": NewTileHiddenDoor("block-greycolored", "damage"),
|
||||||
"HiddenDoor13": NewTileHiddenDoor("block-greycolored", "damage"),
|
"HiddenDoor13": NewTileHiddenDoor("block-greycolored", "damage"),
|
||||||
"Switch": NewTileSwitch([]string{"switch-open.png", "switch-closed.png"}),
|
"Switch": NewTileSwitch([]string{"switch1", "switch2"}),
|
||||||
"Door": NewTileDoor([]string{"door-open.png", "door-closed.png"}),
|
"Door": NewTileDoor([]string{"door1", "door2"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 280 B |
|
Before Width: | Height: | Size: 250 B |
BIN
assets/sprites/door1.png
Normal file
|
After Width: | Height: | Size: 477 B |
BIN
assets/sprites/door2.png
Normal file
|
After Width: | Height: | Size: 446 B |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 464 B |
|
Before Width: | Height: | Size: 463 B |
BIN
assets/sprites/switch1.png
Normal file
|
After Width: | Height: | Size: 508 B |
BIN
assets/sprites/switch2.png
Normal file
|
After Width: | Height: | Size: 532 B |
@ -23,11 +23,15 @@ type Door struct {
|
|||||||
Id string
|
Id string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (door *Door) Open() *ebiten.Image {
|
func (door *Door) Toggle() {
|
||||||
return door.OpenSprite
|
door.IsOpen = !door.IsOpen
|
||||||
}
|
}
|
||||||
|
|
||||||
func (door *Door) Close() *ebiten.Image {
|
func (door *Door) Sprite() *ebiten.Image {
|
||||||
|
if door.IsOpen {
|
||||||
|
return door.OpenSprite
|
||||||
|
}
|
||||||
|
|
||||||
return door.CloseSprite
|
return door.CloseSprite
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,3 +43,15 @@ type Switch struct {
|
|||||||
CloseSprite *ebiten.Image
|
CloseSprite *ebiten.Image
|
||||||
Ref string // the IId of the door
|
Ref string // the IId of the door
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (switcher *Switch) Toggle() {
|
||||||
|
switcher.IsOpen = !switcher.IsOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
func (switcher *Switch) Sprite() *ebiten.Image {
|
||||||
|
if switcher.IsOpen {
|
||||||
|
return switcher.OpenSprite
|
||||||
|
}
|
||||||
|
|
||||||
|
return switcher.CloseSprite
|
||||||
|
}
|
||||||
|
|||||||
@ -55,6 +55,8 @@ func NewLevel(game *Game, cellsize int, plan *ldtkgo.Level) *Level {
|
|||||||
systemlist = append(systemlist, systems.NewDestroyableSystem(game.World, gridcontainer,
|
systemlist = append(systemlist, systems.NewDestroyableSystem(game.World, gridcontainer,
|
||||||
game.Cellsize))
|
game.Cellsize))
|
||||||
|
|
||||||
|
systemlist = append(systemlist, systems.NewPairSystem(game.World, gridcontainer))
|
||||||
|
|
||||||
systemlist = append(systemlist, systems.NewHudSystem(game.World, plan))
|
systemlist = append(systemlist, systems.NewHudSystem(game.World, plan))
|
||||||
|
|
||||||
mapslice, backupmap := LevelToSlice(game, plan, cellsize)
|
mapslice, backupmap := LevelToSlice(game, plan, cellsize)
|
||||||
@ -176,11 +178,15 @@ func LevelToSlice(game *Game, level *ldtkgo.Level, tilesize int) (Map, Map) {
|
|||||||
if ref.Value != nil {
|
if ref.Value != nil {
|
||||||
refid := ref.Value.(map[string]interface{})
|
refid := ref.Value.(map[string]interface{})
|
||||||
tile.Ref = refid["entityIid"].(string)
|
tile.Ref = refid["entityIid"].(string)
|
||||||
|
slog.Debug("LOAD TILE", "tileref",
|
||||||
|
tile.Ref, "tileid", tile.Id,
|
||||||
|
"name", entity.Identifier,
|
||||||
|
"isswitch", tile.Switch,
|
||||||
|
"isdoor", tile.Door,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
slog.Debug("LOAD TILE", "tile", entity.TileRect)
|
|
||||||
|
|
||||||
tileRect := entity.TileRect
|
tileRect := entity.TileRect
|
||||||
|
|
||||||
tile.Sprite = tileset.SubImage(
|
tile.Sprite = tileset.SubImage(
|
||||||
|
|||||||
12
grid/grid.go
@ -8,8 +8,6 @@ import (
|
|||||||
"openquell/config"
|
"openquell/config"
|
||||||
"openquell/observers"
|
"openquell/observers"
|
||||||
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/mlange-42/arche/ecs"
|
"github.com/mlange-42/arche/ecs"
|
||||||
"github.com/mlange-42/arche/generic"
|
"github.com/mlange-42/arche/generic"
|
||||||
)
|
)
|
||||||
@ -141,16 +139,16 @@ func NewGrid(world *ecs.World,
|
|||||||
case tile.Switch:
|
case tile.Switch:
|
||||||
entity := switchmapper.New()
|
entity := switchmapper.New()
|
||||||
pos, render, _, switcher = switchmapper.Get(entity)
|
pos, render, _, switcher = switchmapper.Get(entity)
|
||||||
switcher.OpenSprite = tile.Tiles[0]
|
|
||||||
switcher.CloseSprite = tile.Tiles[0]
|
switcher.CloseSprite = tile.Tiles[0]
|
||||||
|
switcher.OpenSprite = tile.Tiles[1]
|
||||||
switcher.Ref = tile.Ref
|
switcher.Ref = tile.Ref
|
||||||
switches = append(switches, entity)
|
switches = append(switches, entity)
|
||||||
|
|
||||||
case tile.Door:
|
case tile.Door:
|
||||||
entity := doormapper.New()
|
entity := doormapper.New()
|
||||||
pos, render, _, door = doormapper.Get(entity)
|
pos, render, _, door = doormapper.Get(entity)
|
||||||
door.OpenSprite = tile.Tiles[0]
|
|
||||||
door.CloseSprite = tile.Tiles[0]
|
door.CloseSprite = tile.Tiles[0]
|
||||||
|
door.OpenSprite = tile.Tiles[1]
|
||||||
door.Id = tile.Id
|
door.Id = tile.Id
|
||||||
doors = append(doors, entity)
|
doors = append(doors, entity)
|
||||||
|
|
||||||
@ -176,17 +174,19 @@ func NewGrid(world *ecs.World,
|
|||||||
pos.Update(point.X*tilesize, point.Y*tilesize, tilesize)
|
pos.Update(point.X*tilesize, point.Y*tilesize, tilesize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for switch->door references
|
||||||
for _, switchentity := range switches {
|
for _, switchentity := range switches {
|
||||||
_, _, bond, switcher = switchmapper.Get(switchentity)
|
_, _, bond, switcher = switchmapper.Get(switchentity)
|
||||||
|
|
||||||
if switcher.Ref != "" {
|
if switcher.Ref != "" {
|
||||||
|
// this switch has a reference
|
||||||
for _, doorentity := range doors {
|
for _, doorentity := range doors {
|
||||||
_, _, _, door = doormapper.Get(doorentity)
|
_, _, _, door = doormapper.Get(doorentity)
|
||||||
if door.Id == switcher.Ref {
|
if door.Id == switcher.Ref {
|
||||||
|
// the switch reference matches the door id, relate the two
|
||||||
bond.Ref = switcher.Ref
|
bond.Ref = switcher.Ref
|
||||||
relID := ecs.ComponentID[components.Bond](world)
|
relID := ecs.ComponentID[components.Bond](world)
|
||||||
world.Relations().Set(doorentity, relID, switchentity)
|
world.Relations().Set(switchentity, relID, doorentity)
|
||||||
slog.Debug("setup switch/door reference")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
117
systems/pair_system.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package systems
|
||||||
|
|
||||||
|
import (
|
||||||
|
"openquell/components"
|
||||||
|
. "openquell/components"
|
||||||
|
. "openquell/config"
|
||||||
|
"openquell/grid"
|
||||||
|
"openquell/observers"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
|
"github.com/mlange-42/arche/ecs"
|
||||||
|
"github.com/mlange-42/arche/generic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PairSystem struct {
|
||||||
|
World *ecs.World
|
||||||
|
DoorSelector *generic.Filter4[Position, Renderable, Bond, Door]
|
||||||
|
SwitchSelector *generic.Filter4[Position, Renderable, Bond, Switch]
|
||||||
|
GridContainer *grid.GridContainer
|
||||||
|
DoorMapper generic.Map4[
|
||||||
|
components.Position,
|
||||||
|
components.Renderable,
|
||||||
|
components.Bond,
|
||||||
|
components.Door]
|
||||||
|
}
|
||||||
|
|
||||||
|
type ToggleDoor struct {
|
||||||
|
Entity ecs.Entity
|
||||||
|
Open bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPairSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
|
||||||
|
doormapper := generic.NewMap4[
|
||||||
|
components.Position,
|
||||||
|
components.Renderable,
|
||||||
|
components.Bond,
|
||||||
|
components.Door](world)
|
||||||
|
|
||||||
|
system := &PairSystem{
|
||||||
|
DoorSelector: generic.NewFilter4[Position, Renderable, Bond, Door](),
|
||||||
|
SwitchSelector: generic.NewFilter4[Position, Renderable, Bond, Switch](),
|
||||||
|
World: world,
|
||||||
|
GridContainer: gridcontainer,
|
||||||
|
DoorMapper: doormapper,
|
||||||
|
}
|
||||||
|
|
||||||
|
return system
|
||||||
|
}
|
||||||
|
|
||||||
|
func (system *PairSystem) Update() error {
|
||||||
|
observer := observers.GetGameObserver(system.World)
|
||||||
|
posID := ecs.ComponentID[components.Position](system.World)
|
||||||
|
veloID := ecs.ComponentID[components.Velocity](system.World)
|
||||||
|
|
||||||
|
query := system.SwitchSelector.Query(system.World)
|
||||||
|
relID := ecs.ComponentID[Bond](system.World)
|
||||||
|
|
||||||
|
EntitiesToSwitch := []*ToggleDoor{}
|
||||||
|
|
||||||
|
for query.Next() {
|
||||||
|
swpos, _, _, switcher := query.Get()
|
||||||
|
|
||||||
|
for _, player := range observer.GetPlayers() {
|
||||||
|
if !system.World.Alive(player) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
playerposition := (*Position)(system.World.Get(player, posID))
|
||||||
|
playervelocity := (*Velocity)(system.World.Get(player, veloID))
|
||||||
|
|
||||||
|
ok, newpos := swpos.Intersects(playerposition, playervelocity)
|
||||||
|
if ok {
|
||||||
|
// player moved on top of the switch
|
||||||
|
switcher.Toggle()
|
||||||
|
// open door
|
||||||
|
door := system.World.Relations().Get(query.Entity(), relID)
|
||||||
|
EntitiesToSwitch = append(EntitiesToSwitch,
|
||||||
|
&ToggleDoor{Entity: door, Open: true})
|
||||||
|
|
||||||
|
playervelocity.Change(Stop)
|
||||||
|
playerposition.Set(newpos)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, toggle := range EntitiesToSwitch {
|
||||||
|
_, _, _, door := system.DoorMapper.Get(toggle.Entity)
|
||||||
|
door.Toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (system *PairSystem) Draw(screen *ebiten.Image) {
|
||||||
|
op := &ebiten.DrawImageOptions{}
|
||||||
|
query := system.SwitchSelector.Query(system.World)
|
||||||
|
|
||||||
|
for query.Next() {
|
||||||
|
pos, _, _, switcher := query.Get()
|
||||||
|
|
||||||
|
op.GeoM.Reset()
|
||||||
|
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||||
|
screen.DrawImage(switcher.Sprite(), op)
|
||||||
|
}
|
||||||
|
|
||||||
|
doorquery := system.DoorSelector.Query(system.World)
|
||||||
|
|
||||||
|
for doorquery.Next() {
|
||||||
|
pos, _, _, door := doorquery.Get()
|
||||||
|
|
||||||
|
op.GeoM.Reset()
|
||||||
|
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
|
||||||
|
screen.DrawImage(door.Sprite(), op)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||