help with jigsaw puzzle code

I would use some version of OOP (object Oriented programming).  Lua, I am told is not true OOP language. There are several great posts  on the forum showing different ways to to do a type of OOP using lua.

here is one link :  http://forums.coronalabs.com/topic/40640-luoop-lua-oop-library/

here is a more recent one : http://forums.coronalabs.com/topic/45630-corona-lua-oop-trying-to-settle-on-a-method/

Using some version of OOP that you learn from reading the posts on the forum about OOP,  I would make a class called ‘puzzle’, and a class called ‘puzzlePiece’.  In the puzzle class, I would have variables that describe the puzzle; such as ‘size’.  So you would set the size of the puzzle each time you create a ‘puzzle’ object, and the ‘puzzle’ object would then, base on it’s size, create that many ‘puzzlePiece’ objects.  It takes a little more coding & learning time up front, but makes it much easier to fix bugs, and much easier for such things as adding more dimensions to your app.

There is a way to do it just using tables, but I would lean toward at least researching the OOP methods, and then you will understand what a class and object are and that will help you figure how to do just what you are wanting to do.

Hope this helps.

so for example where would i put those class and what would i put in them? im a noob with making games

It would be best if you checked out some of those tutorials on the forum first.  What I do is not true OOP and is not as versatile as some of these other methods.

Here are some links:

http://forums.coronalabs.com/topic/49915-loogine-a-new-open-source-oop-engine-based-on-luoop-in-progress/

http://jessewarden.com/2011/07/corona-game-example-oop-scope-box2d-collisions-part-1.html

http://lazywombat.co.uk/object-oriented-programming-in-corona-sdk-part-1-basics/

The third one is closer to how I do it, and I feel that one is easier to understand. But, the other 2 are closer to true OOP.

I could type a bunch of code showing how I would do it, but you might be better reading these links first, and see which method you would prefer.  It may answer your questions better.  If you are still having issue, reply and I will type out a sample of what i do.

Good luck

does anyone know what coding languages are compatible with .lua. if you know then please let me know.

is there a way to auto generate the puzzle pieces final position so they fit together?

Jonathon,

Here is a quick and dirty way to do what I think you are trying to do.  The method (of sorta OOP) that I use I picked up from someone who posted it on the forum a long time ago. I adapted it a little to fit my needs.  I am not saying it is the best way or right way or only way. It is just a way that works for me.

Again this is the bare bones.  I cannot ‘ever’ get the ‘formatting’ code tags on the forum post to show my code properly formatted. So cut and paste the code below into a new project on your editor to see the code formatted.  And it will be eraser to read.

I only did the piece class and main. I did not bother with a puzzle class, which you may be able to figure how to do that from this code.

Code makes a single puzzle of 4 pieces, 2x2.

You will need 2 lua files (main.lua and piece.lua) to test this.  And you will need to crate 4 images name p1.png, p2.png, p3.png, p4.png… they should each be the same size … and a background image to use as a frame for the puzzle.

 *********   piece.lua    *******

– sample code from corona tutorial on collisions

local function hasCollided( obj1, obj2 )

   if ( obj1 == nil ) then  --make sure the first object exists

      return false

   end

   if ( obj2 == nil ) then  --make sure the other object exists

      return false

   end

   local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin

   local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax

   local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin

   local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax

   return (left or right) and (up or down)

end

local M = {}

 function M.new(_id)

  local self = { id = _id, image, home, origX, origY, storePos }  

  self.image = display.newImage(“Textures/Puzzles/Puzzle1/p” … self.id … “.png”)

  self.home = display.newRect(0,0,self.image.width, self.image.height)

    self.storePos = {x =0, y = 0}

  local function getHome()

  return self.home

  end

local function setPosition(_x, _y)

self.image.x = _x

self.image.y = _y

– shift image; adjust for reference point

self.image.x = self.image.x - (self.image.width * .5)

self.image.y = self.image.y - (self.image.height * .5)

– this rect is the home spot for the piece.

self.home.x = self.image.x

self.home.y = self.image.y

self.home.isVisible = false

end

local function getImage()

return self.image

end

local function store(_pos)

self.image.x = _pos.x

self.image.y = _pos.y

self.storePos.x = self.image.x

self.storePos.y = self.image.y

end

local function onTouch(e)

– you may find better ‘dragging’ code on the forum

– this is just a simple version of dragging object

if e.phase == “began” then

display.getCurrentStage():setFocus( e.target )

self.origX = self.image.x 

self.origY = self.image.y 

elseif e.phase == “moved” then

local x = (e.x - e.xStart) + self.origX

local y = (e.y - e.yStart) + self.origY

self.image.x, self.image.y = x, y

elseif e.phase == “ended”  or e.phase == “cancelled” then

– now check for collision with the home spot

– if collided with home rectangle, move piece into place

if hasCollided( self.image, self.home ) then

– let main know piece fits, let main insert piece into the puzzle frame

