Python 是一种非常适合编程初学者的语言,并且非常适合任何想要“完成工作”而不花费大量时间在样板代码上的人。Arcade 是一个 Python 库,用于创建 2D 视频游戏,它易于上手,并且随着您经验的积累,功能非常强大。在本文中,我将解释如何开始使用 Python 和 Arcade 编程视频游戏。
在使用 PyGame 库教授学生之后,我开始了 Arcade 的开发。我使用 PyGame 进行了近 10 年的面对面教学,并且我开发了 ProgramArcadeGames.com 用于在线教学。PyGame 很棒,但最终我觉得我浪费时间在弥补 从未修复的错误。
我担心教授像 事件循环 这样的东西,这已经不是我们编码的方式了。我有一个 整个章节,我在其中解释了为什么 y 坐标是颠倒的。因为 PyGame 很少更新,并且它基于旧的 SDL 1 库,而不是像更现代的 OpenGL 这样的东西,所以我对它的未来没有抱太大希望。
我想要一个更易于使用、更强大且使用 Python 3 的一些新特性的库,例如装饰器和类型提示。Arcade 就是它。这就是如何开始使用它。
安装
Arcade,像许多其他软件包一样,可以通过 PyPi 获得,这意味着您可以使用 pip
命令(或 pipenv 命令)安装 Arcade。如果您已经安装了 Python,您可能只需打开 Windows 上的命令提示符并输入
pip install arcade
或者在 MacOS 和 Linux 上输入
pip3 install arcade
有关更详细的安装说明,您可以参考 Arcade 安装文档。
简单绘图
您只需几行代码即可打开窗口并创建简单的图形。让我们创建一个示例,绘制一个笑脸,如下图所示

下面的脚本展示了如何使用 Arcade 的绘图命令 来做到这一点。请注意,您不需要知道如何使用类甚至定义函数。对于任何想要开始学习编程的人来说,使用快速视觉反馈进行编程非常棒。
import arcade
# Set constants for the screen size
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
# Open the window. Set the window title and dimensions (width and height)
arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing Example")
# Set the background color to white.
# For a list of named colors see:
# http://arcade.academy/arcade.color.html
# Colors can also be specified in (red, green, blue) format and
# (red, green, blue, alpha) format.
arcade.set_background_color(arcade.color.WHITE)
# Start the render process. This must be done before any drawing commands.
arcade.start_render()
# Draw the face
x = 300
y = 300
radius = 200
arcade.draw_circle_filled(x, y, radius, arcade.color.YELLOW)
# Draw the right eye
x = 370
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)
# Draw the left eye
x = 230
y = 350
radius = 20
arcade.draw_circle_filled(x, y, radius, arcade.color.BLACK)
# Draw the smile
x = 300
y = 280
width = 120
height = 100
start_angle = 190
end_angle = 350
arcade.draw_arc_outline(x, y, width, height, arcade.color.BLACK, start_angle, end_angle, 10)
# Finish drawing and display the result
arcade.finish_render()
# Keep the window open until the user hits the 'close' button
arcade.run()
使用函数
当然,在全局上下文中编写代码不是好的形式。值得庆幸的是,通过使用函数来改进您的程序很容易。在这里,我们可以看到一个使用函数在特定 (x, y) 位置绘制松树的示例
def draw_pine_tree(x, y):
""" This function draws a pine tree at the specified location. """
# Draw the triangle on top of the trunk.
# We need three x, y points for the triangle.
arcade.draw_triangle_filled(x + 40, y, # Point 1
x, y - 100, # Point 2
x + 80, y - 100, # Point 3
arcade.color.DARK_GREEN)
# Draw the trunk
arcade.draw_lrtb_rectangle_filled(x + 30, x + 50, y - 100, y - 140,
arcade.color.DARK_BROWN)
有关完整示例,请参阅 使用函数绘图。

