SDL2 GameController Support
This commit is contained in:
parent
9e640ab5c3
commit
1f4af682e1
|
@ -40,12 +40,18 @@ type State struct {
|
||||||
TouchCenterY int
|
TouchCenterY int
|
||||||
GestureRotated float64
|
GestureRotated float64
|
||||||
GesturePinched float64
|
GesturePinched float64
|
||||||
|
|
||||||
|
// Game controller events.
|
||||||
|
// NOTE: for SDL2 you will need to call GameControllerEventState(1)
|
||||||
|
// from veandco/go-sdl2/sdl for events to be read by SDL2.
|
||||||
|
Controllers map[int]GameController
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewState creates a new event.State.
|
// NewState creates a new event.State.
|
||||||
func NewState() *State {
|
func NewState() *State {
|
||||||
return &State{
|
return &State{
|
||||||
keydown: map[string]interface{}{},
|
keydown: map[string]interface{}{},
|
||||||
|
Controllers: map[int]GameController{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,3 +124,30 @@ var shiftMap = map[string]string{
|
||||||
".": ">",
|
".": ">",
|
||||||
"/": "?",
|
"/": "?",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddController adds a new controller to the event state. This is typically called
|
||||||
|
// automatically by the render engine, e.g. on an SDL ControllerDeviceEvent.
|
||||||
|
func (s *State) AddController(index int, v GameController) bool {
|
||||||
|
if _, ok := s.Controllers[index]; ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s.Controllers[index] = v
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveController removes the available controller.
|
||||||
|
func (s *State) RemoveController(index int) bool {
|
||||||
|
if _, ok := s.Controllers[index]; ok {
|
||||||
|
delete(s.Controllers, index)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetController gets a registered controller by index.
|
||||||
|
func (s *State) GetController(index int) (GameController, bool) {
|
||||||
|
if c, ok := s.Controllers[index]; ok {
|
||||||
|
return c, true
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
41
event/game_controller.go
Normal file
41
event/game_controller.go
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
// GameController holds event state for one or more (Xbox-style) controllers.
|
||||||
|
type GameController interface {
|
||||||
|
ID() int // Usually the controller index number
|
||||||
|
Name() string // Friendly name of the controller
|
||||||
|
|
||||||
|
// State setters, to be called by the engine.
|
||||||
|
// Note: button names are implementation-specific, use Button*() methods in your code.
|
||||||
|
SetButtonState(name string, pressed bool)
|
||||||
|
GetButtonState(name string) bool
|
||||||
|
SetAxisState(name string, value int) // value maybe -32768 to 32767
|
||||||
|
|
||||||
|
// State getters.
|
||||||
|
ButtonA() bool
|
||||||
|
ButtonB() bool
|
||||||
|
ButtonX() bool
|
||||||
|
ButtonY() bool
|
||||||
|
ButtonL1() bool // Left shoulder
|
||||||
|
ButtonR1() bool // Right shoulder
|
||||||
|
ButtonL2() bool // Left trigger (digital)
|
||||||
|
ButtonR2() bool // Right trigger (digital)
|
||||||
|
ButtonLStick() bool
|
||||||
|
ButtonRStick() bool
|
||||||
|
ButtonStart() bool
|
||||||
|
ButtonSelect() bool // Back button
|
||||||
|
ButtonHome() bool // Guide button
|
||||||
|
|
||||||
|
// D-Pad buttons.
|
||||||
|
ButtonUp() bool
|
||||||
|
ButtonLeft() bool
|
||||||
|
ButtonRight() bool
|
||||||
|
ButtonDown() bool
|
||||||
|
|
||||||
|
// Axis getters. Returns Vectors ranging from -1.0 to 1.0 being a
|
||||||
|
// percentage of the axis between neutral and maxed out.
|
||||||
|
LeftStick() Vector
|
||||||
|
RightStick() Vector
|
||||||
|
LeftTrigger() float64
|
||||||
|
RightTrigger() float64
|
||||||
|
}
|
7
event/vector.go
Normal file
7
event/vector.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package event
|
||||||
|
|
||||||
|
// Vector holds a floating point vector along an X and Y axis.
|
||||||
|
type Vector struct {
|
||||||
|
X float64
|
||||||
|
Y float64
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ var (
|
||||||
DebugMouseEvents = false
|
DebugMouseEvents = false
|
||||||
DebugClickEvents = false
|
DebugClickEvents = false
|
||||||
DebugKeyEvents = false
|
DebugKeyEvents = false
|
||||||
|
DebugControllerEvents = false
|
||||||
)
|
)
|
||||||
|
|
||||||
// Poll for events.
|
// Poll for events.
|
||||||
|
@ -39,7 +40,7 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
if t.Event == sdl.WINDOWEVENT_RESIZED {
|
if t.Event == sdl.WINDOWEVENT_RESIZED {
|
||||||
fmt.Printf("[%d ms] tick:%d Window Resized to %dx%d\n",
|
fmt.Printf("[%d ms] tick:%d Window Resized to %dx%d\n",
|
||||||
t.Timestamp,
|
t.Timestamp,
|
||||||
r.ticks,
|
sdl.GetTicks(),
|
||||||
t.Data1,
|
t.Data1,
|
||||||
t.Data2,
|
t.Data2,
|
||||||
)
|
)
|
||||||
|
@ -52,7 +53,7 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
case *sdl.MouseMotionEvent:
|
case *sdl.MouseMotionEvent:
|
||||||
if DebugMouseEvents {
|
if DebugMouseEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MouseMotion type:%d id:%d x:%d y:%d xrel:%d yrel:%d\n",
|
fmt.Printf("[%d ms] tick:%d MouseMotion type:%d id:%d x:%d y:%d xrel:%d yrel:%d\n",
|
||||||
t.Timestamp, r.ticks, t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel,
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Which, t.X, t.Y, t.XRel, t.YRel,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
case *sdl.MouseButtonEvent:
|
case *sdl.MouseButtonEvent:
|
||||||
if DebugClickEvents {
|
if DebugClickEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MouseButton type:%d id:%d x:%d y:%d button:%d state:%d\n",
|
fmt.Printf("[%d ms] tick:%d MouseButton type:%d id:%d x:%d y:%d button:%d state:%d\n",
|
||||||
t.Timestamp, r.ticks, t.Type, t.Which, t.X, t.Y, t.Button, t.State,
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Which, t.X, t.Y, t.Button, t.State,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,13 +105,13 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
case *sdl.MouseWheelEvent:
|
case *sdl.MouseWheelEvent:
|
||||||
if DebugMouseEvents {
|
if DebugMouseEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MouseWheel type:%d id:%d x:%d y:%d\n",
|
fmt.Printf("[%d ms] tick:%d MouseWheel type:%d id:%d x:%d y:%d\n",
|
||||||
t.Timestamp, r.ticks, t.Type, t.Which, t.X, t.Y,
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Which, t.X, t.Y,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
case *sdl.MultiGestureEvent:
|
case *sdl.MultiGestureEvent:
|
||||||
if DebugTouchEvents {
|
if DebugTouchEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d MultiGesture type:%d Num=%d TouchID=%+v Dt=%f Dd=%f XY=%f,%f\n",
|
fmt.Printf("[%d ms] tick:%d MultiGesture type:%d Num=%d TouchID=%+v Dt=%f Dd=%f XY=%f,%f\n",
|
||||||
t.Timestamp, r.ticks, t.Type, t.NumFingers, t.TouchID, t.DTheta, t.DDist, t.X, t.Y,
|
t.Timestamp, sdl.GetTicks(), t.Type, t.NumFingers, t.TouchID, t.DTheta, t.DDist, t.X, t.Y,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
s.Touching = true
|
s.Touching = true
|
||||||
|
@ -122,7 +123,7 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
case *sdl.KeyboardEvent:
|
case *sdl.KeyboardEvent:
|
||||||
if DebugKeyEvents {
|
if DebugKeyEvents {
|
||||||
fmt.Printf("[%d ms] tick:%d Keyboard type:%d sym:%c modifiers:%d state:%d repeat:%d\n",
|
fmt.Printf("[%d ms] tick:%d Keyboard type:%d sym:%c modifiers:%d state:%d repeat:%d\n",
|
||||||
t.Timestamp, r.ticks, t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat,
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Keysym.Sym, t.Keysym.Mod, t.State, t.Repeat,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +191,80 @@ func (r *Renderer) Poll() (*event.State, error) {
|
||||||
// Push the string value of the key.
|
// Push the string value of the key.
|
||||||
s.SetKeyDown(string(t.Keysym.Sym), t.State == 1 || t.Repeat == 1)
|
s.SetKeyDown(string(t.Keysym.Sym), t.State == 1 || t.Repeat == 1)
|
||||||
}
|
}
|
||||||
|
case *sdl.ControllerDeviceEvent:
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d ControllerDevice type:%d timestamp:%d which:%d\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Timestamp, t.Which,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var index = int(t.Which)
|
||||||
|
|
||||||
|
// Update the catalog of available controllers.
|
||||||
|
switch t.Type {
|
||||||
|
case sdl.CONTROLLERDEVICEADDED:
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d AddController: %s\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), sdl.GameControllerNameForIndex(index),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add and open the GameController.
|
||||||
|
var (
|
||||||
|
name = sdl.GameControllerNameForIndex(index)
|
||||||
|
ctrlImpl = sdl.GameControllerOpen(index)
|
||||||
|
ctrl = NewGameController(index, name, ctrlImpl)
|
||||||
|
)
|
||||||
|
s.AddController(index, ctrl)
|
||||||
|
case sdl.CONTROLLERDEVICEREMOVED:
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d RemoveController: %s\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), sdl.GameControllerNameForIndex(index),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
s.RemoveController(index)
|
||||||
|
}
|
||||||
|
case *sdl.ControllerButtonEvent:
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d ControllerButton type:%d timestamp:%d which:%d btn:%d state:%d\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Timestamp, t.Which, t.Button, t.State,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = int(t.Which)
|
||||||
|
buttonName = sdl.GameControllerGetStringForButton(sdl.GameControllerButton(t.Button))
|
||||||
|
)
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d ControllerButton: index:%d name:%s pressed:%d\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), index, buttonName, t.State,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrl, ok := s.GetController(index); ok {
|
||||||
|
ctrl.SetButtonState(buttonName, t.State == sdl.PRESSED)
|
||||||
|
}
|
||||||
|
case *sdl.ControllerAxisEvent:
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d ControllerAxis type:%d timestamp:%d which:%d axis:%d value:%d\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), t.Type, t.Timestamp, t.Which, t.Axis, t.Value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
index = int(t.Which)
|
||||||
|
axisName = sdl.GameControllerGetStringForAxis(sdl.GameControllerAxis(t.Axis))
|
||||||
|
value = int(t.Value)
|
||||||
|
)
|
||||||
|
if DebugControllerEvents {
|
||||||
|
fmt.Printf("[%d ms] tick:%d ControllerAxis: index:%d name:%s value:%d\n",
|
||||||
|
t.Timestamp, sdl.GetTicks(), index, axisName, value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctrl, ok := s.GetController(index); ok {
|
||||||
|
ctrl.SetAxisState(axisName, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
199
sdl/game_controller.go
Normal file
199
sdl/game_controller.go
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
package sdl
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.kirsle.net/go/render/event"
|
||||||
|
"github.com/veandco/go-sdl2/sdl"
|
||||||
|
)
|
||||||
|
|
||||||
|
// User tuneable properties.
|
||||||
|
var (
|
||||||
|
// For controllers having a digital (non-analog) Left/Right Trigger, the press percentage
|
||||||
|
// for which to consider it a boolean press.
|
||||||
|
TriggerAxisBooleanThreshold float64 = 0.5
|
||||||
|
)
|
||||||
|
|
||||||
|
// GameController holds an abstraction around SDL2 GameControllers.
|
||||||
|
type GameController struct {
|
||||||
|
id int
|
||||||
|
name string
|
||||||
|
active bool
|
||||||
|
|
||||||
|
// Underlying SDL2 GameController.
|
||||||
|
ctrl *sdl.GameController
|
||||||
|
|
||||||
|
// Button states.
|
||||||
|
buttons map[string]bool
|
||||||
|
axes map[string]int
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewGameController creates a GameController from an SDL2 controller.
|
||||||
|
func NewGameController(index int, name string, ctrl *sdl.GameController) *GameController {
|
||||||
|
return &GameController{
|
||||||
|
id: index,
|
||||||
|
name: name,
|
||||||
|
ctrl: ctrl,
|
||||||
|
buttons: map[string]bool{},
|
||||||
|
axes: map[string]int{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the controller index as SDL2 knows it.
|
||||||
|
func (gc *GameController) ID() int {
|
||||||
|
return gc.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name returns the controller name.
|
||||||
|
func (gc *GameController) Name() string {
|
||||||
|
return gc.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetButtonState sets the state using the SDL2 button names.
|
||||||
|
func (gc *GameController) SetButtonState(name string, pressed bool) {
|
||||||
|
gc.buttons[name] = pressed
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetButtonState returns the button state by SDL2 button name.
|
||||||
|
func (gc *GameController) GetButtonState(name string) bool {
|
||||||
|
if v, ok := gc.buttons[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetAxisState sets the axis state.
|
||||||
|
func (gc *GameController) SetAxisState(name string, value int) {
|
||||||
|
gc.axes[name] = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAxisState returns the underlying SDL2 axis state.
|
||||||
|
func (gc *GameController) GetAxisState(name string) int {
|
||||||
|
if v, ok := gc.axes[name]; ok {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonA returns whether the logical Xbox button is pressed.
|
||||||
|
func (gc *GameController) ButtonA() bool {
|
||||||
|
return gc.GetButtonState("a")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonB returns whether the logical Xbox button is pressed.
|
||||||
|
func (gc *GameController) ButtonB() bool {
|
||||||
|
return gc.GetButtonState("b")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonX returns whether the logical Xbox button is pressed.
|
||||||
|
func (gc *GameController) ButtonX() bool {
|
||||||
|
return gc.GetButtonState("x")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonY returns whether the logical Xbox button is pressed.
|
||||||
|
func (gc *GameController) ButtonY() bool {
|
||||||
|
return gc.GetButtonState("y")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonL1 returns whether the Left Shoulder button is pressed.
|
||||||
|
func (gc *GameController) ButtonL1() bool {
|
||||||
|
return gc.GetButtonState("leftshoulder")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonR1 returns whether the Right Shoulder button is pressed.
|
||||||
|
func (gc *GameController) ButtonR1() bool {
|
||||||
|
return gc.GetButtonState("rightshoulder")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonL2 returns whether the Left Trigger (digital) button is pressed.
|
||||||
|
// Returns true if the LeftTrigger is 50% pressed or TriggerAxisBooleanThreshold.
|
||||||
|
func (gc *GameController) ButtonL2() bool {
|
||||||
|
return gc.axisToFloat("lefttrigger") > TriggerAxisBooleanThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonR2 returns whether the Left Trigger (digital) button is pressed.
|
||||||
|
// Returns true if the LeftTrigger is 50% pressed or TriggerAxisBooleanThreshold.
|
||||||
|
func (gc *GameController) ButtonR2() bool {
|
||||||
|
return gc.axisToFloat("righttrigger") > TriggerAxisBooleanThreshold
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonLStick returns whether the Left Stick button is pressed.
|
||||||
|
func (gc *GameController) ButtonLStick() bool {
|
||||||
|
return gc.GetButtonState("leftstick")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonRStick returns whether the Right Stick button is pressed.
|
||||||
|
func (gc *GameController) ButtonRStick() bool {
|
||||||
|
return gc.GetButtonState("rightstick")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonStart returns whether the logical Xbox button is pressed.
|
||||||
|
func (gc *GameController) ButtonStart() bool {
|
||||||
|
return gc.GetButtonState("start")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonSelect returns whether the Xbox "back" button is pressed.
|
||||||
|
func (gc *GameController) ButtonSelect() bool {
|
||||||
|
return gc.GetButtonState("back")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonUp returns whether the Xbox D-Pad button is pressed.
|
||||||
|
func (gc *GameController) ButtonUp() bool {
|
||||||
|
return gc.GetButtonState("dpup")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonDown returns whether the Xbox D-Pad button is pressed.
|
||||||
|
func (gc *GameController) ButtonDown() bool {
|
||||||
|
return gc.GetButtonState("dpdown")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonLeft returns whether the Xbox D-Pad button is pressed.
|
||||||
|
func (gc *GameController) ButtonLeft() bool {
|
||||||
|
return gc.GetButtonState("dpleft")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonRight returns whether the Xbox D-Pad button is pressed.
|
||||||
|
func (gc *GameController) ButtonRight() bool {
|
||||||
|
return gc.GetButtonState("dpright")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ButtonHome returns whether the Xbox "guide" button is pressed.
|
||||||
|
func (gc *GameController) ButtonHome() bool {
|
||||||
|
return gc.GetButtonState("guide")
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftStick returns the vector of X and Y of the left analog stick.
|
||||||
|
func (gc *GameController) LeftStick() event.Vector {
|
||||||
|
return event.Vector{
|
||||||
|
X: gc.axisToFloat("leftx"),
|
||||||
|
Y: gc.axisToFloat("lefty"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RightStick returns the vector of X and Y of the right analog stick.
|
||||||
|
func (gc *GameController) RightStick() event.Vector {
|
||||||
|
return event.Vector{
|
||||||
|
X: gc.axisToFloat("rightx"),
|
||||||
|
Y: gc.axisToFloat("righty"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LeftTrigger returns the vector of the left analog trigger.
|
||||||
|
func (gc *GameController) LeftTrigger() float64 {
|
||||||
|
return gc.axisToFloat("lefttrigger")
|
||||||
|
}
|
||||||
|
|
||||||
|
// RightTrigger returns the vector of the left analog trigger.
|
||||||
|
func (gc *GameController) RightTrigger() float64 {
|
||||||
|
return gc.axisToFloat("righttrigger")
|
||||||
|
}
|
||||||
|
|
||||||
|
// axisToFloat converts an SDL2 Axis value to a float between -1.0..1.0
|
||||||
|
func (gc *GameController) axisToFloat(name string) float64 {
|
||||||
|
// SDL2 Axis is an int16 ranging from -32768 to 32767,
|
||||||
|
// convert this into a percentage +- 0 to 1.
|
||||||
|
axis := gc.GetAxisState(name)
|
||||||
|
if axis < 0 {
|
||||||
|
return float64(axis) / 32768
|
||||||
|
} else {
|
||||||
|
return float64(axis) / 32767
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image"
|
"image"
|
||||||
"time"
|
|
||||||
|
|
||||||
"git.kirsle.net/go/render"
|
"git.kirsle.net/go/render"
|
||||||
"git.kirsle.net/go/render/event"
|
"git.kirsle.net/go/render/event"
|
||||||
|
@ -20,14 +19,11 @@ type Renderer struct {
|
||||||
title string
|
title string
|
||||||
width int32
|
width int32
|
||||||
height int32
|
height int32
|
||||||
startTime time.Time
|
|
||||||
|
|
||||||
// Private fields.
|
// Private fields.
|
||||||
events *event.State
|
events *event.State
|
||||||
window *sdl.Window
|
window *sdl.Window
|
||||||
renderer *sdl.Renderer
|
renderer *sdl.Renderer
|
||||||
running bool
|
|
||||||
ticks uint64
|
|
||||||
textures map[string]*Texture // cached textures
|
textures map[string]*Texture // cached textures
|
||||||
|
|
||||||
// Optimizations to minimize SDL calls.
|
// Optimizations to minimize SDL calls.
|
||||||
|
|
|
@ -52,6 +52,8 @@ func LoadFont(filename string, size int) (*ttf.Font, error) {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fontsMu.Lock()
|
||||||
|
defer fontsMu.Unlock()
|
||||||
if binary, ok := installedFont[filename]; ok {
|
if binary, ok := installedFont[filename]; ok {
|
||||||
var RWops *sdl.RWops
|
var RWops *sdl.RWops
|
||||||
RWops, err = sdl.RWFromMem(binary)
|
RWops, err = sdl.RWFromMem(binary)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user