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:
parent
cabff986f4
commit
a459c97c86
17 changed files with 228 additions and 61 deletions
13
CHANGELOG
Normal file
13
CHANGELOG
Normal 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
|
|
@ -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 {
|
||||
|
|
8
asset/sound/explosion/LICENSE
Normal file
8
asset/sound/explosion/LICENSE
Normal 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/
|
BIN
asset/sound/explosion/explosion1.ogg
Normal file
BIN
asset/sound/explosion/explosion1.ogg
Normal file
Binary file not shown.
BIN
asset/sound/explosion/explosion2.ogg
Normal file
BIN
asset/sound/explosion/explosion2.ogg
Normal file
Binary file not shown.
BIN
asset/sound/please_recycle.ogg
Normal file
BIN
asset/sound/please_recycle.ogg
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
6
go.mod
6
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
|
||||
|
|
12
go.sum
12
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=
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
115
world/world.go
115
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()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue