Metroidvania video game
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
5.0 KiB

package asset
import (
"bytes"
"embed"
"image"
"image/color"
"io"
"math"
"github.com/hajimehoshi/ebiten/v2/audio/wav"
"github.com/hajimehoshi/ebiten/v2/audio"
"github.com/hajimehoshi/ebiten/v2/audio/vorbis"
"github.com/hajimehoshi/ebiten/v2"
_ "image/png"
)
//go:embed image map sound
var FS embed.FS
var ImgWhiteSquare = newFilledImage(4, 4, color.White)
var ImgBullet = newFilledImage(4, 4, color.RGBA{80, 142, 237, 255})
var ImgRobotTileset = LoadImage("image/robot-tileset/tileset.png")
var ImgNewspaper = LoadImage("image/newspaper.png")
const (
idleX, idleY = 208, 118
idleW, idleH = 16, 27
)
var ImgPlayerIdle1 = ImgRobotTileset.SubImage(image.Rect(idleX, idleY, idleX+idleW, idleY+idleH)).(*ebiten.Image)
var ImgPlayerIdle2 = ImgRobotTileset.SubImage(image.Rect(idleX+idleW, idleY, idleX+idleW+idleW, idleY+idleH)).(*ebiten.Image)
var ImgPlayerIdle3 = ImgRobotTileset.SubImage(image.Rect(idleX+idleW*2, idleY, idleX+idleW*2+idleW, idleY+idleH)).(*ebiten.Image)
var ImgPlayerIdle4 = ImgRobotTileset.SubImage(image.Rect(idleX+idleW*3, idleY, idleX+idleW*3+idleW, idleY+idleH)).(*ebiten.Image)
var PlayerIdleFrames = []*ebiten.Image{
ImgPlayerIdle3,
ImgPlayerIdle4,
ImgPlayerIdle1,
ImgPlayerIdle2,
}
var ImgPlayerIdle1Rot90 = rotate90(ImgPlayerIdle1)
var ImgPlayerIdle2Rot90 = rotate90(ImgPlayerIdle2)
var ImgPlayerIdle3Rot90 = rotate90(ImgPlayerIdle3)
var ImgPlayerIdle4Rot90 = rotate90(ImgPlayerIdle4)
var PlayerIdleFramesRot90 = []*ebiten.Image{
ImgPlayerIdle1Rot90,
ImgPlayerIdle2Rot90,
ImgPlayerIdle3Rot90,
ImgPlayerIdle4Rot90,
}
const (
walkX, walkY = 288, 118
walkW, walkH = 16, 26
)
var ImgPlayerWalk1 = ImgRobotTileset.SubImage(image.Rect(walkX, walkY, walkX+walkW, walkY+walkH)).(*ebiten.Image)
var ImgPlayerWalk2 = ImgRobotTileset.SubImage(image.Rect(walkX+walkW, walkY, walkX+walkW+walkW, walkY+walkH)).(*ebiten.Image)
var ImgPlayerWalk3 = ImgRobotTileset.SubImage(image.Rect(walkX+walkW*2, walkY, walkX+walkW*2+walkW, walkY+walkH)).(*ebiten.Image)
var ImgPlayerWalk4 = ImgRobotTileset.SubImage(image.Rect(walkX+walkW*3, walkY, walkX+walkW*3+walkW, walkY+walkH)).(*ebiten.Image)
var PlayerWalkFrames = []*ebiten.Image{
ImgPlayerWalk1,
ImgPlayerWalk2,
ImgPlayerWalk3,
ImgPlayerWalk4,
}
var ImgPlayerWalk1Rot90 = rotate90(ImgPlayerWalk1)
var ImgPlayerWalk2Rot90 = rotate90(ImgPlayerWalk2)
var ImgPlayerWalk3Rot90 = rotate90(ImgPlayerWalk3)
var ImgPlayerWalk4Rot90 = rotate90(ImgPlayerWalk4)
var PlayerWalkFramesRot90 = []*ebiten.Image{
ImgPlayerWalk1Rot90,
ImgPlayerWalk2Rot90,
ImgPlayerWalk3Rot90,
ImgPlayerWalk4Rot90,
}
const (
TileBeamOrange1 = 256
TileBeamOrange2 = 257
TileBeamOrange3 = 258
TileBeamBlue1 = 259
TileBeamBlue2 = 260
TileBeamBlue3 = 261
)
var BeamTiles = []uint32{
TileBeamOrange1,
TileBeamOrange2,
TileBeamOrange3,
TileBeamBlue1,
TileBeamBlue2,
TileBeamBlue3,
}
func rotate90(src *ebiten.Image) *ebiten.Image {
bounds := src.Bounds()
width, height := bounds.Dx(), bounds.Dy()
img := ebiten.NewImage(height*2, width)
op := &ebiten.DrawImageOptions{}
op.GeoM.Translate(0, -float64(height)/2)
op.GeoM.Rotate(math.Pi / 2)
op.GeoM.Translate(float64(width)-4, 0)
img.DrawImage(src, op)
return img
}
func newFilledImage(w int, h int, c color.Color) *ebiten.Image {
img := ebiten.NewImage(w, h)
img.Fill(c)
return img
}
func LoadImage(p string) *ebiten.Image {
f, err := FS.Open(p)
if err != nil {
panic(err)
}
defer f.Close()
baseImg, _, err := image.Decode(f)
if err != nil {
panic(err)
}
return ebiten.NewImageFromImage(baseImg)
}
func LoadBytes(p string) []byte {
b, err := FS.ReadFile(p)
if err != nil {
panic(err)
}
return b
}
const sampleRate = 44100
var audioContext = audio.NewContext(sampleRate)
var (
SoundFire = LoadWAV(audioContext, "sound/fire.wav")
SoundHit = LoadWAV(audioContext, "sound/hit.wav")
SoundExplode = LoadWAV(audioContext, "sound/explode.wav")
SoundAlarm = LoadWAV(audioContext, "sound/alarm.wav")
SoundMusic = LoadOGG(audioContext, "sound/mechanical_spider_theme.ogg", true)
)
func LoadWAV(context *audio.Context, p string) *audio.Player {
f, err := FS.Open(p)
if err != nil {
panic(err)
}
defer f.Close()
stream, err := wav.DecodeWithSampleRate(sampleRate, f)
if err != nil {
panic(err)
}
player, err := context.NewPlayer(stream)
if err != nil {
panic(err)
}
// Workaround to prevent delays when playing for the first time.
player.SetVolume(0)
player.Play()
player.Pause()
player.Rewind()
player.SetVolume(1)
return player
}
func LoadOGG(context *audio.Context, p string, loop bool) *audio.Player {
b := LoadBytes(p)
stream, err := vorbis.DecodeWithSampleRate(sampleRate, bytes.NewReader(b))
if err != nil {
panic(err)
}
var s io.Reader
if loop {
s = audio.NewInfiniteLoop(stream, stream.Length())
} else {
s = stream
}
player, err := context.NewPlayer(s)
if err != nil {
panic(err)
}
// Workaround to prevent delays when playing for the first time.
player.SetVolume(0)
player.Play()
player.Pause()
player.Rewind()
player.SetVolume(1)
return player
}