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