----------------------- -- Start of menu.lua -- ----------------------- -------------------------- -- Start of process.lua -- -------------------------- ----------------------- -- Start of glib.lua -- ----------------------- ------------------------------- -- Start of BetterLuaApi.lua -- ------------------------------- -- BetterLuaAPI for the TI-Nspire -- Version 3.5 (March 17th 2014) -- Adriweb 2013 -- http://tiplanet.org - http://inspired-lua.org -- Contributions by LDStudios -- Put all this or some of this (be careful, though, some functions use each other) in your code and thank me ;) ---------------------- ------ Utilities ----- ---------------------- -- Thanks John Powers (TI) ! -- Needed if OS < 3.2 if not platform.withGC then function platform.withGC(f) local gc = platform.gc() gc:begin() local result = { f(gc) } gc:finish() return unpack(result) end end -- Credits to Jim Bauwens :) -- See http://inspired-lua.org/index.php/2013/05/how-to-add-your-own-functions-to-gc/ -- Needed. function AddToGC(key, func) local gcMetatable = platform.withGC(getmetatable) gcMetatable[key] = func end ---------------------- ----- New Things ----- ---------------------- device = { api, hasColor, isCalc, theType, lang } device.api = platform.apilevel device.hasColor = platform.isColorDisplay() device.lang = locale.name() function on.resize(w, h) device.isCalc = platform.window:width() < 320 device.theType = platform.isTabletModeRendering and (platform.isTabletModeRendering() and "tablet" or "software") or (platform.isDeviceModeRendering() and "handheld" or "software") -- put the rest of your resize code here end Color = { ["black"] = { 0, 0, 0 }, ["red"] = { 255, 0, 0 }, ["green"] = { 0, 255, 0 }, ["blue "] = { 0, 0, 255 }, ["white"] = { 255, 255, 255 }, ["brown"] = { 165, 42, 42 }, ["cyan"] = { 0, 255, 255 }, ["darkblue"] = { 0, 0, 139 }, ["darkred"] = { 139, 0, 0 }, ["fuchsia"] = { 255, 0, 255 }, ["gold"] = { 255, 215, 0 }, ["gray"] = { 127, 127, 127 }, ["grey"] = { 127, 127, 127 }, ["lightblue"] = { 173, 216, 230 }, ["lightgreen"] = { 144, 238, 144 }, ["magenta"] = { 255, 0, 255 }, ["maroon"] = { 128, 0, 0 }, ["navyblue"] = { 159, 175, 223 }, ["orange"] = { 255, 165, 0 }, ["palegreen"] = { 152, 251, 152 }, ["pink"] = { 255, 192, 203 }, ["purple"] = { 128, 0, 128 }, ["royalblue"] = { 65, 105, 225 }, ["salmon"] = { 250, 128, 114 }, ["seagreen"] = { 46, 139, 87 }, ["silver"] = { 192, 192, 192 }, ["turquoise"] = { 64, 224, 208 }, ["violet"] = { 238, 130, 238 }, ["yellow"] = { 255, 255, 0 } } Color.mt = { __index = function() return { 0, 0, 0 } end } setmetatable(Color, Color.mt) local function copyTable(t) local t2 = {} for k, v in pairs(t) do t2[k] = v end return t2 end -- This function recursively copies a table's contents, and ensures that metatables are preserved. -- That is, it will correctly clone a pure Lua object. -- Taken from http://snippets.luacode.org/snippets/Deep_copy_of_a_Lua_Table_2 local function deepcopy(t) if type(t) ~= 'table' then return t end local mt = getmetatable(t) local res = {} for k, v in pairs(t) do if type(v) == 'table' then v = deepcopy(v) end res[k] = v end setmetatable(res, mt) return res end local function test(arg) return arg and 1 or 0 end local function uCol(col) return col[1], col[2], col[3] end local function screenRefresh() return platform.window:invalidate() end local function pww() return platform.window:width() end local function pwh() return platform.window:height() end local function drawPoint(gc, x, y) gc:fillRect(x, y, 1, 1) end local function drawCircle(gc, x, y, r) gc:drawArc(x-r, y-r, 2*r, 2*r, 0, 360) end local function fillCircle(gc, x, y, r) gc:fillArc(x-r, y-r, 2*r, 2*r, 0, 360) end local function fillGradientRect(gc,x,y,w,h,color1,color2,d) local l = {w,x} if d==2 then l = {h,y} end for i=l[2],l[1]+l[2] do gc:setColorRGB(color1[1],color1[2],color1[3]) if d==1 then gc:fillRect(i,y,1,h) else gc:fillRect(x,i,w,1) end color1={color1[1]+(color1[1]-color2[1])/(i-l[1]-l[2]),color1[2]+(color1[2]-color2[2])/(i-l[1]-l[2]),color1[3]+(color1[3]-color2[3])/(i-l[1]-l[2])} end end local function fillGradientCircle(gc,x,y,r,color1,color2) for i=0,r do gc:setColorRGB(color1[1],color1[2],color1[3]) gc:setPen("thick") drawCircle(gc,x,y,i) color1={color1[1]+(color2[1]-color1[1])/(r-i),color1[2]+(color2[2]-color1[2])/(r-i),color1[3]+(color2[3]-color1[3])/(r-i)} end end local function drawThickCircle(gc,x,y,r,r2) gc:setPen("thick") for i=r,r2 do drawCircle(gc,x,y,i) end end local function drawCenteredString(gc, str) gc:drawString(str, (platform.window:width() - gc:getStringWidth(str)) / 2, platform.window:height() / 2, "middle") end local function drawXCenteredString(gc, str, y) gc:drawString(str, (platform.window:width() - gc:getStringWidth(str)) / 2, y, "top") end local function setColor(gc, theColor) if type(theColor) == "string" then theColor = theColor:lower() if type(Color[theColor]) == "table" then gc:setColorRGB(uCol(Color[theColor])) end elseif type(theColor) == "table" then gc:setColorRGB(uCol(theColor)) end end local function verticalBar(gc, x) gc:fillRect(x, 0, 1, platform.window:height()) end local function horizontalBar(gc, y) gc:fillRect(0, y, platform.window:width(), 1) end local function drawSquare(gc, x, y, l) gc:drawPolyLine({ (x - l / 2), (y - l / 2), (x + l / 2), (y - l / 2), (x + l / 2), (y + l / 2), (x - l / 2), (y + l / 2), (x - l / 2), (y - l / 2) }) end local function drawRoundRect(gc, x, y, wd, ht, rd) -- wd = width, ht = height, rd = radius of the rounded corner local x = x - wd / 2 -- let the center of the square be the origin (x coord) local y = y - ht / 2 -- same for y coord if rd > ht / 2 then rd = ht / 2 end -- avoid drawing cool but unexpected shapes. This will draw a circle (max rd) gc:drawLine(x + rd, y, x + wd - (rd), y) gc:drawArc(x + wd - (rd * 2), y + ht - (rd * 2), rd * 2, rd * 2, 270, 90) gc:drawLine(x + wd, y + rd, x + wd, y + ht - (rd)) gc:drawArc(x + wd - (rd * 2), y, rd * 2, rd * 2, 0, 90) gc:drawLine(x + wd - (rd), y + ht, x + rd, y + ht) gc:drawArc(x, y, rd * 2, rd * 2, 90, 90) gc:drawLine(x, y + ht - (rd), x, y + rd) gc:drawArc(x, y + ht - (rd * 2), rd * 2, rd * 2, 180, 90) end local function fillRoundRect(gc, x, y, wd, ht, radius) -- wd = width and ht = height -- renders badly when transparency (alpha) is not at maximum >< will re-code later if radius > ht / 2 then radius = ht / 2 end -- avoid drawing cool but unexpected shapes. This will draw a circle (max radius) gc:fillPolygon({ (x - wd / 2), (y - ht / 2 + radius), (x + wd / 2), (y - ht / 2 + radius), (x + wd / 2), (y + ht / 2 - radius), (x - wd / 2), (y + ht / 2 - radius), (x - wd / 2), (y - ht / 2 + radius) }) gc:fillPolygon({ (x - wd / 2 - radius + 1), (y - ht / 2), (x + wd / 2 - radius + 1), (y - ht / 2), (x + wd / 2 - radius + 1), (y + ht / 2), (x - wd / 2 + radius), (y + ht / 2), (x - wd / 2 + radius), (y - ht / 2) }) local x = x - wd / 2 -- let the center of the square be the origin (x coord) local y = y - ht / 2 -- same gc:fillArc(x + wd - (radius * 2), y + ht - (radius * 2), radius * 2, radius * 2, 1, -91) gc:fillArc(x + wd - (radius * 2), y, radius * 2, radius * 2, -2, 91) gc:fillArc(x, y, radius * 2, radius * 2, 85, 95) gc:fillArc(x, y + ht - (radius * 2), radius * 2, radius * 2, 180, 95) end local function clearWindow(gc, theColor) gc:setColor(theColor) -- will handle both strings like "red" and direct colors like {255,0,0} gc:fillRect(0, 0, platform.window:width(), platform.window:height()) end ----------------------------------------- ------ Adding the functions to gc ------- ----------------------------------------- AddToGC("setColor", setColor) AddToGC("drawPoint", drawPoint) AddToGC("drawCircle", drawCircle) AddToGC("fillCircle", fillCircle) AddToGC("drawThickCircle", drawThickCircle) AddToGC("fillGradientCircle", fillGradientCircle) AddToGC("drawGradientRect", drawGradientRect) AddToGC("drawSquare", drawSquare) AddToGC("drawRoundRect", drawRoundRect) AddToGC("fillRoundRect", fillRoundRect) AddToGC("verticalBar", verticalBar) AddToGC("horizontalBar", horizontalBar) AddToGC("drawCenteredString", drawCenteredString) AddToGC("drawXCenteredString", drawXCenteredString) AddToGC("clearWindow", clearWindow) ----------------------------- -- End of BetterLuaApi.lua -- ----------------------------- platform.apiLevel = '2.3' local disp=platform.window local dispX=disp:width() local dispY=disp:height() function centerText(gc, text, midX, midY) gc:drawString(text, midX-gc:getStringWidth(text)/2, midY-gc:getStringHeight(text)/2, "top") end function centerTextWithRect(gc, text, midX, midY, rectColor) centerText(gc, text, midX, midY) gc:setColorRGB(rectColor) gc:drawRect(midX-gc:getStringWidth(text)/2, midY-gc:getStringHeight(text)/2, gc:getStringWidth(text), gc:getStringHeight(text)) end function drawBoard(gc, sBX, sBY, sX, sY, bW, bH)--sB-sizeBoard, sX-startX, sY-startY, bW-boardWidth, bH-boardHeight local sizeRectX=bW/sBX local sizeRectY=bH/sBY for i=0, sBY do gc:drawLine(sX, sY+sizeRectY*i, sX+bW, sY+sizeRectY*i) end for i=0, sBX do gc:drawLine(sX+sizeRectX*i, sY, sX+sizeRectX*i, sY+bH) end end function fTriangle(gc, x1, y1, x2, y2, x3, y3)--f=fill local points={{x1, y1}, {x2, y2}, {x3, y3}} for i=1, 3 do for j=i,3 do if points[i][2]>points[j][2] then local tmp={points[i][1], points[i][2]} points[i][1]=points[j][1] points[i][2]=points[j][2] points[j][1]=tmp[1] points[j][2]=tmp[2] elseif points[i][2]==points[j][2] then if points[i][1]>points[j][1] then local tmp={points[i][1], points[i][2]} points[i][1]=points[j][1] points[i][2]=points[j][2] points[j][1]=tmp[1] points[j][2]=tmp[2] end end end end if points[1][2]==points[2][2] then--two points are smaller coords. increment y local xSlope1=(points[3][1]-points[1][1])/(points[3][2]-points[1][2]) local xSlope2=(points[3][1]-points[2][1])/(points[3][2]-points[2][2]) local startX=points[1][1] local endX=points[2][1] if endX=360 then self.coords[5]=self.coords[5]-360 end if self.coords[6]>=360 then self.coords[6]=self.coords[6]-360 end gc:drawArc(self.coords[1], self.coords[2], self.coords[3], self.coords[4], self.coords[5], self.coords[6]) elseif self.type==6 then self:moveCoords(1, x, y) gc:drawString(self.data, self.coords[1], self.coords[2]) elseif self.type==7 then self:moveCoords(1, x, y) gc:drawImage(self.data, self.coords[1], self.coords[2]) elseif self.type==8 then self:moveCoords(1, x, y) gc:drawRoundRect(self.coords[1], self.coords[2], self.coords[3], self.coords[4], self.coords[5]) elseif self.type==9 then for i=1, #self.coords, 2 do self:moveCoords(i, x, y) end gc:fillPolygon(self.coords) elseif self.type==10 then self:moveCoords(1, x, y) gc:fillRect(self.coords[1], self.coords[2], self.coords[3], self.coords[4]) elseif self.type==11 then self.coords[1]=self.coords[1]+self.tx+x self.coords[2]=self.coords[2]+self.ty+y self.coords[5]=(self.coords[5]+self.rotAngle)%360 if self.coords[5]>=360 then self.coords[5]=self.coords[5]%360 end if self.coords[6]>=360 then self.coords[6]=self.coords[6]%360 end gc:fillArc(self.coords[1], self.coords[2], self.coords[3], self.coords[4], self.coords[5], self.coords[6]) elseif self.type==12 then self:moveCoords(1, x, y) gc:fillRoundRect(self.coords[1], self.coords[2], self.coords[3], self.coords[4], self.coords[5]) elseif self.type==13 then self:moveCoords(1, x, y) centerText(gc, self.data, self.coords[1], self.coords[2]) elseif self.type==14 then self:moveCoords(1, x, y) local tmpcolors1={math.floor(self.color/0x10000), math.floor((self.color%0x10000)/0x100), self.color%0x100} local tmpcolors2={math.floor(self.color2/0x10000), math.floor((self.color2%0x10000)/0x100), self.color%0x100} gc:fillGradientRect(self.coords[1], self.coords[2], self.coords[3], self.coords[4], tmpcolors1, tmpcolors2) elseif self.type==15 then self:moveCoords(1, x, y) gc:fillCircle(self.coords[1], self.coords[2], self.coords[3]) elseif self.type==16 then self.coords[1]=self.coords[1]+self.tx+x self.coords[2]=self.coords[2]+self.ty+y local tmpcolors1={math.floor(self.color/0x10000), math.floor((self.color%0x10000)/0x100), self.color%0x100} local tmpcolors2={math.floor(self.color2/0x10000), math.floor((self.color2%0x10000)/0x100), self.color%0x100} gc:fillGradientCircle(self.coords[1], self.coords[2], self.coords[3], tmpcolors1, tmpcolors2) end for i=1, #self.coords do self.coords[i]=self.tmpCoords[i] end end end do glib=class() function glib:init(width, height) self.width=width self.height=height self.Shapes={} self.rotAngle=0 end function glib:addShape(s, x, y, rotAngle) self.Shapes[#self.Shapes+1]=shape.clone(s) self.Shapes[#self.Shapes]:translate(x, y) end function glib:rotate(angle) self.rotAngle=angle%360 end function glib:changeRot(angle) self.rotAngle=(self.rotAngle+angle)%360 end function glib:draw(gc, x, y, mode) local changeX=0 local changeY=0 if mode~=nil then if mode=="middle" then changeX=self.width/2 changeY=self.height/2 elseif mode=="midtop" then changeX=self.width/2 elseif mode=="midbottom" then changeX=self.width/2 changeY=self.height end end gc:clipRect("set", x-changeX, y-changeY, self.width, self.height) for i=1, #self.Shapes do local tmp=self.Shapes[i].rotAngle self.Shapes[i]:rotate(self.Shapes[i].rotAngle+self.rotAngle) self.Shapes[i]:draw(gc, x, y) self.Shapes[i]:rotate(tmp) end gc:clipRect("reset") end end --------------------- -- End of glib.lua -- --------------------- require ('physics') local vec=physics.Vect local mouse=vec(0,0) local millis=timer.getMilliSecCounter process = class() process.inputEnabled=true process.priority=0--1 is always. 2 is run at least once every two runs. 3 can't skip 4 runs in a row. 4 only runs if fps is above target. Also set 0 if disabling process. This only increments unsuc/sets unsuc to 0 upon timer run process.paintPriority=0--0 if a background process process.targetFPS=30--if fps dips below target, then if priority is not 1 it will skip running the process unless it meets the minimum run amount process.lastRun=0--set to millis() upon starting process process.lastPaint=0 process.numUnsucRuns=0--resets after a successful run process.numPaintUnsuc=0 function process:setDefaults() self.inputEnabled=true self.priority=1 self.paintPriority=1 self.targetFPS=30 self.lastRun=millis() self.lastPaint=millis() end function process:deactivate() self.priority=0 self.paintPriority=0 self.inputEnabled=false end function process:deactivatePrior() self.priority=0 self.paintPriority=0 end function process:setBackground(priority) if priority~=nil then self.priority=priority self.lastRun=millis() end self.paintPriority=0 end function process:setPaintable(priority) self.paintPriority=priority self.lastPaint=millis() end function process:setPriorities(prior, paintPrior, input) self.priority=prior self.paintPriority=paintPrior self.lastRun=millis() self.lastPaint=millis() if input~=nil then self.inputEnabled=input else self.inputEnabled=true end end function process:init() end function process:paint(gc, x, y, width, height) end function process:timer() end function process:charIn(ch) end function process:arrowKey(key) end function process:escapeKey() end function process:enterKey() end function process:tabKey() end function process:contextMenu() end function process:backtabKey() end function process:backspaceKey() end function process:clearKey() end function process:mouseMove(x, y) end function process:mouseDown(x, y) end function process:mouseUp() end function process:rightMouseDown(x, y) end function process:help() end function process:varChange(varList) end function process:Open() end function process:Close() end function process:activate() end local processes = {} function PushProcess(proc) proc:setDefaults() proc:Open() table.insert(processes, proc) disp:invalidate() end function PullProcess() if #processes > 0 then processes[#processes]:Close() table.remove(processes) if #processes>0 then processes[#processes]:activate() end disp:invalidate() end end -- Link events to processManager function on.paint(gc, x, y, width, height) if x~=nil then print("x: "..x) end for _, proc in pairs(processes) do if proc.paintPriority==1 then proc:paint(gc, x, y, width, height) elseif proc.paintPriority==2 then if millis()-proc.lastPaint>=1000/proc.targetFPS then proc:paint(gc) proc.lastPaint=millis() else if proc.numPaintUnsuc>=1 then proc:paint(gc, x, y, width, height) proc.numPaintUnsuc=0 proc.lastPaint=millis() else proc.numPaintUnsuc=proc.numPaintUnsuc+1 proc.lastPaint=millis() end end elseif proc.paintPriority==3 then if millis()-proc.lastPaint>=1000/proc.targetFPS then proc:paint(gc, x, y, width, height) proc.lastPaint=millis() else if proc.numPaintUnsuc>=3 then proc:paint(gc, x, y, width, height) proc.numPaintUnsuc=0 proc.lastPaint=millis() else proc.numPaintUnsuc=proc.numPaintUnsuc+1 proc.lastPaint=millis() end end elseif proc.paintPriority==4 then if millis()-proc.lastPaint>=1000/proc.targetFPS then proc:paint(gc, x, y, width, height) proc.lastPaint=millis() end end end end function on.timer() for _, proc in pairs(processes) do if proc.priority==1 then proc:timer() proc.lastRun=millis() elseif proc.priority==2 then if millis()-proc.lastRun<=1000/proc.targetFPS then proc:timer() proc.lastRun=millis() else if proc.numPaintUnsuc>=1 then proc:timer() proc.numPaintUnsuc=0 proc.lastRun=millis() else proc.numPaintUnsuc=proc.numPaintUnsuc+1 proc.lastRun=millis() end end elseif proc.priority==3 then if millis()-proc.lastRun<=1000/proc.targetFPS then proc:timer() proc.lastRun=millis() else if proc.numPaintUnsuc>=3 then proc:timer() proc.numPaintUnsuc=0 proc.lastRun=millis() else proc.numPaintUnsuc=proc.numPaintUnsuc+1 proc.lastRun=millis() end end elseif proc.priority==4 then if millis()-proc.lastRun<=1000/proc.targetFPS then proc:timer() proc.lastRun=millis() end end end end function on.charIn(ch) for _, proc in pairs(processes) do if proc.inputEnabled then proc:charIn(ch) end end --disp:invalidate() end function on.arrowKey(key) for _, proc in pairs(processes) do if proc.inputEnabled then proc:arrowKey(key) end end --disp:invalidate() end function on.escapeKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:escapeKey() end end --disp:invalidate() end function on.enterKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:enterKey() end end --disp:invalidate() end function on.tabKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:tabKey() end end --disp:invalidate() end function on.contextMenu() for _, proc in pairs(processes) do if proc.inputEnabled then proc:contextMenu() end end --disp:invalidate() end function on.backtabKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:backtabKey() end end --disp:invalidate() end function on.backspaceKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:backspaceKey() end end --disp:invalidate() end function on.clearKey() for _, proc in pairs(processes) do if proc.inputEnabled then proc:clearKey() end end --disp:invalidate() end function on.mouseDown(x, y) for _, proc in pairs(processes) do if proc.inputEnabled then proc:mouseDown(x, y) end end --disp:invalidate() end function on.mouseUp() for _, proc in pairs(processes) do if proc.inputEnabled then proc:mouseUp() end end end function on.mouseMove(x, y) mouse=vec(x, y) for _, proc in pairs(processes) do if proc.inputEnabled then proc:mouseMove(x, y) end end end function on.rightMouseDown(x, y) for _, proc in pairs(processes) do if proc.inputEnabled then proc:rightMouseDown(x, y) end end --disp:invalidate() end function on.help() for _, proc in pairs(processes) do if proc.inputEnabled then proc:help() end end --disp:invalidate() end function on.varChange(varList) for _, proc in pairs(processes) do if proc.inputEnabled then proc:varChange(varList) end end --disp:invalidate() end ------------------------ -- End of process.lua -- ------------------------ local milSecs=1000--seconds to milliseconds local minSecs=60--seconds to minutes do menu=process() menu.items={} menu.backs={} menu.x=1 menu.curBack=1 menu.prevBackTime=millis() menu.backSecs=5 function menu:drawBackground(gc) if self.backs[self.curBack]~=nil then gc:drawImage(self.backs[self.curBack], -1,0) end end function menu:arrowKey(key) if key=="up" then if self.x>1 then self.x=self.x-1 else self.x=#self.items end elseif key=="down" then if self.x<#self.items then self.x=self.x+1 else self.x=1 end end disp:invalidate() end function menu:add(name, item) self.items[#self.items+1]={n=name, i=item, id=#self.items+1} end function menu:paint(gc) self:drawBackground(gc) for _, item in pairs(self.items) do gc:setColorRGB(0x000000) centerText(gc, item.n, dispX/2, dispY/2-gc:getStringHeight(item.n)*(#self.items-item.id-1)*2/3) if item.id==self.x then gc:drawRect(dispX/2-gc:getStringWidth(item.n)/2, dispY/2-gc:getStringHeight(item.n)*(#self.items-item.id-1/2)*2/3, gc:getStringWidth(item.n), gc:getStringHeight(item.n)*2/3) end end gc:setFont("sansserif", "r", 18) if self.title~=nil then if self.titleColor~=nil then gc:setColorRGB(self.titleColor) end centerText(gc, self.title, dispX/2, gc:getStringHeight(self.title)/2, "top") end end function menu:setBackSecs(secs) self.backSecs=secs end function menu:timer() if millis()-self.prevBackTime>self.backSecs*1000 then if self.curBack<#self.backs then self.curBack=self.curBack+1 else self.curBack=1 end self.prevBackTime=millis() end disp:invalidate() end function menu:addBackground(img) self.backs[#self.backs+1]=img:copy(dispX+1, dispY) end function menu:activate() self:setDefaults() end function menu:Open() self:setDefaults() end function menu:Close() self:deactivate() end function menu:enterKey() self:deactivate() PushProcess(self.items[self.x].i) disp:invalidate() end function menu:mouseDown(x, y) self:deactivate() PushProcess(self.items[self.x].i) disp:invalidate() end function menu:setTitle(title, color) self.title=title self.titleColor=color end end do readme=process() readme.hlpInfo="" readme.dispHelp=D2Editor.newRichText() function readme:Open() --self:deactivate() --self.inputEnabled=true self.dispHelp:setVisible(false) self.dispHelp:setText(self.hlpInfo, 1) self.dispHelp:move(0, 0) self.dispHelp:setBorder(0) self.dispHelp:setReadOnly(true) self.dispHelp:resize(dispX, dispY) self.dispHelp:setVisible(true) end function readme:timer() self.dispHelp:setFocus(true) end function readme:Close() self.dispHelp:setFocus(false) self.dispHelp:setVisible(false) end function readme:escapeKey() PullProcess() end function readme:backspaceKey() PullProcess() end function readme:setText(text) self.hlpInfo=text end end --[[do hlpScreen=process() hlpScreen.hlpInfo="Going to be made" hlpScreen.dispHelp=D2Editor.newRichText() function hlpScreen:Open() --self:deactivate() --self.inputEnabled=true self.dispHelp:move(0,0) self.dispHelp:setBorder(0) self.dispHelp:setReadOnly(true) self.dispHelp:setText(self.hlpInfo) self.dispHelp:resize(318, 212) self.dispHelp:setVisible(true) end function hlpScreen:Close() self.dispHelp:setVisible(false) end function hlpScreen:escapeKey() PullProcess() end end do settings=process() function settings:escapeKey() PullProcess() end end function on.construction() --menu:setBackground(image.new(_R.IMG.background)) --game:setBackground(image.new(_R.IMG.background)) --menu:add("Play", game) --menu:add("Help Screen", hlpScreen) --menu:add("Settings", settings) PushProcess(menu) disp:invalidate() end function on.activate() timer.start(5) disp:invalidate() end function on.deactivate() timer.stop() end]] --------------------- -- End of menu.lua -- --------------------- ------------------------- -- Start of hitbox.lua -- ------------------------- do hitbox=class() hitbox.width=0 hitbox.height=0 function round(num)--to nearest int return math.floor(num+0.5) end function hitbox:init(width, height) self.width=width self.height=height self:rst() end function hitbox:test(x, y, targX, targY)--x, y is top left if targX~=nil and targY~=nil then targX=round(targX-x) targY=round(targY-y) if targX>=0 and targX=0 and targY=0 and x=0 and ypoints[j][2] then local tmp={points[i][1], points[i][2]} points[i][1]=points[j][1] points[i][2]=points[j][2] points[j][1]=tmp[1] points[j][2]=tmp[2] elseif points[i][2]==points[j][2] then if points[i][1]>points[j][1] then local tmp={points[i][1], points[i][2]} points[i][1]=points[j][1] points[i][2]=points[j][2] points[j][1]=tmp[1] points[j][2]=tmp[2] end end end end if points[1][2]==points[2][2] then--two points are smaller coords. increment y local xSlope1=(points[3][1]-points[1][1])/(points[3][2]-points[1][2]) local xSlope2=(points[3][1]-points[2][1])/(points[3][2]-points[2][2]) local startX=points[1][1] local endX=points[2][1] if endX1 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