Click detection on rotating circle

Advanced game related topics
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Click detection on rotating circle

Post by Fluid Byte »

I'm just woundering how you would get the RGB value for a certain position from a Sprite3D. It's easy for images since you can use Start-/StopDrawing() and using ImageOutput() with the image you want the color value from. It's all in memory, nothing's painted on screen and then you simply use Point().

But how this works for sprites and 3D sprites in particular?
Last edited by Fluid Byte on Fri Aug 01, 2008 9:11 pm, edited 1 time in total.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

for sprites you can also use Draw with SpriteOutput.
or direct access with pointers wich is also an alternative for Images.

for sprite3D you have to access the texture-sprite (the 2D sprite you made the sprite3D from),
there is no way to access the transformed matrix since transformation is done on-the-fly while displaying.
oh... and have a nice day.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

there is no way to access the transformed matrix since transformation is done on-the-fly while displaying
To put this straight, you don't only mean Rotate-/Zoom/-TransformSprite() but any form of accessing a Sprite3D for color information? That would be pretty bad because thats what I want to do. I am making a "Wheel Of Fortune" for my game using Sprite3D. I rotate the sprite and when the user clicks on it I determine wich part of the wheel has been clicked by checking a color mask of the same size.

Maybe there is another, better way to acomplish this?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
djes
Addict
Addict
Posts: 1806
Joined: Sat Feb 19, 2005 2:46 pm
Location: Pas-de-Calais, France

Post by djes »

After the sprite's being "painted" on the screen you can test the pixel under the mouse with point and StartDrawing(ScreenOutput())
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

you have the rotation angle of the sprite,
the click-coordinate, and the centre-coordinate of the sprite.

the two coordinates are connected with a line that has a certain angle on the screen.
this angle minus the rotation angle of the sprite is the relative angle of the click on the base-sprite.

now you can set up a table of base angles wich field is wich on your wheel.


using color-maps for click location is a good idea for such things like clicking counties on a topographic map.
for easy mathematic problems like rotation angles it's overkill. ;)
oh... and have a nice day.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

What can I say? I suck at math. I took you sugegstions and it's almost working. The Problem is when you substract the wheel angle from the mouse angle. Sometimes the angle gets negative and sometimes the result is simply wrong.

Here's what I have put together so far:

Code: Select all

InitSprite() : InitKeyboard() : InitSprite3D() : InitMouse()

CenterX = 320 : CenterY = 240 : Angle.f = 0 : Radius = 100

