player.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. ########################################################################
  2. # Hello Worlds - Libre 3D RPG game.
  3. # Copyright (C) 2020 CYBERDEViL
  4. #
  5. # This file is part of Hello Worlds.
  6. #
  7. # Hello Worlds is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Hello Worlds is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. # Panda3d
  22. from panda3d.core import Vec3
  23. from panda3d.core import PandaNode, NodePath, TextNode
  24. from panda3d.core import Camera, OrthographicLens, PGTop
  25. from direct.showbase import DirectObject
  26. # Local
  27. from core.db import Maps, AssetsPath
  28. from core.character import Character
  29. import os
  30. class MiniMap(DirectObject.DirectObject):
  31. def __init__(self, mapId):
  32. self._mapId = mapId
  33. # Create 2d display stuff
  34. self.dr = base.win.makeDisplayRegion()
  35. self.dr.setSort(20)
  36. self.myCamera2d = NodePath(Camera('myCam2d'))
  37. lens = OrthographicLens()
  38. lens.setFilmSize(2, 2)
  39. lens.setNearFar(-1000, 1000)
  40. self.myCamera2d.node().setLens(lens)
  41. self.myRender2d = NodePath('myRender2d')
  42. self.myRender2d.setDepthTest(False)
  43. self.myRender2d.setDepthWrite(False)
  44. self.myCamera2d.reparentTo(self.myRender2d)
  45. self.dr.setCamera(self.myCamera2d)
  46. self._aspectRatio = base.getAspectRatio()
  47. self.myAspect2d = self.myRender2d.attachNewNode(PGTop('myAspect2d'))
  48. self.myAspect2d.setScale(1.0 / self._aspectRatio, 1.0, 1.0)
  49. # we now get buffer thats going to hold the texture of our new scene
  50. #self.mapWidth = Maps[mapId].width
  51. #self.mapHeight = Maps[mapId].height
  52. self.mapWidth = 100
  53. self.mapHeight = 100 # TODO
  54. self.mapWidthRatio = self.mapWidth / self.mapHeight
  55. self.mapHeightRatio = self.mapHeight / self.mapWidth
  56. if self.mapWidthRatio > 1: self.mapHeightRatio = 1
  57. else: self.mapWidthRatio = 1
  58. self.textureBuffer = base.win.makeTextureBuffer("miniMapBuffer", 256, 256)
  59. # now we have to setup a new scene graph to make this scene
  60. self.miniMapRender = NodePath("miniMapRender")
  61. # this takes care of setting up ther camera properly
  62. self.altCam = base.makeCamera(self.textureBuffer)
  63. self.altCam.reparentTo(self.miniMapRender)
  64. self.altCam.setPos(0, -24, 0)
  65. self._2dMap = loader.loadModel(
  66. Maps[mapId].orthoFilePath
  67. )
  68. self._2dMap.setScale(self.mapWidthRatio, 1, self.mapHeightRatio)
  69. self._2dMap.reparentTo(self.miniMapRender)
  70. self.altCam.lookAt(self._2dMap)
  71. self._model = loader.loadModel(os.path.join(AssetsPath.widgets, "miniMap.egg"))
  72. self._model.reparentTo(self.myAspect2d)
  73. self._model.setPos(-1.50, 0, 0.7)
  74. self.resize()
  75. projectionObj = self._model.find("**/miniMap")
  76. tex = self.textureBuffer.getTexture()
  77. projectionObj.setTexture(tex, 1)
  78. projectionObj.reparentTo(self._model)
  79. # Player head
  80. self._playerHead = self._model.find("**/miniMapHead")
  81. self._playerHead.reparentTo(self._model)
  82. # Zoom buttons
  83. self._zoomInButton = self._model.find("**/miniMapZoomIn")
  84. self._zoomOutButton = self._model.find("**/miniMapZoomOut")
  85. self._zoomInButton.reparentTo(self._model)
  86. self._zoomOutButton.reparentTo(self._model)
  87. self.accept("m", self.zoomIn)
  88. self.accept("n", self.zoomOut)
  89. self.accept("b", self.resize)
  90. self.accept("v", base.bufferViewer.toggleEnable)
  91. base.bufferViewer.setPosition("llcorner")
  92. base.bufferViewer.setCardSize(1.0, 0.0)
  93. base.mouseHandler.connect('mouse1', self._onLeftMouseClick, priority=1)
  94. #base.mouseHandler.connect('wheel_up', self._onLeftMouseClick, priority=1)
  95. #base.mouseHandler.connect('wheel_down', self._onLeftMouseClick, priority=1)
  96. self.accept('WINDOW_RESIZED', self.resize)
  97. def __del__(self):
  98. print("Destroyed MiniMap")
  99. """Events
  100. """
  101. def resize(self):
  102. """ Keep the minimap always the same size.
  103. """
  104. # Size of the miniMap-frame as reference
  105. blenderUnitWidth = 0.5
  106. blenderUnitHeight = 0.5
  107. screenWidth = base.win.getProperties().getXSize()
  108. screenHeight = base.win.getProperties().getYSize()
  109. ratio = base.getAspectRatio()
  110. zeroXPx = screenWidth / 2
  111. zeroZPx = screenHeight / 2
  112. oneUnitPerPixelX = ratio / zeroXPx
  113. oneUnitPerPixelZ = 1 / zeroZPx
  114. wantPixelsWidth = 175
  115. wantPixelsHeight = 175
  116. currentWidthPx = blenderUnitWidth / oneUnitPerPixelX
  117. currentHeightPx = blenderUnitHeight / oneUnitPerPixelZ
  118. widthScale = wantPixelsWidth / currentWidthPx
  119. heightScale = wantPixelsHeight / currentHeightPx
  120. self._model.setScale(widthScale, 1, heightScale)
  121. # Now re-position (TODO re-evaluate this method)
  122. wantPixelsTop = 25
  123. wantPixelsLeft = 15
  124. topPx = 1 - ((wantPixelsTop + (wantPixelsHeight / 2)) * oneUnitPerPixelZ)
  125. leftPx = ratio - ((wantPixelsLeft + (currentWidthPx / 2)) * oneUnitPerPixelX) # move to right
  126. self._model.setPos(leftPx, 0, topPx)
  127. def destroy(self):
  128. self.ignoreAll()
  129. self.removeAllTasks()
  130. loader.unloadModel(self._model)
  131. self._model.removeNode()
  132. del self._model
  133. self._model = None
  134. loader.unloadModel(self._2dMap)
  135. del self._2dMap
  136. self._2dMap = None
  137. self.altCam.removeNode()
  138. self.altCam = None
  139. self.myCamera2d.removeNode()
  140. self.myCamera2d = None
  141. self.myRender2d.removeNode()
  142. self.myRender2d = None
  143. self.myAspect2d.removeNode()
  144. self.myAspect2d = None
  145. self.miniMapRender.removeNode()
  146. self.miniMapRender = None
  147. base.graphicsEngine.removeWindow(self.textureBuffer)
  148. self.textureBuffer = None
  149. self.dr = None
  150. def setPos(self, pos):
  151. self._onPlayerPositionUpdateEvent(pos)
  152. def setOrientation(self, omega):
  153. self.altCam.setR(omega)
  154. def modOrientation(self, omega):
  155. self._onPlayerRotateEvent(omega)
  156. def _onPlayerRotateEvent(self, omega):
  157. self.altCam.setR(self.altCam, -omega)
  158. def _onPlayerPositionUpdateEvent(self, characterPos):
  159. self.altCam.setX(((characterPos[0] / self.mapWidth) * 16) * self.mapWidthRatio) # 2d map == 16x16 blender units
  160. self.altCam.setZ(((characterPos[1] / self.mapHeight) * 16) * self.mapHeightRatio)
  161. def _onLeftMouseClick(self, args=[]):
  162. mpos = base.mouseWatcherNode.getMouse()
  163. mousePos = (mpos.getX() * self._aspectRatio, mpos.getY())
  164. zoomInButtonPos = (
  165. ((self._model.getX() + self._zoomInButton.getX())),
  166. self._model.getZ() + self._zoomInButton.getZ()
  167. );
  168. zoomOutButtonPos = (
  169. ((self._model.getX() + self._zoomOutButton.getX())),
  170. self._model.getZ() + self._zoomOutButton.getZ()
  171. );
  172. margin = 0.03
  173. if (mousePos[0] + margin >= zoomInButtonPos[0]
  174. and mousePos[0] - margin <= zoomInButtonPos[0]
  175. and mousePos[1] + margin >= zoomInButtonPos[1]
  176. and mousePos[1] - margin <= zoomInButtonPos[1]):
  177. self.zoomIn()
  178. return True
  179. elif (mousePos[0] + margin >= zoomOutButtonPos[0]
  180. and mousePos[0] - margin <= zoomOutButtonPos[0]
  181. and mousePos[1] + margin >= zoomOutButtonPos[1]
  182. and mousePos[1] - margin <= zoomOutButtonPos[1]):
  183. self.zoomOut()
  184. return True
  185. else: return False
  186. @property
  187. def camera(self): return self.altCam
  188. # TODO it makes different on how large a map is (-4 * mapRatio?)
  189. def zoomIn(self):
  190. if self.altCam.getY() < (-24):
  191. self.altCam.setY(self.altCam, 1)
  192. return True
  193. return False
  194. # TODO it makes different on how large a map is (-96 * mapRatio?)
  195. def zoomOut(self):
  196. if self.altCam.getY() > (-128):
  197. self.altCam.setY(self.altCam, -1)
  198. return True
  199. return False
  200. class InputLocker(DirectObject.DirectObject):
  201. def __init__(self):
  202. self._lockInput = False
  203. self.accept('lockInput', self._setLockInput)
  204. def _setLockInput(self, state):
  205. self._lockInput = state
  206. def locked(self): return self._lockInput
  207. class PlayerCharacter(Character):
  208. def __init__(self, world, worldNP, characterModel):
  209. Character.__init__(self, world, worldNP, characterModel)
  210. class PlayerController:
  211. def __init__(self, character=None, mapId=None):
  212. """
  213. @type character: CharacterProto or None
  214. @param character:
  215. """
  216. self._character = None
  217. self.miniMap = None
  218. self.character = character
  219. self.mapId = mapId
  220. self.keyMap = {
  221. "shuffleLeft": 0,
  222. "shuffleRight": 0,
  223. "forward": 0,
  224. "backward": 0,
  225. "jump": 0,
  226. "walk": 0,
  227. "rotateLeft": 0,
  228. "rotateRight": 0,
  229. "cameraUp": 0,
  230. "cameraDown" : 0,
  231. "leftMouse" : 0,
  232. "rightMouse" : 0
  233. }
  234. self._previousKeyMap = self.keyMap.copy()
  235. base.accept('space', self.setKey, ["jump", True])
  236. #base.accept('c', self.doCrouch)
  237. base.accept("a", self.setKey, ["shuffleLeft", True])
  238. base.accept("d", self.setKey, ["shuffleRight", True])
  239. base.accept("w", self.setKey, ["forward", True])
  240. base.accept("W", self.setKey, ["walk", True])
  241. base.accept("shift", self.setKey, ["walk", True])
  242. base.accept("s", self.setKey, ["backward", True])
  243. base.accept("q", self.setKey, ["rotateLeft", True])
  244. base.accept("e", self.setKey, ["rotateRight", True])
  245. base.accept("r", self.setKey, ["cameraUp", True])
  246. base.accept("f", self.setKey, ["cameraDown", True])
  247. base.accept("a-up", self.setKey, ["shuffleLeft", False])
  248. base.accept("d-up", self.setKey, ["shuffleRight", False])
  249. base.accept("w-up", self.setKey, ["forward", False])
  250. base.accept("W-up", self.setKey, ["walk", False])
  251. base.accept("shift-up", self.setKey, ["walk", False])
  252. base.accept("s-up", self.setKey, ["backward", False])
  253. base.accept("q-up", self.setKey, ["rotateLeft", False])
  254. base.accept("e-up", self.setKey, ["rotateRight", False])
  255. base.accept("r-up", self.setKey, ["cameraUp", False])
  256. base.accept("f-up", self.setKey, ["cameraDown", False])
  257. base.accept("p", self.toggleCharacter) # TODO this is a test
  258. self._mouseEvents = {
  259. "leftJustClicked" : True,
  260. "rightJustClicked" : True
  261. }
  262. self._cursorBackup = [0, 0]
  263. self._cursorPrevPos = [0, 0]
  264. self._currentCameraAngle = [0, 0]
  265. self._cursorBusy = False
  266. self._cameraZoomLevel = 2.0
  267. self._cameraZoomMax = 20
  268. self._cameraZoomMin = 0
  269. self._cameraHorizontalAngle = 0;
  270. self._cameraVerticalAngle = 0;
  271. base.mouseHandler.connect('mouse1', self.setKey, args=["leftMouse", True], priority=10)
  272. base.mouseHandler.connect('mouse1-up', self.setKey, args=["leftMouse", False], priority=10)
  273. base.mouseHandler.connect('mouse3', self.setKey, args=["rightMouse", True], priority=10)
  274. base.mouseHandler.connect('mouse3-up', self.setKey, args=["rightMouse", False], priority=10)
  275. base.mouseHandler.connect('wheel_up', self.mouseWheelUp, priority=10)
  276. base.mouseHandler.connect('wheel_down', self.mouseWheelDown, priority=10)
  277. self._cursorBackup = [0, 0]
  278. self._cursorPrevPos = [0, 0]
  279. self._cameraZoomLevel = 2.0
  280. self._cameraZoomMax = 20
  281. self._cameraZoomMin = 0
  282. self._cameraHorizontalAngle = 0
  283. self._cameraVerticalAngle = 0
  284. self._inputLocker = InputLocker()
  285. self._inputChanged = False
  286. self._orientationChanged = False
  287. self._movingAnimation = ""
  288. self.setup()
  289. def toggleCharacter(self):
  290. """ This is here for testing.
  291. """
  292. if base.world.player:
  293. if self.character == base.world.player:
  294. selectedId = base.world.npcsManager.selectedNpcModel.selectedId
  295. npc = base.world.npcsManager.getSpawn(selectedId)
  296. self.character = npc
  297. else:
  298. self.character = base.world.player
  299. base.uiManager.characterChanged()
  300. def setup(self):
  301. # Character camera
  302. self.floater = NodePath(PandaNode("floater"))
  303. self.camFloater = NodePath(PandaNode("camFloater"))
  304. self.camFloater.reparentTo(self.floater)
  305. self.camFloater.setPos(0, -5, 0.6)
  306. # Player name node
  307. # TODO more dynamic height
  308. self.characterName = TextNode('characterName')
  309. self.characterNameNP = self.floater.attachNewNode(self.characterName)
  310. self.characterNameNP.setScale(0.1)
  311. self._attach()
  312. base.camera.lookAt( 0, 0, 0 )
  313. def destroy(self):
  314. taskMgr.remove('userInteract')
  315. self.floater.removeNode()
  316. self.camFloater.removeNode()
  317. self.characterNameNP.removeNode()
  318. if self.miniMap:
  319. self._destroyMiniMap()
  320. def _destroyMiniMap(self):
  321. self.miniMap.destroy()
  322. self.miniMap = None
  323. def _attach(self):
  324. if self.character:
  325. self.floater.detachNode()
  326. self.floater.reparentTo(self.character.characterNP)
  327. self.floater.setZ(self.character.characterNP, 1.2) # Set floater height TODO make dynamic
  328. self.characterNameNP.setPos((0.1, .1, 0.3))
  329. base.camera.reparentTo(self.camFloater)
  330. self.characterName.setText(self.character.characterData.name)
  331. self.miniMap.setOrientation(self.character.getOrientation())
  332. @property
  333. def character(self): return self._character
  334. @character.setter
  335. def character(self, character):
  336. """
  337. @type character: CharacterProto or None
  338. @param character:
  339. """
  340. if self._character:
  341. taskMgr.remove('userInteract')
  342. self._character.hasDied.disconnect(self.characterDied)
  343. self._character = character
  344. if character:
  345. character.hasDied.connect(self.characterDied)
  346. taskMgr.add(self.update, 'userInteract')
  347. self._attach()
  348. def characterDied(self, spawnId):
  349. if self.character != base.world.player:
  350. self.toggleCharacter()
  351. return
  352. base.uiManager.actionMessenger.print("You died! Game over! Hehe yeah kidding, this is still TODO!", 20)
  353. taskMgr.remove('userInteract')
  354. @property
  355. def mapId(self): return self._mapId
  356. @mapId.setter
  357. def mapId(self, mapId):
  358. self._mapId = mapId
  359. if mapId is not None:
  360. if self.miniMap:
  361. pass
  362. # self.miniMap.setMapId() TODO
  363. else:
  364. self.miniMap = MiniMap(self.mapId)
  365. elif self.miniMap:
  366. self._destroyMiniMap()
  367. def centerCursor(self):
  368. props = base.win.getProperties();
  369. base.win.movePointer(0, int(props.getXSize() / 2), int(props.getYSize() / 2))
  370. def backupCursorPosition(self):
  371. mw = base.mouseWatcherNode
  372. self._cursorBackup = [mw.getMouseX(), mw.getMouseY()]
  373. def restoreCursorPosition(self):
  374. props = base.win.getProperties()
  375. x = int((props.getXSize() / 2) * (self._cursorBackup[0] + 1 ))
  376. y = int((props.getYSize() / 2) * (-self._cursorBackup[1] + 1 ))
  377. base.win.movePointer(0, x, y)
  378. self._cursorBackup = [0, 0]
  379. def update(self, task):
  380. dt = globalClock.getDt()
  381. if self.character and not self.character.isDead(): self.processInput(dt)
  382. return task.cont
  383. @property
  384. def cursorBusy(self): return self._cursorBusy
  385. def rotate(self, omega): # override
  386. self._orientationChanged = True
  387. self.character.rotate(omega)
  388. def rotateLeft(self, dt): # override
  389. self._orientationChanged = True
  390. return self.character.rotateLeft(dt)
  391. def rotateRight(self, dt): # override
  392. self._orientationChanged = True
  393. return self.character.rotateRight(dt)
  394. def mouseWheelUp(self):
  395. if (self.camFloater.getY()+0.3) < -1.0:
  396. self.camFloater.setY(self.camFloater.getY()+0.3)
  397. return True
  398. return False
  399. def mouseWheelDown(self):
  400. if (self.camFloater.getY()+-0.3) > -15:
  401. self.camFloater.setY(self.camFloater.getY()-0.3)
  402. return True
  403. return False
  404. def setKey(self, key, value):# override
  405. self._inputChanged = True
  406. self.keyMap[key] = value
  407. def moveCameraVertical(self, amount):
  408. newZ = self.camFloater.getZ(self.character.characterNP) + amount
  409. if newZ < 15 and newZ > -15: # Max zoomout
  410. self.camFloater.setZ(self.camFloater, amount)
  411. def processInput(self, dt):
  412. omega = 0.0
  413. mouseForward = False
  414. camSen = 220
  415. charSen = 32
  416. if self.keyMap["leftMouse"] or self.keyMap["rightMouse"]:
  417. if self.keyMap["leftMouse"] and self.keyMap["rightMouse"]:
  418. mouseForward = True
  419. if self.keyMap["rightMouse"]:
  420. if self._mouseEvents["rightJustClicked"]:
  421. self._mouseEvents["rightJustClicked"] = False
  422. if not self._cursorBackup[0]:
  423. self._cursorBusy = True
  424. base.mouseHandler.showCursor(False);
  425. self.backupCursorPosition();
  426. self.centerCursor();
  427. else:
  428. # Move camera
  429. xDiff = base.mouseWatcherNode.getMouseX()
  430. yDiff = base.mouseWatcherNode.getMouseY()
  431. self.moveCameraVertical(-(yDiff * camSen) * dt)
  432. # Rotate characterNP
  433. omega = -xDiff * charSen
  434. self.rotate(omega)
  435. self.centerCursor()
  436. elif self.keyMap["leftMouse"]:
  437. if self._mouseEvents["leftJustClicked"]:
  438. self._mouseEvents["leftJustClicked"] = False
  439. if not self._cursorBackup[0]:
  440. self._cursorBusy = True
  441. base.mouseHandler.showCursor(False);
  442. self.backupCursorPosition();
  443. self.centerCursor();
  444. else:
  445. xDiff = base.mouseWatcherNode.getMouseX() * 560
  446. yDiff = base.mouseWatcherNode.getMouseY() * 300
  447. self.moveCameraVertical(-yDiff * dt)
  448. self.floater.setH(self.floater, -xDiff * dt)
  449. self.centerCursor();
  450. elif self._cursorBackup[0]:
  451. self._mouseEvents["leftJustClicked"] = True
  452. self._mouseEvents["rightJustClicked"] = True
  453. self.restoreCursorPosition();
  454. self._cursorBusy = False
  455. base.mouseHandler.showCursor();
  456. mouseForward = False
  457. # Restore camera behind character if moving and not leftmouse
  458. if self.keyMap['forward'] and not self.keyMap["leftMouse"]:
  459. if self.floater.getH() > 1:
  460. self.floater.setH(self.floater, -1)
  461. elif self.floater.getH() < -1:
  462. self.floater.setH(self.floater, 1)
  463. moveVec = Vec3()
  464. if self.keyMap['forward'] or mouseForward:
  465. self.character.forward(dt, moveVec)
  466. elif self.keyMap['backward']:
  467. self.character.backward(dt, moveVec)
  468. if self.keyMap['shuffleLeft']:
  469. self.character.shuffleLeft(dt, moveVec)
  470. elif self.keyMap['shuffleRight']:
  471. self.character.shuffleRight(dt, moveVec)
  472. if self.keyMap['rotateLeft']:
  473. self.miniMap.modOrientation(self.rotateLeft(dt))
  474. elif self.keyMap['rotateRight']:
  475. self.miniMap.modOrientation(self.rotateRight(dt))
  476. if self._orientationChanged:
  477. self._orientationChanged = False
  478. # Update mini-map orientation
  479. if self.miniMap:
  480. self.miniMap.setOrientation(self.character.getOrientation())
  481. """ Animations
  482. """
  483. if self._movingAnimation == "run":
  484. if not (self.keyMap["forward"] or mouseForward):
  485. self.character.actorNP.stop()
  486. self.character.actorNP.loop("idle")
  487. self._movingAnimation = ""
  488. elif self.keyMap["jump"]:
  489. self.character.actorNP.stop()
  490. self.character.actorNP.setPlayRate(1.2, "runJump")
  491. self.character.actorNP.play("runJump")
  492. self._movingAnimation = "runJump"
  493. elif self._movingAnimation == "runJump":
  494. if self.character.characterCont.isOnGround():
  495. self.character.actorNP.loop("run")
  496. self._movingAnimation = "run"
  497. else:
  498. if self.keyMap["forward"] or mouseForward:
  499. self.character.actorNP.loop("run")
  500. self._movingAnimation = "run"
  501. """ Apply inputs
  502. """
  503. if self.keyMap["jump"]:
  504. self.keyMap["jump"] = False
  505. self.character.doJump()
  506. # Move
  507. self.character.setPos(moveVec)
  508. self.character.updatePreviousPos()
  509. if self.character.isMoving:
  510. if self.miniMap: self.miniMap.setPos(self.character._previousCharacterPos)
  511. if self.keyMap['cameraUp']:
  512. self.moveCameraVertical(0.2)
  513. elif self.keyMap['cameraDown']:
  514. self.moveCameraVertical(-0.2)
  515. base.camera.lookAt(self.floater)