Last active
December 10, 2015 03:38
-
-
Save JMV38/4375513 to your computer and use it in GitHub Desktop.
kraizyCircles
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Main | |
-- 0 chemin 00 | |
-- copyright JMV38 2012 - all rights reserved | |
displayMode(FULLSCREEN) | |
setInstructionLimit(0) | |
-- Use this function to perform your initial setup | |
function setup() | |
SIDE = "left" | |
XCENTER = WIDTH/2 + 50 | |
playerName = "?" | |
SCORE = 0 | |
NMAX = 0 -- resevrved | |
SIZE = math.min(WIDTH,HEIGHT)/3 | |
board = Board() | |
STEP = 5 -- this is the unit distance in pixels. | |
LEVEL = 1 -- current level | |
ckeckStorage() -- because storage problems presently | |
ALL_LEVELS_ENABLED = not(GLOBAL_STORAGE or LOCAL_STORAGE) | |
-- ALL_LEVELS_ENABLED = true -- uncomment for debug only | |
SELECTED_PATH = nil -- reserved keyword | |
SELECTED_PATH_T0 = 0 -- reserved keyword | |
levels = AllLevels() | |
stage = OneLevel(LEVEL) | |
end | |
function ckeckStorage() | |
saveGlobalData("testChemin","true") | |
GLOBAL_STORAGE= (readGlobalData("testChemin")=="true") | |
print ("global storage :"..tostring(GLOBAL_STORAGE)) | |
saveLocalData("testChemin","true") | |
LOCAL_STORAGE = (readLocalData("testChemin")=="true") | |
print ("local storage :"..tostring(LOCAL_STORAGE)) | |
end | |
function draw() | |
resetMatrix() resetStyle() | |
background(46, 46, 46, 255) | |
board:draw() | |
stage:draw() | |
end | |
function touched(touch) | |
board:touched(touch) | |
stage:touched(touch) | |
end | |
--# Board | |
Board = class() | |
-- the game board commands | |
function Board:init() | |
-- create the buttons | |
local N=8 | |
self.buttons = {} | |
for i=1,N do self.buttons[i] = Button(i,N) end | |
-- button to swap side | |
swapButton = self.buttons[8] | |
swapButton.enabled = true | |
swapButton.butColor = swapButton.purple | |
swapButton.txt = "swap side" | |
swapButton.onclick = function() self:swapSide() end | |
-- player button | |
playerButton = self.buttons[1] | |
playerButton.enabled = true | |
playerButton.butColor = playerButton.purple | |
playerButton.txt = "player: "..playerName | |
playerButton.onclick = function() self:getPlayer() end | |
-- score button | |
scoreButton = self.buttons[2] | |
scoreButton.enabled = true | |
scoreButton.txt = "SCORE" | |
scoreButton.fontSize = scoreButton.fontSize *1.5 | |
-- go! button | |
goButton = self.buttons[4] | |
goButton.enabled = true | |
goButton.txt = "run" | |
goButton.butColor = goButton.purple | |
goButton.onclick = function() | |
stage:runPhase() | |
end | |
-- retry button | |
retryButton = self.buttons[3] | |
retryButton.enabled = true | |
retryButton.butColor = retryButton.purple | |
retryButton.txt = "draw" | |
retryButton.onclick = function() | |
stage:buildPhase() | |
end | |
-- next level button | |
nextButton = self.buttons[6] | |
nextButton.enabled = true | |
nextButton.butColor = nextButton.purple | |
nextButton.txt = "next level" | |
nextButton.onclick = function() self:nextLevel() end | |
-- previous level button | |
prevButton = self.buttons[7] | |
prevButton.enabled = false | |
prevButton.butColor = prevButton.purple | |
prevButton.txt = "prev level" | |
prevButton.onclick = function() self:prevLevel() end | |
end | |
function Board:nextLevel() | |
if LEVEL < NMAX then | |
LEVEL = LEVEL + 1 | |
stage = OneLevel(LEVEL) | |
end | |
end | |
function Board:prevLevel() | |
LEVEL = LEVEL - 1 | |
stage = OneLevel(LEVEL) | |
prevButton.enabled = (LEVEL>1) | |
end | |
function Board:swapSide() | |
if SIDE == "left" then | |
SIDE = "right" | |
XCENTER = WIDTH/2 + 50 | |
for i,b in ipairs(self.buttons) do b.x = 75 end | |
else | |
SIDE = "left" | |
XCENTER = WIDTH/2 - 50 | |
for i,b in ipairs(self.buttons) do b.x = WIDTH - 75 end | |
end | |
end | |
function Board:getPlayer() | |
showKeyboard() | |
playerName = "" | |
playerButton.txt = playerName | |
keyboard = function(key) | |
playerName = playerName..key | |
playerButton.txt = playerName | |
end | |
end | |
function Board:draw() | |
for i,b in ipairs(self.buttons) do b:draw() end | |
if LEVEL==1 then self:instructions() end | |
end | |
function Board:touched(touch) | |
for i,b in ipairs(self.buttons) do b:touched(touch) end | |
end | |
function Board:instructions() | |
pushStyle() | |
textWrapWidth(WIDTH-300) | |
local txt ="" | |
txt = "The objective of this game it to link targets of same colors\n" | |
.. "The starting point is the blinking dot. There are many ways to move it:\n" | |
.. "1- Touch it and drag it to where you want.\n" | |
.. "2- Press the target circle: the point will go straight to it\n" | |
.. "3- Double tap the target: the path is selected and goes straight to your touch. " | |
.. "Double tap again to deselect the path\n" | |
.. "Triple tap the starting target to reset the path\n" | |
.. "When the dot reaches the target, the path is complete (the dot stop blinking)." | |
.. " When all the paths are complete, the 'run' button turns green\n" | |
.. "Link the 2 points below to proceed:" | |
fontSize(WIDTH/50) | |
font("ArialMT") | |
fill(0, 179, 255, 255) | |
text(txt,XCENTER,HEIGHT/4*3) | |
txt = "Pressing the 'run' button will release a ball in each path\n" | |
.. "The balls will follow the paths to their target.\n" | |
.. "The balls should not touch: if they do, you have lost! Press 'draw' to correct. " | |
.. "If the balls reach their target with not contact, you can go to next level\n" | |
.. "If you make the best score it will be saved (touch 'player?' to enter your name) \n" | |
.. "Press 'draw' to restart and improve your score or go to next level.\n" | |
.. "The initial idea was in a post of Dave1707 'circles of confusion'\n" | |
.. "Copyright of this code: JMV38 - 2012 - all rights reserved" | |
text(txt,XCENTER,HEIGHT/4) | |
popStyle() | |
end | |
--# Button | |
Button = class() | |
function Button:init(n,N) | |
self.x = 75 | |
self.y = HEIGHT/(N+1)*(N-n+1) | |
self.w = 70 | |
self.h = HEIGHT/(N+1)/2.1 | |
self.fontSize = WIDTH/30 | |
self.green = color(0, 255, 19, 255) | |
self.red = color(255, 0, 0, 255) | |
self.purple = color(197, 15, 204, 255) | |
self.black = color(60, 60, 60, 255) | |
self.white = color(255, 255, 255, 255) | |
self.butColor = self.green | |
self.txtColor = self.black | |
self.txt = "button "..tostring(n) | |
self.enabled = false | |
self.onclick = function() end -- do nothing by default | |
end | |
function Button:draw() | |
if self.enabled then | |
pushStyle() | |
rectMode(RADIUS) | |
fill(self.butColor) | |
rect(self.x,self.y,self.w,self.h) | |
fill(self.txtColor) | |
textMode(CENTER) | |
textWrapWidth(self.w*1.8) | |
fontSize(self.fontSize) | |
font("Baskerville-BoldItalic") | |
text(self.txt,self.x,self.y) | |
popStyle() | |
end | |
end | |
local abs = math.abs | |
function Button:touched(touch) | |
if self.enabled then | |
if touch.state == BEGAN then | |
if (abs(touch.x- self.x)<self.w) and (abs(touch.y- self.y)<self.h) | |
then self.onclick() end | |
end | |
end | |
end | |
--# OneLevel | |
OneLevel = class() | |
-- copyright JMV38 2012 - all rights reserved | |
function OneLevel:init(lev) | |
-- free memory | |
collectgarbage() | |
local N = levels:nbrPaths(lev) | |
self.lev = lev | |
self.N = N | |
-- create the points | |
self.pathList = levels:paths(N) | |
-- other objects | |
self.objects = levels:objects(lev) | |
-- compute the reference score | |
self.maxCount = 0 | |
for i,p in ipairs(self.pathList) do | |
self.maxCount = self.maxCount + p.start:dist(p.target)/STEP + 1 | |
end | |
self.score = 100 | |
self:scoreUpdate() | |
self.complete = false | |
self.collision = false | |
self.victory = false | |
-- management of game | |
self.phase = "pathBuild" -- or "ballRun" | |
self:buildPhase() | |
self.maxScoreKey = "cheminMaxScoreLevel".. self.lev | |
self.winnerKey = "cheminWinnerLevel".. self.lev | |
self:readMaxScore() | |
prevButton.enabled = (self.lev>1) | |
end | |
function OneLevel:readMaxScore() | |
local txt | |
if LOCAL_STORAGE then | |
txt = tostring(readLocalData(self.maxScoreKey)) | |
self.winner = readLocalData(self.winnerKey) or "?" | |
elseif GLOBAL_STORAGE then | |
txt = tostring(readGlobalData(self.maxScoreKey)) | |
self.winner = readGlobalData(self.winnerKey) or "?" | |
else | |
txt = tostring(SCORE) | |
self.winner = playerName | |
end | |
self.maxScore = 0 | |
for i =0,100 do | |
if txt == tostring(i) then self.maxScore = i end | |
end | |
nextButton.enabled = ((self.maxScore > 0) and (self.lev<NMAX)) or ALL_LEVELS_ENABLED | |
end | |
function OneLevel:saveMaxScore() | |
if LOCAL_STORAGE then | |
saveLocalData(self.maxScoreKey,tostring(self.score)) | |
saveLocalData(self.winnerKey,playerName) | |
elseif GLOBAL_STORAGE then | |
saveGlobalData(self.maxScoreKey,tostring(self.score)) | |
saveGlobalData(self.winnerKey,playerName) | |
end | |
self:readMaxScore() | |
end | |
function OneLevel:scoreUpdate() | |
local score = 0 | |
for _,p in ipairs(self.pathList) do score = score + p.i end | |
local newScore = 200 - math.floor(score/self.maxCount/2*200) | |
if self.score ~= newScore then sound(SOUND_BLIT, 28454) end | |
self.score = newScore | |
if self.score == 0 then self.gameover=true end | |
end | |
function OneLevel:checkComplete() | |
local complete = true | |
for _,p in ipairs(self.pathList) do complete = complete and p.complete end | |
-- if all path complete emphasize the <go!> button when it changes | |
if self.complete ~= complete then | |
if complete == true | |
then | |
goButton.butColor = goButton.green | |
retryButton.butColor = retryButton.purple | |
else | |
goButton.butColor = goButton.purple | |
end | |
end | |
self.complete = complete | |
end | |
local floor = math.floor | |
function OneLevel:checkCollision() | |
local collision = false | |
local v1,v2 | |
for i,p1 in ipairs(self.pathList) do | |
for j,p2 in ipairs(self.pathList) do | |
if i~=j then | |
v1 = p1.pos[floor(p1.ballIndex)] | |
v2 = p2.pos[floor(p2.ballIndex)] | |
if v1:dist(v2) < (p1.ballSize + p2.ballSize-2) | |
then | |
collision = true | |
end | |
end | |
end | |
for _,o in ipairs(self.objects) do | |
v1 = p1.pos[floor(p1.ballIndex)] | |
v2 = o.pos | |
if (v1:dist(v2) < (p1.ballSize + o.size-2)) | |
then collision = o:action(p1) or collision | |
end | |
end | |
end | |
-- explosion only once | |
if collision and not self.collision then sound(SOUND_EXPLODE, 28454) end | |
self.collision = collision | |
end | |
function OneLevel:maxScoreDraw() | |
scoreButton.txt = self.score | |
fontSize(30) | |
font("AmericanTypewriter-Bold") | |
fill(255, 255, 255, 255) | |
text("level: ".. self.lev .." - max score: " .. self.maxScore .. " by " .. self.winner | |
,WIDTH/2,HEIGHT - 50) | |
end | |
function OneLevel:runPhase() | |
self.phase = "ballRun" | |
for k,p in ipairs(self.pathList) do | |
p:ballRun() | |
end | |
retryButton.butColor = retryButton.purple | |
goButton.butColor = goButton.green | |
end | |
function OneLevel:buildPhase() | |
self.phase = "pathBuild" | |
for k,p in ipairs(self.pathList) do | |
p:ballHide() | |
end | |
retryButton.butColor = retryButton.green | |
goButton.butColor = goButton.purple | |
nextButton.butColor = nextButton.purple | |
end | |
function OneLevel:stopBalls() | |
goButton.butColor = goButton.red | |
for k,p in ipairs(self.pathList) do | |
p:ballStop() | |
end | |
end | |
function OneLevel:checkVictory() | |
local victory = true | |
for _,p in ipairs(self.pathList) do victory = victory and p.ballArrived end | |
-- play victory sound once | |
if victory and not self.victory then | |
sound(SOUND_POWERUP, 28455) | |
nextButton.butColor = nextButton.green | |
retryButton.butColor = retryButton.purple | |
goButton.butColor = goButton.purple | |
if self.score > self.maxScore then -- save new max score | |
self:saveMaxScore() | |
end | |
end | |
self.victory = victory | |
end | |
function OneLevel:draw() | |
self:maxScoreDraw() | |
for _,p in ipairs(self.pathList) do p:drawPath() end | |
for _,p in ipairs(self.pathList) do p:drawBall() end | |
for _,o in ipairs(self.objects) do o:draw() end | |
if self.phase == "pathBuild" then | |
self:scoreUpdate() | |
self:checkComplete() | |
end | |
if self.phase == "ballRun" then | |
self:checkCollision() | |
if self.collision then self:stopBalls() end | |
self:checkVictory() | |
end | |
end | |
function OneLevel:touched(touch) | |
-- the touch is activated only during the built phase | |
if self.phase == "pathBuild" then | |
for i,p in ipairs(self.pathList) do p:touched(touch) end | |
end | |
end | |
--# AllLevels | |
AllLevels = class() | |
function AllLevels:init() | |
NMAX = 27 | |
end | |
function AllLevels:nbrPaths(lev) | |
local N | |
if lev <= 6 then N = lev | |
else N = (lev-7) % 3 + 3 | |
end | |
return N | |
end | |
function AllLevels:paths(N) | |
-- the list of preferred colors for the paths | |
self.colorList = {} | |
self.colorList[1] = color(253, 255, 0, 255) | |
self.colorList[2] = color(255, 188, 0, 255) | |
self.colorList[3] = color(255, 75, 0, 255) | |
self.colorList[4] = color(255, 0, 157, 255) | |
self.colorList[5] = color(252, 0, 255, 255) | |
self.colorList[6] = color(138, 0, 255, 255) | |
self.colorList[7] = color(0, 159, 255, 255) | |
self.colorList[8] = color(0, 247, 255, 255) | |
self.colorList[9] = color(0, 255, 158, 255) | |
self.colorList[10] = color(41, 255, 0, 255) | |
-- create the points | |
self.pathList = {} | |
local w = SIZE | |
local cx,cy = WIDTH/2,HEIGHT/2 | |
local dAlpha = math.pi/N | |
local sgn = -1 | |
for i=1,N do | |
local x0,y0 = math.cos(dAlpha*i)*w*sgn + cx, math.sin(dAlpha*i)*w*sgn + cy | |
local x1,y1 = -math.cos(dAlpha*i)*w*sgn + cx, -math.sin(dAlpha*i)*w*sgn + cy | |
sgn = sgn*(-1) | |
self.pathList[i] = Path(vec2(x0,y0),vec2(x1,y1),self.colorList[i]) | |
end | |
return self.pathList | |
end | |
function AllLevels:objects(lev) | |
local list = {} | |
if lev==7 then | |
list = {Object(2,0,0,"bloc")} | |
elseif lev==8 then | |
list = {Object(1,-3,0,"bloc"), Object(1,3,0,"bloc")} | |
elseif lev==9 then | |
list = {Object(1,-3,-2,"bloc"), Object(1,3,-2,"bloc"), Object(1,0,2,"bloc")} | |
elseif lev==10 then list = {Object(3,0,2,"faster")} | |
elseif lev==11 then list = {Object(2,0,-5,"faster"), Object(2,0,5,"faster")} | |
elseif lev==12 then | |
list = {Object(1,-3,2,"faster"), Object(1,3,2,"faster"), Object(1,0,-2,"faster")} | |
elseif lev==13 then | |
list = {Object(3,0,2,"faster"),Object(2,0,-2,"bloc")} | |
elseif lev==14 then | |
list = {Object(2,0,-5,"faster"), Object(2,0,5,"faster"), | |
Object(1,-3,0,"bloc"), Object(1,3,0,"bloc")} | |
elseif lev==15 then | |
list = {Object(1,-4,3,"faster"), Object(1,4,3,"faster"), Object(1,0,-4,"faster"), | |
Object(1,-3,-2,"bloc"), Object(1,3,-2,"bloc"), Object(1,0,2,"bloc")} | |
elseif lev==16 then | |
list = {Object(2,0,0,"slower")} | |
elseif lev==17 then | |
list = { | |
Object(1,-3,0,"slower"), Object(1,3,0,"slower")} | |
elseif lev==18 then | |
list = { | |
Object(1,-6,0,"slower"), Object(1,0,0,"slower"), Object(1,6,0,"slower"), | |
} | |
elseif lev==19 then | |
list = {Object(3,0,2,"faster"),Object(2,0,-2,"bloc"), | |
Object(1,-3,0,"slower"), Object(1,3,0,"slower")} | |
elseif lev==20 then | |
list = {Object(2,0,-5,"faster"), Object(2,0,5,"faster"), Object(2,0,0,"slower"), | |
Object(1,-3,0,"bloc"), Object(1,3,0,"bloc")} | |
elseif lev==21 then | |
list = {Object(1,-4,3,"faster"), Object(1,4,3,"faster"), Object(1,0,-4,"faster"), | |
Object(1,-6,0,"slower"), Object(1,6,0,"slower"), | |
Object(1,-3,-2,"bloc"), Object(1,3,-2,"bloc"), Object(1,0,2,"bloc")} | |
elseif lev==22 then | |
list = { | |
Object(2,-3,0,"smaller"), Object(2,3,0,"bigger"), | |
} | |
elseif lev==23 then | |
list = { | |
Object(1,-2,-2,"smaller"), Object(1,2,2,"smaller"), | |
Object(1,2,-2,"bigger"), Object(1,-2,2,"bigger"), | |
} | |
elseif lev==24 then | |
list = { | |
Object(1,-4,0,"smaller"), Object(1,4,0,"smaller"), | |
Object(1,0,-4,"smaller"), Object(1,0,4,"smaller"), | |
Object(2.5,0,0,"bigger"), | |
} | |
elseif lev==25 then | |
list = {Object(3,0,2,"faster"),Object(2,0,-2,"bloc"), | |
Object(1,0,5,"bigger"), Object(1,-3,4,"smaller"),Object(1,3,4,"smaller"), | |
Object(1,-3,0,"slower"), Object(1,3,0,"slower")} | |
elseif lev==26 then | |
list = {Object(2,0,-5,"faster"), Object(2,0,5,"faster"), Object(2,0,0,"slower"), | |
Object(1,4,4,"bigger"), Object(1,-4,4,"bigger"), | |
Object(1,4,-4,"smaller"), Object(1,-4,-4,"smaller"), | |
Object(1,-3,0,"bloc"), Object(1,3,0,"bloc")} | |
elseif lev==27 then | |
list = {Object(1,-4,3,"faster"), Object(1,4,3,"faster"), Object(1,0,-4,"faster"), | |
Object(1,-6,0,"slower"), Object(1,6,0,"slower"), | |
Object(1,-5,-5,"bigger"), Object(1,5,-5,"bigger"),Object(1,0,6,"bigger"), | |
Object(1,0,-1.5,"smaller"), Object(1,-2.5,1.5,"smaller"),Object(1,2.5,1.5,"smaller"), | |
Object(1,-3,-2,"bloc"), Object(1,3,-2,"bloc"), Object(1,0,2,"bloc")} | |
end | |
return list | |
end | |
--# Path | |
Path = class() | |
-- copyright JMV38 2012 - all rights reserved | |
function Path:init(v0,v1,col) | |
self.color = col | |
local w = 25 | |
-- this part is to manage the path drawing | |
self.pos = {} | |
self.ms = mesh() | |
self.start = v0 | |
self.target = v1 | |
self.step = STEP | |
self:add(v0) | |
self.selected = false | |
self.alwaysSelected = false | |
self.complete = false | |
self.buildEnabled = false | |
-- this is to manage the ball | |
self.ballVisible = false | |
self.ballIndex = 1 | |
self.ballSize0 = w -- initial ball size | |
self.ballSize = w | |
self.ballSpeed = 0 -- in unit lenght (step) per frame | |
self.ballArrived = false | |
self:initImages() | |
end | |
function Path:add(v) | |
local w = 20 | |
local i = self.ms:addRect(v.x,v.y,w,w) | |
self.ms:setRectTex(i,0,0,1,1) | |
self.pos[i] = v | |
self.i = i | |
-- if we are very close but not exactly on it, then finish the path | |
if self.target:dist(v) <= self.step then | |
if v ~= self.target then self:add(self.target) end | |
end | |
-- when we are on the target then the path is complete and make a sound | |
if v == self.target then | |
self.complete = true | |
sound(SOUND_PICKUP, 28455) | |
end | |
end | |
function Path:ballRun() | |
self.ballVisible = true | |
self.ballSpeed = 1 | |
self.ballArrived = false | |
self.ballIndex = 1 | |
self.ballSize = self.ballSize0 | |
self:ballInit() | |
end | |
function Path:ballStop() | |
self.ballSpeed = 0 | |
end | |
function Path:ballHide() | |
self.ballVisible = false | |
end | |
local floor = math.floor | |
local cos = math.cos | |
local abs = math.abs | |
function Path:drawPath() | |
-- ###### path drawing part: | |
-- start and target points always displayed | |
local v = self.start | |
sprite(self.startImg,v.x,v.y) | |
v = self.target | |
sprite(self.targetImg,v.x,v.y) | |
-- draw the path | |
self.ms:draw() | |
-- blink the unfinished path | |
if not self.complete then | |
v = self.pos[self.i] | |
pushStyle() | |
local t = cos(ElapsedTime*10)*64 + 192 | |
tint(t, t, t, 255) | |
sprite(self.stepImg,v.x,v.y) | |
popStyle() | |
end | |
-- check if always selected, and show it | |
if self.complete and (SELECTED_PATH == self) then SELECTED_PATH=nil end | |
self.alwaysSelected = (SELECTED_PATH == self) | |
if self.alwaysSelected then self.selected = true end | |
if self.alwaysSelected then | |
v = self.pos[self.i] | |
sprite(self.curImg,v.x,v.y) | |
end | |
-- ####### building part: | |
-- the build of the path is done in draw, so it works even when there is no touch MOVE | |
local step = self.step | |
local touch | |
if self.targetSelected and (TARGET_T0 < ElapsedTime) then touch = self.target | |
elseif self.selected then touch = CurrentTouch | |
end | |
if touch and not self.complete and self.buildEnabled | |
and (ElapsedTime>SELECTED_PATH_T0) | |
then | |
local v1 = vec2(touch.x, touch.y) | |
local v0 = self.pos[self.i] | |
if v0:dist(v1) > step then | |
v1 = v0 + (v1-v0):normalize()*step | |
self:add(v1) | |
end | |
end | |
end | |
function Path:drawBall() | |
-- ###### ball draw and move part: | |
if self.resetBallSize and self.ballSize~=self.ballSize0 then | |
local x = self.ballSize - self.ballSize0 | |
local s = x / abs(x) | |
self.ballSize = floor((x*s)/1.1)*s + self.ballSize0 | |
self:ballInit() | |
end | |
self.resetBallSize = true | |
local v | |
if self.ballVisible then | |
-- draw the ball | |
v = self.pos[floor(self.ballIndex)] -- fraction index are allowed for slower speed | |
if v then | |
pushMatrix() | |
sprite(self.ballImg,v.x,v.y) | |
end | |
-- move the ball | |
if not self.ballArrived then | |
local imax = #self.pos | |
self.ballIndex = self.ballIndex + self.ballSpeed | |
if self.ballIndex > imax then self.ballIndex = imax end | |
-- if the ball is arrived then stop incrementing | |
local i = floor(self.ballIndex) | |
if i == imax then | |
self.ballSpeed = 0 -- at the end of the path stop the ball | |
-- but this doesn't mean the ball is arrived to the target | |
if self.pos[i] == self.target then self.ballArrived = true end | |
end | |
end | |
end | |
end | |
function Path:touched(touch) | |
-- touch outside the board do not count | |
local t = vec2(touch.x,touch.y) | |
local touchInBoard = (t:dist(vec2(WIDTH/2,HEIGHT/2))<SIZE*1.2) | |
-- the touch events are used only to start or stop the build, not to do it. | |
if touch.state == BEGAN and touchInBoard then | |
self.buildEnabled = true | |
-- check if something has been touched | |
local v = self.pos[self.i] | |
local endTouched = (v:dist(t) < self.curSize*2) | |
local closeToEndTouched = (v:dist(t) < self.curSize*4) | |
local startTouched = (self.start:dist(t) < self.baseSize*1.5) | |
local targetTouched = (self.target:dist(t) < self.baseSize*1.5) | |
local tapCount = touch.tapCount | |
-- if you touch the end of the path, then it is selected | |
if endTouched and not SELECTED_PATH then self.selected = true end | |
-- used in the draw to go more easily to target | |
if targetTouched then | |
self.targetSelected = true ; TARGET_T0 = ElapsedTime + 0.3 | |
end | |
-- double tap to lock the selection | |
if (startTouched or targetTouched) and tapCount == 2 then | |
if SELECTED_PATH == self then | |
SELECTED_PATH = nil ; SELECTED_PATH_T0 = 0 | |
else SELECTED_PATH = self ; SELECTED_PATH_T0 = ElapsedTime + 0.3 | |
end | |
end | |
-- triple tap on start/end base to reset the path | |
if (startTouched or (targetTouched and self.complete)) and tapCount == 3 | |
then | |
self:init(self.start,self.target,self.color) | |
collectgarbage() | |
end | |
-- if the target is touched, then automatic draw in this direction | |
-- if targetTouched and tapCount == 1 then self.targetSelected = true end | |
end | |
-- to capture the end of a touch: ENDED or CANCELLED or whatever... | |
if not (touch.state == BEGAN or touch.state == MOVING) then | |
self.buildEnabled = false | |
self.selected = false | |
self.targetSelected = false | |
end | |
-- always selected is not allowed if path is complete | |
if self.complete then self.alwaysSelected = false end | |
-- apply always selected: | |
if self.alwaysSelected then self.selected = true end | |
end | |
function Path:initImages() | |
local w = self.ballSize0 | |
-- this is the path step | |
local stepImg = image(21,21) | |
setContext(stepImg) | |
pushStyle() | |
background(0,0,0,0) | |
fill(self.color) | |
noStroke() | |
ellipse(10,10,21) | |
popStyle() | |
setContext() | |
self.stepImg = stepImg | |
self.ms.texture = stepImg | |
-- this is the start and end point image | |
self.baseSize = w | |
local targetImg = image(w*2+1,w*2+1) | |
setContext(targetImg) | |
pushStyle() | |
background(0,0,0,0) | |
stroke(self.color) | |
strokeWidth(3) | |
fill(0,0,0,0) | |
ellipse(25,25,48) | |
ellipse(25,25,38) | |
popStyle() | |
setContext() | |
self.targetImg = targetImg | |
local startImg = image(w*2+1,w*2+1) | |
setContext(startImg) | |
pushStyle() | |
background(0,0,0,0) | |
stroke(self.color) | |
strokeWidth(3) | |
fill(0,0,0,0) | |
ellipse(25,25,48) | |
popStyle() | |
setContext() | |
self.startImg = startImg | |
-- this is the cursor when the end of a path is always selected | |
self.curSize = w * 0.7 | |
local curImg = image(w*2+1,w*2+1) | |
setContext(curImg) | |
pushStyle() | |
background(0,0,0,0) | |
stroke(self.color) | |
strokeWidth(10) | |
fill(0,0,0,0) | |
ellipse(25,25,48) | |
popStyle() | |
setContext() | |
self.curImg = curImg | |
-- this is the ball | |
self:ballInit() | |
end | |
function Path:ballInit() | |
w = self.ballSize | |
local ballImg = image(w*2+1,w*2+1) | |
setContext(ballImg) | |
pushStyle() | |
background(0,0,0,0) | |
stroke(127, 127, 127, 255) | |
strokeWidth(8) | |
fill(self.color) | |
ellipse(w,w,w*2-2) | |
popStyle() | |
setContext() | |
self.ballImg = ballImg | |
end | |
--# Object | |
Object = class() | |
function Object:init(r,x,y,type) | |
self.type = type | |
if type=="bloc" then | |
self.collision = true | |
self.color = color(178, 178, 178, 133) | |
elseif type=="faster" then | |
self.color = color(236, 65, 111, 133) | |
elseif type=="slower" then | |
self.color = color(64, 236, 77, 133) | |
elseif type=="bigger" then | |
self.color = color(255, 236, 0, 133) | |
elseif type=="smaller" then | |
self.color = color(45, 0, 255, 133) | |
end | |
self.size = r/10 * SIZE | |
local cx,cy = WIDTH/2,HEIGHT/2 | |
self.pos = vec2(cx + x/10*SIZE, cy + y/10*SIZE) | |
-- image | |
local img = image(self.size*2+1,self.size*2+1) | |
setContext(img) | |
pushStyle() | |
background(0,0,0,0) | |
fill(self.color) | |
noStroke() | |
ellipse(self.size+1,self.size+1,self.size*2) | |
popStyle() | |
setContext() | |
self.img = img | |
end | |
function Object:action(path) | |
local collision = false | |
path.resetBallSize = true | |
local normal, ballSize = path.ballSize0,path.ballSize | |
local smaller, bigger = normal/1.5,normal*1.5 | |
if self.type == "bloc" then collision = true | |
elseif self.type == "faster" then path.ballSpeed = 2 | |
elseif self.type == "slower" then path.ballSpeed = 0.5 | |
elseif self.type == "bigger" then | |
if ballSize < bigger then path.ballSize = path.ballSize*1.03 ; path:ballInit() end | |
path.resetBallSize = false | |
elseif self.type == "smaller" then | |
if ballSize > smaller then path.ballSize = path.ballSize/1.03 ; path:ballInit() end | |
path.resetBallSize = false | |
end | |
return collision | |
end | |
function Object:draw() | |
local v = self.pos | |
sprite(self.img,v.x, v.y) | |
end | |
function Object:touched(touch) | |
-- Codea does not automatically call this method | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment