kleiner spaceshooter
Übersicht

pinochinoBetreff: kleiner spaceshooter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich habe mich mal an nem ganz simplen "Spaceshooter" versucht.
"1 Spielerschiff auf der Linken seite 6 Gegnerschiffe auf der rechten seite, die man abschiesst" Die Gegnerschiffe bewegen sich noch nicht, aber das ist nicht mein Problem. Mein Problem sind die Schüsse ich kann diese auf Leertaste "abfeuern" immer einen nach dem anderen. wenn jetzt ein Schuss auf ein Gegnerschiff trifft werden Gegnerschiff und Schuss gelöscht. Wenn aber 2 Schüsse unterwegs sind und der erste auftrifft gibts eine Fehlermeldung, das das Image nicht Existiert Code: [AUSKLAPPEN] If ImagesCollide(schussgfx,t\x,t\y,0,gegnergfx,g\x,g\y,0)Then
Hab ne weile nach dem Problem gesucht und denke es wird daran liegen das der schuss gelöscht wird aber ja noch ein zweiter unterwegs ist den das Programm dann nicht mehr erkennt. Nur eine Lösung hab ich bisher nicht gefunden. Gesamter Code: Code: [AUSKLAPPEN] Const xmax=800, ymax= 600
Graphics xmax,ymax,16,2 SetBuffer BackBuffer() ftimer=CreateTimer(60) Global spielergfx, gegnergfx, schussgfx images_load() Type gegner Field x# Field y# Field tot End Type Type schuss Field x# Field y# Field speed# Field tot End Type Local spieler_x# = 30 Local spieler_y# = ymax/2 Repeat WaitTimer(ftimer) DrawImage spielergfx, spieler_x,spieler_y If KeyDown(200) Then spieler_y=spieler_y-3 EndIf If KeyDown(208) Then spieler_y=spieler_y+3 EndIf If KeyHit(57) Then neu_schuss(spieler_x,spieler_y,+7,1) DrawImage schussgfx, spieler_x,spieler_y EndIf If spieler_y = ymax Then spieler_y = spieler_y-3 If spieler_y = 0 Then spieler_y = spieler_y+3 For t.schuss = Each schuss DrawImage schussgfx,t\x,t\y t\x=t\x+t\speed If t\x=0 Then t\tot=1 If t\tot=1 Then Delete t.schuss Next Local gegnercounter=0 For g.gegner = Each gegner gegnercounter=gegnercounter+1 DrawImage gegnergfx,g\x,g\y For t.schuss = Each schuss If ImagesCollide(schussgfx,t\x,t\y,0,gegnergfx,g\x,g\y,0)Then t\tot=1 g\tot=1 If g\tot=1 Then Delete g.gegner EndIf EndIf Next Next If gegnercounter<=5 Then neu_gegner() EndIf Flip Cls Until KeyHit(1) End Function images_load() spielergfx = LoadImage("gfx\raumschiff.png") MidHandle spielergfx gegnergfx = LoadImage("gfx\gegnerschiff.png") MidHandle gegnergfx RotateImage gegnergfx,-90 schussgfx = LoadImage("gfx\schuss.png") MidHandle schussgfx RotateImage schussgfx, 90 End Function Function neu_schuss(x#,y#,speed#,schaden#) t.schuss = New schuss t\x=x t\y=y t\speed=speed End Function Function neu_gegner() g.gegner = New gegner g\x= 700 g\y=Rnd(50,550) End Function |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
ich denke, die Ursache liegt ganz wo anders...
In der Gegner-Routine darfst Du den Gegner nicht töten, solange noch die Schuss-FOR-EACH-Schleife läuft. Sonst kann es dir passieren, dass zwar noch weitere Schüsse unterwegs sind, aber der Gegner mit dem sie gerade verglichen werden schon nicht mehr existiert. |
||
bjh |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
hallo pinochino,
ich benutze immer imagesoverlap. würde ich dir auch empfehlen. ![]() ich würde auch den schuss und den gegner schon beim aufprall löschen. dann sparst du dir variablen. ich benutze nie so viele funktionen. ![]() ich hoffe, jemand anderer kann dir besser helfen |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
BlitzBasic: [AUSKLAPPEN] For g.gegner = Each gegner |
||
bjh |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
ich würde es immer noch ohne tot-variablen machen ![]() |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ich danke euch beiden.
Den Gegner ausserhalb der t.schuss-Schleife löschen war die Antowrt! EDIT: Stimmt die tot variable könnte ich weglassen und den gegner einfach löschen. Meine erste Überlegung bevor ich angefangen haben den Code zu schreiben war aber eine Gegner-Lebensberechnung mit einzubauen und dafür bräuchte ich diese Variable ... glaube ich. ![]() |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
Du kannst auf die Variable Gegner\Tot nicht verzichten. Den Schuss kannst du immer gleich löschen. Da der Gegner aber auf der äußeren FOR/EACH-Schleife läuft, darf er in der inneren Schleife eben NICHT sofort gelöscht werden! | ||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Zitat: Da der Gegner aber auf der äußeren FOR/EACH-Schleife läuft, darf er in der inneren Schleife eben NICHT sofort gelöscht werden!
Hab ich verstanden & Funktioniert. Zitat: Du kannst auf die Variable Gegner\Tot nicht verzichten.
Hab ich ausprobiert und ohne g\tot gehts nicht! ![]() mfg pinO |
||
![]() |
skey-z |
![]() Antworten mit Zitat ![]() |
---|---|---|
Doch Midimaster du kannst darauf verzichten, indem du vor der Kollision prüfts, ob der aktuelle Gegner <> NULL ist. | ||
Awards:
Coffee's Monatswettbewerb Feb. 08: 1. Platz BAC#57: 2. Platz |
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Noch eine Frage.
Ich möchte wenn Gegner mit Spieler kollidiert das Spielgeschehen anhalten, einen Text ausgeben und dann das Programm beim drücken einer beliebigen Taste beenden. Aber alle meine Versuche schlugen fehl. Code: [AUSKLAPPEN] If ImagesCollide(spielergfx,spieler_x,spieler_y,0,gegnergfx,g\x,g\y,0) Then Text xmax/2,ymax/2, "GAME OVER! - DEIN SCHIFF WURDE ZERSTOERT!" Text xmax/2,ymax/2+20, "PROGRAMM WIRD AUF TASTENDRUCK GESCHLOSSEN!" waitkey END EndIf habs auch mit Delay und timern versucht aber hat bei mir alles nicht hingehauen. (Timer weiß ich nur das man die FPS begrenzen kann oda so ![]() gruß pinO |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
also, wenn du es ganz professionell machen willst, dann hält die Hauptschleife gar nicht an, sondern alle Spielteilnehmer halten an. Ins Spielgeschehen wird nun ein Rechteck eingeblendet auf dem der Text steht. Nach einer Weile oder Spielereingabe wird dann das Rechteck nicht mehr mitgezeichnet, und die Spielfiguren erhalten wieder ihre Bewegungsmöglichkeiten zurück.
Nachzulesen in meinem Timer-Tutorial https://www.blitzforum.de/foru...hp?t=34436 Dich interessiert dabei am meisten das Kapitel III: Ein Textfeld wird für 3 Sekunden eingeblendet Wichtig ist aber auch das Kapitel I |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Deine Tutorials sind wirklich Spitze ![]() Ich hab dieses scheinbar irgendwie übersehen, werde es sofort durcharbeiten Sind einige interessante Themen dabei ![]() Zitat: Lektion I: Wohin führt dieses Tutorial?
Immer wieder scheitern neue Blitz-User an dem Problem mitten im laufenden Spiel eine der Spielfiguren eine länger dauernde Aktion durchführen zu lassen. Folgende Aktionen fallen wir dabei ein: A. Eine Explosion beendet das Leben des Gegners. Nun soll die Explosion in 10 Frames an der Stelle, wo der Treffer war ablaufen. Der Rest des Spieles soll aber weiterlaufen. B. Der Spieler springt über ein Hindernis. Dabei soll der höchste Punkt nicht auf ein Mal erreicht werden, sondern es soll eine Art Flug zu sehen sein. C. Der User soll eine Text-Eingabe machen können, während das Spiel im Hintergrund weiterläuft. D. Alle 30 Sekunden soll ein neuer Gegner geboren werden. E. Eine Stoppuhr wird in der Bildschirmecke angezeigt. F. Die Spielfiguren sollen unabhängig von der Rechnerleistung auf jedem Computer gleich schnell laufen. Auf all diese Probleme ist das Arbeiten mit Timern die Lösung. Ich geh jetzt brav Lesen und dann mein Problem lösen ![]() |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Joa ... nee Dachte es Verstanden zu haben, dann aber doch versagt. ![]() Code: [AUSKLAPPEN] If ImagesCollide(spielergfx,spieler_x,spieler_y,0,gegnergfx,g\x,g\y,0) Then
TextTimer=MilliSecs()+5*1000 EndIf If TextTimer>MilliSecs() Then Text 100,200,"GAME OVER - SPIEL WIRD BEENDET" If TextTimer<MilliSecs() Then GameEndTimer=MilliSecs() +1000 If GameEndTimer<MilliSecs() Then End EndIf EndIf Hab Viele Verschiedene Varianten aus Probiert. Jetziger Code siehe oben! Hilfe Bitte ![]() mfg pinO EDIT: Oops DoppelPost Verzeihung |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
na, das sieht doch schon ganz vielversprechend aus. Leider hast Du zu wenig Code gesendet. Man müßte auch noch sehen wo die Hauptschleife ist....
Die Timer müssen auch immer darauf gecheckt werden, ob sie schon mal benutzt worden sind. Sonst wird ja der betreffende Code-Abschnitt ständig neu aufgerufen. Die TIMER sollen aber ja immer nur 1x gesetzt werden Du testest, ob Sie schon gesetzt sind, indem man sie auf "=0" testet: BlitzBasic: [AUSKLAPPEN] (If TextTimer=0) And (ImagesCollide(spielergfx,spieler_x,spieler_y,0,gegnergfx,g\x,g\y,0)) Then |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Warum sie jetzt alles eingeklammert haben Versteh ich nicht! ![]() Nochmal mein Gedankengang : Code: [AUSKLAPPEN] If TextTimer=0 And ImagesCollide(spielergfx,spieler_x,spieler_y,0,gegnergfx,g\x,g\y,0) Then
TextTimer=MilliSecs()+5*1000 EndIf Erst wird abgefragt ob der TextTimer=0 ist UND ob spielergfx mit gegnergfx Kollidiert Wenn das so ist wird TextTimer auf 5sec gestellt. Code: [AUSKLAPPEN] If TextTimer>MilliSecs() Then
Text 100,200,"GAME OVER - SPIEL WIRD BEENDET" EndIf Solange TextTimer größer ist als MilliSecs (MilliSecs holt ja jetzt langsam auf) wird GAME - OVER .... Angezeigt Code: [AUSKLAPPEN] If GameEndTimer=0 And TextTimer>0 And TextTimer<MilliSecs() Then
GameEndTimer=MilliSecs() +1000 EndIf Jetzt wird erst abgefragt ob GameEndTimer=0 ist (Unbenutzt) UND ob TextTimer größer als 0(Benutzt)UND ob TextTimer kleiner als Millisecs ist ( Millisecs hat überholt) Dann wird der GameEndTimer auf 1sec gesetzt. Code: [AUSKLAPPEN] If GameEndTimer>0 And GameEndTimer<MilliSecs() Then
End EndIf Wenn GameEndTimer größer ist als 0 (Benutzt) UND GameEndTimer kleiner ist als MilliSecs ( MilliSecs hat wieder Aufgeholt) Dann Programm Beenden! Korrigiere mich Bitte wenn ich das Falsch angehe! ![]() mfg pinO |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
die Klammern sind nur da, weil es übersichtlicher ausschaut.
Du hast alles korrekt nachvollzogen. Ich hoffe mal, du wolltest es auch so? Aber die Grundidee hast du ja jetzt drauf: Immer fragen, ob der Timer schon gesetzt wurden, bzw. ob er noch nicht gesetzt wurde. Es ginge natürlich auch mit FLAGS: BlitzBasic: [AUSKLAPPEN] If GameEndFlag=0 |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Zitat: Du hast alles korrekt nachvollzogen. Ich hoffe mal, du wolltest es auch so?
Ich wollte es so nachvollziehen? Oder ich wollte das es so abläuft wie es jetzt aufgebaut ist? ![]() Ich habe es so nachvollzogen wie es mir Logisch erschien. Hehe. Und so wie es jetzt im Spiel abläuft ist es auch korrekt. ![]() Vielen Dank für Ihre unermüdliche Hilfe und den Verweis auf Ihr Tutorial zu Timern, welches ich vollkommen übersehen habe im FAQ-Forum. Ich werde das Spiel Schritt für Schritt erweitern, ich denke das ist eine gute Methode sich ein gewisses Grundwissen anzueignen. Somit werden sich mir schon bald weitere Rätsel auftuen welche es zu Lösen gilt und über Ihren Rat würde ich mich immer freuen. ![]() so long pinO EDIT: Noch eine "kleine" Frage: Wie kann ich bei Kollision das ganze Spielgeschehen anhalten das die schiffe stillstehen etc? kann ich das mit nem Goto befehl machen das ich die main schleife bis auf GameOverText immer überspringe bis end ? ![]() |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das ist eine nicht ganz leichte Angelegenheit und es gibt mehrere Möglichkeiten dafür....
A Zunächst könntest Du tatsächlich die Stellen, wo Bewegungen addiert werden, überspringen. GOTO sehen die anderen nicht gerne...ist aber möglich. B Jedes Spielelement könnte aber auch einen eigenen TIMER haben, der festlegt alle wieviel msec es sich bewegen soll. Setzt Du diese Timer kurzfristig mal auf Millisecs()+5*1000, bleibt alles für 5sec stehen. C Oder du machst es wieder über Flags. Also jedes Spielelement hat einen TIMER, der festlegt, wie schnell oder oft es agiert und ein FLAG, das festlegt, ob es sich überhaupt bewegt. Dies Möglichkeit finde ich am schönsten. Hier musst Du keine Ablaufzeit festlegen, sondern kannst z.b. auch solange anhalten, bis der User eine Taste drückt. Bei genügend unterschiedlichen FLAGs kann man dann auch Gruppen oder alles anhalten: BlitzBasic: [AUSKLAPPEN] Repeat |
||
pinochino |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Es ist zum verzweifeln . ... ![]() ![]() Ich wollte den Spaceshooter nochmal komplett ohne Hilfe nachbauen ... denkste... Ich bin am ?gegnercounter? gescheitert glaub ich nach ewigen Suchen im Code verglich ich den Code nochmal mit der Vorlage und alles scheint richtig zu sein aber der gegner wird scheinbar nict gelöscht wenn er eine bestimte x koordinate erreicht und nach dem löschen wird auch kein neuer erstellt.... Nochmal drüber gucken bitte ![]() ![]() Code: [AUSKLAPPEN] Const xmax=800, ymax=600
Graphics xmax,ymax,16,2 SetBuffer BackBuffer() Global fps=CreateTimer(60) Global playerx# = 30 Global playery# = ymax/2 Global playerspeed# = 5 Global player_last_schuss Global player_level = 1 Global playergfx=LoadImage("gfx\raumschiff.png") MidHandle playergfx Global schussgfx=LoadImage("gfx\schuss.png") MidHandle schussgfx RotateImage schussgfx, 90 Global gegnergfx=LoadImage("gfx\gegnerschiff.png") MidHandle gegnergfx RotateImage gegnergfx, -90 Type schuss Field x# Field y# Field speed# Field tot End Type Type gegner Field x# Field y# Field speed# Field tot End Type Repeat WaitTimer(fps) DrawImage playergfx, playerx,playery If KeyDown(200) Then playery=playery-playerspeed EndIf If KeyDown(208) Then playery=playery+playerspeed EndIf If playery>600 Then playery=playery-playerspeed If playery<0 Then playery=playery+playerspeed If KeyDown(57)And player_last_schuss<MilliSecs() Then create_schuss(playerx,playery,10) player_last_schuss=MilliSecs()+1000 EndIf For s.schuss = Each schuss DrawImage schussgfx,s\x,s\y s\x=s\x+10 If s\x>800 Then s\tot =1 If s\tot = 1 Then Delete s.schuss Next Local gegnercounter For g.gegner = Each gegner gegnercounter=gegnercounter+1 DrawImage gegnergfx,g\x,g\y If g\x=100 Then g\tot=1 g\x=g\x-g\speed For s.schuss = Each schuss If ImagesCollide(gegnergfx,g\x,g\y,0,schussgfx,s\x,s\y,0) Then s\tot=1 g\tot=1 EndIf Next If g\tot=1 Then Delete g.gegner EndIf Next If gegnercounter<player_level Then create_gegner() EndIf Flip 0 Cls Until KeyHit(1) End Function create_schuss(x#,y#,speed#) s.schuss = New schuss s\x = x s\y = y s\speed= speed End Function Function create_gegner() g.gegner = New gegner g\x= 600 g\y= Rand(10,590) g\speed= 3 End Function |
||
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
von mir gibt es auch ein "fehler suchen"-tutorial, indem strategien erklärt werden, wie man fehler schon im vorfeld verhindert....und wie man sie findet, wenn es doch einmal passiert ist...
https://www.blitzforum.de/foru...hp?t=33510 [EDIT] Mit DEBUGLOG kannst Du Variablen-Werte während des Spiel im DEBUG-Fenster ausgeben. Da siehst Du oft schon, warum etwas nicht stattfindet. Ändere folgende Code-Stelle: BlitzBasic: [AUSKLAPPEN] DebugLog GegnerCounter + " " + PlayerLevel ...und überprüfe, ob du dieses Reslutat erwartet hättest... Dann überlege wo Du als nächstes einen DEBUGLOG einfügen kannst... ich werde mich gleich wieder melden.... |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group