经验更丰富的程序员会知道,现代图形程序首先将绘图信息加载到图形卡上,然后要求图形卡稍后批量绘制。Arcade 也支持这一点。单独绘制 10,000 个矩形大约需要 0.800 秒。批量绘制它们所用的时间不到 0.001 秒。
Window 类
较大的程序通常会从 Window 类派生,或者 使用装饰器。这允许程序员编写代码来处理绘图、更新和处理来自用户的输入。下面是基于 Window
的程序的启动模板。
import arcade
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
class MyGame(arcade.Window):
""" Main application class. """
def __init__(self, width, height):
super().__init__(width, height)
arcade.set_background_color(arcade.color.AMAZON)
def setup(self):
# Set up your game here
pass
def on_draw(self):
""" Render the screen. """
arcade.start_render()
# Your drawing code goes here
def update(self, delta_time):
""" All the logic to move, and the game logic goes here. """
pass
def main():
game = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT)
game.setup()
arcade.run()
if __name__ == "__main__":
main()
Window
类有几个方法,您的程序可以覆盖这些方法来为程序提供功能。以下是一些最常用的方法
on_draw
:所有绘制屏幕的代码都放在这里。update
:所有移动项目和执行游戏逻辑的代码都放在这里。这大约每秒调用 60 次。on_key_press
:处理按下键时的事件,例如给玩家一个速度。on_key_release
:处理释放键时的情况,在这里您可能会阻止玩家移动。on_mouse_motion
:每次鼠标移动时都会调用此方法。on_mouse_press
:在按下鼠标按钮时调用。set_viewport
:此函数用于滚动游戏,当您的世界比一个屏幕上可以看到的要大得多时。调用set_viewport
允许程序员设置当前可见的世界部分。
精灵
精灵是在 Arcade 中创建 2D 位图对象的简便方法。Arcade 具有使精灵易于绘制、移动和动画化的方法。您还可以轻松地使用精灵来检测对象之间的碰撞。
创建精灵
从图形创建 Arcade 的 Sprite 类的实例很容易。程序员只需要一个图像的文件名作为精灵的基础,并且可以选择一个数字来向上或向下缩放图像。例如
SPRITE_SCALING_COIN = 0.2
coin = arcade.Sprite("coin_01.png", SPRITE_SCALING_COIN)
此代码将使用存储在 coin_01.png
中的图像创建精灵。图像将缩小到其原始高度和宽度的 20%。

精灵列表
精灵通常组织成列表。这些列表使管理精灵更容易。列表中的精灵将使用 OpenGL 批量绘制精灵组。下面的代码设置了一个游戏,其中包含一个玩家和一堆供玩家收集的金币。我们使用两个列表,一个用于玩家,一个用于金币。
def setup(self):
""" Set up the game and initialize the variables. """
# Create the sprite lists
self.player_list = arcade.SpriteList()
self.coin_list = arcade.SpriteList()
# Score
self.score = 0
# Set up the player
# Character image from kenney.nl
self.player_sprite = arcade.Sprite("images/character.png", SPRITE_SCALING_PLAYER)
self.player_sprite.center_x = 50 # Starting position
self.player_sprite.center_y = 50
self.player_list.append(self.player_sprite)
# Create the coins
for i in range(COIN_COUNT):
# Create the coin instance
# Coin image from kenney.nl
coin = arcade.Sprite("images/coin_01.png", SPRITE_SCALING_COIN)
# Position the coin
coin.center_x = random.randrange(SCREEN_WIDTH)
coin.center_y = random.randrange(SCREEN_HEIGHT)
# Add the coin to the lists
self.coin_list.append(coin)
我们可以轻松地绘制金币列表中的所有金币
def on_draw(self):
""" Draw everything """
arcade.start_render()
self.coin_list.draw()
self.player_list.draw()
检测精灵碰撞
函数 check_for_collision_with_list
允许我们查看精灵是否撞到了列表中的另一个精灵。我们可以使用它来查看玩家精灵接触的所有金币。使用一个简单的 for
循环,我们可以从游戏中移除金币并增加我们的分数。
def update(self, delta_time):
# Generate a list of all coin sprites that collided with the player.
coins_hit_list = arcade.check_for_collision_with_list(self.player_sprite, self.coin_list)
# Loop through each colliding sprite, remove it, and add to the score.
for coin in coins_hit_list:
coin.kill()
self.score += 1
有关完整示例,请参阅 collect_coins.py。
游戏物理
许多游戏都包含某种物理效果。最简单的是自上而下的程序,它可以防止玩家穿墙而过。平台游戏增加了更多的复杂性,包括重力和移动平台。一些游戏使用完整的 2D 物理引擎,包括质量、摩擦力、弹簧等等。
自上而下的游戏

