News : The level of daily SPAM has reached insane proportions, all registrations are now admin activated. I also ask you to send me an e-mail (john (at) murga (dot) org), to confirm that you want me to activate your account and that you are not a bot or a spammer.
I wonder if anyone knows if it's possible to slice up a single image in FLTK, specifically apply one portion of an image to one widget and another portion to a different image?
I was looking at draw(), which apparently allows for an offset, but I don't understand how it works. I either get a "Bad drawable" (something like that) error or segfault depending on what I try.
I'm building one of those old slide puzzles where you have to unscramble a picture, and was hoping I could use a single arbitrary image rather than having to create a series of pieces specifically for the puzzle.
Code:
ts=48 -- tile size
tc=6 -- number of tiles in one line
fr=10 -- frame size
function move_tile(t)
local my_x,my_y,movex,movey=t:x(),t:y()
-- tile must be adjacent to the missing piece
if (my_x == tile[hidden]:x() and math.abs(my_y-tile[hidden]:y()) == ts)
or (my_y == tile[hidden]:y() and math.abs(my_x-tile[hidden]:x()) == ts)
then
movex=tile[hidden]:x()
movey=tile[hidden]:y()
tile[hidden]:position(my_x,my_y)
t:position(movex,movey)
w:redraw()
end
end
-- array of tiles, top left to right, then move down
tile={}
-- allow space for the frame
row=fr; col=fr
for i=0,tc*tc-1 do
tile[i]=fltk:Fl_Button(col,row,ts,ts)
tile[i]:callback(move_tile)
tile[i]:label(i+1) -- simple numbers could be replaced by images
-- next piece is ts pixels to the right
col=col+ts
-- start the next row
if col == ts*tc+fr then col=fr;row=row+ts end
end
-- turn a random tile into the missing piece
math.randomseed(os.time())
hidden=math.random(0,24)
tile[hidden]:label("")
tile[hidden]:box(fltk.FL_DOWN_BOX)
-- next step would be to jumble the tiles, but I haven't worked that out.
No rush at all. I'm just playing around with the scrambling and the detection of a completed puzzle, and that's all I planned to do on that project until the next murgaLua release.
Well, it seems to be working very well. Thank you!
Here is a new improved version including the new getTiles()
NOTE: I tested the previous version once in Windows, and the desktop froze. I don't know if it was a problem with the script or with Windows, but just beware!
Another note of warning:
For some reason it segfaults when trying to load a transparent PNG. John's tile script succeeds with the very same image, so I don't know what I did to break it. Adding os.exit() just before getTiles() doesn't segfault, so i'm confused.
Code:
#!/usr/bin/murgaLua
-- slide puzzle for MurgaLua 0.6.4+
-- 2008 mikshaw
-- window and image size are determined by these variables
ts=48 -- tile size
tc=4 -- number of tiles in one line
fr=5 -- frame size
if not Fl_Image.getTiles then
fltk.fl_alert("This program requires murgaLua 0.6.4 or newer.\n\n"..
"http://www.murga-projects.com/murgaLua/index.html")
os.exit(1)
end
function reset_hidden()
tile[hidden]:box(fltk.FL_UP_BOX)
tile[hidden]:labeltype(fltk.FL_NORMAL_LABEL)
end
function load_callback(object)
-- mod of a function written by John Murga
fileName = fltk.fl_file_chooser("Choose an RGB image", "Image Files (*.{jpg,png})", nil, nil)
if fileName then
if image1 then image1:uncache() end -- don't know if this is needed
image1 = Fl_Shared_Image.get(fileName,ts*tc,ts*tc)
myImages = image1:getTiles(ts,ts)
for key,value in ipairs(myImages) do
tile[key-1]:image(value)
tile[key-1]:redraw()
end
scramble()
scrambutt:label("load an image")
end
end
function move_tile(t)
local my_x,my_y,movex,movey=t:x(),t:y()
-- tile must be adjacent to the missing piece
if (my_x == tile[hidden]:x() and math.abs(my_y-tile[hidden]:y()) == ts)
or (my_y == tile[hidden]:y() and math.abs(my_x-tile[hidden]:x()) == ts)
then
movex=tile[hidden]:x()
movey=tile[hidden]:y()
tile[hidden]:position(my_x,my_y)
t:position(movex,movey)
w:redraw()
end
if start==0 then -- don't check puzzle during scramble
local ok=0
for i=0,tc*tc-1 do
if tile[i]:x()==pos[i].col and tile[i]:y()==pos[i].row then
ok=ok+1
if ok==tc*tc then
reset_hidden()
fltk.fl_beep()
scrambutt:label(prize[math.random(1,table.getn(prize))])
for i=0,tc*tc-1 do tile[i]:set_output() end -- disable the buttons
break
end
end
end
end
end
function scramble()
-- this picks a random tile to attempt to move and
-- repeats the process many times. Simply placing
-- tiles in random locations could potentially make
-- the puzzle impossible to solve
for i=0,tc*tc-1 do tile[i]:clear_output() end -- enable the buttons
if hidden then reset_hidden() end
-- turn a random tile into the missing piece
hidden=math.random(0,tc*tc-1)
tile[hidden]:labeltype(fltk.FL_NO_LABEL)
tile[hidden]:box(fltk.FL_DOWN_BOX)
start=1
local scram=0
while scram < 10000 do
move_tile(tile[math.random(0,tc*tc-1)])
scram=scram+1
end
start=0
w:redraw()
end
Fl:visible_focus(0) -- get rid of the ants
Fl:set_boxtype(fltk.FL_UP_BOX,fltk.FL_THIN_UP_BOX)
Fl:set_boxtype(fltk.FL_DOWN_BOX,fltk.FL_THIN_DOWN_BOX)
w=fltk:Fl_Double_Window(ts*tc+fr*2,ts*(tc+0.5)+fr*3,"slide puzzle")
scrambutt=fltk:Fl_Button(fr,ts*tc+fr*2,ts*tc,ts/2,"load an image")
scrambutt:callback(load_callback)
-- array of tiles, top left to right, then move down
tile={}; pos={}
-- allow space for the frame
row=fr; col=fr
-- subtract one is used because the number of tiles starts at one
-- but the table starts at zero (easier to position them from zero)
for i=0,tc*tc-1 do
tile[i]=fltk:Fl_Button(col,row,ts,ts)
tile[i]:align(80)
tile[i]:callback(move_tile)
pos[i]={col=col,row=row}
-- next piece is ts pixels to the right
col=col+ts
-- start the next row
if col == ts*tc+fr then col=fr;row=row+ts end
end
w:show()
Fl:run()
This post was last modified: 02-25-2008 07:35 AM by mikshaw.
I'm not having any luck importing any image. Seg fault each time.
When clicking on a tile I get a crash with:
Code:
/bin/murgaLua: miktiles.lua:43: attempt to index field '?' (a nil value)
stack traceback:
miktiles.lua:43: in function <miktiles.lua:40>
[C]: in function 'run'
miktiles.lua:118: in main chunk
[C]: ?
Thats the value : hidden
setting hidden = 0 at outside the functions solves That crash but I don't know what else it breaks.
The previous version had an empty tile, this version doesn't.
Don't know if that makes a difference.
This post was last modified: 02-25-2008 08:11 AM by iGame3D.
setting hidden = 0 at outside the functions solves That crash
I wonder if there might be a difference in the way variables are created. In Linux it seems that a global variable can be created within a function. Maybe on Mac a global variable has to be initialized outside a function before it can be set in a function? If so, I think the start variable may need to be initialized too (start=1).