Spieler-Types-Collision

Übersicht BlitzBasic Beginners-Corner

Neue Antwort erstellen

 

Mr. P

Betreff: Spieler-Types-Collision

BeitragMi, Jun 14, 2017 22:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Hallo Leute brauche wiedermal eure Hilfe. Ich bin gerade dabei nen RPG zu programmieren und bin auf folgendes Problem gestoßen: Die Spielfigur wird bei einem Gegner hinter ihm angezeigt, wenn sie hinter ihm steht, bei zwei Gegnern wirkt das ganze schon nicht mehr. Woran kann das liegen, mit spaceinvaders klappt das ganze ja auch mit den bullets genauso gut.

BlitzBasic: [AUSKLAPPEN]

Global player = LoadAnimImage("player.png",35,52.5,0,12);64,0,12)
Global bob = LoadAnimImage("roberto.png",35,52.5,0,12)
Global dot = LoadAnimImage("dotty.png",35,52.5,0,12)

Type friendly
Field x
Field y
Field dir$
Field n
Field pic
Field k#
Field ran
Field rdm
End Type

While Not KeyHit(1)
drawPlayer()
Wend
End

Function drawPlayer()
If GraphicsHeight()/2-tsize/4+py > f\y-tsize/4-offy
DrawImage f\pic,f\x-offx,f\y-tsize*2/3-offy,f\k
DrawImage player,GraphicsWidth()/2+tsize/2+px,GraphicsHeight()/2-tsize/8+py,key
If f\ran = False Then f\k = 6
Else
DrawImage player,GraphicsWidth()/2+tsize/2+px,GraphicsHeight()/2-tsize/8+py,key
DrawImage f\pic,f\x-offx,f\y-tsize*2/3-offy,f\k
If f\ran = False Then f\k = 0
EndIf

If ImagesOverlap(f\pic,f\x+tsize/2-offx,f\y-tsize/4-offy,player,GraphicsWidth()/2+tsize/2+px,GraphicsHeight()/2-tsize/8+py);ImagesCollide(f\pic,f\x+tsize/2-offx,f\y-tsize/4-offy,f\k,coll,GraphicsWidth()/2+tsize/2+px,GraphicsHeight()/2-tsize/8+py,key);arrow,MouseX(),MouseY(),0)
showbar = True
n = f\n
f\ran = False
Else
showbar = False;If ImagesCollide(gamepad,0,screenh-bars,0,arrow,MouseX(),MouseY(),0)If MouseDown(1) Then showbar = False
EndIf
End Function


*edit

Also es geht darum. dass der Spieler entweder hinter oder vor einem Gegner gezeichnet wird, je nachdem auf welcher Höhe er sich befindet. Jetzt verstehe ich auch was du meinst Xeres, aber die Lösung will mir so schnell nicht einfallen.
  • Zuletzt bearbeitet von Mr. P am Mi, Jun 14, 2017 22:59, insgesamt 2-mal bearbeitet

Cykid

BeitragMi, Jun 14, 2017 22:27
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe noch nicht ganz verstanden was du möchstest.

Geht es dir darum das der Spieler unter dem Gegner gezeichnet wird?

Xeres

Moderator

BeitragMi, Jun 14, 2017 22:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich vermute, was du meinst ist, dass wenn du Bilder aus Types zeichnest, manche Bilder andere überdecken, obwohl sie weiter im Hintergrund gezeichnet werden sollten.

Die Ursache ist ganz klar: du sortierst die Bilder nicht, sondern zeichnest sie in der Reihenfolge, wie du sie erstellt hast.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)
 

LordCoder

BeitragDo, Jun 15, 2017 2:52
Antworten mit Zitat
Benutzer-Profile anzeigen
Damit die Objekte in der richtigen Reihenfolge gezeichnet werden, müssen sie sortiert werden. Hier eine Möglichkeit das zu machen:
Erstellen wir erst mal 100 Instanzen des Typs player:
Code: [AUSKLAPPEN]
Graphics 640,480

