Alle Originalinhalte werden auf Ukrainisch erstellt. Noch nicht alle Inhalte wurden übersetzt. Einige Beiträge sind möglicherweise nur auf Ukrainisch verfügbar.Mehr erfahren

Wir schreiben das Demospiel Drones vs Zombies (Gosu / Ruby)

Beitrags-Cover: Wir schreiben das Demospiel Drones vs Zombies (Gosu / Ruby)
InhaltsverzeichnisKlicke auf den Link, um zur gewünschten Stelle zu navigieren
Dieser Inhalt wurde automatisch aus dem Ukrainischen übersetzt.
Ich habe bereits eine minimale Übersicht über die Funktionen der Bibliothek gosu geschrieben. Um ein einfaches 2D-Spiel zu erstellen, benötigt man tatsächlich nicht viel Code. Man kann auch auf grafische Elemente verzichten und einfache Formen (programmgemäß gezeichnet) verwenden. Für den Anfang (während des Lernens der Engine) sollte man das so machen, aber ein springendes Rechteck ist vielleicht nicht so cool wie etwas Gezeichnetes.
Ich habe kostenlose Icons (Attribution ist gemäß den Nutzungsbedingungen erforderlich) Freepik auf der Website Flaticon genommen. Grafiken kann man völlig kostenlos finden, selbst zeichnen, bestellen oder mit KI generieren. Generierte Inhalte können für den Entwicklungsprozess geeignet sein, aber für die Veröffentlichung in die Welt ist es dennoch besser, die Dienste von Künstlern in Anspruch zu nehmen und deren Wirtschaft und Kreativität zu unterstützen.
Nun zurück zum Thema dieses Beitrags - die Demo des Spiels Drones vs Zombies. Das Konzept ist recht einfach - mit einem Drohnen muss man Zombies zerstören, die versuchen, den Piloten zu erreichen. Die Demo ist nicht perfekt, zeigt aber gut, dass etwa 250 Zeilen Code und ein paar Bilder eine Idee/Konzeption des Spiels in eine Demo verwandeln können.
Der Code meiner Demo:
# Drones VS Zombies v.1.0.0

# Icons: https://www.flaticon.com/authors/freepik
# Code:  demo von memecode https://tseivo.com/b/memecode

require 'gosu'

class DroneGame < Gosu::Window
  WIDTH = 800
  HEIGHT = 600

  def initialize
    super(WIDTH, HEIGHT)
    self.caption = "Drones VS Zombies"
    reset_game
    @background_color = Gosu::Color.new(255, 85, 104, 50)
    @font = Gosu::Font.new(20)
    @paused = false
  end

  def update
    return if @game_over || @paused

    @drones.each(&:update)
    handle_explosions
    @drones.reject!(&:exploded?)
    spawn_drone if @drones.empty?

    @zombies.each(&:update)
    handle_zombie_movement
    handle_collisions
    @zombies.reject!(&:dead?)
    spawn_zombie if rand < 0.02
    check_game_over
  end

  def draw
    draw_quad(0, 0, @background_color, WIDTH, 0, @background_color, WIDTH, HEIGHT, @background_color, 0, HEIGHT, @background_color)
    @operator.draw
    @drones.each(&:draw)
    @zombies.each(&:draw)
    @font.draw_text("Punkte: #{@points}", 10, 10, 2)
    if @game_over
      @font.draw_text("Spiel Vorbei! Endpunktzahl: #{@points}", WIDTH / 2 - 100, HEIGHT / 2, 3, 1.0, 1.0, Gosu::Color::RED)
      @font.draw_text("Drücke Space um neu zu starten", WIDTH / 2 - 100, HEIGHT / 2 + 30, 3, 1.0, 1.0, Gosu::Color::WHITE)
    elsif @paused
      @font.draw_text("Pausiert", WIDTH / 2 - 50, HEIGHT / 2, 3, 1.0, 1.0, Gosu::Color::YELLOW)
      @font.draw_text("Drücke Esc um fortzufahren", WIDTH / 2 - 100, HEIGHT / 2 + 30, 3, 1.0, 1.0, Gosu::Color::WHITE)
    end
  end

  def button_down(id)
    case id
    when Gosu::KbReturn
      @drones.each(&:explode) unless @paused
    when Gosu::KbSpace
      reset_game if @game_over
    when Gosu::KbEscape
      @paused = !@paused unless @game_over
    end
  end

  private

  def handle_collisions
    @drones.each do |drone|
      # Überprüfen der Kollision mit dem Operator
      if drone.collides_with?(@operator) && !drone.exploded?
        drone.explode
        @game_over = true
        next
      end

      # Überprüfen der Kollision mit Zombies
      @zombies.each do |zombie|
        if drone.collides_with?(zombie) && !drone.exploded?
          zombie.hit
          drone.explode
          @points += 1
        end
      end
    end
  end

  def handle_explosions
    @drones.each do |drone|
      next unless drone.exploded?

      @zombies.reject! do |zombie|
        drone.collides_with?(zombie)
      end

      # Überprüfen der Kollision mit dem Operator nach der Explosion
      if drone.collides_with?(@operator)
        @game_over = true
      end
    end
  end

  def handle_zombie_movement
    @zombies.each do |zombie|
      zombie.move_towards(@operator.x, @operator.y)
    end
  end

  def spawn_zombie
    @zombies << Zombie.new
  end

  def spawn_drone
    @drones << Drone.new(@operator.x, @operator.y - 100)
  end

  def check_game_over
    @zombies.each do |zombie|
      if Gosu.distance(zombie.x, zombie.y, @operator.x, @operator.y) < 30
        @game_over = true
      end
    end
  end

  def reset_game
    @operator = Operator.new
    @drones = []
    @zombies = []
    @points = 0
    @game_over = false
    @paused = false
    spawn_drone
  end
