Python 是一种非常适合编程初学者的语言,也非常适合任何想要“完成工作”而不花费大量时间在样板代码上的人。Arcade 是一个用于创建 2D 视频游戏的 Python 库,它易于上手,并且随着您经验的积累,功能非常强大。在本文中,我将解释如何开始使用 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 在 PyCon Cleveland 2018 上的演讲 使用 Arcade 轻松创建 2D 游戏。
5 条评论