--include "menu.lua" --include "hitbox.lua" do game=process() local xSpd=65 local g=130 local jumpVel=-100 local spikeLen=18 local spikeWidth=25 local coords=vec(0,0) local vel=vec(xSpd,0) local displacement=vec(dispX/2, dispY/2) local accel=vec(0,g)--1 for slow speed up as you advance local bounds={vec(-dispX/4, -dispY/2), vec(dispX/4, dispY/2)} --local numSpikes=math.floor(vec(bounds[2]-bounds[1]):x()/spikeWidth) local lenSpikes=math.floor(vec(bounds[2]-bounds[1]):y()/spikeWidth+1) local clip=vec(bounds[1]+displacement) local endClip=vec(bounds[2]-bounds[1]) local curSpikes={1, 4, 8, lenSpikes} local round=0 local highscores={0,0} local multiplier=1 --[[local upTriangles=glib(vec(bounds[2]-bounds[1]):x(), spikeLen) local downTriangles=glib(vec(bounds[2]-bounds[1]):x(), spikeLen)]] local leftTriangle=shape() local rightTriangle=shape() local leftSpikeHitbox=hitbox() local rightSpikeHitbox=hitbox() local paintFlag=false local timesPainted=0 local curSprite={} local allSprites={} local emu=false local money=0 local iconSize=20 local spikeSubtracter=0x3F3F3F local colors={0xAFAFAF, 0x8F8FFF, 0x7FFF8F, 0xFF8F8F, 0x6F6F6F, 0x6F6FBF, 0x6FBF6F, 0xBF6F6F, 0xFFFFFF, 0xFFFF6F} local backgroundColor=colors[1] local spikeColor=backgroundColor-spikeSubtracter local mode=1 local modeNames={"classic", "timer"} local timerStart=0 local timerLength=2*milSecs*minSecs local timerY=2 local timerHeight=4 local timerWidth=100 do dying=process() function dying:Open() money=money+math.pow(round,2)/50 document.markChanged() end function dying:paint(gc) gc:setFont("serif", "r", 24) menu:drawBackground(gc) centerText(gc, "You died", dispX/2, 15) centerText(gc, "You got a score of "..round, dispX/2, 15+gc:getStringHeight("You died")) centerText(gc, "You earned "..math.floor((math.pow(round,2)/150)).." coins", dispX/2, 15+2*gc:getStringHeight("You died")) centerText(gc, "You have "..math.floor(money).." coins", dispX/2, 15+3*gc:getStringHeight("You died")) centerText(gc, "Your highscore is "..math.floor(highscores[mode]), dispX/2, 15+4*gc:getStringHeight("You died")) end function dying:escapeKey() PullProcess() end function dying:backspaceKey() PullProcess() end function dying:mouseDown() PullProcess() end function dying:tabKey() PullProcess() end function dying:enterKey() PullProcess() end end do selMode=process() function selMode:paint(gc) menu:drawBackground(gc) for i=1, #modeNames do gc:setColorRGB(0x000000) centerText(gc, modeNames[i], dispX/2, dispY/2-gc:getStringHeight(modeNames[i])*(#modeNames-i-1)*2/3) if mode==i then gc:drawRect(dispX/2-gc:getStringWidth(modeNames[i])/2, dispY/2-gc:getStringHeight(modeNames[i])*(#modeNames-mode-1/2)*2/3, gc:getStringWidth(modeNames[i]), gc:getStringHeight(modeNames[i])*2/3) end end end function selMode:enterKey() PullProcess() end function selMode:mouseDown() PullProcess() end function selMode:arrowKey(key) if key=="up" then if mode>1 then mode=mode-1 else mode=#modeNames end elseif key=="down" then if mode<#modeNames then mode=mode+1 else mode=1 end end disp:invalidate() end function selMode:escapeKey() PullProcess() end function selMode:backspaceKey() PullProcess() end end do sprite=class() local jumpTime=200 local abilY=10 local abilHeight=10 local abilLen=100 local startX=dispX/2-abilLen/2 local abilDispTime=400 local abilColor=0x00FFFF function sprite:init(img1, img2, rimg1, rimg2, cost, abil) self.img1=img1 self.img2=img2 self.rimg1=rimg1 self.rimg2=rimg2 if cost==0 or cost==nil then self.cost=0 self.unlocked=true else self.cost=cost self.unlocked=false end self.lastJump=0 self.prevAbil=0 self.abil={}--1: type, 2: recharge time, 3: image, 4: horizontally flipped image, 5 and on: stuff special to type, if exist if abil==nil then self.abil[1]=0 else for i=1, #abil do self.abil[i]=abil[i] end self.prevAbil=millis()-self.abil[2] end self.invincible=false end function sprite:jump() self.lastJump=millis() end function sprite:draw(gc, x, y) if self.abil[1]~=0 then local timeLeft=self.abil[2]+self.prevAbil-millis() if timeLeft<0 then timeLeft=0 end if timeLeft>self.abil[2] then timeLeft=self.abil[2] end gc:setColorRGB(0xFF*timeLeft/self.abil[2], 0xFF*(self.abil[2]-timeLeft)/self.abil[2], 0x00) gc:fillRect(startX, abilY, abilLen*(self.abil[2]-timeLeft)/self.abil[2], abilHeight) if timeLeft==0 then gc:setColorRGB(0x00, 0xFF*(self.abil[2]-timeLeft)/self.abil[2]-0x77, 0x00) gc:drawRect(startX, abilY, abilLen*(self.abil[2]-timeLeft)/self.abil[2], abilHeight) end if self.abil[5]~=nil and self.abil[5]~=0 then gc:setColorRGB(abilColor) if millis()-self.prevAbil0 then if self.lastJump+jumpTime>millis() then gc:drawImage(self.img2, x-self.img2:width()/2, y-self.img2:height()/2) else gc:drawImage(self.img1, x-self.img1:width()/2, y-self.img1:height()/2) end if self.abil[3]~=nil and self.abil[4]~=nil and millis()-self.prevAbilmillis() then gc:drawImage(self.rimg2, x-self.rimg2:width()/2, y-self.rimg2:height()/2) else gc:drawImage(self.rimg1, x-self.rimg1:width()/2, y-self.rimg1:height()/2) end if self.abil[3]~=nil and self.abil[4]~=nil and millis()-self.prevAbil0 then if self.abil[1]==1 then local tmp=math.random(#curSpikes) curSpikes[tmp]=curSpikes[#curSpikes] curSpikes[#curSpikes]=nil elseif self.abil[1]==2 then curSpikes={} elseif self.abil[1]==3 then self.invincible=true elseif self.abil[1]==4 then elseif self.abil[1]==5 then elseif self.abil[1]==6 then elseif self.abil[1]==7 then elseif self.abil[1]==8 then elseif self.abil[1]==9 then end self.prevAbil=millis() end end end function sprite:canDie() if self.invincible and self.abil[1]==3 then if millis()-self.prevAbil0 then return 1 elseif num<0 then return -1 else return 0 end end function game:Open() --[[local upTriangle=shape() local downTriangle=shape() local allUp={} local allDown={} upTriangle:polyLine({0, 0, spikeWidth, 0, spikeWidth/2, spikeLen, 0, 0}) downTriangle:polyLine({0, spikeLen, spikeWidth, spikeLen, spikeWidth/2, 0, 0, spikeLen}) upTriangle:setColorRGB(0x5F5F9F) downTriangle:setColorRGB(0x5F5F9F) for i=0, numSpikes do downTriangles:addShape(shape.clone(downTriangle), i*spikeWidth, 0, 0) upTriangles:addShape(shape.clone(upTriangle), i*spikeWidth, 0, 0) end]] timer.start(1/50) rightSpikeHitbox=hitbox(spikeLen+1, spikeWidth+2) leftSpikeHitbox=hitbox(spikeLen+1, spikeWidth+2) rightSpikeHitbox:fillTriangle(spikeLen, -1, spikeLen, spikeWidth+3, 0, spikeWidth/2-1) leftSpikeHitbox:fillTriangle(0, -1, 0, spikeWidth+3, spikeLen, spikeWidth/2-1) leftTriangle:fillPolygon({0, 0, 0, spikeWidth, spikeLen, spikeWidth/2, 0, 0}) rightTriangle:fillPolygon({spikeLen, 0, spikeLen, spikeWidth, 0, spikeWidth/2, spikeLen, 0}) rightTriangle:translate(-spikeLen, 0) leftTriangle:setColorRGB(spikeColor) rightTriangle:setColorRGB(spikeColor) paintFlag=false rst() curSprite:enableAbil() if platform.hw()>3 then emu=true end mode=0 end function game:activate() game:setDefaults() if mode==2 then timerStart=millis() end paintFlag=false disp:invalidate() end function game:Close() timer.stop() end function rst() coords=vec(0,0) vel=vec(xSpd,0) accel=vec(0, g) round=0 genSpikes() paintFlag=false disp:invalidate() end --[[function drawTriangles(gc) upTriangles:draw(gc, clip:x(), 0) downTriangles:draw(gc, clip:x(), dispY-spikeLen) end]] function genSpikes() multiplier=(-500)*(math.pow(1.025, -(round+172)))+8 local numRandSpikes=math.floor(multiplier) multiplier=math.pow(multiplier, 0.65) curSpikes={} local tmpSpikes={} for i=1, lenSpikes do tmpSpikes[i]=i end for i=1, numRandSpikes do local tmp=math.random(lenSpikes-i+1) if tmpSpikes[tmp]~=nil then curSpikes[i]=tmpSpikes[tmp] else print("not working "..tmp..","..(lenSpikes-i+1)) end tmpSpikes[tmp]=tmpSpikes[lenSpikes-i+1] tmpSpikes[lenSpikes-i+1]=nil end end function sideTriangles(gc) leftTriangle:setColorRGB(spikeColor) rightTriangle:setColorRGB(spikeColor) --gc:setColorRGB(spikeColor) for i=1, #curSpikes do if vel:x()>0 then rightTriangle:draw(gc, clip:x()+endClip:x(), (curSpikes[i]-1)*spikeWidth) --rightSpikeHitbox:draw(gc, clip:x()+endClip:x()-rightSpikeHitbox.width+1, (curSpikes[i]-1)*spikeWidth-1) else leftTriangle:draw(gc, clip:x(), (curSpikes[i]-1)*spikeWidth) --leftSpikeHitbox:draw(gc, clip:x(), (curSpikes[i]-1)*spikeWidth-1) end end end function die() if curSprite:canDie() then if highscores[mode]~=nil then if round>highscores[mode] then highscores[mode]=round end else highscores[mode]=round end PullProcess() menu:deactivate() PushProcess(dying) end end function bounce() if sign(vel:x())==sign(coords:x()) then vel:setx(-vel:x()) accel:setx(-accel:x()) round=round+1 genSpikes() end end function flap() vel:sety(jumpVel) curSprite:jump() end function game:paint(gc, x, y, width, height) if (not paintFlag) or emu then --[[gc:setColorRGB(0x7F7F7F) gc:fillRect(0,0,dispX,dispY)]] menu:drawBackground(gc) --gc:setColorRGB(0x000000) --leftSpikeHitbox:draw(gc) gc:clipRect("set", clip:x(), clip:y(), endClip:x(), endClip:y()) timesPainted=timesPainted+1 end local dispCoords=vec(coords+displacement) gc:setColorRGB(backgroundColor) gc:fillRect(clip:x(), clip:y(), endClip:x(), endClip:y()) --drawTriangles(gc) sideTriangles(gc) gc:setColorRGB(0x000000) gc:setFont("serif", "r", 24) centerText(gc, ""..round, dispX/2, dispY/2) --gc:setColorRGB(0xFF0000) --gc:fillRect(dispCoords:x()-5, dispCoords:y()-5, 10, 10) if mode==2 then local m=1-(millis()-timerStart)/timerLength gc:setColorRGB(0xFF*(1-m), 0xFF*m, 0x00) gc:fillRect((dispX-timerWidth*m)/2, timerY, timerWidth*m, timerHeight) end if x~=nil then gc:drawString(""..x, dispX/2, 20, 0, 0) end curSprite:draw(gc, dispCoords:x(), dispCoords:y()) paintFlag=true end function game:timer() if mode==0 then self:deactivate() mode=1 PushProcess(selMode) else updateColor() local mil=millis()-self.lastRun local fac=mil/1000*multiplier coords=coords+vel:mult(fac) vel=vel+accel:mult(fac) if coords:y()bounds[2]:y() then die() end --[[if (coords:x()bounds[2]:x()-spikeLen) and sign(vel:x())==sign(coords:x()) then for _, i in pairs(curSpikes) do if coords:y()+displacement:y()>(i-1)*spikeWidth and coords:y()+displacement:y()0 then if rightSpikeHitbox:test(clip:x()+endClip:x()-spikeLen, (i-1)*spikeWidth-1, coords:x()+displacement:x(), coords:y()+displacement:y()) then if mode==1 then die() elseif mode==2 then round=round-4 bounce() end end else if leftSpikeHitbox:test(clip:x(), (i-1)*spikeWidth-1, coords:x()+displacement:x(), coords:y()+displacement:y()) then if mode==1 then die() elseif mode==2 then round=round-4 bounce() end end end end if coords:x()bounds[2]:x() then bounce() end if timerStart+timerLength0 then Y=Y-1 if Y0 then X=X-1 end elseif key=="right" then if XnumIconsY then startY=startY+1 end end end disp:invalidate() end function unlock() if allSprites[Y*numIconsX+X+1]~=nil then if allSprites[Y*numIconsX+X+1].unlocked then curSprite=allSprites[Y*numIconsX+X+1] else if money>=allSprites[Y*numIconsX+X+1].cost or free==true then money=money-allSprites[Y*numIconsX+X+1].cost allSprites[Y*numIconsX+X+1].unlocked=true curSprite=allSprites[Y*numIconsX+X+1] document.markChanged() end end end disp:invalidate() end function game.store:enterKey() unlock() end function game.store:mouseDown() unlock() end function game.store:setFree() free=true end function game.store:clearKey() money=0 highscores={0,0} curSprite=allSprites[1] for i=1, #allSprites do if allSprites[i].cost~=0 then allSprites[i].unlocked=false end end disp:invalidate() end end function game:returnSave() local save={} save.money=money save.highscores={} save.unlocked={} for i=1, #allSprites do save.unlocked[i]=allSprites[i].unlocked end for i=1, #highscores do save.highscores[i]=highscores[i] end return save end function game:restoreSave(save) if save~=nil then money=save.money highscores={} for i=1, #allSprites do allSprites[i].unlocked=save.unlocked[i] end for i=1, #highscores do highscores[i]=save.highscores[i] end end end end function on.save() return game:returnSave() end function on.restore(state) game:restoreSave(state) end function on.construction() game:addSprite(image.new(_R.IMG.w1_1), image.new(_R.IMG.w1_2), image.new(_R.IMG.w1_3), image.new(_R.IMG.w1_4))--reg walrii game:addSprite(image.new(_R.IMG.w2_1), image.new(_R.IMG.w2_2), image.new(_R.IMG.w2_3), image.new(_R.IMG.w2_4), 50, {1, 5000, image.new(_R.IMG.w2_5), image.new(_R.IMG.w2_6)})--walrichu game:addSprite(image.new(_R.IMG.w3_1), image.new(_R.IMG.w3_2), image.new(_R.IMG.w3_3), image.new(_R.IMG.w3_4), 100, {3, 25000, nil, nil, 1500})--French walrii game:addSprite(image.new(_R.IMG.w4_1), image.new(_R.IMG.w4_2), image.new(_R.IMG.w4_3), image.new(_R.IMG.w4_4), 100, {2, 20000, image.new(_R.IMG.w4_5), image.new(_R.IMG.w4_6)})--Iron walrii game:addSprite(image.new(_R.IMG.w5_1), image.new(_R.IMG.w5_2), image.new(_R.IMG.w5_3), image.new(_R.IMG.w5_4), 200, {3, 21000, nil, nil, 1600})--Mosquito walrii game:addSprite(image.new(_R.IMG.w6_1), image.new(_R.IMG.w6_2), image.new(_R.IMG.w6_3), image.new(_R.IMG.w6_4), 250, {2, 18000})--Space walrii game:addSprite(image.new(_R.IMG.w7_1), image.new(_R.IMG.w7_2), image.new(_R.IMG.w7_3), image.new(_R.IMG.w7_4), 400, {2, 16000})--Sun walrii game:addSprite(image.new(_R.IMG.w8_1), image.new(_R.IMG.w8_2), image.new(_R.IMG.w8_3), image.new(_R.IMG.w8_4), 500, {1, 3500})--Cup walrii game:addSprite(image.new(_R.IMG.w9_1), image.new(_R.IMG.w9_2), image.new(_R.IMG.w9_3), image.new(_R.IMG.w9_4), 500, {3, 20000, nil, nil, 1800})--Zombie walrii game:addSprite(image.new(_R.IMG.w10_1), image.new(_R.IMG.w10_2), image.new(_R.IMG.w10_3), image.new(_R.IMG.w10_4), 1000, {2, 15000})--Moon walrii game:addSprite(image.new(_R.IMG.w11_1), image.new(_R.IMG.w11_2), image.new(_R.IMG.w11_3), image.new(_R.IMG.w11_4), 1500, {2, 12500})--Vader walrii game:addSprite(image.new(_R.IMG.w12_1), image.new(_R.IMG.w12_2), image.new(_R.IMG.w12_3), image.new(_R.IMG.w12_4), 2000, {3, 18000, nil, nil, 2000})--Nemo walrii --game.store:setFree() readme:setText("Walrii dts Nspire:\n\nContents:\n 1. Gameplay\n 1.1 Game modes\n 1.2 Different sprites and power ups\n 1.3 Status Bars\n 2. Controls\n 3. Credits\n \n1. Gameplay\n The goal of the game is to survive as long as possible without hitting the spikes. Thus you die if you hit a spike or hit the top or bottom of the screen.\n The game is similar to flappy bird in that you either jump or let yourself fall.\n You move back and forth between the sides, with new spikes being generated each time you switch sides.\n Your score is the number of times you've switched sides, and as your score increases the speed and number of spikes being generated also increases.\n Finally, you earn coins based on the number of points you get when you die. You can use coins to buy new sprites(see 1.2).\n \n 1.1 Game modes:\n There are two game modes: classic and timer.\n In classic you play as normal, and die if you hit a spike.\n In timer mode, the game lasts two minutes, and if you hit a spike your score decreases by three points. However, if you hit the ceiling you die, no matter how much time is left.\n When your two minutes are up or you hit the ceiling, you die, and your score is taken as normal.\n \n 1.2 Different sprites and power ups:\n Using your coins, you can buy new sprites. These sprites have abilities, which allow you to boost gameplay. Sprites vary from 50-2000 coins, and there are 12 of them in total(including the starting sprite).\n You buy new sprites in the store.\n There are three different types of abilities or power ups the sprites offer:\n 1. A few sprites have the ability to destroy one random spike. They take a small amount of type to regenerate, but are(in my opinion) not that useful.\n 2. A good amount of the sprites have the ability to destroy all the spikes in the round. This takes longer to regenerate, and is pretty useful.\n 3. Lastly, another good portion of the sprites have invincibility. When activated, the sprite cannot die for a certain amount of time. These take the longest to regenerate.\n \n 1.3 Status Bars:\n There are up to three status bars in the game at one time.\n The thin one highest up is only available in timer mode, and it shows how much time you have left. It grows smaller and gets gradually redder as less time is left.\n The thick one near the top shows the status of the ability. If it is fully charged up, green, and with a dark green border, the ability is ready. Otherwise it grows and gets gradually greener as reaching completeness.\n The blue thick one near the bottom only appears when you activate the invincibility ability. It shows how much time is left until the invincibility wears off.\n\n2. Controls\n You flap your wings/jump by pressing Enter or clicking.\n You activate the ability by pressing tab or any key under on.charIn(c), which includes, but is not limited to, pressing an alphanumerical key.\n \n Use the up and down arrow keys to navigate the menu, and press backspace/escape to exit out of a process, going back to the main menu(usually).\n Use the four arrow keys to navigate the store, and click/press enter to buy or select a sprite. Just having your cursor over the sprite will not select it.\n \n3. Credits\n The game was developed by Andrew Krapivin, otherwise known as semiprocoder or awesommee333. You can contact me by emailing andyhsstudent@gmail.com.\n Thanks goes to adriweb and ldstudios for their Better than Lua api.") menu:add("play", game) menu:add("store", game.store) menu:add("ReadMe", readme) menu:setTitle("Walrii DTS", 0x00FFFF) menu:addBackground(image.new(_R.IMG.background)) PushProcess(menu) end