LoadFont(0,"Courier New",9,#PB_Font_Bold)

OpenWindow(0,0,0,640,480,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

lpBuffer = AllocateMemory(630)
UnpackMemory(?Cursor,lpBuffer)
CatchSprite(0,lpBuffer)
TransparentSpriteColor(0,RGB(0,128,128))
FreeMemory(lpBuffer) 

Procedure.f Angle(X1.f,Y1.f,X2.f,Y2.f)
	Protected A.f, B.f, C.f, Angle.f
	
	A = X2 - X1
	B = Y2 - Y1
	C = Sqr(A * A + B * B)
	
	Angle = ACos(A/C) * 57.29577

	If Y1 < Y2 : Angle = 360 - Angle : EndIf
	
	ProcedureReturn Angle
EndProcedure

Repeat
	EventID = WindowEvent()
		
	ClearScreen($202020)
	
	ExamineKeyboard() : ExamineMouse()
	
	If Angle = 360 : Angle = 0 : EndIf
	
	StartDrawing(ScreenOutput())	
	DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
	DrawingFont(FontID(0))
	
	For i=0 To 90 Step 4
		LX = CenterX + (Cos((-i - Angle) / 180 * #PI) * Radius)
		LY = CenterY + (Sin((-i - Angle) / 180 * #PI) * Radius)	
		LineXY(CenterX,CenterY,LX,LY,#Red)
		
		LX = CenterX + (Cos((-i - Angle - 90) / 180 * #PI) * Radius)
		LY = CenterY + (Sin((-i - Angle - 90) / 180 * #PI) * Radius)	
		LineXY(CenterX,CenterY,LX,LY,#Green)		
		
		LX = CenterX + (Cos((-i - Angle - 180) / 180 * #PI) * Radius)
		LY = CenterY + (Sin((-i - Angle - 180) / 180 * #PI) * Radius)	
		LineXY(CenterX,CenterY,LX,LY,#Blue)
		
		LX = CenterX + (Cos((-i - Angle - 270) / 180 * #PI) * Radius)
		LY = CenterY + (Sin((-i - Angle - 270) / 180 * #PI) * Radius)	
		LineXY(CenterX,CenterY,LX,LY,#Yellow)
	Next
			
	Ellipse(CenterX,CenterY,Radius,Radius,#Green)
	
	FrontColor(#White)
	For i=0 To 359 Step 90
		TX = CenterX + (Cos((-i - Angle) / 180 * #PI) * (Radius + 20))
		TY = CenterY + (Sin((-i - Angle) / 180 * #PI) * (Radius + 20))
		DrawText(TX-15,TY-5,RSet(Str(i),3) + "°")
	Next
		
	LineXY(CenterX,CenterY,MouseX(),MouseY())
	
	MouseAngle.f = Angle(CenterX,CenterY,MouseX(),MouseY())
	ClickedAngle = MouseAngle - Angle
	
	DrawText(70,80,"Circle X / Y = " + Str(CenterX) + "," + Str(CenterY))
	DrawText(70,100,"Circle Angle = " + Str(Angle) + "°")	
	DrawText(70,120,"Mouse X / Y = " + Str(MouseX()) + "," + Str(MouseY()))
	DrawText(70,140,"Mouse Angle = " + Str(Mouseangle) + "°")
	DrawText(70,160,"Clicked Angle = " + Str((ClickedAngle)) + "°")
	
	DrawText(450,80,"   0-90° = Red")
	DrawText(450,100," 90-180° = Green")
	DrawText(450,120,"180-270° = Blue")
	DrawText(450,140,"270-360° = Yellow")
	
	DrawingMode(0)
	Box(420,80,20,14,#Red)
	Box(420,100,20,14,#Green)
	Box(420,120,20,14,#Blue)
	Box(420,140,20,14,#Yellow)
	
	DrawingMode(#PB_2DDrawing_Outlined)
	Select ClickedAngle
		Case 0 To 90 : BRDY = 80
		Case 90 To 180 : BRDY = 100
		Case 180 To 270 : BRDY = 120
		Case 270 To 359 : BRDY = 140
	EndSelect	
	Box(420,BRDY,20,14,#Black) : Box(419,BRDY-1,22,16,#White)
	StopDrawing()
	
	Angle + 0.25
	
	DisplayTransparentSprite(0,MouseX(),MouseY())
	
	FlipBuffers()
Until KeyboardPushed(1) Or EventID = #WM_CLOSE

DataSection
   Cursor:
   Data.l $0276434A,$4A720000,$A9B7AACC,$146320D0,$284A6811,$01232023,$9188409D,$F3000461,$20492601,$0A0401E0
   Data.l $E00081C0,$FFC0E015,$09302024,$409C3C04,$66013801,$FE4D02B6,$91FB77FB,$B7C236B7,$BDF63086,$BFEC1EC1
   Data.l $C0F36107,$0F625EF7,$008A083D,$87FFF581,$C4592A11,$4287C926,$3EC90540,$69F6974F,$21E5E328,$DDDE6107
   Data.l $50B353C6,$0FB86C06,$0000D893
   Data.b $90,$48
EndDataSection
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

for the subtraction, try

( alpha - beta + 360 ) % 360

the +360 makes sure it is positive, the mod reduces it to one full circle.

the other point is to make sure you work with the same angle projection for both starting angles.
the zero degrees have to be in the same direction, you can mix up this easily using a bunch full of sine and cosine.
this is a bit more math.... I know...
nothing I'm keen on that on a hot midsummer friday night, sorries.
oh... and have a nice day.
Derek
Addict
Addict
Posts: 2356
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

Try inserting this

Code: Select all

If clickedangle<0
clickedangle+360
EndIf 
after

Code: Select all

MouseAngle.f = Angle(CenterX,CenterY,MouseX(),MouseY()) 
ClickedAngle = MouseAngle - Angle 
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

Oy, those are floats.... then MOD will not work.
oh... and have a nice day.
User avatar
Fluid Byte
Addict
Addict
Posts: 2336
Joined: Fri Jul 21, 2006 4:41 am
Location: Berlin, Germany

Post by Fluid Byte »

Now that bitch is working like it should!

Thanks Kaeru, thanks Bender! Image
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
Derek
Addict
Addict
Posts: 2356
Joined: Wed Apr 07, 2004 12:51 am
Location: England

Post by Derek »

No probs 8)
User avatar
Kaeru Gaman
Addict
Addict
Posts: 4826
Joined: Sun Mar 19, 2006 1:57 pm
Location: Germany

Post by Kaeru Gaman »

yer welcome 8)
oh... and have a nice day.
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Click detection on rotating circle

Post by infratec »

Since I stumpled over this old thread, I ported it to newer PB versions:

Code: Select all

InitSprite() : InitKeyboard() : InitMouse()

CenterX = 320 : CenterY = 240 : Angle.f = 0 : Radius = 100

LoadFont(0,"Courier New",9,#PB_Font_Bold)

OpenWindow(0,0,0,640,480,"void",#PB_Window_SystemMenu | #PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),0,0,640,480,0,0,0)

UseJCALG1Packer()

lpBuffer = AllocateMemory(630)
UncompressMemory(?Cursor, ?CursorEnd - ?Cursor, lpBuffer, MemorySize(lpBuffer), #PB_PackerPlugin_JCALG1)
CatchSprite(0, lpBuffer)
TransparentSpriteColor(0,RGB(0,128,128))
FreeMemory(lpBuffer)

Procedure.f Angle(X1.f,Y1.f,X2.f,Y2.f)
  Protected A.f, B.f, C.f, Angle.f
  
  A = X2 - X1
  B = Y2 - Y1
  C = Sqr(A * A + B * B)
  
  Angle = ACos(A/C) * 57.29577
  
  If Y1 < Y2 : Angle = 360 - Angle : EndIf
  
  ProcedureReturn Angle
EndProcedure

Repeat
  EventID = WindowEvent()
  
  ClearScreen($202020)
  
  ExamineKeyboard() : ExamineMouse()
  
  If Angle = 360 : Angle = 0 : EndIf
  
  StartDrawing(ScreenOutput())   
  DrawingMode(#PB_2DDrawing_Outlined | #PB_2DDrawing_Transparent)
  DrawingFont(FontID(0))
  
  For i=0 To 90 Step 4
    LX = CenterX + (Cos((-i - Angle) / 180 * #PI) * Radius)
    LY = CenterY + (Sin((-i - Angle) / 180 * #PI) * Radius)   
    LineXY(CenterX,CenterY,LX,LY,#Red)
    
    LX = CenterX + (Cos((-i - Angle - 90) / 180 * #PI) * Radius)
    LY = CenterY + (Sin((-i - Angle - 90) / 180 * #PI) * Radius)   
    LineXY(CenterX,CenterY,LX,LY,#Green)      
    
    LX = CenterX + (Cos((-i - Angle - 180) / 180 * #PI) * Radius)
    LY = CenterY + (Sin((-i - Angle - 180) / 180 * #PI) * Radius)   
    LineXY(CenterX,CenterY,LX,LY,#Blue)
    
    LX = CenterX + (Cos((-i - Angle - 270) / 180 * #PI) * Radius)
    LY = CenterY + (Sin((-i - Angle - 270) / 180 * #PI) * Radius)   
    LineXY(CenterX,CenterY,LX,LY,#Yellow)
  Next
  
  Ellipse(CenterX,CenterY,Radius,Radius,#Green)
  
  FrontColor(#White)
  For i=0 To 359 Step 90
    TX = CenterX + (Cos((-i - Angle) / 180 * #PI) * (Radius + 20))
    TY = CenterY + (Sin((-i - Angle) / 180 * #PI) * (Radius + 20))
    DrawText(TX-15,TY-5,RSet(Str(i),3) + "°")
  Next
  
  LineXY(CenterX,CenterY,MouseX(),MouseY())
  
  MouseAngle.f = Angle(CenterX,CenterY,MouseX(),MouseY())
  ClickedAngle = MouseAngle - Angle
  If clickedangle < 0
    clickedangle + 360
  EndIf 
  
  DrawText(70,80,"Circle X / Y = " + Str(CenterX) + "," + Str(CenterY))
  DrawText(70,100,"Circle Angle = " + Str(Angle) + "°")   
  DrawText(70,120,"Mouse X / Y = " + Str(MouseX()) + "," + Str(MouseY()))
  DrawText(70,140,"Mouse Angle = " + Str(Mouseangle) + "°")
  DrawText(70,160,"Clicked Angle = " + Str((ClickedAngle)) + "°")
  
  DrawText(450,80,"   0-90° = Red")
  DrawText(450,100," 90-180° = Green")
  DrawText(450,120,"180-270° = Blue")
  DrawText(450,140,"270-360° = Yellow")
  
  DrawingMode(0)
  Box(420,80,20,14,#Red)
  Box(420,100,20,14,#Green)
  Box(420,120,20,14,#Blue)
  Box(420,140,20,14,#Yellow)
  
  DrawingMode(#PB_2DDrawing_Outlined)
  Select ClickedAngle
    Case 0 To 90 : BRDY = 80
    Case 90 To 180 : BRDY = 100
    Case 180 To 270 : BRDY = 120
    Case 270 To 359 : BRDY = 140
  EndSelect   
  Box(420,BRDY,20,14,#Black) : Box(419,BRDY-1,22,16,#White)
  StopDrawing()
  
  Angle + 0.25
  
  DisplayTransparentSprite(0,MouseX(),MouseY())
  
  FlipBuffers()
Until KeyboardPushed(1) Or EventID = #WM_CLOSE

DataSection
  Cursor:
  Data.l $0276434A,$4A720000,$A9B7AACC,$146320D0,$284A6811,$01232023,$9188409D,$F3000461,$20492601,$0A0401E0
  Data.l $E00081C0,$FFC0E015,$09302024,$409C3C04,$66013801,$FE4D02B6,$91FB77FB,$B7C236B7,$BDF63086,$BFEC1EC1
  Data.l $C0F36107,$0F625EF7,$008A083D,$87FFF581,$C4592A11,$4287C926,$3EC90540,$69F6974F,$21E5E328,$DDDE6107
  Data.l $50B353C6,$0FB86C06,$0000D893
  Data.b $90,$48
  CursorEnd:
EndDataSection
Bugfix from Derek is included :wink:
Post Reply