end

class Operator
  attr_reader :x, :y, :size

  def initialize
    @x = DroneGame::WIDTH / 2
    @y = DroneGame::HEIGHT - 50
    @image = Gosu::Image.new("operator.png")
    @size = 100
  end

  def draw
    @image.draw(@x - @size / 2, @y - @size / 2, 1)
  end
end

class Drone
  attr_reader :x, :y, :exploded, :size

  def initialize(x, y)
    @x, @y = x, y
    @image = Gosu::Image.new("drone.png")
    @explosion_image = Gosu::Image.new("explosion.png")
    @exploded = false
    @size = 100
    @angle = 0  # Initialisiere den Winkel
    @explosion_timer = 0
  end

  def update
    return if @exploded

    @y -= 5 if Gosu.button_down?(Gosu::KbUp)
    @y += 5 if Gosu.button_down?(Gosu::KbDown)
    @x -= 5 if Gosu.button_down?(Gosu::KbLeft)
    @x += 5 if Gosu.button_down?(Gosu::KbRight)

    # Rotation
    @angle -= 5 if Gosu.button_down?(Gosu::KbLeft)
    @angle += 5 if Gosu.button_down?(Gosu::KbRight)

    # Grenzkontrolle
    @x = [[@x, 0].max, DroneGame::WIDTH].min
    @y = [[@y, 0].max, DroneGame::HEIGHT].min

    if @explosion_timer > 0
      @explosion_timer -= 1
    end
  end

  def draw
    if @exploded
      if @explosion_timer > 0
        @explosion_image.draw_rot(@x, @y, 1, @angle, 0.5, 0.5)
      end
    else
      @image.draw_rot(@x, @y, 1, @angle)
    end
  end

  def explode
    @exploded = true
    @explosion_timer = 550
  end

  def exploded?
    @exploded
  end

  def collides_with?(object)
    Gosu.distance(@x, @y, object.x, object.y) < (@size / 2 + object.size / 2)
  end
end

class Zombie
  attr_reader :x, :y, :size

  def initialize
    @x = rand * DroneGame::WIDTH
    @y = 0
    @image = Gosu::Image.new("zombie.png")
    @size = 100
    @speed = rand(0.05..0.2)
    @alive = true
  end

  def update
    return unless @alive
    @y += @speed
  end

  def draw
    @image.draw(@x - @size / 2, @y - @size / 2, 1)
  end

  def move_towards(target_x, target_y)
    if @y < target_y
      @y += @speed
    elsif @y > target_y
      @y -= @speed
    end
    if @x < target_x
      @x += @speed
    elsif @x > target_x
      @x -= @speed
    end
  end

  def hit
    die if Gosu.distance(@x, @y, DroneGame::WIDTH / 2, DroneGame::HEIGHT - 50) < 50
  end

  def die
    @alive = false
    @speed = 0
  end

  def dead?
    !@alive
  end
end

DroneGame.new.show
Fügen Sie die Bilder selbst hinzu (ich möchte das Urheberrecht nicht versehentlich verletzen):
  • drone.png
  • explosion.png
  • operator.png
  • zombie.png
Die Größe für jedes dieser Bilder sollte 100x100px (png mit Transparenz) sein.

Klasse DroneGame

  • Die Hauptklasse des Spiels, abgeleitet von Gosu::Window.
  • Initialisiert das Spiel-Fenster, setzt die Hintergrundfarbe und die Schriftart für Textelemente.
  • Enthält die Logik für die Aktualisierung des Spiels (update) und die Darstellung (draw), verarbeitet die Ereignisse der Tastenanschläge (button_down).

Klasse Operator

  • Stellt den Operator der Drohne dar.
  • Verantwortlich für seine Position auf dem Bildschirm und die Darstellung des Operatorbildes.