Type player
  Field x
  Field y
  Field col ;grey colors
End Type

For i=1 To 100
  p.player=New player
  p\x=Rnd(640)
  p\y=Rnd(480)
  p\col=Rnd(255)
Next

Jetzt möchten wir sie zeichnen. Normalerweise würden wir das so machen:
Code: [AUSKLAPPEN]
For p.player = Each player
  Color p\col, p\col, p\col
  Rect p\x, p\y, 50, 50
Next

user posted image

Dann gibt es aber das Problem, dass sie sich überlappen. Wir möchten nun zuerst die Figuren zeichnen, die am weitesten im Hintergrund sind (die die kleinste y-koordinate haben). Wir suchen also zuerst das Objekt mit der kleinsten y-Koordinate (loop 1) und speichern diesen Wert unter up. Dann zeichnen wir alle Objekte mit dieser y-Koordinate (loop 2). Nun merken wir uns den Wert von up in low und suchen den nächst kleinsten y-Wert. (also den kleinsten, der noch grösser ist als low.) (in loop 1) Wenn wir den gefunden haben, dann zeichnen wir die Objekte mit diesen y-Koordinaten. usw. Hier der code:
Code: [AUSKLAPPEN]
low=0
While (low<480)
  up=480
  For p.player = Each player ; (loop 1) find the lowest y value that was not drawn yet
    If (p\y <up And p\y > low) Then
      up = p\y
    End If
  Next ; Now up is the lowest y value that is bigger than up.
  For p.player = Each player ; (loop 2) draw all the images of that y level
    If (p\y = up) Then
      Color p\col,p\col,p\col
      Rect p\x, p\y, 50, 50
    EndIf 
  Next
  low=up
Wend

user posted image

Bemerkungen:
1) Sortieren braucht Zeit. Wenn du sehr viele (zum Beispiel n) objekte hast, dann benötigt der hier präsentierte Algorithmus Grössenordnung n^2 Schleifendurchgänge. Es gibt bessere Sortieralgorithmen, die mit n*log(n) auskommen. (Edit: oder auch nicht. Siehe Bemerkung von Thunder)
2) Vielleicht möchtest du die sachen nicht nur nach y-Koordinate sortieren, sondern auch nach x und/oder nach Grösse etc.. Man kann den Code erweitern..
  • Zuletzt bearbeitet von LordCoder am Do, Jun 15, 2017 18:36, insgesamt 2-mal bearbeitet

Thunder

BeitragDo, Jun 15, 2017 9:00
Antworten mit Zitat
Benutzer-Profile anzeigen
LordCoder hat Folgendes geschrieben:

1) Sortieren braucht Zeit. Wenn du sehr viele (zum Beispiel n) objekte hast, dann benötigt der hier präsentierte Algorithmus Grössenordnung n^2 Schleifendurchgänge. Es gibt bessere Sortieralgorithmen, die mit n*log(n) auskommen.


Eigentlich läuft dein Code in O(n). Die äußere Schleife läuft im Worst Case 480 Mal und ist daher O(1).
(du machst einen Bucketsort https://de.wikipedia.org/wiki/Bucketsort)

Die besseren Sortieralgorithmen (Quicksort, Mergesort, ...) brauchen außerdem normalerweise
Random Access und den hast du nicht bei BB Types. Sobald du die auf Linked Lists implementierst,
hast du erst wieder schlechtere Performance.
Meine Sachen: https://bitbucket.org/chtisgit https://github.com/chtisgit

diceman

BeitragSo, Jul 02, 2017 13:21
Antworten mit Zitat
Benutzer-Profile anzeigen
Wie wäre es, wenn du alle Objekte in einem 2-Dimensionalen Array speicherst, und dann einmal die Schleife durchläufst, von der untersten bis zur obersten Ebene, und nur jeweils die Rechtecke, die sich in der entsprechende Ebene befinden, zeichnest?


Beispiel-Listing:
Code: [AUSKLAPPEN]
Graphics 800,600,32,2
SeedRnd MilliSecs()
SetBuffer BackBuffer()

Const rectMax = 100
Const xMax = 800
Const yMax = 600
Const depthMax = 255

Type RECTANGLE
   Field X
   Field Y
   Field SIZE
   Field DEPTH
End Type
Dim rectList.RECTANGLE(rectMax,depthMax)



createRects()
drawRects()
WaitKey()
sortRects()
drawSortedRects()
WaitKey()
End






Function createRects()
   For a = 1 To rectMax
      r.RECTANGLE = New RECTANGLE
      r\SIZE = Rand(20,100)
      r\X = Rand(1,xMax-r\SIZE)
      r\Y = Rand(1,yMax-r\SIZE)
      r\DEPTH = Rand(0,depthMax)
   Next
End Function



Function drawRects()
   Cls
   For r.RECTANGLE = Each RECTANGLE
      Color r\DEPTH,r\DEPTH,r\DEPTH
      Rect r\X,r\Y,r\SIZE,r\SIZE,1
   Next
   Flip
End Function



Function sortRects()
   Local count
   For r.RECTANGLE = Each RECTANGLE
      rectList(count,r\DEPTH) = r
      count = count +1
   Next
End Function



Function drawSortedRects()
   Cls
   For d = 0 To depthMax
      For r = 1 To rectMax
         If rectList(r,d) <> Null
            Color rectList(r,d)\DEPTH,rectList(r,d)\DEPTH,rectList(r,d)\DEPTH
            Rect rectList(r,d)\X,rectList(r,d)\Y,rectList(r,d)\SIZE,rectList(r,d)\SIZE,1
         EndIf
      Next
   Next
   Flip
End Function



//EDIT:
Ungleich eleganter (und vor allem schneller) ist es, wenn du in der drawSortedRects()-Funktion tatsächlich nur existierende Types ansteuerst. Also die if <> Null Abfrage obsolet wirst. Dazu braucht es ein zusätzliches eindimensionales Array rectAmount(), welches die jeweilige Anzahl von Rechtecken in jeder Ebene speichert. Das untenstehende Programm sortiert auf meinem lahmarschigen Laptop, bei deaktiviertem Debug, 1 Mio. Rechtecke in ~33 Millisekunden (das Zeichnen dauert natürlich etwas länger Very Happy ).

Code: [AUSKLAPPEN]
Graphics 800,600,32,2
SeedRnd MilliSecs()
SetBuffer BackBuffer()

Const rectMax = 100
Const xMax = 800
Const yMax = 600
Const depthMax = 255
Dim rectAmount(depthMax)

Type RECTANGLE
   Field X
   Field Y
   Field SIZE
   Field DEPTH
End Type
Dim rectList.RECTANGLE(rectMax,depthMax)



createRects()
sortRects()
drawSortedRects()
WaitKey()
End






Function createRects()
   For a = 1 To rectMax
      r.RECTANGLE = New RECTANGLE
      r\SIZE = Rand(20,100)
      r\X = Rand(1,xMax-r\SIZE)
      r\Y = Rand(1,yMax-r\SIZE)
      r\DEPTH = Rand(0,depthMax)
   Next
End Function



Function sortRects()
   Dim rectAmount(depthMax)
   For r.RECTANGLE = Each RECTANGLE
      rectAmount(r\DEPTH) = rectAmount(r\DEPTH) +1
      rectList(rectAmount(r\DEPTH),r\DEPTH) = r
   Next
End Function



Function drawSortedRects()
   Cls
   For d = 0 To depthMax
      For r = 1 To rectAmount(d)
         Color rectList(r,d)\DEPTH,rectList(r,d)\DEPTH,rectList(r,d)\DEPTH
         Rect rectList(r,d)\X,rectList(r,d)\Y,rectList(r,d)\SIZE,rectList(r,d)\SIZE,1
      Next
   Next
   Flip
End Function
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.

Neue Antwort erstellen


Übersicht BlitzBasic Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group