Letter Puzzle

Miscellaneous Forums/Blitz Showcase/Letter Puzzle

The forum is locked. These are the original blitzbasic.com forums, kept so they can still be read. No new topics, replies or edits can be made here. To join in, head over to the Blitz3D+ forums.

Here is a version with filled shapes. I have removed the tPoint structure since the polygon shapes use array data

Couple of things to fix:
1) CheckIfFinished() not implemented
2) PointInPoly() function not working yet? The shape should turn RED when the mouse is over it

The shapes x/y positional structure stays the same in this example. The movement of the poly is done by using the SetOrigin command
Only the rotation affects the array values


There is another great puzzle similar to this where you need to fill a box area with pre-defined shapes. I cannot remember the name of the puzzle though

SuperStrict

Graphics 800,600

'-----------
' SHAPE DATA
'-----------
'       num. points, x, y,   x,   y,   x,   y,   x,  y,   x,  y

Global shapes:tShape[4]
shapes[0]=tShape.Create([30.0,  -100.0,    30.0,  55.0, -40.0,  55.0, -40.0, -30.0])
shapes[1]=tShape.Create([-35.0,   -75.0,   -35.0,  25.0,  35.0,  25.0,  35.0,  -5.0])
shapes[2]=tShape.Create([-15.0,    50.0,   -15.0, -15.0,  50.0, -15.0])
shapes[3]=tShape.Create([30.0,  -100.0,    30.0,  90.0, -15.0,  45.0, -40.0, 70.0, -40.0, -30.0])


Local GameHandle:tGameHandle=tGameHandle.Create(4)

While Not KeyHit(KEY_ESCAPE)
	GameHandle.mainLoop()
	Flip
	Cls
Wend

End

'---------------------------------------------
' GameHandle type
' -Handles general flow of the game
'---------------------------------------------
Type tGameHandle
	Const SOL_DIST:Int=5 ' distance there may be between points for them to be 'connected'
	Const MODE_MOVE:Int=1
	Const MODE_ROTATE:Int=2
	Global oldGfx:Int[]=New Int[4] ' colR,colG,colB,lineW
	
	Field numShapes:Int,numSolutions:Int
	Field solData1:Int[] ' solution data [p1]
	Field solData2:Int[] ' solution data [p2]
	Field selectedShape:Int=-1
	Field currentMode:Int=MODE_MOVE
	Field tmpX:Int=-1,tmpY:Int=-1 ' mouse move

	Function Create:tGameHandle(_numshapes%)
		Local g:tGameHandle=New tGameHandle
		g.numShapes=_numshapes
		g.LoadSolutions()
		g.repositionShapes()
		g.selectedShape=0
		SetClsColor( 50,130,50 )
		Return G
	EndFunction
	
	Method loadSolutions()
		Local pX%,pY%		
		ReadData( numSolutions )
		solData1=New Int[numSolutions]
		solData2=New Int[numSolutions]
		For Local i%=0 Until numSolutions
			ReadData(pX)
			ReadData(pY)
			solData1[i]=pX
			solData2[i]=pY
		Next
	EndMethod
	
	Method repositionShapes()
		For Local i:Int=0 Until numShapes
			shapes[i].setPosition( i*100+200,300 )
		Next
	End Method
	
	Method draw()
		For Local i:Int=0 Until numShapes
			If i=selectedShape
				shapes[i].changeCol( 50,50,200 )
			Else
				shapes[i].changeCol( 255,255,255 )
			EndIf
			shapes[i].draw
		Next
		drawGUI()
	EndMethod
	
	Method drawGUI()
		setGfx( 0,0,0,2 )
		DrawRect( 0,0,GraphicsWidth(),100 )
		setGfx( 255,255,255,2 )
		DrawText( "Rotate (rmb) and move (lmb) to pieces so they form the letter:",50,10 )
		setGfx( 255,50,50,2 )
		DrawRect( 550,10,18,25 )
		setGfx( 255,255,255,2 );SetScale( 2.0,2.0 )
		DrawText( "T",550,10 );SetScale( 1.0,1.0 )
		DrawText( "Press keys [1-4] or [TAB] to select pieces",50,70 )
		restoreGfx()
	End Method
	
	Method checkIfFinsished:Byte()
		For Local i:Int=0 Until numSolutions
'			If(solData1[i]],solData2[i]) > SOL_DIST )
				Return False
