295 lines
5.6 KiB
Go
295 lines
5.6 KiB
Go
package main
|
|
|
|
import "C"
|
|
|
|
import (
|
|
"path/filepath"
|
|
"runtime"
|
|
|
|
"github.com/veandco/go-sdl2/img"
|
|
"github.com/veandco/go-sdl2/mix"
|
|
"github.com/veandco/go-sdl2/sdl"
|
|
"github.com/veandco/go-sdl2/ttf"
|
|
)
|
|
|
|
const (
|
|
winTitle = "Go SDL2"
|
|
winWidth = 480
|
|
winHeight = 800
|
|
)
|
|
|
|
// Game states.
|
|
const (
|
|
stateRun = iota
|
|
stateFlap
|
|
stateDead
|
|
)
|
|
|
|
// States text.
|
|
var stateText = map[int]string{
|
|
stateRun: "RUN",
|
|
stateFlap: "FLAP",
|
|
stateDead: "DEAD",
|
|
}
|
|
|
|
// Text represents state text.
|
|
type Text struct {
|
|
Width int32
|
|
Height int32
|
|
Texture *sdl.Texture
|
|
}
|
|
|
|
// Engine represents SDL engine.
|
|
type Engine struct {
|
|
State int
|
|
Window *sdl.Window
|
|
Renderer *sdl.Renderer
|
|
Sprite *sdl.Texture
|
|
Font *ttf.Font
|
|
Music *mix.Music
|
|
Sound *mix.Chunk
|
|
StateText map[int]*Text
|
|
running bool
|
|
}
|
|
|
|
// NewEngine returns new engine.
|
|
func NewEngine() (e *Engine) {
|
|
e = &Engine{}
|
|
e.running = true
|
|
return
|
|
}
|
|
|
|
// Init initializes SDL.
|
|
func (e *Engine) Init() (err error) {
|
|
err = sdl.Init(sdl.INIT_EVERYTHING)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
img.Init(img.INIT_PNG)
|
|
|
|
err = mix.Init(mix.INIT_MP3)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = ttf.Init()
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = mix.OpenAudio(mix.DEFAULT_FREQUENCY, mix.DEFAULT_FORMAT, mix.DEFAULT_CHANNELS, 3072)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
e.Window, err = sdl.CreateWindow(winTitle, sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, winWidth, winHeight, sdl.WINDOW_SHOWN)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
e.Renderer, err = sdl.CreateRenderer(e.Window, -1, sdl.RENDERER_ACCELERATED)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Destroy destroys SDL and releases the memory.
|
|
func (e *Engine) Destroy() {
|
|
e.Renderer.Destroy()
|
|
e.Window.Destroy()
|
|
mix.CloseAudio()
|
|
|
|
img.Quit()
|
|
mix.Quit()
|
|
ttf.Quit()
|
|
sdl.Quit()
|
|
}
|
|
|
|
// Running checks if loop is running.
|
|
func (e *Engine) Running() bool {
|
|
return e.running
|
|
}
|
|
|
|
// Quit exits main loop.
|
|
func (e *Engine) Quit() {
|
|
e.running = false
|
|
}
|
|
|
|
// Load loads resources.
|
|
func (e *Engine) Load() {
|
|
assetDir := ""
|
|
if runtime.GOOS != "android" {
|
|
assetDir = filepath.Join("android", "src", "main", "assets")
|
|
}
|
|
|
|
var err error
|
|
e.Sprite, err = img.LoadTexture(e.Renderer, filepath.Join(assetDir, "images", "sprite.png"))
|
|
if err != nil {
|
|
sdl.LogError(sdl.LOG_CATEGORY_APPLICATION, "LoadTexture: %s\n", err)
|
|
}
|
|
|
|
e.Font, err = ttf.OpenFont(filepath.Join(assetDir, "fonts", "universalfruitcake.ttf"), 24)
|
|
if err != nil {
|
|
sdl.LogError(sdl.LOG_CATEGORY_APPLICATION, "OpenFont: %s\n", err)
|
|
}
|
|
|
|
e.Music, err = mix.LoadMUS(filepath.Join(assetDir, "music", "frantic-gameplay.mp3"))
|
|
if err != nil {
|
|
sdl.LogError(sdl.LOG_CATEGORY_APPLICATION, "LoadMUS: %s\n", err)
|
|
}
|
|
|
|
e.Sound, err = mix.LoadWAV(filepath.Join(assetDir, "sounds", "click.wav"))
|
|
if err != nil {
|
|
sdl.LogError(sdl.LOG_CATEGORY_APPLICATION, "LoadWAV: %s\n", err)
|
|
}
|
|
|
|
e.StateText = map[int]*Text{}
|
|
for k, v := range stateText {
|
|
t, _ := e.renderText(v, sdl.Color{0, 0, 0, 0})
|
|
_, _, tW, tH, _ := t.Query()
|
|
e.StateText[k] = &Text{tW, tH, t}
|
|
}
|
|
}
|
|
|
|
// Unload unloads resources.
|
|
func (e *Engine) Unload() {
|
|
for _, v := range e.StateText {
|
|
v.Texture.Destroy()
|
|
}
|
|
|
|
e.Sprite.Destroy()
|
|
e.Font.Close()
|
|
e.Music.Free()
|
|
e.Sound.Free()
|
|
}
|
|
|
|
// renderText renders texture from ttf font.
|
|
func (e *Engine) renderText(text string, color sdl.Color) (texture *sdl.Texture, err error) {
|
|
surface, err := e.Font.RenderUTF8Blended(text, color)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
defer surface.Free()
|
|
|
|
texture, err = e.Renderer.CreateTextureFromSurface(surface)
|
|
return
|
|
}
|
|
|
|
//export SDL_main
|
|
func SDL_main() {
|
|
runtime.LockOSThread()
|
|
e := NewEngine()
|
|
|
|
err := e.Init()
|
|
if err != nil {
|
|
sdl.LogError(sdl.LOG_CATEGORY_APPLICATION, "Init: %s\n", err)
|
|
}
|
|
defer e.Destroy()
|
|
|
|
e.Load()
|
|
defer e.Unload()
|
|
|
|
// Sprite size
|
|
const n = 128
|
|
|
|
// Sprite rects
|
|
var rects []*sdl.Rect
|
|
for x := 0; x < 6; x++ {
|
|
rect := &sdl.Rect{int32(n * x), 0, n, n}
|
|
rects = append(rects, rect)
|
|
}
|
|
|
|
e.Music.Play(-1)
|
|
|
|
var frame int = 0
|
|
var alpha uint8 = 255
|
|
var showText bool = true
|
|
|
|
var text *Text = e.StateText[stateRun]
|
|
|
|
for e.Running() {
|
|
for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
|
|
switch t := event.(type) {
|
|
case *sdl.QuitEvent:
|
|
e.Quit()
|
|
|
|
case *sdl.MouseButtonEvent:
|
|
e.Sound.Play(2, 0)
|
|
if t.Type == sdl.MOUSEBUTTONDOWN && t.Button == sdl.BUTTON_LEFT {
|
|
alpha = 255
|
|
showText = true
|
|
|
|
if e.State == stateRun {
|
|
text = e.StateText[stateFlap]
|
|
e.State = stateFlap
|
|
} else if e.State == stateFlap {
|
|
text = e.StateText[stateDead]
|
|
e.State = stateDead
|
|
} else if e.State == stateDead {
|
|
text = e.StateText[stateRun]
|
|
e.State = stateRun
|
|
}
|
|
}
|
|
|
|
case *sdl.KeyboardEvent:
|
|
if t.Keysym.Scancode == sdl.SCANCODE_ESCAPE || t.Keysym.Scancode == sdl.SCANCODE_AC_BACK {
|
|
e.Quit()
|
|
}
|
|
}
|
|
}
|
|
|
|
e.Renderer.Clear()
|
|
|
|
var clips []*sdl.Rect
|
|
|
|
w, h := e.Window.GetSize()
|
|
x, y := int32(w/2), int32(h/2)
|
|
|
|
switch e.State {
|
|
case stateRun:
|
|
e.Renderer.SetDrawColor(168, 235, 254, 255)
|
|
clips = rects[0:2]
|
|
|
|
case stateFlap:
|
|
e.Renderer.SetDrawColor(251, 231, 240, 255)
|
|
clips = rects[2:4]
|
|
|
|
case stateDead:
|
|
e.Renderer.SetDrawColor(255, 250, 205, 255)
|
|
clips = rects[4:6]
|
|
}
|
|
|
|
clip := clips[frame/2]
|
|
|
|
e.Renderer.FillRect(nil)
|
|
e.Renderer.Copy(e.Sprite, clip, &sdl.Rect{x - (n / 2), y - (n / 2), n, n})
|
|
|
|
if showText {
|
|
text.Texture.SetAlphaMod(alpha)
|
|
e.Renderer.Copy(text.Texture, nil, &sdl.Rect{x - (text.Width / 2), y - n*1.5, text.Width, text.Height})
|
|
}
|
|
|
|
e.Renderer.Present()
|
|
sdl.Delay(50)
|
|
|
|
frame += 1
|
|
if frame/2 >= 2 {
|
|
frame = 0
|
|
}
|
|
|
|
alpha -= 10
|
|
if alpha <= 10 {
|
|
alpha = 255
|
|
showText = false
|
|
}
|
|
}
|
|
}
|
|
|
|
func main() {
|
|
SDL_main()
|
|
}
|