From 55a106e84e09bbb8e2ea8de8c5728104b90bf9d5 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Sat, 22 Jan 2022 16:21:02 -0800 Subject: [PATCH] Add bulldozer sound effect --- README.md | 1 - asset/asset.go | 18 +- asset/map/power_solar.tmx | 22 +++ asset/sound/bulldozer/LICENSE | 6 + asset/sound/bulldozer/bulldozer.ogg | Bin 0 -> 73309 bytes asset/sound/select/LICENSE | 2 +- game/game.go | 28 +++- go.mod | 2 +- go.sum | 4 +- main.go | 5 - system/input_move.go | 222 +++++++++++++++++++------ system/populate.go | 99 +++++------ system/powerscan.go | 20 +-- system/renderhud.go | 248 ++++++++++++++++++++++------ world/help.go | 20 +++ world/powermap.go | 10 +- world/structure.go | 2 + world/world.go | 92 +++++++++-- 18 files changed, 591 insertions(+), 210 deletions(-) create mode 100644 asset/map/power_solar.tmx create mode 100644 asset/sound/bulldozer/LICENSE create mode 100644 asset/sound/bulldozer/bulldozer.ogg create mode 100644 world/help.go diff --git a/README.md b/README.md index 9caf8cb..fa2c30c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,5 @@ Please share issues and suggestions [here](https://code.rocketnine.space/tslocum ## Dependencies - [ebiten](https://github.com/hajimehoshi/ebiten) - Game engine -- [gohan](https://code.rocketnine.space/tslocum/gohan) - Entity Component System framework - [go-tiled](https://github.com/lafriks/go-tiled) - Tiled map file (.TMX) parser - [go-astar](https://github.com/beefsack/go-astar) - Pathfinding library diff --git a/asset/asset.go b/asset/asset.go index 4d4555e..d988082 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -27,13 +27,14 @@ var ( ) var ( - SoundMusic *audio.Player - SoundSelect *audio.Player - SoundPop1 *audio.Player - SoundPop2 *audio.Player - SoundPop3 *audio.Player - SoundPop4 *audio.Player - SoundPop5 *audio.Player + SoundMusic *audio.Player + SoundSelect *audio.Player + SoundBulldoze *audio.Player + SoundPop1 *audio.Player + SoundPop2 *audio.Player + SoundPop3 *audio.Player + SoundPop4 *audio.Player + SoundPop5 *audio.Player ) func init() { @@ -48,6 +49,9 @@ func LoadSounds(ctx *audio.Context) { SoundSelect = LoadWAV(ctx, "sound/select/select.wav") SoundSelect.SetVolume(0.6) + SoundBulldoze = LoadOGG(ctx, "sound/bulldozer/bulldozer.ogg", true) + SoundBulldoze.SetVolume(0.4) + const popVolume = 0.15 SoundPop1 = LoadWAV(ctx, "sound/pop/pop1.wav") SoundPop2 = LoadWAV(ctx, "sound/pop/pop2.wav") diff --git a/asset/map/power_solar.tmx b/asset/map/power_solar.tmx new file mode 100644 index 0000000..5cef820 --- /dev/null +++ b/asset/map/power_solar.tmx @@ -0,0 +1,22 @@ + + + + + +519,519,519,519,519, +519,519,519,519,519, +519,519,519,519,519, +519,519,519,4,4, +519,519,519,4,527 + + + + +0,0,0,0,0, +0,0,0,0,0, +0,0,0,0,0, +0,0,0,11,11, +0,0,0,11,6 + + + diff --git a/asset/sound/bulldozer/LICENSE b/asset/sound/bulldozer/LICENSE new file mode 100644 index 0000000..10f052d --- /dev/null +++ b/asset/sound/bulldozer/LICENSE @@ -0,0 +1,6 @@ +This sound clip was made available for use by kijjaz under the +Creative Commons 0 License. + +Source: https://freesound.org/people/kijjaz/sounds/389584/ + +License: https://creativecommons.org/publicdomain/zero/1.0/ diff --git a/asset/sound/bulldozer/bulldozer.ogg b/asset/sound/bulldozer/bulldozer.ogg new file mode 100644 index 0000000000000000000000000000000000000000..2c964c6e26287ce05d07bc6475b8a3a61089194a GIT binary patch literal 73309 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 *_^eM_vfdb0S<=FqPZy?wJM?bgand< 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 1 || dY > 1) && err != world.ErrNothingToBulldoze { + errMessage := err.Error() + if len(errMessage) > 0 { + errMessage = strings.ToUpper(errMessage[0:1]) + errMessage[1:] + } + world.ShowMessage(errMessage, 3) + } + } + return structure, err +} + func (s *playerMoveSystem) Update(ctx *gohan.Context) error { if ebiten.IsKeyPressed(ebiten.KeyEscape) && !world.World.DisableEsc { os.Exit(0) @@ -230,70 +284,132 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { } } } - } else if world.World.HoverStructure != 0 { + return nil + } + + if x >= world.World.ScreenW-helpW && y >= world.World.ScreenH-helpH { + if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { + const ( + helpPrev = iota + helpClose + helpNext + ) + + helpButton := world.HelpButtonAt(x-(world.World.ScreenW-helpW), y-(world.World.ScreenH-helpH)) + var updated bool + switch helpButton { + case helpPrev: + if world.World.HelpPage > 0 { + world.World.HelpPage-- + updated = true + } + case helpClose: + world.World.HelpPage = -1 + updated = true + case helpNext: + if world.World.HelpPage < len(world.HelpText)-1 { + world.World.HelpPage++ + updated = true + } + } + if updated { + world.World.HelpUpdated = true + world.World.HUDUpdated = true + + asset.SoundSelect.Rewind() + asset.SoundSelect.Play() + } + } + return nil + } + + if world.World.HoverStructure != 0 { + roadTiles := func(fromX, fromY, toX, toY int) [][2]int { + var tiles [][2]int + fx, fy := float64(fromX), float64(fromY) + tx, ty := float64(toX), float64(toY) + dx, dy := tx-fx, ty-fy + for dx < -1 || dx > 1 || dy < -1 || dy > 1 { + dx /= 2 + dy /= 2 + } + tiles = append(tiles, [2]int{fromX, fromY}) + for fx != tx || fy != ty { + fx, fy = fx+dx, fy+dy + tiles = append(tiles, [2]int{int(fx), int(fy)}) + } + return tiles + } + tileX, tileY := world.ScreenToCartesian(x, y) if tileX >= 0 && tileY >= 0 && tileX < 256 && tileY < 256 { - multiUseStructure := world.World.HoverStructure == world.StructureBulldozer || world.World.HoverStructure == world.StructureRoad - if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) || (multiUseStructure && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft)) { + + multiUseStructure := world.World.HoverStructure == world.StructureBulldozer || world.World.HoverStructure == world.StructureRoad || world.IsZone(world.World.HoverStructure) + dragStarted := world.World.BuildDragX != -1 || world.World.BuildDragY != -1 + if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) || (multiUseStructure && ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft)) || dragStarted { + if !dragStarted { + world.World.BuildDragX, world.World.BuildDragY = int(tileX), int(tileY) + + if world.World.HoverStructure == world.StructureBulldozer { + asset.SoundBulldoze.Play() + } + } + + if world.World.HoverStructure == world.StructureRoad { + tiles := roadTiles(world.World.BuildDragX, world.World.BuildDragY, int(tileX), int(tileY)) + + if dragStarted && !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + // TODO build all tiles + world.World.Level.ClearHoverSprites() + var cost int + var builtRoad bool + for _, tile := range tiles { + _, err := s.buildStructure(world.World.HoverStructure, tile[0], tile[1], !builtRoad) + if err == nil { + cost += world.StructureCosts[world.World.HoverStructure] + builtRoad = true + } + } + if cost > 0 { + world.ShowBuildCost(world.World.HoverStructure, cost) + } + + world.World.BuildDragX, world.World.BuildDragY = -1, -1 + dragStarted = false + } else { + // TODO draw hover sprites + // TODO move below into shared func + world.World.Level.ClearHoverSprites() + for _, tile := range tiles { + world.BuildStructure(world.World.HoverStructure, true, tile[0], tile[1]) + } + } + return nil + } else if dragStarted && !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + world.World.BuildDragX, world.World.BuildDragY = -1, -1 + asset.SoundBulldoze.Pause() + } + cost := world.StructureCosts[world.World.HoverStructure] if world.World.Funds < cost { - // TODO - log.Println("NOT ENOUGH FUNDS") + world.ShowMessage("Insufficient funds", 3) } else { world.World.Level.ClearHoverSprites() // TODO draw hovers and build all roads in a line from drag start - - s, err := world.BuildStructure(world.World.HoverStructure, false, int(tileX), int(tileY)) + structure, err := s.buildStructure(world.World.HoverStructure, int(tileX), int(tileY), true) if err == nil { - tileX, tileY = float64(s.X), float64(s.Y) - - isPowerPlant := world.World.HoverStructure == world.StructurePowerPlantCoal - if isPowerPlant { - plant := &world.PowerPlant{ - Type: world.World.HoverStructure, - X: int(tileX), - Y: int(tileY), - } - world.World.PowerPlants = append(world.World.PowerPlants, plant) - } - - isZone := world.World.HoverStructure == world.StructureResidentialZone || world.World.HoverStructure == world.StructureCommercialZone || world.World.HoverStructure == world.StructureIndustrialZone - if isZone { - zone := &world.Zone{ - Type: world.World.HoverStructure, - X: int(tileX), - Y: int(tileY), - } - world.World.Zones = append(world.World.Zones, zone) - } - - if world.World.HoverStructure != world.StructureBulldozer { - sounds := []*audio.Player{ - asset.SoundPop2, - asset.SoundPop3, - } - sound := sounds[rand.Intn(len(sounds))] - sound.Rewind() - sound.Play() - } - world.World.Funds -= cost - - if world.World.HoverStructure == world.StructureResidentialZone { - world.ShowMessage(world.World.Printer.Sprintf("Zoned area for residential use (-$%d)", cost), 3) - } else if world.World.HoverStructure == world.StructureCommercialZone { - world.ShowMessage(world.World.Printer.Sprintf("Zoned area for commercial use (-$%d)", cost), 3) - } else if world.World.HoverStructure == world.StructureIndustrialZone { - world.ShowMessage(world.World.Printer.Sprintf("Zoned area for industrial use (-$%d)", cost), 3) - } else { - world.ShowMessage(world.World.Printer.Sprintf("Built %s (-$%d)", strings.ToLower(world.StructureTooltips[world.World.HoverStructure]), cost), 3) - } - - world.World.HUDUpdated = true + tileX, tileY = float64(structure.X), float64(structure.Y) + world.ShowBuildCost(world.World.HoverStructure, cost) } + world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY)) } - } else if int(tileX) != world.World.HoverX || int(tileY) != world.World.HoverY { + } else { + if world.World.LastBuildX != -1 || world.World.LastBuildY != -1 { + world.World.LastBuildX, world.World.LastBuildY = -1, -1 + } + world.World.Level.ClearHoverSprites() world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY)) diff --git a/system/populate.go b/system/populate.go index 2b7eb01..a0e82d9 100644 --- a/system/populate.go +++ b/system/populate.go @@ -33,7 +33,10 @@ func (s *PopulateSystem) Update(_ *gohan.Context) error { return nil } - const popDuration = 144 * 4 + const popDuration = 144 * 7 + if world.World.Ticks%popDuration != 0 { + return nil + } // Thresholds. const ( @@ -81,58 +84,56 @@ func (s *PopulateSystem) Update(_ *gohan.Context) error { } const maxPopulation = 10 - if world.World.Ticks%popDuration == 0 { - popR, popC, popI := world.Population() - targetR, targetC, targetI := world.TargetPopulation() - for _, zone := range world.World.Zones { - var offset int - if zone.Type == world.StructureResidentialZone { - if popR < targetR { - offset = 1 - } else if popR > targetR { - offset = -1 - } - } else if zone.Type == world.StructureCommercialZone { - if popC < targetC { - offset = 1 - } else if popC > targetC { - offset = -1 - } - } else { // Industrial - if popI < targetI { - offset = 1 - } else if popI > targetI { - offset = -1 - } + popR, popC, popI := world.Population() + targetR, targetC, targetI := world.TargetPopulation() + for _, zone := range world.World.Zones { + var offset int + if zone.Type == world.StructureResidentialZone { + if popR < targetR { + offset = 1 + } else if popR > targetR { + offset = -1 } - if offset == -1 && zone.Population > 0 { - zone.Population-- - if zone.Type == world.StructureResidentialZone { - popR-- - } else if zone.Type == world.StructureCommercialZone { - popC-- - } else { // Industrial - popI-- - } - } else if offset == 1 && zone.Population < maxPopulation && zone.Powered { - zone.Population++ - if zone.Type == world.StructureResidentialZone { - popR++ - } else if zone.Type == world.StructureCommercialZone { - popC++ - } else { // Industrial - popI++ - } + } else if zone.Type == world.StructureCommercialZone { + if popC < targetC { + offset = 1 + } else if popC > targetC { + offset = -1 } - newType := buildStructureType(zone.Type, zone.Population) - // TODO only bulldoze when changed - for offsetX := 0; offsetX < 2; offsetX++ { - for offsetY := 0; offsetY < 2; offsetY++ { - world.BuildStructure(world.StructureBulldozer, false, zone.X-offsetX, zone.Y-offsetY) - } + } else { // Industrial + if popI < targetI { + offset = 1 + } else if popI > targetI { + offset = -1 } - world.BuildStructure(newType, false, zone.X, zone.Y) } + if offset == -1 && zone.Population > 0 { + zone.Population-- + if zone.Type == world.StructureResidentialZone { + popR-- + } else if zone.Type == world.StructureCommercialZone { + popC-- + } else { // Industrial + popI-- + } + } else if offset == 1 && zone.Population < maxPopulation && zone.Powered { + zone.Population++ + if zone.Type == world.StructureResidentialZone { + popR++ + } else if zone.Type == world.StructureCommercialZone { + popC++ + } else { // Industrial + popI++ + } + } + newType := buildStructureType(zone.Type, zone.Population) + // TODO only bulldoze when changed + for offsetX := 0; offsetX < 2; offsetX++ { + for offsetY := 0; offsetY < 2; offsetY++ { + world.BuildStructure(world.StructureBulldozer, false, zone.X-offsetX, zone.Y-offsetY) + } + } + world.BuildStructure(newType, false, zone.X, zone.Y) } // TODO populate and de-populate zones by target population diff --git a/system/powerscan.go b/system/powerscan.go index 377677d..1f8f335 100644 --- a/system/powerscan.go +++ b/system/powerscan.go @@ -1,8 +1,6 @@ package system import ( - "log" - "github.com/beefsack/go-astar" "code.rocketnine.space/tslocum/citylimits/component" @@ -58,7 +56,6 @@ func (s *PowerScanSystem) Update(_ *gohan.Context) error { plantSize = 5 ) powerSourceTiles := make([][]*world.PowerMapTile, len(world.World.PowerPlants)) - log.Println("POWER TILES") for i, plant := range world.World.PowerPlants { for y := 0; y < plantSize; y++ { t := world.World.Power.GetTile(plant.X+1, plant.Y-y) @@ -132,23 +129,15 @@ func (s *PowerScanSystem) Update(_ *gohan.Context) error { } for _, powerSource := range powerSourceTiles[j] { + from := world.World.Power.GetTile(powerSource.X, powerSource.Y) + for _, to := range powerDestinationTiles { if to == nil { continue } - from := world.World.Power.GetTile(powerSource.X, powerSource.Y) - - log.Println("SEARCH", from.X, from.Y, "TO", to.X, to.Y) - - /*for _, n := range powerSource.PathNeighbors() { - t := n.(*world.PowerMapTile) - log.Println("NEIGHBOR", t.X, t.Y, t.CarriesPower) - }*/ - - p, dist, found := astar.Path(from, to) + _, _, found := astar.Path(from, to) if found { - log.Printf("Resulting path\n%+v %f", p, dist) powerRemaining[j] -= powerRequired powered = true break FINDPOWERPATH @@ -157,11 +146,10 @@ func (s *PowerScanSystem) Update(_ *gohan.Context) error { } } zone.Powered = powered - log.Println("ZONE", zone, zone.Powered) - if !powered { havePowerOut = true world.World.PowerOuts[zone.X][zone.Y] = true + world.World.HavePowerOut = true } totalPowerRequired += powerRequired diff --git a/system/renderhud.go b/system/renderhud.go index d2972d6..00c4b90 100644 --- a/system/renderhud.go +++ b/system/renderhud.go @@ -3,6 +3,7 @@ package system import ( "image" "image/color" + "math" "strings" "github.com/hajimehoshi/ebiten/v2/ebitenutil" @@ -13,11 +14,17 @@ import ( "github.com/hajimehoshi/ebiten/v2" ) +const ( + helpW = 480 + helpH = 185 +) + type RenderHudSystem struct { op *ebiten.DrawImageOptions hudImg *ebiten.Image tmpImg *ebiten.Image tmpImg2 *ebiten.Image + helpImg *ebiten.Image sidebarColor color.RGBA } @@ -27,6 +34,7 @@ func NewRenderHudSystem() *RenderHudSystem { hudImg: ebiten.NewImage(1, 1), tmpImg: ebiten.NewImage(1, 1), tmpImg2: ebiten.NewImage(1, 1), + helpImg: ebiten.NewImage(helpW, helpH), } sidebarShade := uint8(111) @@ -58,12 +66,16 @@ func (s *RenderHudSystem) Draw(_ *gohan.Context, screen *ebiten.Image) error { s.drawSidebar() s.drawMessages() s.drawTooltip() + s.drawHelp() world.World.HUDUpdated = false } screen.DrawImage(s.hudImg, nil) return nil } +const columns = 3 +const buttonWidth = world.SidebarWidth / columns + func (s *RenderHudSystem) drawSidebar() { bounds := s.hudImg.Bounds() if bounds.Dx() != world.World.ScreenW || bounds.Dy() != world.World.ScreenH { @@ -75,10 +87,6 @@ func (s *RenderHudSystem) drawSidebar() { s.tmpImg.Clear() s.tmpImg2.Clear() } - w := world.SidebarWidth - if bounds.Dx() < w { - w = bounds.Dx() - } // Fill background. s.hudImg.SubImage(image.Rect(0, 0, world.SidebarWidth, world.World.ScreenH)).(*ebiten.Image).Fill(s.sidebarColor) @@ -86,9 +94,6 @@ func (s *RenderHudSystem) drawSidebar() { // Draw buttons. const paddingSize = 1 - const columns = 3 - - const buttonWidth = world.SidebarWidth / columns const buttonHeight = buttonWidth world.World.HUDButtonRects = make([]image.Rectangle, len(world.HUDButtons)) var lastButtonY int @@ -115,58 +120,25 @@ func (s *RenderHudSystem) drawSidebar() { } world.World.HUDButtonRects[i] = r - lastButtonY = y - } - - s.drawDate(lastButtonY + buttonHeight + 10) - s.drawFunds(lastButtonY + buttonHeight + 55) - - // Draw RCI indicator. - rciPadding := buttonWidth - 14 - const rciSize = 100 - rciX := buttonWidth - rciY := lastButtonY + buttonHeight + 55 + rciPadding - - const rciButtonHeight = 20 - - // Draw RCI bars. - colorR := color.RGBA{0, 255, 0, 255} - colorC := color.RGBA{0, 0, 255, 255} - colorI := color.RGBA{231, 231, 72, 255} - demandR, demandC, demandI := world.Demand() - drawDemandBar := func(demand float64, clr color.RGBA, i int) { - barOffsetSize := 12 - barOffset := -barOffsetSize + (i * barOffsetSize) - barWidth := 7 - barX := rciX + buttonWidth/2 - barWidth/2 + barOffset - barY := rciY + (rciSize / 2) - if demand < 0 { - barY += rciButtonHeight / 2 - } else { - barY -= rciButtonHeight / 2 + if button != nil && button.StructureType != world.StructureToggleTransparentStructures { + lastButtonY = y } - barHeight := int((float64(rciSize) / 2) * demand) - s.tmpImg.SubImage(image.Rect(barX, barY, barX+barWidth, barY-barHeight)).(*ebiten.Image).Fill(clr) } - drawDemandBar(demandR, colorR, 0) - drawDemandBar(demandC, colorC, 1) - drawDemandBar(demandI, colorI, 2) - // Draw RCI button. - const rciButtonPadding = 12 - const rciButtonLabelPaddingX = 6 - const rciButtonLabelPaddingY = 1 - rciButtonY := rciY + (rciSize / 2) - (rciButtonHeight / 2) - rciButtonRect := image.Rect(rciX+rciButtonPadding, rciButtonY, rciX+buttonWidth-rciButtonPadding, rciButtonY+rciButtonHeight) + dateY := lastButtonY + buttonHeight*2 - buttonHeight/2 - 16 + s.drawDate(dateY) + s.drawFunds(dateY + 50) - s.drawButtonBackground(s.tmpImg, rciButtonRect, false) // TODO + indicatorY := dateY + 179 + // Draw RCI indicator. + s.drawDemand(buttonWidth/2, indicatorY) - // Draw RCI label. - ebitenutil.DebugPrintAt(s.tmpImg, "R C I", rciX+rciButtonPadding+rciButtonLabelPaddingX, rciButtonY+rciButtonLabelPaddingY) - - s.drawButtonBorder(s.tmpImg, rciButtonRect, false) // TODO + // Draw PWR indicator. + s.drawPower(buttonWidth/2+buttonWidth, indicatorY) s.hudImg.DrawImage(s.tmpImg, nil) + + s.hudImg.SubImage(image.Rect(world.SidebarWidth-1, 0, world.SidebarWidth, world.World.ScreenH)).(*ebiten.Image).Fill(color.Black) } func (s *RenderHudSystem) drawButtonBackground(img *ebiten.Image, r image.Rectangle, selected bool) { @@ -243,6 +215,116 @@ func maxLen(v []string) int { return max } +func (s *RenderHudSystem) drawDemand(x, y int) { + const rciSize = 100 + rciX := x + rciY := y + + const rciButtonHeight = 20 + + colorR := color.RGBA{0, 255, 0, 255} + colorC := color.RGBA{0, 0, 255, 255} + colorI := color.RGBA{231, 231, 72, 255} + demandR, demandC, demandI := world.Demand() + drawDemandBar := func(demand float64, clr color.RGBA, i int) { + barOffsetSize := 12 + barOffset := -barOffsetSize + (i * barOffsetSize) + barWidth := 7 + barX := rciX + buttonWidth/2 - barWidth/2 + barOffset + barY := rciY + (rciSize / 2) + if demand < 0 { + barY += rciButtonHeight / 2 + } else { + barY -= rciButtonHeight / 2 + } + barHeight := int((float64(rciSize) / 2) * demand) + s.tmpImg.SubImage(image.Rect(barX, barY, barX+barWidth, barY-barHeight)).(*ebiten.Image).Fill(clr) + } + drawDemandBar(demandR, colorR, 0) + drawDemandBar(demandC, colorC, 1) + drawDemandBar(demandI, colorI, 2) + + // Draw button. + const rciButtonPadding = 12 + const rciButtonLabelPaddingX = 6 + const rciButtonLabelPaddingY = 1 + rciButtonY := rciY + (rciSize / 2) - (rciButtonHeight / 2) + rciButtonRect := image.Rect(rciX+rciButtonPadding, rciButtonY, rciX+buttonWidth-rciButtonPadding, rciButtonY+rciButtonHeight) + + s.drawButtonBackground(s.tmpImg, rciButtonRect, false) // TODO + + // Draw label. + ebitenutil.DebugPrintAt(s.tmpImg, "R C I", rciX+rciButtonPadding+rciButtonLabelPaddingX, rciButtonY+rciButtonLabelPaddingY) + + s.drawButtonBorder(s.tmpImg, rciButtonRect, false) // TODO +} + +func (s *RenderHudSystem) drawPower(x, y int) { + const rciSize = 100 + rciX := x + rciY := y + + const rciButtonHeight = 20 + + colorPowerNormal := color.RGBA{0, 255, 0, 255} + colorPowerOut := color.RGBA{255, 0, 0, 255} + colorPowerCapacity := color.RGBA{16, 16, 16, 255} + drawPowerBar := func(demand float64, clr color.RGBA, i int) { + barOffsetSize := 7 + barOffset := -barOffsetSize + (i * barOffsetSize) + barWidth := 7 + barX := rciX + buttonWidth/2 - barWidth/2 + barOffset + 4 + barY := rciY + (rciSize / 2) + if demand < 0 { + barY += rciButtonHeight / 2 + } else { + barY -= rciButtonHeight / 2 + } + barHeight := int((float64(rciSize) / 2) * demand) + s.tmpImg.SubImage(image.Rect(barX, barY, barX+barWidth, barY-barHeight)).(*ebiten.Image).Fill(clr) + } + + powerColor := colorPowerNormal + if world.World.HavePowerOut || world.World.PowerNeeded > world.World.PowerAvailable { + powerColor = colorPowerOut + } + + max := world.World.PowerNeeded + if world.World.PowerAvailable > max { + max = world.World.PowerAvailable + } + + pctUsage, pctCapacity := float64(world.World.PowerNeeded)/float64(max), float64(world.World.PowerAvailable)/float64(max) + clamp := func(v float64) float64 { + if math.IsNaN(v) { + return 0 + } + if v < -1 { + v = -1 + } else if v > 1 { + v = 1 + } + return v + } + + drawPowerBar(clamp(pctUsage), powerColor, 0) + drawPowerBar(clamp(pctCapacity), colorPowerCapacity, 1) + + // Draw button. + const rciButtonPadding = 12 + const rciButtonLabelPaddingX = 6 + const rciButtonLabelPaddingY = 1 + rciButtonY := rciY + (rciSize / 2) - (rciButtonHeight / 2) + rciButtonRect := image.Rect(rciX+rciButtonPadding, rciButtonY, rciX+buttonWidth-rciButtonPadding, rciButtonY+rciButtonHeight) + + s.drawButtonBackground(s.tmpImg, rciButtonRect, false) // TODO + + // Draw label. + ebitenutil.DebugPrintAt(s.tmpImg, "POWER", rciX+rciButtonPadding+rciButtonLabelPaddingX, rciButtonY+rciButtonLabelPaddingY) + + s.drawButtonBorder(s.tmpImg, rciButtonRect, false) // TODO +} + func (s *RenderHudSystem) drawMessages() { lines := len(world.World.Messages) if lines == 0 { @@ -264,10 +346,10 @@ func (s *RenderHudSystem) drawMessages() { max := len(label) lines = 1 - const padding = 12 + const padding = 10 scale := 2.0 - w, h := (max*6+10)*int(scale), 16*(int(scale))*lines+6 + w, h := (max*6+10)*int(scale), 16*(int(scale))*lines+10 x, y := world.World.ScreenW-w, 0 r := image.Rect(x, y, x+w, y+h) s.hudImg.SubImage(r).(*ebiten.Image).Fill(color.RGBA{0, 0, 0, 120}) @@ -276,7 +358,7 @@ func (s *RenderHudSystem) drawMessages() { ebitenutil.DebugPrint(s.tmpImg, label) op := &ebiten.DrawImageOptions{} op.GeoM.Scale(scale, scale) - op.GeoM.Translate(float64(x)+padding, 0) + op.GeoM.Translate(float64(x)+padding, 3) s.hudImg.DrawImage(s.tmpImg, op) } @@ -320,3 +402,59 @@ func (s *RenderHudSystem) drawFunds(y int) { op.GeoM.Translate(float64(x), float64(y)) s.hudImg.DrawImage(s.tmpImg2, op) } + +func (s *RenderHudSystem) drawHelp() { + if world.World.HelpPage < 0 { + return + } + + if world.World.HelpUpdated { + s.helpImg.Fill(s.sidebarColor) + + label := strings.TrimSpace(world.HelpText[world.World.HelpPage]) + + s.tmpImg.Clear() + ebitenutil.DebugPrint(s.tmpImg, label) + + op := &ebiten.DrawImageOptions{} + op.GeoM.Scale(2, 2) + op.GeoM.Translate(5, 0) + s.helpImg.DrawImage(s.tmpImg, op) + + s.helpImg.SubImage(image.Rect(0, 0, helpW, 1)).(*ebiten.Image).Fill(color.Black) + s.helpImg.SubImage(image.Rect(0, 0, 1, helpH)).(*ebiten.Image).Fill(color.Black) + + // Draw prev/next buttons. + buttonSize := 32 + buttonPadding := 4 + prevRect := image.Rect(buttonPadding+2, helpH-buttonSize-buttonPadding+1, buttonSize+buttonPadding+2, helpH-buttonPadding+1) + closeRect := image.Rect(helpW/2-buttonSize/2, helpH-buttonSize-buttonPadding+1, helpW/2+buttonSize/2, helpH-buttonPadding+1) + nextRect := image.Rect(helpW-buttonPadding, helpH-buttonSize-buttonPadding+1, helpW-buttonSize-buttonPadding, helpH-buttonPadding+1) + + drawButton := func(r image.Rectangle, l string) { + s.drawButtonBackground(s.helpImg, r, false) + ebitenutil.DebugPrintAt(s.helpImg, l, r.Min.X+buttonSize/2-4, r.Min.Y+buttonSize/2-10) + s.drawButtonBorder(s.helpImg, r, false) + } + + if world.World.HelpPage > 0 { + drawButton(prevRect, "<") + } + drawButton(closeRect, "X") + if world.World.HelpPage < len(world.HelpText)-1 { + drawButton(nextRect, ">") + } + + world.World.HelpButtonRects = []image.Rectangle{ + prevRect, + closeRect, + nextRect, + } + + world.World.HelpUpdated = false + } + + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(float64(world.World.ScreenW)-helpW, float64(world.World.ScreenH)-helpH) + s.hudImg.DrawImage(s.helpImg, op) +} diff --git a/world/help.go b/world/help.go new file mode 100644 index 0000000..761bbf4 --- /dev/null +++ b/world/help.go @@ -0,0 +1,20 @@ +package world + +// HelpText lines must be 39 characters or less. +var HelpText = []string{` +Welcome to City Limits! (1/3) +Blah blah blah...1231231231231231231234 +Testing, testing... Testing, testing... +How does this much text per page seem? +`, ` +Yadda yadda yadda (2/3) +Do you like the game? +I hoped you would. +I spent a lot of time making it. +`, ` +Oh no... More text?!? (3/3) +If I wanted to read, I would have +grabbed a book, not a game! I'm outta +here! *Door slam*... *Engine starting* +`, +} diff --git a/world/powermap.go b/world/powermap.go index 64f4d3d..f1ccd01 100644 --- a/world/powermap.go +++ b/world/powermap.go @@ -4,12 +4,6 @@ import ( "github.com/beefsack/go-astar" ) -const ( - powerEmptyTile = iota - powerSourceTile - powerDestinationTile -) - type PowerMapTile struct { X int Y int @@ -94,6 +88,7 @@ func ResetPowerOuts() { World.PowerOuts[x][y] = false } } + World.HavePowerOut = false } func (m PowerMap) GetTile(x, y int) *PowerMapTile { @@ -105,6 +100,9 @@ func (m PowerMap) GetTile(x, y int) *PowerMapTile { func (m PowerMap) SetTile(x, y int, carriesPower bool) { t := m[x][y] + if t.CarriesPower == carriesPower { + return + } t.CarriesPower = carriesPower World.PowerUpdated = true diff --git a/world/structure.go b/world/structure.go index 3ca33f0..26150c5 100644 --- a/world/structure.go +++ b/world/structure.go @@ -20,6 +20,7 @@ const ( StructureIndustrialHigh StructurePoliceStation StructurePowerPlantCoal + StructurePowerPlantSolar ) var StructureFilePaths = map[int]string{ @@ -39,6 +40,7 @@ var StructureFilePaths = map[int]string{ StructureIndustrialHigh: "map/industrial_high1.tmx", StructurePoliceStation: "map/policestation.tmx", StructurePowerPlantCoal: "map/power_coal.tmx", + StructurePowerPlantSolar: "map/power_solar.tmx", } type Structure struct { diff --git a/world/world.go b/world/world.go index 4c60fd9..2770c90 100644 --- a/world/world.go +++ b/world/world.go @@ -9,7 +9,9 @@ import ( "math/rand" "path/filepath" "strconv" + "strings" "sync" + "time" "golang.org/x/text/language" "golang.org/x/text/message" @@ -27,7 +29,7 @@ const startingYear = 1950 const maxPopulation = 100000 const ( - MonthTicks = 144 * 3 + MonthTicks = 144 * 7 YearTicks = MonthTicks * 12 ) @@ -39,7 +41,7 @@ const startingFunds = 10000 const startingZoom = 1.0 -const SidebarWidth = 198 +const SidebarWidth = 199 type HUDButton struct { Sprite *ebiten.Image @@ -50,7 +52,7 @@ type HUDButton struct { var HUDButtons []*HUDButton -var CameraMinZoom = 0.4 +var CameraMinZoom = 0.1 var CameraMaxZoom = 1.0 var World = &GameWorld{ @@ -65,6 +67,10 @@ var World = &GameWorld{ Printer: message.NewPrinter(language.English), Power: newPowerMap(), PowerOuts: newPowerOuts(), + BuildDragX: -1, + BuildDragY: -1, + LastBuildX: -1, + LastBuildY: -1, } type Zone struct { @@ -142,10 +148,15 @@ type GameWorld struct { HUDUpdated bool HUDButtonRects []image.Rectangle + HelpUpdated bool + HelpPage int + HelpButtonRects []image.Rectangle + PowerPlants []*PowerPlant Zones []*Zone - PowerOuts [][]bool + HavePowerOut bool + PowerOuts [][]bool Ticks int @@ -165,9 +176,17 @@ type GameWorld struct { PowerAvailable int PowerNeeded int + BuildDragX int + BuildDragY int + + LastBuildX int + LastBuildY int + resetTipShown bool } +var ErrNothingToBulldoze = errors.New("nothing to bulldoze") + func TileToGameCoords(x, y int) (float64, float64) { //return float64(x) * 32, float64(g.currentMap.Height*32) - float64(y)*32 - 32 return float64(x) * TileSize, float64(y) * TileSize @@ -179,6 +198,8 @@ func Reset() { } World.Player = 0 + rand.Seed(time.Now().UnixNano()) + World.Funds = startingFunds World.ObjectGroups = nil @@ -188,6 +209,10 @@ func Reset() { World.TriggerEntities = nil World.TriggerRects = nil World.TriggerNames = nil + + World.CamX = float64((32 * TileSize) - rand.Intn(64*TileSize)) + World.CamY = float64((32 * TileSize) + rand.Intn(32*TileSize)) + } func LoadMap(structureType int) (*tiled.Map, error) { @@ -283,6 +308,20 @@ func LoadTileset() error { return nil } +func ShowBuildCost(structureType int, cost int) { + if structureType == StructureBulldozer { + ShowMessage(World.Printer.Sprintf("Bulldozed area (-$%d)", cost), 3) + } else if structureType == StructureResidentialZone { + ShowMessage(World.Printer.Sprintf("Zoned area for residential use (-$%d)", cost), 3) + } else if structureType == StructureCommercialZone { + ShowMessage(World.Printer.Sprintf("Zoned area for commercial use (-$%d)", cost), 3) + } else if structureType == StructureIndustrialZone { + ShowMessage(World.Printer.Sprintf("Zoned area for industrial use (-$%d)", cost), 3) + } else { + ShowMessage(World.Printer.Sprintf("Built %s (-$%d)", strings.ToLower(StructureTooltips[World.HoverStructure]), cost), 3) + } +} + func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Structure, error) { // For previewing buildings /*v := rand.Intn(3) @@ -361,7 +400,7 @@ func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Str } } if !bulldozed { - return nil, errors.New("nothing to bulldoze") + return nil, ErrNothingToBulldoze } World.Power.SetTile(placeX, placeY, false) return structure, nil @@ -475,7 +514,11 @@ VALIDBUILD: if structureType == StructureRoad { World.Power.SetTile(tx, ty, true) } - World.PowerUpdated = true + + isZone := structureType == StructureResidentialZone || structureType == StructureCommercialZone || structureType == StructureIndustrialZone + if isZone || structureType == StructurePowerPlantCoal || structureType == StructureBulldozer { + World.PowerUpdated = true + } } // TODO handle flipping @@ -535,6 +578,9 @@ func StartGame() { if !World.MuteMusic { asset.SoundMusic.Play() } + + // Show initial help page. + SetHelpPage(0) } // CartesianToIso transforms cartesian coordinates into isometric coordinates. @@ -571,15 +617,25 @@ func ScreenToCartesian(x, y int) (float64, float64) { } func HUDButtonAt(x, y int) *HUDButton { - for i, colorRect := range World.HUDButtonRects { - point := image.Point{x, y} - if point.In(colorRect) { + point := image.Point{x, y} + for i, rect := range World.HUDButtonRects { + if point.In(rect) { return HUDButtons[i] } } return nil } +func HelpButtonAt(x, y int) int { + point := image.Point{x, y} + for i, rect := range World.HelpButtonRects { + if point.In(rect) { + return i + } + } + return -1 +} + func SetHoverStructure(structureType int) { World.HoverStructure = structureType World.HUDUpdated = true @@ -630,6 +686,7 @@ var StructureTooltips = map[int]string{ StructureRoad: "Road", StructurePoliceStation: "Police station", StructurePowerPlantCoal: "Coal power plant", + StructurePowerPlantSolar: "Solar power plant", StructureResidentialZone: "Residential zone", StructureCommercialZone: "Commercial zone", StructureIndustrialZone: "Industrial zone", @@ -640,6 +697,7 @@ var StructureCosts = map[int]int{ StructureRoad: 25, StructurePoliceStation: 1000, StructurePowerPlantCoal: 4000, + StructurePowerPlantSolar: 10000, StructureResidentialZone: 100, StructureCommercialZone: 200, StructureIndustrialZone: 100, @@ -726,7 +784,8 @@ func ValidXY(x, y int) bool { } var PowerPlantCapacities = map[int]int{ - StructurePowerPlantCoal: 60, + StructurePowerPlantCoal: 60, + StructurePowerPlantSolar: 40, } var ZonePowerRequirement = map[int]int{ @@ -734,3 +793,16 @@ var ZonePowerRequirement = map[int]int{ StructureCommercialZone: 1, StructureIndustrialZone: 1, } + +func SetHelpPage(page int) { + World.HelpPage = page + World.HelpUpdated = true +} + +func IsPowerPlant(structureType int) bool { + return structureType == StructurePowerPlantCoal || structureType == StructurePowerPlantSolar +} + +func IsZone(structureType int) bool { + return structureType == StructureResidentialZone || structureType == StructureCommercialZone || structureType == StructureIndustrialZone +}