I got the PointInPoly() function working now so you can directly select a shape with the mouse. Same for rotation. Just hover over a shape then RIGHT-CLICK to rotate and LEFT-CLICK to move. The shape becomes the active one under both situations
Conrad,
I had to change the 2nd shape so that it draws in a clockwise manor. The PointInPoly() function only works on polygons constructed in a clockwise fashion
Can you therefore update the puzzle completion checking routine since this is will be currently broken?
SuperStrict
Framework BRL.GLMax2D
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,-005.0 , 35.0, 25.0 , -35.0, 25.0 , -35.0,-75.0 ])
shapes[2]=tShape.Create([-15.0, 050.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=8 ' 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 [shape p1]
Field solData3:Int[] ' solution data [p2]
Field solData4:Int[] ' solution data [shape 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%,s1%,s2%
ReadData( numSolutions )
solData1=New Int[numSolutions]
solData2=New Int[numSolutions]
solData3=New Int[numSolutions]
solData4=New Int[numSolutions]
For Local i%=0 Until numSolutions
ReadData(pX)
ReadData(s1)
ReadData(pY)
ReadData(s2)
solData1[i]=pX
solData2[i]=s1
solData3[i]=pY
solData4[i]=s2
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
shapes[i].changeCol( 255-i*20,255-i*20,255-i*20 )
If i=selectedShape Then shapes[i].changeCol( 80,250,60 )
If PointInPoly(MouseX()-shapes[i].posX,MouseY()-shapes[i].posY,shapes[i].polydata)
shapes[i].changeCol ($ff,$40,$40)
If (MouseHit(1) Or MouseHit(2)) Then selectedShape=i
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()
Local i%,x1%,y1%,x2%,y2%,dx%,dy%
For i=0 Until numSolutions
x1=shapes[solData2[i]].PolyData[solData1[i]*2]+shapes[solData2[i]].posX
y1=shapes[solData2[i]].PolyData[solData1[i]*2+1]+shapes[solData2[i]].posY
x2=shapes[solData4[i]].PolyData[solData3[i]*2]+shapes[solData4[i]].posX
y2=shapes[solData4[i]].PolyData[solData3[i]*2+1]+shapes[solData4[i]].posY
dx=Abs(x1-x2);dy=Abs(y1-y2)
If ( Sqr(dx*dx+dy*dy) > 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
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 PointInPoly%(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, point1-shape-id, point2-id, point2-shape-id ...
DefData 5, 3,0,1,3, 0,2,0,3, 3,3,3,1, 0,0,2,2, 0,1,4,3