flightstick.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env python
  2. '''
  3. Demonstrate usage of flight stick
  4. In this sample you can use a flight stick to control the camera and show some
  5. messages on screen. You can accelerate using the throttle.
  6. '''
  7. from direct.showbase.ShowBase import ShowBase
  8. from panda3d.core import TextNode, InputDevice, loadPrcFileData, Vec3
  9. from direct.gui.OnscreenText import OnscreenText
  10. loadPrcFileData("", """
  11. default-fov 60
  12. notify-level-device debug
  13. """)
  14. STICK_DEAD_ZONE = 0.02
  15. THROTTLE_DEAD_ZONE = 0.02
  16. class App(ShowBase):
  17. def __init__(self):
  18. ShowBase.__init__(self)
  19. # Print all events sent through the messenger
  20. #self.messenger.toggleVerbose()
  21. self.lblWarning = OnscreenText(
  22. text = "No devices found",
  23. fg=(1,0,0,1),
  24. scale = .25)
  25. self.lblAction = OnscreenText(
  26. text = "Action",
  27. fg=(1,1,1,1),
  28. scale = .15)
  29. self.lblAction.hide()
  30. # Is there a gamepad connected?
  31. self.flightStick = None
  32. devices = self.devices.getDevices(InputDevice.DeviceClass.flight_stick)
  33. if devices:
  34. self.connect(devices[0])
  35. self.currentMoveSpeed = 0.0
  36. self.maxAccleration = 28.0
  37. self.deaccleration = 10.0
  38. self.deaclerationBreak = 37.0
  39. self.maxSpeed = 80.0
  40. # Accept device dis-/connection events
  41. self.accept("connect-device", self.connect)
  42. self.accept("disconnect-device", self.disconnect)
  43. self.accept("escape", exit)
  44. self.accept("flight_stick0-start", exit)
  45. # Accept button events of the first connected flight stick
  46. self.accept("flight_stick0-trigger", self.action, extraArgs=["Trigger"])
  47. self.accept("flight_stick0-trigger-up", self.actionUp)
  48. self.environment = loader.loadModel("environment")
  49. self.environment.reparentTo(render)
  50. # disable pandas default mouse-camera controls so we can handle the camera
  51. # movements by ourself
  52. self.disableMouse()
  53. self.reset()
  54. self.taskMgr.add(self.moveTask, "movement update task")
  55. def connect(self, device):
  56. """Event handler that is called when a device is discovered."""
  57. # We're only interested if this is a flight stick and we don't have a
  58. # flight stick yet.
  59. if device.device_class == InputDevice.DeviceClass.flight_stick and not self.flightStick:
  60. print("Found %s" % (device))
  61. self.flightStick = device
  62. # Enable this device to ShowBase so that we can receive events.
  63. # We set up the events with a prefix of "flight_stick0-".
  64. self.attachInputDevice(device, prefix="flight_stick0")
  65. # Hide the warning that we have no devices.
  66. self.lblWarning.hide()
  67. def disconnect(self, device):
  68. """Event handler that is called when a device is removed."""
  69. if self.flightStick != device:
  70. # We don't care since it's not our gamepad.
  71. return
  72. # Tell ShowBase that the device is no longer needed.
  73. print("Disconnected %s" % (device))
  74. self.detachInputDevice(device)
  75. self.flightStick = None
  76. # Do we have any other gamepads? Attach the first other gamepad.
  77. devices = self.devices.getDevices(InputDevice.DeviceClass.flight_stick)
  78. if devices:
  79. self.connect(devices[0])
  80. else:
  81. # No devices. Show the warning.
  82. self.lblWarning.show()
  83. def reset(self):
  84. """Reset the camera to the initial position."""
  85. self.camera.setPosHpr(0, -200, 10, 0, 0, 0)
  86. def action(self, button):
  87. # Just show which button has been pressed.
  88. self.lblAction.text = "Pressed %s" % button
  89. self.lblAction.show()
  90. def actionUp(self):
  91. # Hide the label showing which button is pressed.
  92. self.lblAction.hide()
  93. def moveTask(self, task):
  94. dt = base.clock.dt
  95. if not self.flightStick:
  96. return task.cont
  97. if self.currentMoveSpeed > 0:
  98. self.currentMoveSpeed -= dt * self.deaccleration
  99. if self.currentMoveSpeed < 0:
  100. self.currentMoveSpeed = 0
  101. # Accelerate using the throttle. Apply deadzone of 0.01.
  102. throttle = self.flightStick.findAxis(InputDevice.Axis.throttle).value
  103. if abs(throttle) < THROTTLE_DEAD_ZONE:
  104. throttle = 0
  105. accleration = throttle * self.maxAccleration
  106. if self.currentMoveSpeed > throttle * self.maxSpeed:
  107. self.currentMoveSpeed -= dt * self.deaccleration
  108. self.currentMoveSpeed += dt * accleration
  109. # Steering
  110. # Control the cameras yaw/Headding
  111. stick_yaw = self.flightStick.findAxis(InputDevice.Axis.yaw)
  112. if abs(stick_yaw.value) > STICK_DEAD_ZONE:
  113. base.camera.setH(base.camera, 100 * dt * stick_yaw.value)
  114. # Control the cameras pitch
  115. stick_y = self.flightStick.findAxis(InputDevice.Axis.pitch)
  116. if abs(stick_y.value) > STICK_DEAD_ZONE:
  117. base.camera.setP(base.camera, 100 * dt * stick_y.value)
  118. # Control the cameras roll
  119. stick_x = self.flightStick.findAxis(InputDevice.Axis.roll)
  120. if abs(stick_x.value) > STICK_DEAD_ZONE:
  121. base.camera.setR(base.camera, 100 * dt * stick_x.value)
  122. # calculate movement
  123. base.camera.setY(base.camera, dt * self.currentMoveSpeed)
  124. # Make sure camera does not go below the ground.
  125. if base.camera.getZ() < 1:
  126. base.camera.setZ(1)
  127. return task.cont
  128. app = App()
  129. app.run()