diff options
| -rw-r--r-- | entity.go | 63 | ||||
| -rw-r--r-- | main.go | 51 | ||||
| -rw-r--r-- | spawn.go | 22 |
3 files changed, 81 insertions, 55 deletions
@@ -3,6 +3,7 @@ package main import ( "age_of_empires/ecs" "age_of_empires/physics" + "image/color" "github.com/hajimehoshi/ebiten/v2" ) @@ -25,3 +26,65 @@ func (e Entity) Bounds() physics.Rectangle { Max: e.Position.Value.Add(e.Image.Value.Bounds().Size()), } } + +type EntityBuilder Entity + +func (b EntityBuilder) WithPosition(position physics.Point) EntityBuilder { + b.Position = ecs.C(position) + return b +} + +func (b EntityBuilder) WithImage(image *ebiten.Image) EntityBuilder { + b.Image = ecs.C(image) + return b +} + +var red = color.RGBA{0xff, 0x00, 0x00, 0xff} + +func (b EntityBuilder) WithSelection(haloKind string) EntityBuilder { + b.Selection = ecs.C(Selection{ + IsSelected: false, + Halo: nil, + }) + switch haloKind { + case "round": + b.Selection.Value.Halo = NewStrokeCircleImage(110, SELECTION_HALO_WIDTH, red) + case "square": + b.Selection.Value.Halo = NewStrokeRectangleImage(physics.Point{X: 110, Y: 110}, SELECTION_HALO_WIDTH, red) + } + return b +} + +func (b EntityBuilder) WithResourceStorage() EntityBuilder { + b.ResourceStorage = ecs.C(ResourceStorage{}) + return b +} + +func (b EntityBuilder) WithResourceSource(amount int) EntityBuilder { + b.ResourceSource = ecs.C(ResourceSource{Remaining: amount}) + return b +} + +func (b EntityBuilder) WithSpawn(spawn Spawn) EntityBuilder { + b.Spawn = ecs.C(spawn) + return b +} + +func (b EntityBuilder) WithMove() EntityBuilder { + b.Move = ecs.C(physics.Move{IsActive: false}) + return b +} + +func (b EntityBuilder) WithOrder() EntityBuilder { + b.Order.IsEnabled = true + return b +} + +func (b EntityBuilder) WithResourceGatherer(maxCapacity int) EntityBuilder { + b.ResourceGatherer = ecs.C(ResourceGatherer{MaxCapacity: maxCapacity}) + return b +} + +func (b EntityBuilder) Build() Entity { + return Entity(b) +} @@ -42,8 +42,7 @@ type Game struct { Selection GlobalSelection ResourceAmount int FaceSource *text.GoTextFaceSource - personImage *ebiten.Image - personSelectionHalo *ebiten.Image + UnitBuilder EntityBuilder } func DrawMove(screen *ebiten.Image, e *Entity) { @@ -209,7 +208,7 @@ func main() { f, err := os.Create("cpu.prof") kcore.Expect(err, "could not create CPU profile") defer f.Close() - kcore.Expect(pprof.StartCPUProfile(f), "could not start CPU profile") + kcore.Expect(pprof.StartCPUProfile(f), "could not start CPU profile") defer pprof.StopCPUProfile() } } @@ -227,47 +226,19 @@ func main() { s, err := text.NewGoTextFaceSource(bytes.NewReader(goregular.TTF)) kcore.Expect(err, "failed to create font source") game.FaceSource = s - ironImage := NewFilledRectangleImage(physics.Point{X: 100, Y: 100}, color.RGBA{0x80, 0x80, 0x80, 0xff}) - ironSelectionHalo := NewStrokeRectangleImage(physics.Point{X: 110, Y: 110}, SELECTION_HALO_WIDTH, color.RGBA{0xff, 0x00, 0x00, 0xff}) - ironMine := Entity{ - Position: ecs.C(physics.Point{X: 1000, Y: 1000}), - Image: ecs.C(ironImage), - ResourceSource: ecs.C(ResourceSource{Remaining: 1000}), - Selection: ecs.C(Selection{IsSelected: false, Halo: ironSelectionHalo}), - } + ironMine := EntityBuilder{}.WithPosition(physics.Point{X: 1000, Y: 1000}).WithImage(NewFilledRectangleImage(physics.Point{X: 100, Y: 100}, color.RGBA{0x80, 0x80, 0x80, 0xff})).WithResourceSource(1000).WithSelection("square").Build() game.Entities = append(game.Entities, &ironMine) - townCenterImage := NewFilledRectangleImage(physics.Point{X: 100, Y: 100}, color.RGBA{0x00, 0x00, 0xff, 0xff}) - townCenter := Entity{ - Position: ecs.C(physics.Point{X: 1000, Y: 2000}), - Image: ecs.C(townCenterImage), - ResourceStorage: ecs.C(ResourceStorage{}), - Selection: ecs.C(Selection{IsSelected: false, Halo: NewStrokeRectangleImage(physics.Point{X: 110, Y: 110}, SELECTION_HALO_WIDTH, color.RGBA{0xff, 0x00, 0x00, 0xff})}), - Spawn: ecs.C(NewSpawn(50, 5*time.Second)), - } + townCenter := EntityBuilder{}.WithPosition(physics.Point{X: 1000, Y: 2000}).WithImage(NewFilledRectangleImage(physics.Point{X: 100, Y: 100}, color.RGBA{0x0, 0x0, 0xff, 0xff})).WithResourceStorage().WithSelection("square").WithSpawn(NewSpawn(50, 5*time.Second)).Build() game.Entities = append(game.Entities, &townCenter) - var order Order - game.personImage = NewFilledCircleImage(100, color.RGBA{0xff, 0xff, 0xff, 0xff}) - game.personSelectionHalo = NewStrokeCircleImage(110, SELECTION_HALO_WIDTH, color.RGBA{0xff, 0x00, 0x00, 0xff}) spawnPosition, _ := game.Closest(townCenter.Position.Value, physics.AdjacentPoints(townCenter.Position.Value)) - person1 := Entity{ - Position: ecs.C(spawnPosition), - Image: ecs.C(game.personImage), - Selection: ecs.C(Selection{IsSelected: false, Halo: game.personSelectionHalo}), - Move: ecs.C(physics.Move{IsActive: false}), - Order: ecs.C(order), - ResourceGatherer: ecs.C(ResourceGatherer{MaxCapacity: 15}), - } - game.Entities = append(game.Entities, &person1) - spawnPosition, _ = game.Closest(townCenter.Position.Value, physics.AdjacentPoints(townCenter.Position.Value)) - person2 := Entity{ - Position: ecs.C(spawnPosition), - Image: ecs.C(game.personImage), - Selection: ecs.C(Selection{IsSelected: false, Halo: game.personSelectionHalo}), - Move: ecs.C(physics.Move{IsActive: false}), - Order: ecs.C(order), - ResourceGatherer: ecs.C(ResourceGatherer{MaxCapacity: 15}), + game.UnitBuilder = EntityBuilder{}.WithImage(NewFilledCircleImage(100, color.White)).WithSelection("round").WithMove().WithOrder().WithResourceGatherer(15) + for i := 0; i < 2; i++ { + spawnPosition, _ = game.Closest(townCenter.Position.Value, physics.AdjacentPoints(townCenter.Position.Value)) + person := game.UnitBuilder.Build() + person.Position = ecs.C(spawnPosition) + game.Entities = append(game.Entities, &person) } - game.Entities = append(game.Entities, &person2) game.CurrentAction = Selecting + ebiten.SetRunnableOnUnfocused(true) kcore.Expect(ebiten.RunGame(game), "failed to run game") } @@ -11,16 +11,16 @@ type spawnRequest struct { } type Spawn struct { - UnitResourceCost int + UnitResourceCost int UnitSpawnDuration time.Duration - Requests []spawnRequest + Requests []spawnRequest } func NewSpawn(unitResourceCost int, unitSpawnDuration time.Duration) Spawn { return Spawn{ - UnitResourceCost: unitResourceCost, + UnitResourceCost: unitResourceCost, UnitSpawnDuration: unitSpawnDuration, - Requests: make([]spawnRequest, 0), + Requests: make([]spawnRequest, 0), } } @@ -32,7 +32,7 @@ func (spawn *Spawn) AddRequest(g *Game) { spawn.Requests = append(spawn.Requests, spawnRequest{start: time.Now()}) } -func UpdateSpawn(g *Game,spawn *ecs.Component[Spawn], position ecs.Component[physics.Point]) { +func UpdateSpawn(g *Game, spawn *ecs.Component[Spawn], position ecs.Component[physics.Point]) { if !spawn.IsEnabled || !position.IsEnabled { return } @@ -40,17 +40,9 @@ func UpdateSpawn(g *Game,spawn *ecs.Component[Spawn], position ecs.Component[phy if len(spawn.Value.Requests) == 0 || now.Sub(spawn.Value.Requests[0].start) < time.Duration(spawn.Value.UnitSpawnDuration) { return } - // TODO: builder - var order Order spawnPosition, _ := g.Closest(position.Value, physics.AdjacentPoints(position.Value)) - unit := Entity{ - Position: ecs.C(spawnPosition), - Image: ecs.C(g.personImage), - Selection: ecs.C(Selection{IsSelected: false, Halo: g.personSelectionHalo}), - Move: ecs.C(physics.Move{IsActive: false}), - Order: ecs.C(order), - ResourceGatherer: ecs.C(ResourceGatherer{MaxCapacity: 15}), - } + unit := g.UnitBuilder.Build() + unit.Position = ecs.C(spawnPosition) g.Entities = append(g.Entities, &unit) spawn.Value.Requests = spawn.Value.Requests[1:] if len(spawn.Value.Requests) > 0 { |