Klasse Drone

  • Stellt die Drohne dar, die für den Angriff verwendet wird.
  • Kann sich nach links, rechts, oben und unten bewegen, verarbeitet Explosionen (explode) und überprüft Kollisionen mit anderen Objekten.

Klasse Zombie

  • Stellt die Zombies dar, die den Operator angreifen.
  • Bewegt sich in Richtung des Operators, kann von Drohnen getroffen werden, was zu ihrer Zerstörung führt.

Hauptfunktionen

  • Start und Neustart des Spiels: Das Spiel beginnt mit dem Spawn des Operators und der Drohnen, die ihn schützen. Nach einer Niederlage (wenn die Zombies den Operator erreichen), kann der Spieler das Spiel durch Drücken der Leertaste (Space) neu starten.
  • Dynamische Objekte: Drohnen und Zombies haben eigene Objekte, die ihre Bewegung und ihren Zustand aktualisieren.
  • Kollisionen und Explosionen: Logik zur Verarbeitung von Kollisionen zwischen Drohnen, Zombies und dem Operator sowie Explosionen von Drohnen, die zur Zerstörung von Zombies und zum Ende des Spiels führen.
Als nächstes möchte ich Geräusche hinzufügen, Gräber für Zombies nach ihrer Zerstörung zeichnen, die Bewegung/Steuerung der Drohne verbessern (derzeit dreht sie sich um ihre Achse), eine Animation der Drohnenpropeller erstellen usw. Ich habe beschlossen, die Demos Schritt für Schritt zu veröffentlichen, da das Schreiben aller gewünschten Dinge sehr viel Zeit in Anspruch nimmt.
Дрон вбив оператора :(
Дрон вбив оператора :(
Zum Beispiel habe ich vor der Veröffentlichung dieses Beitrags ein paar Dinge hinzugefügt:
  • Der Operator der Drohne kann sich versehentlich selbst mit der Drohne zerstören
  • Ich habe Grenzen für das Schlachtfeld hinzugefügt (zuvor konnte die Drohne aus dem Fenster fliegen und sich sozusagen verlieren)

Dieser Beitrag hat noch keine Ergänzungen vom Autor.

[Ruby] Was unterscheidet Variablen, die mit @, @@ und $ beginnen?
23. Jun, 14:00 Uhr

[Ruby] Was unterscheidet Variablen, die mit @, @@ und $ beginnen?

meme code
meme code@memecode
Was ist eine Funktion in der Programmierung?
24. Jun, 18:15 Uhr

Was ist eine Funktion in der Programmierung?

meme code
meme code@memecode
[Fix] extconf.rb ist bei der Installation der Ruby-Bibliothek Gosu fehlgeschlagen
27. Jun, 16:38 Uhr

[Fix] extconf.rb ist bei der Installation der Ruby-Bibliothek Gosu fehlgeschlagen

meme code
meme code@memecode
Wie macht man einen leeren Git-Commit?
28. Jun, 08:33 Uhr

Wie macht man einen leeren Git-Commit?

meme code
meme code@memecode
Ruby-Bibliothek Gosu zur Erstellung von 2D-Spielen
29. Jun, 08:48 Uhr

Ruby-Bibliothek Gosu zur Erstellung von 2D-Spielen

meme code
meme code@memecode
Gosu Ruby Tutorial - пройдемось по офіційній документації
03. Jul, 11:50 Uhr

Gosu Ruby Tutorial - пройдемось по офіційній документації

meme code
meme code@memecode
Wie behebt man einen Windows-Absturz, der durch CrowdStrike verursacht wurde?
19. Jul, 13:53 Uhr

Wie behebt man einen Windows-Absturz, der durch CrowdStrike verursacht wurde?

meme code
meme code@memecode
Was bedeutet .map(&:name) in Ruby?
28. Jul, 11:18 Uhr

Was bedeutet .map(&:name) in Ruby?

meme code
meme code@memecode
Wie funktioniert die map-Methode in Ruby? Eine Übersicht über die Funktionsweise der Methode mit Beispielen
30. Jul, 07:33 Uhr

Wie funktioniert die map-Methode in Ruby? Eine Übersicht über die Funktionsweise der Methode mit Beispielen

meme code
meme code@memecode
Was bedeutet der Punkt am Anfang einer Datei (.gitignore, .DS_Store, .bashrc usw.)?
02. Aug, 13:15 Uhr

Was bedeutet der Punkt am Anfang einer Datei (.gitignore, .DS_Store, .bashrc usw.)?

meme code
meme code@memecode
Was ist .gitignore? Wozu dient es und wie verwendet man es?
02. Aug, 14:58 Uhr

Was ist .gitignore? Wozu dient es und wie verwendet man es?

meme code
meme code@memecode
Wie entfernt man die .DS_Store-Datei aus einem Git-Repository?
02. Aug, 19:34 Uhr

Wie entfernt man die .DS_Store-Datei aus einem Git-Repository?

meme code
meme code@memecode