G_setPiece(self.id)

else

– move piece back to the side of screen, it’s original store position

transition.to(self.image, {time = 500, x = self.storePos.x, y = self.storePos.y})

end

display.getCurrentStage():setFocus(nil)

end

return true

end

self.image:addEventListener(“touch”, onTouch)

return { getHome = getHome, setPosition = setPosition, store = store, getImage = getImage }

end

return M

 *********    main.lua   ********

display.setStatusBar(display.HiddenStatusBar) 

local _W = display.contentWidth

local _H = display.contentHeight

local MID_W = _W * .5

local MID_H = _H * .5

local Piece = require(“piece”)

local pieces = {}

local pieceCnt = 1

local bkgd = display.newImage(“Textures/bkgd.png”)

local puzzleFrame = display.newGroup()

puzzleFrame:insert(bkgd)

– 2X2 PUZZLE … total 4 pieces

for i = 1, 2 do

for ii = 1, 2 do

table.insert(pieces, Piece.new(pieceCnt)  )

puzzleFrame:insert(pieces[pieceCnt].getHome())

local width = pieces[pieceCnt].getImage().width

local height = pieces[pieceCnt].getImage().height

pieces[pieceCnt].setPosition( (ii - 1) * width, (i-1) * height )

pieces[pieceCnt].store( {x =50, y = pieceCnt * 40} )

pieceCnt = pieceCnt + 1

end

end

puzzleFrame.x = MID_W

puzzleFrame.y = MID_H

function G_setPiece(_id)

puzzleFrame:insert(pieces[_id].getImage())

pieces[_id].getImage().x = pieces[_id].getHome().x

pieces[_id].getImage().y = pieces[_id].getHome().y

end

so would the same code work for more than 4 puzzle peices with the right modifications? like 9 puzzle peices or more.

it gave me this error when i tried to work this

yes.

just change these 2 lines, in main.lua

for i = 1, 2 do

for ii = 1, 2 do

 

to 

 

for i = 1, 3 do

for ii = 1, 3 do

just be sure to have 9 puzzle pieces named  p1.png  thru p9.png, so the piece class will find each puzzle image.

However, It is better to not use separate textures for each piece.  It is more efficient and cleaner to use newIimageSheet, where you would have one texture with 9 frames, 1 frame for each puzzle piece.

But, either way works.

Check out this link that explains  newImageSheet

http://docs.coronalabs.com/api/library/graphics/newImageSheet.html

you can make this change to ‘piece.lua’ to use image sheet instead of the separate textures:

– place these 2 lines somewhere above     local M = {}        in the ‘piece.lua’ file

local options_Puzzle1 = { width = 40, height = 40, numFrames = 9, sheetContentWidth = 120, sheetContentHeight = 120 }

local puzzlePieces = graphics.newImageSheet(“Textures/puzzle1_Sheet.png”, options_Puzzle1)

– in this example you would need to have a texture that is 120 x 120, that looks like a grid of puzzle pieces

– in a 3x3 pattern.  Each one of those are a 40x40 frame.

– but the texture (image sheet) does not have to be 3x3 pattern, it could be one long horizontal or vertical strip of frames

– It is just that the params in the ‘options_Puzzle1’ have to match how many frames, size of the frames and size of the full texture.

–  Read the docs front the link above to get a better understanding on that.

 --change this line

 self.image = display.newImage(“Textures/Puzzles/Puzzle1/p” … self.id … “.png”)

 --to this 

 self.image = display.newImage(puzzlePieces, self.id)

 – self.id here will be the numbers 1 thru 9, in this example

 – that point to relative frame in the imageSheet you created above

This also is just a quick easy way to do it.  There are several things to optimize this and make it more versatile… but this example should help you.

Ref your error message:

When you created the piece.lua file, did you save it to the project directory?  The same directory where you have the main.lua for this example?

The error sounds to me like it can’t find the ‘piece’lua’ file.  Another possibility is if you have any thing spelled wrong or the wrong case.  So make sure the file name ‘piece.lua’  and require(“piece”) , have ‘piece’ spelled the same and same lower case letters.

it gives me a error with the piece line 32 for image a nil value. and how would i get more than one puzzle so that people can choose different puzzles.

can you reply and paste in your piece.lua file  and will look at it.

Meanwhile, the line     self.image = display.newImage(“Textures/Puzzles/Puzzle1/p” … self.id … “.png”) needs to match the path correctly where you have your images?

Are you using imagesheet for the puzzle piece images or separate textures?

i am trying to get the screenshot to dissipear after it has been taken. does any one know what is wrong with my code? here it is

local function

captureDeviceScreen ( )

local captured_image = display.captureScreen ( true )

captured_image:scale (.5, .5)

local alert = native.showAlert ( “Success”, “Captured Image is Saved to Library”, { “OK” } )

end

Runtime:addEventListener(“tap”, captureDeviceScreen)

– Project: build.settings

– Description: 

