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?
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