Grafic: How to create puzzle tiles?

Just starting out? Need help? Post your questions and find answers here.
dige
Addict
Addict
Posts: 1403
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Grafic: How to create puzzle tiles?

Post by dige »

I'd like to create a little puzzle game. One image shall divided into nice puzzle tiles..
But how create them? Like this:

Image

Any ideas? :?
"Daddy, I'll run faster, then it is not so far..."
User avatar
Michael Vogel
Addict
Addict
Posts: 2802
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Grafic: How to create puzzle tiles?

Post by Michael Vogel »

A quick start, I would recommend thinking about vector drawing to create a nicer shape...

Code: Select all

; Define

	#X=800
	#Y=600

	Enumeration
		#Image
		#Tile
	EndEnumeration

	CreateImage(#Image,#X,#Y,32)
	CreateImage(#Tile,#X,#Y,32)
	StartDrawing(ImageOutput(#Image))

	DrawingMode(#PB_2DDrawing_Gradient)
	GradientColor(0.4,$00FFFF)
	GradientColor(0.6,$FFFF00)
	FrontColor($FF0000)
	LinearGradient(0,0,#X,#Y)
	Box(0,0,#X,#Y,$FFFFFF)

	DrawingMode(#PB_2DDrawing_AlphaBlend)
	For i=0 To #Y>>2
		Circle(Random(#X),Random(#Y),Random(#X>>4),$80000000|Random(#White))
	Next i
	StopDrawing()

	Structure SetType
		TilesX.i
		TilesY.i
		SizeX.i
		SizeY.i
		HalfX.i
		HalfY.i
		Radius.i
		Back.i
	EndStructure

	Global Set.SetType

; EndDefine

Procedure ClearBoard()

	StartDrawing(ImageOutput(#Image))

	DrawingMode(#PB_2DDrawing_AlphaChannel)
	Box(0,0,ImageWidth(#Image),ImageHeight(#Image),0)

	StopDrawing()

EndProcedure
Procedure ShowTile(x,y)

	Protected color

	#DrawDark=		$80000000
	#DrawOpaque=	$FF000000

	With Set

		For i=0 To 1
			If i=0
				color=#DrawDark
				\Radius+1
				resize=1
				StartDrawing(ImageOutput(#Tile))
				Box(0,0,#X,#Y,#White)
				DrawingMode(#PB_2DDrawing_AlphaBlend)
			Else
				color=#DrawOpaque
				\Radius-1
				resize=0
				StartDrawing(ImageOutput(#Image))
				DrawingMode(#PB_2DDrawing_AlphaChannel)
			EndIf

			Box(x*\SizeX-resize,y*\SizeY-resize,\SizeX+resize<<1,\SizeY+resize<<1,color)
			If (x+y)&1
				Circle(x*\SizeX+\HalfY,y*\SizeY-\Back,\Radius,color)
				Circle(x*\SizeX-\Back,y*\SizeY+\HalfY,\Radius,color)
				If x<\TilesX-1
					Circle((x+1)*\SizeX+\Back,y*\SizeY+\HalfY,\Radius,color)
				EndIf
				If y<\TilesY-1
					Circle(x*\SizeX+\HalfY,(y+1)*\SizeY+\Back,\Radius,color)
				EndIf
			Else
				Circle(x*\SizeX-\Back,y*\SizeY+\HalfY,\Radius,color)
				Circle(x*\SizeX+\HalfY,y*\SizeY-\Back,\Radius,color)
				If x<\TilesX-1
					Circle((x+1)*\SizeX+\Back,y*\SizeY+\HalfY,\Radius,color)
				EndIf
				If y<\TilesY-1
					Circle(x*\SizeX+\HalfY,(y+1)*\SizeY+\Back,\Radius,color)
				EndIf
			EndIf

			StopDrawing()

		Next i
	EndWith


EndProcedure
Procedure ShowBoard()

	StartDrawing(ImageOutput(#Tile))
	DrawAlphaImage(ImageID(#Image),0,0)
	StopDrawing()
	;CopyImage(#Image,#Tile)
	SetGadgetState(0,ImageID(#Tile))

EndProcedure

Procedure PuzzleInit(Image,TilesX,TilesY)

	Protected x,y

	With Set

		\TilesX=TilesX
		\TilesY=TilesY
		\SizeX=ImageWidth(Image)/\TilesX
		\SizeY=ImageHeight(Image)/\TilesY

		\HalfX=\SizeX>>1
		\HalfY=\SizeY>>1

		\Back=\HalfY/3
		\Radius=\Back+5

	EndWith

EndProcedure


OpenWindow(0,0,0,#X,#Y,"Image Demo",#PB_Window_SystemMenu|#PB_Window_TitleBar)
PuzzleInit(#Image,8,6)
ImageGadget(0,0,0,#X,#Y,ImageID(#Image))
AddWindowTimer(0,0,250)

Repeat
	Select WaitWindowEvent()
	Case #PB_Event_Timer
		z+1
		If z>10
			ClearBoard()
			ShowTile(Random(7),Random(5))
			ShowBoard()
		EndIf
	Case #PB_Event_CloseWindow
		End
	EndSelect
ForEver
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: Grafic: How to create puzzle tiles?

Post by freak »

The VectorDrawing library is a good fit for this. The VectorSourceImage() command lets you use the contents of an image to fill or stroke any shape you defined as a path.

Here is an example:

Code: Select all

LoadImage(0, #PB_Compiler_Home + "Examples\Sources\Data\PureBasicLogo.bmp")

If OpenWindow(0, 0, 0, 800, 600, "Example", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  CanvasGadget(0, 0, 0, 800, 600)
  
  If StartVectorDrawing(CanvasVectorOutput(0))
    
    ; First move the origin of our coordinate system to somewhere in the middle of the canvas.
    ; You can use this to keep the code that defines the shapes independent from where the actual tile will be drawn.    
    TranslateCoordinates(100, 100)
    
    ; Create a path that defines the tile shape
    MovePathCursor(0, 0)
    AddPathLine(80, 0)
    AddPathLine(80, 20)
    AddPathCurve(120, 0, 120, 80, 80, 60)
    AddPathLine(80, 80)
    AddPathLine(60, 80)
    AddPathCurve(80, 120, 0, 120, 20, 80)
    AddPathLine(0, 80)
    ClosePath()
    
    ; Move the origin of the "source" coordinate system. Basically, this moves the image we will use for drawing
    ; in relation to the path we just defined. This way the tile shows a part from the middle of the source image
    ; which is more interesting than the edge
    TranslateCoordinates(-200, 0, #PB_Coordinate_Source)
    
    ; Select the image as the source for drawing operations
    VectorSourceImage(ImageID(0), 255, ImageWidth(0) * 2, ImageHeight(0) * 2)
    
    ; Fill the tile shape with the image contents. keep the path
    FillPath(#PB_Path_Preserve)
    
    ; Select a solid color and draw the outline of the tile as well
    VectorSourceColor($FF000000)    
    StrokePath(2)    
    
    StopVectorDrawing()
  EndIf

  Repeat
    Event = WaitWindowEvent()    
  Until Event = #PB_Event_CloseWindow  

EndIf
The library can also help you figure out if the mouse is inside a tile when reacting to user input:
Once you define the path that makes up your tile you can use the IsInsidePath() function to determine if the current mouse coordinates are inside that path or not.
quidquid Latine dictum sit altum videtur
User avatar
Michael Vogel
Addict
Addict
Posts: 2802
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Grafic: How to create puzzle tiles?

Post by Michael Vogel »

I found some cliparts for jigsaw tiles which could be converted to purebasic vector commands easily...

http://de.clipart.me/premium-background ... age-508412
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Re: Grafic: How to create puzzle tiles?

Post by djes »

Nice question, nice examples !
Freak> Did I say to you that this lib is just great ? I say it.
dige
Addict
Addict
Posts: 1403
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Grafic: How to create puzzle tiles?

Post by dige »

Thank you Michael Vogel & freak,
what a great demonstration of the power of the vectorlib!

It looks like, that I need to create more than 9 different kind of pieces/tiles
for corners, edges and inside the body.

I'll fit freak's example for my own purposes and transfer than the tiles/images into sprites.

If there comes out something presentable, I'll post it here ;-)

cya dige
"Daddy, I'll run faster, then it is not so far..."
dige
Addict
Addict
Posts: 1403
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Grafic: How to create puzzle tiles?

Post by dige »

My first attempt:

Image

Does someone knows, why the sprites are not transparent?

Code: Select all

InitSprite()
; UsePNGImageDecoder()
; LoadImage(0, "C:\Temp\Puzzle_Vorlage.png")

CreateImage(0, 866, 579)
If StartDrawing(ImageOutput(0))
  DrawingMode(#PB_2DDrawing_Gradient)      
      BackColor($00FFFF)
      FrontColor($FF0000)
      
      BoxedGradient(0, 0, OutputWidth(), OutputHeight())
  Box(0, 0, OutputWidth(), OutputHeight())
  StopDrawing()
EndIf

Procedure CreatePuzzleTile (Size, FillImgID, Pattern.i, SpriteID = #PB_Ignore)
  
  Protected ImgID = CreateImage(#PB_Any, Size, Size, 32, #PB_Image_Transparent)
  Protected peak.d = (Size * 15) / 100
  Protected gap.d  = (Size * 25) / 100
  Protected length.d = Size - ( 2 * peak )
  
  ; 	       
  ; Pattern: 1-tongue|2-groove Bits from upper to right to bottom to left
  ; Edge Tile upper left = 00011000 (groove right, tongue bottom)
  
  
 If StartVectorDrawing(ImageVectorOutput(ImgID))
   
   ;TranslateCoordinates(peak, peak)
   
   MovePathCursor(peak, peak)
   
   ;{ Check upper side (Cursor Upper Left)
   If Pattern & %11 
     AddPathLine(peak + length/2 - gap/2, peak)
     
     If Pattern & %1 ; tongue
        AddPathCurve(0, 0, size, 0,  peak + length/2 + gap/2, peak)    ; Tongue
       Else
        AddPathCurve(0, 2*peak, size, 2*peak,  peak + length/2 + gap/2, peak)    ; Groove
      EndIf
   EndIf  
   AddPathLine(size-peak, peak)
   ;} 
   
   ;{ Check right side (Cursor Upper Right)
   If Pattern & %1100
     AddPathLine(size-peak, peak + length/2 - gap/2)
     
     If Pattern & %0100 ; tongue
        AddPathCurve(size, 0, size, size, size - peak, peak + length/2 + gap/2)    ; Tongue
       Else
        AddPathCurve(length, 0, length, size, size - peak, peak + length/2 + gap/2)    ; Groove
      EndIf
   EndIf  
   AddPathLine(size-peak, size-peak)
   ;}
   
   ;{ Check bottom side (Cursor bottom Right)
   If Pattern & %110000
     AddPathLine(peak + length/2 + gap/2, size - peak)
     
     If Pattern & %010000 ; tongue
        AddPathCurve(size, size, 0, size, peak + length/2 - gap/2, size - peak)    ; Tongue
       Else
        AddPathCurve(size, size - 2*peak, 0, size - 2*peak, peak + length/2 - gap/2, size - peak)    ; Tongue
      EndIf
   EndIf  
   AddPathLine(peak, size-peak)
   ;}
   
   
   ;{ Check left side (Cursor bottom left)
   If Pattern & %11000000
     AddPathLine(peak, peak + length/2 + gap/2)
     
     If Pattern & %01000000 ; tongue
        AddPathCurve(0, size, 0, 0, peak, peak + length/2 - gap/2)
       Else
        AddPathCurve(2*peak, size, 2*peak, 0, peak, peak + length/2 - gap/2) 
      EndIf
   EndIf  
   AddPathLine(peak, peak)
   ;}
   

   
   ClosePath()
   VectorSourceImage(ImageID(FillImgID), 255, ImageWidth(FillImgID), ImageHeight(FillImgID))
   
   ; Fill the tile shape with the image contents. keep the path
   FillPath(#PB_Path_Preserve)
 
   ; Select a solid color and draw the outline of the tile as well
   VectorSourceColor(RGBA(100, 100, 255, 255))   
   StrokePath(2)   
   StopVectorDrawing()
 EndIf
 
 If SpriteID <> #PB_Ignore
    CreateSprite(SpriteID, Size, Size, #PB_Sprite_AlphaBlending)
    If StartDrawing(SpriteOutput(SpriteID))
      DrawAlphaImage(ImageID(ImgID), 0, 0 )
      StopDrawing()
    EndIf  
 EndIf
  
 FreeImage(ImgID) 
 
 ProcedureReturn peak
EndProcedure

If OpenWindow(0, 0, 0, 800, 600, "Example", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  OpenWindowedScreen(WindowID(0), 0, 0, 800, 600)
  
  If StartDrawing(ScreenOutput())
    Box(0, 0, OutputWidth(), OutputHeight(), RGB(100, 100, 100))
    DrawAlphaImage(ImageID(0), 0, 0, 100)
    StopDrawing()
  EndIf
  
  tilesize = 180
  x = 0
  y = 0
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  x = x + tilesize - 2 * CreatePuzzleTile (tilesize, 3, %00011000, 0)
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  x = x + tilesize - 2 * CreatePuzzleTile (tilesize, 3, %01100100, 1)
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  x = x + tilesize - 2 * CreatePuzzleTile (tilesize, 3, %10011000, 2)
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  x = x + tilesize - 2 * CreatePuzzleTile (tilesize, 3, %01100000, 3)

  
  DisplayTransparentSprite(0, 0, 0)
  DisplayTransparentSprite(1, 190 - 2*offset, 0)
  DisplayTransparentSprite(2, 380 - 2*offset, 0)
  DisplayTransparentSprite(3, 580 - 2*offset, 0)

  Repeat
    Event = WaitWindowEvent()   
  Until Event = #PB_Event_CloseWindow 

EndIf
"Daddy, I'll run faster, then it is not so far..."
User avatar
Michael Vogel
Addict
Addict
Posts: 2802
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Grafic: How to create puzzle tiles?

Post by Michael Vogel »

Try this...

Code: Select all

If SpriteID <> #PB_Ignore
		CreateSprite(SpriteID, Size, Size, #PB_Sprite_AlphaBlending)
		If StartDrawing(SpriteOutput(SpriteID))
			DrawingMode(#PB_2DDrawing_AlphaChannel)
			Box(0,0,size,size,128)
			DrawingMode(#PB_2DDrawing_AlphaBlend)
			DrawAlphaImage(ImageID(ImgID), 0, 0 )
			StopDrawing()
		EndIf
	EndIf
You can create all needed shapes by (mirroring and) rotating a short bezier curve containing four supporting points. I did a quick drawing by using a base square 28x28 and wrote all coordinates so you may be able to create good looking tiles now...

Image
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2139
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Grafic: How to create puzzle tiles?

Post by Andre »

Cool topic, nice examples! Thank you :mrgreen:
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
dige
Addict
Addict
Posts: 1403
Joined: Wed Apr 30, 2003 8:15 am
Location: Germany
Contact:

Re: Grafic: How to create puzzle tiles?

Post by dige »

How to pick up the sprite under the mouse cursor?
Do it need an extra Mousesprite and #PB_Sprite_PixelCollision?

Image

Code: Select all

; Puzzle Creator
; Dige 10/2016
; http://www.purebasic.fr/english/viewtopic.php?f=13&t=66746

InitSprite()
UsePNGImageDecoder()
UseJPEGImageDecoder()

Structure _PUZZLE
  id.i
  x.i
  y.i
  
  cr.i
  cx.i
  cy.i
EndStructure

Global NewList Puzzles._PUZZLE()

If LoadImage(0, "C:\Temp\Endurotraining-original-135.jpg") = 0
  CreateImage(0, 800, 600)
  If StartDrawing(ImageOutput(0))
    DrawingMode(#PB_2DDrawing_Gradient)      
    BackColor($00FFFF)
    FrontColor($FF0000)
    BoxedGradient(0, 0, OutputWidth(), OutputHeight())
    Box(0, 0, OutputWidth(), OutputHeight())
    StopDrawing()
  EndIf
Else
  ResizeImage(0, 800, 600)
EndIf

Procedure DrawPuzzle(bgr = 0)
  
  FlipBuffers()
  ClearScreen(RGB(0,0,0))
  
  If bgr
    If StartDrawing(ScreenOutput())
      Box(0, 0, OutputWidth(), OutputHeight(), RGB(100, 100, 100))
      DrawAlphaImage(ImageID(0), 0, 0, 100)
      StopDrawing()
    EndIf
  EndIf  
  
  ForEach Puzzles()
    With Puzzles()
      RotateSprite(\id, \cr, #PB_Absolute)
      DisplayTransparentSprite(\id, \cx, \cy)
    EndWith
  Next
  
EndProcedure

Procedure CreatePuzzleTile (Size, FillImgID, Pattern.i, SpriteID, x, y)
  
  Protected ImgID = CreateImage(#PB_Any, Size, Size, 32, #PB_Image_Transparent)
  Protected peak.i = (Size * 15) / 100
  Protected gap.i  = (Size * 25) / 100
  Protected length.i = Size - ( 2 * peak )
  
  ; 	       
  ; Pattern: 1-tongue|2-groove Bits from upper to right to bottom to left
  ; Edge Tile upper left = 00011000 (groove right, tongue bottom)
  
  
 If StartVectorDrawing(ImageVectorOutput(ImgID))
   
   ;TranslateCoordinates(peak, peak)
   
   MovePathCursor(peak, peak)
   
   ;{ Check upper side (Cursor Upper Left)
   If Pattern & %11 
     AddPathLine(peak + length/2 - gap/2, peak)
     
     If Pattern & %1 ; tongue
        AddPathCurve(0, 0, size, 0,  peak + length/2 + gap/2, peak)    ; Tongue
       Else
        AddPathCurve(0, 2*peak, size, 2*peak,  peak + length/2 + gap/2, peak)    ; Groove
      EndIf
   EndIf  
   AddPathLine(size-peak, peak)
   ;} 
   
   ;{ Check right side (Cursor Upper Right)
   If Pattern & %1100
     AddPathLine(size-peak, peak + length/2 - gap/2)
     
     If Pattern & %0100 ; tongue
        AddPathCurve(size, 0, size, size, size - peak, peak + length/2 + gap/2)    ; Tongue
       Else
        AddPathCurve(length, 0, length, size, size - peak, peak + length/2 + gap/2)    ; Groove
      EndIf
   EndIf  
   AddPathLine(size-peak, size-peak)
   ;}
   
   ;{ Check bottom side (Cursor bottom Right)
   If Pattern & %110000
     AddPathLine(peak + length/2 + gap/2, size - peak)
     
     If Pattern & %010000 ; tongue
        AddPathCurve(size, size, 0, size, peak + length/2 - gap/2, size - peak)    ; Tongue
       Else
        AddPathCurve(size, size - 2*peak, 0, size - 2*peak, peak + length/2 - gap/2, size - peak)    ; Tongue
      EndIf
   EndIf  
   AddPathLine(peak, size-peak)
   ;}
   
   
   ;{ Check left side (Cursor bottom left)
   If Pattern & %11000000
     AddPathLine(peak, peak + length/2 + gap/2)
     
     If Pattern & %01000000 ; tongue
        AddPathCurve(0, size, 0, 0, peak, peak + length/2 - gap/2)
       Else
        AddPathCurve(2*peak, size, 2*peak, 0, peak, peak + length/2 - gap/2) 
      EndIf
   EndIf  
   AddPathLine(peak, peak)
   ;}
   

   
   ClosePath()
   VectorSourceImage(ImageID(FillImgID), 255, ImageWidth(FillImgID), ImageHeight(FillImgID))
   
   ; Fill the tile shape with the image contents. keep the path
   FillPath(#PB_Path_Preserve)
 
   ; Select a solid color and draw the outline of the tile as well
   VectorSourceColor(RGBA(100, 100, 100, 255))   
   StrokePath(2)   
   StopVectorDrawing()
 EndIf
 
  
  CreateSprite(SpriteID, Size, Size, #PB_Sprite_AlphaBlending)
  If StartDrawing(SpriteOutput(SpriteID))
     DrawingMode(#PB_2DDrawing_AlphaChannel)
     Box(0,0,size,size,128)
     DrawingMode(#PB_2DDrawing_AlphaBlend)
     DrawAlphaImage(ImageID(ImgID), 0, 0 )
     StopDrawing()
   EndIf
   AddElement( Puzzles())
   With Puzzles()
     \id = SpriteID
     \x  = x
     \y  = y
     \cx = x
     \cy = y
     \cr = 0
   EndWith  
  
 FreeImage(ImgID) 
 
 ProcedureReturn length
EndProcedure

  w = 800
  h = 600


If OpenWindow(0, 0, 0, w, h, "Puzzle Game", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  OpenWindowedScreen(WindowID(0), 0, 0, w, h)
  
  tilesize = 180
  x = 0
  y = 0
  l = 0
  
  ; First Row
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %00011000, 0, 0, 0)
  x + l
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100100, 1, 1*l, 0)
  x + l
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011000, 2, 2*l, 0)
  x + l
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100100, 3, 3*l, 0)
  x + l
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011000, 4, 4*l, 0)
  x + l
  
  GrabImage(0, 3, x, 0, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100000, 5, 5*l, 0)
  
  ; Second Row
  x = 0
  y + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %00100110, 6, 0, l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011001, 7, 1*l, l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100110, 8, 2*l, l)
  x + l

  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011001, 9, 3*l, l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100110, 10, 4*l, l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10010001, 11, 5*l, l)
  
  ; Third Row
  x = 0
  y + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %00011001, 12, 0, 2*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100110, 13, 1*l, 2*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011001, 14, 2*l, 2*l)
  x + l

  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100110, 15, 3*l, 2*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10011001, 16, 4*l, 2*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01100010, 17, 5*l, 2*l)
  
 ; Last Row
  x = 0
  y + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %00000110, 18, 0, 3*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10001001, 19, 1*l, 3*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01000110, 20, 2*l, 3*l)
  x + l

  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10001001, 21, 3*l, 3*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %01000110, 22, 4*l, 3*l)
  x + l
  
  GrabImage(0, 3, x, y, tilesize, tilesize)
  l = CreatePuzzleTile (tilesize, 3, %10000001, 23, 5*l, 3*l)
  
  DrawPuzzle(1)
  
  Repeat
    Event = WaitWindowEvent()   
    
    If Event = #WM_KEYDOWN
      ForEach Puzzles()
        With Puzzles()
          Select Random(3)
            Case 0 : \cr = 0
            Case 1 : \cr = 90
            Case 2 : \cr = 180
            Case 3 : \cr = 270
          EndSelect
          
          \cx = Random(w - tilesize)
          \cy = Random(h - tilesize)

        EndWith
      Next
      DrawPuzzle(0)
    EndIf
    
  Until Event = #PB_Event_CloseWindow 

EndIf
"Daddy, I'll run faster, then it is not so far..."
User avatar
Michael Vogel
Addict
Addict
Posts: 2802
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Grafic: How to create puzzle tiles?

Post by Michael Vogel »

Did not had a look at the sprites at the moment, but I've tried to create more realistic jigsaw tiles. Here's the result, you can reduce the creation of "special tiles" (marked with red dots) by decreasing the value of the constant #Chi.

Code: Select all

; Define

	#BoardMaxX=50
	#BoardMaxY=40

	#TileFill=	1

	Enumeration
		#SideTop
		#SideLeft
		#SideBottom
		#SideRight
	EndEnumeration

	EnumerationBinary
		#BorderTop
		#BorderLeft
		#BorderBottom
		#BorderRight
	EndEnumeration

	Enumeration
		#FlagHole
		#FlagNose
		#FlagLine
		#FlagFilter
	EndEnumeration

	Structure Tile
		x.i
		y.i
		type.i
		fixed.i
	EndStructure

	Global Dim Curve.Point(#SideRight,1,18)
	Global Dim Board.Tile(#BoardMaxX,#BoardMaxY)

; EndDefine

Procedure InitShapes()

	Protected BirdsTail.s
	Protected *Mem
	Protected i,j,k

	#BirdTailDots=9
	#BirdSize=28

	BirdsTail="@VDVETEREOANDLFKJMNN";	(c) 2016 by Michael Vogel


	*Mem=@BirdsTail
	For i=0 To #BirdTailDots
		Curve(#SideBottom,#FlagNose,#BirdTailDots+i)\x=PeekB(*Mem)-'@'
		Curve(#SideBottom,#FlagNose,#BirdTailDots-i)\x=-Curve(#SideBottom,#FlagNose,#BirdTailDots+i)\x
		*Mem+1
		Curve(#SideBottom,#FlagNose,#BirdTailDots+i)\y=PeekB(*Mem)-'@'
		Curve(#SideBottom,#FlagNose,#BirdTailDots-i)\y=Curve(#SideBottom,#FlagNose,#BirdTailDots+i)\y
		*Mem+1
	Next i

	For i=0 To #BirdTailDots<<1
		Curve(#SideTop,#FlagNose,i)\x=-Curve(#SideBottom,#FlagNose,i)\x
		Curve(#SideTop,#FlagNose,i)\y=-Curve(#SideBottom,#FlagNose,i)\y
		Curve(#SideLeft,#FlagNose,i)\x=-Curve(#SideBottom,#FlagNose,i)\y
		Curve(#SideLeft,#FlagNose,i)\y=Curve(#SideBottom,#FlagNose,i)\x
		Curve(#SideRight,#FlagNose,i)\x=Curve(#SideBottom,#FlagNose,i)\y
		Curve(#SideRight,#FlagNose,i)\y=-Curve(#SideBottom,#FlagNose,i)\x
	Next i

	For j=0 To #SideRight
		For i=0 To #BirdTailDots<<1
			k=(1-(j&1)<<1)
			Curve(j,#FlagHole,i)\x=Curve(j,#FlagNose,i)\x*k+#BirdSize*(j-2)*(j&1)
			Curve(j,#FlagHole,i)\y=-Curve(j,#FlagNose,i)\y*k+#BirdSize*(j-1)*(j&1)!1
		Next i
	Next j

EndProcedure
Procedure DrawSide(x,y,side,type)

	Protected i,pos

	If side=#SideTop
		MovePathCursor(x+Curve(side,#Null,pos)\x,y+Curve(side,#Null,pos)\y)
	EndIf

	If type&#FlagLine
		AddPathLine(x+Curve(side,#Null,#BirdTailDots<<1)\x,y+Curve(side,#Null,#BirdTailDots<<1)\y)

	Else
		pos=0
		For i=0 To 5
			AddPathCurve(x+Curve(side,type,pos+1)\x,y+Curve(side,type,pos+1)\y,x+Curve(side,type,pos+2)\x,y+Curve(side,type,pos+2)\y,x+Curve(side,type,pos+3)\x,y+Curve(side,type,pos+3)\y)
			pos+3
		Next i

	EndIf

	If side=#SideRight
		ClosePath()
	EndIf

EndProcedure
Procedure DrawTile(x,y,type)

	If #TileFill
		DrawSide(x,y,#SideTop,	type>>0&#FlagFilter)
		DrawSide(x,y,#SideLeft,	type>>2&#FlagFilter)
		DrawSide(x,y,#SideBottom,type>>4&#FlagFilter)
		DrawSide(x,y,#SideRight,	type>>6&#FlagFilter)

		VectorSourceColor($ffC0C0C0|(Random(#White)))
		FillPath()
		StrokePath(0.1)
	EndIf

	DrawSide(x,y,#SideTop,	type>>0&#FlagFilter)
	DrawSide(x,y,#SideLeft,	type>>2&#FlagFilter)
	DrawSide(x,y,#SideBottom,type>>4&#FlagFilter)
	DrawSide(x,y,#SideRight,	type>>6&#FlagFilter)
	VectorSourceColor($FF000000)
	StrokePath(0.5,#PB_Path_RoundCorner)

EndProcedure
Procedure InitBoard(x,y,size,special)

	Protected i,j,z

	If x>#BoardMaxX Or y>#BoardMaxY
		End
	EndIf

	For i=1 To x
		For j=1 To y
			With Board(i,j)
				\x=i*size
				\y=j*size
				\type=%10001<<(((i+j)&1)<<1)
				If j=1
					\type|%10
				EndIf
				If i=1
					\type|%1000
				EndIf
				If j=y
					\type|%100000
				EndIf
				If i=x
					\type|%10000000
				EndIf
			EndWith
		Next j
	Next i

	z=x*y*special/100
	While z
		z-1
		i=Random(x-1)
		j=Random(y-1)
		If Random(1)
			Board(i,j)\type!%10000
			Board(i,j+1)\type!%1
		Else
			Board(i,j)\type!%1000000
			Board(i+1,j)\type!%100
		EndIf
	Wend

EndProcedure

#X=	8
#Y=	5
#Chi=	25; (0 to 100)
#Rho=	2

InitShapes()
InitBoard(#X,#Y,#BirdSize+#Rho,#Chi)

If OpenWindow(0,0,0,900,600,"Jigsaw tiles created by Michael Vogel", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	CanvasGadget(0,0,0,900,600)

	If StartVectorDrawing(CanvasVectorOutput(0))
		ScaleCoordinates(3.6,3.6)
		TranslateCoordinates(-10,-8)

		For i=1 To #X
			For j=1 To #Y
				With Board(i,j)
					DrawTile(\x,\y,\type)
					If i>1 And j>1 And i<#X And j<#y And \type<>%10001 And \type<>%1000100
						VectorSourceColor($FF0000FF)
						AddPathCircle(\x,\y,3)
						FillPath()
						StrokePath(0.1);	mark special tile
					EndIf
				EndWith
			Next j
		Next i

		StopVectorDrawing()
	EndIf

	Repeat
		Event = WaitWindowEvent()
	Until Event = #PB_Event_CloseWindow
EndIf
Post Reply