Seite 1 von 1

2D Shooter Maus-Fadenkreuz Winkel & Radius Problem

Verfasst: 29.12.2009 22:17
von TomS
Hallo.

Ich arbeite gerade an einem 2D Jump 'n' Run - Shooter, der von der Steuerung so wie die Flash Version von 'Portal' aufgebaut ist.
Also die typische Ego-Shooter Steuerung WASD + Maus nur eben in Super Mario 2D-Seitenansicht.

Im Gegensatz zu dem Portalspiel soll mein Fadenkreuz aber einen festen Abstand zum Spieler haben, damit das zielen nicht ganz so einfach wird^^

Ich habe jetzt versucht den Winkel zwischen Maus und Spielfigur zu errechnen (für die Krümelkacker hier ;) Den Winkel der Gerade durch Maus und Spieler gegen die X-Achse des Screens).
Allerdings kann ich die Maus dann immer noch unendlich weit weg bewegen, was erstens genaueres Zielen ermöglichen würde, was dem Sinn von dem Fadenkreuz mit konstantem Abstand ein wenig entgegen wirken würde.
Außerdem macht es ein schnelles Umdrehen der Spielfigur praktisch unmöglich, vor allem wenn man gar nicht weiß, wie weit die Maus eigentlich weg ist.

Ich hab schon versucht den Abstand zu berechnen (delta-Variable im Code) und dann mit MouseLocate() zu arbeiten, was aber zu keinem brauchbaren Ergebnis führte.

Bin für jeden Lösungsansatz dankbar.

Außerdem hab ich noch ein weiteres Problem.
Und zwar wird nur der untere Halbkreis abgedeckt. Das heißt wenn die Maus über 180° hinaus geht, verschwindet das Fadenkreuz und taucht bei 0° wieder auf.
Da habe ich sicher nur eine Kleinigkeit übersehen.

Hier mal der Code, der beide Probleme verdeutlicht.

Code: Alles auswählen

EnableExplicit 

If (Not InitSprite()) Or (Not InitMouse())
	End
EndIf

Enumeration 1
	#Sprite_Player
	#Sprite_Crosshair
	#Sprite_Mouse
EndEnumeration 

Define x0 = 300 	; Mittelpunkt (FensterDimensionen / 2)
Define y0 = 300
Define wEvent		; WindowEvent-Variable
Define x2,y2		; Mauskoordinaten zur Winkelberechnung
Define winkel.f	; Berechneter Winkel
Define radius = 100; Abstand des Fadenkreuzes
Define delta.f		; Abstand Mouse-Player


