Heim  >  Artikel  >  Backend-Entwicklung  >  Erstellen interaktiver Spiele mit Python 3 und Pygame: Teil 4

Erstellen interaktiver Spiele mit Python 3 und Pygame: Teil 4

WBOY
WBOYOriginal
2023-08-27 15:01:141264Durchsuche

使用 Python 3 和 Pygame 创建互动游戏:第 4 部分

Übersicht

Dies ist der vierte Teil einer fünfteiligen Tutorial-Reihe zum Erstellen von Spielen mit Python 3 und Pygame. Im dritten Teil haben wir uns mit dem Kern von Breakout befasst, gelernt, wie man mit Ereignissen umgeht, einen Blick auf die wichtigsten Breakout-Klassen geworfen und gesehen, wie man verschiedene Spielobjekte bewegt.

In diesem Teil lernen wir, wie man Kollisionen erkennt und was passiert, wenn der Ball auf verschiedene Objekte wie Paddel, Ziegel, Wände, Decken und Böden trifft. Abschließend besprechen wir wichtige Themen der Spiel-Benutzeroberfläche, insbesondere die Erstellung von Menüs mit unseren eigenen benutzerdefinierten Schaltflächen.

Kollisionserkennung

Im Spiel kollidieren Dinge miteinander. Der Durchbruch ist keine Ausnahme. Meistens ist es so, dass der Ball etwas trifft. handle_ball_collisions() 方法有一个嵌套函数,名为 intersect(), wird verwendet, um zu testen, ob der Ball ein Objekt trifft und wo er das Objekt trifft. Wenn der Ball das Objekt verfehlt, wird „Links“, „Rechts“, „Oben“, „Unten“ oder „Keine“ zurückgegeben.

def handle_ball_collisions(self):
    def intersect(obj, ball):
        edges = dict(
            left=Rect(obj.left, obj.top, 1, obj.height),
            right=Rect(obj.right, obj.top, 1, obj.height),
            top=Rect(obj.left, obj.top, obj.width, 1),
            bottom=Rect(obj.left, obj.bottom, obj.width, 1))
        collisions = set(edge for edge, rect in edges.items() if
                         ball.bounds.colliderect(rect))
        if not collisions:
            return None

        if len(collisions) == 1:
            return list(collisions)[0]

        if 'top' in collisions:
            if ball.centery >= obj.top:
                return 'top'
            if ball.centerx < obj.left:
                return 'left'
            else:
                return 'right'

        if 'bottom' in collisions:
            if ball.centery >= obj.bottom:
                return 'bottom'
            if ball.centerx < obj.left:
                return 'left'
            else:
                return 'right'

Schlag den Ball mit dem Schläger

Wenn der Ball den Schläger trifft, springt er weg. Wenn es auf die Oberseite des Paddels trifft, prallt es zurück, behält aber die gleiche horizontale Geschwindigkeitskomponente bei.

Wenn es jedoch auf eine Seite des Paddels trifft, springt es auf die andere Seite (nach links oder rechts) und setzt seine Abwärtsbewegung fort, bis es den Boden berührt. Dieser Code verwendet die Intersect-Funktion().

# Hit paddle
s = self.ball.speed
edge = intersect(self.paddle, self.ball)
if edge is not None:
    self.sound_effects['paddle_hit'].play()
if edge == 'top':
	speed_x = s[0]
	speed_y = -s[1]
	if self.paddle.moving_left:
		speed_x -= 1
	elif self.paddle.moving_left:
		speed_x += 1
	self.ball.speed = speed_x, speed_y
elif edge in ('left', 'right'):
	self.ball.speed = (-s[0], s[1])

Landung

Wenn der Schläger den Ball auf dem Weg nach unten verfehlt (oder der Ball die Seite des Schlägers trifft), fällt der Ball weiter und landet schließlich auf dem Boden. An diesem Punkt verliert der Spieler ein Leben und der Ball wird wiederhergestellt, sodass das Spiel fortgesetzt werden kann. Das Spiel endet, wenn der Spieler keine Leben mehr hat.