'			EndIf
		Next
		Return True
	EndMethod
			
	Method mainLoop()
		handleInput()
		draw()
		If( checkIfFinsished()=True )
			completed()
		EndIf
	EndMethod
	
	Method completed()
		Local count:Int
		selectedShape=-1
		While( count < 10 )
			Delay( 80 )
			If( (count Mod 2)=0 )
				SetClsColor( 200,50,50 )
			Else
				SetClsColor( 50,200,50 )
			EndIf
			Cls
			draw()
			Flip
			count:+1
		Wend
		count=0
		setGfx( 0,0,0,2 )
		SetClsColor( 200,50,50 )
		While( count < 10 )
			Delay( 80 )
			If( (count Mod 2)=0 )
				SetClsColor( 200,50,50 )
			Else
				SetClsColor( 50,200,50 )
			EndIf
			Cls()
			draw()
			DrawRect( GraphicsWidth()/2-(count*40)/2,GraphicsHeight()/2-(count*30)/2,count*40,count*30 )
			Flip
			count:+1
		Wend
		draw()
		DrawRect( GraphicsWidth()/2-(count*40)/2,GraphicsHeight()/2-(count*30)/2,count*40,count*30 )
		setGfx( 200,200,200,2 )
		SetScale( 2.0,2.0 )
		DrawText( "Congratualations!",GraphicsWidth()/2-(count*40)/2+30,GraphicsHeight()/2-(count*30)/2+30 )
		SetScale( 2.8,4.0 )
		DrawText( "Puzzle completed!",GraphicsWidth()/2-(count*40)/2+10,GraphicsHeight()/2-(count*30)/2+100 )
		Flip
		restoreGfx()
		WaitKey()
		End
	EndMethod
	
	Method handleInput()
		If KeyDown(key_up) shapes[selectedShape].move(0,-3)
		If KeyDown(key_down) shapes[selectedShape].move(0,3)
		If KeyDown(key_left) shapes[selectedShape].move(-3,0)
		If KeyDown(key_right) shapes[selectedShape].move(3,0)
		
		If KeyHit(KEY_1) selectedShape=0
		If KeyHit(KEY_2) selectedShape=1
		If KeyHit(KEY_3) selectedShape=2
		If KeyHit(KEY_4) selectedShape=3
		If KeyHit(KEY_5) selectedShape=4
		If KeyHit(KEY_6) selectedShape=5
		If KeyHit(KEY_7) selectedShape=6
		
		If KeyDown(KEY_R) shapes[selectedShape].rotate(3)
		
		If KeyHit(KEY_TAB)
			selectedShape:+1
			If selectedShape>3 selectedShape=0
		EndIf
		
		If( MouseDown(MOUSE_LEFT) )
			If tmpX=-1 tmpX=MouseX()
			If tmpY=-1 tmpY=MouseY()
			shapes[selectedShape].move( MouseX()-tmpX,MouseY()-tmpY )
			tmpX=MouseX()
			tmpY=MouseY()	
		ElseIf( MouseDown(MOUSE_RIGHT) )	
			If tmpX=-1 tmpX=MouseX()
			If tmpY=-1 tmpY=MouseY()
			shapes[selectedShape].rotate( MouseX()-tmpX+MouseY()-tmpY )
			tmpX=MouseX()
			tmpY=MouseY()
		Else
			tmpX=-1
			tmpY=-1
		EndIf	
	EndMethod
	
	Function setGfx( _r:Int,_g:Int,_b:Int,_lw:Int )
		restoreGfx()
		GetColor( oldGfx[0],oldGfx[1],oldGfx[2] )
		SetColor( _r,_g,_b )
		SetLineWidth( _lw )
	EndFunction
	
	Function restoreGfx()
		SetColor ( tGameHandle.oldGfx[0],tGameHandle.oldGfx[1],tGameHandle.oldGfx[2] )
		SetLineWidth( oldGfx[3] )
	EndFunction
End Type

'---------------------------------------------
' Shape type
' -Holds all data for every shape
'---------------------------------------------
Type tShape
	Field posX:Int,posY:Int
	Field PolyData#[]
	Field colorR:Int=255,colorG:Int=255,colorB:Int=255
	Field drawPoints:Byte=False
	Field lineW:Int=3
	
	Function Create:tShape(pdata#[])
		Local s:tShape=New tShape
		s.PolyData=pdata
		Return s
	EndFunction
	
	Function createSquare:tShape(_w#=100.0,_h#=100.0)
		Local s:tShape=tShape.Create([0.0,0.0,_w,0.0,_w,_h,0.0,_h])
		Return s
	EndFunction
	
	Method move( _dx:Int,_dy:Int )
		posX:+_dx
		posY:+_dy
	EndMethod
	
	Method setPosition(nx#,ny# )
		posX=nx ; posY=ny
	EndMethod
	
	Method rotate( _angle:Int )
		Local xnew:Float,ynew:Float
		Local p%=0
		Repeat
			xnew=PolyData[p]*Cos(_angle)-PolyData[p+1]*Sin(_angle)
			ynew=PolyData[p]*Sin(_angle)+PolyData[p+1]*Cos(_angle)
			PolyData[p]=xnew
			PolyData[p+1]=ynew
			p:+2
		Until p>=PolyData.Length
	EndMethod
		
	Method draw()
		tGameHandle.setGfx( colorR,colorG,colorB,lineW )
		SetOrigin posX,posY
		If InsidePoly(MouseX()-posX,MouseY()-posY,polydata)
			changeCol $ff,$00,$00
		EndIf
		DrawPoly polydata
		SetOrigin 0,0
		tGameHandle.restoreGfx()
	EndMethod
	
	Method changeCol(_r:Int,_g:Int,_b:Int,_lw:Int=2)
		colorR=_r
		colorG=_g
		colorB=_b
		lineW=_lw
	EndMethod
End Type


Function calcDist:Int(s0:tShape,s1:tShape)
	Local dx:Int,dy:Int
	dx=Abs(s0.posX+s1.posX)
	dy=Abs(s0.posY+s1.posY)
	Return( Int( Sqr( dx*dx+dy*dy ) ) )
End Function

Function dot%(x0%,y0%,x1%,y1%,x2%,y2%)
	Return (x1-x0)*(y2-y1)-(x2-x1)*(y1-y0)
End Function

Function InsidePoly%(px%,py%,p#[])
	Local i%=0
	' compare x/y coords with next x/y coords in array
	Repeat
		If dot(p[i+0],p[i+1],p[i+2],p[i+3],px,py)<=0 Return False
		i:+2
	Until i=p.Length-2
	i=p.Length-2
	' compare last x/y coord pair with first
	If dot(p[i+0],p[i+1],p[0],p[1],px,py)>0 Return True
	Return False
End Function


'--------------
' SOLUTION DATA
'--------------
'    NumSolutions,   point1 id, point2 id ...
DefData 5,              3,12 , 8,11 , 10,0 , 14,7 , 4,15