Problem mit schussfunktion

Fragen zu Grafik- & Soundproblemen und zur Spieleprogrammierung haben hier ihren Platz.
Rockmaster
Beiträge: 105
Registriert: 28.04.2006 22:19

Problem mit schussfunktion

Beitrag von Rockmaster »

hi ich habe ein Problem...
und zwar krieg ich es bei meinem minigame nich hin das das schiff dass der spieler steuert beim tastendruck schießt!
ich hab es so eingestellt, dass der spieler das schiff rotieren kann und dann in die richtung in die das schiff geneigt ist fliegt!
Das geht auch Problemlos aber ich hab keine Ahnung wie ich das auf die bullets umsetzen soll...
Die projektile sollen nämlich bei einem tastendruck sofort gezeigt werden und dann auch wenn man die taste losläst weiterfliegen und weiterhin angezigt werden
ich hab keine ahnung was ich tun soll :(
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Beitrag von Kurzer »

Hast Du mal ein bißchen Sourcecode zum gucken?

Generell sollten die X, Y Positionen deines Projektils in Variablen oder besser Arrays bzw. LinkedList stecken, wenn du mehr als ein Projektil gleichzeitig abfeuern möchtest.

Dein game muß einen loop durchlaufen (auch wenn keine Taste gedrückt ist), welcher die Position des Projektils gemäß Richtung des Schiffes aktualisiert.
Der Tastendruck muß dann dafür sorgen, daß ein neues Listennelement (also ein Projektil) erzeugt wird bzw. bei Array muß ein Flag am "Projektil-Array" gesetzt werden, das dem loop anzeigt, daß diese X, Y Positionen zu aktualisieren sind.

Der Loop muß dann entsprechend auch feststellen, ob der Schuß getroffen hat bzw., ob er aus dem Screen raus ist. Dann muß das Element aus der Liste entfernt werden, bzw. beim Array das Flag wieder zurückgesetzt werden.

Also so in etwas sollte das laufen.

Gruß Markus
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

ich hab bei mir ein code gefunden, mit dem ich mal solche winkelsachen probiert hab und hab jetz noch schnell die bullets hinzugefügt. vielleicht hilft dir das. der code is aber ziemlich schweinisch dahin ge...
es werden sich also noch einige meckerer finden :roll:
ausserdem ist einiges wahrscheinlich auch überflüssig (->fallentscheidung?)
mit linker maustaste wird "geschossen"

Code: Alles auswählen

alpha.f
xd.f
yd.f
x.f
y.f

Structure bulletsS
  x.f
  y.f
  ;angle.f
  radius.l
EndStructure
NewList bullets.bulletsS()

winNr = OpenWindow(#PB_Any, 100,100,500,400, "angles")
winHd = WindowID(winNr)


Repeat
  ExamineDesktops()
  
  StartDrawing(WindowOutput(winNr))
    Box(0,0,500,400,$808080)
    Line(100,200, 50,0, $a0a0a0)

    xd=   WindowMouseX(winNr) - WindowWidth(winNr) /2.0
    yd= -(WindowMouseY(winNr) - WindowHeight(winNr)/2.0)
    If xd>0 And yd>0 : alpha=         ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd>0 And yd<0 : alpha= 2*#PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd>0 : alpha=   #PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd<0 : alpha=   #PI + ATan(Abs(yd)/Abs(xd)) : EndIf
    x.f=Cos(alpha)
    y.f=Sin(alpha)
    Line(100,200, x*50,-y*50, $0000ff)
    Line(250,200, xd,-yd, $ff0000)

    ForEach bullets()
      bullets()\radius + 1
      Circle(    100 + bullets()\radius * bullets()\x,      200 - bullets()\radius * bullets()\y,        5, $00ff00)
      If bullets()\radius > 100
        DeleteElement( bullets(), 1)
      EndIf
    Next
  StopDrawing()

  event = WindowEvent()
  Select event
    Case #PB_Event_CloseWindow
      quit=1
    Case 513; left mouse click
      AddElement( bullets() )
      bullets()\x = x
      bullets()\y = y
      bullets()\radius = 0
  EndSelect

  Delay(30)
Until quit
my pb stuff..
Bild..jedenfalls war das mal so.
Rockmaster
Beiträge: 105
Registriert: 28.04.2006 22:19

Beitrag von Rockmaster »

Ich bin teilweise noch anfänger in PB und versteh nich wirklich viel von dem code... :oops:
Könnte man so etwas nicht auch mit diesen so genannten "Threads" machen?
Ich habe gelsesen dass die unabhängig vom hauptprogramm laufen.
Benutzeravatar
Kurzer
Beiträge: 1617
Registriert: 25.04.2006 17:29
Wohnort: Nähe Hamburg

Beitrag von Kurzer »

Threads ist nicht der richtige Weg für sowas und es machts vermutlich noch komplizierter.

Ich kann nicht unbedingt auf PB bezogen sprechen, weil ich da selbst noch Anfänger bin, aber was bei einem Ballergame so alles parallel ablaufen muß, daß weiß ich.

Wichtig zu klären ist erstmal:
Ist Dir denn rein theoretisch klar, was der Rechner bzw. das Programm alles tun müsste, um eben so eine Salve von Schüssen auf den Schirm zu bringen? Also wenn Du die Problemlösung z.B. auf einem Zettel in normaler Umganssprache ausformulieren würdest.

Wenn Du die Problemstellung also schonmal theoretisch lösen kannst, dann ist das die halbe Miete. Wenn man noch nicht alle PB-Befehle kennt, die dazu nötig sind, ist das zwar ziemlich ärgerlich, aber das ist eine Sache die sich im laufe der Zeit von selbst erledigt.
Das/die ersten Programme dauern leider dadurch unverhältnismäßig lange (also bei der Erstellung). Das mußt Du einfach so hinnehmen und wenn möglich nicht ungeduldig werden oder gar alles hinknallen.

Falls dir die theoretische Lösung der Problemstellung nicht klar ist, dann solltest Du mit etwas einfacheren Strukturen beginnen. Etwa nur ein Schuß für den es dann auch nur 3 oder 4 feste Variablen gibt.
Der Code da oben ist eigentlich gutes Anschauungsmaterial, aber eben schon einen Schritt weiter als es vermutlich für Dich gut wäre.

Versuche es erstmal mit etwas weniger Anspruch an Dich selbst.

Also: Vorher mal ganz in Ruhe nachdenken, welche Schritte zur Problemlösung alle nötig sind - also so rein theoretisch - und nicht einfach auf Teufel-komm-raus loscoden.

(Ich habe einen Kumpel, der konnte sich (früher mal) noch keinen Heimcomputer leisten, aber er hat ungelogen nächtelang an der Schreibmaschine Programmcode entwickelt... der dann nacher, als er seinen VIC 20 hatte, auch anstandslos funktionierte... naja, er musste das zwar alles nochmal abtippen und der Typ ist eh nen ziemlich heftiges Beispiel, aber das ist genau der richtige Weg (wenn auch etwas übertrieben in diesem Fall ;). Der Kerl hat später VIC20/C64/Amigas göttlich in Assembler programmiert und konnte mit den Maschinen "jonglieren", wie ein Artist! Eben weil er immer das Problem und seine Lösung so exekt wie möglich versucht hat zu verstehen.)

Auch wichtig:
Versuche möglichst ein großes Problem in mehrere kleine Teilprobleme zu splitten, durch die das große Problem abgebildet wird.
Der Mensch ist nicht dazu gemacht ein komplexes Problem als ganzes zu erfassen und zu lösen... Immer schön kleine Häppchen... Babyschritte sozusagen. Klingt blöd, aber bringt viel.

Und am besten bringt man seine Lösungen zu den kleinen Problem-Häppchen alle fein säuberlich getrennt in einzelnen Prozeduren unter. Man verliert so nicht so schnell den Überblick.

Also soweit erstmal ein paar persönliche Tips von mir.

Viel Erfolg wünsche ich.

Gruß Markus
"Never run a changing system!" | "Unterhalten sich zwei Alleinunterhalter... Paradox, oder?"
PB 6.12 x64, OS: Win 11 24H2 x64, Desktopscaling: 150%, CPU: I7 12700 H, RAM: 32 GB, GPU: Intel(R) Iris(R) Xe Graphics | NVIDIA GeForce RTX 3070
Useralter in 2025: 57 Jahre.
Rockmaster
Beiträge: 105
Registriert: 28.04.2006 22:19

Beitrag von Rockmaster »

Ich bin bis auf diese funktion mit den schusssalven bisher sehr gut klargekommen...
grade die theorie ist mein problem, denn in der praxis find ich immer was ich brauche...
Ich verstehe nur teilweise die logik eines programms und das macht mir die sache schwer!
wenn rauskriege wie PB bei den schüssen arbeiten muss wird das coden nich schwer sein...
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

ich hab dir mal eine art tutorial gemacht, damit könntest du klar kommen.
der erste code erklärt allgemein trigonometrie.
im zweiten code sind dann einfach noch die schuss-sachen hinzugefügt.
führe die codes einfach mal aus...

trigonometrie:

Code: Alles auswählen

alpha.f

quit.l
winNr = OpenWindow(#PB_Any, 100,100,500,400, "angles")
winHd = WindowID(winNr)
Repeat
  ExamineDesktops()
  
  StartDrawing(WindowOutput(winNr))
  
    Box(0,0,500,400,$808080);nur das fenster leeren
    Line(250,200, 100,0, $a0a0a0);zeigt nur den winkel 0 an

    ;xd = x pos der maus, relativ zur fenster mitte
    xd=   WindowMouseX(winNr) - WindowWidth(winNr) /2.0
    
    ;yd = y pos der maus, relativ zur fenster mitte
    ;( das "-" (minus) am anfang rechnet nur ins mathematische
    ;koordinatensystem um, in welchem ja "y" von unten nach
    ;oben verläuft) [diese umrechnung dient nur der anschaulichkeit]
    yd= -(WindowMouseY(winNr) - WindowHeight(winNr)/2.0)
    ;die koordinaten [xd,yd] beziehen sich nun auf einen imaginären
    ;koord.-ursprung(0,0) unten links (mathematisch), nicht oben links.
    
    
    
    ;alpha (typ float) wird errechnet. fallunterscheidung, je nachdem
    ;in welchem quadranten sich der punkt(xd,yd) befindet
    ;das kann man verschieden machen, ich hab xd unterschieden(pos. oder neg.),
    ;man muss nur einen der beiden koordinatenpunkte
    ;auf vorzeichen prüfen, weil [xd,yd] und [-xd,-yd] ja versch. punkte
    ;sind, aber gleiche winkel haben. wenn nur yd neg. ist
    ;sorgt die fallunterscheidung für das richtige vorzeichen des winkels.
    
    ;winkel angaben, im bogenmass(radiant), drehung von 3:00 uhr ( =0 grad ) gegen den uhrzeigersinn:
    ;   0 grad =     0 rad
    ;  90 grad = #PI/2 rad
    ; 180 grad = #PI   rad
    ; 360 grad = #PI*2 rad 

    If xd>0 And yd>0 : alpha=         ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd>0 And yd<0 : alpha= 2*#PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd>0 : alpha=   #PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd<0 : alpha=   #PI + ATan(Abs(yd)/Abs(xd)) : EndIf
    
    If xd=0 And yd>0 : alpha=   #PI*0.5 : EndIf
    If xd=0 And yd<0 : alpha=   #PI*1.5 : EndIf
    ; (die fallunterscheidung geht auch einfacher, aber mit gerimerem didaktischen wert ;)

    ; hier wird sozusagen zurueckgerechnet
    ; x und y haben dann aber werte für den "einheitskreis" (radius=1), also muss man sie noch mit dem gewuenschten radius multiplizieren.
    x.f=100*  Cos(alpha)
    y.f=100* -Sin(alpha) ;y wird wieder umgerechnet vom math. zum computer-koordinatensysten (punkt(0,0) oben links)
    
    ; grad(0...360°) vs rad(0...2*PI) [bogenmass]:
    ; grad = rad *180/PI
    ;  rad = grad *PI/180
    DrawText( 10,10, "grad "+StrF( alpha*(180/#PI) ) )
    DrawText( 10,30, "rad  "+StrF( alpha ) )
    DrawText( 10,50, "xd   "+Str( xd ) )
    DrawText( 10,70, "yd   "+Str( yd ) )
    DrawText( 10,90, "x    "+StrF( x ) )
    DrawText( 10,110,"y    "+StrF( y ) )
    
    Line(250,200, x,y, $0000ff) ;x und y werden relativ zum punkt[250,200] verwendet (kein LineXY() verwendet)

  StopDrawing()

  event = WindowEvent()
  Select event
    Case #PB_Event_CloseWindow
      quit=1
  EndSelect
  Delay(20)
Until quit
...und hier mit bullets (linksclick->schiessen):

Code: Alles auswählen

;##################### new ####
Structure bulletsS
  radius.l
  alpha.f
EndStructure
NewList bullets.bulletsS()
;##############################

alpha.f

quit.l
winNr = OpenWindow(#PB_Any, 100,100,500,400, "angles")
winHd = WindowID(winNr)
Repeat
  ExamineDesktops()
  
  StartDrawing(WindowOutput(winNr))
  
    Box(0,0,500,400,$808080)
    Line(250,200, 100,0, $a0a0a0)

    xd=   WindowMouseX(winNr) - WindowWidth(winNr) /2.0
    yd= -(WindowMouseY(winNr) - WindowHeight(winNr)/2.0)

    If xd>0 And yd>0 : alpha=         ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd>0 And yd<0 : alpha= 2*#PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd>0 : alpha=   #PI - ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd<0 And yd<0 : alpha=   #PI + ATan(Abs(yd)/Abs(xd)) : EndIf
    If xd=0 And yd>0 : alpha=   #PI*0.5  : EndIf
    If xd=0 And yd<0 : alpha=   #PI*1.5 : EndIf

    x = 100*  Cos(alpha)
    y = 100* -Sin(alpha)

    Line(250,200, x,y, $0000ff)
    
    ;##################### new ####
    ForEach bullets()
      xBull =  Cos(bullets()\alpha) * bullets()\radius
      yBull = -Sin(bullets()\alpha) * bullets()\radius
      Circle( 250+xBull, 200+yBull, 5, $00ff00 )
      bullets()\radius + 1
      If bullets()\radius > 100
        DeleteElement( bullets(), 1 )
      EndIf
    Next
    ;##############################
    
    
  StopDrawing()

  event = WindowEvent()
  Select event
    Case #PB_Event_CloseWindow
      quit=1
    ;##################### new ####
    Case 513; leftclick
      AddElement( bullets() )
      bullets()\alpha = alpha
    ;##############################
  EndSelect
  Delay(20)
Until quit
hier is noch ein bild wo die winkel-sachen noch deutlicher werden sollten
(koordinaten sind im mathematischen system -> y wird nach oben groesser):
Bild
my pb stuff..
Bild..jedenfalls war das mal so.
Ghost
Beiträge: 141
Registriert: 10.04.2006 09:10

Beitrag von Ghost »

hi
steh grad vor demselben Problem und wollt mal wissen wie man das macht wenn man keinen direckten zielpunkt hatt . Also nur die richtung (neigung des schiffes) kennt in dem das objeckt schießen soll ?
(nutze v. 3.3)
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

x = cos(alpha_des_schiffes_beim_feuern) * timer
y = sin(alpha_des_schiffes_beim_feuern) * timer

das sind dann die koordinaten des bullet-sprites, wobei timer halt dann pro frame oder so hochgezählt wird und sich der schuss damit bewegt.
<edit: du meinst doch wenn das schiff selbst feuert, nicht wenn auf das schiff geschossen wird.(?)>
my pb stuff..
Bild..jedenfalls war das mal so.
Ghost
Beiträge: 141
Registriert: 10.04.2006 09:10

Beitrag von Ghost »

danke :)
ähm cos und sin ... meinst du damit vom schiff zum bullet aus gesehen

ja das mein ich
(nutze v. 3.3)
Antworten