• API
• FAQ
• Tools
• Archive
SHARE
TWEET

# Arena

ezak Jan 3rd, 2013 116 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. --# Combat
2. Combat = class()
3.
4. function Combat:init(p1, p2, dist)
5.     self.p1 = p1
6.     self.p2 = p2
7.
8.     self.p1.fighting = true
9.     self.p2.fighting = true
10.
11.     self.inCombat = true
12.     self.timer = 0
13.     self.dist = dist
14.     self.closedUp = false
15. end
16.
17. function Combat:doCombat()
18.     local sin = math.sin
19.     local cos = math.cos
20.     local atan2 = math.atan2
21.
22.     local p1m = self.p1.model
23.     local p2m = self.p2.model
24.
25.     self.p1.direction = atan2(p2m.y - p1m.y, p2m.x - p1m.x)
26.     self.p2.direction = atan2(p1m.y - p2m.y, p1m.x - p2m.x)
27.
28.     if not self.closedUp or self.dist > 35 then
29.         local x = p1m.x - p2m.x
30.         local y = p1m.y - p2m.y
31.         local dist = math.sqrt(x*x + y*y)
32.
33.         if self.dist ~= dist then
34.             self.closedUp = true
35.         end
36.
37.         self.dist = dist
38.
39.         p1m.x = p1m.x + cos(self.p1.direction)*30*DeltaTime
40.         p1m.y = p1m.y + sin(self.p1.direction)*30*DeltaTime
41.
42.         p2m.x = p2m.x + cos(self.p2.direction)*30*DeltaTime
43.         p2m.y = p2m.y + sin(self.p2.direction)*30*DeltaTime
44.
45.         return
46.     end
47.
48.     if not self.closedUp or self.dist < 34 then
49.         local x = p1m.x - p2m.x
50.         local y = p1m.y - p2m.y
51.
52.         local dist = math.sqrt(x*x + y*y)
53.
54.         if self.dist ~= dist then
55.             self.closedUp = true
56.         end
57.
58.         self.dist = dist
59.
60.         p1m.x = p1m.x - cos(self.p1.direction)*30*DeltaTime
61.         p1m.y = p1m.y - sin(self.p1.direction)*30*DeltaTime
62.
63.         p2m.x = p2m.x - cos(self.p2.direction)*30*DeltaTime
64.         p2m.y = p2m.y - sin(self.p2.direction)*30*DeltaTime
65.         return
66.     end
67.
68.
69.     self.p1.direction = self.p1.direction + sin(-self.timer*8)
70.     self.p2.direction = self.p2.direction + sin(-self.timer*8)
71.
72.     self.timer = self.timer + DeltaTime
73.
74.     if self.timer > .8 then
75.         self.timer = 0
76.         if self.p1.despawning or self.p2.despawning then
77.             self.p1.despawning = true
78.             self.p2.despawning = true
79.             self.inCombat = false
80.             self.p1.fighting = false
81.             self.p2.fighting = false
82.             return
83.         end
84.
85.
86.         self.p1:modLife(-self.p2.power)
87.         self.p2:modLife(-self.p1.power)
88.
89.         if self.p1.life <= 0 then
90.             self.p1.dying = true
91.             self.inCombat = false
92.             if self.p2.life > 0 then
93.                 self.p2.fighting = false
94.                 self.p2.despawning = true
95.             end
96.         end
97.
98.         if self.p2.life <= 0 then
99.             self.p2.dying = true
100.             self.inCombat = false
101.             if self.p1.life > 0 then
102.                 self.p1.fighting = false
103.                 self.p1.despawning = true
104.             end
105.         end
106.
107.     end
108.
109. end
110. --# GUI
111. GUI = class()
112.
113. function GUI:init(player)
114.     self.stick = Stick()
115.     self.button = {}
116.     self.id = player
117. end
118.
119. function GUI:draw()
120.     local stick = self.stick
121.
122.     if stick.active then
123.         stick:draw()
124.     end
125.
126.     for _, button in ipairs(self.button) do
127.         button:draw()
128.     end
129. end
130.
131. function GUI:touched(touch, side)
132.     if side then
133.         self.stick:touched(touch)
134.     else
135.         for _, button in ipairs(self.button) do
136.             local type = button:touched(touch)
137.             if type == "summon" then
138.                 if touch.state == BEGAN then
139.                     self.id:summon(graphics.toon)
140.                 end
141.             end
142.
143.             if type == "attack" then
144.                 if touch.state == BEGAN and not self.id.shielding then
145.                     self.id.attacking = true
146.                 end
147.             end
148.
149.             if type == "fire" then
150.                 if touch.state == BEGAN and not self.id.fire and self.id.mana > 1 then
151.                     self.id.fire = true
152.                     self.id:getNearestEnemy()
153.                     self.id:modMana(-1)
154.                 end
155.             end
156.
157.             if type == "unsummon" then
158.                 if touch.state == BEGAN and not self.id.unsummon and self.id.mana > 2 then
159.                     self.id.unsummon = true
160.                     self.id:getNearestEnemy()
161.                     self.id:modMana(-2)
162.                 end
163.             end
164.
165.             if type == "buff" then
166.                 if touch.state == BEGAN and not self.id.buff and self.id.mana > 2 then
167.                     self.id.buff = true
168.                     self.id:getNearestFriend()
169.                     self.id:modMana(-2)
170.                 end
171.             end
172.
173.             if type == "shield" then
174.                 if touch.state == ENDED and not self.id.attacking then
175.                     self.id.shielding = false
176.                     self.id.timer = 0
177.                 else
178.                     if self.id.mana >= 1 and not self.id.attacking then
179.                         self.id.shielding = true
180.                     end
181.                 end
182.
183.             end
184.         end
185.     end
186. end
187.
188. --# Main
189. -- PvP latest
190. function setup()
191.     displayMode(FULLSCREEN)
192.     spriteMode(CENTER)
193.
194.     bnw = false
195.
196.     Camera = vec3(1,1,1)
197.     Light = vec3(1,1,1)
198.     font("Futura-CondensedExtraBold")
199.   --  noSmooth()
200.     parameter.integer("mode", 1, 2, 1)
201.
202.     parameter.integer("zzz", -20, 20, 0)
203.
204.     parameter.integer("lx", -100, 100, 1)
205.     parameter.integer("ly", -100, 100, 1)
206.     parameter.integer("lz", -100, 100, 100)
207. --    parameter.integer("zoomX", 1, 1000, 200)
208.  --   parameter.integer("zoomY", -1000, -1, -175)
209.
210.     -- sprite setup
211.     graphics = Graphics()
212.
213.     -- player setup
214.     player1 = Player(graphics.toon, -110, 0)
215.     player2 = Player(graphics.toon, 150, 0)
216.
217.     player1.target = player2
218.     local ins = table.insert
219.
220.
221.     ins(player1.gui.button, Buttons("attack", WIDTH - 100,200))
222.     ins(player1.gui.button, Buttons("shield", WIDTH - 200,100))
223.
224.     ins(player1.gui.button, Buttons("summon", WIDTH - 32,300))
225.     ins(player1.gui.button, Buttons("fire", WIDTH - 96,300))
226.     ins(player1.gui.button, Buttons("unsummon", WIDTH - 32,364))
227.     ins(player1.gui.button, Buttons("buff", WIDTH - 96,364))
228.
229.     player2.target = player1
230.     ins(player2.gui.button, Buttons("attack", 100, HEIGHT - 200))
231.     ins(player2.gui.button, Buttons("shield", 200, HEIGHT - 100))
232.
233.     ins(player2.gui.button, Buttons("summon", 32, HEIGHT - 300))
234.     ins(player2.gui.button, Buttons("unsummon", 32, HEIGHT - 364))
235.     ins(player2.gui.button, Buttons("buff", 96, HEIGHT - 364))
236.     ins(player2.gui.button, Buttons("fire", 96, HEIGHT - 300))
237.     player2.gui.stick.direction = -3.14
238.
239.     graphics.players = {player1, player2}
240.
241.     tick = 0
242.     timer = 0
243.     fps = 0
244.
245.     x = 0
246.     y = 0
247.     smoothing = 0
248.   --  im = image(WIDTH,HEIGHT)
249. end
250.
251. function draw()
252.     if bnw then
253.         background(200, 200, 200, 255)
254.     else
255.         background(102, 150, 80, 255)
256.     end
257.     setCamera()
258.     -- scene
259.
260.     graphics:drawWorld()
261.
262.     -- draw players ane minions
263.     player1:draw()
264.     translate(0,0,.2)
265.     player2:draw()
266.
267.     if bnw then
268.         tint(200, 200, 200, 255)
269.     else
270.         tint(102, 150, 80, 255)
271.     end
272.
273.  --   sprite(graphics.BG, xxx, yyy, zzz, zzz)
274.     translate(0,0,-4)
275.     sprite(graphics.BG, 0, 0, 880, 880)
276.     noTint()
277.     -- draw shadows, spawn points, text, etc...
278.     graphics:draw()
279.
280.
281.
282.     -- move seemless sky texture and draw it
283.     --[[
284.     x = x + (1/2048)
285.     y = y + (1/2048)
286.     translate(0,0,200)
287.     graphics.sky:setRectTex(graphics.skyId, x, y, 1, 1)
288.     graphics.sky:draw()
289.     translate(0,0,-200)
290.     ]]--
291.
292.     ortho()
293.     viewMatrix(matrix())
294.     sprite(graphics.mask, WIDTH/2, HEIGHT/2, WIDTH+300, HEIGHT+300)
295.
296.     -- draw pads and buttons
297.     player1.gui:draw()
298.     player2.gui:draw()
299.
300.     if timer > .4 then
301.         timer = 0
302.         tick = tick + .2
303.         fps = math.floor(1/DeltaTime*10)/10
304.
305.         player1:modMana(.1)
306.         player2:modMana(.1)
307.     end
308.
309.     local n = 2
310.     for i=1, 5 do
311.         if player1.summons[i] then
312.             n = n + 1
313.         end
314.         if player2.summons[i] then
315.             n = n + 1
316.         end
317.     end
318.
319.     text(n.." objects, "..(n*graphics.toon.size/3).." polygons", 150, HEIGHT - 20)
320.     text("FPS: "..fps, WIDTH - 50, HEIGHT - 20)
321.
322.     timer = timer + DeltaTime
323. end
324.
325. function touched(touch)
326.     if touch.y < HEIGHT/2 then
327.         player1.gui:touched(touch, touch.x < WIDTH/2)
328.     else
329.         player2.gui:touched(touch, touch.x > WIDTH/2)
330.     end
331. end
332.
333.
334. function setCamera()
335.     -- set camera to point between both players
336.     -- and zoom out so both are always on screen
337.     local p1 = player1.model
338.     local p2 = player2.model
339.     local x, y, dist, tmp
340.     x = (p1.x - p2.x)
341.     y = (p1.y - p2.y)
342.     dist = math.sqrt(x*x+y*y)
343.     x = (p1.x + p2.x)/2
344.     y = (p1.y + p2.y)/2
345.     perspective(60, WIDTH/HEIGHT)
346.
347.     if mode == 1 then
348.
349.         Light = vec3(lx, ly, lz):normalize()
350.         Camera = vec3(x,-175+y,200+dist):normalize()
351.         camera(x,-175+y,200+dist, x,y,0, 0,1,0)
352.     else
353.         Camera = vec3(x,-1+y,200+dist):normalize()
354.         Light = vec3(lx, ly, lz):normalize()
355.         camera(x,-1+y,200+dist, x,y,0, 0,1,0)
356.     end
357. end
358. --# Player
359. Player = class()
360.
361. function Player:init(mdl, x, y)
362.     self.summons = {nil, nil, nil, nil, nil}
363.     self.direction = 0
364.
365.     -- numerical life and power
366.     self.life = 10
367.     self.mana = 10
368.     self.maxMana = 10
369.     self.speed = 1
370.
371.     -- graphical format of life and power
372.     self:modLife(0)
373.     self:modMana(0)
374.
375.     -- enemy player
376.     self.target = nil
377.     self.nearestEnemy = nil
378.     self.nearestFriend = nil
379.
380.     -- player 3d model, position and scale
381.     self.model = Cube(mdl, x, y, 12)
382.
383.     -- player touchpad and buttons
384.     self.gui = GUI(self)
385.
386.     self.casting = false
387.     self.shielding = false
388.
389.     self.buff = false
390.     self.fire = false
391.     self.unsummon = false
392.
393.     self.attacking = false
394.     self.hasHit = false
395.
396.     self.timer = 0
397. end
398.
399. function Player:modLife(val)
400.     self.life = self.life + val
401.     if self.life > 10 then
402.         self.life = 10
403.     end
404.     self.lifeText = self:setStat(self.life)
405. end
406.
407. function Player:modMana(val)
408.     self.mana = self.mana + val
409.     if self.mana >= self.maxMana then
410.         self.mana = self.maxMana
411.     end
412.     if self.mana <= 0 then
413.         self.mana = 0
414.     end
415.     self.manaText = self:setStat(self.mana)
416. end
417.
418. -- convert numeral stats to graphics so it can be displayed
419. function Player:setStat(val)
420.     local txt = ""
421.     for i=1, val do
422.         txt = txt.."|"
423.     end
424.     return txt
425. end
426.
427.
428. function Player:draw()
429.     local pos = self.model
430.     local target = self.target.model
431.     local stick = self.gui.stick
432.
433.     -- draw all minions
434.     for i=1, 5 do
435.         local minion = self.summons[i]
436.         if minion then
438.                 self.summons[i] = nil
439.             else
440.                 translate(0,0,.2)
441.                 minion:draw()
442.             end
443.         end
444.     end
445.
446.     self.direction = stick.direction
447.     -- do attack
448.     if self.attacking then
449.         self.direction = self.direction + math.sin(-self.timer*math.pi*2)
450.         self.timer = self.timer + DeltaTime
451.         if self.timer > 1 then
452.             self.attacking = false
453.             self.hasHit = false
454.             self.timer = 0
455.         end
456.     end
457.
458.     -- do shield
459.     if self.shielding then
460.         self.timer = self.timer + DeltaTime
461.         self:modMana(-DeltaTime*1.5)
462.         if self.mana == 0 then
463.             self.shielding = false
464.             self.timer = 0
465.         end
466.     end
467.
468.     -- do fire
469.     if self.fire then
470.         self.timer = self.timer + DeltaTime
471.         if self.timer > 1 then
472.             self.fire = false
473.             if not self.nearestEnemy.shielding then
474.                 self.nearestEnemy:modLife(-1)
475.             end
476.             self.timer = 0
477.         end
478.     end
479.
480.     -- do unsummon
481.     if self.unsummon then
482.         self.nearestEnemy.despawning = true
483.         self.unsummon = false
484.     end
485.
486.     -- do buff
487.     if self.buff then
488.         self.timer = self.timer + DeltaTime
489.         if self.timer > 1 then
490.             self.buff = false
491.             if self.nearestFriend then
492.                 self.nearestFriend:modLife(1)
493.                 self.nearestFriend:modPower(1)
494.             else
495.                 self:modMana(2)
496.             end
497.             self.timer = 0
498.         end
499.     end
500.
501.
502.     -- check if player can move, and move if possible
503.     if stick.active and not self:checkCollision() then
504.         pos.x = pos.x + math.cos(self.direction)*self.speed*60*DeltaTime
505.         pos.y = pos.y + math.sin(self.direction)*self.speed*60*DeltaTime
506.     end
507.         -- face other player
508.     -- local direction = math.atan2(target.y - pos.y, target.x - pos.x)
509.
510.     -- draw player based on stick direction
511.     self.model:draw(self.direction, stick.active)
512. end
513.
514. function Player:summon(mdl)
515.     -- add minion in front of player
516.     if self.mana >= 1 then
517.         local deltaX = self.model.x+50*math.cos(self.direction)
518.         local deltaY = self.model.y+50*math.sin(self.direction)
519.
520.         for i=1, 5 do
521.             if self.summons[i] == nil then
522.                 self.summons[i] = Summon(mdl, deltaX, deltaY, self.target, i)
523.                 self:modMana(-1)
524.                 return
525.             end
526.         end
527.
528.     end
529. end
530.
531. function Player:getNearestEnemy()
532.     local x = self.model.x - self.target.model.x
533.     local y = self.model.y - self.target.model.y
534.     local closest = -1
535.     local sqrt = math.sqrt
536.     local pos = self.model
537.
538.     local dist = 0
539.     local targ = nil
540.     -- test collision on enemy minions
541.     for i=1, 5 do
542.         local minion = self.target.summons[i]
543.         if minion then
544.             if not (minion.despawning or minion.spawning or minion.dying) then
545.                 x = pos.x - minion.model.x
546.                 y = pos.x - minion.model.y
547.                 dist = sqrt(x*x + y*y)
548.                 if dist < closest or closest == -1 then
549.                     targ = minion
550.                     closest = dist
551.                 end
552.             end
553.         end
554.     end
555.
556.     if closest == -1 then
557.         targ = self.target
558.     end
559.
560.     self.nearestEnemy = targ
561.
562. end
563.
564. function Player:getNearestFriend()
565.     local closest = -1
566.     local sqrt = math.sqrt
567.     local pos = self.model
568.
569.     local dist = 0
570.     local targ = nil
571.     -- test collision on friendly minions
572.     for i=1, 5 do
573.         local minion = self.summons[i]
574.         if minion then
575.             if not (minion.despawning or minion.spawning or minion.dying) then
576.                 x = pos.x - minion.model.x
577.                 y = pos.x - minion.model.y
578.                 dist = sqrt(x*x + y*y)
579.                 if dist < closest or closest == -1 then
580.                     targ = minion
581.                     closest = dist
582.                 end
583.             end
584.         end
585.     end
586.
587.     if closest == -1 then
588.         targ = nil
589.     end
590.
591.     self.nearestFriend = targ
592.
593. end
594.
595.
596. function Player:checkCollision()
597.     local x, y
598.     local sqrt = math.sqrt
599.
600.     -- set collision point in front of player
601.     local deltaX = self.model.x + 15*math.cos(self.direction)
602.     local deltaY = self.model.y + 15*math.sin(self.direction)
603.
604.     -- test collision on opposing player
605.     x = deltaX - self.target.model.x
606.     y = deltaY - self.target.model.y
607.     if sqrt(x*x + y*y) < 15 then
608.         return true
609.     end
610.
611.     -- test collision on enemy minions
612.     for i=1, 5 do
613.         local minion = self.target.summons[i]
614.         if minion then
615.             if not (minion.despawning or minion.spawning or minion.fighting) then
616.                 x = deltaX - minion.model.x
617.                 y = deltaY - minion.model.y
618.
619.                 if sqrt(x*x + y*y) < 15 then
620.                     return true
621.                 end
622.             end
623.         end
624.     end
625.
626.     return false
627.
628. end
629.
630. --# Summon
631. Summon = class()
632.
633. function Summon:init(mdl, x, y, target, id)
634.     self.id = id
635.
636.     -- numerical life and power
637.     self.life = 1+math.floor(math.random(3))
638.     self.power = 1
639.     -- update format of life and power
640.     self:modLife(0)
641.     self:modPower(0)
642.
643.     self.spawnTime = 1
644.
645.     self.combat = nil
646.
647.     -- model, position, scale, direction, spawn point and speed of minion
648.     self.model = Cube(mdl, x, y, 12)
649.     self.direction = math.atan2(target.model.y - self.model.y, target.model.x - self.model.x)
650.     self.spawn = vec2(x, y)
651.     self.speed = 1 + math.random()
652.
653.     -- current player target
654.     self.target = target
655.
657.
658.     self.spawning = true
659.     self.dying = false
660.     self.despawning = false
661.     self.fighting = false
662.     self.attackingPlayer = false
663.
664.     self.timer = 0
665. end
666.
667. function Summon:modLife(val)
668.     self.life = self.life + val
669.     self.lifeText = self:setStat(self.life)
670. end
671.
672. function Summon:modPower(val)
673.     self.power = self.power + val
674.     self.powerText = self:setStat(self.power)
675. end
676.
677. -- convert numeral stats to graphics so it can be displayed
678. function Summon:setStat(val)
679.     local txt = ""
680.     for i=1, val do
681.         txt = txt.."|"
682.     end
683.     return txt
684. end
685.
686. function Summon:draw()
687.     if self.life <= 0 then
688.         self.dying = true
689.     end
690.
691.     local pos = self.model
692.     local target = self.target.model
693.
694.
695.     -- draw minion in correct direction
696.     if self.dying then
697.         pushMatrix()
698.         translate(0, 0, -self.timer*50)
699.         pos:draw(self.direction, false)
700.         popMatrix()
701.     elseif self.spawning then
702.         if self.timer>self.spawnTime/2 then
703.             pos:draw(self.direction, false)
704.         end
705.     elseif self.despawning then
706.         if self.timer<.5 then
707.             pos:draw(self.direction, false)
708.         end
709.     else
710.         pos:draw(self.direction, not (self.fighting or self.attackingPlayer))
711.     end
712.
713.
714.     -- check if engaged in combat
715.     if self.combat then
716.         self.combat:doCombat()
717.         if not self.combat.inCombat then
718.             self.combat = nil
719.         end
720.         return
721.     end
722.
723.     -- stop movement until poping is done
724.     if self.spawning then
725.         self.direction = self.timer*(4*math.pi/self.spawnTime)
726.         self.timer = self.timer + DeltaTime
727.         if self.timer > self.spawnTime then
728.             self.spawning = false
729.             self.timer = 0
730.         end
731.         return
732.     end
733.
734.     -- stop movement until poping is done
735.     if self.despawning then
736.         self.direction = self.timer*(4*math.pi/self.spawnTime)
737.         self.timer = self.timer + DeltaTime
738.         if self.timer > 1 then
739.             self.despawning = false
740.             self.spawning = true
741.             self.timer = 0
742.             pos.x = self.spawn.x
743.             pos.y = self.spawn.y
744.         end
745.         return
746.     end
747.
748.     -- stop movement then die
749.     if self.dying then
750.         self.timer = self.timer + DeltaTime
751.         if self.timer > 1 then
752.             self.dying = false
753.             self.timer = 0
755.         end
756.         return
757.     end
758.
759.
760.     -- stop movement until attack to player is done, then respawn
761.     if self.attackingPlayer then
762.         if self.target.attacking and not self.target.hasHit then
763.             self:modLife(-1)
764.             self.target.hasHit = true
765.         end
766.         self.direction = math.atan2(target.y - pos.y, target.x - pos.x) + math.sin(self.timer*math.pi*2)
767.         self.timer = self.timer + DeltaTime
768.         if self.timer > .7 then
769.             if self.target.shielding then
770.                 self.target:modLife(-math.floor(self.power/2))
771.             else
772.                 self.target:modLife(-self.power)
773.             end
774.             self.attackingPlayer = false
775.             self.despawning = true
776.             self.timer = 0
777.         end
778.         return
779.     end
780.
781.     if not self.fighting then
782.         -- check distance to target
783.         local x = pos.x - target.x
784.         local y = pos.y - target.y
785.         local dist = math.sqrt(x*x + y*y)
786.         -- attack player when in range
787.         if not self.attackingPlayer and dist < 50 then
788.             self.attackingPlayer = true
789.             self.timer = 0
790.             return
791.         end
792.
793.         -- face target at all times
794.         self.direction = math.atan2(target.y - pos.y, target.x - pos.x)
795.         if not self:checkCollision() then
796.             pos.x = pos.x + math.cos(self.direction)*self.speed*60*DeltaTime
797.             pos.y = pos.y + math.sin(self.direction)*self.speed*60*DeltaTime
798.         end
799.     end
800.
801.
802.
803. end
804.
805. function Summon:checkCollision()
806.     local x, y, deltaX, deltaY, friend, enemy
807.
808.     local sqrt = math.sqrt
809.
810.     local dist
811.     for i=1, 5 do
812.
813.     -- check collision vs enemy minions and start fighting
814.         enemy = self.target.summons[i]
815.         if enemy and not (enemy.attackingPlayer or enemy.despawning or enemy.spawning or enemy.fighting) then
816.             x = self.model.x - enemy.model.x
817.             y = self.model.y - enemy.model.y
818.             dist = sqrt(x*x + y*y)
819.             if dist < 45 then
820.                 self.combat = Combat(self, enemy, dist)
821.                 return true
822.             end
823.         end
824.
825.     -- check collision vs friendly minions
826.         friend = self.target.target.summons[i]
827.         if friend and (friend.id ~= self.id) and not (friend.despawning or friend.spawning or friend.fighting) then
828.             -- set collision point in front of minion
829.             deltaX = self.model.x + 16*math.cos(self.direction)
830.             deltaY = self.model.y + 16*math.sin(self.direction)
831.             x = deltaX - friend.model.x
832.             y = deltaY - friend.model.y
833.
834.             if sqrt(x*x + y*y) < 15 then
835.                 return true
836.             end
837.         end
838.     end
839.
840.     return false
841.
842. end
843.
844.
845. --# Cube
846. Cube = class()
847.
848.
849. function Cube:init(mdl, x, y, s)
850.     self.x = x
851.     self.y = y
852.
853.     self.size = s
854.
855.     -- 3D model to be used
856.     self.mdl = mdl
857.
858.
859. end
860.
861. function Cube:draw(dir, moving)
862.     local direction = dir or 0
863.     direction = direction/math.pi*180
864.
865.     pushMatrix()
866.
867.     -- position 3D model
868.     translate(self.x,self.y, self.size/2+20)
869.
870.     -- animate 3D model
871.     if moving then
872.         rotate(math.sin(ElapsedTime*20)*5, 1, 1, 1)
873.     else
874.         rotate(math.sin(ElapsedTime*5)*1, 1, 1, 1)
875.     end
876.
877.     -- set 3D model orientation
878.     rotate(direction, 0, 0, 1)
879.     scale(self.size,self.size,self.size)
883.     end
884.     self.mdl:draw()
885.
886.
887.
888.     popMatrix()
889. end
890.
891.
892. --# Stick
893. Stick = class()
894.
895. function Stick:init()
896.     self.direction = 0
897.     self.dist = 0
898.
899.     self.active = false
900.     self.origin = vec2(150, 150)
901.     self.center = self.origin
902.     self.pos = self.origin
903.
904.     stroke(127, 127, 127, 127)
905.     strokeWidth(10)
906.     noFill()
907.     self.stick_bg = image(128, 128)
908.     setContext(self.stick_bg)
909.     ellipse(64, 64, 128)
910.
911.     noStroke()
912.     fill(192, 192, 192, 127)
913.     self.stick = image(96, 96)
914.     setContext(self.stick)
915.     ellipse(48, 48, 96)
916.
917. end
918.
919. function Stick:draw()
920.     sprite(self.stick_bg, self.center.x, self.center.y)
921.     sprite(self.stick, self.pos.x, self.pos.y)
922. end
923.
924. function Stick:touched(touch)
925.     if touch.state == BEGAN then
926.         self.center = vec2(touch.x, touch.y)
927.         self.active = true
928.     end
929.
930.     self.pos = vec2(touch.x, touch.y)
931.     self.direction = math.atan2(self.pos.y - self.center.y, self.pos.x - self.center.x)
932.
933.     self.dist = math.min(2, self.pos:dist(self.center)/32)
934.
935.     if touch.state == ENDED then
936.         self.center = self.origin
937.         self.pos = self.center
938.         self.active = false
939.     end
940.
941.
942. end
943.
944. --# Buttons
945. Buttons = class()
946.
947. function Buttons:init(type, x, y)
948.     self.type = type
949.     self.x = x
950.     self.y = y
951. end
952.
953. function Buttons:draw()
954.     if self.type == "summon" then
955.         sprite(graphics.buttonSummon, self.x, self.y)
956.     elseif self.type == "attack" then
957.         sprite(graphics.buttonAttack, self.x, self.y)
958.     elseif self.type == "shield" then
959.         sprite(graphics.buttonShield, self.x, self.y)
960.     elseif self.type == "fire" then
961.         sprite(graphics.buttonFire, self.x, self.y)
962.     elseif self.type == "buff" then
963.         sprite(graphics.buttonBuff, self.x, self.y)
964.     elseif self.type == "unsummon" then
965.         sprite(graphics.buttonUnsummon, self.x, self.y)
966.     end
967.
968.
969. end
970.
971. function Buttons:touched(touch)
972.     if touch.x > self.x - 48 and touch.x < self.x + 48 then
973.         if touch.y > self.y - 48 and touch.y < self.y + 48 then
974.             return self.type
975.         end
976.     end
977.     return false
978. end
979.
981. --Model = class()
982.
983. function Model(mdl, texture)
985.     local width, height = spriteSize(mdl)
986.
987.
988.
989.     local verts = {}
990.     local normals = {}
991.     local colors = {}
992.     local coords = {}
993.
994.     local a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, x, y, z, X, Y, n, size
995.     local strToChar = string.char
996.     local ins = table.insert
997.
998.
999.     cnt = 0
1000.     X = 1
1001.     Y = height
1002.
1003.     n = 1
1004.     a1, b1, c1 = img:get(X,Y)
1005.     X, Y = nextPixel(X, Y, width)
1006.     d1 = img:get(X,Y)
1007.     X, Y = nextPixel(X, Y, width)
1008.     size = bytesToFloat(strToChar(a1, b1, c1, d1))
1009.
1010.     cnt = 0
1011. -- vertices
1012.     while n<=size do
1013.         a1, b1, c1 = img:get(X,Y)
1014.         X, Y = nextPixel(X, Y, width)
1015.
1016.         d1, a2, b2 = img:get(X,Y)
1017.         X, Y = nextPixel(X, Y, width)
1018.
1019.         c2, d2, a3 = img:get(X,Y)
1020.         X, Y = nextPixel(X, Y, width)
1021.
1022.         b3, c3, d3 = img:get(X,Y)
1023.         X, Y = nextPixel(X, Y, width)
1024.
1025.         x = bytesToFloat(strToChar(a1, b1, c1, d1))
1026.         y = bytesToFloat(strToChar(a2, b2, c2, d2))
1027.         z = bytesToFloat(strToChar(a3, b3, c3, d3))
1028.
1029.         ins(verts, vec3(x, y, z))
1030.         n = n + 1
1031.     end
1032.     print(cnt.." for "..size.." vertices")
1033.     cnt = 0
1034. -- normals
1035.     n = 1
1036.     while n<=size do
1037.         a1, b1, c1 = img:get(X,Y)
1038.         X, Y = nextPixel(X, Y, width)
1039.
1040.         d1, a2, b2 = img:get(X,Y)
1041.         X, Y = nextPixel(X, Y, width)
1042.
1043.         c2, d2, a3 = img:get(X,Y)
1044.         X, Y = nextPixel(X, Y, width)
1045.
1046.         b3, c3, d3 = img:get(X,Y)
1047.         X, Y = nextPixel(X, Y, width)
1048.
1049.         x = bytesToFloat(strToChar(a1, b1, c1, d1))
1050.         y = bytesToFloat(strToChar(a2, b2, c2, d2))
1051.         z = bytesToFloat(strToChar(a3, b3, c3, d3))
1052.
1053.         ins(normals, vec3(x, y, z))
1054.         n = n + 1
1055.     end
1056.     print(cnt.." for "..size.." normals")
1057.     cnt = 0
1058. -- colors
1059.     n = 1
1060.     while n<=size do
1061.         a1, b1, c1 = img:get(X,Y)
1062.         X, Y = nextPixel(X, Y, width)
1063.
1064.         d1, a2, b2 = img:get(X,Y)
1065.         X, Y = nextPixel(X, Y, width)
1066.
1067.         c2, d2, a3 = img:get(X,Y)
1068.         X, Y = nextPixel(X, Y, width)
1069.
1070.         b3, c3, d3 = img:get(X,Y)
1071.         X, Y = nextPixel(X, Y, width)
1072.
1073.         x = bytesToFloat(strToChar(a1, b1, c1, d1))*255
1074.         y = bytesToFloat(strToChar(a2, b2, c2, d2))*255
1075.         z = bytesToFloat(strToChar(a3, b3, c3, d3))*255
1076.
1077.
1078.         ins(colors, color(x, y, z, 255))
1079.         n = n + 1
1080.     end
1081.     print(cnt.." for "..size.." colors")
1082.     cnt = 0
1083.
1084. -- texture coordinates
1085.     if texture then
1086.         n = 1
1087.         while n<=size do
1088.             a1, b1, c1 = img:get(X,Y)
1089.             X, Y = nextPixel(X, Y, width)
1090.
1091.             d1, a2, b2 = img:get(X,Y)
1092.             X, Y = nextPixel(X, Y, width)
1093.
1094.             c2, d2, a3 = img:get(X,Y)
1095.             X, Y = nextPixel(X, Y, width)
1096.
1097.             x = bytesToFloat(strToChar(a1, b1, c1, d1))
1098.             y = bytesToFloat(strToChar(a2, b2, c2, d2))
1099.
1100.             ins(coords, vec2(x,y))
1101.             n = n + 1
1102.         end
1103.     end
1104.
1105.     local total = 3*(size*4)+(size*3)+2
1106.     print(cnt.." for "..size.." texture coords")
1107.     print("total:"..total.." pixels, for a model of "..(size/3).." polygons")
1108.
1109.     local min = math.ceil(math.sqrt(total))
1110.     print("min img size:"..min.."x"..min)
1111.     cnt = 0
1112.
1113.     local data = mesh()
1114.     data.vertices = verts
1115.     data.colors = colors
1116.     data.normals = normals
1117.
1118.     if texture then
1119.         data.texture = texture
1120.         data.texCoords = coords
1122.     else
1124.     end
1125.
1128.
1129.     verts = nil
1130.     coords = nil
1131.     colors = nil
1132.     normals = nil
1133.     img = nil
1134.
1135.     return data
1136.
1137. end
1138.
1139.
1140.
1141. -- Converts a string of 4 bytes to a float
1142. function bytesToFloat(x)
1143.     local byte = string.byte
1144.     local ldexp = math.ldexp
1145.     local sign = 1
1146.     local mantissa = byte(x, 3) % 128
1147.     for i = 2, 1, -1 do
1148.         mantissa = mantissa * 256 + byte(x, i)
1149.     end
1150.     if byte(x, 4) > 127 then
1151.         sign = -1
1152.     end
1153.     local exponent = (byte(x, 4) % 128) * 2 + math.floor(byte(x, 3) / 128)
1154.     if exponent == 0 then
1155.         return 0
1156.     end
1157.     mantissa = (ldexp(mantissa, -23) + 1) * sign
1158.     return ldexp(mantissa, exponent - 127)
1159. end
1160.
1161. -- Goes to next available pixel
1162. function nextPixel(x, y, max)
1163.     cnt = cnt + 1
1164.     x = x + 1
1165.     if x>max then
1166.         x = 1
1167.         y = y - 1
1168.     end
1169.     return x, y
1170. end
1171.
1172. --# Graphics
1173. Graphics = class()
1174.
1175. function Graphics:init()
1176.     self.players = nil
1177.
1178.
1179.
1180.     -- 2D graphics
1188.
1191.
1196.
1197.
1198.     -- 3D graphics
1199.     if bnw then
1200.         self.toon = Model("Dropbox:model")
1201.     else
1202.         self.toon = Model("Dropbox:model", "Dropbox:texture2")
1203.     end
1204.    -- self.toon:setColors(128, 128, 128, 255)
1205.
1206.     self.shield = Model("Dropbox:model2") --,"Dropbox:shieldBubble")
1207.     self.shield:setColors(64, 225, 255, 128)
1208.
1209.     self.world = Model("Dropbox:worldModel")
1210.     if bnw then
1211.         self.world:setColors(255, 255, 255, 255)
1212.     end
1213.     self.sky = mesh()
1214.     self.skyId = self.sky:addRect(0, 0, 880, 880)
1215.     self.sky.texture = "Dropbox:sky"
1216.     self.sky:setColors(128, 128, 128, 100)
1217.
1218.     local rnd = math.random
1219.     local ins = table.insert
1220.     self.randoms = {}
1221.     for i=1, 10 do
1222.         ins(self.randoms, rnd())
1223.     end
1224. end
1225.
1226.
1227. function Graphics:draw()
1228.     local playerModel, minionModel
1229.
1231.     local spawn = self.spawn
1232.     pushStyle()
1233.     pushMatrix()
1234.     fontSize(8)
1235.
1236.
1237.
1238.
1239.     for _, player in ipairs(self.players) do
1240.         playerModel = player.model
1242.         translate(0,0,.2)
1244.
1245.         -- draw player life and mana
1246.         translate(0,0,.2)
1247.         fill(0, 255, 0, 255)
1248.         text(player.life.." "..player.lifeText, playerModel.x, playerModel.y - 20)
1249.         fill(0, 0, 255, 255)
1250.         text(player.manaText, playerModel.x, playerModel.y - 30)
1251.
1252.         for i=1, 5 do
1253.             minion = player.summons[i]
1254.             if minion then
1255.                 minionModel = minion.model
1256.
1257.                 -- draw minion spawn point and shadow
1258.                 translate(0,0,.2)
1259.                 sprite(spawn, minion.spawn.x, minion.spawn.y)
1260.                 translate(0,0,.2)
1262.
1263.                 -- draw minion life and power
1264.                 translate(0,0,.2)
1265.                 fill(0, 255, 0, 255)
1266.                 text(minion.lifeText, minionModel.x, minionModel.y - 15)
1267.                 fill(255, 0, 0, 255)
1268.                 text(minion.powerText, minionModel.x, minionModel.y - 25)
1269.             end
1270.         end
1271.     end
1272.
1273.  for _, player in ipairs(self.players) do
1274.         if player.shielding then
1275.             self:drawShield(player)
1276.         end
1277.
1278.         translate(0,0,.2)
1279.         if player.fire then
1280.             pushMatrix()
1281.             translate(player.nearestEnemy.model.x,player.nearestEnemy.model.y,0)
1282.             local n = math.cos(player.timer*4.5)
1283.             scale(n,n,1)
1284.             if player.timer>.5 then
1285.             sprite("Dropbox:blast4", 0, 0, 50)
1286.
1287.             translate(0,0,35)
1288.             sprite("Dropbox:blast2", 0, 0, 100)
1289.
1290.             translate(0,0,35)
1291.             sprite("Dropbox:blast4", 0, 0, 75)
1292.             end
1293.             translate(0,0,260)
1294.             rotate(90, 1,0,0)
1295.             rotate((player.timer)*720, 0,1,0)
1296.             sprite(graphics.bolt, 0,0, 100-math.sin(player.timer*2)*100, 512)
1297.         --    rotate(math.pi/2+(player.timer)*math.pi/2, 0,1,0)
1298.       --      sprite(graphics.bolt, 0,0, 100-math.sin(player.timer*2)*100, 512)
1299.             popMatrix()
1300.
1301.
1302.         end
1303.     end
1304.
1305.     local delta
1306.     for _, player in ipairs(self.players) do
1307.         playerModel = player.model
1308.         for i=1, 5 do
1309.             minion = player.summons[i]
1310.             if minion then
1311.                 minionModel = minion.model
1312.                 if minion.spawning or minion.despawning or minion.dying then
1313.                     local rnd = math.random
1314.                     if minion.spawning then
1315.                         delta = 1/minion.spawnTime
1316.                     else
1317.                         delta = 1
1318.                     end
1319.
1320.                     tint(255, 255, 255, 255-minion.timer*delta*255)
1321.
1322.                     for i=1, 5 do
1323.                         translate(0,0,.2)
1324.                         local n = 180 + self.randoms[i]*360
1325.                         pushMatrix()
1326.
1327.                         translate(minionModel.x,minionModel.y,i*15)
1328.                         scale(delta*minion.timer*n/540, delta*minion.timer*n/540, delta*minion.timer*n/540)
1329.                         rotate(n+math.sin(minion.timer)*n, 0,0,1)
1330.                         sprite(graphics.swirl, 0,0, 130)
1331.                         popMatrix()
1332.
1333.                     end
1334.                 end
1335.             end
1336.         end
1337.     end
1338.
1339.     popStyle()
1340.     popMatrix()
1341. end
1342.
1343. function Graphics:drawShield(player)
1344.     moving = true
1345.     local direction = player.timer*1800
1346.
1347.     local pos = player.model
1348.     pushMatrix()
1349.
1350.     -- position 3D model
1351.     translate(pos.x,pos.y, pos.size/2+20)
1352.
1353.     self.shield:setColors(0,0,255,64*math.abs(math.sin(player.timer*10)))
1354.
1355.     -- animate 3D model
1356.     if moving then
1357.         rotate(math.sin(ElapsedTime*20)*5, 1, 1, 1)
1358.     else
1359.         rotate(math.sin(ElapsedTime*5)*1, 1, 1, 1)
1360.     end
1361.
1362.     -- set 3D model orientation
1363.     rotate(direction, 0, 0, 1)
1364.     scale(pos.size,pos.size,pos.size)
1365.
1366.     self.shield:draw()
1367.
1368.     popMatrix()
1369. end
1370.
1371. function Graphics:drawWorld()
1372.
1373.
1374.     pushMatrix()
1375.
1376.     -- position 3D model
1377. --    translate(pos.x,pos.y, pos.size/2+20)
1378.
1379.
1380.     -- animate 3D model
1381.
1382.
1383.     -- set 3D model orientation
1384.   --  translate(0, 30, 0)
1385.     scale(40, 40, 40)
1386.