added hidden doors/destroyable walls, fixed game reloading (tile clone)
This commit is contained in:
		
							parent
							
								
									ab07bc23e3
								
							
						
					
					
						commit
						b0a8060d5b
					
				
							
								
								
									
										6
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								TODO.md
									
									
									
									
									
								
							| @ -33,3 +33,9 @@ if inpututil.IsKeyJustPressed(ebiten.KeyS) { | |||||||
|   the edge of the obstacle and not inside as it is now |   the edge of the obstacle and not inside as it is now | ||||||
|    |    | ||||||
| - Check player-player collisions! | - Check player-player collisions! | ||||||
|  | 
 | ||||||
|  | - Do all collision detections in ONE system | ||||||
|  | 
 | ||||||
|  | - do not use the map anymore for collision detection | ||||||
|  | 
 | ||||||
|  | - check swept AABB instead of my collision detection, to allow for higher speeds | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ Background: background-lila | |||||||
|                      |                      | ||||||
|                      |                      | ||||||
|    #######           |    #######           | ||||||
|    #     #           |    #o    #           | ||||||
|    #  t  #           |    #  t  #           | ||||||
|    #> S <#           |    #> S <#           | ||||||
|    #     #           |    #     #           | ||||||
|  | |||||||
| @ -4,13 +4,13 @@ Background: background-lila | |||||||
|                      |                      | ||||||
|                      |                      | ||||||
|                      |                      | ||||||
|      ##########      |      ########W#      | ||||||
|     #         v#     |     #     v    #     | ||||||
|     #          #     |     #          #     | ||||||
|     #S        s#     |     #S        s#     | ||||||
|     #          #     |     ############     | ||||||
|     #^         #     |     # o        #     | ||||||
|      ##########      |      ######## #      | ||||||
|                      |                      | ||||||
|                      |                      | ||||||
|                      |                      | ||||||
|  | |||||||
| @ -25,18 +25,42 @@ type Tile struct { | |||||||
| 	Id          byte | 	Id          byte | ||||||
| 	Sprite      *ebiten.Image | 	Sprite      *ebiten.Image | ||||||
| 	Class       string | 	Class       string | ||||||
| 	Solid       bool | 	Solid       bool            // wall brick | ||||||
| 	Player      bool | 	Player      bool            // player sphere | ||||||
| 	IsPrimary   bool | 	IsPrimary   bool            // primary player sphere | ||||||
| 	Renderable  bool | 	Renderable  bool            // visible, has sprite | ||||||
| 	Velocity    bool | 	Velocity    bool            // movable | ||||||
| 	Collectible bool | 	Collectible bool            // collectible, vanishes once collected | ||||||
| 	Transient   bool | 	Transient   bool            // turns into brick wall when traversed | ||||||
|  | 	Destroyable bool            // turns into empty floor when bumped into twice | ||||||
| 	Particle    int             // -1=unused, 0-3 = show image of slice | 	Particle    int             // -1=unused, 0-3 = show image of slice | ||||||
| 	Tiles       []*ebiten.Image | 	Tiles       []*ebiten.Image // has N sprites | ||||||
| 	TileNames   []string        // same thing, only the names | 	TileNames   []string        // same thing, only the names | ||||||
| 	Obstacle    bool | 	Obstacle    bool            // is an obstacle/enemy | ||||||
| 	Direction   int // obstacles | 	Direction   int             // obstacle business end shows into this direction | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (tile *Tile) Clone() *Tile { | ||||||
|  | 	newtile := &Tile{ | ||||||
|  | 		Id:          tile.Id, | ||||||
|  | 		Sprite:      tile.Sprite, | ||||||
|  | 		Class:       tile.Class, | ||||||
|  | 		Solid:       tile.Solid, | ||||||
|  | 		Player:      tile.Player, | ||||||
|  | 		IsPrimary:   tile.IsPrimary, | ||||||
|  | 		Renderable:  tile.Renderable, | ||||||
|  | 		Velocity:    tile.Velocity, | ||||||
|  | 		Collectible: tile.Collectible, | ||||||
|  | 		Transient:   tile.Transient, | ||||||
|  | 		Destroyable: tile.Destroyable, | ||||||
|  | 		Particle:    tile.Particle, | ||||||
|  | 		Tiles:       tile.Tiles, | ||||||
|  | 		TileNames:   tile.TileNames, | ||||||
|  | 		Obstacle:    tile.Obstacle, | ||||||
|  | 		Direction:   tile.Direction, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return newtile | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| @ -128,7 +152,7 @@ func NewTileTranswall(class []string) *Tile { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &Tile{ | 	return &Tile{ | ||||||
| 		Id:         '*', | 		Id:         't', | ||||||
| 		Class:      "transwall", | 		Class:      "transwall", | ||||||
| 		Solid:      false, | 		Solid:      false, | ||||||
| 		Renderable: true, | 		Renderable: true, | ||||||
| @ -139,6 +163,27 @@ func NewTileTranswall(class []string) *Tile { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func NewTileHiddenDoor(class []string) *Tile { | ||||||
|  | 	sprites := []*ebiten.Image{} | ||||||
|  | 	names := []string{} | ||||||
|  | 
 | ||||||
|  | 	for _, sprite := range class { | ||||||
|  | 		sprites = append(sprites, Assets[sprite]) | ||||||
|  | 		names = append(names, sprite) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return &Tile{ | ||||||
|  | 		Id:          'W', | ||||||
|  | 		Class:       "hiddendoor", | ||||||
|  | 		Solid:       false, | ||||||
|  | 		Renderable:  true, | ||||||
|  | 		Destroyable: true, | ||||||
|  | 		Tiles:       sprites, | ||||||
|  | 		Sprite:      sprites[0], // initially use the first | ||||||
|  | 		TileNames:   names, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // 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 | ||||||
| 
 | 
 | ||||||
| @ -164,7 +209,8 @@ type RawLevel struct { | |||||||
| func InitTiles() TileRegistry { | func InitTiles() TileRegistry { | ||||||
| 	return TileRegistry{ | 	return TileRegistry{ | ||||||
| 		' ': {Id: ' ', Class: "floor", Renderable: false}, | 		' ': {Id: ' ', Class: "floor", Renderable: false}, | ||||||
| 		'#': NewTileBlock("block-grey32"), | 		//'#': NewTileBlock("block-grey32"), | ||||||
|  | 		'#': NewTileBlock("block-greycolored"), | ||||||
| 		'B': NewTileBlock("block-orange-32"), | 		'B': NewTileBlock("block-orange-32"), | ||||||
| 		'S': NewTilePlayer(Primary), | 		'S': NewTilePlayer(Primary), | ||||||
| 		's': NewTilePlayer(Secondary), | 		's': NewTilePlayer(Secondary), | ||||||
| @ -183,6 +229,7 @@ func InitTiles() TileRegistry { | |||||||
| 			"particle-ring-6", | 			"particle-ring-6", | ||||||
| 		}), | 		}), | ||||||
| 		't': NewTileTranswall([]string{"transwall", "block-orange-32"}), | 		't': NewTileTranswall([]string{"transwall", "block-orange-32"}), | ||||||
|  | 		'W': NewTileHiddenDoor([]string{"block-greycolored", "block-greycolored-damaged"}), | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								assets/sprites/block-greycolored-damaged.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/sprites/block-greycolored-damaged.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 1.8 KiB | 
							
								
								
									
										
											BIN
										
									
								
								assets/sprites/block-greycolored.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								assets/sprites/block-greycolored.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 5.7 KiB | 
							
								
								
									
										29
									
								
								components/destroyable.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								components/destroyable.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | |||||||
|  | package components | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log" | ||||||
|  | 
 | ||||||
|  | 	"github.com/hajimehoshi/ebiten/v2" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // A hidden door in a wall. If the player bumps into it once, it shows | ||||||
|  | // damage and it vanishes the next time. | ||||||
|  | 
 | ||||||
|  | type Destroyable struct { | ||||||
|  | 	Activated bool | ||||||
|  | 	Sprites   []*ebiten.Image | ||||||
|  | 	Current   int // sprite index | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (door *Destroyable) GetNext() *ebiten.Image { | ||||||
|  | 	if len(door.Sprites) > door.Current { | ||||||
|  | 		door.Current++ | ||||||
|  | 		return door.Sprites[door.Current] | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	log.Fatalf("not enough sprites in transient tile, have %d sprites, index requested: %d", | ||||||
|  | 		len(door.Sprites), door.Current+1, | ||||||
|  | 	) | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
| @ -96,7 +96,6 @@ func (game *Game) Update() error { | |||||||
| 
 | 
 | ||||||
| 		if next == Play { | 		if next == Play { | ||||||
| 			// fresh setup of actual level every time we enter the play scene | 			// fresh setup of actual level every time we enter the play scene | ||||||
| 			//game.Scenes[Play] = NewLevelScene(game, gameobserver.CurrentLevel) |  | ||||||
| 			game.Scenes[Play].SetLevel(gameobserver.CurrentLevel) | 			game.Scenes[Play].SetLevel(gameobserver.CurrentLevel) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,6 +3,7 @@ package game | |||||||
| import ( | import ( | ||||||
| 	"image" | 	"image" | ||||||
| 	"log" | 	"log" | ||||||
|  | 	"log/slog" | ||||||
| 	"openquell/assets" | 	"openquell/assets" | ||||||
| 	"openquell/components" | 	"openquell/components" | ||||||
| 	"openquell/grid" | 	"openquell/grid" | ||||||
| @ -15,12 +16,16 @@ import ( | |||||||
| 	"github.com/mlange-42/arche/ecs" | 	"github.com/mlange-42/arche/ecs" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | type Map map[image.Point]*assets.Tile | ||||||
|  | type BackupMap map[image.Point]assets.Tile | ||||||
|  | 
 | ||||||
| type Level struct { | type Level struct { | ||||||
| 	Cellsize, Width, Height int | 	Cellsize, Width, Height int | ||||||
| 	World                   *ecs.World | 	World                   *ecs.World | ||||||
| 	Name                    string | 	Name                    string | ||||||
| 	Description             string | 	Description             string | ||||||
| 	Mapslice                map[image.Point]*assets.Tile | 	Mapslice                Map | ||||||
|  | 	BackupMapslice          Map | ||||||
| 	GridContainer           *grid.GridContainer | 	GridContainer           *grid.GridContainer | ||||||
| 	Systems                 []systems.System | 	Systems                 []systems.System | ||||||
| 	Grid                    *grid.Grid | 	Grid                    *grid.Grid | ||||||
| @ -45,8 +50,13 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level { | |||||||
| 
 | 
 | ||||||
| 	systemlist = append(systemlist, systems.NewTransientSystem(game.World, gridcontainer)) | 	systemlist = append(systemlist, systems.NewTransientSystem(game.World, gridcontainer)) | ||||||
| 
 | 
 | ||||||
|  | 	systemlist = append(systemlist, systems.NewDestroyableSystem(game.World, gridcontainer)) | ||||||
|  | 
 | ||||||
|  | 	mapslice, backupmap := LevelToSlice(game, plan, cellsize) | ||||||
|  | 
 | ||||||
| 	return &Level{ | 	return &Level{ | ||||||
| 		Mapslice:      LevelToSlice(game, plan, cellsize), | 		Mapslice:       mapslice, | ||||||
|  | 		BackupMapslice: backupmap, | ||||||
| 		Cellsize:       cellsize, | 		Cellsize:       cellsize, | ||||||
| 		World:          game.World, | 		World:          game.World, | ||||||
| 		Width:          game.ScreenWidth, | 		Width:          game.ScreenWidth, | ||||||
| @ -77,6 +87,12 @@ func (level *Level) Position2Point(position *components.Position) image.Point { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (level *Level) RestoreMap() { | ||||||
|  | 	for point, tile := range level.BackupMapslice { | ||||||
|  | 		level.Mapslice[point] = tile.Clone() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (level *Level) SetupGrid(game *Game) { | func (level *Level) SetupGrid(game *Game) { | ||||||
| 	// generic variant does not work here: | 	// generic variant does not work here: | ||||||
| 	// selector := generic.NewFilter1[components.Position]() | 	// selector := generic.NewFilter1[components.Position]() | ||||||
| @ -92,15 +108,20 @@ func (level *Level) SetupGrid(game *Game) { | |||||||
| 	playerobserver := observers.GetPlayerObserver(level.World) | 	playerobserver := observers.GetPlayerObserver(level.World) | ||||||
| 	playerobserver.RemoveEntities() | 	playerobserver.RemoveEntities() | ||||||
| 
 | 
 | ||||||
|  | 	// get rid of possibly manipulated map | ||||||
|  | 	level.RestoreMap() | ||||||
|  | 
 | ||||||
| 	// setup world | 	// setup world | ||||||
|  | 	slog.Debug("new grid?") | ||||||
| 	level.GridContainer.SetGrid( | 	level.GridContainer.SetGrid( | ||||||
| 		grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice)) | 		grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // parses a RawLevel and generates a mapslice from it, which is being used as grid | // parses a RawLevel and generates a mapslice from it, which is being used as grid | ||||||
| func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) map[image.Point]*assets.Tile { | func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) (Map, Map) { | ||||||
| 	size := game.ScreenWidth * game.ScreenHeight | 	size := game.ScreenWidth * game.ScreenHeight | ||||||
| 	mapslice := make(map[image.Point]*assets.Tile, size) | 	mapslice := make(Map, size) | ||||||
|  | 	backupmap := make(Map, size) | ||||||
| 
 | 
 | ||||||
| 	for y, line := range strings.Split(string(level.Data), "\n") { | 	for y, line := range strings.Split(string(level.Data), "\n") { | ||||||
| 		if len(line) != game.ScreenWidth/tilesize && y < game.ScreenHeight/tilesize { | 		if len(line) != game.ScreenWidth/tilesize && y < game.ScreenHeight/tilesize { | ||||||
| @ -113,9 +134,11 @@ func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) map[image.Po | |||||||
| 				log.Fatalf("unregistered tile type %c encountered", char) | 				log.Fatalf("unregistered tile type %c encountered", char) | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			mapslice[image.Point{x, y}] = assets.Tiles[byte(char)] | 			tile := assets.Tiles[byte(char)] | ||||||
|  | 			mapslice[image.Point{x, y}] = tile | ||||||
|  | 			backupmap[image.Point{x, y}] = tile.Clone() | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return mapslice | 	return mapslice, backupmap | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								grid/grid.go
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								grid/grid.go
									
									
									
									
									
								
							| @ -61,12 +61,18 @@ func NewGrid(world *ecs.World, | |||||||
| 		components.Renderable, | 		components.Renderable, | ||||||
| 		components.Transient](world) | 		components.Transient](world) | ||||||
| 
 | 
 | ||||||
|  | 	doormapper := generic.NewMap3[ | ||||||
|  | 		components.Position, | ||||||
|  | 		components.Renderable, | ||||||
|  | 		components.Destroyable](world) | ||||||
|  | 
 | ||||||
| 	var pos *components.Position | 	var pos *components.Position | ||||||
| 	var vel *components.Velocity | 	var vel *components.Velocity | ||||||
| 	var render *components.Renderable | 	var render *components.Renderable | ||||||
| 	var speed *components.Speed | 	var speed *components.Speed | ||||||
| 	var transient *components.Transient | 	var transient *components.Transient | ||||||
| 	var player *components.Player | 	var player *components.Player | ||||||
|  | 	var destroyable *components.Destroyable | ||||||
| 
 | 
 | ||||||
| 	playerobserver := observers.GetPlayerObserver(world) | 	playerobserver := observers.GetPlayerObserver(world) | ||||||
| 	obstacleobserver := observers.GetObstacleObserver(world) | 	obstacleobserver := observers.GetObstacleObserver(world) | ||||||
| @ -99,6 +105,10 @@ func NewGrid(world *ecs.World, | |||||||
| 				entity := transmapper.New() | 				entity := transmapper.New() | ||||||
| 				pos, render, transient = transmapper.Get(entity) | 				pos, render, transient = transmapper.Get(entity) | ||||||
| 				transient.Sprites = tile.TileNames | 				transient.Sprites = tile.TileNames | ||||||
|  | 			case tile.Destroyable: | ||||||
|  | 				entity := doormapper.New() | ||||||
|  | 				pos, render, destroyable = doormapper.Get(entity) | ||||||
|  | 				destroyable.Sprites = tile.Tiles | ||||||
| 			default: | 			default: | ||||||
| 				log.Fatalln("unsupported tile type encountered") | 				log.Fatalln("unsupported tile type encountered") | ||||||
| 			} | 			} | ||||||
| @ -143,7 +153,15 @@ func (grid *Grid) GetTile( | |||||||
| 	return tile | 	return tile | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (grid *Grid) SetTile(tile *assets.Tile, point image.Point) { | func (grid *Grid) RemoveTile(point image.Point) { | ||||||
|  | 	delete(grid.Map, point) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (grid *Grid) SetFloorTile(point image.Point) { | ||||||
|  | 	grid.Map[point] = assets.Tiles[' '] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (grid *Grid) SetSolidTile(tile *assets.Tile, point image.Point) { | ||||||
| 	solidmapper := generic.NewMap4[ | 	solidmapper := generic.NewMap4[ | ||||||
| 		components.Position, | 		components.Position, | ||||||
| 		components.Renderable, | 		components.Renderable, | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								src/block-grey-damage.xcf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/block-grey-damage.xcf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										108
									
								
								systems/destroyable_system.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								systems/destroyable_system.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | |||||||
|  | package systems | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"log/slog" | ||||||
|  | 	"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 DestroyableSystem struct { | ||||||
|  | 	World         *ecs.World | ||||||
|  | 	Selector      *generic.Filter3[Position, Renderable, Destroyable] | ||||||
|  | 	GridContainer *grid.GridContainer | ||||||
|  | 	SolidMapper   generic.Map4[ // needed for replacement | ||||||
|  | 		components.Position, | ||||||
|  | 		components.Renderable, | ||||||
|  | 		components.Tilish, | ||||||
|  | 		components.Solid] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | type DoorToRemove struct { | ||||||
|  | 	Entity   ecs.Entity | ||||||
|  | 	Position *components.Position | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func NewDestroyableSystem(world *ecs.World, gridcontainer *grid.GridContainer) System { | ||||||
|  | 	solidmapper := generic.NewMap4[ | ||||||
|  | 		components.Position, | ||||||
|  | 		components.Renderable, | ||||||
|  | 		components.Tilish, | ||||||
|  | 		components.Solid](world) | ||||||
|  | 
 | ||||||
|  | 	system := &DestroyableSystem{ | ||||||
|  | 		Selector:      generic.NewFilter3[Position, Renderable, Destroyable](), | ||||||
|  | 		World:         world, | ||||||
|  | 		GridContainer: gridcontainer, | ||||||
|  | 		SolidMapper:   solidmapper, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return system | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (system *DestroyableSystem) Update() error { | ||||||
|  | 	playerobserver := observers.GetPlayerObserver(system.World) | ||||||
|  | 	posID := ecs.ComponentID[components.Position](system.World) | ||||||
|  | 	veloID := ecs.ComponentID[components.Velocity](system.World) | ||||||
|  | 
 | ||||||
|  | 	query := system.Selector.Query(system.World) | ||||||
|  | 
 | ||||||
|  | 	EntitiestoRemove := []*DoorToRemove{} | ||||||
|  | 
 | ||||||
|  | 	for query.Next() { | ||||||
|  | 		doorposition, renderable, door := query.Get() | ||||||
|  | 
 | ||||||
|  | 		for player := range playerobserver.Entities { | ||||||
|  | 			playerposition := (*Position)(system.World.Get(player, posID)) | ||||||
|  | 			playervelocity := (*Velocity)(system.World.Get(player, veloID)) | ||||||
|  | 
 | ||||||
|  | 			ok, newpos := doorposition.Intersects(playerposition, playervelocity) | ||||||
|  | 			if ok { | ||||||
|  | 				// player bumped into hidden wall, activate it, snap in player | ||||||
|  | 				slog.Debug("bump not die", "originalpos", playerposition) | ||||||
|  | 				playervelocity.Change(Stop) | ||||||
|  | 				playerposition.Set(newpos) | ||||||
|  | 
 | ||||||
|  | 				if door.Activated { | ||||||
|  | 					// player bumps into the door a second time, now hide it | ||||||
|  | 					EntitiestoRemove = append(EntitiestoRemove, | ||||||
|  | 						&DoorToRemove{Entity: query.Entity(), Position: doorposition}) | ||||||
|  | 				} else { | ||||||
|  | 					slog.Debug("activating destroyable", "doorpos", doorposition) | ||||||
|  | 					door.Activated = true | ||||||
|  | 					renderable.Image = door.GetNext() | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, door := range EntitiestoRemove { | ||||||
|  | 		slog.Debug("hiding destroyable", "doorpos", door.Position.Point()) | ||||||
|  | 
 | ||||||
|  | 		// remove door entity | ||||||
|  | 		system.World.RemoveEntity(door.Entity) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (system *DestroyableSystem) Draw(screen *ebiten.Image) { | ||||||
|  | 	// write transients (these are no tiles!) | ||||||
|  | 	op := &ebiten.DrawImageOptions{} | ||||||
|  | 	query := system.Selector.Query(system.World) | ||||||
|  | 
 | ||||||
|  | 	for query.Next() { | ||||||
|  | 		pos, render, _ := query.Get() | ||||||
|  | 
 | ||||||
|  | 		op.GeoM.Reset() | ||||||
|  | 		op.GeoM.Translate(float64(pos.X), float64(pos.Y)) | ||||||
|  | 		screen.DrawImage(render.Image, op) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -3,6 +3,7 @@ package systems | |||||||
| import ( | import ( | ||||||
| 	"image" | 	"image" | ||||||
| 	"image/draw" | 	"image/draw" | ||||||
|  | 	"log/slog" | ||||||
| 	. "openquell/components" | 	. "openquell/components" | ||||||
| 
 | 
 | ||||||
| 	"github.com/hajimehoshi/ebiten/v2" | 	"github.com/hajimehoshi/ebiten/v2" | ||||||
| @ -44,8 +45,8 @@ func (system *GridSystem) Update() error { return nil } | |||||||
| func (system *GridSystem) Draw(screen *ebiten.Image) { | func (system *GridSystem) Draw(screen *ebiten.Image) { | ||||||
| 	op := &ebiten.DrawImageOptions{} | 	op := &ebiten.DrawImageOptions{} | ||||||
| 	query := system.Selector.Query(system.World) | 	query := system.Selector.Query(system.World) | ||||||
| 
 |  | ||||||
| 	if !system.UseCache || query.Count() != system.Count { | 	if !system.UseCache || query.Count() != system.Count { | ||||||
|  | 		slog.Debug("entity number changes", "old", system.Count, "current", query.Count()) | ||||||
| 		// map not cached or cacheable, write it to the cache | 		// map not cached or cacheable, write it to the cache | ||||||
| 		draw.Draw(system.Cache, system.Background.Bounds(), system.Background, image.ZP, draw.Src) | 		draw.Draw(system.Cache, system.Background.Bounds(), system.Background, image.ZP, draw.Src) | ||||||
| 
 | 
 | ||||||
| @ -54,6 +55,7 @@ func (system *GridSystem) Draw(screen *ebiten.Image) { | |||||||
| 		for query.Next() { | 		for query.Next() { | ||||||
| 			sprite, pos, _ := query.Get() | 			sprite, pos, _ := query.Get() | ||||||
| 
 | 
 | ||||||
|  | 			//slog.Debug("drawing sprite", "sprite", sprite, "point", pos.Point()) | ||||||
| 			draw.Draw( | 			draw.Draw( | ||||||
| 				system.Cache, | 				system.Cache, | ||||||
| 				image.Rect(pos.X, pos.Y, pos.X+pos.Cellsize, pos.Y+pos.Cellsize), | 				image.Rect(pos.X, pos.Y, pos.X+pos.Cellsize, pos.Y+pos.Cellsize), | ||||||
|  | |||||||
| @ -95,7 +95,7 @@ func (system *TransientSystem) Update() error { | |||||||
| 
 | 
 | ||||||
| 		//  also  setup the  grid  tile  with  a  new solid,  so  that | 		//  also  setup the  grid  tile  with  a  new solid,  so  that | ||||||
| 		// collision detection works | 		// collision detection works | ||||||
| 		system.GridContainer.Grid.SetTile( | 		system.GridContainer.Grid.SetSolidTile( | ||||||
| 			assets.NewTileBlock(convertible.NewSprite), | 			assets.NewTileBlock(convertible.NewSprite), | ||||||
| 			convertible.Position.Point(), | 			convertible.Position.Point(), | ||||||
| 		) | 		) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user