– Version: 1.0

– Managed with http://CoronaProjectManager.com

– Copyright 2014 . All Rights Reserved.

– 

local function hasCollided( obj1, obj2 )

   if ( obj1 == nil ) then  --make sure the first object exists

      return false

   end

   if ( obj2 == nil ) then  --make sure the other object exists

      return false

   end

   local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin

   local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax

   local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin

   local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax

   return (left or right) and (up or down)

end

local options_Puzzle1 = { width = 40, height = 40, numFrames = 9, sheetContentWidth = 120, sheetContentHeight = 120 }

local puzzlePieces = graphics.newImageSheet(“1.png”, options_Puzzle1)

local M = {}

 function M.new(_id)

  local self = { id = _id, image, home, origX, origY, storePos }  

self.image = display.newImage(“Libraries/Pictures/IMG_4448/p” … self.id … “.jpg”)

  self.home = display.newRect(0,0,self.image.width, self.image.height)

    self.storePos = {x =0, y = 0}

  local function getHome()

  return self.home

  end

local function setPosition(_x, _y)

self.image.x = _x

self.image.y = _y

– shift image; adjust for reference point

self.image.x = self.image.x - (self.image.width * .5)

self.image.y = self.image.y - (self.image.height * .5)

– this rect is the home spot for the piece.

self.home.x = self.image.x

self.home.y = self.image.y

self.home.isVisible = false

end

local function getImage()

return self.image

end

local function store(_pos)

self.image.x = _pos.x

self.image.y = _pos.y

self.storePos.x = self.image.x

self.storePos.y = self.image.y

end

local function onTouch(e)

– you may find better ‘dragging’ code on the forum

– this is just a simple version of dragging object

if e.phase == “began” then

display.getCurrentStage():setFocus( e.target )

self.origX = self.image.x 

self.origY = self.image.y 

elseif e.phase == “moved” then

local x = (e.x - e.xStart) + self.origX

local y = (e.y - e.yStart) + self.origY

self.image.x, self.image.y = x, y

elseif e.phase == “ended”  or e.phase == “cancelled” then

– now check for collision with the home spot

– if collided with home rectangle, move piece into place

if hasCollided( self.image, self.home ) then

– let main know piece fits, let main insert piece into the puzzle frame

G_setPiece(self.id)

else

– move piece back to the side of screen, it’s original store position

transition.to(self.image, {time = 500, x = self.storePos.x, y = self.storePos.y})

end

display.getCurrentStage():setFocus(nil)

end

return true

end

self.image:addEventListener(“touch”, onTouch)

return { getHome = getHome, setPosition = setPosition, store = store, getImage = getImage }

end

return M

First let’s fix the error…  So, this looks like the only change to the code you made was the path for the image; which is all you need to do to test it. So I am guessing that path is maybe wrong.

Is the path you have type here spelled correctly and the case correct ?   Is the path , “Libraries/Pictures/IMG_4448”

in your project folder?

On the terminal output display where you see the error  ‘image a nil value’, above that message a few lines, is there any line that shows this message :

Failed to find image “Libraries/Pictures/IMG_4448/p1.jpg”  ??    this will tell you the image is not found, thus the error on line 32.

I will send you an example of how to have a list of several puzzles for the user to choose from, later this evening.

all i had to do was just erase the library pictures and img_4448 and just leave the p and change the jpg to png and it fixed the error. is there a way for it to go to the next jigsaw puzzle?

Jonathon,

There is a way to have a table of puzzles and allow user to select any puzzle and pull the pieces for any of those puzzles.

If you can email me at  ripps7@hotmail.com , I can email you a link to a sample of code I did to create a simple puzzle. 

I also would recommend you checkout this info about OOP on Corona Blog page; just posted yesterday.

Develephant talks about one of the easiest OOP methods I have seen yet for lua.  I think this will be super helpful if you can take the time to watch the video, and then be sure to download the ‘example’ code that is in a link below the video. 

Corona Geek #103, about 20 mins into the video is when they start the OOP discussion.

does anyone know how to make a game ever expanding? like for this game, i would like to be able to make it so that people can send in the photos that they want to make into a jigsaw puzzles, so it could be expanding. and how would i add difficulty levels, like easy, medium and hard.

any idea on how to make these look joined? also the x and y coordinates what should they be?

here are the coordinates for smooth1.png

{x=66, y=59},

{x=153, y=65},

{x=260, y=65},

{x=55, y=155},

{x=163,  y=155},

{x=260,  y=164},

{x=55, y=256},

{x=152, y=255},

{x=253, y=255}

}

and here are the coordinates for smooth.png

{x=66, y=59},

{x=165, y=70},

{x=265, y=65},

{x=66, y=150},

{x=165,  y=170},

{x=270,  y=165},

{x=74, y=252},

{x=174, y=263},

{x=270, y=263}

}

does anyone know what coding languages are compatible with .lua. if you know then please let me know.