引言
相信大多数人在小时候都或多或少玩过许多款游戏,当我们第一次接触编程时,心中想到的第一件事情可能也是开发一款非常酷的游戏,可以分享给我们的家人、同学和朋友。
倘若没有现成的框架或足够的学习资料时,常人是难以开发出一款带有高级特效的游戏。现在,学完了Python
这门编程语言,结合强大且丰富的Python
社区,使得我们制作优秀电脑游戏比以往容易得多。
在本教程中,我们将带你探索几款热门的基于Python
的游戏引擎,带领大家学习如何制作自己的第一款Python
小游戏!
本文的大纲目录如下:
-
了解现如今几款流行的 Python
游戏引擎的优缺点 -
了解这些游戏引擎的运行情况 -
了解它们与独立游戏引擎的区别 -
了解其他可用的 Python
游戏引擎
Source: Top Python Game Engines
Author: Jon Fincher
Date: May 04, 2022
Python Game Engines Overview
Python
游戏引擎通常以Python
库的形式呈现给大家,因此可以以多种方式进行安装。大多数都可以在PyPI
上使用,并且可以通过pip
工具进行安装。然而,有一些只能在GitHub
、GitLab
或其他代码托管仓库上使用,而且它们可能需要其他安装步骤。本文将介绍几个常用游戏引擎的安装方法。
Python
是一种通用编程语言,除了编写电脑游戏外,它还被用于各种任务。相比之下,有许多不同的独立游戏引擎是专门为编写游戏而定制的。其中包括:
-
The Unreal Engine -
Unity -
Godot
这些独立的游戏引擎与Python
游戏引擎的几个关键区别点在于:
语言支持
C++、C#和JavaScript等语言在独立游戏引擎中很受欢迎,因为引擎本身通常是用这些语言编写的。很少有独立引擎支持Python
。
专有脚本支持
此外,许多独立的游戏引擎维护和支持自己的脚本语言,这可能与Python
不同。例如,Unity
原生使用C#
,而Unreal
最适合使用C++
。
平台支持
许多现代的独立游戏引擎能够为各种平台(包括手机和专用游戏系统)制作游戏,而无需复杂的程序。相比之下,将Python
游戏移植到不同平台,特别是移动端平台,可能是一项艰巨的任务。
授权选项
基于所使用的引擎,使用独立游戏引擎编写的游戏可能有不同的授权选项和限制。
那么为什么我们还要用Python
来编写游戏呢?其中一个很重要的原因便是使用独立游戏引擎通常需要你学习一种新的编程或脚本语言,即学习成本很高。而Python
游戏引擎只需要你捡起现有的Python
基础知识便可以完成许多游戏demo
的开发,降低学习难度,让你快速入门。
Python
环境中有许多好用的游戏引擎,这里的优势主要是指以下几点:
-
社区活跃 -
持续维护 -
文档丰富
下面,我们将按照下述步骤介绍每个游戏引擎:
-
安装方法 -
基础概念 -
主要功能 -
代码实现
Pygame
所有接触过Python
编程的人,第一个能想到的游戏引擎应该就是Pygame
。事实上,在Real Python中已经有一个关于Pygame的很好的入门教程,强烈推荐大家关注学习!后续我们也会同步更新相关的教程呈现给大家。
Pygame
是作为被搁置的PySDL
库的替换而编写的,它封装并扩展了SDL
库,SDL
是Simple DirectMedia Layer
的缩写。SDL
提供对系统底层多媒体硬件组件(如声音、视频、鼠标、键盘和操纵杆)的跨平台访问。SDL
和Pygame
的跨平台特性意味着你可以为支持它们的每个平台编写游戏和丰富的多媒体Python
程序!
Pygame Installation
Pygame
在PyPI
上可用,因此在创建并激活虚拟环境后,可以使用适当的pip
命令安装它:
$ python -m pip install pygame
完成之后,你可以通过运行该库附带的例子来验证安装是否成功:
python -m pygame.examples.aliens
现在你已经安装了Pygame
,你可以立即开始使用它。如果在安装过程中遇到问题,那么入门指南将为你提供一切尽可能的解决方案。
Basic Concepts
Pygame
被组织成几个不同的模块,它们提供对计算机图形、声音和输入硬件的抽象访问。Pygame还定义了许多类,这些类封装了与硬件无关的概念。例如,绘图是在Surface
对象上完成的,其矩形限制由其Rect
对象定义。
每款游戏都利用游戏循环来控制游戏玩法。这个循环会随着游戏的进展而不断迭代。Pygame
提供了实现游戏循环的方法和函数,但它不自动提供。游戏作者需要实现游戏循环的功能。
游戏循环的每次迭代被称为一个框架。每一帧,游戏执行四
个重要动作:
-
处理用户输入。
Pygame
中的用户输入是使用事件模型处理的。鼠标和键盘输入生成事件,可以根据需要读取和处理事件,也可以忽略事件。Pygame
本身不提供任何事件处理程序。 -
更新游戏对象的状态。游戏对象可以使用任何
Pygame
数据结构或特殊的Pygame
类表示。可以在Python
中创建和扩展精灵、图像、字体和颜色等对象,以提供尽可能多的必要状态信息。 -
更新显示和音频输出。
Pygame
提供对显示和声音硬件的抽象访问。显示器、混音器和音乐模块允许游戏作者在游戏设计和执行方面的灵活性。 -
保持游戏的速度。
Pygame
的时间模块允许游戏作者控制游戏速度。通过确保每个帧在指定的时间限制内完成,游戏作者可以确保游戏在不同的硬件上运行相似。
Basic Application
首先,让我们新建一个Pygame
程序pygame_basic.py
,在屏幕上绘制了一些图形和一些文本:
实现上述窗口及功能对应的代码片段如下:
"""
Basic "Hello, World!" program in Pygame
This program is designed to demonstrate the basic capabilities
of Pygame. It will:
- Create a game window
- Fill the background with white
- Draw some basic shapes in different colors
- Draw some text in a specified size and color
- Allow you to close the window
"""
# Import and initialize the pygame library
import pygame
pygame.init()
# Set the width and height of the output window, in pixels
WIDTH = 800
HEIGHT = 600
# Set up the drawing window
screen = pygame.display.set_mode([WIDTH, HEIGHT])
# Run until the user asks to quit
running = True
while running:
# Did the user click the window close button?
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Fill the background with white
screen.fill((255, 255, 255))
# Draw a blue circle with a radius of 50 in the center of the screen
pygame.draw.circle(screen, (0, 0, 255), (WIDTH // 2, HEIGHT // 2), 50)
# Draw a red-outlined square in the top-left corner of the screen
red_square = pygame.Rect((50, 50), (100, 100))
pygame.draw.rect(screen, (200, 0, 0), red_square, 1)
# Draw an orange caption along the bottom in 60-point font
text_font = pygame.font.SysFont("any_font", 60)
text_block = text_font.render(
"Hello, World! From Pygame", False, (200, 100, 0)
)
screen.blit(text_block, (50, HEIGHT - 50))
# Flip the display
pygame.display.flip()
# Done! Time to quit.
pygame.quit()
尽管它的功能很简单,但即使是这个基本的
Pygame
程序也需要一个游戏循环和事件处理程序。游戏循环从27
行开始,由运行变量控制。将此变量设置为False
将结束程序。事件处理从第
30
行开始,带有一个事件循环。使用pygame.event.get()
从队列中检索事件,并在每次循环迭代期间一次处理一个事件。在本例中,唯一要处理的事件是pygame
事件,当用户关闭游戏窗口时生成。当处理此事件时,设置running = False
,这将最终结束游戏循环和程序。
Pygame
提供了各种绘制基本形状的方法,如圆形和矩形。在这个示例中,第38
行上画了一个蓝色的圆,第41
和42
行上画了一个红色的正方形。注意,绘制矩形需要首先创建一个Rect
对象。在屏幕上绘制文本稍微复杂一些。首先,在第
45
行,选择一种字体并创建一个字体对象。在第46
到48
行使用该字体,调用.render()
方法进行渲染。这将创建一个包含以指定字体和颜色呈现的文本的Surface
对象。最后,使用第49
行中的.blit()
方法将Surface
复制到屏幕上。游戏循环的结束发生在第
52
行,当之前绘制的所有内容都显示在显示器上时。如果没有这一行,就不会显示任何内容。Advanced Application
当然,
Pygame
的设计初衷是用Python
编写游戏。为了探索一个真正的Pygame
游戏的功能和需求,我们尝试用Pygame编写一个小游戏,包含以下细节:
-
玩家是屏幕上的一个精灵,通过移动鼠标进行控制。 -
每隔一定的时间,硬币就会一个接一个地出现在屏幕上。 -
当玩家移动到每一枚硬币上时,它就会消失,玩家将获得10分。 -
随着游戏的发展,玩家会更快地添加金币。 -
当屏幕上出现十多个硬币时,游戏结束。
完成后,游戏看起来会是这样的:
完整的代码如下:
"""
Complete Game in Pygame
This game demonstrates some of the more advanced features of
Pygame, including:
- Using sprites to render complex graphics
- Handling user mouse input
- Basic sound output
"""
# Import and initialize the pygame library
import pygame
# To randomize coin placement
from random import randint
# To find your assets
from pathlib import Path
# For type hinting
from typing import Tuple
# Set the width and height of the output window, in pixels
WIDTH = 800
HEIGHT = 600
# How quickly do you generate coins? Time is in milliseconds
coin_countdown = 2500
coin_interval = 100
# How many coins can be on the screen before you end?
COIN_COUNT = 10
# Define the Player sprite
class Player(pygame.sprite.Sprite):
def __init__(self):
"""Initialize the player sprite"""
super(Player, self).__init__()
# Get the image to draw for the player
player_image = str(
Path.cwd() / "pygame" / "images" / "alien_green_stand.png"
)
# Load the image, preserve alpha channel for transparency
self.surf = pygame.image.load(player_image).convert_alpha()
# Save the rect so you can move it
self.rect = self.surf.get_rect()
def update(self, pos: Tuple):
"""Update the position of the player
Arguments:
pos {Tuple} -- the (X,Y) position to move the player
"""
self.rect.center = pos
# Define the Coin sprite
class Coin(pygame.sprite.Sprite):
def __init__(self):
"""Initialize the coin sprite"""
super(Coin, self).__init__()
# Get the image to draw for the coin
coin_image = str(Path.cwd() / "pygame" / "images" / "coin_gold.png")
# Load the image, preserve alpha channel for transparency
self.surf = pygame.image.load(coin_image).convert_alpha()
# The starting position is randomly generated
self.rect = self.surf.get_rect(
center=(
randint(10, WIDTH - 10),
randint(10, HEIGHT - 10),
)
)
# Initialize the Pygame engine
pygame.init()
# Set up the drawing window
screen = pygame.display.set_mode(size=[WIDTH, HEIGHT])
# Hide the mouse cursor
pygame.mouse.set_visible(False)
# Set up the clock for a decent frame rate
clock = pygame.time.Clock()
# Create a custom event for adding a new coin
ADDCOIN = pygame.USEREVENT + 1
pygame.time.set_timer(ADDCOIN, coin_countdown)
# Set up the coin_list
coin_list = pygame.sprite.Group()
# Initialize the score
score = 0
# Set up the coin pickup sound
coin_pickup_sound = pygame.mixer.Sound(
str(Path.cwd() / "pygame" / "sounds" / "coin_pickup.wav")
)
# Create a player sprite and set its initial position
player = Player()
player.update(pygame.mouse.get_pos())
# Run until you get to an end condition
running = True
while running:
# Did the user click the window close button?
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Should you add a new coin?
elif event.type == ADDCOIN:
# Create a new coin and add it to the coin_list
new_coin = Coin()
coin_list.add(new_coin)
# Speed things up if fewer than three coins are on-screen
if len(coin_list) < 3:
coin_countdown -= coin_interval
# Need to have some interval
if coin_countdown < 100:
coin_countdown = 100
# Stop the previous timer by setting the interval to 0
pygame.time.set_timer(ADDCOIN, 0)
# Start a new timer
pygame.time.set_timer(ADDCOIN, coin_countdown)
# Update the player position
player.update(pygame.mouse.get_pos())
# Check if the player has collided with a coin, removing the coin if so
coins_collected = pygame.sprite.spritecollide(
sprite=player, group=coin_list, dokill=True
)
for coin in coins_collected:
# Each coin is worth 10 points
score += 10
# Play the coin collected sound
coin_pickup_sound.play()
# Are there too many coins on the screen?
if len(coin_list) >= COIN_COUNT:
# This counts as an end condition, so you end your game loop
running = False
# To render the screen, first fill the background with pink
screen.fill((255, 170, 164))
# Draw the coins next
for coin in coin_list:
screen.blit(coin.surf, coin.rect)
# Then draw the player
screen.blit(player.surf, player.rect)
# Finally, draw the score at the bottom left
score_font = pygame.font.SysFont("any_font", 36)
score_block = score_font.render(f"Score: {score}", False, (0, 0, 0))
screen.blit(score_block, (50, HEIGHT - 50))
# Flip the display to make everything appear
pygame.display.flip()
# Ensure you maintain a 30 frames per second rate
clock.tick(30)
# Done! Print the final score
print(f"Game over! Final score: {score}")
# Make the mouse visible again
pygame.mouse.set_visible(True)
# Quit the game
pygame.quit()
Pygame
中的精灵提供了一些基本功能,但它们被设计成子类,而不是单独使用。Pygame
精灵在默认情况下没有与它们相关的图像,它们不能自己定位。为了正确地绘制和管理屏幕上的玩家和硬币,在第
35
至55
行创建了一个player
类,在第58
至75
行创建了一个Coin
类。当每个精灵对象被创建时,它首先定位并加载它将显示的图像,并将其保存在self.surf
中。self.rect
属性用于定位并移动屏幕上的精灵。定时在屏幕上添加硬币是通过计时器完成的。在·Pygame·中,每当计时器过期时就会触发事件,游戏开发者可以将自己的事件定义为整数常量。
ADDCOIN
事件在第90
行上定义,计时器在第91
行上的coin_countdown
毫秒后触发该事件。因为
ADDCOIN
是一个事件,所以需要在事件循环中处理它,这发生在第118
行到134
行。该事件创建一个新的Coin
对象并将其添加到现有的coin_list
中。检查屏幕上的硬币数量。如果少于3
个,则减少coin_countdown
。最后,停止前一个计时器,开始一个新的计时器。当玩家移动时,他们会与硬币碰撞,并收集它们。这将自动从
coin_list
中删除收集到的每个硬币。这也会更新乐谱并播放声音。玩家移动发生在第
137
行。在第140
至142
行检查与屏幕上硬币的碰撞。dokill=True
参数自动从coin_list
中删除硬币。最后,第143
行到147
行更新分数并播放收集到的每个硬币的声音。当用户关闭窗口,或者当屏幕上有超过
10
个硬币时,游戏就结束了。在第150
行到152
行检查是否有超过10
个硬币。因为
Pygame
精灵没有内置的图像知识,它们也不知道如何在屏幕上绘制自己。游戏作者需要清除屏幕,以正确的顺序绘制所有精灵,绘制屏幕得分,然后.flip()
显示所有内容。这一切都发生在第155
到170
行。
总的来说,
Pygame
是一个非常强大和完善的库,但它也有缺点。实现基本的精灵行为和实现游戏循环和基本事件处理程序等关键游戏需求取决于游戏作者。接下来,你将看到其他游戏引擎如何在减少工作量的同时提供类似的结果。今天将为大家介绍到这里,后续我们将会以相同的案例为大家介绍其它几款游戏引擎,包括
Pygame Zero
、Arcade
、adventurelib
和Ren’Py
,大家可以综合比较一下。敬请期待,下期不见不散。往期回顾 【Python项目实战】网页爬取(上)
【Python项目实战】网页爬取(中)
【Python项目实战】网页爬取(下)
Python-Turtle库-从入门到精通
【不可不知系列】编译器|编辑器|集成开发环境的区别和联系
原文始发于微信公众号(Pytrick):【Python项目实战】主流游戏引擎(上)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/56399.html