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