Add sound effects and music

This commit is contained in:
Trevor Slocum 2022-01-11 15:02:02 -08:00
parent 5dc4cbb245
commit 659d8a86ea
16 changed files with 94 additions and 11 deletions

View File

@ -28,9 +28,10 @@ Please share issues and suggestions [here](https://code.rocketnine.space/tslocum
## Credits
- [Trevor Slocum](https://rocketnine.space) - Game design and programming
- [node punk](https://open.spotify.com/artist/15eFpWQPNRxB89PnFNWvjU?si=z-jfVwYHTxugaC-BGZiyNg) - Music
- [node punk](https://soundcloud.com/solve_x) - Music
## 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

View File

@ -16,20 +16,46 @@ import (
const sampleRate = 44100
//go:embed image map
//go:embed image map sound
var FS embed.FS
var ImgWhiteSquare = ebiten.NewImage(128, 128)
var ImgBlackSquare = ebiten.NewImage(128, 128)
var ImgBlank = ebiten.NewImage(1, 1)
var SoundMusic *audio.Player
var SoundSelect *audio.Player
var (
SoundPop1 *audio.Player
SoundPop2 *audio.Player
SoundPop3 *audio.Player
SoundPop4 *audio.Player
SoundPop5 *audio.Player
)
func init() {
ImgWhiteSquare.Fill(color.White)
ImgBlackSquare.Fill(color.Black)
}
func LoadSounds(ctx *audio.Context) {
// TODO
SoundMusic = LoadOGG(ctx, "sound/we_will_build_it.ogg", true)
SoundMusic.SetVolume(0.6)
SoundSelect = LoadWAV(ctx, "sound/select/select.wav")
SoundSelect.SetVolume(0.6)
SoundPop1 = LoadWAV(ctx, "sound/pop/pop1.wav")
SoundPop2 = LoadWAV(ctx, "sound/pop/pop2.wav")
SoundPop3 = LoadWAV(ctx, "sound/pop/pop3.wav")
SoundPop4 = LoadWAV(ctx, "sound/pop/pop4.wav")
SoundPop5 = LoadWAV(ctx, "sound/pop/pop5.wav")
SoundPop1.SetVolume(0.2)
SoundPop2.SetVolume(0.2)
SoundPop3.SetVolume(0.2)
SoundPop4.SetVolume(0.2)
SoundPop5.SetVolume(0.2)
}
func LoadImage(p string) *ebiten.Image {

View File

@ -6,7 +6,7 @@
67,67,67,67,
67,67,67,67,
67,67,67,67,
67,67,527,67
67,67,67,527
</data>
</layer>
<layer id="2" name="2" width="4" height="4" offsetx="0" offsety="-80">

6
asset/sound/pop/LICENSE Normal file
View File

@ -0,0 +1,6 @@
These sound clips were made available for use by onikage22 under the
Creative Commons 0 License.
Source: https://freesound.org/people/onikage22/sounds/240566/
License: http://creativecommons.org/publicdomain/zero/1.0/

BIN
asset/sound/pop/pop1.wav Normal file

Binary file not shown.

BIN
asset/sound/pop/pop2.wav Normal file

Binary file not shown.

BIN
asset/sound/pop/pop3.wav Normal file

Binary file not shown.

BIN
asset/sound/pop/pop4.wav Normal file

Binary file not shown.

BIN
asset/sound/pop/pop5.wav Normal file

Binary file not shown.

View File

@ -0,0 +1,6 @@
These sound clips were made available for use by soiboi under the
Creative Commons 0 License.
Source: https://freesound.org/people/soiboi/sounds/556823/
License: http://creativecommons.org/publicdomain/zero/1.0/

Binary file not shown.

Binary file not shown.

View File

@ -18,6 +18,7 @@ func parseFlags() {
flag.BoolVar(&fullscreen, "fullscreen", false, "run in fullscreen mode")
flag.BoolVar(&world.World.NativeResolution, "native", false, "display at native resolution")
flag.BoolVar(&noSplash, "no-splash", false, "skip splash screen")
flag.BoolVar(&world.World.MuteMusic, "mute-music", false, "mute music")
flag.IntVar(&world.World.Debug, "debug", 0, "print debug information")
flag.Parse()

View File

@ -252,6 +252,7 @@ func (g *game) Draw(screen *ebiten.Image) {
}
var sprite *ebiten.Image
colorScale := 1.0
alpha := 1.0
if tile.HoverSprite != nil {
sprite = tile.HoverSprite
colorScale = 0.6
@ -260,12 +261,16 @@ func (g *game) Draw(screen *ebiten.Image) {
}
} else if tile.Sprite != nil {
sprite = tile.Sprite
// TODO
/*if i > 0 && world.World.HoverStructure == world.StructureRoad {
alpha = 0.6
}*/
} else if tile.EnvironmentSprite != nil {
sprite = tile.EnvironmentSprite
} else {
continue
}
drawn += g.renderSprite(float64(x), float64(y), 0, float64(i*-80), 0, 1, colorScale, 1, false, false, sprite, screen)
drawn += g.renderSprite(float64(x), float64(y), 0, float64(i*-80), 0, 1, colorScale, alpha, false, false, sprite, screen)
}
}
}

View File

@ -1,8 +1,13 @@
package system
import (
"math/rand"
"os"
"github.com/hajimehoshi/ebiten/v2/audio"
"code.rocketnine.space/tslocum/citylimits/asset"
"code.rocketnine.space/tslocum/citylimits/component"
"code.rocketnine.space/tslocum/citylimits/world"
"code.rocketnine.space/tslocum/gohan"
@ -78,7 +83,12 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
}
if inpututil.IsKeyJustPressed(ebiten.KeyM) {
// TODO mute sound
world.World.MuteMusic = !world.World.MuteMusic
if world.World.MuteMusic {
asset.SoundMusic.Pause()
} else {
asset.SoundMusic.Play()
}
}
if world.World.GameOver {
@ -119,10 +129,10 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
world.World.CamScale -= (world.World.CamScale - world.World.CamScaleTarget) / div
}
pressLeft := ebiten.IsKeyPressed(ebiten.KeyLeft)
pressRight := ebiten.IsKeyPressed(ebiten.KeyRight)
pressUp := ebiten.IsKeyPressed(ebiten.KeyUp)
pressDown := ebiten.IsKeyPressed(ebiten.KeyDown)
pressLeft := ebiten.IsKeyPressed(ebiten.KeyLeft) || ebiten.IsKeyPressed(ebiten.KeyA)
pressRight := ebiten.IsKeyPressed(ebiten.KeyRight) || ebiten.IsKeyPressed(ebiten.KeyD)
pressUp := ebiten.IsKeyPressed(ebiten.KeyUp) || ebiten.IsKeyPressed(ebiten.KeyW)
pressDown := ebiten.IsKeyPressed(ebiten.KeyDown) || ebiten.IsKeyPressed(ebiten.KeyS)
const camSpeed = 10
if (pressLeft && !pressRight) ||
@ -194,6 +204,8 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
} else {
world.SetHoverStructure(button.StructureType)
}
asset.SoundSelect.Rewind()
asset.SoundSelect.Play()
}
}
}
@ -213,7 +225,19 @@ func (s *playerMoveSystem) Update(ctx *gohan.Context) error {
world.World.Level.Tiles[i][int(tileX)][int(tileY)].EnvironmentSprite = img
}
} else {
world.BuildStructure(world.World.HoverStructure, false, int(tileX), int(tileY))
_, err := world.BuildStructure(world.World.HoverStructure, false, int(tileX), int(tileY))
if err == nil {
sounds := []*audio.Player{
asset.SoundPop1,
asset.SoundPop2,
asset.SoundPop3,
asset.SoundPop4,
asset.SoundPop5,
}
sound := sounds[rand.Intn(len(sounds))]
sound.Rewind()
sound.Play()
}
}
world.BuildStructure(world.World.HoverStructure, true, int(tileX), int(tileY))
} else if int(tileX) != world.World.HoverX || int(tileY) != world.World.HoverY {

View File

@ -107,6 +107,9 @@ type GameWorld struct {
ResetGame bool
MuteMusic bool
MuteSoundEffects bool // TODO
GotCursorPosition bool
tilesets []*ebiten.Image
@ -292,16 +295,23 @@ func BuildStructure(structureType int, hover bool, placeX int, placeY int) (*Str
// TODO Add entity
valid := true
var existingRoadTiles int
VALIDBUILD:
for y := 0; y < m.Height; y++ {
for x := 0; x < m.Width; x++ {
tx, ty := (x+placeX)-w, (y+placeY)-h
if structureType == StructureRoad && World.Level.Tiles[0][tx][ty].Sprite == World.TileImages[World.TileImagesFirstGID] {
existingRoadTiles++
}
if World.Level.Tiles[1][tx][ty].Sprite != nil || (World.Level.Tiles[0][tx][ty].Sprite != nil && (structureType != StructureRoad || World.Level.Tiles[0][tx][ty].Sprite != World.TileImages[World.TileImagesFirstGID])) {
valid = false
break VALIDBUILD
}
}
}
if structureType == StructureRoad && existingRoadTiles == 4 {
valid = false
}
if hover {
World.HoverValid = valid
} else if !valid {
@ -412,6 +422,10 @@ func StartGame() {
return
}
World.GameStarted = true
if !World.MuteMusic {
asset.SoundMusic.Play()
}
}
func SetMessage(message string, duration int) {