对于简单的自上而下的游戏,Arcade 程序需要一个墙壁列表,玩家(或任何其他东西)无法穿过这些墙壁。我通常称之为 wall_list
。然后在 Window
类的设置代码中使用以下代码创建一个物理引擎
self.physics_engine = arcade.PhysicsEngineSimple(self.player_sprite, self.wall_list)
player_sprite
被赋予一个运动向量,其具有两个属性 change_x
和 change_y
。一个简单的例子是让玩家通过键盘移动。例如,这可能在 Window
类的自定义子类中
MOVEMENT_SPEED = 5
def on_key_press(self, key, modifiers):
"""Called whenever a key is pressed. """
if key == arcade.key.UP:
self.player_sprite.change_y = MOVEMENT_SPEED
elif key == arcade.key.DOWN:
self.player_sprite.change_y = -MOVEMENT_SPEED
elif key == arcade.key.LEFT:
self.player_sprite.change_x = -MOVEMENT_SPEED
elif key == arcade.key.RIGHT:
self.player_sprite.change_x = MOVEMENT_SPEED
def on_key_release(self, key, modifiers):
"""Called when the user releases a key. """
if key == arcade.key.UP or key == arcade.key.DOWN:
self.player_sprite.change_y = 0
elif key == arcade.key.LEFT or key == arcade.key.RIGHT:
self.player_sprite.change_x = 0
虽然该代码设置了玩家的速度,但它并没有移动玩家。在 Window
类的 update
方法中,调用 physics_engine.update()
将移动玩家,但不会穿过墙壁。
def update(self, delta_time):
""" Movement and game logic """
self.physics_engine.update()
有关完整示例,请参阅 sprite_move_walls.py。
平台游戏

切换到侧视图平台游戏相当容易。程序员只需要将物理引擎切换到 PhysicsEnginePlatformer
并添加重力常数即可。
self.physics_engine = arcade.PhysicsEnginePlatformer(self.player_sprite,
self.wall_list,
gravity_constant=GRAVITY)
您可以使用像 Tiled 这样的程序来布置构成您关卡的图块/方块。
有关示例,请参阅 sprite_tiled_map.py。
对于完整的 2D 物理效果,您可以集成 PyMunk 库。
通过示例学习
最好的学习方法之一是通过示例。Arcade 库有很长的 示例程序 列表,人们可以借鉴这些示例来创建游戏。这些示例中的每一个都展示了一个游戏概念,这些概念是学生多年来在我的课堂上或在线提出的。
一旦安装了 Arcade,运行这些演示中的任何一个都很容易。每个示例的程序开头都有一个注释,其中包含您可以在命令行中键入以运行示例的命令,例如
python -m arcade.examples.sprite_moving_platforms
总结
Arcade 让您可以使用易于理解的代码开始编程图形和游戏。许多新程序员在入门后不久就创建了 很棒的游戏。试试看!
要了解更多信息,请参加 Paul Vincent Craven 的演讲,使用 Arcade 轻松创建 2D 游戏,在 PyCon Cleveland 2018 上。
5 条评论