News : The level of daily SPAM has reached insane proportions, all registrations are now manual. I ask you to send me an e-mail (john (at) murga (dot) org), to confirm that you want me to create an account for you.


Post Reply  Post Thread 
puzzle remix
Author Message
mikshaw
Senior Member
****


Posts: 522
Group: Registered
Joined: Apr 2007
Status: Offline
Reputation: 5
Post: #1
puzzle remix

Remixed the slide puzzle into something more closely resembling a jigsaw puzzle, giving a little different gameplay, and making the code a little lighter and less complex...scrambling is less restricted, there's no swapping of images, and images don't have to be scaled to preset dimensions.

It still needs work. Some images, particularly GIFs, don't tile properly, and I had to be cautious about how scaling is done so images with prime numbers as height or width don't create a billion tiles.

The scaling especially needs work. Ideally I'd like to not scale the image at all and just scale the tiles to fit the image, but there seems to be a problem with using floating point numbers in scaling and/or tiling. So for now it scales the image only enough to fit within a grid determined by the size of the tiles. It still results in some crunchy pixels.

I'd tried cropping the image instead of scaling, by using fl_read_image, but it seems I've completely forgotten how that works.

Code:
old stuff removed


new stuff...

Code:
#!/usr/bin/env murgaLua

-- jigsaw-like puzzle for MurgaLua 0.6.4+
-- 2011 mikshaw

ts = 64 --tile size

function err(e,r)
if fltk then fltk.fl_alert(e) else print(e) end
os.exit(r)
end

if not Fl_Image.getTiles then
err("This program requires murgaLua 0.6.4 or newer.\n\n"..
    "http://www.murga-projects.com/murgaLua/index.html", 1)
end

fileName = arg[1] -- if filename given as cmdline argument
-- browse for file
fltk.fl_register_images() -- do this early so chooser can show preview
if not fileName then
fileName = fltk.fl_file_chooser("Choose an RGB image", "Image Files (*.{jpg,png,bmp,xbm,xpm,gif})", nil, nil)
end
if not fileName then
err("Please supply an image filename.\nUse: "..
    fltk.fl_filename_name(arg[0]).." \"filename\"\n"..
    "or select an image with the file chooser." , 2)
end

-- check image
img = Fl_Shared_Image.get(fileName)
if not img then err("Could not open "..fileName, 3) end
iw = img:w(); ih = img:h()

-- try to find a balance between image size and tile size
if iw % ts == 0 and ih % ts == 0 then
  tw, th = ts, ts
  cols = iw / ts
  rows = ih / ts
else
  cols = math.floor(iw / ts)
  rows = math.floor(ih / ts)
  tw = math.floor(iw / cols)
  th = math.floor(ih / rows)
  iw = cols * tw
  ih = rows * th
end

function set_tile_images()
-- take a crop of the box image
win:make_current()
imageString = fltk.fl_read_image(0, 0, iw, ih, 0)
image = fltk:Fl_RGB_Image(imageString, iw, ih, 3)

-- tile it up
imgtiles = image:getTiles(tw,th)
for i,_ in pairs(tile) do
  tile[i]:image(imgtiles[i+1])
end
box:image(image)
box:hide()
end

function scramble()
math.randomseed(os.time())
for scram = 1, 10000 do
  local a = math.random(0, rows * cols - 1)
  tile_A_x = tile[a]:x(); tile_A_y = tile[a]:y()
  local b = math.random(0, rows * cols - 1)
  tile[a]:position(tile[b]:x(), tile[b]:y())
  tile[b]:position(tile_A_x, tile_A_y)
end
end

function secondsToClock(sSeconds)
-- TJ_Tigger from http://www.indigorose.com/forums/archive/index.php/t-14669.html
local nSeconds = tonumber(sSeconds)
if nSeconds == 0 then
return "00:00:00";
else
nHours = string.format("%02.f", math.floor(nSeconds/3600));
nMins = string.format("%02.f", math.floor(nSeconds/60 - (nHours*60)));
nSecs = string.format("%02.f", math.floor(nSeconds - nHours*3600 - nMins *60));
return nHours..":"..nMins..":"..nSecs
end
end

function drag_loop()
  if inplay == 1 then
    drag_box:position(Fl:event_x() - tw / 2, Fl:event_y() - th / 2)
    win:redraw()
  end
  drag_timer:doWait(.02)
