cloud-game/ui/gameview.go
2019-04-02 01:18:57 +08:00

175 lines
4.1 KiB
Go

package ui
import (
"image"
"github.com/giongto35/game-online/nes"
"github.com/go-gl/gl/v2.1/gl"
"github.com/go-gl/glfw/v3.2/glfw"
)
const padding = 0
type GameView struct {
director *Director
console *nes.Console
title string
hash string
texture uint32
record bool
frames []image.Image
keyPressed []bool
imageChannel chan *image.RGBA
inputChannel chan int
}
func NewGameView(director *Director, console *nes.Console, title, hash string, imageChannel chan *image.RGBA, inputChannel chan int) View {
texture := createTexture()
gameview := &GameView{director, console, title, hash, texture, false, nil, make([]bool, 255), imageChannel, inputChannel}
go gameview.ListenToInputChannel()
return gameview
}
func (view *GameView) ListenToInputChannel() {
for {
key := <-view.inputChannel
if key < 0 {
view.keyPressed[-key] = false
} else {
view.keyPressed[key] = true
}
}
}
func (view *GameView) Enter() {
gl.ClearColor(0, 0, 0, 1)
view.director.SetTitle(view.title)
view.console.SetAudioChannel(view.director.audio.channel)
view.console.SetAudioSampleRate(view.director.audio.sampleRate)
view.director.window.SetKeyCallback(view.onKey)
// load state
if err := view.console.LoadState(savePath(view.hash)); err == nil {
return
} else {
view.console.Reset()
}
// load sram
cartridge := view.console.Cartridge
if cartridge.Battery != 0 {
if sram, err := readSRAM(sramPath(view.hash)); err == nil {
cartridge.SRAM = sram
}
}
}
func (view *GameView) Exit() {
view.director.window.SetKeyCallback(nil)
view.console.SetAudioChannel(nil)
view.console.SetAudioSampleRate(0)
// save sram
cartridge := view.console.Cartridge
if cartridge.Battery != 0 {
writeSRAM(sramPath(view.hash), cartridge.SRAM)
}
// save state
view.console.SaveState(savePath(view.hash))
}
func (view *GameView) Update(t, dt float64) {
if dt > 1 {
dt = 0
}
window := view.director.window
console := view.console
if joystickReset(glfw.Joystick1) {
view.director.ShowMenu()
}
if joystickReset(glfw.Joystick2) {
view.director.ShowMenu()
}
if readKey(window, glfw.KeyEscape) {
view.director.ShowMenu()
}
//updateControllers(window, console)
view.updateControllers()
console.StepSeconds(dt)
gl.BindTexture(gl.TEXTURE_2D, view.texture)
setTexture(console.Buffer())
view.imageChannel <- console.Buffer()
drawBuffer(view.director.window)
gl.BindTexture(gl.TEXTURE_2D, 0)
if view.record {
view.frames = append(view.frames, copyImage(console.Buffer()))
}
}
func (view *GameView) onKey(window *glfw.Window,
key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
if action == glfw.Press {
switch key {
case glfw.KeySpace:
screenshot(view.console.Buffer())
case glfw.KeyR:
view.console.Reset()
case glfw.KeyTab:
if view.record {
view.record = false
animation(view.frames)
view.frames = nil
} else {
view.record = true
}
}
}
}
func drawBuffer(window *glfw.Window) {
w, h := window.GetFramebufferSize()
s1 := float32(w) / 256
s2 := float32(h) / 240
f := float32(1 - padding)
var x, y float32
if s1 >= s2 {
x = f * s2 / s1
y = f
} else {
x = f
y = f * s1 / s2
}
gl.Begin(gl.QUADS)
gl.TexCoord2f(0, 1)
gl.Vertex2f(-x, -y)
gl.TexCoord2f(1, 1)
gl.Vertex2f(x, -y)
gl.TexCoord2f(1, 0)
gl.Vertex2f(x, y)
gl.TexCoord2f(0, 0)
gl.Vertex2f(-x, y)
gl.End()
}
func updateControllers(window *glfw.Window, console *nes.Console) {
turbo := console.PPU.Frame%6 < 3
k1 := readKeys(window, turbo)
j1 := readJoystick(glfw.Joystick1, turbo)
j2 := readJoystick(glfw.Joystick2, turbo)
console.SetButtons1(combineButtons(k1, j1))
console.SetButtons2(j2)
}
func (view *GameView) updateControllers() {
// TODO: switch case
var buttons [8]bool
buttons[nes.ButtonLeft] = view.keyPressed[37]
buttons[nes.ButtonUp] = view.keyPressed[38]
buttons[nes.ButtonRight] = view.keyPressed[39]
buttons[nes.ButtonDown] = view.keyPressed[40]
buttons[nes.ButtonA] = view.keyPressed[32]
buttons[nes.ButtonB] = view.keyPressed[17]
buttons[nes.ButtonStart] = view.keyPressed[13]
buttons[nes.ButtonSelect] = view.keyPressed[16]
view.console.Controller1.SetButtons(buttons)
}