Tutorial 5: Das erste 2D Game: Angriffe und leben

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Tutorial 5: Das erste 2D Game: Angriffe und leben

      So Nun zum nächsten Teil: Die angriffe und die leben.

      Unswar wird man über das drücken der Leer-Taste Bomben werfen.

      Was euch also schon Klar sein sollte ist, dass wir in der update Methode eine weitere abfrage brauchen:

      Quellcode

      1. protected override void Update(GameTime gameTime)
      2. {
      3. // Ermöglicht ein Beenden des Spiels
      4. if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
      5. this.Exit();
      6. //Variable die den tastenstatus enthält
      7. KeyboardState ks = Keyboard.GetState();
      8. //variablen für die richtung der beschläunigung
      9. int mX = 0;
      10. int mY = 0;
      11. //tasten abfrage
      12. if (ks.IsKeyDown(Keys.Up))
      13. mY += 1;
      14. if (ks.IsKeyDown(Keys.Down))
      15. mY -= 1;
      16. if (ks.IsKeyDown(Keys.Right))
      17. mX += 1;
      18. if (ks.IsKeyDown(Keys.Left))
      19. mX -= 1;
      20. [COLOR="red"] //Bomben werfen
      21. if (ks.IsKeyDown(Keys.Space)) {
      22. }[/COLOR]
      23. float newX = mX * (float)gameTime.ElapsedGameTime.TotalSeconds * 80; //beschleunigungsfaktor für x errechnen
      24. float newY = -mY * (float)gameTime.ElapsedGameTime.TotalSeconds * 80; //beschleunigungsfaktor für y errechnen[...]
      Alles anzeigen

      Nun entsteht hierbei ein kleines Problem, aber darum kümmere ich mich später...

      Erst einmal muss nun eine neue bombe erstellt werden, die dann hinzugefügt wird:

      Quellcode

      1. Bomb b = new Bomb();

      Nun muss die Startposition der bombe erstellt werden:

      Quellcode

      1. b.pos = new Vector2([COLOR="orange"]player.tex.Width / 2[/COLOR] + player.pos.X, [COLOR="#ff00ff"]player.tex.Height[/COLOR] + player.pos.Y);

      Der orange teil sorgt dafür das die bombe in der Mitte der Spieler Textur entsteht, der Lilane damit sie unterhalb des Spielers entsteht.

      Als geschwindigkeit wird eine geste geschwindigkeit nach unten verwendet,

      Quellcode

      1. b.speed = new Vector2([COLOR="orange"]player.speed.X / 3f[/COLOR] , [COLOR="#ff00ff"]135[/COLOR]);

      Den Orangen teil verwende ich diesmal um eine kleine bewegung in die richtung des spielers hinzubekommen, da die Bombe ja immernoch einen teil der geschwindigkeit hat.
      Lila ist die startgeschwindigkeit; 135 px/s nach unten.

      Der schaden soll ein wenig (pseudo-)Zufällig errechnet werden, dafür verwende ich die random Klasse

      Quellcode

      1. //Neuen Pseudo-Zahl Generator
      2. Random rnd = new Random(DateTime.Now.Millisecond);
      3. //Damage bestimmen
      4. b.damage = rnd.Next(5, 13);
      5. //Generator löschen für den garbage Collector
      6. rnd = null;

      Damit wird ein "Zufälliger wert zwischen 5 und zwölf ermittelt.

      Es bleiben noch BoomInstance(sound) und Tex(Textur)
      für beide könnte man ganz einfach den Content aufrufen, aber sowas in der Update Methode kostet wertvolle zeit. Deshalb erstellen wir vorher schon diese beiden objekte und schreiben dann nur einen verweis in die Bombe.
      Für das erstellen brauchen wir erst mal 2 weitere Variablen im GameEnvironment aus der Objekte.cs:

      Quellcode

      1. public struct GameEnvironment {
      2. /// <summary>
      3. /// Hintergrund Musik
      4. /// </summary>
      5. public SoundEffect bgMusic { get; set; }
      6. /// <summary>
      7. /// Hintergrund Musik Instance
      8. /// </summary>
      9. public SoundEffectInstance bgMusicInstance { get; set; }
      10. /// <summary>
      11. /// Ob das Menü offen ist
      12. /// </summary>
      13. public bool isMenu { get; set; }
      14. /// <summary>
      15. /// Ob das Spiel Gewonnen ist
      16. /// </summary>
      17. public bool won { get; set; }
      18. /// <summary>
      19. /// Ob das Spiel Verloren ist
      20. /// </summary>
      21. public bool lost { get; set; }
      22. /// <summary>
      23. /// Die Hintergrund Farbe
      24. /// </summary>
      25. public Color bgColor { get; set; }
      26. /// <summary>
      27. /// Das bild des mauszeigers
      28. /// </summary>
      29. public Texture2D cursorTex { get; set; }
      30. /// <summary>
      31. /// die position des Mauscursors
      32. /// </summary>
      33. public Vector2 mousePos { get; set; }
      34. /// <summary>
      35. /// Die Breite
      36. /// </summary>
      37. public int windowWidth { get; set; }
      38. /// <summary>
      39. /// Die Höhe
      40. /// </summary>
      41. public int windowHeight { get; set; }
      42. [COLOR="red"] /// <summary>
      43. /// Die Textur der Spieler bomben
      44. /// </summary>
      45. public Texture2D pBombTex { get; set; }
      46. /// <summary>
      47. /// Die Textur der Gegner bomben
      48. /// </summary>
      49. public Texture2D eBombTex { get; set; }
      50. /// <summary>
      51. /// Der Sound der Spieler bomben
      52. /// </summary>
      53. public SoundEffect pBombSound { get; set; }
      54. /// <summary>
      55. /// Der Sound der Gegner bomben
      56. /// </summary>
      57. public SoundEffect eBombSound { get; set; }[/COLOR]
      58. }
      Alles anzeigen

      dann müssen die in LoadContent auch noch geladen werden:

      Quellcode

      1. protected override void LoadContent()
      2. {
      3. // Erstellen Sie einen neuen SpriteBatch, der zum Zeichnen von Texturen verwendet werden kann.
      4. spriteBatch = new SpriteBatch(GraphicsDevice);
      5. player.tex = Content.Load<Texture2D>("PlayerIMG"); //Textur für den Spieler
      6. enemy.tex = Content.Load<Texture2D>("EnemyIMG"); //Textur für den Spieler
      7. environment.bgMusic = Content.Load<SoundEffect>("BGM"); //Hintergrund Musik Laden
      8. environment.bgMusicInstance = environment.bgMusic.CreateInstance(); // Hintergrund Musik Instanz zum abspielen Erstellen
      9. environment.bgMusicInstance.IsLooped = true;//Damit die musik wieder von forn anfängt
      10. environment.bgMusicInstance.Play();//Abspielen starten
      11. environment.cursorTex = Content.Load<Texture2D>("Cursor"); //Mauszeiger bild Laden
      12. [COLOR="red"] environment.eBombSound = Content.Load<SoundEffect>("Laser"); //Gegner Laser Sound Laden
      13. environment.pBombSound = Content.Load<SoundEffect>("Boom"); //Spieler Bomben Sound Laden
      14. environment.pBombTex = Content.Load<Texture2D>("bomb"); //Spieler Bomben Textur Laden
      15. environment.eBombTex = Content.Load<Texture2D>("Shot"); //Gegner Bomben Textur Laden[/COLOR]
      16. }
      Alles anzeigen


      Und nun gibt es nur noch einen neuen zeiger auf die bombe hinzuzufügen

      Quellcode

      1. //Bomben werfen
      2. if (ks.IsKeyDown(Keys.Space)) {
      3. //Erstellen
      4. Bomb b = new Bomb();
      5. //Startposition errechnen
      6. b.pos = new Vector2(player.tex.Width / 2 + player.pos.X, player.tex.Height + player.pos.Y);
      7. //Startgeschwindigkeit errechnen
      8. b.speed = new Vector2(player.speed.X / 3f, 135);
      9. //Neuen Pseudo-Zahl Generator
      10. Random rnd = new Random(DateTime.Now.Millisecond);
      11. //Damage bestimmen
      12. b.damage = rnd.Next(5, 13);
      13. //Generator löschen für den garbage Collector
      14. rnd = null;
      15. [COLOR="red"] //auf Textur verweisen
      16. b.tex = environment.pBombTex;
      17. //sound Instanz erstellen
      18. b.boomInstance = environment.pBombSound.CreateInstance();[/COLOR]
      19. Und dann noch mit
      20. [CODE] player.Bombs.Add(b);
      Alles anzeigen

      hinzufügen.

      Nun geht es an das zeichnen, in der Draw Methode

      Quellcode

      1. protected override void Draw(GameTime gameTime)
      2. {
      3. GraphicsDevice.Clear(Color.CornflowerBlue);
      4. spriteBatch.Begin();//Zeichnen starten
      5. spriteBatch.Draw(player.tex, player.pos, Color.White);//Spieler zeichnen
      6. spriteBatch.Draw(enemy.tex, enemy.pos, Color.White);//gegner zeichnen
      7. [COLOR="red"] foreach (Bomb b in player.Bombs) // Jede bombe des spielers durchgehen
      8. spriteBatch.Draw(b.tex, b.pos, Color.White); //und zeichnen
      9. foreach (Bomb b in enemy.Bombs)// Jede bombe des gegners durchgehen
      10. spriteBatch.Draw(b.tex, b.pos, Color.White); //und zeichnen[/COLOR]
      11. spriteBatch.End();//Zeichnen ende
      12. base.Draw(gameTime);
      13. }
      Alles anzeigen

      }[/CODE]

      Jetzt geht es nur noch an die Bewegung der bomben:
      Dafür wird nun in der Update Methode eigentlich das Selbe gemacht wie für den gegner nur halt nach unten/oben:

      Quellcode

      1. for (int i = 0; i <= player.Bombs.Count - 1; i++ )/*Jeden Bombenindex durchgehen*/ {
      2. Bomb b = player.Bombs[i]; //Bombe am index aufrufen
      3. b.pos += b.speed* (float)gameTime.ElapsedGameTime.TotalSeconds; //neue position ermitteln
      4. player.Bombs.Add(b); //Neuen eintrag setzen
      5. player.Bombs.RemoveAt(i); //Alten eintrag löschen
      6. }


      Bomben kolision:
      Das folgende verfahren ist total naiv und unprofessionell, und nur bei wenigen kollisionen zu enpfehlen, da ich jede bombe mit jedem objekt abgleiche
      die rechenleistung ist also

      Quellcode

      1. Anzahl_DER_OBJEKTE^ANZAHL_DER_BOMBEN * LEISTUNG_PRO_ABFRAGE

      und dies kann einen enormen verschleiß an zeit haben, wenn man viele objekte hat.
      dennoch für das recht es.

      Für die kollisionserkennung verwenden wir die schleife zur bewegung, und hängen die abfrage einfach rein, sodass sollte eine kollision vorliegen das objekt einfach nicht mehr hinzugefügt wird:

      Quellcode

      1. //Bomben bewegen
      2. for (int i = 0; i <= player.Bombs.Count - 1; i++ )/*Jeden Bombenindex durchgehen*/ {
      3. Bomb b = player.Bombs[i]; //Bombe am index aufrufen
      4. b.pos += b.speed* (float)gameTime.ElapsedGameTime.TotalSeconds; //neue position ermitteln
      5. //wenn die bombe nicht im gegner ist
      6. [COLOR="red"] if (!(b.pos.Y + b.tex.Height >= enemy.pos.Y & b.pos.X >= enemy.pos.X - b.tex.Width & b.pos.X <= enemy.pos.X + enemy.tex.Width))[/COLOR] {
      7. //wenn die bomben auf dem boden aufkommen
      8. [COLOR="orange"]if (b.pos.Y >= environment.windowHeight - b.tex.Height)[/COLOR] {
      9. b.boomInstance.Play();
      10. } else { //sonst
      11. player.Bombs.Add(b); //Neuen eintrag setzen
      12. }
      13. } else { //sonst
      14. b.boomInstance.Play(); //explosions Sound Spielen
      15. enemy.lives -= b.damage;//schaden abziehen
      16. }
      17. player.Bombs.RemoveAt(i); //Alten eintrag löschen
      18. }
      Alles anzeigen

      Das rote fragt ab ob der gegner berührt ist, wenn nicht wird mit dem orangenen abgefragt ob der boden berührt ist, wenn der gegner berührt ist wird der Sound gespielt und der gegner verliert leben, beim boden wird nur der sound gespielt, und nur wenn nichts davon Stimmt bleibt die bombe in der liste.

      Nun zu dem kleinen poblem:
      Sobald man auf leer klickt wirft man X bomben.
      Dies beheben wir mit einer wartezeit: also wenn die noch nicht um ist wird keine bombe geworfen.

      Dafür fügen wir 2 neue variablen zur player und zur enemy struktur hinzu:

      Quellcode

      1. /// <summary>
      2. /// Der Zeitpunkt des letzten schusses
      3. /// </summary>
      4. public float lastShot { get; set; }
      5. /// <summary>
      6. /// Die Wartezeit bis zum nächsten
      7. /// </summary>
      8. public float waitTime { get; set; }

      nun müssen wir die natürlich auch mitladen, dafür gehen wir in die Initialize Methode aus der game.CS

      Quellcode

      1. protected override void Initialize()
      2. {
      3. // TODO: Fügen Sie Ihre Initialisierungslogik hier hinzu
      4. player = new Player();
      5. enemy = new Enemy();
      6. environment = new GameEnvironment();
      7. //Globale Einstellungen
      8. environment.bgColor = Color.CornflowerBlue; //Die Hintergrundfarbe für das Spiel(Standart hintergrundfarbe von)
      9. environment.isMenu = false; //Ob das Menu offen ist (Vor erst nicht, das Menu kommt später)
      10. environment.lost = false; //Ob das Spiel verloren ist
      11. environment.won = false; //Ob das Spiel gewonnen ist
      12. environment.windowHeight = this.GraphicsDevice.Viewport.Height; //Die Fenster Höhe abspeichern
      13. environment.windowWidth = this.GraphicsDevice.Viewport.Width; //Die Fenster Breite abspeichern
      14. //Player Einstellungen
      15. player.Bombs = new List<Bomb>(); //Bomben Array/Liste Initialisieren
      16. player.lives = 3; //Leben festlegen
      17. player.pos = new Vector2(0, 0); //Standartposition für den Spieler bei Spielbeginn
      18. player.speed = new Vector2(0, 0); //keine bewegung am start
      19. [COLOR="red"] player.lastShot = 0f;
      20. player.waitTime = 0.5f;[/COLOR]
      21. //Gegner Einstellungen
      22. enemy.Bombs = new List<Bomb>(); //Bomben Array/Liste Initialisieren
      23. enemy.lives = 100; //Leben festlegen (100%)
      24. enemy.pos = new Vector2(0f, environment.windowHeight - 97f); //Die position (0pixel auf X, und die Fenster höhe - die höhe des bildes auf der Y)
      25. enemy.speed = new Vector2(150f, 0f); //Geschwindigketi(mit 5 pixeln pro sek nach rechts)
      26. [COLOR="red"] enemy.lastShot = 0f;
      27. enemy.waitTime = 2f;[/COLOR]
      28. base.Initialize();
      29. }
      Alles anzeigen

      Nun bauen wir das mit einer simplen abfrage noch ein:

      Quellcode

      1. //Abfragen on schon lang genug gewartet wurde
      2. [COLOR="red"]if ((float)gameTime.TotalGameTime.TotalSeconds >= player.lastShot + player.waitTime) {[/COLOR]
      3. //Bomben werfen
      4. if (ks.IsKeyDown(Keys.Space)) {
      5. [COLOR="red"] //Neue LastShot Zeit
      6. player.lastShot = (float)gameTime.TotalGameTime.TotalSeconds;[/COLOR]
      7. //Erstellen
      8. Bomb b = new Bomb();
      9. //Startposition errechnen
      10. b.pos = new Vector2(player.tex.Width / 2 + player.pos.X, player.tex.Height + player.pos.Y);
      11. //Startgeschwindigkeit errechnen
      12. b.speed = new Vector2(player.speed.X / 3f, 135);
      13. //Neuen Pseudo-Zahl Generator
      14. Random rnd = new Random(DateTime.Now.Millisecond);
      15. //Damage bestimmen
      16. b.damage = rnd.Next(5, 13);
      17. //Generator löschen für den garbage Collector
      18. rnd = null;
      19. //auf Textur verweisen
      20. b.tex = environment.pBombTex;
      21. //sound Instanz erstellen
      22. b.boomInstance = environment.pBombSound.CreateInstance();
      23. //Bombe hinzufügen
      24. player.Bombs.Add(b);
      25. }
      26. }
      Alles anzeigen

      mit (float)gameTime.TotalGameTime.TotalSeconds wird der float wert der aktuellen spiel zeit in sekunden rausgefunden, mit dem zeitpunkt des letzten schusses verglichen, und wenn die waitTime vorbei ist kann erneut geschossen werden.

      Jetzt muss das ganze nur noch auf den gegner umgeschrieben werden, da der gegner ein pc ist wird anstatt mit der tastenabfrage mit einem zufall von 1 und 2 entschieden ob geschossen wird oder nicht:

      Quellcode

      1. //Abfragen on schon lang genug gewartet wurde
      2. if ((float)gameTime.TotalGameTime.TotalSeconds >= enemy.lastShot + enemy.waitTime)
      3. {
      4. Random gen = new Random(DateTime.Now.Millisecond);
      5. //Bomben werfen
      6. if (gen.Next(1,3)==1)
      7. {
      8. //Neue LastShot Zeit
      9. enemy.lastShot = (float)gameTime.TotalGameTime.TotalSeconds;
      10. //Erstellen
      11. Bomb b = new Bomb();
      12. //Startposition errechnen
      13. b.pos = new Vector2(enemy.tex.Width / 2 + enemy.pos.X, enemy.pos.Y);
      14. //Startgeschwindigkeit errechnen
      15. b.speed = new Vector2(0f, -135);
      16. //Damage bestimmen
      17. b.damage = 1;
      18. //auf Textur verweisen
      19. b.tex = environment.eBombTex;
      20. //sound Instanz erstellen
      21. b.boomInstance = environment.eBombSound.CreateInstance();
      22. //Bombe hinzufügen
      23. enemy.Bombs.Add(b);
      24. }
      25. }
      26. //Bomben bewegen
      27. for (int i = 0; i <= enemy.Bombs.Count - 1; i++)/*Jeden Bombenindex durchgehen*/
      28. {
      29. Bomb b = enemy.Bombs[i]; //Bombe am index aufrufen
      30. b.pos += b.speed * (float)gameTime.ElapsedGameTime.TotalSeconds; //neue position ermitteln
      31. //wenn die bombe nicht im gegner ist
      32. if (!(b.pos.Y + b.tex.Height >= player.pos.Y [COLOR="red"]& b.pos.Y <= player.pos.Y+player.tex.Height[/COLOR] & b.pos.X >= player.pos.X - b.tex.Width & b.pos.X <= player.pos.X + player.tex.Width))
      33. {
      34. //wenn die bomben auf dem boden aufkommen
      35. [COLOR="orange"] if (b.pos.Y <= 0)
      36. {
      37. b.boomInstance.Play();
      38. }[/COLOR]
      39. else
      40. { //sonst
      41. enemy.Bombs.Add(b); //Neuen eintrag setzen
      42. }
      43. }
      44. else
      45. { //sonst
      46. b.boomInstance.Play();
      47. player.lives -= b.damage;
      48. }
      49. enemy.Bombs.RemoveAt(i); //Alten eintrag löschen
      50. }
      Alles anzeigen

      Die änderungen sind: ich habe player und enemy vertauscht, den roten punkt zur kollisonsabfrage hinzugefügt(damit auch untendrunter abgefragt wird) und ich habe die richtung auf - gestellt, damit sie hoch fliegen, und mit den orangenen teil habe ich die rand kollision auf den oberen rand gestellt.

      Die leben:

      Zu erst laden wir die textur im load content(hab ich im anderen tutorial vergessen)

      Quellcode

      1. protected override void LoadContent()
      2. {
      3. // Erstellen Sie einen neuen SpriteBatch, der zum Zeichnen von Texturen verwendet werden kann.
      4. spriteBatch = new SpriteBatch(GraphicsDevice);
      5. player.tex = Content.Load<Texture2D>("PlayerIMG"); //Textur für den Spieler
      6. [COLOR="red"] player.liveTex = Content.Load<Texture2D>("PL"); //Lebenstextur laden[/COLOR]
      7. enemy.tex = Content.Load<Texture2D>("EnemyIMG"); //Textur für den Spieler
      8. [COLOR="red"] enemy.liveTex = Content.Load<Texture2D>("EL"); //Lebenstextur laden[/COLOR]
      9. environment.bgMusic = Content.Load<SoundEffect>("BGM"); //Hintergrund Musik Laden
      10. environment.bgMusicInstance = environment.bgMusic.CreateInstance(); // Hintergrund Musik Instanz zum abspielen Erstellen
      11. environment.bgMusicInstance.IsLooped = true;//Damit die musik wieder von forn anfängt
      12. environment.bgMusicInstance.Play();//Abspielen starten
      13. environment.cursorTex = Content.Load<Texture2D>("Cursor"); //Mauszeiger bild Laden
      14. environment.eBombSound = Content.Load<SoundEffect>("Laser"); //Gegner Laser Sound Laden
      15. environment.pBombSound = Content.Load<SoundEffect>("Boom"); //Spieler Bomben Sound Laden
      16. environment.pBombTex = Content.Load<Texture2D>("bomb"); //Spieler Bomben Textur Laden
      17. environment.eBombTex = Content.Load<Texture2D>("Shot"); //Gegner Bomben Textur Laden
      18. }
      Alles anzeigen


      für gewöhnlich würden wir die Leben so zeichnen lassen

      Quellcode

      1. spriteBatch.Draw(enemy.liveTex, new Rectangle(0, 0, environment.windowWidth, 15), Color.White);

      da haben wir aber immer nur skalierte leben, um was abzuschneiden benötigen wir das source rectange.
      Dabei handelt es sich um den ausschnitt, der gezeigt werden soll, alles andere fällt weg
      um nur den lebensteil des gegners anzuzeigen brauchen wir

      Quellcode

      1. spriteBatch.Draw(enemy.liveTex, new Rectangle(0, 0, (environment.windowWidth / 100) * enemy.lives, 15), new Rectangle(0, 0, (environment.windowWidth / 100) * enemy.lives, 15), Color.White); // ausschnitt zeichnen

      hier bei ist vor allem wichtig dass das destination rectangle(das erste) nicht größer als das source rectangle(das 2te) ist. das source rectangle geht von dem punkt 0,0 auf eurer textur, nicht von dem in dem programm aus also entspricht 0,0 der position der textur, während sich das destination rectangle nach den programm koordinaten richtet
      Die form der größen berechnung ist reine prozentrechnugn, und dass muss ich wohl von euch erwarten.

      die spieler textur wird so gezeichnet:

      Quellcode

      1. spriteBatch.Draw(player.liveTex, new Vector2(environment.windowWidth-45, 15), new Rectangle(0, 0, 15*player.lives, 15), Color.White); // ausschnitt zeichnen
      dabei habe ich einen vector 2 genommen, da höhen und breiten angaben in diesem fall sinnlos sind(die textur hat ne feste größe)
      und dass new Rectangle(0, 0, 15*player.lives, 15) berechnet die anzahl der herzen(1 herz = 15 px)

      So gut wenn ihr das gemacht habt ist das spiel eigentlich soweit fertig, Was jetzt noch kommt hat weniger was mit XNA zu tun, das sind eher extras die durch reine anfrageng geschehen.

      Dann kommt am Ende noch einmal ein kleines tutorial wie man das ganze auf windows phone und XBox umschreibt.

      Die komplette bisherige projektmappe bekommt ihr hier:
      rapidshare.com/files/453578802/Bomber.zip

      Ach nochwas: Die hintergrund musik hab ich komplett selbst gemacht: die gehört mir(falls einer auf die idee kommen sollte das teil oder teile davon zu verwenden)
    • Werbung zur Unterstützung des Forums ( Bitte AddBlocker deaktivieren )

    • Alles schön und gut, dass du dich bemühst, aber es kommt mir keine rechte Freude an so einigem auf.
      Nochmals, wieso nimmst du Strukturen statt Klassen für Objekte, die mit ner Klasse 1000x besser bedient sind.
      Außerdem kannste bei nicht benötigten Sachen gleich Dispose() aufrufen, nur auf den GC zu warten kann teilweise tödlich sein.
      Es mag stimmen, dass man während Update nich unbedingt was laden sollte, da es aufgrund der häufigen Aufruferei blöd wäre, aber es macht meistens auch mal sinn, etwas trotzdem dort nachzuladen, aber dafür zu sorgen, dass es am ende dennoch wieder geladen wird, wenn von XNA die LoadContent Methode aufgerufen wird, damits keine Probleme gibt.
      Achja, deine Kollisionsabfrage ist sehr umständlich und doof, benutz ein Rechteck um die Textur quasi als Bounding-Box und führe damit die Kollisionsabfrage durch, die sieht erstens besser aus und bringt mehr als deine Methode.

      Für mich sehen die Tutorials teilweise aus, wie als hättest du kaum Ahnung, willst aber was machen, die Mängel fliegen einem richtig zu in manchen Fällen.
      Gerade Spieleentwickler müssen Bescheid wissen von diesen Dingen:
      1. Kapselung der Daten in Klassen/Strukturen (wozu ist alles sonst Objektorientiert, wenn man eh alles irgendwie zusammenschmeißt)
      2. Namenskonventionen
      3. Saubere Programmierung (<-- das wichtigste)

      Achja, einige SCreens im Tut würden nie schaden und mehr erklären auch nicht.
      Und wenn Probleme auftauchen, schmeiß sie raus und sag nich, "dazu kommen wir gleich"
      Das is schon bei deiner Steuerungslogik, du sagst, es gäbe ein Problem mit dem vertauschen von den Richtungen und statt es gleich richtig zu machen, drehst du lieber ein Vorzeichen in ner spätern berechnung rum.
      Viel Spaß beim Bugfix, wenn du so weitermachst.
    • Nochmals, wieso nimmst du Strukturen statt Klassen für Objekte, die mit ner Klasse 1000x besser bedient sind.

      Klassen bringens nur wenn man Methoden verwenden will (Interne und Externe) während als Datenspeicher Strukturen vollkommen ausreichen
      Außerdem kannste bei nicht benötigten Sachen gleich Dispose() aufrufen, nur auf den GC zu warten kann teilweise tödlich sein.

      Natürlich auch diese form der Kollisionserkennung ist tötlich, doch bei diesem spiel machts keinen unterschied
      Es mag stimmen, dass man während Update nich unbedingt was laden sollte, da es aufgrund der häufigen Aufruferei blöd wäre, aber es macht meistens auch mal sinn, etwas trotzdem dort nachzuladen, aber dafür zu sorgen, dass es am ende dennoch wieder geladen wird, wenn von XNA die LoadContent Methode aufgerufen wird, damits keine Probleme gibt.

      Mit jedem mal Content.Load wird ein neuer Speicher im Ram erstellt, in dem das reingeschrieben wird, mit meiner methode wird nur einer erstellt auf den verwiesen wird.
      Bei Dingen die oft geladen werden kannst du davon ausgehen, dass das laden in der Update Methode 1000x tötlicher wäre als der GC
      1. Kapselung der Daten in Klassen/Strukturen (wozu ist alles sonst Objektorientiert, wenn man eh alles irgendwie zusammenschmeißt)

      Zu viele verschachtelungen machen das Ganze unübersichtlich, Jeder muss selbst wissen wie er das macht für mich wäre jede weitere abkapselung total unübersichtlich und ich würde überhaupt nicht klar kommen, wenns bei dir anders ist musst du es den anderen aber nicht aufbinden. Außerdem wenn du schon mit dem OOP kommst: bei dem OOP wird jede klasse einzeln initialisiert und abgefragt, und dass kostet wertvolle resseurcen und ram, Meiner meinung nach hat das OOP keinen vorteil der diesen nachteil überwiegt.
      2. Namenskonventionen

      Ich mache es so: Denglische namen, Klassen Groß geschrieben, Variablen und Methoden klein geschrieben, so hat man Klare unterschiede zwischen Player und player.
      Das is schon bei deiner Steuerungslogik, du sagst, es gäbe ein Problem mit dem vertauschen von den Richtungen und statt es gleich richtig zu machen, drehst du lieber ein Vorzeichen in ner spätern berechnung rum.

      Das hat einen bestimmten grund: wenn ich direkt die fehler umgehen würde würden leute das einfach abschreiben und warscheinlich nichtmal drüber nachdenken, wenn ich aber erst diesen fehler aufweise dann ist man gezwungen drüber nachzudenken, und an welcher stelle man den behebt ist doch egal.
    • Für mich ist das Tutorial nur aus irgentwelchen sachen zusammengesetzt.
      Und das auch noch schlecht, was bringt es User die sich auf Spieleprogrammierung spezalisieren,
      und dan so etwas sehen. Das ist tut mir leid aber Augenkrebs in meinen Augen.

      Ich z.B Programmiere gerade ein Spiel, und wen ich das Anwenden würde was du hier schreibst...
      ayayay sag ich da nur. Schau du dir am besten nochmal Tutorials an bevor du welche schreibst.

      So etwas wie Internefreaks sein Tutorial ist ein richtiges:
      mmorpg-core.com/forum/tutorial…d-erklaerungen-21957.html

      Ich behaupte nicht das du keine Ahnung davon hast, aber von jedem tutorial das ich von dir lese kommt es mir
      so vor.
    • Klassen bringen aber trotzdem mehr als du denkst, so kannst du die ganze Logik des Players, der Gegner sowie der Bomben kapseln und hast weniger Arbeit, die Sachen in den Maincode einzubauen usw.
      Eine Klasse für Player usw ist besser als eine Struktur, allein wegen der Übersicht und so.

      Trotz allem ist ein Aufruf von Dispose die bessere Variante, als auf den GC zu warten, denn der tritt nicht immer in Aktion, dazu müssen schon bestimmte Dinge erfüllt sein, damit der wirklich kommt.
      Und deine Antwort mit Content.Load zeigt mir, dass du:
      1. Nich wirklich Ahnung von Content.Load hast
      2. Meinen Beitrag nicht gelesen hast bzw nicht richtig
      Content.Load lädt einen Inhalt nur einmal und gibt ansonsten immer wieder einen Verweis auf das Ding zurück, das wär ja noch schöner, wenns wirklich jedes mal geladen wird, wenn mans brauch, also so dumm sind die XNA entwickler auch nicht, dass sie nicht etwas auf den Speicherverbrauch achten.
      Aber dennoch sollte man nie immer alles direkt vorladen, man bedenke, dass XBox sowie das WindowsPhone nur begrenzt Speicher haben, da muss man auf alles achten.

      Die Kapselung in Klassen hat einige Vorteile:
      Man kann Methoden definieren, der Code wird sauberer usw, was wird da unübersichtlich, wenn du mal schnell ne Klasse anlegst für ein Spielobjekt usw.
      Und wenn du schon sagst, dass alles initialisiert und abgefragt wird und dies nur "Ressourcen" und "Ram" kostet, dann halte dich bitte von C# sowie VB.net fern.
      Denn da arbeitest du eigentlich soweit nur mit Klassen und Strukturen, das .NET Framework ist eine Klassenbibliothek.

      Fehler macht man, das ist klar.
      Aber es nicht definitiv nicht immer egal, wo man einen Fehler letztendlich behebt, das kann z.T sogar eher zum Nachteil werden, einen Fehler nicht da zu beheben, wo er sich befindet, sondern eher woanders auszugleichen.
      Und ob du nun den Fehler umgehst oder nicht, die Leute können immernoch C&P machen und nicht drüber nachdenken, außerdem soll ein Tutorial Wissen vermitteln und den Leuten zeigen, wie etwas geht und daher eigentlich von vornerein nicht unbedingt so aufgebaut sein, dass man zwangläufig auf nen Fehler trifft, also man soll sie nicht absichtlich einbauen, das ist nicht förderlich.
    • Jok3r;227987 schrieb:

      Für mich ist das Tutorial nur aus irgen[COLOR="#ff0000"]d[/COLOR]welchen [COLOR="#ff0000"]S[/COLOR]achen zusammengesetzt.
      Und das auch noch schlecht, was bringt es User[COLOR="#ff0000"]n[/COLOR] die sich auf Spieleprogrammierung spez[COLOR="#ff0000"]i[/COLOR]alisieren,
      und dan[COLOR="#ff0000"]n[/COLOR] so etwas sehen. [COLOR="#ff0000"]Es[/COLOR] tut mir leid[COLOR="#ff0000"],[/COLOR] aber [COLOR="#ff0000"]das ist[/COLOR] Augenkrebs in meinen Augen.

      Ich z.B [COLOR="#ff0000"]p[/COLOR]rogrammiere gerade ein Spiel, und wen[COLOR="#ff0000"]n[/COLOR] ich das [COLOR="#ff0000"]a[/COLOR]nwenden würde was du hier schreibst...
      [COLOR="#ff0000"]A[/COLOR]yayay sag ich da nur. Schau du dir am [COLOR="#ff0000"]B[/COLOR]esten nochmal Tutorials an bevor du welche schreibst.

      So etwas wie Internefreaks sein Tutorial ist ein richtiges:
      mmorpg-core.com/forum/tutorial…d-erklaerungen-21957.html

      Ich behaupte nicht das[COLOR="#ff0000"]s[/COLOR] du keine Ahnung davon hast, aber [COLOR="#ff0000"]bei[/COLOR] jedem[COLOR="#ff0000"] T[/COLOR]utorial das ich von dir lese kommt es mir
      so vor.

      Von deiner Rechtschreibung und Grammatik bekomme ich auch Augenkrebs...

      Wie schaffen Leute wie du eigentlich die Abschlussprüfung? Gibt es dort nicht massiven Abzug, wenn man in jeden Satz vier oder fünf Rechtschreibfehler haut und dazu eine... "experimentelle" Grammatik nutzt?
    • Klassen bringen aber trotzdem mehr als du denkst, so kannst du die ganze Logik des Players, der Gegner sowie der Bomben kapseln und hast weniger Arbeit, die Sachen in den Maincode einzubauen usw.


      Man kann sich drüber kloppen, aber ICH kapsele nur dann wenn ich es für wichtig halte(wenn es ganz alg methoden sind die ich noch öfters brauchen kann) spiel individuelles kommt bei mir in die main



      Und deine Antwort mit Content.Load zeigt mir, dass du:

      1. Nich wirklich Ahnung von Content.Load hast

      2. Meinen Beitrag nicht gelesen hast bzw nicht richtig

      Content.Load lädt einen Inhalt nur einmal und gibt ansonsten immer wieder einen Verweis auf das Ding zurück, das wär ja noch schöner, wenns wirklich jedes mal geladen wird, wenn mans brauch, also so dumm sind die XNA entwickler auch nicht, dass sie nicht etwas auf den Speicherverbrauch achten.


      Das ist jetzt pwinlich ich habs mit der quarz programmierung verwechselt



      Man kann Methoden definieren, der Code wird sauberer usw, was wird da unübersichtlich, wenn du mal schnell ne Klasse anlegst für ein Spielobjekt usw.

      Und wenn du schon sagst, dass alles initialisiert und abgefragt wird und dies nur "Ressourcen" und "Ram" kostet, dann halte dich bitte von C# sowie VB.net fern.

      Ich hasse es mich für einen kleinen logik fehler durch 15(hyperbel) dateien durchzuklicken wãhrend ich sonst den gesammten code auf einem haufen hab
      wenn überhaupt mache ich projekt unabhångige modele aber mehr auch nicht
    • Hey leute,
      ich programmiere ein bomberman und Map und Spielerklasse mit Kollision und alles habe ich.
      Nun meine Frage an euch ist, ich habe eine Basisklasse namen feature, von der leite ich später alle Features, wie bomben, laternen blablab^^... um den Spieler schneller und stärker oder so zu machen.

      Auf jeden Fall, habe ich die Featureklasse so gebaut:

      public abstract class Features
      {
      public Texture2D texture;
      public Rectangle dimension;
      public Rectangle position;
      public SoundState music_states;
      public Song song;
      public Timer timer;
      /// <summary>
      /// Standardcontructor
      /// </summary>
      public Features()
      {


      }
      public virtual void Push(/* The feature object */)
      {


      }
      public virtual void ClearFeature(/* The feature object*/)
      {


      }
      public virtual void EventSound(/* Song for Event */)
      {

      }
      }
      }
      Und ich will eine <hat eine beziehung zwischen Spieler und Bombe, denn der Spieler hat ja eine Bombe.

      und ich hatte eine Methode in der Playerklasse definiert die heisst: Placebomb, nur ich weiss nicht so recht, was der Code dieser Funktion können soll, mangels Verständnisprobleme,:

      private void placeBomb()
      {
      if (Keyboard.GetState().IsKeyDown(Keys.Enter))
      {
      myBomb.position = new Rectangle(player_rect.X + 30, player_rect.Y, 30, 30);
      }
      }
      public void Draw(SpriteBatch spritebatch)
      {
      myBomb.position = new Rectangle(player_rect.X + 30, player_rect.Y, 30, 30);
      spritebatch.Draw(player_Text, player_rect, Color.White);
      spritebatch.Draw(bomb_text, myBomb.position,new Rectangle(),Color.White);
      }
      Und ich rufe sie auch auf, aber wenn gedebuggt wird, dann passiert alles was passieren soll, nur wenn ich enter drücke, passiert nix keine Bombe.

      Und ich wollte euch fragen, wie würdet ihr so eine klasse definieren?

      ich entschuldige mich, nur ich habe iwie ein blackout was das