keineschweine.nim 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. import
  2. os, math, strutils, gl, tables,
  3. sfml, sfml_audio, sfml_colors, chipmunk, math_helpers,
  4. input_helpers, animations, game_objects, sfml_stuff, map_filter,
  5. sg_gui, sg_assets, sound_buffer, enet_client
  6. when defined(profiler):
  7. import nimprof
  8. type
  9. PPlayer* = ref TPlayer
  10. TPlayer* = object
  11. id: uint16
  12. vehicle: PVehicle
  13. spectator: bool
  14. alias: string
  15. nameTag: PText
  16. items: seq[PItem]
  17. PVehicle* = ref TVehicle
  18. TVehicle* = object
  19. body*: chipmunk.PBody
  20. shape*: chipmunk.PShape
  21. record*: PVehicleRecord
  22. sprite*: PSprite
  23. spriteRect*: TIntRect
  24. occupant: PPlayer
  25. when false:
  26. position*: TVector2f
  27. velocity*: TVector2f
  28. angle*: float
  29. PItem* = ref object
  30. record: PItemRecord
  31. cooldown: float
  32. PLiveBullet* = ref TLiveBullet ##represents a live bullet in the arena
  33. TLiveBullet* = object
  34. lifetime*: float
  35. dead: bool
  36. anim*: PAnimation
  37. record*: PBulletRecord
  38. fromPlayer*: PPlayer
  39. trailDelay*: float
  40. body: chipmunk.PBody
  41. shape: chipmunk.PShape
  42. include vehicles
  43. const
  44. LGrabbable* = (1 shl 0).TLayers
  45. LBorders* = (1 shl 1).TLayers
  46. LPlayer* = ((1 shl 2) and LBorders.int).TLayers
  47. LEnemy* = ((1 shl 4) and LBorders.int).TLayers
  48. LEnemyFire* = (LPlayer).TLayers
  49. LPlayerFire* = (LEnemy).TLayers
  50. CTBullet = 1.TCollisionType
  51. CTVehicle= 2.TCollisionType
  52. ##temporary constants
  53. W_LIMIT = 2.3
  54. V_LIMIT = 35
  55. MaxLocalBots = 3
  56. var
  57. localPlayer: PPlayer
  58. localBots: seq[PPlayer] = @[]
  59. activeVehicle: PVehicle
  60. myVehicles: seq[PVehicle] = @[]
  61. objects: seq[PGameObject] = @[]
  62. liveBullets: seq[PLiveBullet] = @[]
  63. explosions: seq[PAnimation] = @[]
  64. gameRunning = true
  65. frameRate = newClock()
  66. showStars = off
  67. levelArea: TIntRect
  68. videoMode: TVideoMode
  69. window: PRenderWindow
  70. worldView: PView
  71. guiView: PView
  72. space = newSpace()
  73. ingameClient = newKeyClient("ingame")
  74. specInputClient = newKeyClient("spec")
  75. specGui = newGuiContainer()
  76. stars: seq[PSpriteSheet] = @[]
  77. playBtn: PButton
  78. shipSelect = newGuiContainer()
  79. delObjects: seq[int] = @[]
  80. showShipSelect = false
  81. myPosition: array[0..1, TVector3f] ##for audio positioning
  82. let
  83. nameTagOffset = vec2f(0.0, 1.0)
  84. when defined(escapeMenuTest):
  85. import browsers
  86. var
  87. escMenu = newGuiContainer(vec2f(100, 100))
  88. escMenuOpen = false
  89. pos = vec2f(0, 0)
  90. escMenu.newButton("Some Website", pos, proc(b: PButton) =
  91. openDefaultBrowser(getClientSettings().website))
  92. pos.y += 20.0
  93. escMenu.newButton("Back to Lobby", pos, proc(b: PButton) =
  94. echo "herro")
  95. proc toggleEscape() =
  96. escMenuOpen = not escMenuOpen
  97. ingameClient.registerHandler(KeyEscape, down, toggleEscape)
  98. specInputClient.registerHandler(KeyEscape, down, toggleEscape)
  99. when defined(foo):
  100. var mouseSprite: sfml.PCircleShape
  101. when defined(recordMode):
  102. var
  103. snapshots: seq[PImage] = @[]
  104. isRecording = false
  105. proc startRecording() =
  106. if snapshots.len > 100: return
  107. echo "Started recording"
  108. isRecording = true
  109. proc stopRecording() =
  110. if isRecording:
  111. echo "Stopped recording. ", snapshots.len, " images."
  112. isRecording = false
  113. proc zeroPad*(s: string; minLen: int): string =
  114. if s.len < minLen:
  115. result = repeat(0, minLen - s.len)
  116. result.add s
  117. else:
  118. result = s
  119. var
  120. recordButton = newButton(
  121. nil, text = "Record", position = vec2f(680, 50),
  122. onClick = proc(b: PButton) = startRecording())
  123. proc newNameTag*(text: string): PText =
  124. result = newText()
  125. result.setFont(guiFont)
  126. result.setCharacterSize(14)
  127. result.setColor(Red)
  128. result.setString(text)
  129. var debugText = newNameTag("Loading...")
  130. debugText.setPosition(vec2f(0.0, 600.0 - 50.0))
  131. when defined(showFPS):
  132. var fpsText = newNameTag("0")
  133. #fpsText.setCharacterSize(16)
  134. fpsText.setPosition(vec2f(300.0, (800 - 50).float))
  135. proc mouseToSpace*(): TVector =
  136. result = window.convertCoords(vec2i(getMousePos()), worldView).sfml2cp()
  137. proc explode*(b: PLiveBullet)
  138. ## TCollisionBeginFunc
  139. proc collisionBulletPlayer(arb: PArbiter; space: PSpace;
  140. data: pointer): bool{.cdecl.} =
  141. var
  142. bullet = cast[PLiveBullet](arb.a.data)
  143. target = cast[PVehicle](arb.b.data)
  144. if target.occupant.isNil or target.occupant == bullet.fromPlayer: return
  145. bullet.explode()
  146. proc angularDampingSim(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} =
  147. body.w -= (body.w * 0.98 * dt)
  148. body.UpdateVelocity(gravity, damping, dt)
  149. proc initLevel() =
  150. loadAllAssets()
  151. if not space.isNil: space.destroy()
  152. space = newSpace()
  153. space.addCollisionHandler CTBullet, CTVehicle, collisionBulletPlayer,
  154. nil, nil, nil, nil
  155. let levelSettings = getLevelSettings()
  156. levelArea.width = levelSettings.size.x
  157. levelArea.height= levelSettings.size.y
  158. let borderSeq = @[
  159. vector(0, 0), vector(levelArea.width.float, 0.0),
  160. vector(levelArea.width.float, levelArea.height.float), vector(0.0, levelArea.height.float)]
  161. for i in 0..3:
  162. var seg = space.addShape(
  163. newSegmentShape(
  164. space.staticBody,
  165. borderSeq[i],
  166. borderSeq[(i + 1) mod 4],
  167. 8.0))
  168. seg.setElasticity 0.96
  169. seg.setLayers(LBorders)
  170. if levelSettings.starfield.len > 0:
  171. showStars = true
  172. for sprite in levelSettings.starfield:
  173. sprite.tex.setRepeated(true)
  174. sprite.sprite.setTextureRect(levelArea)
  175. sprite.sprite.setOrigin(vec2f(0, 0))
  176. stars.add(sprite)
  177. var pos = vec2f(0.0, 0.0)
  178. for veh in playableVehicles():
  179. shipSelect.newButton(
  180. veh.name,
  181. position = pos,
  182. onClick = proc(b: PButton) =
  183. echo "-__-")
  184. pos.y += 18.0
  185. proc newItem*(record: PItemRecord): PItem =
  186. new(result)
  187. result.record = record
  188. proc newItem*(name: string): PItem {.inline.} =
  189. return newItem(fetchItm(name))
  190. proc canUse*(itm: PItem): bool =
  191. if itm.cooldown > 0.0: return
  192. return true
  193. proc update*(itm: PItem; dt: float) =
  194. if itm.cooldown > 0:
  195. itm.cooldown -= dt
  196. proc free(obj: PLiveBullet) =
  197. obj.shape.free
  198. obj.body.free
  199. obj.record = nil
  200. template newExplosion(obj, animation) =
  201. explosions.add(newAnimation(animation, AnimOnce, obj.body.getPos.cp2sfml, obj.body.getAngle))
  202. template newExplosion(obj, animation, angle) =
  203. explosions.add(newAnimation(animation, AnimOnce, obj.body.getPos.cp2sfml, angle))
  204. proc explode*(b: PLiveBullet) =
  205. if b.dead: return
  206. b.dead = true
  207. space.removeShape b.shape
  208. space.removeBody b.body
  209. if not b.record.explosion.anim.isNil:
  210. newExplosion(b, b.record.explosion.anim)
  211. playSound(b.record.explosion.sound, b.body.getPos())
  212. proc bulletUpdate(body: PBody, gravity: TVector, damping, dt: CpFloat){.cdecl.} =
  213. body.UpdateVelocity(gravity, damping, dt)
  214. template getPhysical() {.dirty.} =
  215. result.body = space.addBody(newBody(
  216. record.physics.mass,
  217. record.physics.moment))
  218. result.shape = space.addShape(
  219. chipmunk.newCircleShape(
  220. result.body,
  221. record.physics.radius,
  222. VectorZero))
  223. proc newBullet*(record: PBulletRecord; fromPlayer: PPlayer): PLiveBullet =
  224. new(result, free)
  225. result.anim = newAnimation(record.anim, AnimLoop)
  226. result.fromPlayer = fromPlayer
  227. result.lifetime = record.lifetime
  228. result.record = record
  229. getPhysical()
  230. if fromPlayer == localPlayer:
  231. result.shape.setLayers(LPlayerFire)
  232. else:
  233. result.shape.setLayers(LEnemyFire)
  234. result.shape.setCollisionType CTBullet
  235. result.shape.setUserData(cast[ptr TLiveBullet](result))
  236. let
  237. fireAngle = fromPlayer.vehicle.body.getAngle()
  238. fireAngleV = vectorForAngle(fireAngle)
  239. result.body.setAngle fireAngle
  240. result.body.setPos(fromPlayer.vehicle.body.getPos() + (fireAngleV * fromPlayer.vehicle.shape.getCircleRadius()))
  241. #result.body.velocityFunc = bulletUpdate
  242. result.body.setVel((fromPlayer.vehicle.body.getVel() * record.inheritVelocity) + (fireAngleV * record.baseVelocity))
  243. proc update*(b: PLiveBullet; dt: float): bool =
  244. if b.dead: return true
  245. b.lifetime -= dt
  246. b.anim.next(dt)
  247. #b.anim.sprite.setPosition(b.body.getPos.floor())
  248. b.anim.setPos(b.body.getPos)
  249. b.anim.setAngle(b.body.getAngle())
  250. if b.lifetime <= 0.0:
  251. b.explode()
  252. return true
  253. b.trailDelay -= dt
  254. if b.trailDelay <= 0.0:
  255. b.trailDelay += b.record.trail.timer
  256. if b.record.trail.anim.isNil: return
  257. newExplosion(b, b.record.trail.anim)
  258. proc draw*(window: PRenderWindow; b: PLiveBullet) {.inline.} =
  259. draw(window, b.anim.sprite)
  260. proc free*(veh: PVehicle) =
  261. ("Destroying vehicle " & veh.record.name).echo
  262. destroy(veh.sprite)
  263. if veh.shape.isNil: "Free'd vehicle's shape was NIL!".echo
  264. else: space.removeShape(veh.shape)
  265. if veh.body.isNil: "Free'd vehicle's BODY was NIL!".echo
  266. else: space.removeBody(veh.body)
  267. veh.body.free()
  268. veh.shape.free()
  269. veh.sprite = nil
  270. veh.body = nil
  271. veh.shape = nil
  272. proc newVehicle*(record: PVehicleRecord): PVehicle =
  273. echo("Creating " & record.name)
  274. new(result, free)
  275. result.record = record
  276. result.sprite = result.record.anim.spriteSheet.sprite.copy()
  277. result.spriteRect = result.sprite.getTextureRect()
  278. getPhysical()
  279. result.body.setAngVelLimit W_LIMIT
  280. result.body.setVelLimit result.record.handling.topSpeed
  281. result.body.velocityFunc = angularDampingSim
  282. result.shape.setCollisionType CTVehicle
  283. result.shape.setUserData(cast[ptr TVehicle](result))
  284. proc newVehicle*(name: string): PVehicle =
  285. result = newVehicle(fetchVeh(name))
  286. proc update*(obj: PVehicle) =
  287. obj.sprite.setPosition(obj.body.getPos.floor)
  288. obj.spriteRect.left = (((-obj.body.getAngVel + W_LIMIT) / (W_LIMIT*2.0) * (obj.record.anim.spriteSheet.cols - 1).float).floor.int * obj.record.anim.spriteSheet.framew).cint
  289. obj.spriteRect.top = ((obj.offsetAngle.wmod(TAU) / TAU) * obj.record.anim.spriteSheet.rows.float).floor.cint * obj.record.anim.spriteSheet.frameh.cint
  290. obj.sprite.setTextureRect(obj.spriteRect)
  291. proc newPlayer*(alias: string = "poo"): PPlayer =
  292. new(result)
  293. result.spectator = true
  294. result.alias = alias
  295. result.nameTag = newNameTag(result.alias)
  296. result.items = @[]
  297. proc updateItems*(player: PPlayer, dt: float) =
  298. for i in items(player.items):
  299. update(i, dt)
  300. proc addItem*(player: PPlayer; name: string) =
  301. player.items.add newItem(name)
  302. proc useItem*(player: PPlayer; slot: int) =
  303. if slot > player.items.len - 1: return
  304. let item = player.items[slot]
  305. if item.canUse:
  306. item.cooldown += item.record.cooldown
  307. let b = newBullet(item.record.bullet, player)
  308. liveBullets.add(b)
  309. sound_buffer.playSound(item.record.useSound, b.body.getPos)
  310. proc update*(obj: PPlayer) =
  311. if not obj.spectator:
  312. obj.vehicle.update()
  313. obj.nameTag.setPosition(obj.vehicle.body.getPos.floor + (nameTagOffset * (obj.vehicle.record.physics.radius + 5).cfloat))
  314. proc draw(window: PRenderWindow, player: PPlayer) {.inline.} =
  315. if not player.spectator:
  316. if player.vehicle != nil:
  317. window.draw(player.vehicle.sprite)
  318. window.draw(player.nameTag)
  319. proc setVehicle(p: PPlayer; v: PVehicle) =
  320. p.vehicle = v #sorry mom, this is just how things worked out ;(
  321. if not v.isNil:
  322. v.occupant = p
  323. proc createBot() =
  324. if localBots.len < MaxLocalBots:
  325. var bot = newPlayer("Dodo Brown")
  326. bot.setVehicle(newVehicle("Turret0"))
  327. if bot.isNil:
  328. echo "BOT IS NIL"
  329. return
  330. elif bot.vehicle.isNil:
  331. echo "BOT VEH IS NIL"
  332. return
  333. localBots.add(bot)
  334. bot.vehicle.body.setPos(vector(100, 100))
  335. echo "new bot at ", $bot.vehicle.body.getPos()
  336. var inputCursor = newVertexArray(sfml.Lines, 2)
  337. inputCursor[0].position = vec2f(10.0, 10.0)
  338. inputCursor[1].position = vec2f(50.0, 90.0)
  339. proc hasVehicle(p: PPlayer): bool {.inline.} =
  340. result = not p.spectator and not p.vehicle.isNil
  341. proc setMyVehicle(v: PVehicle) {.inline.} =
  342. activeVehicle = v
  343. localPlayer.setVehicle v
  344. proc unspec() =
  345. var veh = newVehicle("Turret0")
  346. if not veh.isNil:
  347. setMyVehicle veh
  348. localPlayer.spectator = false
  349. ingameClient.setActive
  350. veh.body.setPos vector(100, 100)
  351. veh.shape.setLayers(LPlayer)
  352. when defined(debugWeps):
  353. localPlayer.addItem("Mass Driver")
  354. localPlayer.addItem("Neutron Bomb")
  355. localPlayer.additem("Dem Lasers")
  356. localPlayer.addItem("Mold Spore Beam")
  357. localPlayer.addItem("Genericorp Mine")
  358. localPlayer.addItem("Gravitic Bomb")
  359. proc spec() =
  360. setMyVehicle nil
  361. localPlayer.spectator = true
  362. specInputClient.setActive
  363. var
  364. specLimiter = newClock()
  365. timeBetweenSpeccing = 1.0 #seconds
  366. proc toggleSpec() {.inline.} =
  367. if specLimiter.getElapsedTime.asSeconds < timeBetweenSpeccing:
  368. return
  369. specLimiter.restart()
  370. if localPlayer.isNil:
  371. echo("OMG WTF PLAYER IS NILL!!")
  372. elif localPlayer.spectator: unspec()
  373. else: spec()
  374. proc addObject*(name: string) =
  375. var o = newObject(name)
  376. if not o.isNil:
  377. echo "Adding object ", o
  378. discard space.addBody(o.body)
  379. discard space.addShape(o.shape)
  380. o.shape.setLayers(LGrabbable)
  381. objects.add(o)
  382. proc explode(obj: PGameObject) =
  383. echo obj, " exploded"
  384. let ind = objects.find(obj)
  385. if ind != -1:
  386. delObjects.add ind
  387. proc update(obj: PGameObject; dt: float) =
  388. if not(obj.anim.next(dt)):
  389. obj.explode()
  390. else:
  391. obj.anim.setPos(obj.body.getPos)
  392. obj.anim.setAngle(obj.body.getAngle)
  393. proc toggleShipSelect() =
  394. showShipSelect = not showShipSelect
  395. proc handleLClick() =
  396. let pos = input_helpers.getMousePos()
  397. when defined(escapeMenuTest):
  398. if escMenuOpen:
  399. escMenu.click(pos)
  400. return
  401. if showShipSelect:
  402. shipSelect.click(pos)
  403. if localPlayer.spectator:
  404. specGui.click(pos)
  405. ingameClient.registerHandler(KeyF12, down, proc() = toggleSpec())
  406. ingameClient.registerHandler(KeyF11, down, toggleShipSelect)
  407. ingameClient.registerHandler(MouseLeft, down, handleLClick)
  408. when defined(recordMode):
  409. if not dirExists("data/snapshots"):
  410. createDir("data/snapshots")
  411. ingameClient.registerHandler(keynum9, down, proc() =
  412. if not isRecording: startRecording()
  413. else: stopRecording())
  414. ingameClient.registerHandler(keynum0, down, proc() =
  415. if snapshots.len > 0 and not isRecording:
  416. echo "Saving images (LOL)"
  417. for i in 0..high(snapshots):
  418. if not(snapshots[i].save("data/snapshots/image"&(zeroPad($i, 3))&".jpg")):
  419. echo "Could not save"
  420. snapshots[i].destroy()
  421. snapshots.setLen 0)
  422. when defined(DebugKeys):
  423. ingameClient.registerHandler MouseRight, down, proc() =
  424. echo($activevehicle.body.getAngle.vectorForAngle())
  425. ingameClient.registerHandler KeyBackslash, down, proc() =
  426. createBot()
  427. ingameClient.registerHandler(KeyNum1, down, proc() =
  428. if localPlayer.items.len == 0:
  429. localPlayer.addItem("Mass Driver")
  430. echo "Gave you a mass driverz")
  431. ingameClient.registerHandler(KeyL, down, proc() =
  432. echo("len(livebullets) = ", len(livebullets)))
  433. ingameClient.registerHandler(KeyRShift, down, proc() =
  434. if keyPressed(KeyR):
  435. echo("Friction: ", ff(activeVehicle.shape.getFriction()))
  436. echo("Damping: ", ff(space.getDamping()))
  437. elif keypressed(KeyM):
  438. echo("Mass: ", activeVehicle.body.getMass.ff())
  439. echo("Moment: ", activeVehicle.body.getMoment.ff())
  440. elif keypressed(KeyI):
  441. echo(repr(activeVehicle.record))
  442. elif keyPressed(KeyH):
  443. activeVehicle.body.setPos(vector(100.0, 100.0))
  444. activeVehicle.body.setVel(VectorZero)
  445. elif keyPressed(KeyComma):
  446. activeVehicle.body.setPos mouseToSpace())
  447. ingameClient.registerHandler(KeyY, down, proc() =
  448. const looloo = ["Asteroid1", "Asteroid2"]
  449. addObject(looloo[rand(looloo.len)]))
  450. ingameClient.registerHandler(KeyO, down, proc() =
  451. if objects.len == 0:
  452. echo "Objects is empty"
  453. return
  454. for i, o in pairs(objects):
  455. echo i, " ", o)
  456. ingameClient.registerHandler(KeyLBracket, down, sound_buffer.report)
  457. var
  458. mouseJoint: PConstraint
  459. mouseBody = space.addBody(newBody(CpInfinity, CpInfinity))
  460. ingameClient.registerHandler(MouseMiddle, down, proc() =
  461. var point = mouseToSpace()
  462. var shape = space.pointQueryFirst(point, LGrabbable, 0)
  463. if not mouseJoint.isNil:
  464. space.removeConstraint mouseJoint
  465. mouseJoint.destroy()
  466. mouseJoint = nil
  467. if shape.isNil:
  468. return
  469. let body = shape.getBody()
  470. mouseJoint = space.addConstraint(
  471. newPivotJoint(mouseBody, body, VectorZero, body.world2local(point)))
  472. mouseJoint.maxForce = 50000.0
  473. mouseJoint.errorBias = pow(1.0 - 0.15, 60))
  474. var specCameraSpeed = 5.0
  475. specInputClient.registerHandler(MouseLeft, down, handleLClick)
  476. specInputClient.registerHandler(KeyF11, down, toggleShipSelect)
  477. specInputClient.registerHandler(KeyF12, down, proc() = toggleSpec())
  478. specInputClient.registerHandler(KeyLShift, down, proc() = specCameraSpeed *= 2)
  479. specInputClient.registerHandler(KeyLShift, up, proc() = specCameraSpeed /= 2)
  480. specInputClient.registerHandler(KeyP, down, proc() =
  481. echo("addObject(solar mold)")
  482. addObject("Solar Mold"))
  483. proc resetForcesCB(body: PBody; data: pointer) {.cdecl.} =
  484. body.resetForces()
  485. var frameCount= 0
  486. proc mainUpdate(dt: float) =
  487. if localPlayer.spectator:
  488. if keyPressed(KeyLeft):
  489. worldView.move(vec2f(-1.0, 0.0) * specCameraSpeed)
  490. elif keyPressed(KeyRight):
  491. worldView.move(vec2f( 1.0, 0.0) * specCameraSpeed)
  492. if keyPressed(KeyUp):
  493. worldView.move(vec2f(0.0, -1.0) * specCameraSpeed)
  494. elif keyPressed(KeyDown):
  495. worldView.move(vec2f(0.0, 1.0) * specCameraSpeed)
  496. elif not activeVehicle.isNil:
  497. if keyPressed(KeyUp):
  498. activeVehicle.accel(dt)
  499. elif keyPressed(KeyDown):
  500. activeVehicle.reverse(dt)
  501. if keyPressed(KeyRight):
  502. activeVehicle.turn_right(dt)
  503. elif keyPressed(KeyLeft):
  504. activeVehicle.turn_left(dt)
  505. if keyPressed(Keyz):
  506. activeVehicle.strafe_left(dt)
  507. elif keyPressed(Keyx):
  508. activeVehicle.strafe_right(dt)
  509. if keyPressed(KeyLControl):
  510. localPlayer.useItem 0
  511. if keyPressed(KeyTab):
  512. localPlayer.useItem 1
  513. if keyPressed(KeyQ):
  514. localPlayer.useItem 2
  515. if keyPressed(KeyW):
  516. localPlayer.useItem 3
  517. if keyPressed(KeyA):
  518. localPlayer.useItem 4
  519. if keyPressed(sfml.KeyS):
  520. localPlayer.useItem 5
  521. if keyPressed(KeyD):
  522. localPlayer.useItem 6
  523. worldView.setCenter(activeVehicle.body.getPos.floor)#cp2sfml)
  524. if localPlayer != nil:
  525. localPlayer.update()
  526. localPlayer.updateItems(dt)
  527. for b in localBots:
  528. b.update()
  529. for o in items(objects):
  530. o.update(dt)
  531. for i in countdown(high(delObjects), 0):
  532. objects.del i
  533. delObjects.setLen 0
  534. var i = 0
  535. while i < len(liveBullets):
  536. if liveBullets[i].update(dt):
  537. liveBullets.del i
  538. else:
  539. inc i
  540. i = 0
  541. while i < len(explosions):
  542. if explosions[i].next(dt): inc i
  543. else: explosions.del i
  544. when defined(DebugKeys):
  545. mouseBody.setPos(mouseToSpace())
  546. space.step(dt)
  547. space.eachBody(resetForcesCB, nil)
  548. when defined(foo):
  549. var coords = window.convertCoords(vec2i(getMousePos()), worldView)
  550. mouseSprite.setPosition(coords)
  551. if localPlayer != nil and localPlayer.vehicle != nil:
  552. let
  553. pos = localPlayer.vehicle.body.getPos()
  554. ang = localPlayer.vehicle.body.getAngle.vectorForAngle()
  555. myPosition[0].x = pos.x
  556. myPosition[0].z = pos.y
  557. myPosition[1].x = ang.x
  558. myPosition[1].z = ang.y
  559. listenerSetPosition(myPosition[0])
  560. listenerSetDirection(myPosition[1])
  561. inc frameCount
  562. when defined(showFPS):
  563. if frameCount mod 60 == 0:
  564. fpsText.setString($(1.0/dt).round)
  565. if frameCount mod 250 == 0:
  566. updateSoundBuffer()
  567. frameCount = 0
  568. proc mainRender() =
  569. window.clear(Black)
  570. window.setView(worldView)
  571. if showStars:
  572. for star in stars:
  573. window.draw(star.sprite)
  574. window.draw(localPlayer)
  575. for b in localBots:
  576. window.draw(b)
  577. for o in objects:
  578. window.draw(o)
  579. for b in explosions: window.draw(b)
  580. for b in liveBullets: window.draw(b)
  581. when defined(Foo):
  582. window.draw(mouseSprite)
  583. window.setView(guiView)
  584. when defined(EscapeMenuTest):
  585. if escMenuOpen:
  586. window.draw escMenu
  587. when defined(showFPS):
  588. window.draw(fpsText)
  589. when defined(recordMode):
  590. window.draw(recordButton)
  591. if localPlayer.spectator:
  592. window.draw(specGui)
  593. if showShipSelect: window.draw shipSelect
  594. window.display()
  595. when defined(recordMode):
  596. if isRecording:
  597. if snapshots.len < 100:
  598. if frameCount mod 5 == 0:
  599. snapshots.add(window.capture())
  600. else: stopRecording()
  601. proc readyMainState() =
  602. specInputClient.setActive()
  603. when true:
  604. import parseopt
  605. localPlayer = newPlayer()
  606. lobbyInit()
  607. videoMode = getClientSettings().resolution
  608. window = newRenderWindow(videoMode, "sup", sfDefaultStyle)
  609. window.setFrameRateLimit 60
  610. worldView = window.getView.copy()
  611. guiView = worldView.copy()
  612. shipSelect.setPosition vec2f(665.0, 50.0)
  613. when defined(foo):
  614. mouseSprite = sfml.newCircleShape(14)
  615. mouseSprite.setFillColor Transparent
  616. mouseSprite.setOutlineColor RoyalBlue
  617. mouseSprite.setOutlineThickness 1.4
  618. mouseSprite.setOrigin vec2f(14, 14)
  619. lobbyReady()
  620. playBtn = specGui.newButton(
  621. "Unspec - F12", position = vec2f(680.0, 8.0), onClick = proc(b: PButton) =
  622. toggleSpec())
  623. block:
  624. var bPlayOffline = false
  625. for kind, key, val in getopt():
  626. case kind
  627. of cmdArgument:
  628. if key == "offline": bPlayOffline = true
  629. else:
  630. echo "Invalid argument ", key, " ", val
  631. if bPlayOffline:
  632. playoffline(nil)
  633. gameRunning = true
  634. while gameRunning:
  635. for event in window.filterEvents:
  636. if event.kind == EvtClosed:
  637. gameRunning = false
  638. break
  639. elif event.kind == EvtMouseWheelMoved and getActiveState() == Field:
  640. if event.mouseWheel.delta == 1:
  641. worldView.zoom(0.9)
  642. else:
  643. worldView.zoom(1.1)
  644. let dt = frameRate.restart.asMilliSeconds().float / 1000.0
  645. case getActiveState()
  646. of Field:
  647. mainUpdate(dt)
  648. mainRender()
  649. of Lobby:
  650. lobbyUpdate(dt)
  651. lobbyDraw(window)
  652. else:
  653. initLevel()
  654. echo("Done? lol")
  655. doneWithSaidTransition()
  656. readyMainState()