[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Re: manually cutting a picture



Ok so let me get this straight what i would do i create a piece say puzzlepiece_1 _2 and so on make them as templates that the user can use to cut out the image where he wants to.

so what i would have is something like this.

Def curvature_func(pos, eb_size, xmod, ymod):
      #A general curve to the piece kinda like a wavy line.
      state1 = float(pos) / float(xmod) * twopi
      state2 = float(pos) / float(ymod) * twopi
      state3 = float(pos) / float(xmod+ymod) * twopi
      state4 = float(pos) * (2.0/3.0) / float(xmod) * twopi
      state5 = float(pos) * (-12.0/5.0) / float(ymod) *twopi

      bgen = math.sin(state1) + math.cos (state2) + math.sin(state3)
      bgen = bgen - mat.cos(states4) + math.cos(state5)

      scale = (eb_size / 5.0
      bgen = (bgen * (scale*0.9))
      return int(bgen)
# def the way the piece will split and a what degree.
def split_puzzle(full_surface, xdivs, ydivs, screen, background):
     img_rect = full_surface.get_rect()
     xsize = img_rect.width / xdivs
     ysize = img_rect.hieght / ydivs
    
     edge_buffer = 20

     img_array = pygame.surfarray.array3d(full_surface)
#this will let them know that the piece is properly being cut...
     total_progress = xdivs*ydivs + (2 * (xdivs) & (xdivs)) + 1

     progress = pygame.sprite.RenderUpdates()
     ProgressMeter.containers = progress
   
    pm = ProgressMeter(total_progress, "Copying Pieces From Image File....",
                           pygame.font.Font(none, 25))
#and clear the message when it is properly cut.
     progress.clear(screen, background)
     progress.update()
     dirty = progress.draw(screen)
     pygame.display.update(dirty)
     pygame.event.pump ()
     debug_font - pygame.font.Font(None, 20)
# now blit the image that was cut out
     for x in range(0, xdivs):
         for y in range(0, ydivs):
              piece_surf = pygame.Surface((xsize+(2*edge_buffer), ysize+(2*edge_buffer))).convert()
              piece_surf.fill((0,0,0,255))
              piece_surf.blit(full_surface, (edge_buffer - 1, edge_buffer - 1),
                                     (x*xsize,y*ysize,xsize,ysize))
#now just reset the action so it can be completed on the next piece.
             new_piece = PuzzlePiece(x,y)
             new_peice.set_image(piece_surf)
             pm.task_complete()
             push_image(progress, screen, background)
             pass
         pass
# i need to find a way to set the values of the sides of the puzzle piece so they can be connected later in the #game.......

# but then apply the wavey line.
      xpos = int(random.random()*100000)
      ypos = int( random.random()*100000)
       for x in range(0, xdivs):
           for y in range(o, ydivs):
                cur = PuzzlePiece.getpiece(x,y)
 
                if cur.south != None:
                    for z in range(0, cur.rect.width):
                          xcopy = curvature_func9xpos, edge_buffer, xsize, ysize)
                           image_ew_jagify(cur, cur.east, edge_buffer, z, ycopy)
                           xpos = xpos + 1
                           pass
                     pass

 Something like that correct.  or would that not work.

On 11/6/07, Casey Duncan <casey@xxxxxxxxxxx> wrote:
On Nov 6, 2007, at 9:29 AM, Joseph king wrote:

> I have a kinda hard question.... i am trying to build a jigsaw game
> with python, i would like to give the option for people to create
> there own puzzle piece.... does anyone know how to accomplish this
> it is becoming increasingly difficult for me

Note that you don't just create one piece, you need a template in
which to cut out the entire puzzle. From there you would need to
create "die" surfaces you can use to stamp out the piece shapes from
the original image. The dies could use alpha blending and even make
nice looking chamfered edges if you wanted.

I think making the dies is the hard part. Are you looking to do that
at run-time or have a set of pregenerated templates?

The dies would consist of surfaces slightly larger than the pieces
they cut out. Around the outside of the die, the surface would be an
opaque black (0,0,0,255). On the inside of the die, where the piece
is, the die would be completely transparent (0,0,0,0). Along the
border of the piece you could transition from slightly translucent to
transparent for a few pixels to make it look die-cut.

To create a piece, you would blit the puzzle image into a new surface
that is the size of the die (cutting out a rectangular piece of the
puzzle). Then you would blit the die on top. This would "cut" out the
piece in the desired irregular shape.

To make the dies, you would need to come up with an algorithm that
creates irregular curved lines across and down your puzzle rectangle.
The lines should be regularly spaced so you can know the approximate
size of each piece ahead of time. This could be a parameter the user
inputs, for instance. You need to make sure the curved parts of the
line aren't too large or happen to close to the intersections, or
you'll wind up with lots of little shards of pieces. I'm sure there
are well studied algorithms for this out there, I'll leave finding
one as an exercise for the reader.

Once you have the lines, you need to figure out where the
intersections are. If you are clever enough they can probably be
completely fixed positions depending on the piece size. Once you know
that you can derive the desired rect of each die (note they will
overlap each other if laid out together on the puzzle image). Then
creating the die becomes a matter of "filling" (using a seed fill or
somesuch) the area of each die outside the piece. You need to make
sure the die is big enough that the fill can "flow" around the edges
properly. Basically the die rect must be slightly larger than the
irregular border of the piece.

Writing a seed fill in python is probably too slow, so you'll want to
find an alternative. One way would be to approximate each die edge as
a filled polygon, then let the filling happen in the library code.
You could also make each piece a polygon and make a die for each
piece but cutting it out and filling the pieces around it. To
accomplish that I would suggest starting with a grid to mark each
piece corner and creating the lines between the pieces as lists of
points approximating a curve. The poly for each piece then becomes
the concatenation of the four point lists for the corners of that
piece. Edges are just a straight line between the corners.

To further simplify things, you could come up with a fixed number of
edge shapes (represented as a list of points relative to a corner).
By combining them in different ways for each piece, the puzzle would
still always be different, but you wouldn't have to worry about
random edge generation cutting things incorrectly.

Anyhow, those are some suggestions off the top of my head. Seems like
a fun problem to solve. Good luck!

-Casey