/* CreateMap creates a new map region entity and returns it */ func CreateMap(db *engine.EntityDB) engine.Entity { retval := db.New("map") // Register a chunk generator on the map emap := db.Get(retval, "map").(*base.EntityMap) emap.RegisterChunkGenerator(NewStoneFieldGenerator(db, .05)) return retval }
func RegisterTypes(db *engine.EntityDB) { db.Register("ai", CreateAI, CloneAI) db.Register("art", CreateArt, CloneArt) db.Register("position", CreatePosition, ClonePosition) db.Register("movement", CreateMovement, CloneMovement) db.Register("map", CreateEntityMap, CloneEntityMap) db.Register("health", CreateHealth, CloneHealth) db.Register("attack", CreateAttack, CloneAttack) }
/* RenderMapAt draws a portion of the map centered at the given entity */ func RenderMapAt(db *engine.EntityDB, eid engine.Entity) { width, height := termbox.Size() pos := db.Get(eid, "position").(*base.Position) emap := db.Get(pos.R, "map").(*base.EntityMap) for y := 0; y < height; y++ { py := pos.Y + int64(y-height/2) for x := 0; x < width; x++ { px := pos.X + int64(x-width/2) // Search for the highest entity on the map in the same general layer // as the passed entity that can be drawn. This will need to be more // formal in the future (not hardcoded knowing the player is on z level // 1, tiles are on z level 0, and the bat at z level 2) topArt := &base.Art{} for i := int64(1); i >= -1; i-- { entity := emap.Get(px, py, pos.Z+i) if db.Has(entity, "art") { topArt = db.Get(entity, "art").(*base.Art) break } } // And draw the found art, which will be an empty black square // if nothing was found Draw(x, height-1-y, topArt.Symbol, topArt.Fg, topArt.Bg) } } termbox.Flush() }
func NewStoneFieldGenerator(db *engine.EntityDB, fill float64) *StoneFieldGenerator { grass := db.New() db.Set(grass, "art", base.NewArt('.', 0, 1, 0, 0, 0, 0)) stone := db.New() db.Set(stone, "art", base.NewArt('#', .7, .7, .7, 0, 0, 0)) return &StoneFieldGenerator{stone: stone, grass: grass, fill: fill} }
func (ai *FollowAI) Act(db *engine.EntityDB, eid engine.Entity) { epos := db.Get(eid, "position").(*base.Position) tpos := db.Get(ai.Target, "position").(*base.Position) dx, dy := int64(0), int64(0) if epos.X > tpos.X+1 || epos.X < tpos.X-1 { dx = int64(math.Copysign(1, float64(tpos.X-epos.X))) } if epos.Y > tpos.Y+1 || epos.Y < tpos.Y-1 { dy = int64(math.Copysign(1, float64(tpos.Y-epos.Y))) } // Since the bat is situated at z-level 2, it will never find // a wall with art symbol '#' at one level below, so this move // function still allows the bat to fly over stones! ^_^ // Hence the "+1" for the z; so the bat stays one level above // the player. base.HelperMove(db, eid, dx, dy, tpos.Z-epos.Z+1) }
/* HelperPlace puts an entity on to the map at a particular position */ func HelperPlace(db *engine.EntityDB, eid engine.Entity, r engine.Entity, x, y, z int64) { if !db.Has(r, "map") { return } db.Get(r, "map").(*EntityMap).Set(x, y, z, eid) pos := db.Create(eid, "position").(*Position) pos.R, pos.X, pos.Y, pos.Z = r, x, y, z }
/* SystemMove applies makes every entity with movement try to move in the map */ func SystemMove(db *engine.EntityDB) { for _, eid := range db.Search("movement", "position") { pos := db.Get(eid, "position").(*Position) mov := db.Get(eid, "movement").(*Movement) emap := db.Get(pos.R, "map").(*EntityMap) // Prevent entities from moving on top of each other, temporarily if emap.Get(pos.X+mov.Dx, pos.Y+mov.Dy, pos.Z+mov.Dz) != 0 { continue } // Move and update the map emap.Set(pos.X, pos.Y, pos.Z, 0) pos.X += mov.Dx pos.Y += mov.Dy pos.Z += mov.Dz emap.Set(pos.X, pos.Y, pos.Z, eid) } }
/* HelperMove validates an entity's attempt to move and sets the entity's movement component appropriately. Returns true if the entity could move */ func HelperMove(db *engine.EntityDB, eid engine.Entity, dx, dy, dz int64) bool { if !db.Has(eid, "movement", "position") { return false } pos := db.Get(eid, "position").(*Position) emap := db.Get(pos.R, "map").(*EntityMap) mov := db.Get(eid, "movement").(*Movement) // TODO: fix layer system and make it real. // Check the entities in the layer beneath the move target // to see if the entity is a wall (with art symbol '#') target := emap.Get(pos.X+dx, pos.Y+dy, pos.Z+dz-1) if db.Has(target, "art") && db.Get(target, "art").(*Art).Symbol == '#' { mov.Dx = 0 mov.Dy = 0 mov.Dz = 0 return false } // Move can be done! mov.Dx = dx mov.Dy = dy mov.Dz = dz return true }
/* SystemAct allows each entity with an AI to attempt to act */ func SystemAct(db *engine.EntityDB) { for _, eid := range db.Search("ai", "position") { ai := db.Get(eid, "ai").(*AI) ai.Controller.Act(db, eid) } }