| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | package game | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"image" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"openquell/assets" | 
					
						
							|  |  |  | 	"openquell/components" | 
					
						
							|  |  |  | 	. "openquell/config" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 19:02:25 +01:00
										 |  |  | 	"github.com/alecthomas/repr" | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 	"github.com/mlange-42/arche/generic" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Grid struct { | 
					
						
							|  |  |  | 	Width    int | 
					
						
							|  |  |  | 	Height   int | 
					
						
							|  |  |  | 	Size     int | 
					
						
							|  |  |  | 	Tilesize int | 
					
						
							|  |  |  | 	TilesX   int | 
					
						
							|  |  |  | 	TilesY   int | 
					
						
							|  |  |  | 	Map      map[image.Point]*assets.Tile | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // FIXME: put component addition into extra callable function, to be called | 
					
						
							|  |  |  | // by game.go in a level-loop. Also remove components of previous level | 
					
						
							|  |  |  | func NewGrid(game *Game, tilesize int, mapslice map[image.Point]*assets.Tile) *Grid { | 
					
						
							|  |  |  | 	// we use this to turn  our tiles into iterable entities, used for | 
					
						
							|  |  |  | 	// collision detection, transformation and other things | 
					
						
							|  |  |  | 	playermapper := generic.NewMap4[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Velocity, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Player](game.World) | 
					
						
							|  |  |  | 	solidmapper := generic.NewMap4[ | 
					
						
							|  |  |  | 		components.Position, | 
					
						
							|  |  |  | 		components.Renderable, | 
					
						
							|  |  |  | 		components.Tilish, | 
					
						
							|  |  |  | 		components.Solid](game.World) | 
					
						
							|  |  |  | 	emptymapper := generic.NewMap2[components.Position, components.Tilish](game.World) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var pos *components.Position | 
					
						
							|  |  |  | 	var render *components.Renderable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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() | 
					
						
							|  |  |  | 				pos, _, render, _ = playermapper.Get(entity) | 
					
						
							|  |  |  | 				fmt.Printf("player start pos: %d,%d\n", point.X*tilesize, point.Y*tilesize) | 
					
						
							|  |  |  | 			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, | 
					
						
							|  |  |  | 		Width:    game.ScreenWidth, | 
					
						
							|  |  |  | 		Height:   game.ScreenHeight, | 
					
						
							|  |  |  | 		TilesX:   game.ScreenWidth / tilesize, | 
					
						
							|  |  |  | 		TilesY:   game.ScreenHeight / tilesize, | 
					
						
							|  |  |  | 		Map:      mapslice, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (grid *Grid) GetSolidNeighborPosition( | 
					
						
							|  |  |  | 	position *components.Position, | 
					
						
							|  |  |  | 	velocity *components.Velocity, | 
					
						
							|  |  |  | 	solid bool) (bool, *components.Position) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if !solid { | 
					
						
							|  |  |  | 		return false, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// set to true,  ifwe are already on the last  tile in the current | 
					
						
							|  |  |  | 	// direction, i.e. on the edge of the grid | 
					
						
							|  |  |  | 	edge := true | 
					
						
							|  |  |  | 	neighborpos := position.Point() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch velocity.Direction { | 
					
						
							|  |  |  | 	case East: | 
					
						
							|  |  |  | 		if neighborpos.X < grid.TilesX { | 
					
						
							|  |  |  | 			neighborpos.X++ | 
					
						
							|  |  |  | 			edge = false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case West: | 
					
						
							|  |  |  | 		if neighborpos.X > 0 { | 
					
						
							|  |  |  | 			neighborpos.X-- | 
					
						
							|  |  |  | 			edge = false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case South: | 
					
						
							|  |  |  | 		if neighborpos.Y < grid.TilesY { | 
					
						
							|  |  |  | 			neighborpos.Y++ | 
					
						
							|  |  |  | 			edge = false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	case North: | 
					
						
							|  |  |  | 		if neighborpos.Y > 0 { | 
					
						
							|  |  |  | 			neighborpos.Y-- | 
					
						
							|  |  |  | 			edge = false | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newpos := components.NewPosition(neighborpos, grid.Tilesize) | 
					
						
							| 
									
										
										
										
											2024-02-06 19:02:25 +01:00
										 |  |  | 	repr.Println(newpos) | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-06 19:02:25 +01:00
										 |  |  | 	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) | 
					
						
							| 
									
										
										
										
											2024-02-06 15:26:20 +01:00
										 |  |  | 		return true, newpos | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false, nil | 
					
						
							|  |  |  | } |