Seite 1 von 4

SpritePixelCollision?

Verfasst: 21.12.2012 18:05
von TheNewOne
Hallo,
ich bin gerade dabei ein kleines Spiel zu programmieren, und bin auf folgendes Problem gestoßen:

Code: Alles auswählen

Global quit.i = 0
Global PlayerX = 500
Global PlayerY = 500
Global FG.i
Global MaxHeight.i = 200/20

Structure Koordinaten
  X.i
  Hoehe.i
EndStructure

Global NewList Blocks.Koordinaten()

For n = 0 To 1600 Step 20
  AddElement(Blocks())
  Blocks()\X = n
  Blocks()\Hoehe = Random(MaxHeight)*20+400
Next

Procedure Fehlerbehandlung(Ergebnis.i, Text.s)
  If Ergebnis = 0
    MessageRequester("Fehler", Text, #PB_MessageRequester_Ok)
    End
  EndIf  
EndProcedure

FehlerBehandlung(InitSprite(), "Initialisieren der Sprites fehlgeschlagen!")
FehlerBehandlung(InitKeyboard(), "Initialisieren der Tastatur fehlgeschlagen!")
FehlerBehandlung(OpenScreen(1600, 900, 32, "FullScreen"), "Öffen des Vollbilds fehlgeschlagen!")

Procedure keys()
  
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_Escape)
    quit = #True
  EndIf
  
  If KeyboardPushed(#PB_Key_D)
    PlayerX + 5
  ElseIf KeyboardPushed(#PB_Key_A)
    PlayerX - 5
  EndIf
  
  If KeyboardPushed(#PB_Key_W)
    FG = -5
  EndIf
    
EndProcedure

Procedure drawPlayer()
  
  PlayerY + FG
  If PlayerY > 800
    FG = 0
    PlayerY = 800
  Else
    FG + 1
  EndIf
  
  If PlayerX > 1580
    PlayerX = 1580
  ElseIf PlayerX < 0
    PlayerX = 0
  EndIf
  
  CreateSprite(1,20,20)
  StartDrawing(SpriteOutput(1))
  Box(0,0,20,20,RGB(0,150,0))
  StopDrawing()
  
  StartDrawing(ScreenOutput())
  Box(0,0, 1600, 900, RGB(225,0,0))
  StopDrawing()
  
  CreateSprite(0, 21, 21)
  StartDrawing(SpriteOutput(0))
  Circle(10, 10, 10, RGB(225,255,0))
  StopDrawing()
  
  ForEach Blocks()
    For n = Blocks()\Hoehe To 900 Step 20
      DisplaySprite(1,Blocks()\X, n) 
    Next
    If SpritePixelCollision(0, PlayerX, PlayerY, 1, Blocks()\X, Blocks()\Hoehe)
        FG = 0
      EndIf
  Next


  
  DisplayTransparentSprite(0, PlayerX, PlayerY)
  TransparentSpriteColor(0,0)
  
EndProcedure

Repeat
  ClearScreen(RGB(0,0,0))
  ExamineKeyboard()
  keys()
  drawPlayer()
  FlipBuffers()
Until quit = #True
Ich möchte dass der Spieler sich nicht durch die grünen Sprites durchbewegen kann, weis aber nicht wie ich das umsetzen soll.

Re: SpritePixelCollision?

Verfasst: 22.12.2012 17:24
von man-in-black
Willst du wirklich SpritePixelCollision nehmen? Das nimmt man eigentlich erst, wenn man mit Figuren komplexer Geometrie arbeitet.
Deine (bisherigen) Objekte sind aber einfache geometrische Figuren, die man besser mit kleinen Formeln erfasst. (Auch wenn dein Spieler später zB einen Menschen darstellen soll, würde sicherlich eine Box als Rechenkörper reichen)

In deinem speziellen Fall (wo jeder x-Wert nur eine Höhe hat), kannst du dir doch die Boxen aus deinem Array suchen, die im unmittelbaren Bereich von PositionSpielerX liegen. Dann muss dein PositionSpielerY einfach immer größer als die Blockhöhen sein.
Bei Bewegungen überprüfst du ERST, ob die Blockhöhe(n), die du betreten würdest, kleiner sind als dein PositionSpielerY,
BEVOR du den Schritt wirklich machst.

Hoffe, es war verständlich. Wenn nicht, meld dich nochmal :P

MFG,
MIB

Re: SpritePixelCollision?

Verfasst: 24.12.2012 13:15
von TheNewOne
Ich versteh wie du es meinst. Ich hab es probiert aber es funktioniert nicht. Was mach ich falsch?

Code: Alles auswählen

If KeyboardPushed(#PB_Key_D)
    ForEach Blocks()
      If PlayerX + 1 = Blocks()\X
        If Not PlayerY < Blocks()\Hoehe
          PlayerX + 5
        EndIf
      EndIf
    Next

Re: SpritePixelCollision?

Verfasst: 24.12.2012 14:15
von jojo1541
Wenn es dir darum geht, dass deine Sprites auch "Wände" haben, anstatt nur "Decken", dann musst du das ganze eben auch für die "Wände" berrechnen. Nicht nur für die Decken.
Oder du machst es, wie MiB vorgeschlagen hat unter Überprüfung der momentanen Höhe.

Re: SpritePixelCollision?

Verfasst: 24.12.2012 14:19
von TheNewOne
Ich hab es ja bereits versucht so zu machen wie MIB es vorgeschlagen hat:

Code: Alles auswählen

If KeyboardPushed(#PB_Key_D)
    ForEach Blocks()
      If PlayerX + 1 = Blocks()\X
        If Not PlayerY < Blocks()\Hoehe
          PlayerX + 5
        EndIf
      EndIf
    Next
Nur bewegt sich der "Spieler" jetzt nicht mehr wenn ich die Taste drücke.

Re: SpritePixelCollision?

Verfasst: 24.12.2012 15:21
von jojo1541
Das Problem bei deinem Code ist der Levelaufbau. Durch die LL kann man im nachhinein nur schwer auf diverse koordinaten zugreifen.
Ich würde dir ein Array empfehlen. Damit kannst du ganz bequem deine Leveldaten auslesen und dann für deine Figur die Kollision berrechnen.

Re: SpritePixelCollision?

Verfasst: 24.12.2012 15:41
von TheNewOne
Das Problem ist, dass ich den Array nicht versteh so wie der in der Hilfe beschrieben ist.

Re: SpritePixelCollision?

Verfasst: 24.12.2012 16:32
von jojo1541

Code: Alles auswählen

Structure Point2
  x.i
  y.i
  color.i
EndStructure


Dim TestArray.i(9) ; Wir erstellen ein Array mit 10 Stellen. 0 - 9

;Im Prinzip lässt sich ein Array genauso behandeln, wie eine Variable. 
;Man kann ihm Typen oder Strukturen zuweisen und die Werte beliebig ändern.
;Nur sind es eben viele "Felder", denen du Werte oder Strukturen zuweisen kannst..


Debug ArraySize(TestArray())
Debug "---"

For x = 0 To 9
  TestArray(x) = x
Next

Debug "Arraywert an Feld 5:"
Debug TestArray(5)
Debug "---"

FreeArray(TestArray())

;Das ganze geht auch in mehreren Dimensionen.

Dim TestArray2(9,9)

;Stell dir das Ganze wie ein Koordinatensystem vor. Du hast zwei Dimensionen, aus denen du nun Felder auswählen kannst.

TestArray2(3,2) = 5 ;Jetzt ist der Arraywert an der Stelle (3|2) 5. 

FreeArray(TestArray())

;So kannst du Sie auslesen und in sie schreiben. Mit strukturierten Arrays verhält es sich genauso.

Dim TestArray3.Point2(9,9)

;Jetzt hat jeder Punkt in diesem Array die Struktur Point. Du kannst also einfach via
TestArray3(3,3)\X = 1
TestArray3(3,3)\Y = 1

;in die Struktur schreiben. Genauso lässt sie sich auch wieder abrufen.

Debug TestArray3(3,3)\X

FreeArray(TestArray3())

;Viel mehr ist es nicht.
Das sollte den Einstieg etwas erleichtern. (Hoffe ich :roll: )

Probier einfach ein bisschen herum und frag, wenn du welche hast. :wink:

Re: SpritePixelCollision?

Verfasst: 25.12.2012 17:27
von TheNewOne
Danke jojo,
ich glaube jetzt hab ichs verstanden :)

Re: SpritePixelCollision?

Verfasst: 28.12.2012 18:57
von TheNewOne
Zumindest dachte ich, dass ich es verstanden hätte. Mein Code Funktioniert nun aber nicht mehr.

Code: Alles auswählen

Global quit.i = 0
Global PlayerX = 500
Global PlayerY = 500
Global FG.i
Global hoehe.i
Global maxHoehe.i = 20

Structure Eigenschaften
  art.i
  durchlaessig.i
EndStructure

Global Dim Punkte.Eigenschaften(90,45)

For n = 0 To 90
  hoehe = Random(maxHoehe) +20
  For m = 90 To hoehe
    Punkte(n,m)\durchlaessig = 0
  Next
  For m = hoehe To 0 Step -1
    Punkte(n,m)\durchlaessig = 1
  Next
Next

Procedure Fehlerbehandlung(Ergebnis.i, Text.s)
  If Ergebnis = 0
    MessageRequester("Fehler", Text, #PB_MessageRequester_Ok)
    End
  EndIf  
EndProcedure

FehlerBehandlung(InitSprite(), "Initialisieren der Sprites fehlgeschlagen!")
FehlerBehandlung(InitKeyboard(), "Initialisieren der Tastatur fehlgeschlagen!")
FehlerBehandlung(OpenScreen(1600, 900, 32, "FullScreen"), "Öffen des Vollbilds fehlgeschlagen!")

Procedure keys()
  
  ExamineKeyboard()
  
  If KeyboardReleased(#PB_Key_Escape)
    quit = #True
  EndIf
  
  If KeyboardPushed(#PB_Key_D)
    If Punkte(PlayerX + 1, PlayerY)\durchlaessig = 1
      PlayerX + 5
    EndIf
  ElseIf KeyboardPushed(#PB_Key_A)
    PlayerX - 5
  EndIf
  
  If KeyboardPushed(#PB_Key_W)
    FG = -5
  EndIf
    
EndProcedure

Procedure drawPlayer()
  
  PlayerY + FG
  If PlayerY > 800
    FG = 0
    PlayerY = 800
  Else
    FG + 1
  EndIf
  
  If PlayerX > 1580
    PlayerX = 1580
  ElseIf PlayerX < 0
    PlayerX = 0
  EndIf
  
  CreateSprite(1,20,20)
  StartDrawing(SpriteOutput(1))
  Box(0,0,20,20,RGB(0,150,0))
  StopDrawing()
  
  CreateSprite(0, 21, 21)
  StartDrawing(SpriteOutput(0))
  Circle(10, 10, 10, RGB(225,255,0))
  StopDrawing()
  
    For n = 0 To 90
      For m = 0 To 45
        If Punkte(n,m)\durchlaessig = 0
         DisplaySprite(1,n*20,m*20)
       EndIf
     Next
    Next
  
  DisplayTransparentSprite(0, PlayerX, PlayerY)
  TransparentSpriteColor(0,0)
  
EndProcedure

Repeat
  ClearScreen(RGB(0,0,0))
  ExamineKeyboard()
  keys()
  drawPlayer()
  FlipBuffers()
Until quit = #True