If OpenWindow(1,0,0,600,600,"Escape zum Beenden",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
	If OpenWindowedScreen(WindowID(1),0,0,600,600,0,0,0)
	
		CreateSprite(#Sprite_Player,10,10)
			StartDrawing(SpriteOutput(#Sprite_Player))
				Circle(5,5,5,$00FF00)
			StopDrawing()
			
		CreateSprite(#Sprite_Crosshair,9,9)
			StartDrawing(SpriteOutput(#Sprite_Crosshair))
				Line(4,0,0,9,$0000FF)
				Line(0,4,9,0,$0000FF)
			StopDrawing()	
		
		CreateSprite(#Sprite_Mouse,20,20)
			StartDrawing(SpriteOutput(#Sprite_Mouse))
				Line(1,1,20,7,$FFFFFF)
				Line(1,1,7,20,$FFFFFF)
				Line(1,1,20,20,$FFFFFF)
			StopDrawing()		

		Repeat ;- REPEAT 
			wEvent = WaitWindowEvent(20)
			ExamineMouse()
			ClearScreen($000000)

			x2 = MouseX()
			y2 = MouseY()
			
			;- Delta berechnen
			;delta = Sqr( Pow((x0-x2),2) + Pow((y0-y2),2) )
			winkel = ATan( (x2-x0) / (y2-y0) ) 

			DisplaySprite(#Sprite_Player, x0, y0)
			DisplaySprite(#Sprite_Crosshair, x0 + Sin(winkel) * (radius), y0 + Cos(winkel) * (radius) )
			DisplaySprite(#Sprite_Mouse, MouseX(), MouseY() )

			FlipBuffers()
			
		Until GetAsyncKeyState_(27) Or wEvent = #PB_Event_CloseWindow
			End 		
	EndIf 
EndIf 
MfG, Toms

Re: 2D Shooter Maus-Fadenkreuz Winkel & Radius Problem

Verfasst: 29.12.2009 23:12
von STARGÅTE
Tachchen, hier erst mal die richige Variante wie das mit der Maus geht ... sodass das Fadenkreuz immer im Richtigen Winkel angezeigt wird ...

Code: Alles auswählen

EnableExplicit 

If (Not InitSprite()) Or (Not InitMouse())
   End
EndIf

Enumeration 1
   #Sprite_Player
   #Sprite_Crosshair
   #Sprite_Mouse
EndEnumeration 

Define x0 = 300    ; Mittelpunkt (FensterDimensionen / 2)
Define y0 = 300
Define wEvent      ; WindowEvent-Variable
Define x2=300,y2=300      ; Mauskoordinaten zur Winkelberechnung
Define Angle.f   ; Berechneter Winkel
Define radius = 100; Abstand des Fadenkreuzes
Define delta.f      ; Abstand Mouse-Player


 ; Berechnet den Winkel
 Procedure.f Angle(x.f,y.f)
  Protected Angle.f
  Angle = ATan(y/x)
  If x < 0 : Angle + #PI : EndIf 
  If x = 0 And y = 0 : Angle = 0 : EndIf
  ProcedureReturn Angle
 EndProcedure
 
 
If OpenWindow(1,0,0,600,600,"Escape zum Beenden",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
   If OpenWindowedScreen(WindowID(1),0,0,600,600,0,0,0)
   
      CreateSprite(#Sprite_Player,10,10)
         StartDrawing(SpriteOutput(#Sprite_Player))
            Circle(5,5,5,$00FF00)
         StopDrawing()
         
      CreateSprite(#Sprite_Crosshair,9,9)
         StartDrawing(SpriteOutput(#Sprite_Crosshair))
            Line(4,0,1,9,$0000FF)
            Line(0,4,9,1,$0000FF)
         StopDrawing()   
      
      CreateSprite(#Sprite_Mouse,20,20)
         StartDrawing(SpriteOutput(#Sprite_Mouse))
            Line(1,1,20,7,$FFFFFF)
            Line(1,1,7,20,$FFFFFF)
            Line(1,1,20,20,$FFFFFF)
         StopDrawing()      

      Repeat ;- REPEAT 
         wEvent = WaitWindowEvent(20)
         ExamineMouse()
         ClearScreen($000000)

         x2 = MouseX()
         y2 = MouseY()
         
         
         Angle.f = Angle(x2-x0,y2-y0)
                  
         
         DisplaySprite(#Sprite_Player, x0, y0)
         DisplaySprite(#Sprite_Crosshair, x0 + Cos(Angle) * (radius), y0 + Sin(Angle) * (radius) )
         DisplaySprite(#Sprite_Mouse, x2, y2 )

         FlipBuffers()
         
      Until GetAsyncKeyState_(27) Or wEvent = #PB_Event_CloseWindow
         End       
   EndIf 
EndIf 
(bei dir hast du sin/cos vertauscht) und die Line oben beim Fadenkreuz hatte keine Breite/Höhe damit war sie unsichtbat (ist erst seit 4.4 so ...)

Nun zum eigentlich vorhaben...

In deinem Spiel willst du eigentlcih garnicht mehr die Maus anzeigen lassen, verstehe ich das richtig ?
Sonden nur das Fadenkreuz...
willst dabei aber dann NICHT diese technik nutzen wie sie jetzt ist, da mit dann "unendlich" weit weg gehen kann... mit der Maus das aber beim Fadenkreuz nciht sieht.

Gut, also muss du mit MouseDelta arbeiten:
Und die Position des Mauszeigers auf den eigentlichen Radius immer normieren.

Das sehe dann so aus : , hier wird die Maus auf dem Kreis gefangen gehalten, und jede Bewegung so angepasst das die der Kreisbahn entspricht.
Ist die Maus ganz rechts (0°) hat eine seitliche bewegzung der Maus keiner lei auswirkungen.
Nur wenn hoch oder runter bewegt wird, kann die Maus dem Kreis folgen:

einfach mal testen, vllt ist das ja das was du willst

Code: Alles auswählen

EnableExplicit 

If (Not InitSprite()) Or (Not InitMouse())
   End
EndIf

Enumeration 1
   #Sprite_Player
   #Sprite_Crosshair
   #Sprite_Mouse
EndEnumeration 

Define x0 = 300    ; Mittelpunkt (FensterDimensionen / 2)
Define y0 = 300
Define wEvent      ; WindowEvent-Variable
Define x2=400,y2=300      ; Mauskoordinaten zur Winkelberechnung
Define Angle.f   ; Berechneter Winkel
Define radius = 100; Abstand des Fadenkreuzes
Define delta.f      ; Abstand Mouse-Player


 ; Berechnet den Winkel
 Procedure.f Angle(x.f,y.f)
  Protected Angle.f
  Angle = ATan(y/x)
  If x < 0 : Angle + #PI : EndIf 
  If x = 0 And y = 0 : Angle = 0 : EndIf
  ProcedureReturn Angle
 EndProcedure
  
 ; Berechnet den Abstand zwischen zwei Punkte
 Macro Distance(x1, y1, x2, y2)
  Sqr( ((x1)-(x2))*((x1)-(x2)) + ((y1)-(y2))*((y1)-(y2)) )
 EndMacro

 
If OpenWindow(1,0,0,600,600,"Escape zum Beenden",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
   If OpenWindowedScreen(WindowID(1),0,0,600,600,0,0,0)
   
      CreateSprite(#Sprite_Player,10,10)
         StartDrawing(SpriteOutput(#Sprite_Player))
            Circle(5,5,5,$00FF00)
         StopDrawing()
         
      CreateSprite(#Sprite_Crosshair,9,9)
         StartDrawing(SpriteOutput(#Sprite_Crosshair))
            Line(4,0,1,9,$0000FF)
            Line(0,4,9,1,$0000FF)
         StopDrawing()   
      
      CreateSprite(#Sprite_Mouse,20,20)
         StartDrawing(SpriteOutput(#Sprite_Mouse))
            Line(1,1,20,7,$FFFFFF)
            Line(1,1,7,20,$FFFFFF)
            Line(1,1,20,20,$FFFFFF)
         StopDrawing()      

      Repeat ;- REPEAT 
         wEvent = WaitWindowEvent(20)
         ExamineMouse()
         ClearScreen($000000)

         x2 + MouseDeltaX()
         y2 + MouseDeltaY()
         delta = Distance(x2,y2, x0,y0)
         ; Normierung auf Radius
         x2 = (x2-x0)*radius/delta + x0
         y2 = (y2-y0)*radius/delta + y0
         
         
         Angle.f = Angle(x2-x0,y2-y0)
                  
         
         DisplaySprite(#Sprite_Player, x0, y0)
         DisplaySprite(#Sprite_Crosshair, x0 + Cos(Angle) * (radius), y0 + Sin(Angle) * (radius) )
         DisplaySprite(#Sprite_Mouse, x2, y2 )

         FlipBuffers()
         
      Until GetAsyncKeyState_(27) Or wEvent = #PB_Event_CloseWindow
         End       
   EndIf

Re: 2D Shooter Maus-Fadenkreuz Winkel & Radius Problem

Verfasst: 30.12.2009 00:47
von TomS
Vielen, vielen Dank. :allright:

Diese Vorlage is wirklich mehr als perfekt.
Jetzt hast du das halbe Spiel programmiert xD

:praise: :praise: :praise:

Re: 2D Shooter Maus-Fadenkreuz Winkel & Radius Problem

Verfasst: 30.12.2009 01:03
von marco2007
2D inkl. Winkelfunktionen + Stargate = Problem gelöst! :D