main.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Copyright 2015 Hajime Hoshi
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package main
  15. import (
  16. "fmt"
  17. "log"
  18. "sort"
  19. "strconv"
  20. "strings"
  21. "time"
  22. "github.com/hajimehoshi/ebiten/v2"
  23. "github.com/hajimehoshi/ebiten/v2/ebitenutil"
  24. "github.com/hajimehoshi/ebiten/v2/inpututil"
  25. )
  26. const (
  27. screenWidth = 640
  28. screenHeight = 480
  29. )
  30. type Game struct {
  31. gamepadIDsBuf []ebiten.GamepadID
  32. gamepadIDs map[ebiten.GamepadID]struct{}
  33. axes map[ebiten.GamepadID][]string
  34. pressedButtons map[ebiten.GamepadID][]string
  35. }
  36. func (g *Game) Update() error {
  37. if g.gamepadIDs == nil {
  38. g.gamepadIDs = map[ebiten.GamepadID]struct{}{}
  39. }
  40. // Log the gamepad connection events.
  41. g.gamepadIDsBuf = inpututil.AppendJustConnectedGamepadIDs(g.gamepadIDsBuf[:0])
  42. for _, id := range g.gamepadIDsBuf {
  43. log.Printf("gamepad connected: id: %d, SDL ID: %s", id, ebiten.GamepadSDLID(id))
  44. g.gamepadIDs[id] = struct{}{}
  45. }
  46. for id := range g.gamepadIDs {
  47. if inpututil.IsGamepadJustDisconnected(id) {
  48. log.Printf("gamepad disconnected: id: %d", id)
  49. delete(g.gamepadIDs, id)
  50. }
  51. }
  52. g.axes = map[ebiten.GamepadID][]string{}
  53. g.pressedButtons = map[ebiten.GamepadID][]string{}
  54. for id := range g.gamepadIDs {
  55. maxAxis := ebiten.GamepadAxisType(ebiten.GamepadAxisCount(id))
  56. for a := ebiten.GamepadAxisType(0); a < maxAxis; a++ {
  57. v := ebiten.GamepadAxisValue(id, a)
  58. g.axes[id] = append(g.axes[id], fmt.Sprintf("%d:%+0.2f", a, v))
  59. }
  60. maxButton := ebiten.GamepadButton(ebiten.GamepadButtonCount(id))
  61. for b := ebiten.GamepadButton(0); b < maxButton; b++ {
  62. if ebiten.IsGamepadButtonPressed(id, b) {
  63. g.pressedButtons[id] = append(g.pressedButtons[id], strconv.Itoa(int(b)))
  64. }
  65. // Log button events.
  66. if inpututil.IsGamepadButtonJustPressed(id, b) {
  67. log.Printf("button pressed: id: %d, button: %d", id, b)
  68. }
  69. if inpututil.IsGamepadButtonJustReleased(id, b) {
  70. log.Printf("button released: id: %d, button: %d", id, b)
  71. }
  72. }
  73. if ebiten.IsStandardGamepadLayoutAvailable(id) {
  74. for b := ebiten.StandardGamepadButton(0); b <= ebiten.StandardGamepadButtonMax; b++ {
  75. // Log button events.
  76. if inpututil.IsStandardGamepadButtonJustPressed(id, b) {
  77. var strong float64
  78. var weak float64
  79. switch b {
  80. case ebiten.StandardGamepadButtonLeftTop,
  81. ebiten.StandardGamepadButtonLeftLeft,
  82. ebiten.StandardGamepadButtonLeftRight,
  83. ebiten.StandardGamepadButtonLeftBottom:
  84. weak = 0.5
  85. case ebiten.StandardGamepadButtonRightTop,
  86. ebiten.StandardGamepadButtonRightLeft,
  87. ebiten.StandardGamepadButtonRightRight,
  88. ebiten.StandardGamepadButtonRightBottom:
  89. strong = 0.5
  90. }
  91. if strong > 0 || weak > 0 {
  92. op := &ebiten.VibrateGamepadOptions{
  93. Duration: 200 * time.Millisecond,
  94. StrongMagnitude: strong,
  95. WeakMagnitude: weak,
  96. }
  97. ebiten.VibrateGamepad(id, op)
  98. }
  99. log.Printf("standard button pressed: id: %d, button: %d", id, b)
  100. }
  101. if inpututil.IsStandardGamepadButtonJustReleased(id, b) {
  102. log.Printf("standard button released: id: %d, button: %d", id, b)
  103. }
  104. }
  105. }
  106. }
  107. return nil
  108. }
  109. var standardButtonToString = map[ebiten.StandardGamepadButton]string{
  110. ebiten.StandardGamepadButtonRightBottom: "RB",
  111. ebiten.StandardGamepadButtonRightRight: "RR",
  112. ebiten.StandardGamepadButtonRightLeft: "RL",
  113. ebiten.StandardGamepadButtonRightTop: "RT",
  114. ebiten.StandardGamepadButtonFrontTopLeft: "FTL",
  115. ebiten.StandardGamepadButtonFrontTopRight: "FTR",
  116. ebiten.StandardGamepadButtonFrontBottomLeft: "FBL",
  117. ebiten.StandardGamepadButtonFrontBottomRight: "FBR",
  118. ebiten.StandardGamepadButtonCenterLeft: "CL",
  119. ebiten.StandardGamepadButtonCenterRight: "CR",
  120. ebiten.StandardGamepadButtonLeftStick: "LS",
  121. ebiten.StandardGamepadButtonRightStick: "RS",
  122. ebiten.StandardGamepadButtonLeftBottom: "LB",
  123. ebiten.StandardGamepadButtonLeftRight: "LR",
  124. ebiten.StandardGamepadButtonLeftLeft: "LL",
  125. ebiten.StandardGamepadButtonLeftTop: "LT",
  126. ebiten.StandardGamepadButtonCenterCenter: "CC",
  127. }
  128. func standardMap(id ebiten.GamepadID) string {
  129. m := ` [FBL ] [FBR ]
  130. [FTL ] [FTR ]
  131. [LT ] [CC ] [RT ]
  132. [LL ][LR ] [CL ][CR ] [RL ][RR ]
  133. [LB ] [RB ]
  134. [LS ] [RS ]
  135. `
  136. for b, str := range standardButtonToString {
  137. placeholder := "[" + str + strings.Repeat(" ", 4-len(str)) + "]"
  138. v := ebiten.StandardGamepadButtonValue(id, b)
  139. switch {
  140. case !ebiten.IsStandardGamepadButtonAvailable(id, b):
  141. m = strings.Replace(m, placeholder, " -- ", 1)
  142. case ebiten.IsStandardGamepadButtonPressed(id, b):
  143. m = strings.Replace(m, placeholder, fmt.Sprintf("[%0.2f]", v), 1)
  144. default:
  145. m = strings.Replace(m, placeholder, fmt.Sprintf(" %0.2f ", v), 1)
  146. }
  147. }
  148. // TODO: Use ebiten.IsStandardGamepadAxisAvailable
  149. m += fmt.Sprintf(" Left Stick: X: %+0.2f, Y: %+0.2f\n Right Stick: X: %+0.2f, Y: %+0.2f",
  150. ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisLeftStickHorizontal),
  151. ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisLeftStickVertical),
  152. ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisRightStickHorizontal),
  153. ebiten.StandardGamepadAxisValue(id, ebiten.StandardGamepadAxisRightStickVertical))
  154. return m
  155. }
  156. func (g *Game) Draw(screen *ebiten.Image) {
  157. // Draw the current gamepad status.
  158. str := ""
  159. if len(g.gamepadIDs) > 0 {
  160. ids := make([]ebiten.GamepadID, 0, len(g.gamepadIDs))
  161. for id := range g.gamepadIDs {
  162. ids = append(ids, id)
  163. }
  164. sort.Slice(ids, func(a, b int) bool {
  165. return ids[a] < ids[b]
  166. })
  167. for _, id := range ids {
  168. var standard string
  169. if ebiten.IsStandardGamepadLayoutAvailable(id) {
  170. standard = " (Standard Layout)"
  171. }
  172. str += fmt.Sprintf("Gamepad (ID: %d, SDL ID: %s)%s:\n", id, ebiten.GamepadSDLID(id), standard)
  173. str += fmt.Sprintf(" Name: %s\n", ebiten.GamepadName(id))
  174. str += fmt.Sprintf(" Axes: %s\n", strings.Join(g.axes[id], ", "))
  175. str += fmt.Sprintf(" Buttons: %s\n", strings.Join(g.pressedButtons[id], ", "))
  176. if ebiten.IsStandardGamepadLayoutAvailable(id) {
  177. str += "\n"
  178. str += standardMap(id) + "\n"
  179. }
  180. str += "\n"
  181. }
  182. } else {
  183. str = "Please connect your gamepad."
  184. }
  185. ebitenutil.DebugPrint(screen, str)
  186. }
  187. func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
  188. return screenWidth, screenHeight
  189. }
  190. func main() {
  191. ebiten.SetWindowSize(screenWidth, screenHeight)
  192. ebiten.SetWindowTitle("Gamepad (Ebitengine Demo)")
  193. if err := ebiten.RunGame(&Game{}); err != nil {
  194. log.Fatal(err)
  195. }
  196. }