Click detection on rotating circle
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
Click detection on rotating circle
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?
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?
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
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.
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.
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
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.there is no way to access the transformed matrix since transformation is done on-the-fly while displaying
Maybe there is another, better way to acomplish this?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
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.
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.
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
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:
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?
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
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.
( 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.
Try inserting this
after
Code: Select all
If clickedangle<0
clickedangle+360
EndIf
Code: Select all
MouseAngle.f = Angle(CenterX,CenterY,MouseX(),MouseY())
ClickedAngle = MouseAngle - Angle
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
Now that bitch is working like it should!
Thanks Kaeru, thanks Bender!
Thanks Kaeru, thanks Bender!
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
- Kaeru Gaman
- Addict
- Posts: 4826
- Joined: Sun Mar 19, 2006 1:57 pm
- Location: Germany
Re: Click detection on rotating circle
Since I stumpled over this old thread, I ported it to newer PB versions:
Bugfix from Derek is included
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