Advertisement
maxiking16

Bit Invader Makeover 0.2

Mar 13th, 2012
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 15.82 KB | None | 0 0
  1.  
  2. --# Main
  3. hero = nil
  4. enemies = nil
  5. bgLines = nil
  6. explosion = nil
  7.  
  8. GAME_PLAYING = 1
  9. GAME_PAUSE = 2
  10. GAME_DEAD = 0
  11. state = GAME_PLAYING
  12.  
  13. right = 1
  14. straight = 2
  15. left = 3
  16. heroState = straight
  17.  
  18. supportedOrientations(LANDSCAPE_ANY,PORTRAIT_ANY)
  19.  
  20. -- Use this function to perform your initial setup
  21. function setup()
  22.     state = GAME_PLAYING
  23.     displayMode(FULLSCREEN)
  24.     supportedOrientations(CurrentOrientation)
  25.     BackgroundSpawnRate = 3
  26.    
  27.     w = WIDTH
  28.     h = HEIGHT
  29.    
  30.     pc = color(127, 127, 127, 255)
  31.     npc = color(255, 255, 255, 255)
  32.     t = "Tyrian Remastered:Pause Circle"
  33.     pauseButton = button("pause",20,h - 70,70,h - 20,pc,npc,t)
  34.     t = "Tyrian Remastered:Arrow Left"
  35.     leftButton = button("left",20,50,100,100,pc,npc,t)
  36.     t = "Tyrian Remastered:Arrow Right"
  37.     rightButton = button("right",150,50,230,100,pc,npc,t)
  38.     t = "Tyrian Remastered:Icon Ship Shoot"
  39.     shootButton = button("shoot",w - 120,50,w - 50,120,pc,npc,t)
  40.     buttons = {pauseButton,leftButton,rightButton,shootButton}
  41.    
  42.     hero = Invader()
  43.     hero.position = vec2(WIDTH/2, 180)
  44.  
  45.     enemies = EnemyHorde()
  46.     enemies.heroBullets = hero.bullets
  47.  
  48.     bgLines = StreamingLines()
  49.    
  50.     highscore = readLocalData("highscore")
  51.  
  52.     if not highscore then
  53.         highscore = 0
  54.     end
  55. end
  56.  
  57. function touchingAtPos()
  58.     if CurrentTouch.state == BEGAN or CurrentTouch.state == MOVING then
  59.         return vec2( CurrentTouch.x, CurrentTouch.y)
  60.     end
  61.  
  62.     return nil
  63. end
  64.  
  65. -- This function gets called once every frame
  66. function draw()
  67.     background(0, 0, 0, 255)
  68.     pushStyle()
  69.     for b = 1,#buttons do
  70.         buttons[b]:touched()
  71.         buttons[b]:draw()
  72.     end
  73.     popStyle()
  74.     bgLines.spawnRate = BackgroundSpawnRate
  75.    
  76.     bgLines:update()
  77.     bgLines:draw()
  78.  
  79.     if state == GAME_PLAYING then
  80.         -- steer the hero
  81.         local ls = leftButton:getInfo()[2]
  82.         local rs = rightButton:getInfo()[2]
  83.         if ls == 1 or ls == 2 then
  84.             hero.position.x = hero.position.x - 5
  85.             heroState = left
  86.         elseif rs == 1 or rs == 2 then
  87.             hero.position.x = hero.position.x + 5
  88.             heroState = right
  89.         else
  90.             heroState = straight
  91.         end
  92.    
  93.        
  94.         if enemies.killCount == 5 then
  95.             enemies.spawnPattern = ENEMY_SPAWN_HARD
  96.         elseif enemies.killCount == 15 then
  97.             enemies.spawnPattern = ENEMY_SPAWN_DEADLY
  98.         end
  99.  
  100.         enemies:draw()
  101.  
  102.         hero:draw()
  103.  
  104.         -- Check if hero is hit
  105.         for i,v in ipairs(enemies.units) do
  106.             if v:dist(hero.position) < 60 then
  107.                 state = GAME_DEAD
  108.                 explosion = Explosion(hero.position)
  109.                 saveLocalData("highscore", highscore)
  110.                
  111.                 if score >= highscore then
  112.                     didGetHighScore = true
  113.                 end
  114.             end
  115.         end
  116.     elseif state == GAME_DEAD then
  117.         if explosion then
  118.             explosion:draw()
  119.             if explosion:isDone() then
  120.                 explosion = nil
  121.             end
  122.         end
  123.        
  124.         fontSize(60)
  125.         textMode(CENTER)
  126.         text("GAME OVER",WIDTH/2,HEIGHT/2)
  127.        
  128.         if didGetHighScore == true then
  129.             fontSize(40)
  130.             text("NEW HIGH SCORE!",WIDTH/2,HEIGHT/2 - 80)
  131.         end
  132.        
  133.     end
  134.    
  135.     -- setting text mode
  136.     fill(255)
  137.     font("Futura-CondensedExtraBold")
  138.     fontSize(30)
  139.     textMode(CORNER)
  140.    
  141.     -- update high score
  142.     score = enemies.killCount * 100
  143.     if score > highscore then
  144.         highscore = score
  145.     end
  146.    
  147.     hs = "High Score: "..highscore
  148.     hswidth = textSize(hs)
  149.     text(hs, WIDTH - hswidth - 10, HEIGHT - 50)
  150.    
  151.     -- Draw scores
  152.     s = "Score: "..score
  153.     swidth = textSize(s)
  154.     text(s, WIDTH - hswidth - 50 - swidth, HEIGHT - 50)
  155. end
  156.  
  157. --# EnemyHorde
  158. ENEMY_SPAWN_EASY = 0
  159. ENEMY_SPAWN_HARD = 1
  160. ENEMY_SPAWN_DEADLY = 2
  161.  
  162. EnemyHorde = class()
  163.  
  164. function EnemyHorde:init()
  165.     -- you can accept and set parameters here
  166.     self.frame = 0
  167.     self.units = {} -- enemy units
  168.     self.heroBullets = {} -- hero's bullets
  169.     self.explosions = {}
  170.     self.enemySize = 60
  171.     self.killCount = 0
  172.     self.spawnPattern = ENEMY_SPAWN_EASY
  173. end
  174.  
  175. function EnemyHorde:draw()
  176.     self.frame = (self.frame+1)%128
  177.  
  178.     pushStyle()
  179.  
  180.     stroke(217, 158, 105, 255)
  181.     strokeWidth(8)
  182.  
  183.     -- Spawn random enemy every 100 frames
  184.     if self.frame%100 == 0 then
  185.         spawn = vec2( math.random(WIDTH), HEIGHT + self.enemySize )
  186.         table.insert( self.units, spawn )
  187.     end
  188.  
  189.     for i,v in ipairs(self.units) do
  190.         -- Move unit down
  191.         v.y = v.y - 5    
  192.  
  193.         -- If hard, move in sine wave
  194.         if self.spawnPattern == ENEMY_SPAWN_HARD then
  195.             -- Compute movement vector
  196.             sideMove = vec2( math.sin(v.y * 0.02) * 60, 0 )
  197.             v = v + sideMove
  198.         elseif self.spawnPattern == ENEMY_SPAWN_DEADLY then
  199.             -- Compute movement vector
  200.             sideMove = vec2( math.sin(v.y * 0.02) * 100, 0 )
  201.             v = v + sideMove
  202.         end
  203.        
  204.         -- Cull unit
  205.         culled = false
  206.         if (v.y + self.enemySize) < 0 then
  207.             table.remove(self.units, i)
  208.             culled = true -- no continue statement
  209.         end
  210.  
  211.         -- Check if hit by a bullet
  212.         if culled == false then
  213.             for j,b in ipairs(self.heroBullets) do
  214.                 if v:dist(b) < self.enemySize/2 then
  215.                     table.remove(self.units, i)
  216.                     table.remove(self.heroBullets, j)
  217.                    
  218.                     -- Explode!
  219.                     table.insert(self.explosions, Explosion(v))
  220.  
  221.                     -- Update killCount
  222.                     self.killCount = self.killCount + 1
  223.                 end
  224.             end
  225.         end
  226.  
  227.         -- Draw unit
  228.         if self.spawnPattern == ENEMY_SPAWN_EASY then
  229.             sprite("Tyrian Remastered:Enemy Ship C 3", v.x, v.y, self.enemySize)
  230.         elseif self.spawnPattern == ENEMY_SPAWN_HARD then
  231.             sprite("Tyrian Remastered:Enemy Ship C 2", v.x, v.y, self.enemySize)
  232.         elseif self.spawnPattern == ENEMY_SPAWN_DEADLY then
  233.             sprite("Tyrian Remastered:Enemy Ship C 1", v.x, v.y, self.enemySize)
  234.         end
  235.     end
  236.  
  237.     -- Draw explosions
  238.     for i,e in ipairs(self.explosions) do
  239.         e:draw()
  240.  
  241.         if e:isDone() then
  242.             table.remove(self.explosions,i)
  243.         end
  244.     end
  245.  
  246.     popStyle()
  247. end
  248.  
  249. --# Invader
  250. Invader = class()
  251.  
  252. function Invader:init()
  253.     self.position = vec2(0,0)
  254.     self.bullets = {}
  255.     self.frame = 0
  256.     self.size = 65
  257.     self.texture = "Tyrian Remastered:Ship B"
  258. end
  259.  
  260. function Invader:spawnBullet()
  261.     sound("shoot",18)
  262.     table.insert( self.bullets, vec2( self.position.x, self.position.y + 30 ) )
  263. end
  264.  
  265. function Invader:drawBullets()
  266.     -- Spawn bullets
  267.     local ss = shootButton:getInfo()[2]
  268.     if ss == 1 or ss == 2 then
  269.         if self.frame%30 == 0 then
  270.             self:spawnBullet()
  271.         end
  272.     end
  273.     -- Move, draw, cull bullets
  274.     for i,v in ipairs(self.bullets) do
  275.         v.y = v.y + 3
  276.  
  277.         sprite("Tyrian Remastered:Bullet Fire C",v.x, v.y,10)
  278.  
  279.         if v.y > (HEIGHT + 10) then
  280.             table.remove(self.bullets,i)
  281.         end
  282.     end
  283. end
  284.  
  285. function Invader:draw()
  286.     self.frame = (self.frame + 1)%128
  287.  
  288.     pushMatrix()
  289.     pushStyle()
  290.    
  291.     -- Set up basic graphical style
  292.     smooth()
  293.  
  294.     -- Transform to pos
  295.     translate(self.position.x, self.position.y)
  296.    
  297.     -- Set the texture
  298.     if heroState == left then
  299.         self.texture = "Tyrian Remastered:Ship B L1"
  300.     elseif heroState == straight then
  301.         self.texture = "Tyrian Remastered:Ship B"
  302.     elseif heroState == right then
  303.         self.texture = "Tyrian Remastered:Ship B R1"
  304.     end
  305.    
  306.     -- Draw our invader
  307.     sprite(self.texture,0,0,self.size)
  308.     popMatrix()
  309.  
  310.     self:drawBullets()
  311.  
  312.     popStyle()
  313. end
  314.  
  315. function Invader:touched(touch)
  316.     -- Codea currently does not automatically call this method
  317. end
  318. --# Background
  319. -- This class draws the lines streaming past in the background
  320. -- of the game. We spawn and delete them in the self.lines table
  321.  
  322. ----------------------------------------------
  323. -- Single line
  324. ----------------------------------------------
  325. StreamLine = class()
  326. function StreamLine:init(pos, vel)
  327.     self.position = pos
  328.     self.velocity = vel
  329. end
  330.  
  331. function StreamLine:update()
  332.     self.position.y = self.position.y - self.velocity
  333. end
  334.  
  335. function StreamLine:draw()
  336.     p = self.position
  337.     line(p.x,p.y,p.x,p.y + self.velocity)
  338. end
  339.  
  340. function StreamLine:shouldCull()
  341.     -- Check if off the bottom of the screen
  342.     if (self.position.y + self.velocity) < 0 then
  343.         return true
  344.     end
  345.  
  346.     return false
  347. end
  348.  
  349. ----------------------------------------------
  350. -- All lines
  351. ----------------------------------------------
  352. StreamingLines = class()
  353.  
  354. function StreamingLines:init()
  355.     self.minSpeed = 5
  356.     self.speed = 30
  357.     self.spawnRate = 2
  358.     self.lines = {}
  359. end
  360.  
  361. function StreamingLines:updateAndCull()
  362.     toCull = {}
  363.     for i,v in ipairs(self.lines) do
  364.         if v:shouldCull() then
  365.             -- table.insert( toCull, i )
  366.             table.remove( self.lines, i )
  367.         else
  368.             v:update()
  369.         end
  370.     end
  371.  
  372.     -- print("Removing ", #toCull)
  373.     --for i = #toCull,1,-1 do
  374.     --    table.remove( self.lines, i )
  375.     --end
  376. end
  377.  
  378. function StreamingLines:update()
  379.     -- Create spawnRate lines per update
  380.     for i = 1,self.spawnRate do
  381.         -- Generate random spawn location
  382.         vel = math.random(self.minSpeed, self.speed)
  383.         spawn = vec2( math.random(WIDTH), HEIGHT + vel )
  384.  
  385.         table.insert(self.lines, StreamLine(spawn, vel))
  386.     end
  387.  
  388.     -- Update and cull offscreen lines
  389.     self:updateAndCull()
  390. end
  391.  
  392. function StreamingLines:draw()
  393.     --print("Num lines = ", #self.lines)
  394.  
  395.     pushStyle()
  396.  
  397.     noSmooth()
  398.     stroke(179, 153, 180, 173)
  399.     strokeWidth(2)
  400.     lineCapMode(SQUARE)
  401.  
  402.     for i,v in ipairs(self.lines) do
  403.         v:draw()
  404.     end
  405.  
  406.     popStyle()
  407. end
  408.  
  409. --# Other_Stuff
  410. -------------------|
  411. button = class() --|
  412. -------------------|
  413. -- by max tamussino
  414. -- contact: max@visuals.at
  415.  
  416. function button:init(title,x1,y1,x2,y2,colorPressed,colorNotPressed,image1,image2)
  417.     -- this button class makes it easier to create buttons. the best thing is: it keeps
  418.     -- the touched function short ;)
  419.     -- so here is how to use it:
  420.     -- - the title the title should be a string, and should represent the function of the button,
  421.     --   like: "closeButton"
  422.     -- - x1,y1,x2,y2 are the coordinates
  423.     -- - good to know: the button can either be a rect or a sprite (in spritely or not).
  424.     --        1) For the rect:
  425.     --        - colorPressed: the color the rect is filled with when the button is pressed.
  426.     --        - colorNotPressed: the color the rect is filled with when the button is not pressed.
  427.     --        - image1: must be set to ""rect"" (string!!).
  428.     --        - image2: must be nil.
  429.     --        - coordinates: for rectMode(CORNERS)
  430.     --        2) For the sprite:
  431.     --               Two possibilities:
  432.     --               a) changing image:
  433.     --                   - this possibility changes the normal image (image1) to image2 if
  434.     --                     the button is touched.
  435.     --                   - colorPressed and colorNotPressed both must be nil.
  436.     --                   - image1: normal image
  437.     --                   - image2: displayed instead of the normal one when touched.
  438.     --               b) changing tint:
  439.     --                   - this possibility changes the fill color of the sprite if the 1
  440.     --                     button is touched
  441.     --                   - colorPressed: the tint() if the button is not touched
  442.     --                   - colorNotPressed: the tint() if the button is touched
  443.     --                   - image2: must be nil
  444.     --
  445.     --
  446.     -- the button:getInfo() function returns a table with the title ( [1] )and the state( [2] ).
  447.     -- to use this, you can can keep track of your buttonstates like this:
  448.     --
  449.     --
  450.     --
  451.     --
  452.     --    if button:getInfo()[2] == 3 then
  453.     --        if button:getInfo()[1] == "closeButton" then
  454.     --            close()
  455.     --        elseif button:getInfo()[1] == "openMenuButton" then
  456.     --            if not menuShown then
  457.     --                menuShown = true
  458.     --            else
  459.     --                menuShown = false
  460.     --            end
  461.     --        elseif button:getInfo()[1] == "showHelpScreenButton" then
  462.     --            if not helpScreenShown then
  463.     --                helpScreenShown = true
  464.     --            else
  465.     --                helpScreenShown = false
  466.     --            end
  467.     --        end
  468.     --    end
  469.     --
  470.     -- i hope it helps you guys! have fun creating buttons! :)
  471.    
  472.     self.title = title
  473.     self.x1 = x1
  474.     self.y1 = y1
  475.     self.x2 = x2
  476.     self.y2 = y2
  477.     self.cp = colorPressed
  478.     self.cnp = colorNotPressed
  479.     self.image1 = image1
  480.     if not self.cp then
  481.         if not self.cnp then
  482.             self.image2 = image2
  483.         end
  484.     end
  485.     self.pressed = false
  486.     rectMode(CORNERS)
  487. end
  488.  
  489. function button:draw()
  490.     spriteMode(CORNERS)
  491.    
  492.     if self.state == 1 or self.state == 2 then
  493.         self.pressed = true
  494.     else
  495.         self.pressed = false
  496.     end
  497.    
  498.     if self.image1 == "rect" then
  499.         if self.pressed then
  500.             fill(self.cp)
  501.             rect(self.x1 - 1,self.y1 - 1,self.x2 - 1,self.y2 - 1)
  502.         else
  503.             fill(self.cnp)
  504.             rect(self.x1,self.y1,self.x2,self.y2)
  505.         end
  506.     elseif self.image2 then
  507.         if self.pressed then
  508.             sprite(self.image2,self.x1 - 2,self.y1 - 2,self.x2 - 2,self.y2 - 2)
  509.         else
  510.             sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
  511.         end
  512.     else
  513.         if self.pressed then
  514.             tint(self.cp)
  515.             sprite(self.image1,self.x1 - 2,self.y1 - 2,self.x2 - 2,self.y2 - 2)
  516.         else
  517.             tint(self.cnp)
  518.             sprite(self.image1,self.x1,self.y1,self.x2,self.y2)
  519.         end
  520.     end
  521.    
  522.     if self.state == 3 then
  523.         if ElapsedTime > endTime + 0.01 then
  524.             self.state = 0
  525.         end
  526.     end
  527. end
  528.  
  529. function button:touched()
  530.     t = CurrentTouch
  531.     if t.x > self.x1 and t.y > self.y1 and t.x < self.x2 and t.y < self.y2 then
  532.         if t.state == BEGAN then
  533.             self.state = 1
  534.             touching = true
  535.         elseif t.state == MOVING then
  536.             self.state = 2
  537.         elseif t.state == ENDED then
  538.             if touching then
  539.                 self.state = 3
  540.             end
  541.             touching = false
  542.             endTime = ElapsedTime
  543.         end
  544.     else
  545.         self.state = 0
  546.     end
  547. end
  548.  
  549. function button:getInfo()
  550.     return {self.title, self.state}
  551. end
  552.  
  553. -----------------------|
  554. Explosion = class()  --|
  555. -----------------------|
  556.  
  557. function Explosion:init(pos)
  558.     self.position = pos
  559.     self.opacity = 255
  560.     self.time = 0
  561.     self.lines = {}
  562.  
  563.     sound("explode",967)
  564.  
  565.     for i = 1,10 do
  566.         dir = vec2(0,1)
  567.         dir = dir:rotate( math.rad(math.random(360)) )
  568.         table.insert( self.lines, dir*math.random(2,7) )
  569.     end
  570. end
  571.  
  572. function Explosion:isDone()
  573.     return self.opacity <= 0
  574. end
  575.  
  576. function Explosion:draw()
  577.     self.time = self.time + 0.5
  578.    
  579.     pushStyle()
  580.  
  581.     lineCapMode(ROUND)
  582.     strokeWidth(20)
  583.     smooth()
  584.     stroke(255,255,255,math.max(self.opacity,0))
  585.  
  586.     p = self.position
  587.     for i,v in ipairs(self.lines) do
  588.         vt = p + v * self.time
  589.         line(p.x, p.y, vt.x, vt.y)
  590.     end
  591.  
  592.     self.opacity = 255 * (1 - (self.time/30));
  593.  
  594.     popStyle()
  595. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement