Created
February 2, 2012 20:09
-
-
Save juaxix/1725481 to your computer and use it in GitHub Desktop.
Magic Puzzle Bubble in Lua by juaxix ( xixgames )
This file contains hidden or 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
Bubble = class() | |
-- Magic Puzzle Bubble by @juaxix - LGPL | |
-- 11/11/11 | |
-- http://xixgames.com | |
-- video: http://www.youtube.com/watch?v=rD0fQVSj_7w | |
-- Bubble states | |
BUBBLE_EMPTY = 0 | |
BUBBLE_CREATED = 1 | |
BUBBLE_FLYING = 2 | |
BUBBLE_ATTACHED = 3 | |
BUBBLE_EXPLODING= 4 | |
BUBBLE_DESTROYED= 5 | |
BUBBLE_FALLING = 6 | |
-- Bubble colors | |
BUBBLE_RED = 1 | |
BUBBLE_YELLOW = 2 | |
BUBBLE_GREEN = 3 | |
BUBBLE_BLUE = 4 | |
BUBBLE_ORANGE = 5 | |
BUBBLE_PURPLE = 6 | |
BUBBLE_GRAY = 7 | |
-- Bubble modes | |
BUBBLE_NORMAL = 1 | |
BUBBLE_LOVE = 2 | |
BUBBLE_MAGIC = 3 | |
-- Bubble positions | |
BUBBLE_UP_LEFT = 1 | |
BUBBLE_UP_RIGHT = 2 | |
BUBBLE_LEFT = 3 | |
BUBBLE_RIGHT = 4 | |
BUBBLE_DOWN_LEFT = 5 | |
BUBBLE_DOWN_RIGHT= 6 | |
function Bubble:init(position,size,mycolor) | |
self.position = position | |
self.size = size | |
self.explored = false | |
self.connected= false -- new algorithm 1/2/2012 | |
self.state = BUBBLE_CREATED | |
if mycolor == nil then | |
local n = (#currentColors) | |
local c = 1 | |
if n>0 then | |
c = math.random(1,n) | |
mycolor = currentColors[c] | |
end | |
end | |
self.bcolor = self:getColor(mycolor) --self:getBorderColor(mycolor) | |
self.color = color(255,255,255,255) --self:getColor(mycolor) | |
self.mycolor = mycolor | |
self.tint = self.bcolor --color(self.color.r,self.color.g,self.color.b,166) | |
self.model = 1--math.random(1,3) | |
self.iposition= vec2(0,0) | |
if self.model == BUBBLE_NORMAL then | |
self.image = "Small World:Mote Sad" | |
self.isizex= self.size * 2 | |
self.isizey= self.size * 2 | |
elseif self.model == BUBBLE_LOVE then | |
self.image = "Small World:Mote Happy" | |
self.isizex= self.size * 1.6 | |
self.isizey= self.size * 1.6 | |
else | |
self.image = "Planet Cute:Star" | |
self.isizex= 50.5 | |
self.isizey= 85.5 | |
self.iposition.y = 7 | |
end | |
end | |
function Bubble:getBorderColor(i) | |
if i == BUBBLE_RED then | |
return color(161, 24, 27, 255) | |
elseif i == BUBBLE_YELLOW then | |
return color(175, 175, 22, 255) | |
elseif i == BUBBLE_GREEN then | |
return color(60, 143, 28, 255) | |
elseif i == BUBBLE_BLUE then | |
return color(23, 125, 170, 255) | |
elseif i == BUBBLE_ORANGE then | |
return color(195, 121, 17, 255) | |
elseif i == BUBBLE_GRAY then | |
return color(45, 43, 97, 255) | |
else | |
return color(126, 27, 148, 255) | |
end | |
end | |
function Bubble:getColor(i) | |
if i == BUBBLE_RED then | |
return color(255, 0, 0, 255) | |
elseif i == BUBBLE_YELLOW then | |
return color(203, 203, 75, 255) | |
elseif i == BUBBLE_GREEN then | |
return color(67, 213, 12, 255) | |
elseif i == BUBBLE_BLUE then | |
return color(4, 21, 241, 255) | |
elseif i == BUBBLE_ORANGE then | |
return color(255, 148, 0, 255) | |
elseif i == BUBBLE_GRAY then | |
return color(76, 83, 94, 255) | |
else | |
return color(208, 0, 255, 255) | |
end | |
end | |
function Bubble:draw() | |
if self.state ==nil or self.state == BUBBLE_EMPTY or self.state == BUBBLE_DESTROYED then | |
return | |
end | |
if self.state == BUBBLE_EXPLODING then | |
sprite("Tyrian Remastered:Explosion Huge", | |
self.position.x,self.position.y,self.size,self.size | |
) | |
elseif self.state == BUBBLE_FALLING then | |
pushMatrix() | |
translate(self.position.x,self.position.y) | |
rotate(180) | |
tint(self.tint) | |
scale(1.5) | |
sprite("Tyrian Remastered:Space Bug Eggs",0,0,self.size/2,self.size/2) | |
popMatrix() | |
else | |
pushMatrix() | |
--stroke(self.bcolor) | |
--strokeWidth(3) | |
fill(self.color) | |
ellipse(self.position.x,self.position.y,self.size,self.size) | |
tint(self.tint) | |
sprite(self.image,self.iposition.x + self.position.x, | |
self.iposition.y + self.position.y, self.isizex,self.isizey) | |
popMatrix() | |
end | |
end |
This file contains hidden or 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
FontAnim = class() | |
-- Magic Puzzle Bubble by @juaxix - LGPL | |
-- 11/11/11 | |
-- http://xixgames.com | |
function FontAnim:init(args) | |
self.text = args.text | |
self.x = args.x | |
self.y = args.y | |
self.time = 3 | |
self.face = args.face or "Futura-CondensedExtraBold" | |
end | |
function FontAnim:draw() | |
self.time = self.time - 1/11 | |
if self.time > 0 then | |
self.y = self.y + 1 | |
text(self.text,self.x, self.y) | |
end | |
end |
This file contains hidden or 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 | |
-- Magic Puzzle Bubble by @juaxix - LGPL | |
-- 11/11/11 | |
-- http://xixgames.com | |
levels = { | |
-- remember: axis are rotated 45 degrees to | |
-- represent the bubbles matrix | |
{ -- Level 1 | |
-- row 1 | |
{BUBBLE_RED,BUBBLE_RED,BUBBLE_YELLOW,BUBBLE_YELLOW,BUBBLE_BLUE,BUBBLE_BLUE,BUBBLE_GREEN, | |
BUBBLE_GREEN}, | |
-- row 2 | |
{BUBBLE_RED,BUBBLE_RED,BUBBLE_YELLOW,BUBBLE_YELLOW,BUBBLE_BLUE,BUBBLE_BLUE,BUBBLE_GREEN}, | |
-- row 3 | |
{BUBBLE_BLUE,BUBBLE_BLUE,BUBBLE_GREEN,BUBBLE_GREEN,BUBBLE_RED,BUBBLE_RED,BUBBLE_YELLOW, | |
BUBBLE_YELLOW}, | |
-- row 4 | |
{BUBBLE_BLUE,BUBBLE_BLUE,BUBBLE_GREEN,BUBBLE_GREEN,BUBBLE_RED,BUBBLE_RED,BUBBLE_YELLOW} | |
}, | |
{ -- Level 2 | |
{nil,nil,nil,BUBBLE_GRAY,BUBBLE_GRAY}, | |
{nil,nil,nil,BUBBLE_BLUE}, | |
{nil,nil,nil,BUBBLE_GREEN}, | |
{nil,nil,nil,BUBBLE_BLUE}, | |
{nil,nil,nil,BUBBLE_PURPLE}, | |
{nil,nil,nil,BUBBLE_GREEN}, | |
{nil,nil,nil,BUBBLE_BLUE} | |
}, | |
{ -- Level 3 | |
{BUBBLE_GREEN, nil,nil,nil,nil,nil,nil,BUBBLE_GREEN}, | |
{BUBBLE_RED, BUBBLE_GREEN, BUBBLE_BLUE, BUBBLE_YELLOW, BUBBLE_RED, BUBBLE_GREEN, | |
BUBBLE_BLUE}, | |
{BUBBLE_YELLOW,nil,nil,nil,nil,nil,nil,BUBBLE_YELLOW}, | |
{BUBBLE_BLUE,BUBBLE_YELLOW, BUBBLE_RED,BUBBLE_GREEN,BUBBLE_BLUE,BUBBLE_YELLOW, | |
BUBBLE_RED}, | |
{nil,nil,nil,BUBBLE_RED}, | |
{nil,nil,nil,BUBBLE_GREEN}, | |
{nil,nil,nil,BUBBLE_RED} | |
}, | |
{-- Level 4 | |
{nil,BUBBLE_GRAY,BUBBLE_GRAY,nil,nil,BUBBLE_BLUE,BUBBLE_BLUE}, | |
{nil,BUBBLE_YELLOW,nil,nil,BUBBLE_PURPLE}, | |
{nil,BUBBLE_BLUE,nil,nil,BUBBLE_GREEN}, | |
{nil,BUBBLE_YELLOW,nil,nil,BUBBLE_GREEN}, | |
{nil,BUBBLE_YELLOW,nil,nil,BUBBLE_GREEN}, | |
{nil,BUBBLE_RED,nil,nil,BUBBLE_YELLOW}, | |
{nil,BUBBLE_YELLOW,nil,nil,BUBBLE_BLUE}, | |
{nil,BUBBLE_RED,nil,nil,BUBBLE_GREEN} | |
}, | |
{ -- Level 5 | |
{nil, BUBBLE_YELLOW,nil,BUBBLE_YELLOW,nil,BUBBLE_YELLOW,nil,BUBBLE_PURPLE}, | |
{BUBBLE_GREEN, nil, BUBBLE_PURPLE, nil, BUBBLE_BLUE, nil, BUBBLE_RED }, | |
{BUBBLE_RED, nil, BUBBLE_BLUE, nil, BUBBLE_YELLOW, nil, BUBBLE_PURPLE}, | |
{nil,BUBBLE_GREEN,nil,BUBBLE_YELLOW, nil, BUBBLE_BLUE}, | |
{nil,BUBBLE_RED, nil,BUBBLE_PURPLE, nil,BUBBLE_ORANGE}, | |
{BUBBLE_BLUE, nil, BUBBLE_GREEN, nil, BUBBLE_GREEN}, | |
{nil,nil,BUBBLE_PURPLE, nil, BUBBLE_YELLOW}, | |
{nil,nil,nil,BUBBLE_RED} | |
}, | |
{ -- Level 6 | |
{BUBBLE_RED,BUBBLE_RED,BUBBLE_GREEN,BUBBLE_RED,BUBBLE_YELLOW,BUBBLE_RED,BUBBLE_PURPLE, | |
BUBBLE_GREEN}, | |
{BUBBLE_GREEN, nil,BUBBLE_PURPLE, nil,BUBBLE_RED, nil, BUBBLE_RED}, | |
{nil,BUBBLE_PURPLE, BUBBLE_BLUE,BUBBLE_RED,BUBBLE_BLUE,BUBBLE_YELLOW,BUBBLE_GRAY}, | |
{nil,BUBBLE_GREEN,nil,BUBBLE_YELLOW,nil,BUBBLE_RED}, | |
{nil,BUBBLE_RED,BUBBLE_GRAY,BUBBLE_YELLOW,BUBBLE_YELLOW,BUBBLE_YELLOW,BUBBLE_RED}, | |
{BUBBLE_GRAY,nil,BUBBLE_BLUE,nil,BUBBLE_RED,nil,BUBBLE_RED}, | |
{BUBBLE_GREEN,BUBBLE_GRAY,BUBBLE_YELLOW,BUBBLE_YELLOW,BUBBLE_GREEN,BUBBLE_BLUE, | |
BUBBLE_GREEN,BUBBLE_PURPLE} | |
}, | |
{ -- Level 7 | |
{nil,nil,nil,BUBBLE_GREEN,BUBBLE_YELLOW}, | |
{nil,nil,BUBBLE_GREEN,BUBBLE_YELLOW,BUBBLE_GREEN}, | |
{nil,nil,nil,BUBBLE_BLUE,BUBBLE_YELLOW}, | |
{nil,BUBBLE_PURPLE,BUBBLE_YELLOW,nil,BUBBLE_ORANGE,BUBBLE_YELLOW}, | |
{nil,BUBBLE_BLUE,BUBBLE_ORANGE,BUBBLE_ORANGE,BUBBLE_BLUE,BUBBLE_PURPLE,BUBBLE_PURPLE}, | |
{nil,BUBBLE_BLUE,nil,nil,nil,BUBBLE_BLUE} | |
}, | |
{ -- Level 8 | |
{BUBBLE_RED,BUBBLE_GREEN,BUBBLE_BLUE,BUBBLE_YELLOW,BUBBLE_PURPLE,BUBBLE_GRAY,BUBBLE_RED, | |
BUBBLE_GREEN}, | |
{BUBBLE_PURPLE,BUBBLE_GRAY,BUBBLE_RED,BUBBLE_GREEN,BUBBLE_BLUE,BUBBLE_YELLOW, | |
BUBBLE_PURPLE}, | |
{BUBBLE_RED,BUBBLE_GREEN,BUBBLE_BLUE,BUBBLE_YELLOW,BUBBLE_PURPLE,BUBBLE_GRAY, | |
BUBBLE_RED,BUBBLE_GREEN}, | |
{BUBBLE_PURPLE,BUBBLE_GRAY,BUBBLE_RED,BUBBLE_GREEN,BUBBLE_BLUE,BUBBLE_YELLOW, | |
BUBBLE_PURPLE} | |
} | |
} | |
supportedOrientations(LANDSCAPE_LEFT) | |
function setup() | |
watch("score") | |
watch("level") | |
currentColors = {} | |
level = 1 | |
score = 0 | |
puzzle = Puzzle(8,12,false) | |
end | |
-- draw Game | |
function draw() | |
background(0) | |
puzzle:draw() | |
end | |
function touched(touch) | |
puzzle:touched(touch) | |
end |
This file contains hidden or 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
Puzzle = class() | |
-- Magic Puzzle Bubble by @juaxix - LGPL | |
-- 11/11/11 | |
-- re-edit on 1/1/12 , 1/2/2012 | |
-- http://xixgames.com | |
-- states | |
PUZZLE_PLAYING = 1 | |
PUZZLE_LOADING = 2 | |
PUZZLE_NEXT = 3 | |
PUZZLE_END = 4 | |
function Puzzle:init(w,h,load_puzzle) | |
-- 12 tiles height x 8 tiles width | |
self.initWidth = 133 | |
self.initHeight= 21 | |
self.tileSize = 60 | |
self.width = w | |
self.height = h | |
self.bubbles = {} | |
self.nextBubble= nil | |
self.timeNextBu= 0 | |
self.nextBuFram= 1/DeltaTime | |
self.bubbleSize= self.tileSize/2 | |
self.BubbleCool= 6 -- next bubble cooldown | |
self.shootSpeed= 0.66 | |
self.minGY = 0.55 | |
self.animaBubbs= {} | |
self.adyAnimBbs= {} | |
self.explodeBbs= {} | |
self.state = PUZZLE_LOADING | |
currentColors = {} | |
-- read current level | |
if load_puzzle then | |
self:loadPuzzle() | |
self.animating = false | |
else | |
self.animating = true | |
self.animaTime = 0 | |
self.state = PUZZLE_NEXT | |
end | |
--sprite("Small World:Mote Sad") | |
self.st = ScrollingTexture( | |
{ | |
texName = "Small World:Mote Sad", | |
width = WIDTH*2 , | |
-- height= 32 | |
} | |
) | |
self.rs = RoundScreen(60) | |
self.fas= {} -- font anim | |
end | |
function Puzzle:loadPuzzle() | |
print("Loading level "..level) | |
self.state = PUZZLE_LOADING | |
-- create the bubbles | |
local n = 0 | |
local k = 0 | |
local w = self.width | |
local h = self.height | |
for i=1, h do | |
self.bubbles[i] = {} | |
n = 0 | |
if levels[level][i]~=nil then | |
n = #(levels[level][i]) | |
end | |
local aux = 0 | |
if math.fmod(i,2)==0 then | |
aux = (self.bubbleSize/2) + 16 | |
end | |
local y = self.initHeight+self.tileSize*self.height - self.bubbleSize - (i-1)*self.tileSize | |
for j=1,self.width do | |
local c,state = nil,BUBBLE_EMPTY | |
if nil==levels[level][i] or nil == levels[level][i][j] then | |
c = nil | |
if aux>0 and j==self.width then | |
state = nil | |
end | |
else | |
c = levels[level][i][j] | |
state = BUBBLE_ATTACHED | |
self:addCurrentColor(c,currentColors) | |
end | |
self.bubbles[i][j] = Bubble( | |
vec2(aux+self.initWidth+self.tileSize*j - self.bubbleSize,y), | |
self.tileSize, -- bubble radius size | |
c --color | |
) | |
self.bubbles[i][j].state = state | |
end | |
end | |
sound(SOUND_POWERUP, 33755) | |
self.state = PUZZLE_PLAYING | |
print(""..(#currentColors).." colors") | |
end | |
function Puzzle:addCurrentColor(c,cc) | |
local n = 0 | |
if cc ~= nil then | |
n = (#cc) | |
else | |
cc = {} | |
end | |
for i=1,n do | |
if cc[i]==c then | |
return | |
end | |
end | |
cc[n+1] = c | |
end | |
function Puzzle:launchBubble() | |
if self.animating or self.nextBubble == nil then return end | |
if self.nextBubble.state == BUBBLE_CREATED then | |
self.nextBubble.state = BUBBLE_FLYING | |
self.nextBubble.velocity = 29*vec2(Gravity.x,self.shootSpeed*DeltaTime*69) | |
sound(SOUND_SHOOT, 16214) | |
end | |
end | |
function Puzzle:clearBubbleExplorations() | |
for i=1,self.height do | |
local m = self.width | |
if math.fmod(i,2) == 0 then | |
m = m - 1 | |
end | |
for j=1,m do | |
self.bubbles[i][j].explored = false | |
end | |
end | |
end | |
function Puzzle:exploreBubble(i,j) | |
local bubble = self.bubbles[i][j] | |
if bubble.explored then return 0 end | |
local count = 1 -- base case | |
local h = self.height | |
local w = self.width | |
bubble.explored = true | |
local a = math.fmod(i,2)==0 | |
-- left | |
if j>1 and self.bubbles[i][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i][j-1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i,j-1) | |
end | |
if a then --even row | |
-- up left | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j) | |
end | |
-- up right | |
if i>1 and j<w and self.bubbles[i-1][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j+1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j+1) | |
end | |
-- down left | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j) | |
end | |
-- down right | |
if i<h and j<w and self.bubbles[i+1][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j+1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i+1,j+1) | |
end | |
else -- not even, odd | |
-- up left | |
if i>1 and j>1 and self.bubbles[i-1][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j-1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j-1) | |
end | |
-- up right | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j) | |
end | |
-- down left | |
if i>1 and j>1 and self.bubbles[i-1][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j-1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i-1,j-1) | |
end | |
-- down right | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i+1,j) | |
end | |
end | |
-- right | |
if j<w and self.bubbles[i][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i][j+1].mycolor == bubble.mycolor then | |
count = count + self:exploreBubble(i,j+1) | |
end | |
return count | |
end | |
-- this function explores all the bubbles | |
function Puzzle:explorePuzzleBubbles() | |
for i=1, self.height do | |
local m = self.width | |
for j=1,m do | |
local b = self.bubbles[i][j] | |
if not (b.explored) then | |
--print("Explore "..i..",",j) | |
local explode = self:exploreBubble(i,j) | |
if explode>2 then | |
--print("in "..i..", "..explode.." of type"..b.mycolor) | |
return explode | |
end | |
end | |
end | |
end | |
self:clearBubbleExplorations() | |
end | |
function Puzzle:findFallingBubblesFrom(i,j) | |
local bubble = self.bubbles[i][j] | |
if bubble.explored then return 0 end | |
local b = nil -- base case | |
local h = self.height | |
local w = self.width | |
table.insert(self.animaBubbs, table.maxn(self.animaBubbs)+1, vec2(i,j)) | |
bubble.explored = true | |
local a = math.fmod(i,2)==0 | |
if a then | |
-- up left | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i-1,j) | |
end | |
-- up right | |
if i>1 and j<w and self.bubbles[i-1][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j+1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i-1,j+1) | |
end | |
-- down right | |
if i<h and j<w and self.bubbles[i+1][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j+1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i+1,j+1) | |
end | |
-- down left | |
if i<h and j>1 and self.bubbles[i+1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i+1,j) | |
end | |
else | |
-- up left | |
if i>1 and j>1 and self.bubbles[i-1][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j-1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i-1,j-1) | |
end | |
-- up right | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i-1][j].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i-1,j) | |
end | |
-- down right | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i+1,j) | |
end | |
-- down left | |
if i<h and j>1 and self.bubbles[i+1][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i+1][j-1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i+1,j-1) | |
end | |
end | |
-- left | |
if j>1 and self.bubbles[i][j-1].state==BUBBLE_ATTACHED and | |
self.bubbles[i][j-1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i,j-1) | |
end | |
-- right | |
if j<w and self.bubbles[i][j+1].state==BUBBLE_ATTACHED and | |
self.bubbles[i][j+1].mycolor == bubble.mycolor then | |
self:findFallingBubblesFrom(i,j+1) | |
end | |
end | |
function Puzzle:attachBubble(i,j,p) | |
local w = self.width | |
local h = self.height | |
local k = 0 | |
local t = 0 | |
local a = math.fmod(i,2)==0 | |
if p == BUBBLE_DOWN_LEFT then | |
if a and i<h and self.bubbles[i+1][j].state == BUBBLE_EMPTY then | |
k = i+1 | |
t = j | |
elseif i<h and j>1 and self.bubbles[i+1][j-1].state == BUBBLE_EMPTY then | |
k = i+1 | |
t = j-1 | |
else | |
print("error positioning down left bbl") | |
return self:attachBubble(i,j,BUBBLE_DOWN_RIGHT) | |
end | |
elseif p == BUBBLE_UP_LEFT then | |
if a and i>1 and self.bubbles[i-1][j].state == BUBBLE_EMPTY then | |
k = i-1 | |
t = j | |
elseif i>1 and j>1 and self.bubbles[i-1][j-1].state == BUBBLE_EMPTY then | |
k = i-1 | |
t = j-1 | |
else | |
print("error positioning up left bbl") | |
end | |
elseif p == BUBBLE_LEFT then | |
if j>1 and self.bubbles[i][j-1].state == BUBBLE_EMPTY then | |
k = i | |
t = j-1 | |
else | |
print("Error positioning left bubble") | |
return self:attachBubble(i,j,BUBBLE_DOWN_LEFT) | |
end | |
elseif p == BUBBLE_DOWN_RIGHT then | |
if a and i<h and j<w and self.bubbles[i+1][j+1].state == BUBBLE_EMPTY then | |
k = i+1 | |
t = j+1 | |
elseif i<h and self.bubbles[i+1][j].state == BUBBLE_EMPTY then | |
k = i+1 | |
t = j | |
else | |
print("error positioning down right bubble "..i..","..j) | |
if a then | |
self.nextBubble = nil | |
else | |
self:attachBubble(i,j,BUBBLE_DOWN_LEFT) | |
end | |
return | |
end | |
elseif p == BUBBLE_UP_RIGHT then | |
if a and i>1 and self.bubbles[i-1][j].state == BUBBLE_EMPTY then | |
k = i-1 | |
t = j | |
elseif i>1 and j<h and self.bubbles[i-1][j+1].state == BUBBLE_EMPTY then | |
k = i-1 | |
t = j+1 | |
else | |
print("error positioning left bubble") | |
return self:attachBubble(i,j,BUBBLE_DOWN_LEFT) | |
end | |
elseif p == BUBBLE_RIGHT then | |
if j<w and self.bubbles[i][j+1].state == BUBBLE_EMPTY then | |
k = i | |
t = j+1 | |
else | |
print("Error positioning right buble") | |
return self:attachBubble(i,j,BUBBLE_DOWN_RIGHT) | |
end | |
end | |
if k==0 and t==0 then | |
print("error: position not found for the new bubble") | |
end | |
if self.bubbles[k][t].state == BUBBLE_ATTACHED then | |
print("error: position is occupied by another bubble") | |
end | |
local aux = 0 | |
if math.fmod(k,2)==0 then | |
aux = (self.bubbleSize/2) + 16 | |
end | |
self.nextBubble.position.y = self.initHeight+self.tileSize*self.height - | |
self.bubbleSize - (k-1)*self.tileSize | |
self.nextBubble.position.x = aux+self.initWidth+self.tileSize*t - | |
self.bubbleSize | |
self.nextBubble.state = BUBBLE_ATTACHED | |
self.bubbles[k][t] = self.nextBubble | |
self:findSolutions(k,t) | |
self.nextBubble = nil | |
if k == self.height-1 and self.bubbles[k][t].state==BUBBLE_ATTACHED then | |
self:GameOver() | |
end | |
end | |
function Puzzle:GameOver() | |
sound(SOUND_RANDOM, 33465) | |
self.state = PUZZLE_END | |
self.animaTime = 0 | |
end | |
function Puzzle:findSolutions(i,j) | |
self:clearBubbleExplorations() | |
self.animaBubbs = {} | |
self:findFallingBubblesFrom(i,j) | |
if ((#self.animaBubbs)>2) then | |
self:findAdjacentAnimaFallingBubbles() | |
self.animating = true | |
self.animaTime = 6 | |
sound(SOUND_EXPLODE, 46131) | |
else | |
sound(SOUND_HIT, 20242) | |
end | |
end | |
function Puzzle:findAdjacentAnimaFallingBubbles() | |
--self:clearBubbleExplorations() | |
self.adyAnimBbs = {} | |
local mini,minj,maxi,maxj = self.height,self.width,0,0 | |
for i,b in ipairs(self.animaBubbs) do | |
--if b.x < mini then mini = b.x end | |
-- if b.x > maxi then maxi = b.x end | |
--if b.y < minj then minj = b.y end | |
-- if b.y > maxj then maxj = b.y end | |
table.insert(self.fas, FontAnim({ | |
text=(3*i), | |
x=self.bubbles[b.x][b.y].position.x, | |
y=self.bubbles[b.x][b.y].position.y | |
})) | |
score = score + (3*i) | |
end | |
-- explore adjacents to find attached falling bubbles | |
--for i,b in ipairs(self.animaBubbs) do | |
-- old system to find adjacents | |
--self:findAdjacentBubbles(b.x,b.y,mini,minj,maxi,maxj) -- = i,j | |
-- new algorithm- 1/2/2012 | |
self:exploreNonAdjscentFallingBubblesFromFirstLine() | |
-- end | |
self:addNotConnectedBubblesAdjacentsToAnima() | |
-- add adjacents to the list of bubble solutions to animate and remove from puzzle board | |
--for i,a in ipairs(self.adyAnimBbs) do | |
-- table.insert(self.animaBubbs, table.maxn(self.animaBubbs)+1, a) | |
--end | |
end | |
function Puzzle:addNotConnectedBubblesAdjacentsToAnima() | |
for i=1,self.height do | |
local m = self.width | |
if math.fmod(i,2) == 0 then | |
m = m - 1 | |
end | |
k = 1 | |
for j=1,m do | |
if self.bubbles[i][j].connected == false and | |
self.bubbles[i][j].state== BUBBLE_ATTACHED then | |
table.insert(self.animaBubbs, vec2(i,j)) | |
table.insert(self.fas, FontAnim({ | |
text=(6*k), | |
x=self.bubbles[i][j].position.x, | |
y=self.bubbles[i][j].position.y | |
})) | |
score = score + (6*k) | |
k = k + 1 | |
end | |
end | |
end | |
end | |
function Puzzle:disconnectBubbles() | |
for i=1,self.height do | |
local m = self.width | |
if math.fmod(i,2) == 0 then | |
m = m - 1 | |
end | |
for j=1,m do | |
self.bubbles[i][j].connected = false | |
end | |
end | |
end | |
function Puzzle:exploreNonAdjscentFallingBubblesFromFirstLine() | |
local j | |
self:disconnectBubbles() | |
for j=1,self.width do | |
self:markConnectedBubbles(1,j) | |
end | |
end | |
function Puzzle:isBubbleInGroup(bubble,group) | |
if group==nil or not #group then return false end | |
for i,v in ipairs(group) do | |
if bubble.x == v.x and bubble.y == v.y then return true end | |
end | |
return false | |
end | |
function Puzzle:markConnectedBubbles(i,j) | |
local s = self:isBubbleInGroup(vec2(i,j),self.animaBubbs) | |
if s then return end | |
local y = self:isBubbleInGroup(vec2(i,j),self.adyAnimBbs) | |
if y then return end | |
local bubble = self.bubbles[i][j] | |
if bubble.state == BUBBLE_EMPTY then return end | |
if bubble.connected then | |
return | |
end | |
bubble.connected = true | |
local b = nil -- base case | |
local h = self.height | |
local w = self.width | |
local a = math.fmod(i,2)==0 | |
local ok= true | |
-- explore the sides | |
-- left | |
if j>1 and self.bubbles[i][j-1].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i,j-1) | |
end | |
-- right | |
if j<w and self.bubbles[i][j+1].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i,j+1) | |
end | |
if a then -- even rows | |
-- down right | |
if i<h and j<w and self.bubbles[i+1][j+1].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i+1,j+1) | |
end | |
-- down left | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i+1,j) | |
end | |
else -- odd rows | |
-- down right | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i+1,j) | |
end | |
-- down left | |
if i<h and j>1 and self.bubbles[i+1][j-1].state==BUBBLE_ATTACHED then | |
self:markConnectedBubbles(i+1,j-1) | |
end | |
end | |
end | |
function Puzzle:findAdjacentBubbles(i,j,i0,j0,i1,j1) | |
local bubble = self.bubbles[i][j] | |
if bubble.explored then | |
return | |
end | |
bubble.explored = true | |
--print(" Exploring "..i..","..j) | |
local b = nil -- base case | |
local h = self.height | |
local w = self.width | |
local a = math.fmod(i,2)==0 | |
local ok= true | |
local s = self:isBubbleInGroup(bubble,self.animaBubbs) | |
local y = self:isBubbleInGroup(bubble,self.adyAnimBbs) | |
-- find a way from the origin group to the current i,j without sisters in solution group: | |
if a then -- even rows | |
-- only add if no bubble is attached up: | |
-- up left | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i-1,j),self.animaBubbs) | |
and not self:isBubbleInGroup(vec2(i-1,j),self.adyAnimBbs) | |
then | |
ok = false | |
end | |
-- up right | |
if i>1 and j<w and self.bubbles[i-1][j+1].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i-1,j+1),self.animaBubbs) | |
and not self:isBubbleInGroup(vec2(i-1,j+1),self.adyAnimBbs) | |
then | |
ok = false | |
end | |
else | |
-- up left | |
if i>1 and j>1 and self.bubbles[i-1][j-1].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i-1,j-1),self.animaBubbs) | |
and not self:isBubbleInGroup(vec2(i-1,j-1),self.adyAnimBbs) | |
then | |
ok = false | |
end | |
-- up right | |
if i>1 and self.bubbles[i-1][j].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i-1,j),self.animaBubbs) | |
and not self:isBubbleInGroup(vec2(i-1,j),self.adyAnimBbs) | |
then | |
ok = false | |
end | |
end | |
if ok then | |
-- only add if it is a new solution: | |
if not s and not y then | |
table.insert(self.adyAnimBbs, table.maxn(self.adyAnimBbs)+1, vec2(i,j)) | |
else -- solution already in the list and explored, next! | |
return | |
end | |
end | |
-- now, explore the sides | |
-- left | |
if j>1 and self.bubbles[i][j-1].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i,j-1),self.animaBubbs) and | |
(i>=i0 and i<=i1 and j) | |
then | |
self:findAdjacentBubbles(i,j-1,i0,j0,i1,j1) | |
end | |
-- right | |
if j<w and self.bubbles[i][j+1].state==BUBBLE_ATTACHED and | |
not self:isBubbleInGroup(vec2(i,j+1),self.animaBubbs) | |
then | |
self:findAdjacentBubbles(i,j+1,i0,j0,i1,j1) | |
end | |
if a then -- even rows | |
-- down right | |
if i<h and j<w and self.bubbles[i+1][j+1].state==BUBBLE_ATTACHED then | |
self:findAdjacentBubbles(i+1,j+1,i0,j0,i1,j1) | |
end | |
-- down left | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED then | |
self:findAdjacentBubbles(i+1,j,i0,j0,i1,j1) | |
end | |
else -- odd rows | |
-- down right | |
if i<h and self.bubbles[i+1][j].state==BUBBLE_ATTACHED then | |
self:findAdjacentBubbles(i+1,j,i0,j0,i1,j1) | |
end | |
-- down left | |
if i<h and j>1 and self.bubbles[i+1][j-1].state==BUBBLE_ATTACHED then | |
self:findAdjacentBubbles(i+1,j-1,i0,j0,i1,j1) | |
end | |
end | |
end | |
function Puzzle:createCurrentColorsList() | |
local mycolors = {} | |
for i=1,self.height do | |
for j=1,self.width do | |
if self.bubbles[i][j].state == BUBBLE_ATTACHED then | |
self:addCurrentColor(self.bubbles[i][j].mycolor, mycolors) | |
end | |
end | |
end | |
currentColors = mycolors | |
end | |
function Puzzle:checkNextBubbleColliding() | |
local r = {} | |
local aux = nil | |
local nb = self.nextBubble | |
local k,t = 0,0 | |
local r = self.tileSize | |
local q = 0 | |
local p = nb.position | |
local d = 99999 | |
for i=1,self.height do | |
for j=1,self.width do | |
local b = self.bubbles[i][j] | |
if b.state == BUBBLE_ATTACHED then | |
q = math.sqrt( (b.position.x-p.x)*(b.position.x-p.x) + | |
(b.position.y-p.y)*(b.position.y-p.y) ) | |
-- if b.position:dist(p)<r then -- radius | |
if q<r and q<d then | |
if aux == nil then | |
aux = b | |
k = i | |
t = j | |
elseif aux.position.y < b.position.y then | |
aux = b | |
k = i | |
t = j | |
break | |
end | |
if aux ~= nil then break end | |
d = q | |
end | |
end -- end if bubble attached | |
end -- for j,h | |
end -- for i,w | |
if aux ~= nil then | |
local xn,yn,xa,ya = nb.position.x,nb.position.y,aux.position.x,aux.position.y | |
--print("sister of "..k..","..t.."nb="..xn..","..yn..";"..xa..","..ya) | |
if xn <= xa and yn <= ya then | |
--print("down left") | |
self:attachBubble(k,t,BUBBLE_DOWN_LEFT) | |
elseif xn <= xa and yn>= (ya+r) then | |
--print("up left") | |
self:attachBubble(k,t,BUBBLE_UP_LEFT) | |
elseif xn <= xa and yn >= ya then | |
--print("left") | |
self:attachBubble(k,t,BUBBLE_LEFT) | |
elseif xn >= xa and yn <= ya then | |
--print("down right") | |
self:attachBubble(k,t,BUBBLE_DOWN_RIGHT) | |
elseif xn >= xa and yn >= (ya+r) then | |
--print("up right") | |
self:attachBubble(k,t,BUBBLE_UP_RIGHT) | |
else | |
--print("right") | |
self:attachBubble(k,t,BUBBLE_RIGHT) | |
end | |
return true | |
end | |
return false | |
end | |
function Puzzle:findRootPosition() | |
local d = 9999 | |
local x = self.nextBubble.position.x | |
local i = 1 | |
for k=1,self.width do | |
local a = self.initWidth+self.tileSize*k - self.bubbleSize | |
if (self.bubbles[1][i].state~=nil and math.abs(x-a)<d) then | |
d = x-a | |
i = k | |
print(d) | |
end | |
end | |
if d == 9999 then | |
print("Cant find a top position!, a=".. | |
self.initWidth+self.tileSize - self.bubbleSize..", x=".. | |
self.nextBubble.position.x | |
) | |
else | |
self.nextBubble.position.y = self.initHeight+self.tileSize*self.height - | |
self.bubbleSize | |
self.nextBubble.position.x = self.initWidth+self.tileSize*i - self.bubbleSize | |
self.nextBubble.state = BUBBLE_ATTACHED | |
self.bubbles[1][i] = self.nextBubble | |
self:findSolutions(1,i) | |
end | |
self.nextBubble = nil | |
end | |
function Puzzle:updateNextBubble() | |
if self.animating or self.nextBubble == nil or | |
self.nextBubble.state == BUBBLE_ATTACHED | |
then | |
return | |
end | |
if self:checkNextBubbleColliding() then | |
return | |
end | |
if self.nextBubble.state == BUBBLE_FLYING then | |
self.nextBubble.position = self.nextBubble.position + self.nextBubble.velocity | |
--self.nextBubble.velocity.y = self.nextBubble.velocity.y + 0.1 | |
end | |
local x = self.nextBubble.position.x | |
local y = self.nextBubble.position.y | |
local r = self.tileSize/2 - 6 | |
local top = HEIGHT - self.initHeight | |
local right = self.initWidth+self.width*self.tileSize | |
local left = self.initWidth | |
local bottom= self.initHeight | |
if (x + r) > right then | |
--self.nextBubble.position.x = right | |
self.nextBubble.velocity.x = -self.nextBubble.velocity.x | |
sound(SOUND_PICKUP, 37987) | |
elseif (x - r) <= left then | |
--self.nextBubble.position.x = left | |
self.nextBubble.velocity.x = -self.nextBubble.velocity.x | |
sound(SOUND_PICKUP, 37987) | |
end | |
if (y + r) > top then | |
self:findRootPosition() | |
end | |
end | |
function Puzzle:updateBubbleExplosions() | |
for i,k in ipairs(self.explodeBbs) do | |
if k.state == BUBBLE_ATTACHED then | |
k.state = BUBBLE_EXPLODING | |
end | |
end | |
end | |
function Puzzle:animateBubbles() | |
self.animaTime = self.animaTime - 1/6 | |
if self.animaTime <= 0.333 then | |
self.animaTime = 0 | |
self.animating = false | |
end | |
for i,k in ipairs(self.animaBubbs) do | |
local b = self.bubbles[k.x][k.y] | |
if b.state == BUBBLE_ATTACHED then | |
b.state = BUBBLE_FALLING | |
elseif not self.animating then | |
b.state = BUBBLE_EMPTY | |
else | |
b.position.y = b.position.y - 23 | |
end | |
end | |
if not self.animating then -- free mem | |
self.animaBubbs = {} | |
end | |
end | |
function Puzzle:updatePuzzleBubbles() | |
--self:updateBubbleExplosions() | |
if self.animating then | |
self:animateBubbles() | |
end | |
for i=1,self.height do | |
local m = self.width | |
if math.fmod(i,2) == 0 then | |
m = m - 1 | |
end | |
for j=1,m do | |
local b = self.bubbles[i][j] | |
if b.state == BUBBLE_DESTROYED then | |
-- create bubble to fall down in the same position and colors | |
end | |
end | |
end | |
end | |
function Puzzle:goToNextLevel() | |
sound(SOUND_POWERUP, 33773) | |
level = level + 1 | |
if level>#levels then | |
self:GameOver() | |
return | |
end | |
self.animating = true | |
self.animaTime = 0 | |
self.state = PUZZLE_NEXT | |
end | |
function Puzzle:update() | |
if not self.animating and self.nextBubble~=nil and self.nextBubble.state == BUBBLE_FLYING then | |
self:updateNextBubble() | |
end | |
self:updatePuzzleBubbles() | |
if currentColors==nil or #currentColors==0 then | |
self:goToNextLevel() | |
end | |
end | |
function Puzzle:generateNextBubble() | |
if not self.animating and self.state==PUZZLE_PLAYING and self.nextBubble == nil then | |
self.timeNextBu = self.timeNextBu - self.nextBuFram | |
if self.timeNextBu <= 0 then | |
self.timeNextBu = self.BubbleCool | |
self.nextBubble = Bubble(vec2(WIDTH/2,self.initHeight + 43),self.tileSize,nil) | |
end | |
end | |
end | |
function Puzzle:drawArrow() | |
noTint() | |
stroke(255, 255, 255, 102) | |
strokeWidth(15) | |
lineCapMode(ROUND) | |
pushMatrix() | |
translate(WIDTH/2, puzzle.initHeight) | |
grav = vec2(Gravity.x * 300, self.shootSpeed * 300) | |
grav2= vec2(Gravity.x * 300, self.minGY * 300) | |
--print(grav) | |
line(0, 0, grav.x,self.minGY*300) | |
-- Arrowhead | |
down = vec2(0, -1) | |
--orient = down:angleBetween(vec2(Gravity.x,-math.abs(Gravity.y))) | |
orient = down:angleBetween(vec2(Gravity.x,-0.55)) | |
pushMatrix() | |
resetMatrix() | |
translate(WIDTH/2,puzzle.initHeight) | |
translate(grav2.x,grav2.y) | |
gr = -math.deg(orient) -180 | |
rotate(gr) | |
line(0, 0, -20, 25) | |
line(0, 0, 20, 25) | |
popMatrix() | |
-- End Arrowhead | |
popMatrix() | |
end | |
function Puzzle:drawBubbles() | |
ellipseMode(CENTER) | |
for i=1,self.height do | |
for j=1,self.width do | |
self.bubbles[i][j]:draw() | |
end | |
end | |
end | |
function Puzzle:drawBackGroundTiles() | |
local color1 = color(114, 81, 184, 255) | |
local color2 = color(56, 56, 114, 255) | |
local tilesz = self.tileSize | |
rectMode(CORNER) | |
noTint() | |
strokeWidth(3) | |
noFill() | |
for i=0 ,self.width-1 do | |
for j=0,self.height-1 do | |
if math.mod((j+i),2)==0 then | |
fill(color1) | |
else | |
fill(color2) | |
end | |
rect(self.initWidth+(tilesz*i),self.initHeight+(tilesz*j),tilesz,tilesz) | |
end | |
end | |
end | |
function Puzzle:drawBorders() | |
--fill(214, 76, 20, 255) | |
stroke(62, 56, 152, 255) | |
strokeWidth(32) | |
smooth() | |
lineCapMode(0) | |
local top = HEIGHT - self.initHeight + 6 | |
local right = self.initWidth+self.width*self.tileSize+15 | |
local left = self.initWidth-15 | |
local bottom= self.initHeight-11 | |
-- top line | |
line(left,top+3,right,top+3) | |
-- left line | |
line(left,top,left,bottom) | |
-- right line | |
line(right,top,right,bottom) | |
-- bottom line | |
line(left,bottom,right,bottom) | |
-- limit line | |
strokeWidth(23) | |
stroke(200, 181, 65, 200) | |
line(left-self.tileSize,bottom+self.tileSize*2,right+self.tileSize,bottom+self.tileSize*2) | |
end | |
function Puzzle:drawNextLevel() | |
noTint() | |
background(0, 53, 255, 255) | |
--sprite("Tyrian Remastered:Arrow Right",WIDTH/2,self.initHeight+43,31*2,66) | |
self.st:draw() | |
self.animaTime = self.animaTime + 0.1 | |
if self.animaTime>=6 then | |
self:init(self.width,self.height,true) | |
return | |
end | |
pushStyle() | |
font("Futura-CondensedExtraBold") | |
fontSize(133) | |
pushMatrix() | |
fill(127, 127, 127, 255) | |
translate(WIDTH/2+3,HEIGHT/2+3) | |
rotate(45) | |
text("LEVEL "..level) | |
fill(math.random(255),255,math.random(255),255) | |
--translate(WIDTH/2,HEIGHT/2) | |
-- rotate(0) | |
text("LEVEL "..level,3,3) | |
popMatrix() | |
popStyle() | |
end | |
function Puzzle:drawGameOver() | |
noTint() | |
background(0, 53, 255, 255) | |
--sprite("Tyrian Remastered:Arrow Right",WIDTH/2,self.initHeight+43,31*2,66) | |
self.st:draw() | |
self.animaTime = self.animaTime + 0.1 | |
if self.animaTime>=6 then | |
self:init(self.width,self.height,true) | |
self.state = PUZZLE_PLAYING | |
end | |
pushStyle() | |
font("ArialRoundedMTBold") | |
fontSize(66) | |
pushMatrix() | |
fill(224, math.random(255), math.random(255),232) | |
translate(WIDTH/2,HEIGHT/2) | |
text("Game Over") | |
popMatrix() | |
popStyle() | |
end | |
function Puzzle:drawTexts() | |
for i,f in ipairs(self.fas) do | |
if f.time<=0 then | |
table.remove(self.fas,i) | |
else | |
f:draw() | |
end | |
end | |
end | |
function Puzzle:draw() | |
if self.state == PUZZLE_NEXT then | |
self:drawNextLevel() | |
elseif self.state == PUZZLE_END then | |
self:drawGameOver() | |
elseif self.state == PUZZLE_PLAYING then | |
self:update() | |
self:createCurrentColorsList() | |
if currentColors == {} then | |
self:goToNextLevel() | |
return | |
end | |
background(71, 119, 232, 255) | |
self:drawBackGroundTiles() | |
self:drawBorders() | |
self:generateNextBubble() | |
self:drawBubbles() | |
self:drawTexts() | |
self:drawArrow() | |
sprite("Tyrian Remastered:Cracked Block",WIDTH/2,self.initHeight+43,31*2,66) | |
if self.nextBubble ~= nil then | |
self.nextBubble:draw() | |
end | |
end | |
self.rs:draw() | |
end | |
function Puzzle:touchBubble(x,y) | |
if self.state ~= PUZZLE_PLAYING then return end | |
local finger = vec2(x,y) | |
local radius = self.tileSize/2 | |
for i=1,self.height do | |
local m = self.width | |
if math.mod(i,2)==0 then | |
m = m - 1 | |
end | |
for j=1, m do | |
local b = self.bubbles[i][j] | |
if math.sqrt( (b.position.x-finger.x)*(b.position.x-finger.x) + | |
(b.position.y-finger.y)*(b.position.y-finger.y) ) < radius | |
then | |
print("touched "..i..","..j.."("..b.position.x..","..b.position.y..".)") | |
self:clearBubbleExplorations() | |
print(self:exploreBubble(i,j).." bubbles") | |
return | |
end | |
end | |
end | |
end | |
function Puzzle:touched(touch) | |
if touch.state == ENDED then | |
if touch.y > 95 then | |
self:touchBubble(touch.x,touch.y) | |
else | |
self:launchBubble() | |
end | |
end | |
end |
This file contains hidden or 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
RoundScreen = class() | |
-- by Simeon from 2livesLeft | |
function RoundScreen:init(radius) | |
-- you can accept and set parameters here | |
self.image = self:setupImage(radius) | |
self.radius = radius | |
self.mesh = mesh() | |
local r = {} | |
local m = self.mesh | |
m.texture = self.image | |
for i = 1,4 do | |
table.insert(r,m:addRect(0,0,0,0)) | |
end | |
self.rects = r | |
end | |
function RoundScreen:setupImage(radius) | |
local roundImage = image(radius,radius) | |
-- draw white circle corner | |
setContext(roundImage) | |
pushStyle() | |
noSmooth() | |
fill(0,0,0,255) | |
rect(0,0,radius,radius) | |
fill(255,255,255,255) | |
ellipse(0,0,radius*2) | |
popStyle() | |
setContext() | |
--process the image | |
local w,h = roundImage.width,roundImage.height | |
for x = 1,w do | |
for y = 1,h do | |
local r,g,b = roundImage:get(x,y) | |
roundImage:set(x,y,0,0,0,255-r) | |
end | |
end | |
return roundImage | |
end | |
function RoundScreen:draw() | |
local m = self.mesh | |
local r = self.rects | |
local rd = self.radius | |
local rd2 = rd/2 - 1 | |
m:setRect(r[1], rd2,rd2,rd,rd) | |
m:setRectTex(r[1], 1,1,-1,-1) | |
m:setRect(r[2], WIDTH - rd2,rd2,rd,rd) | |
m:setRectTex(r[2], 0,1,1,-1) | |
m:setRect(r[3], rd2,HEIGHT - rd2,rd,rd) | |
m:setRectTex(r[3], 1,0,-1,1) | |
m:setRect(r[4], WIDTH - rd2,HEIGHT - rd2,rd,rd) | |
pushMatrix() | |
resetMatrix() | |
m:draw() | |
popMatrix() | |
end |
This file contains hidden or 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
ScrollingTexture = class() | |
-- by Simeon | |
function ScrollingTexture:init(args) | |
-- you can accept and set parameters here | |
self.mesh = mesh() | |
self.texName = args.texName | |
self.mesh.texture = self.texName | |
self.width = args.width or WIDTH | |
self.height = args.height or HEIGHT | |
self.texOffset = 0 | |
local w,h = spriteSize(self.texName) | |
-- Allocate a mesh across the screen | |
local cw = self.width / w | |
local ch = self.height / h | |
self.rects = {} | |
local m = self.mesh | |
for x = 1,cw do | |
for y = 1,ch do | |
local index = m:addRect((x-1)*w + w/2,(y-1)*h + h/2,w,h) | |
table.insert(self.rects,index) | |
end | |
end | |
end | |
function ScrollingTexture:update() | |
self.texOffset = self.texOffset + DeltaTime * 0.5 | |
local o = self.texOffset | |
local m = self.mesh | |
for _,v in pairs(self.rects) do | |
m:setRectTex(v,o,o,1,1) | |
end | |
end | |
function ScrollingTexture:draw() | |
self:update() | |
self.mesh:draw() | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment