SpritePixelCollision bei 5.2 so schlecht !

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
funkheld
Beiträge: 649
Registriert: 31.12.2009 11:58

SpritePixelCollision bei 5.2 so schlecht !

Beitrag von funkheld »

Hallo, guten Tag.
Die Spritecolli ist grottenschlecht, oder mach ich einen Fehler ?
Ich habe ein Sprite 64x64(Raupenfahrzeig) und ein Sprite 500x500(Grundfläche mit Umrandung).
Bei beiden ist die Farbe 255,0,255 durchsichtig.

4-5 Pixel vor der Collision wird schon eine Colli angezeigt.
Wenn ich mit dem Fahrzeugkörper ausserhalb der Berührung bin und dann drehe und der Kettenantrieb kommt in die Berührungsfläche , wird erst nach 5-6 Punkten in der Fläche eine Colli angezeigt.

Was ist da falsch ?
Vielleicht kann ich einem Mal die Sprite schicken zum Testen?

Gruss

Code: Alles auswählen

Global x1.f,y1.f,dx.f,dy.f,winkel.f, r.l,delta.l,colli.l
 
 Enumeration
   #Window_0
   #sprite_0
   #sprite_1
 EndEnumeration

InitSprite()

OpenWindow(#Window_0, 0, 0, 800, 700, "Screen", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window_0), 150, 10, 600,600, 0, 0, 0)

LoadSprite(#sprite_0, "raupe.bmp", #PB_Sprite_PixelCollision)
LoadSprite(#sprite_1, "grundspr.bmp", #PB_Sprite_PixelCollision)
TransparentSpriteColor(#sprite_0, RGB(255,0,255))
TransparentSpriteColor(#sprite_1, RGB(255,0,255))

dx=100
dy=100
delta=2

Repeat
  Event = WaitWindowEvent(1)
  
  Select Event
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
    
    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect

  If GetAsyncKeyState_(#VK_RIGHT)
    winkel=winkel+2
  ElseIf GetAsyncKeyState_(#VK_LEFT)
    winkel=winkel-2
  EndIf
 
  If GetAsyncKeyState_(#VK_UP)
    y1=Sin(winkel/180*#PI)*delta
    x1=Cos(winkel/180*#PI)*delta
    dx+x1
    dy+y1   
  ElseIf GetAsyncKeyState_(#VK_DOWN)
    y1=Sin(winkel/180*#PI)*delta
    x1=Cos(winkel/180*#PI)*delta
    dx-x1
    dy-y1
  EndIf
  
  ClearScreen(RGB(255,255,0))
  DisplayTransparentSprite(#sprite_1,10,10)
  DisplayTransparentSprite(#sprite_0,dx,dy)
  RotateSprite(#sprite_0,winkel+90,#PB_Absolute)
  colli = SpritePixelCollision(#Sprite_0, dx,dy, #Sprite_1,10,10)
  
  FlipBuffers()
  Debug colli
   
ForEver
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von STARGÅTE »

Also zuerst mal, SpritePixelCollision() funktioniert nicht mit rotierten Sprites, denn davon steht auch nix in der Hilfe, da steht nur gezoomt.

Ansonsten kann ich keine Abweichung feststellen:

Code: Alles auswählen

InitSprite()


Enumeration
	#Window
EndEnumeration

OpenWindow(#Window, 0, 0, 800, 600, "ScreenTitle", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window), 0, 0, 0)

TransparentSpriteColor(#PB_Default, $000000)
CreateSprite(1, 256, 256, #PB_Sprite_PixelCollision)
CreateSprite(2, 64, 64, #PB_Sprite_PixelCollision)

If StartDrawing(SpriteOutput(1))
	Box(0, 0, 16, 256, $FFFFFF)
	Box(0, 0, 256, 16, $FFFFFF)
	StopDrawing()
EndIf

If StartDrawing(SpriteOutput(2))
	Box(24, 0, 16, 64, $FFFFFF)
	StopDrawing()
EndIf

Define X, Y

Repeat
	
	Repeat
		
		Select WindowEvent()
			Case #PB_Event_CloseWindow
				End
			Case #Null
				Break
		EndSelect
		
	ForEver
	
	ClearScreen(0)
	
	DisplayTransparentSprite(1, 100, 100)
	DisplayTransparentSprite(2, WindowMouseX(#Window)-32, WindowMouseY(#Window)-32)
	
	SetWindowTitle(#Window, Str(SpritePixelCollision(1, 100, 100, 2, WindowMouseX(#Window)-32, WindowMouseY(#Window)-32)))
	
	FlipBuffers()
	
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
funkheld
Beiträge: 649
Registriert: 31.12.2009 11:58

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von funkheld »

Jup, danke.
Da ist ja öde....

Wie kann man das realisieren ?
Evtl mit Catchsprite das gedrehte Sprite irgendwie wieder in das Originalsprite setzen, aber wie ?

Gruss
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von STARGÅTE »

funkheld hat geschrieben:Evtl mit Catchsprite das gedrehte Sprite irgendwie wieder in das Originalsprite setzen, aber wie ?
Nene, viel zu langsam, um es in Echtzeit auszuführen.

Je nach Form des Objekts würde ich dann lieber n Kollisionsabfrage zwischen: Kugel/Box/Dreieck/Polygon und der Wand machen.
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von KeyKon »

Ich hab das mal vor Ewigkeiten recht einfach gemacht, indem ich zu jedem Sprite (das waren in meinem Fall wohlgemerkt nur einige wenige) einfach 180 Rotations-Stufen generiert habe (beim Laden).
Dadurch konnte ich immer mit dem entsprechenden Sprites die Kollision so genau wie es für mich nötig war nachprüfen (wenn mans genauer will muss man halt mehr Rotations-Stufen anlegen^^).
Ich denke in zweiten von Rechnern mit 4GB+ RAM kann man sich sowas leisten^^

Wenn möglich ist natürlich STARGATEs Methode vorzuziehen!

LG KeyKon
(\/) (°,,,°) (\/)
funkheld
Beiträge: 649
Registriert: 31.12.2009 11:58

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von funkheld »

Jup, danke.
Wollte ich auch erst machen.

Jetzt habe ich eine Lösung mit "Grabsprite" und "Copysprite" gefunden.
Das Sprite habe ich ausserhalb des sichtbaren Bereichs gelegt mit Displaysprite und habe es dann da auch mit Grabsprite abgeholt.

--------------------------
OpenWindow(#Window_0, 0, 0, 900, 650, "Screen", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window_0), 120, 10, 1000,600, 0, 0, 0)
---------------------------
OpenWindowedScreen geht nach rechts raus und ist grösser in der Breite als das Openwindow und da ausserhalb sehe ich das Sprite nicht auf meinem Spielwindow. Die Geschwindigkeit wird durch diese 3 Spritegeschichten hintereinander nicht wesentlich beeinflusst, weil die Kopiergeschichten echt superschnell sind.

Code: Alles auswählen

DisplaySprite(#sprite_auto_load,910,10)
GrabSprite(#sprite_grab,900,0,84,84,#PB_Sprite_PixelCollision) 
CopySprite(#Sprite_grab, #Sprite_auto,#PB_Sprite_PixelCollision) 
Gruss
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von NicTheQuick »

Interessante Idee. Denk dran, dass ein gedrehtes Sprite später insgesamt breiter und höher ist als zuvor, wenn du es wieder komplett grabben willst.
funkheld
Beiträge: 649
Registriert: 31.12.2009 11:58

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von funkheld »

Die Grundfläche ist grösser als das Spielsprite damit beim drehen die Ecken mit berücksicht werden.

Gruss
funkheld
Beiträge: 649
Registriert: 31.12.2009 11:58

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von funkheld »

So jetzt habe ich das Roboterauto fertig mit 2 Tastern vorn , die eine Kollision aufnehmen.
Habe als Grundkörper ein Sprite und die 2 Tasten vorn sind auch je ein Sprite. Alle 3 Sprite haben die gleiche Grundgrösse damit beim Drehen keine Verschiebungen zu sehen sind. Das Auto dreht sich um einpaar Grad , je nachdem welcher Taster eine Kollision hat.
Es funktioniert einwandfrei. Das Auto weicht allen Hindernissen aus.

Gruss

Code: Alles auswählen

 Global x1.f,y1.f,dx.f,dy.f,winkel.f, r.l,delta.l,collir.l,collil.l,neuspr.l,sprite_hgrund.l
 
 Enumeration
   #Window_0
   #sprite_auto_load
   #sprite_auto_loadr
   #sprite_auto_loadl
   #sprite_zaun
   #sprite_grab
   #sprite_auto
   #sprite_autor
   #sprite_autol
   #button_0
   #button_1
   #button_2
 EndEnumeration

InitSprite()

OpenWindow(#Window_0, 0, 0, 900, 650, "Screen", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window_0), 120, 10, 1000,600, 0, 0, 0)

ButtonGadget(#button_0, 10,10, 80, 25, "")
ButtonGadget(#button_1, 10,35, 80, 25, "")
ButtonGadget(#button_2, 10,60, 80, 25, "")

LoadSprite(#sprite_auto_load, "d:/data/auto.bmp", #PB_Sprite_PixelCollision)
LoadSprite(#sprite_auto_loadr, "d:/data/autor.bmp", #PB_Sprite_PixelCollision)
LoadSprite(#sprite_auto_loadl, "d:/data/autol.bmp", #PB_Sprite_PixelCollision)

LoadSprite(#sprite_zaun, "d:/data/grundsprs5.bmp", #PB_Sprite_PixelCollision)
sprite_hgrund=CreateSprite(#PB_Any,90,90,#PB_Sprite_PixelCollision)

StartDrawing(SpriteOutput(sprite_hgrund))
  Box(0,0,90,90,RGB(0,0,0))
StopDrawing()

dx=220
dy=100
delta=1

Repeat
  Event = WaitWindowEvent(1)
  
  Select Event
    Case #PB_Event_Gadget
      EventGadget = EventGadget()
      
      If EventGadget = #Button_0
             
      EndIf
      If EventGadget = #Button_1
             
      EndIf
      If EventGadget = #Button_2
             
      EndIf
    
    Case #PB_Event_CloseWindow
      EventWindow = EventWindow()
      If EventWindow = #Window_0
        CloseWindow(#Window_0)
        Break
      EndIf
  EndSelect

  If GetAsyncKeyState_(#VK_RIGHT)
    winkel=winkel+2
  ElseIf GetAsyncKeyState_(#VK_LEFT)
    winkel=winkel-2
  EndIf
 
  
    y1=Sin(winkel/180*#PI)*delta
    x1=Cos(winkel/180*#PI)*delta
    dx+x1
    dy+y1   
  
  
  ClearScreen(RGB(255,255,0))
  DisplayTransparentSprite(#sprite_zaun,150,10)
  
  DisplaySprite(sprite_hgrund,900,0) 
  DisplaySprite(#sprite_auto_load,910,10)
  GrabSprite(#sprite_grab,900,0,84,84,#PB_Sprite_PixelCollision) 
  CopySprite(#Sprite_grab, #Sprite_auto,#PB_Sprite_PixelCollision) 
  
  DisplaySprite(#sprite_auto_loadr,910,10)
  GrabSprite(#sprite_grab,900,0,84,84,#PB_Sprite_PixelCollision) 
  CopySprite(#Sprite_grab, #Sprite_autor,#PB_Sprite_PixelCollision) 
  
  DisplaySprite(#sprite_auto_loadl,910,10)
  GrabSprite(#sprite_grab,900,0,84,84,#PB_Sprite_PixelCollision) 
  CopySprite(#Sprite_grab, #Sprite_autol,#PB_Sprite_PixelCollision) 
  
  
  RotateSprite(#sprite_auto_load,winkel+90,#PB_Absolute)
  RotateSprite(#sprite_auto_loadr,winkel+90,#PB_Absolute)
  RotateSprite(#sprite_auto_loadl,winkel+90,#PB_Absolute)
  

  DisplayTransparentSprite(#sprite_auto,dx,dy)
  DisplayTransparentSprite(#sprite_autor,dx,dy)
  DisplayTransparentSprite(#sprite_autol,dx,dy)
  colli = SpritePixelCollision(#Sprite_auto, dx,dy, #Sprite_zaun,150,10)
  collir = SpritePixelCollision(#Sprite_autor, dx,dy, #Sprite_zaun,150,10)
  collil = SpritePixelCollision(#Sprite_autol, dx,dy, #Sprite_zaun,150,10)
  
  FlipBuffers()
  If collil
    winkel=winkel+3
  ElseIf collir
    winkel=winkel-3
  EndIf  
   
ForEver

Hier ein Bild:
Bild
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7031
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: SpritePixelCollision bei 5.2 so schlecht !

Beitrag von STARGÅTE »

Warum machst du denn noch ein CopySprite() ?
Du kannst doch gleich GrabSprite(#Sprite_autol) und GrabSprite(#Sprite_autor) machen.
funkheld hat geschrieben:Die Geschwindigkeit wird durch diese 3 Spritegeschichten hintereinander nicht wesentlich beeinflusst, weil die Kopiergeschichten echt superschnell sind.
Wenn du meinst ...
bei diesem Code habe ich ohne GrabSprite() 9500 FPS
mit einem GrabSprite() habe ich nur noch 300 FPS !! Also 32 mal langsammer.
Klar sind 300 FPS immer noch genug, aber wenn du mehr solche Sachen einbaust ...

Code: Alles auswählen

InitSprite()


Enumeration
   #Window
EndEnumeration

OpenWindow(#Window, 0, 0, 800, 600, "ScreenTitle", #PB_Window_SystemMenu|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(#Window), 0, 0, WindowWidth(#Window), WindowHeight(#Window), 0, 0, 0, #PB_Screen_NoSynchronization)

TransparentSpriteColor(#PB_Default, $000000)
CreateSprite(1, 256, 256, #PB_Sprite_PixelCollision)
CreateSprite(2, 64, 64, #PB_Sprite_PixelCollision)

If StartDrawing(SpriteOutput(1))
   Box(0, 0, 16, 256, $FFFFFF)
   Box(0, 0, 256, 16, $FFFFFF)
   StopDrawing()
EndIf

If StartDrawing(SpriteOutput(2))
   Box(24, 0, 16, 64, $FFFFFF)
   StopDrawing()
EndIf

Define X, Y, Time.i, Count.i

Repeat
   
   Repeat
      
      Select WindowEvent()
         Case #PB_Event_CloseWindow
            End
         Case #Null
            Break
      EndSelect
      
   ForEver
   
   ClearScreen(0)
   
   DisplayTransparentSprite(1, 100, 100)
   DisplayTransparentSprite(2, WindowMouseX(#Window)-32, WindowMouseY(#Window)-32)
   
   GrabSprite(3,0,0,100,100,#PB_Sprite_PixelCollision) 
   
   If ElapsedMilliseconds()-Time > 1000
     SetWindowTitle(#Window, Str(Count))
     Time = ElapsedMilliseconds()
     Count = 0
   EndIf
   
   FlipBuffers()
   Count + 1
   
ForEver
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Antworten