Major game update

- 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
This commit is contained in:
Trevor Slocum 2022-01-30 08:21:07 -08:00
parent cabff986f4
commit a459c97c86
17 changed files with 228 additions and 61 deletions

13
CHANGELOG Normal file
View File

@ -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

View File

@ -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 {

View File

@ -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/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

6
go.mod
View File

@ -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

12
go.sum
View File

@ -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=

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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()
}
}