# Hit floor
if self.ball.top > c.screen_height:
    self.lives -= 1
	if self.lives == 0:
		self.game_over = True
	else:
		self.create_ball()

Stöße gegen Decken und Wände

Wenn der Ball eine Wand oder Decke trifft, springt er einfach zurück.

# Hit ceiling
if self.ball.top < 0:
    self.ball.speed = (s[0], -s[1])

# Hit wall
if self.ball.left < 0 or self.ball.right > c.screen_width:
	self.ball.speed = (-s[0], s[1])

Brick Break

Wenn der Ball einen Stein trifft, ist das ein großes Ereignis in Breakout – der Stein verschwindet, der Spieler erhält einen Punkt, der Ball springt zurück und ein paar andere Dinge passieren (Soundeffekte und möglicherweise Spezialeffekte), die ich besprechen werde das später.

Um festzustellen, ob ein Stein getroffen wurde, prüft der Code, ob irgendwelche Steine ​​den Ball kreuzen:

# Hit brick
for brick in self.bricks:
    edge = intersect(brick, self.ball)
	if not edge:
		continue

	self.bricks.remove(brick)
	self.objects.remove(brick)
	self.score += self.points_per_brick

	if edge in ('top', 'bottom'):
		self.ball.speed = (s[0], -s[1])
	else:
		self.ball.speed = (-s[0], s[1])

Programmieren Sie das Spielmenü

Die meisten Spiele haben eine Art Benutzeroberfläche. Breakout verfügt über ein einfaches Menü mit zwei Schaltflächen: „PLAY“ und „QUIT“. Dieses Menü erscheint, wenn das Spiel beginnt, und verschwindet, wenn der Spieler auf „Start“ klickt. Sehen wir uns an, wie Schaltflächen und Menüs implementiert sind und wie sie sich in das Spiel integrieren.

Schaltfläche „Erstellen“

Pygame verfügt nicht über eine integrierte UI-Bibliothek. Es gibt Erweiterungen von Drittanbietern, aber ich habe beschlossen, meine eigene Schaltfläche für das Menü zu erstellen. Schaltflächen sind Spielobjekte mit drei Zuständen: normal, schwebend und gedrückt. Der Normalzustand liegt vor, wenn sich die Maus nicht über der Schaltfläche befindet, und der Hover-Zustand liegt vor, wenn sich die Maus über der Schaltfläche befindet, die linke Maustaste jedoch nicht gedrückt wird. Der gedrückte Zustand liegt vor, wenn sich die Maus über der Schaltfläche befindet und der Spieler die linke Maustaste drückt.

Die Schaltfläche ist als Rechteck mit einer Hintergrundfarbe und darauf angezeigtem Text implementiert. Die Schaltfläche erhält außerdem eine on_click-Funktion (standardmäßig eine Noop-Lambda-Funktion), die aufgerufen wird, wenn auf die Schaltfläche geklickt wird.

import pygame

from game_object import GameObject
from text_object import TextObject
import config as c


class Button(GameObject):
    def __init__(self, 
                 x, 
                 y, 
                 w, 
                 h, 
                 text, 
                 on_click=lambda x: None, 
                 padding=0):
        super().__init__(x, y, w, h)
        self.state = 'normal'
        self.on_click = on_click

        self.text = TextObject(x + padding, 
                               y + padding, lambda: text, 
                               c.button_text_color, 
                               c.font_name, 
                               c.font_size)

    def draw(self, surface):
        pygame.draw.rect(surface, 
                         self.back_color, 
                         self.bounds)
        self.text.draw(surface)

Schaltflächen verarbeiten ihre eigenen Mausereignisse und ändern ihren internen Status basierend auf diesen Ereignissen. Beim Drücken der Taste wird die MOUSEBUTTONUP 事件,表示玩家点击了按钮,并调用 on_click()-Funktion empfangen.

