Home ← TI-Nspire Authoring ← Lua Scripting HQ ← Lua and JavaScript
Todo: - Image support - Font size support - Physics support - Toolpallete support - Clipboard - D2Editor - coroutine (possibly not possible) - string functions - keyboard improvements
-- by Marc Garneau, 2012 -- piman@telus.net -- http://web.me.com/piman2/PimanNspire/Blog/Blog.html -- presented at T^3 International Conference • Chicago, IL • March 3, 2012 -- This is a simple version of using counters to model integers, -- for the purpose of introducing classes in a workshop. -- There are other features I plan to add later; see list at bottom. platform.apilevel = '1.0' Color = { red = {0xFF, 0x00, 0x00}, yellow = {0xFF, 0xFF, 0x00}, } function reset() -- The Objects list will get new generated counters, but starts with one. Objects = { Circle(xstart, ystartred, W/20, "red",-1), Circle(xstart, ystartyellow, W/20, "yellow",1), } z = 1 end function on.resize() W = platform.window:width() H = platform.window:height() xstart = 7*W/8 xmat = 3*W/4 ystartyellow = H/2 ystartred = 5*H/6 TrackedObject = nil -- TrackOffsetx = 0 -- TrackOffsety = 0 reset() end Circle = class() function Circle:init(x, y, radius,color,value) self.x = x self.y = y self.radius = radius self.color = Color[color] self.selected = false self.value = value end function Circle:contains(x, y) local r = self.radius local d = math.sqrt((self.x - x)^2 + (self.y - y)^2) return d <= r end function Circle:paint(gc) local cx = self.x - self.radius local cy = self.y - self.radius local diameter = 2*self.radius gc:setColorRGB(unpack(self.color)) gc:fillArc(cx, cy, diameter, diameter, 0, 360) gc:setPen("thin","smooth") gc:setColorRGB(0, 0, 0) gc:drawArc(cx, cy, diameter, diameter, 0, 360) if self.selected then gc:setPen("medium","smooth") gc:setColorRGB(0, 0, 0) gc:drawArc(cx, cy, diameter, diameter, 0, 360) end end -- this does more than count the value of the counters; it also sends counters back to their starting position if they are moved to the right of the mat; -- it also moves counters back onto the mat if they go too far off of the mat function count() value = 0 for i = 1, #Objects do local obj = Objects[i] if obj.x < xmat then value = value + obj.value else obj.x = xstart if obj.value == 1 then obj.y = ystartyellow else obj.y = ystartred end end if obj.x < 0 then obj.x = obj.radius end if obj.y > H then obj.y = H-obj.radius end if obj.y < 0 then obj.y = obj.radius end end end function on.mouseDown(x,y) for i = 1, #Objects do local obj = Objects[i] if obj:contains(x, y) then TrackedObject = obj obj.selected = true -- this avoids the object jumping to centre when you don't put the mouse down in the centre -- TrackOffsetx = TrackedObject.x - x -- TrackOffsety = TrackedObject.y - y -- this is the coolest part; if I grab a counter from the right, it will create a new one to replenish the supply! if obj.x == xstart then if obj.y == ystartred then table.insert(Objects, Circle(xstart, ystartred, W/20, "red",-1)) else table.insert(Objects, Circle(xstart, ystartyellow, W/20, "yellow",1)) end end platform.window:invalidate() break end end end function on.mouseUp(x,y) if TrackedObject ~= nil then TrackedObject.selected = false end TrackedObject = nil platform.window:invalidate() end function on.mouseMove(x,y) if TrackedObject ~= nil then TrackedObject.x = x -- + TrackOffsetx TrackedObject.y = y -- + TrackOffsety platform.window:invalidate() end end -- use tab key to toggle whether the value shows or not function on.tabKey() if z == 0 then z = 1 else z = 0 end platform.window:invalidate() end function on.charIn(char) if char=="r" or char=="R" then reset() end platform.window:invalidate() end function on.deleteKey() reset() platform.window:invalidate() end function on.paint(gc) gc:setColorRGB(204,204,204) gc:fillRect(0,0,xmat,H) gc:setColorRGB(0,0,0) gc:setPen("thick","smooth") gc:drawRect(xmat,0,0,H) for hippo, obj in ipairs(Objects) do obj:paint(gc) end count() gc:setColorRGB(0,0,0) gc:setFont("sansserif","r",10) if #Objects > 2 then gc:drawString("(R)eset",5,0.99*H) end if z == 1 then -- gc:drawString("Press TAB to hide total value.",10,20) gc:setFont("sansserif", "b", 10) gc:drawString("Value = "..value,xmat+W/50,20) else -- gc:drawString("Press TAB to show total value.",10,20) end gc:setFont("sansserif", "b", 16) gc:drawString("+",xstart-W/50,ystartyellow-W/20) gc:drawString("-",xstart-W/50,ystartred-W/20) end -- Things to do next -- Track off-set to avoid pointer jumping to center of each counter -- zero pairs -- Use arrow keys to undo/redo -- Animate movement -- Snap counters to grid, with overlap causing a 0 -- menu to choose colours of counters -- give a number line representation of what's being modeled (maybe just do that on a split page with a Graph's app) -- change pointer to hand