diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..fe4744f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,13 @@ +v1.1.0 +- Fixed bulldozer +- Fixed tax system (now collected per citizen) +- Fixed building unintentionally when adjusting tax rates +- Fixed game crash on Windows +- Added city population indicator +- Added center camera via right click +- Added new music to soundtrack +- Removed screen edge scrolling +- Removed middle mouse scrolling + +v1.0.0 +- Initial release diff --git a/asset/asset.go b/asset/asset.go index d05e000..192047a 100644 --- a/asset/asset.go +++ b/asset/asset.go @@ -28,14 +28,21 @@ var ( ) var ( - SoundMusic *audio.Player + SoundMusic1 *audio.Player + SoundMusic2 *audio.Player + SoundMusic3 *audio.Player + SoundSelect *audio.Player SoundBulldoze *audio.Player - SoundPop1 *audio.Player - SoundPop2 *audio.Player - SoundPop3 *audio.Player - SoundPop4 *audio.Player - SoundPop5 *audio.Player + + SoundPop1 *audio.Player + SoundPop2 *audio.Player + SoundPop3 *audio.Player + SoundPop4 *audio.Player + SoundPop5 *audio.Player + + SoundExplosion1 *audio.Player + SoundExplosion2 *audio.Player ) func init() { @@ -44,8 +51,14 @@ func init() { } func LoadSounds(ctx *audio.Context) { - SoundMusic = LoadOGG(ctx, "sound/we_will_build_it.ogg", true) - SoundMusic.SetVolume(0.6) + SoundMusic1 = LoadOGG(ctx, "sound/we_will_build_it.ogg", false) + SoundMusic1.SetVolume(0.6) + + SoundMusic2 = LoadOGG(ctx, "sound/please_recycle.ogg", false) + SoundMusic2.SetVolume(0.1) + + SoundMusic3 = LoadOGG(ctx, "sound/the_world_is_a_landfill_and_its_your_fault_you_fucking_son_of_a_bitch_god_damn.ogg", false) + SoundMusic3.SetVolume(0.4) SoundSelect = LoadWAV(ctx, "sound/select/select.wav") SoundSelect.SetVolume(0.6) @@ -64,6 +77,12 @@ func LoadSounds(ctx *audio.Context) { SoundPop3.SetVolume(popVolume) SoundPop4.SetVolume(popVolume) SoundPop5.SetVolume(popVolume) + + const explosionVolume = 0.1 + SoundExplosion1 = LoadOGG(ctx, "sound/explosion/explosion1.ogg", false) + SoundExplosion2 = LoadOGG(ctx, "sound/explosion/explosion2.ogg", false) + SoundExplosion1.SetVolume(explosionVolume) + SoundExplosion2.SetVolume(explosionVolume) } func LoadImage(p string) *ebiten.Image { diff --git a/asset/sound/explosion/LICENSE b/asset/sound/explosion/LICENSE new file mode 100644 index 0000000..8130061 --- /dev/null +++ b/asset/sound/explosion/LICENSE @@ -0,0 +1,8 @@ +These sound clips were made available for use by derplayer under the +Creative Commons 0 License. + +Sources: +- https://freesound.org/people/derplayer/sounds/587194/ +- https://freesound.org/people/derplayer/sounds/587193/ + +License: http://creativecommons.org/publicdomain/zero/1.0/ diff --git a/asset/sound/explosion/explosion1.ogg b/asset/sound/explosion/explosion1.ogg new file mode 100644 index 0000000..3ce3351 Binary files /dev/null and b/asset/sound/explosion/explosion1.ogg differ diff --git a/asset/sound/explosion/explosion2.ogg b/asset/sound/explosion/explosion2.ogg new file mode 100644 index 0000000..d7fd839 Binary files /dev/null and b/asset/sound/explosion/explosion2.ogg differ diff --git a/asset/sound/please_recycle.ogg b/asset/sound/please_recycle.ogg new file mode 100644 index 0000000..622a195 Binary files /dev/null and b/asset/sound/please_recycle.ogg differ diff --git a/asset/sound/the_world_is_a_landfill_and_its_your_fault_you_fucking_son_of_a_bitch_god_damn.ogg b/asset/sound/the_world_is_a_landfill_and_its_your_fault_you_fucking_son_of_a_bitch_god_damn.ogg new file mode 100644 index 0000000..a5e8f13 Binary files /dev/null and b/asset/sound/the_world_is_a_landfill_and_its_your_fault_you_fucking_son_of_a_bitch_god_damn.ogg differ diff --git a/asset/sound/we_will_build_it.ogg b/asset/sound/we_will_build_it.ogg index 5ea8fd3..0fb41e0 100644 Binary files a/asset/sound/we_will_build_it.ogg and b/asset/sound/we_will_build_it.ogg differ diff --git a/go.mod b/go.mod index e4b15e1..3e96e59 100644 --- a/go.mod +++ b/go.mod @@ -17,8 +17,10 @@ require ( github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect github.com/jfreymuth/oggvorbis v1.0.3 // indirect github.com/jfreymuth/vorbis v1.0.2 // indirect - golang.org/x/exp v0.0.0-20220121174013-7b334a16533f // indirect + golang.org/x/exp v0.0.0-20220128181451-c853b6ddb95e // indirect golang.org/x/mobile v0.0.0-20220112015953-858099ff7816 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 // indirect ) + +replace github.com/lafriks/go-tiled => github.com/tslocum/go-tiled v0.7.1-0.20220129040705-2d2dec486bd9 diff --git a/go.sum b/go.sum index e3afecc..c610308 100644 --- a/go.sum +++ b/go.sum @@ -25,14 +25,14 @@ github.com/jfreymuth/oggvorbis v1.0.3 h1:MLNGGyhOMiVcvea9Dp5+gbs2SAwqwQbtrWnonYa github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= github.com/jfreymuth/vorbis v1.0.2 h1:m1xH6+ZI4thH927pgKD8JOH4eaGRm18rEE9/0WKjvNE= github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= -github.com/lafriks/go-tiled v0.7.0 h1:xb1iVYtPpjpHx9i/LjqHwoS2xdfrihCsFRKOFn7fOBU= -github.com/lafriks/go-tiled v0.7.0/go.mod h1:xy+4iO8AKWpFNBWeqBqnq+Cb3Oirm5oin/irP/jPx6A= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tslocum/go-tiled v0.7.1-0.20220129040705-2d2dec486bd9 h1:Uf42chMg2Cp5/qZkb9QIPzXgn9jM6Mv2Wp5tOIpVDcY= +github.com/tslocum/go-tiled v0.7.1-0.20220129040705-2d2dec486bd9/go.mod h1:xy+4iO8AKWpFNBWeqBqnq+Cb3Oirm5oin/irP/jPx6A= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -40,8 +40,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= -golang.org/x/exp v0.0.0-20220121174013-7b334a16533f h1:u4dL7EmDaaJ+1e0HD9rawKa15yKPQZWXQ/epCOPAU+A= -golang.org/x/exp v0.0.0-20220121174013-7b334a16533f/go.mod h1:M50CtfS+xv2iy/epuEazynj250ScQ0/DOjcsin9UE8k= +golang.org/x/exp v0.0.0-20220128181451-c853b6ddb95e h1:FmsvSkPHPBTboKvYBUtHbHvkQGxq+XSrqPXKDQf2W3s= +golang.org/x/exp v0.0.0-20220128181451-c853b6ddb95e/go.mod h1:M50CtfS+xv2iy/epuEazynj250ScQ0/DOjcsin9UE8k= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -74,8 +74,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27 h1:XDXtA5hveEEV8JB2l7nhMTp3t3cHp9ZpwcdjqyEWLlo= +golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/system/input_move.go b/system/input_move.go index bd9b4a1..31aae9c 100644 --- a/system/input_move.go +++ b/system/input_move.go @@ -57,7 +57,7 @@ func (s *playerMoveSystem) buildStructure(structureType int, tileX int, tileY in return nil, errors.New("insufficient funds") } - structure, err := world.BuildStructure(world.World.HoverStructure, false, tileX, tileY) + structure, err := world.BuildStructure(world.World.HoverStructure, false, tileX, tileY, false) if err == nil || world.World.HoverStructure == world.StructureBulldozer { world.World.LastBuildX, world.World.LastBuildY = tileX, tileY @@ -147,12 +147,19 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { if inpututil.IsKeyJustPressed(ebiten.KeyM) { world.World.MuteMusic = !world.World.MuteMusic if world.World.MuteMusic { - asset.SoundMusic.Pause() + asset.SoundMusic1.Pause() + asset.SoundMusic2.Pause() + asset.SoundMusic3.Pause() } else { - asset.SoundMusic.Play() + world.ResumeSong() } } + if inpututil.IsKeyJustPressed(ebiten.KeyN) { + world.World.MuteMusic = false + world.PlayNextSong() + } + if world.World.GameOver { if inpututil.IsKeyJustPressed(ebiten.KeyEnter) { world.World.ResetGame = true @@ -213,7 +220,6 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { } } - const scrollEdgeSize = 1 x, y := ebiten.CursorPosition() if !world.World.GotCursorPosition { if x != 0 || y != 0 { @@ -237,18 +243,12 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { if s.scrollDragX != -1 && s.scrollDragY != -1 { s.scrollDragX, s.scrollDragY = -1, -1 //ebiten.SetCursorMode(ebiten.CursorModeVisible) - } else if x >= -2 && y >= -2 && x < world.World.ScreenW+2 && y < world.World.ScreenH+2 { - // Pan via screen edge. - if x <= scrollEdgeSize { - world.World.CamX -= camSpeed - } else if x >= world.World.ScreenW-scrollEdgeSize-1 { - world.World.CamX += camSpeed - } - if y <= scrollEdgeSize { - world.World.CamY -= camSpeed - } else if y >= world.World.ScreenH-scrollEdgeSize-1 { - world.World.CamY += camSpeed - } + } + + if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonRight) { + vX, vY := world.World.ScreenW/2-x, world.World.ScreenH/2-y + dx, dy := float64(vX)/world.World.CamScale, float64(vY)/world.World.CamScale + world.World.CamX, world.World.CamY = world.World.CamX-dx, world.World.CamY-dy } } // Clamp viewport. @@ -309,7 +309,9 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { return nil } - world.HandleRCIWindowClick(x, y) + if world.HandleRCIWindow(x, y) { + return nil + } if x >= world.World.ScreenW-helpW && y >= world.World.ScreenH-helpH { if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) { @@ -408,10 +410,10 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { // TODO draw hover sprites // TODO move below into shared func world.World.Level.ClearHoverSprites() - world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY)) + world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY), false) var cost int for _, tile := range tiles { - world.BuildStructure(world.World.HoverStructure, true, tile[0], tile[1]) + world.BuildStructure(world.World.HoverStructure, true, tile[0], tile[1], false) cost += world.StructureCosts[world.World.HoverStructure] } world.World.HoverValid = cost <= world.World.Funds @@ -441,13 +443,13 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error { } if world.World.HoverStructure > 0 { - world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY)) + world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY), false) } } } else { world.World.Level.ClearHoverSprites() - world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY)) + world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY), false) } world.World.HoverX, world.World.HoverY = int(tileX), int(tileY) } diff --git a/system/populate.go b/system/populate.go index a0e82d9..116a4a7 100644 --- a/system/populate.go +++ b/system/populate.go @@ -130,10 +130,10 @@ func (s *PopulateSystem) Update(_ *gohan.Context) error { // 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(world.StructureBulldozer, false, zone.X-offsetX, zone.Y-offsetY, true) } } - world.BuildStructure(newType, false, zone.X, zone.Y) + world.BuildStructure(newType, false, zone.X, zone.Y, true) } // TODO populate and de-populate zones by target population diff --git a/system/renderhud.go b/system/renderhud.go index 7e99ce9..9e81844 100644 --- a/system/renderhud.go +++ b/system/renderhud.go @@ -149,6 +149,8 @@ func (s *RenderHudSystem) drawSidebar() { // Draw PWR indicator. s.drawPower(buttonWidth/2+buttonWidth, indicatorY) + s.drawPopulation(world.World.ScreenH - 45) + 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) @@ -418,6 +420,37 @@ func (s *RenderHudSystem) drawFunds(y int) { s.hudImg.DrawImage(s.tmpImg2, op) } +func (s *RenderHudSystem) drawPopulation(y int) { + var population int + for _, zone := range world.World.Zones { + population += zone.Population + } + + const datePadding = 10 + label := "Pop" + + scale := 2.0 + x, y := datePadding, y + + s.tmpImg2.Clear() + ebitenutil.DebugPrint(s.tmpImg2, label) + op := &ebiten.DrawImageOptions{} + op.GeoM.Scale(scale, scale) + op.GeoM.Translate(float64(x), float64(y)) + s.hudImg.DrawImage(s.tmpImg2, op) + + label = world.World.Printer.Sprintf("%d", population) + + x = world.SidebarWidth - 1 - datePadding - (len(label) * 6 * int(scale)) + + s.tmpImg2.Clear() + ebitenutil.DebugPrint(s.tmpImg2, label) + op.GeoM.Reset() + op.GeoM.Scale(scale, scale) + op.GeoM.Translate(float64(x), float64(y)) + s.hudImg.DrawImage(s.tmpImg2, op) +} + func (s *RenderHudSystem) drawHelp() { if world.World.HelpPage < 0 { return diff --git a/system/tax.go b/system/tax.go index 46bc403..df674f5 100644 --- a/system/tax.go +++ b/system/tax.go @@ -37,7 +37,7 @@ func (s *TaxSystem) Update(_ *gohan.Context) error { return nil } - taxCollectionAmount := 777.77 + taxCollectionAmount := 27.77 for _, zone := range world.World.Zones { if zone.Population == 0 { continue @@ -50,7 +50,7 @@ func (s *TaxSystem) Update(_ *gohan.Context) error { taxRate = world.World.TaxI } - world.World.Funds += int(taxCollectionAmount * taxRate) + world.World.Funds += int(taxCollectionAmount * taxRate * float64(zone.Population)) } return nil } diff --git a/system/tick.go b/system/tick.go index 2d5dbb4..82cfaee 100644 --- a/system/tick.go +++ b/system/tick.go @@ -1,6 +1,7 @@ package system import ( + "code.rocketnine.space/tslocum/citylimits/asset" "code.rocketnine.space/tslocum/citylimits/component" "code.rocketnine.space/tslocum/citylimits/world" "code.rocketnine.space/tslocum/gohan" @@ -33,14 +34,18 @@ func (s *TickSystem) Update(_ *gohan.Context) error { return nil } - world.World.Ticks++ // Update date display. if world.World.Ticks%world.MonthTicks == 0 { world.World.HUDUpdated = true } if world.World.Ticks%144 == 0 { world.TickMessages() + + if !world.World.MuteMusic && !asset.SoundMusic1.IsPlaying() && !asset.SoundMusic2.IsPlaying() && !asset.SoundMusic3.IsPlaying() { + world.PlayNextSong() + } } + world.World.Ticks++ return nil } diff --git a/world/help.go b/world/help.go index 1c02bed..942208a 100644 --- a/world/help.go +++ b/world/help.go @@ -9,10 +9,10 @@ Will you lead the clean energy front, or will you put profits before people? `, ` Moving Via Mouse (2/10) -To move around, place your cursor at -the edge of the screen, or press and -hold your middle mouse button while -moving your cursor. +To move around, press and hold your +middle mouse button while moving your +mouse, or press right click to center +the camera on an area immediately. `, ` Moving Via Keyboard (3/10) You can also use your keyboard to move diff --git a/world/world.go b/world/world.go index a4eb2a3..de8cb75 100644 --- a/world/world.go +++ b/world/world.go @@ -211,6 +211,8 @@ type GameWorld struct { TaxC float64 TaxI float64 + playingSong int + resetTipShown bool } @@ -237,6 +239,7 @@ func Reset() { World.CamX = float64((32 * TileSize) - rand.Intn(64*TileSize)) World.CamY = float64((32 * TileSize) + rand.Intn(32*TileSize)) + World.playingSong = rand.Intn(3) } func LoadMap(structureType int) (*tiled.Map, error) { @@ -246,7 +249,7 @@ func LoadMap(structureType int) (*tiled.Map, error) { } // Parse .tmx file. - m, err := tiled.LoadFile(filepath.FromSlash(filePath), tiled.WithFileSystem(asset.FS)) + m, err := tiled.LoadFile(filePath, tiled.WithFileSystem(asset.FS)) if err != nil { log.Fatalf("error parsing world: %+v", err) } @@ -309,7 +312,7 @@ func LoadTileset() error { tileset := m.Tilesets[0] imgPath := filepath.Join("./image/tileset/", tileset.Image.Source) - f, err := asset.FS.Open(filepath.FromSlash(imgPath)) + f, err := asset.FS.Open(filepath.ToSlash(imgPath)) if err != nil { panic(err) } @@ -346,7 +349,15 @@ func ShowBuildCost(structureType int, cost int) { } } -func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Structure, error) { +func bulldozeArea(x int, y int, size int) { + for dx := 0; dx < size; dx++ { + for dy := 0; dy < size; dy++ { + BuildStructure(StructureBulldozer, false, x-dx, y-dy, true) + } + } +} + +func BuildStructure(structureType int, hover bool, placeX int, placeY int, internal bool) (*Structure, error) { m, err := LoadMap(structureType) if err != nil { return nil, err @@ -407,6 +418,47 @@ func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Str if !bulldozed { return nil, ErrNothingToBulldoze } + if !internal { + var bulldozeStructure bool + checkSpaces := 2 + REMOVEZONES: + for i, zone := range World.Zones { + for dx := 0; dx < checkSpaces; dx++ { + for dy := 0; dy < checkSpaces; dy++ { + if placeX == zone.X-dx && placeY == zone.Y-dy { + World.Zones = append(World.Zones[:i], World.Zones[i+1:]...) + bulldozeArea(zone.X, zone.Y, 2) + bulldozeStructure = true + break REMOVEZONES + } + } + } + } + checkSpaces = 5 + REMOVEPOWER: + for i, plant := range World.PowerPlants { + for dx := 0; dx < checkSpaces; dx++ { + for dy := 0; dy < checkSpaces; dy++ { + if placeX == plant.X-dx && placeY == plant.Y-dy { + World.PowerPlants = append(World.PowerPlants[:i], World.PowerPlants[i+1:]...) + bulldozeArea(plant.X, plant.Y, 5) + bulldozeStructure = true + World.PowerUpdated = true + break REMOVEPOWER + } + } + } + } + if bulldozeStructure { + sounds := []*audio.Player{ + asset.SoundExplosion1, + asset.SoundExplosion2, + } + sound := sounds[rand.Intn(len(sounds))] + sound.Rewind() + sound.Play() + } + } World.Power.SetTile(placeX, placeY, false) return structure, nil } @@ -558,10 +610,6 @@ func StartGame() { } World.GameStarted = true - if !World.MuteMusic { - asset.SoundMusic.Play() - } - // Show initial help page. SetHelpPage(0) } @@ -627,18 +675,18 @@ func AltButtonAt(x, y int) int { return -1 } -func HandleRCIWindowClick(x, y int) { +func HandleRCIWindow(x, y int) bool { if !World.ShowRCIWindow { - return - } - - if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { - return + return false } point := image.Point{x, y} if !point.In(World.RCIWindowRect) { - return + return false + } + + if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + return true } var updated bool @@ -668,7 +716,7 @@ func HandleRCIWindowClick(x, y int) { updated = true } if !updated { - return + return true } if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) || World.Ticks%16 == 0 { @@ -683,6 +731,7 @@ func HandleRCIWindowClick(x, y int) { sound.Rewind() sound.Play() } + return true } func SetHoverStructure(structureType int) { @@ -866,3 +915,39 @@ func IsPowerPlant(structureType int) bool { func IsZone(structureType int) bool { return structureType == StructureResidentialZone || structureType == StructureCommercialZone || structureType == StructureIndustrialZone } + +func PlayNextSong() { + const numSongs = 3 + + asset.SoundMusic1.Pause() + asset.SoundMusic2.Pause() + asset.SoundMusic3.Pause() + + World.playingSong++ + if World.playingSong == numSongs { + World.playingSong = 0 + } + + switch World.playingSong { + case 0: + asset.SoundMusic1.Rewind() + asset.SoundMusic1.Play() + case 1: + asset.SoundMusic2.Rewind() + asset.SoundMusic2.Play() + case 2: + asset.SoundMusic3.Rewind() + asset.SoundMusic3.Play() + } +} + +func ResumeSong() { + switch World.playingSong { + case 0: + asset.SoundMusic1.Play() + case 1: + asset.SoundMusic2.Play() + case 2: + asset.SoundMusic3.Play() + } +}