Bjornir90

Project alpha test

Aug 5th, 2013
108
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --Version 2.4.0
  2.  
  3.  
  4. local termX, termY = term.getSize()
  5. local midX = math.floor(termX/2)
  6.  
  7. print("Loading API")
  8. os.loadAPI("projectalpha/gameutils")
  9. os.loadAPI("projectalpha/gui")
  10. print("Loading game")
  11.  
  12. local player = gameutils.loadSprite("projectalpha/.sprites/player.nfp", math.floor(termX/2)-2, termY-2)
  13. local quit = false
  14. local timer = nil
  15. local timerID = nil
  16. local buffer = {}
  17. local drawn = {}
  18. local oldPix = paintutils.drawPixel
  19. local gameSpeed = 0.1 --in second
  20. local pause = false
  21. local score = 0
  22. local lives = 3
  23. local dodging = false
  24. local projID = 0
  25. local ennemyID = 0
  26. local invincible = false
  27. local devmode = false
  28. local _log = "****Game initialized****\n"
  29. local Args = ...
  30. local firstLaunch = false
  31. local sendScore = false
  32.  
  33. local file = fs.open("projectAlpha/game.log", "w")
  34. file.write("Version 2.4.0 Indev\n")
  35. file.close()
  36.  
  37.  
  38. gameutils.initializeBuffer()
  39. gui.initializeLog()
  40.  
  41. local playerPos = {
  42.     x = math.floor(termX/2)-2,
  43.     y = termY-2,
  44. }
  45.  
  46. local missile = {
  47.  gameData = { exist = false,}
  48. }
  49.  
  50. local entities = {
  51.     projectile = {},
  52.     ennemy = {},
  53. }
  54.  
  55. --Initialize buffer
  56. for i=1, termY do
  57.  buffer[i] = {}
  58.  for u=1, termX do
  59.   buffer[i][u] = colors.black
  60.  end
  61. end
  62.  
  63.  
  64. local backbuffer = buffer
  65.  
  66. print("Loading done")
  67.  
  68.  
  69. local function flush()
  70.     local file = fs.open("projectAlpha/game.log", "a")
  71.     file.write(_log)
  72.     file.close()
  73. end
  74.  
  75. local function log(_string)
  76.     _log = _log.."\n".._string
  77. end
  78.  
  79. local function exit()
  80.     gui.clear()
  81.     print("Thanks you for playing project alpha :)")
  82.     log("****Game exited****")
  83.     for i=1, #entities.ennemy do
  84.         log("Ennemy still alive : "..entities.ennemy[i].id)
  85.     end
  86.     log("Total ennemies alive : "..#entities.ennemy)
  87.     log("Total ennemies spawned : "..ennemyID)
  88.     flush()
  89.     local f = fs.open("projectAlpha/score", "a")
  90.     f.write("Score on "..tostring(os.clock).." is : "..score.."\n")
  91.     f.close()
  92.     paintutils.drawPixel = oldPix
  93. end
  94.  
  95. --MENU FUNCTION
  96.  
  97. local function selectMain()
  98.     local select = gui.getSelection()
  99.     gui.clearBuffer()
  100.     if select == 1 then
  101.         log("Launching game")
  102.         main()
  103.     elseif select == 2 then
  104.         load()
  105.     elseif select == 3 then
  106.         optionMenu()
  107.     elseif select == 4 then
  108.      exit()
  109.     else
  110.         error("An error occured on variable : select from function main")
  111.     end
  112. end
  113.  
  114. local function mainMenu()
  115.     gui.clear()
  116.     gui.setButton(midX - 2, 4, "PLAY", colors.cyan, colors.blue)
  117.     gui.setButton(midX - 2, 8, "LOAD", colors.cyan, colors.blue)
  118.     gui.setButton(midX - 3, 12, "OPTION", colors.cyan, colors.blue)
  119.     gui.setButton(midX - 2, 16, "QUIT", colors.cyan, colors.blue)
  120.     gui.setHeader("                 MAIN MENU", colors.cyan)
  121.     gui.render()
  122.     selectMain()
  123. end
  124.  
  125. local function selectOption()
  126.     local select = gui.getSelection()
  127.     gui.clearBuffer()
  128.     if select == 1 then
  129.         return
  130.         --Choose difficulty via a box
  131.     elseif select == 2 then
  132.         gui.clear()
  133.         term.setCursorPos(1,5)
  134.         print("Bjornir90, coder, artist (kind of :p)")
  135.      print("GravityScore for luaide, an amazing program")
  136.      print("NitrogenFinger for his amazing gameutils API, and NpaintPro")
  137.      print("And i want to say that i had much fun doing this game, i learned a lot thanks to it, and i hope you will like it as much as i do, and that you'll maybe learn something from it (feel free to read it or use it in your program, just please give credit)")
  138.     elseif select == 3 then
  139.         mainMenu()
  140.     else
  141.         error("An error has occured on variable select in function option")
  142.     end
  143. end
  144.  
  145.  
  146. function optionMenu()
  147.     gui.clear()
  148.     gui.setButton(midX - 5, 5, "DIFFICULTY", colors.cyan, colors.blue)
  149.     gui.setButton(midX - 3, 9, "CREDITS", colors.cyan, colors.blue)
  150.     gui.setButton(midX - 3, 13, "CANCEL", colors.cyan, colors.blue)
  151.     gui.setHeader("                 Options", colors.cyan)
  152.     gui.render()
  153.     selectOption()
  154. end
  155.  
  156.  
  157.  
  158. --Optimize drawing of pixel
  159. --/!\ WARNING : do not write things or it will mess up everything !
  160.  
  161.  
  162. function paintutils.drawPixel(x,y,colour)
  163.  buffer[y][x] = colour
  164. end
  165.  
  166. --Save and load function
  167.  
  168. function save()
  169.     local file = fs.open("projectAlpha/saves/LastSave.sve", "w")
  170.     file.writeLine(playerPos.x)
  171.     file.writeLine(playerPos.y)
  172.     file.writeLine(score)
  173.     file.close()
  174.     print("Game successfully saved !")
  175.     log("Game saved")
  176. end
  177.  
  178.  
  179. function load()
  180.     local file = fs.open("projectAlpha/saves/LastSave.sve", "r")
  181.     playerPos.x = tonumber(file.readLine())
  182.     playerPos.y = tonumber(file.readLine())
  183.     score = tonumber(file.readLine())
  184.     file.close()
  185.     print("Game loaded !")
  186.     log("Game loaded")
  187. end
  188.  
  189. --Hostile ship related functions
  190.  
  191. local function spawn()
  192.     local posx = math.random(1, termX)
  193.     local rand = math.random(1,100)
  194.     if rand > 75 and #entities.ennemy < 5 then
  195.         local newEnnemy = gameutils.loadSprite("projectalpha/.sprites/ennemy.nfp", posx, 1)
  196.         newEnnemy.id = ennemyID
  197.         newEnnemy.gameData = {
  198.         x = posx,
  199.         y = 1,
  200.         speed = 1,
  201.         health = 1,
  202.         exist = true,
  203.     }
  204.         log("Ennemy loaded : "..ennemyID)
  205.         ennemyID = ennemyID + 1
  206.         table.insert(entities.ennemy, newEnnemy)
  207.         log("Ennemy spawned")
  208.     end
  209. end
  210.  
  211.  
  212.  
  213. local function handler()
  214.     for i=1, #entities.projectile do
  215.   if entities.projectile[i].gameData.y < 1 then
  216.    entities.projectile[i].gameData.exist = false
  217.         end
  218.      if entities.projectile[i].gameData.exist == true then
  219.         entities.projectile[i]:moveTo(entities.projectile[i].gameData.x, entities.projectile[i].gameData.y-2)
  220.         entities.projectile[i].gameData.y = entities.projectile[i].gameData.y-2
  221.      end
  222.     end
  223.     if missile.gameData.exist == true then
  224.      local x = {}
  225.      local y = {}
  226.      for i=1, #entities.ennemy do
  227.       local ennemy = entities.ennemy[i].gameData
  228.         --determine closest ennemy
  229.       y[i] = math.abs(missile.gameData.y-ennemy.y)
  230.         --Save every value in table
  231.       for u=1, #y do
  232.         --Check if it is the closest in table
  233.         missile.gameData.target.y = ennemy.y
  234.         missile.gameData.target.x = ennemy.x
  235.         if math.abs(missile.gameData.target.y-missile.gameData.y) > math.abs(missile.gameData.y-ennemy.y) then
  236.             if math.abs(missile.gameData.target.x-missile.gameData.x) > math.abs(missile.gameData.x-ennemy.x) then
  237.                 missile.gameData.target.y = ennemy.y
  238.                 missile.gameData.target.x = ennemy.x
  239.             end
  240.         end
  241.        end
  242.      end
  243.      --movement of missile
  244.      local _speed = 1
  245.      if missile.gameData.target.x+4 < missile.gameData.x then --missile on the right   
  246.       missile.gameData.going = "left"
  247.       missile.currentFrame = 1
  248.       missile:moveTo(missile.gameData.x-_speed, missile.gameData.y)
  249.       missile.gameData.x=missile.gameData.x-_speed
  250.      elseif missile.gameData.target.x-1 > missile.gameData.x then --missile on the left
  251.       missile.gameData.going = "right"
  252.       missile.currentFrame = 5
  253.       missile:moveTo(missile.gameData.x+_speed, missile.gameData.y)
  254.       missile.gameData.x=missile.gameData.x+_speed
  255.      else
  256.       missile.gameData.going = "nowhere"
  257.      end
  258.      if missile.gameData.y < missile.gameData.target.y+1 then --missile above ennemy
  259.       if missile.gameData.going == "left" then
  260.        missile.currentFrame = 6
  261.       elseif missile.gameData.going == "right" then
  262.        missile.currentFrame = 8
  263.       else
  264.        missile.currentFrame = 7
  265.       end
  266.       missile:moveTo(missile.gameData.x, missile.gameData.y+_speed)
  267.       missile.gameData.y = missile.gameData.y + _speed
  268.      elseif missile.gameData.y > missile.gameData.target.y+1 then --missile below ennemy
  269.       if missile.gameData.going == "left" then
  270.        missile.currentFrame = 2
  271.       elseif missile.gameData.going == "right" then
  272.        missile.currentFrame = 4
  273.       else
  274.        missile.currentFrame = 3
  275.       end
  276.       missile:moveTo(missile.gameData.x, missile.gameData.y-_speed)
  277.       missile.gameData.y = missile.gameData.y-_speed
  278.      end
  279.  end
  280.  
  281.     for i=1, #entities.ennemy do
  282.      local ennemy = entities.ennemy[i]
  283.     _speed = ennemy.gameData.speed
  284.      if playerPos.x+4 < ennemy.gameData.x then --ennemy on the right   
  285.       ennemy:moveTo(ennemy.gameData.x-_speed, ennemy.gameData.y)
  286.       ennemy.gameData.x=ennemy.gameData.x-_speed
  287.      elseif playerPos.x-1 > ennemy.gameData.x+4 then --ennemy on the left
  288.       ennemy:moveTo(ennemy.gameData.x+_speed, ennemy.gameData.y)
  289.       ennemy.gameData.x=ennemy.gameData.x+_speed
  290.      elseif ennemy.gameData.y < playerPos.y+1 then --ennemy above player
  291.        ennemy:moveTo(ennemy.gameData.x, ennemy.gameData.y+_speed)
  292.        ennemy.gameData.y = ennemy.gameData.y + _speed
  293.      elseif ennemy.gameData.y > playerPos.y+2 then --ennemy below player
  294.        ennemy:moveTo(ennemy.gameData.x, ennemy.gameData.y-_speed)
  295.        ennemy.gameData.y = ennemy.gameData.y-_speed
  296.      end
  297.     end --End of the ennemy for boucle
  298.     --Collisions
  299.     for i=1, #entities.projectile do
  300.         for u=1, #entities.ennemy do
  301.             if entities.projectile[i]:pCollidesWith(entities.ennemy[u]) then
  302.                 entities.projectile[i].gameData.exist = false
  303.                 entities.ennemy[u].gameData.exist = false
  304.                 score = score + 100
  305.                 log("Ennemy Killed with lasers")
  306.             end
  307.         end
  308.     end
  309.     for i=1, #entities.ennemy do
  310.      if missile.gameData.exist then
  311.      if missile:pCollidesWith(entities.ennemy[i]) then
  312.        missile.gameData.exist = false
  313.        entities.ennemy[i].gameData.exist = false
  314.        score = score + 75
  315.        log("Missile hit ennemy "..entities.ennemy[i].id)
  316.       end
  317.   end
  318.         if player:pCollidesWith(entities.ennemy[i]) then
  319.             lives = lives-1
  320.             entities.ennemy[i].gameData.exist = false
  321.             log("Player hit")
  322.             log("Player lives : "..lives)
  323.             if lives == 0 and invincible == false then
  324.                 quit = true
  325.             end
  326.         end
  327.     end
  328. end
  329.  
  330.  
  331. --Player movement
  332.  
  333. local function movementHandler(param1)
  334.     log("Key pressed : "..param1)
  335.     if param1 == keys.right then
  336.         player:moveTo(playerPos.x + 2, playerPos.y)
  337.         playerPos.x = playerPos.x + 2
  338.     elseif param1 == keys.left then
  339.         player:moveTo(playerPos.x - 2, playerPos.y)
  340.         playerPos.x = playerPos.x - 2
  341.     elseif param1 == keys.up then
  342.         player:moveTo(playerPos.x, playerPos.y-2)
  343.         playerPos.y = playerPos.y - 2
  344.     elseif param1 == keys.down then
  345.         player:moveTo(playerPos.x, playerPos.y+2)
  346.         playerPos.y = playerPos.y + 2
  347.     elseif param1 == keys.p then
  348.         pause = true
  349.     elseif param1 == keys.space then
  350.      local newProj = gameutils.loadSprite("projectalpha/.sprites/pPlayer.nfp", playerPos.x+2, playerPos.y - 3)
  351.         newProj.id = projID
  352.        
  353.         newProj.gameData = {
  354.             x = playerPos.x + 2,
  355.             y = playerPos.y - 3,
  356.             exist = true
  357.         }
  358.        
  359.         log("Projectile loaded : "..projID)
  360.         projID = projID + 1
  361.         table.insert(entities.projectile, newProj)
  362.  elseif param1 == keys.f and missile.gameData.exist == false then
  363.   missile = gameutils.loadAnimation("projectAlpha/.sprites/mPlayer.nfa", playerPos.x+2, playerPos.y-3)
  364.  
  365.   missile.gameData = {
  366.    x=playerPos.x+2,
  367.    y=playerPos.y-3,
  368.    exist = true,
  369.    target = {
  370.     x=0,
  371.     y=0
  372.    },
  373.    going = "somewhere",
  374.   }
  375.  
  376.   log("Missile loaded")
  377.     elseif param1 == keys.q then
  378.         quit = true
  379.         return "exited"
  380.     elseif param1 == keys.c and devmode == true and invincible == false then
  381.         invincible = true
  382.     elseif param1 == keys.c and devmode == true and invincible == true then
  383.         invincible = false
  384.     end
  385.     return "ended"
  386. end
  387.  
  388. local function tutorial()
  389.  gui.clear()
  390.  print("Thanks for installing projectalpha !")
  391.  print("This is my first game and i hope you will enjoy it :)")
  392.  print("Keys :")
  393.  print("arrows = move")
  394.  print("space = lasers")
  395.  print("f = missile")
  396.  print("p = pause")
  397.  print("q = quit")
  398.  term.setTextColor(colors.red)
  399.  print("I would like to collect score using http API, for balance purpose")
  400.  print("Do you allow me to send your score ? (y/n)")
  401.  print("This can be changed in the meta.conf file, located in projectAlpha dir")
  402.  local input = read()
  403.  if input == "y" or input == "yes" then
  404.   gui.clear()
  405.   term.setTextColor(colors.white)
  406.   print("Thanks you for your help :)")
  407.   local f = fs.open("projectAlpha/meta.conf", "a")
  408.   f.write("sendscore=true;\n")
  409.   f.close()
  410.  end
  411.  gui.clear()
  412. end
  413.  
  414.  
  415. function main()
  416.  if firstLaunch == true then
  417.   tutorial() -- Need to write it
  418.  end
  419.  local timerID = os.startTimer(gameSpeed)
  420. while quit == false do
  421.     flush()
  422.     _log = ""
  423.     gui.clear()
  424.     local currentTime = tostring(os.clock())
  425.     log("Draw a frame at "..currentTime)
  426.     log("Player position : "..playerPos.x.." "..playerPos.y)
  427.     log("Missile is active : "..tostring(missile.gameData.exist))
  428.     if missile.gameData.exist then
  429.         log("Missile target x : "..tostring(missile.gameData.target.x).." y : "..tostring(missile.gameData.target.y))
  430.     end
  431.     --Draw entities
  432.     for i=1, #entities.ennemy do
  433.         gameutils.writeToBuffer(entities.ennemy[i])
  434.     end
  435.     for i=1, #entities.projectile do
  436.         gameutils.writeToBuffer(entities.projectile[i])
  437.     end
  438.     if missile.gameData.exist == true then
  439.      gameutils.writeToBuffer(missile)
  440.     end
  441.     gameutils.writeToBuffer(player)
  442.     if devmode == true then
  443.         paintutils.drawPixel(playerPos.x-1, playerPos.y, colors.red)
  444.         paintutils.drawPixel(playerPos.x+5, playerPos.y, colors.red)
  445.     end
  446.     gameutils.drawBuffer()
  447.    
  448.     -- Function that refresh screen using buffer
  449.     for i=1, termY do
  450.      for u=1, termX do
  451.       if buffer[i][u] ~= backbuffer[i][u] then
  452.        oldPix(u, i, buffer[i][u])
  453.       end
  454.      end
  455.     end
  456.  
  457.     if devmode == true then
  458.         term.setCursorPos(1,1)
  459.         print(timerID)
  460.         print(playerPos.x.." "..playerPos.y)
  461.         print("SCORE : "..score)
  462.         print("ENNEMIES ON SCREEN : "..tostring(#entities.ennemy))
  463.         print("INVINCIBLE : "..tostring(invincible))
  464.     end
  465.    
  466.     gameutils.clearBuffer()
  467.     local event, param, param1, param2 = os.pullEvent()
  468.    
  469.     if event == "key" then
  470.         movementHandler(param)
  471.     elseif event == "timer" then
  472.         if param == timerID then
  473.        
  474.             local rand = math.random(0,1000)
  475.             if second == 0 and rand >= 900 then
  476.                 gui.clear() term.setCursorPos(1,1) term.setTextColor(colors.red) print("Keep an eye out for an invasion from the Outside...") term.setTextColor(colors.white) sleep(0.5) gui.clear() second = 1
  477.             end
  478.            
  479.             spawn()
  480.             handler()
  481.             timerID = os.startTimer(gameSpeed)
  482.         end
  483.     end
  484.    
  485.     tempProjectile = entities.projectile
  486.     entities.projectile = {}
  487.     for i=1, #tempProjectile do     --Remake the table every time so no problem with ghosts projectiles
  488.         if tempProjectile[i].gameData.exist == true then
  489.             table.insert(entities.projectile, tempProjectile[i])
  490.         end
  491.     end
  492.     tempEnnemy = entities.ennemy
  493.     entities.ennemy = {}
  494.     for i=1, #tempEnnemy do     --Same here
  495.         if tempEnnemy[i].gameData.exist == true then
  496.             table.insert(entities.ennemy, tempEnnemy[i])
  497.         end
  498.     end
  499.    
  500.     if pause then
  501.         log("Game paused")
  502.         term.setBackgroundColor(colors.black)
  503.         term.clear()
  504.         term.setCursorPos(5,3)
  505.         write("Press P to resume game")
  506.         term.setCursorPos(5,4)
  507.         write("Press S to save game")
  508.         term.setCursorPos(5,5)
  509.         write("Press L to load game")
  510.         term.setCursorPos(5,6)
  511.         write("Press Q to quit game")
  512.         while true do
  513.             local event, key = os.pullEvent("key")
  514.             if key == keys.p then
  515.                 pause = false
  516.                 if gameSpeed == nil then
  517.                     flush()
  518.                     error("A needed variable is empty ! (gameSpeed)")
  519.                 end
  520.                 timerID = os.startTimer(gameSpeed)
  521.                 break
  522.             elseif key == keys.s then
  523.                 save()
  524.             elseif key == keys.l then
  525.                 load()
  526.             elseif key == keys.q then
  527.                 quit = true
  528.                 break
  529.             end
  530.         end
  531.     end
  532. end
  533. mainMenu()
  534.  
  535. end
  536.  
  537.  
  538. gui.clear()
  539. mainMenu()
RAW Paste Data