def handle_mouse_event(self, type, pos):
    if type == pygame.MOUSEMOTION:
		self.handle_mouse_move(pos)
	elif type == pygame.MOUSEBUTTONDOWN:
		self.handle_mouse_down(pos)
	elif type == pygame.MOUSEBUTTONUP:
		self.handle_mouse_up(pos)

def handle_mouse_move(self, pos):
	if self.bounds.collidepoint(pos):
		if self.state != 'pressed':
			self.state = 'hover'
	else:
		self.state = 'normal'

def handle_mouse_down(self, pos):
	if self.bounds.collidepoint(pos):
		self.state = 'pressed'

def handle_mouse_up(self, pos):
	if self.state == 'pressed':
		self.on_click(self)
		self.state = 'hover'

Die back_color-Eigenschaft, die zum Zeichnen des Hintergrundrechtecks ​​verwendet wird, gibt immer eine Farbe zurück, die dem aktuellen Status der Schaltfläche entspricht, sodass der Spieler deutlich erkennen kann, dass die Schaltfläche aktiv ist:

@property
def back_color(self):
    return dict(normal=c.button_normal_back_color,
                hover=c.button_hover_back_color,
                pressed=c.button_pressed_back_color)[self.state]

Menü erstellen

create_menu() 函数创建一个带有两个按钮的菜单,其中包含文本“PLAY”和“QUIT”。它有两个嵌套函数,名为 on_play()on_quit() ,它提供给相应的按钮。每个按钮都添加到 objects 列表(待绘制)以及 menu_buttons Felder.

def create_menu(self):
    for i, (text, handler) in enumerate((('PLAY', on_play), 
                                         ('QUIT', on_quit))):
        b = Button(c.menu_offset_x,
                   c.menu_offset_y + (c.menu_button_h + 5) * i,
                   c.menu_button_w,
                   c.menu_button_h,
                   text,
                   handler,
                   padding=5)
        self.objects.append(b)
        self.menu_buttons.append(b)
        self.mouse_handlers.append(b.handle_mouse_event)

Wenn auf die PLAY-Schaltfläche geklickt wird, wird on_play() aufgerufen, das von objects 列表中删除按钮,这样就不再绘制它们了。此外,触发游戏开始的布尔字段 is_game_runningstart_level auf True gesetzt wird.

Auf „True“ setzen, wenn auf die Schaltfläche „Beenden“ geklickt wird, wodurch die letzte Spielsequenz ausgelöst wird. is_game_running 设置为 False (有效暂停游戏)并且 game_over

def on_play(button):
    for b in self.menu_buttons:
		self.objects.remove(b)

	self.is_game_running = True
	self.start_level = True

def on_quit(button):
	self.game_over = True
	self.is_game_running = False

Spielmenü anzeigen und ausblenden

Das Ein- und Ausblenden von Menüs ist implizit. Wenn sich die Schaltflächen in der

-Liste befinden, ist das Menü sichtbar; wenn sie entfernt werden, wird es ausgeblendet. So einfach ist das. objects

Es ist möglich, ein verschachteltes Menü mit einer eigenen Oberfläche zu erstellen, die Unterkomponenten wie Schaltflächen darstellt, und diese Menükomponente dann einfach hinzuzufügen/zu entfernen, aber dieses einfache Menü benötigt das nicht.

Fazit

In diesem Abschnitt behandeln wir die Kollisionserkennung und was passiert, wenn der Ball auf verschiedene Objekte wie Paddel, Ziegel, Wände, Decken und Böden trifft. Darüber hinaus haben wir ein eigenes Menü mit benutzerdefinierten Schaltflächen erstellt, die je nach Befehl ein- und ausgeblendet werden.

In diesem letzten Teil der Serie werfen wir einen Blick auf das letzte Spiel und legen dabei großen Wert auf Spielstände und Leben, Soundeffekte und Musik.

Dann werden wir ein komplexes Spezialeffektsystem entwickeln, um das Spiel interessanter zu machen. Abschließend besprechen wir zukünftige Richtungen und mögliche Verbesserungen.

Das obige ist der detaillierte Inhalt vonErstellen interaktiver Spiele mit Python 3 und Pygame: Teil 4. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn