Frage wegen meinem 2D Shooter..
Frage wegen meinem 2D Shooter..
Hallo,
/edit: das mit schiessen ist nun geklärt, und die kollision klappt auch zur hälfte !
/edit: das mit schiessen ist nun geklärt, und die kollision klappt auch zur hälfte !
Zuletzt geändert von Xsoft am 26.09.2004 13:45, insgesamt 1-mal geändert.
Windows XP Home Edition - SP1 - Pure Basic 3.93 - jaPBe
Bei Geschossen würde ich eine Linked List verwenden. Dann noch eine Structure welche die Daten des Geschosses enthält.
Etwa so:
Wenn du jetzt schießt, einfach ein Element der Liste hinzufügen und die Eigeneschafen wie Pos_x, Pos_y, Speed_x, Speed_y und so setzen. Dann im Programmcode weiter unten eine Schleife welche jedes Listenelement durchläuft und bewegt:
Dabei ist zu berücksichtigen, dass der Speed so gesetzt ist, dass die Richtung auch passt. Also, wenn der Schuss nach links gefeuert wird, dass dann speed_x = abs_speed und speed_y = 0 wird. (abs_speed enthält den gesamten Speed des Geschosses ohne Richtung. Also etwa 20.)
Beim Schuss nach oben muss dann speed_x = 0 sein und speed_y = -abs_speed.
Wenn du Schüsse hast, welche im 360 Grad winkel beliebig jeden Winkel annehmen können, musst du das per SInus, Cosinus und co. errechnen, welchen Wert Speed_x und Speed_y annehmen bei entsprechendem WInkel. Dabei hilft dir jetzt die Nutzung von abs_speed. Denn du musst den Vektor zerlegen in X und Y Richtung, und das geht dann wenn man die gesamtgeschwindigkeit kennt und den Winkel.
Mit dieser Formel kann man den Speed_x berechnen:
WICHTIG: ##WINKEL## muss natürlich durch den eigenen Winkel ersetzt werden. ALso durch den Schusswinkel des Geschosses.
Für Y rechnet man den Speed übrigends auch so aus wie oben, nur anstelle von Cosinus muss man Sinus nehmen.
Ich hoffe das hilft dir etwas mit den Geschossen. So kann man das zumindest machen und dann die Geschwindigkeit für die einzelnen Richtungen errechnen. Vektor zerlegen in X und Y und den Speed zur Position hinzufügen.
// Alle Codes sind nicht getestet sondern aus dem "Stand" aufgeschrieben. Schreibfehler können somit vorhanden sein.
Etwa so:
Code: Alles auswählen
structure geschoss_struc
pos_x.w
pos_y.w
graphic.w
damage.w
speed_x.w
speed_y.w
abs_speed.w
endstructure
newlist bullet.geschoss_struc()
Code: Alles auswählen
foreach bullet()
bullet()\pos_x = bullet()\pos_x + bullet()\speed_x
bullet()\pos_y = bullet()\pos_y + bullet()\speed_y
next bullet()
Beim Schuss nach oben muss dann speed_x = 0 sein und speed_y = -abs_speed.
Wenn du Schüsse hast, welche im 360 Grad winkel beliebig jeden Winkel annehmen können, musst du das per SInus, Cosinus und co. errechnen, welchen Wert Speed_x und Speed_y annehmen bei entsprechendem WInkel. Dabei hilft dir jetzt die Nutzung von abs_speed. Denn du musst den Vektor zerlegen in X und Y Richtung, und das geht dann wenn man die gesamtgeschwindigkeit kennt und den Winkel.
Mit dieser Formel kann man den Speed_x berechnen:
Code: Alles auswählen
bullet()\speed_x = (Cos(2 * 3.14 * ##WINKEL## / 360) * bullet()\abs_speed)Für Y rechnet man den Speed übrigends auch so aus wie oben, nur anstelle von Cosinus muss man Sinus nehmen.
Ich hoffe das hilft dir etwas mit den Geschossen. So kann man das zumindest machen und dann die Geschwindigkeit für die einzelnen Richtungen errechnen. Vektor zerlegen in X und Y und den Speed zur Position hinzufügen.
// Alle Codes sind nicht getestet sondern aus dem "Stand" aufgeschrieben. Schreibfehler können somit vorhanden sein.
- remi_meier
- Beiträge: 1078
- Registriert: 29.08.2004 20:11
- Wohnort: Schweiz
@Xsoft: Wenn du Zeit hast, kannst du auch den Sourcecode meines Spieles TankBlaster (http://mypage.bluewin.ch/remimeier/zip/TankBlaster.zip) analysieren. Sollte alles drinn sein, was du brauchst.
greetz
remi
greetz
remi
collision könntest du so machen, dass du nach dem Bewegen des Spielers prüfst, ob er mit einem anderen Sprite kollidiert (per spritepixelcollision()) und dir die zuletzt gegangene Richtung des Spielers merkst. Wenn jetzt eine Berührung stattfindet, einfach in Gegenrichtung um 1 pixel verschieben und wieder au kollision prüfen. Das musst du dann solange machen, bis keine Kollision mehr auftritt. Und erst am Ende, wenn keine Kollision mehr ist, wird das Sprite angezeigt, dadurch bemerkt man nicht, dass der Spieler übrspünglich in das andere Sprite hinein gelaufen war und wieder "rausgeschoben" wurde. 
Und da du ja sowieso nur 2 Wege hast, links und rechts, sollte sich die Sache mit der Kollision recht einfach gestalten.
Und da du ja sowieso nur 2 Wege hast, links und rechts, sollte sich die Sache mit der Kollision recht einfach gestalten.
-
DarkDragon
- Beiträge: 6291
- Registriert: 29.08.2004 08:37
- Computerausstattung: Hoffentlich bald keine mehr
- Kontaktdaten:
Mal ein kleines, unauskommentiertes Beispiel:
Code: Alles auswählen
InitSprite()
InitKeyboard()
Structure Point2D
X.f
Y.f
EndStructure
Global Tank.Point2D, TilesX, TilesY
TilesX = 1024/32
TilesY = 768/32
Dim Map.l(TilesX-1, TilesY-1)
Procedure CheckCollision(SpeedX.f, SpeedY.f)
For x=0 To TilesX-1
For y=0 To TilesY-1
If Map(x, y) <> 0
If SpriteCollision(0, Int(Tank\X + SpeedX), Int(Tank\Y + SpeedY), Map(x, y), x*32, y*32)
ProcedureReturn 1
EndIf
EndIf
Next y
Next x
EndProcedure
OpenScreen(1024, 768, 32, "")
CreateSprite(0, 32, 32) ;Panzer
StartDrawing(SpriteOutput(0))
Box(0, 0, 32, 32, RGB(128, 128, 128))
StopDrawing()
CreateSprite(1, 64, 64) ;Objekt 1
StartDrawing(SpriteOutput(1))
Box(0, 0, 64, 64, RGB(128, 0, 0))
StopDrawing()
CreateSprite(2, 32, 32) ;Objekt 2
StartDrawing(SpriteOutput(2))
Box(0, 0, 32, 32, RGB(0, 0, 128))
StopDrawing()
Tank\X = 32
Tank\Y = 32
For x=0 To TilesX-1
For y=0 To TilesY-1
If x = 0 Or y = 0 Or y = TilesY-1 Or x = TilesX-1
Map(x, y) = 2
ElseIf x = Int(TilesX/2)-1 And y = Int(TilesY/2)-1
Map(x, y) = 1
EndIf
Next y
Next x
Repeat
ExamineKeyboard()
ClearScreen(0, 128, 0)
For x=0 To TilesX-1
For y=0 To TilesY-1
If Map(x, y) <> 0
DisplaySprite(Map(x, y), x*32, y*32)
EndIf
Next y
Next x
If KeyboardPushed(#PB_KEY_UP)
If CheckCollision(0, -0.5) = 0
Tank\Y - 0.5
EndIf
ElseIf KeyboardPushed(#PB_KEY_DOWN)
If CheckCollision(0, 0.5) = 0
Tank\Y + 0.5
EndIf
EndIf
If KeyboardPushed(#PB_KEY_LEFT)
If CheckCollision(-0.5, 0) = 0
Tank\X - 0.5
EndIf
ElseIf KeyboardPushed(#PB_KEY_RIGHT)
If CheckCollision(0.5, 0) = 0
Tank\X + 0.5
EndIf
EndIf
DisplaySprite(0, Tank\X, Tank\Y)
FlipBuffers(0)
Until KeyboardPushed(#PB_KEY_ESCAPE)
EndAngenommen es gäbe einen Algorithmus mit imaginärer Laufzeit O(i * n), dann gilt O((i * n)^2) = O(-1 * n^2) d.h. wenn man diesen Algorithmus verschachtelt ist er fertig, bevor er angefangen hat.
- NicTheQuick
- Ein Admin
- Beiträge: 8812
- 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
Auweia...Sunny hat geschrieben:Code: Alles auswählen
Structure geschoss_struc pos_x.w pos_y.w graphic.w damage.w speed_x.w speed_y.w abs_speed.w EndStructure
Ich würde für Spiele niemals Words benutzen. Aber auch keine Longs. Sondern wohl eher Floats. Wie will man denn sonst langsame und genaue Bewegungen erstellen?
Sollte also eher so aussehen:
Code: Alles auswählen
Structure geschoss_struc
pos_x.f
pos_y.f
graphic.l
damage.f
speed_x.f
speed_y.f
abs_speed.f
EndStructure