| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | package grid | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"image" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"openquell/assets" | 
					
						
							|  |  |  | 	"openquell/components" | 
					
						
							| 
									
										
										
										
											2024-02-11 14:24:30 +01:00
										 |  |  | 	"openquell/config" | 
					
						
							| 
									
										
										
										
											2024-02-11 13:00:56 +01:00
										 |  |  | 	"openquell/observers" | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 	"github.com/mlange-42/arche/ecs" | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	"github.com/mlange-42/arche/generic" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Grid struct { | 
					
						
							| 
									
										
										
										
											2024-02-23 18:47:15 +01:00
										 |  |  | 	World          *ecs.World | 
					
						
							|  |  |  | 	Width          int | 
					
						
							|  |  |  | 	Height         int | 
					
						
							|  |  |  | 	Size           int | 
					
						
							|  |  |  | 	Tilesize       int | 
					
						
							|  |  |  | 	TilesX, TilesY int | 
					
						
							|  |  |  | 	Map            map[image.Point]*assets.Tile | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FIXME: put component addition into extra callable function, to be called | 
					
						
							|  |  |  | // by game.go in a level-loop. Also remove components of previous level | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | func NewGrid(world *ecs.World, | 
					
						
							|  |  |  | 	tilesize, width, height int, mapslice map[image.Point]*assets.Tile) *Grid { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	// we use this to turn  our tiles into iterable entities, used for | 
					
						
							|  |  |  | 	// collision detection, transformation and other things | 
					
						
							| 
									
										
										
										
											2024-02-11 14:24:30 +01:00
										 |  |  | 	playermapper := generic.NewMap5[ | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Velocity, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							| 
									
										
										
										
											2024-02-11 14:24:30 +01:00
										 |  |  | 		components.Speed, | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 		components.Player](world) | 
					
						
							| 
									
										
										
										
											2024-02-07 18:01:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	solidmapper := generic.NewMap4[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Tilish, | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 		components.Solid](world) | 
					
						
							| 
									
										
										
										
											2024-02-07 18:01:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 	emptymapper := generic.NewMap2[components.Position, components.Tilish](world) | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-07 18:01:58 +01:00
										 |  |  | 	colmapper := generic.NewMap3[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 		components.Collectible](world) | 
					
						
							| 
									
										
										
										
											2024-02-07 18:01:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 	obsmapper := generic.NewMap5[ | 
					
						
							| 
									
										
										
										
											2024-02-19 19:05:48 +01:00
										 |  |  | 		components.Position, | 
					
						
							| 
									
										
										
										
											2024-02-20 18:47:32 +01:00
										 |  |  | 		components.Velocity, | 
					
						
							| 
									
										
										
										
											2024-02-19 19:05:48 +01:00
										 |  |  | 		components.Renderable, | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 		components.Speed, | 
					
						
							| 
									
										
										
										
											2024-02-19 19:05:48 +01:00
										 |  |  | 		components.Obstacle](world) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 	transmapper := generic.NewMap3[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Transient](world) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-25 14:05:44 +01:00
										 |  |  | 	doormapper := generic.NewMap3[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Destroyable](world) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	var pos *components.Position | 
					
						
							| 
									
										
										
										
											2024-02-20 18:47:32 +01:00
										 |  |  | 	var vel *components.Velocity | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	var render *components.Renderable | 
					
						
							| 
									
										
										
										
											2024-02-11 14:24:30 +01:00
										 |  |  | 	var speed *components.Speed | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 	var transient *components.Transient | 
					
						
							| 
									
										
										
										
											2024-02-22 19:40:49 +01:00
										 |  |  | 	var player *components.Player | 
					
						
							| 
									
										
										
										
											2024-02-25 14:05:44 +01:00
										 |  |  | 	var destroyable *components.Destroyable | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-11 13:00:56 +01:00
										 |  |  | 	playerobserver := observers.GetPlayerObserver(world) | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 	obstacleobserver := observers.GetObstacleObserver(world) | 
					
						
							| 
									
										
										
										
											2024-02-11 13:00:56 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	for point, tile := range mapslice { | 
					
						
							|  |  |  | 		switch tile.Renderable { | 
					
						
							|  |  |  | 		case true: | 
					
						
							|  |  |  | 			switch { | 
					
						
							|  |  |  | 			case tile.Solid: | 
					
						
							|  |  |  | 				entity := solidmapper.New() | 
					
						
							|  |  |  | 				pos, render, _, _ = solidmapper.Get(entity) | 
					
						
							|  |  |  | 			case tile.Player: | 
					
						
							|  |  |  | 				entity := playermapper.New() | 
					
						
							| 
									
										
										
										
											2024-02-22 19:40:49 +01:00
										 |  |  | 				pos, _, render, speed, player = playermapper.Get(entity) | 
					
						
							| 
									
										
										
										
											2024-02-11 13:00:56 +01:00
										 |  |  | 				playerobserver.AddEntity(entity) | 
					
						
							| 
									
										
										
										
											2024-02-11 14:24:30 +01:00
										 |  |  | 				speed.Value = config.PLAYERSPEED | 
					
						
							| 
									
										
										
										
											2024-02-22 19:40:49 +01:00
										 |  |  | 				player.IsPrimary = tile.IsPrimary | 
					
						
							|  |  |  | 				player.Sprites = tile.Tiles | 
					
						
							| 
									
										
										
										
											2024-02-07 18:01:58 +01:00
										 |  |  | 			case tile.Collectible: | 
					
						
							|  |  |  | 				entity := colmapper.New() | 
					
						
							|  |  |  | 				pos, render, _ = colmapper.Get(entity) | 
					
						
							| 
									
										
										
										
											2024-02-19 19:05:48 +01:00
										 |  |  | 			case tile.Obstacle: | 
					
						
							|  |  |  | 				entity := obsmapper.New() | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 				pos, vel, render, speed, _ = obsmapper.Get(entity) | 
					
						
							| 
									
										
										
										
											2024-02-20 18:47:32 +01:00
										 |  |  | 				vel.Direction = tile.Direction | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 				vel.PointingAt = tile.Direction | 
					
						
							|  |  |  | 				speed.Value = config.PLAYERSPEED | 
					
						
							|  |  |  | 				obstacleobserver.AddEntity(entity) | 
					
						
							|  |  |  | 			case tile.Transient: | 
					
						
							|  |  |  | 				entity := transmapper.New() | 
					
						
							|  |  |  | 				pos, render, transient = transmapper.Get(entity) | 
					
						
							|  |  |  | 				transient.Sprites = tile.TileNames | 
					
						
							| 
									
										
										
										
											2024-02-25 14:05:44 +01:00
										 |  |  | 			case tile.Destroyable: | 
					
						
							|  |  |  | 				entity := doormapper.New() | 
					
						
							|  |  |  | 				pos, render, destroyable = doormapper.Get(entity) | 
					
						
							|  |  |  | 				destroyable.Sprites = tile.Tiles | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 			default: | 
					
						
							|  |  |  | 				log.Fatalln("unsupported tile type encountered") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			render.Image = tile.Sprite | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			// empty  cell, this is  where the player[s]  move. No | 
					
						
							|  |  |  | 			// sprite required since  every level has a background | 
					
						
							|  |  |  | 			// image. | 
					
						
							|  |  |  | 			entity := emptymapper.New() | 
					
						
							|  |  |  | 			pos, _ = emptymapper.Get(entity) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// however, every tile has a position | 
					
						
							|  |  |  | 		pos.Update(point.X*tilesize, point.Y*tilesize, tilesize) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return &Grid{ | 
					
						
							|  |  |  | 		Size:     len(mapslice), | 
					
						
							|  |  |  | 		Tilesize: tilesize, | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 		Width:    width, | 
					
						
							|  |  |  | 		Height:   height, | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 		Map:      mapslice, | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 		World:    world, | 
					
						
							| 
									
										
										
										
											2024-02-23 18:47:15 +01:00
										 |  |  | 		TilesX:   width / tilesize, | 
					
						
							|  |  |  | 		TilesY:   height / tilesize, | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | // return the tile the moving object would end up on if indeed moving | 
					
						
							|  |  |  | func (grid *Grid) GetTile( | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	position *components.Position, | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 	velocity *components.Velocity) *assets.Tile { | 
					
						
							| 
									
										
										
										
											2024-02-06 19:02:25 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 	newpoint := image.Point{ | 
					
						
							|  |  |  | 		int(position.X+velocity.Data.X) / grid.Tilesize, | 
					
						
							|  |  |  | 		int(position.Y+velocity.Data.Y) / grid.Tilesize, | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-10 19:45:06 +01:00
										 |  |  | 	tile := grid.Map[newpoint] | 
					
						
							|  |  |  | 	return tile | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-25 14:05:44 +01:00
										 |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2024-02-22 14:33:01 +01:00
										 |  |  | 	solidmapper := generic.NewMap4[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Tilish, | 
					
						
							|  |  |  | 		components.Solid](grid.World) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	grid.Map[point] = tile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	entity := solidmapper.New() | 
					
						
							|  |  |  | 	pos, render, _, _ := solidmapper.Get(entity) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	render.Image = tile.Sprite | 
					
						
							|  |  |  | 	pos.Update(point.X*grid.Tilesize, point.Y*grid.Tilesize, grid.Tilesize) | 
					
						
							|  |  |  | } |