自动驾驶仿真工程师,上班玩玩自制赛车游戏,是不是很香?此前的分享中,我们成功地在Carla的服务器端打开了一个界面,并根据实时更新观察者视角,获得了最初的仿真体验。但真实使用过程中,服务器端的界面我们是不会动的,而是重新生成一个或多个新的客户端界面。相当于服务器主机只有一个,但是有多个玩家客户端在操控,共同控制服务器里各自的车辆形式,进行交互。这种多个客户端一个服务器端的模式,正是Carla的底层架构模式。大家完全可以基于Carla开发出来一个多人赛车游戏。要创建客户端游戏界面,最好的python库就是pygame,本期,我们尝试来结合carla和pygame,创建客户端游戏界面。pygame中显示的界面内容,我们尝试从车辆上的摄像头传感器中获取。Python Pygame 是一款专门为开发和设计 2D 电子游戏而生的软件包,它支 Windows、Linux、Mac OS 等操作系统,具有良好的跨平台性。Pygame 由 Pete Shinners 于 2000 年开发而成,是一款免费、开源的的软件包,因此您可以放心地使用它来开发游戏,不用担心有任何费用产生。
Pygame 在 SDL(Simple DirectMedia Layer,使用 C语言编写的多媒体开发库) 的基础上开发而成,它提供了诸多操作模块,比如图像模块(image)、声音模块(mixer)、输入/输出(鼠标、键盘、显示屏)模块等。相比于开发 3D 游戏而言,Pygame 更擅长开发 2D 游戏,比如于飞机大战、贪吃蛇、扫雷等游戏。要使用pygame,命令行输入如下指令完成安装即可。
# -*- coding:utf-8 -*-
import pygameimport sys #sys是python的标准库,提供Python运行时环境变量的操控
pygame.init() # 内部各功能模块进行初始化创建及变量设置,默认调用size = width, height = 800, 600 # 设置游戏窗口大小,分别是宽度和高度screen = pygame.display.set_mode(size) # 初始化显示窗口pygame.display.set_caption("我的小游戏程序") # 设置显示窗口的标题内容,是一个字符串类型while True: # 无限循环,直到Python运行时退出结束 for event in pygame.event.get(): # 从Pygame的事件队列中取出事件,并从队列中删除该事件 if event.type == pygame.QUIT: # 获得事件类型,并逐类响应 sys.exit() # 用于退出结束游戏并退出 pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
运行后会创建打开一个如下的窗口,只有点击关闭按钮,才会退出该程序。
再来看看下面的例子,我们对上述代码稍加改动,手动创建了一个50*50大小的Surface对象,将之添加到了显示窗口(100,100)位置处。# -*- coding:utf-8 -*-
import pygameimport sys #sys是python的标准库,提供Python运行时环境变量的操控
pygame.init() # 内部各功能模块进行初始化创建及变量设置,默认调用size = width, height = 800, 600 # 设置游戏窗口大小,分别是宽度和高度screen = pygame.display.set_mode(size) # 初始化显示窗口pygame.display.set_caption("我的小游戏程序") # 设置显示窗口的标题内容,是一个字符串类型
# 创建一个 50*50 的图像, 并优化显示face = pygame.Surface((50, 50), flags=pygame.HWSURFACE)face.fill(color='white') #填充颜色
while True: # 无限循环,确保窗口一直显示 for event in pygame.event.get(): # 遍历所有用户操作事件 if event.type == pygame.QUIT: # 获得事件类型,判断是否为关闭窗口 sys.exit() # 用于结束程序的运行并退出 # 将绘制的图像添加到主屏幕上,(100,100)是位置坐标,显示屏的左上角为坐标系的(0,0)原点 screen.blit(face, (100, 100)) pygame.display.update() # 对显示窗口进行更新,默认窗口全部重绘
pygame.quit() # 退出pygame
现在,我们实现了自己创建一个图像并显示在了pygame的窗口中。那么carla服务器端的图像,又该怎么显示到pygame窗口中呢?
import pygameimport sysimport carlaimport numpy as np
def sensor_image(image): array = np.frombuffer(image.raw_data, dtype=np.dtype("uint8")) array = np.reshape(array, (image.height, image.width, 4)) array = array[:, :, :3] array = array[:, :, ::-1] surface = pygame.surfarray.make_surface(array.swapaxes(0, 1)) my_display.blit(surface, (0, 0)) return surface
try: pygame.init() size = width, height = 800, 600 screen = pygame.display.set_mode(size) pygame.display.set_caption("我的小游戏程序") my_display = pygame.display.set_mode(size, pygame.HWSURFACE | pygame.DOUBLEBUF)
actor_list = [] client = carla.Client('localhost', 2000) client.set_timeout(5.0) world = client.get_world() blueprint_library = world.get_blueprint_library() bp = blueprint_library.filter('model3')[0] print("the vehicle blueprint:", bp) spawn_point = world.get_map().get_spawn_points()[0] vehicle = world.spawn_actor(bp, spawn_point) vehicle.set_autopilot(True) actor_list.append(vehicle) blueprint = blueprint_library.find('sensor.camera.rgb') blueprint.set_attribute('image_size_x', str(width)) blueprint.set_attribute('image_size_y', str(height)) blueprint.set_attribute('fov', '110') spawn_point = carla.Transform(carla.Location(x=-4, z=2)) sensor_camera = world.spawn_actor(blueprint, spawn_point, attach_to=vehicle) actor_list.append(sensor_camera) sensor_camera.listen(lambda img: sensor_image(img))
while True: for event in pygame.event.get(): if event.type == pygame.QUIT: sys.exit() pygame.display.update()
finally: pygame.quit() for actor in actor_list: actor.destroy() print("销毁:", actor)
如上内容,即如何获得Carla中的摄像头数据,并将之显示到pygame窗口中。效果如下:

上图中,大窗口为Carla的仿真世界,即服务器端。小窗口为pygame窗口,是我们创建的客户端界面。如果将客户端窗口运行多次,将会打开多个客户端窗口。再配合pygame获取键盘输入的功能,即能实现以键盘方式驱动车辆形式,实现多个玩家赛车的场景了。
自动驾驶仿真工程师,上班玩玩自制赛车游戏,是不是很香?本期分享到这里,诸位道友如有所得,欢迎关注-点赞-收藏-转发哦。