end

function isitfinish()
for i = 0, rows * cols - 1 do
  if tile[i]:x() ~= pos[i].col or tile[i]:y() ~= pos[i].row then
  return end
end
for i,_ in pairs(tile) do
  tile[i]:hide()
end
preview:hide()
box:show()
if not seconds then
  seconds = os.time() - starttime
  fltk.fl_message("time: "..secondsToClock(seconds).."\n"..moves.." moves")
end
end

function move_tile(t)
if inplay == 0 then
  if not starttime then starttime = os.time()  end
  inplay = 1
  drag_box:show()
  from_t, from_x, from_y = t, t:x(), t:y()
  drag_box:image(t:image())
  t:labeltype(fltk.FL_NO_LABEL)
  t:box(fltk.FL_DOWN_BOX)
else
  inplay = 0
  from_t:labeltype(fltk.FL_NORMAL_LABEL)
  from_t:box(fltk.FL_NO_BOX)
  if from_t:x() ~= t:x() or from_t:y() ~= t:y() then
    from_t:position(t:x(),t:y())
    t:position(from_x, from_y)
    moves = moves + 1
  end
  drag_box:hide()
  win:redraw()
  isitfinish()
end
end

fs, moves, starttime, seconds = 0, 0, nil, nil
Fl:visible_focus(0)
timer = murgaLua.createFltkTimer()
timer:callback(set_tile_images)


win = fltk:Fl_Double_Window(iw,ih, fltk.fl_filename_name(fileName))

tile = {}; pos = {}
row = 0; col = 0
-- -1 is used because the number of tiles starts at 1
-- but table starts at 0 (easier to position them from zero)
for i = 0, rows * cols - 1 do
  tile[i] = fltk:Fl_Button(col,row,tw,th)
  tile[i]:box(fltk.FL_NO_BOX)
  tile[i]:align(80)
  tile[i]:callback(move_tile)
  pos[i]={col=col, row=row}
  col = col + tw
  -- start the next row
  if col == iw then col = 0; row = row + th end
end

drag_box = fltk:Fl_Box(0,0,tw,th)
drag_box:hide()
drag_timer = murgaLua.createFltkTimer()
drag_timer:callback(drag_loop)
drag_timer:do_callback()
inplay = 0

preview = fltk:Fl_Button(-10,-10,1,1)
preview:shortcut("p")
preview:callback(
function()
if box:visible() == 1 then box:hide() else box:show() end
end
)

if iw <= Fl:w() and ih <= Fl:h() then
fullscr = fltk:Fl_Button(-10,-10,1,1)
fullscr:shortcut("f")
fullscr:callback(
function()
if fs == 0 then
  fs = 1
  wx, wy = win:x(), win:y()
  win:fullscreen()
else
  fs = 0
  win:resize(wx,wy,iw,ih)
end
end
)
end

box = fltk:Fl_Box(0,0,iw,ih)
box:image(img)
win:show()
timer:doWait(1)
scramble()
Fl:run()

This post was last modified: 01-10-2011 05:01 AM by mikshaw.

01-08-2011 04:17 AM
Find all posts by this user Quote this message in a reply
Post Reply  Post Thread 

Messages In This Thread
puzzle remix - mikshaw - 01-08-2011 04:17 AM
RE: puzzle remix - mikshaw - 01-08-2011, 04:37 AM
RE: puzzle remix - mikshaw - 01-09-2011, 04:16 AM
RE: puzzle remix - mikshaw - 01-09-2011, 01:09 PM
RE: puzzle remix - mikshaw - 01-10-2011, 05:04 AM
RE: puzzle remix - mikshaw - 01-10-2011, 05:17 AM
RE: puzzle remix - mikshaw - 01-10-2011, 08:28 AM
RE: puzzle remix - mikshaw - 01-11-2011, 01:02 AM
RE: puzzle remix - jpjacobs - 01-11-2011, 01:28 AM
RE: puzzle remix - mikshaw - 01-11-2011, 05:18 AM
RE: puzzle remix - iGame3D - 02-04-2011, 11:51 AM

View a Printable Version
Send this Thread to a Friend
Subscribe to this Thread | Add Thread to Favorites

Forum Jump: