实现效果
绘制平面地图
按动键盘可以实现地图位置的移动(图片中的A保存相对不动)
实现地图类
初始化地图类
同上一篇博文讲过的,增加long
、wide
保存地图块的长宽,和transform2x
是否将图片放大两倍,suf_m
来保存原始的地图数据,suf_s
用来保存绘制地图数据
def __init__(self, maps=[[0, 0], [0, 0]], long=72, wide=72, transform2X=True):
# 用键值对保存图片信息
"""
用字典来保存图片位置
<1 代表路面、草坪等可以通过的地方
≥1且<2 代表墙面、等
≥2 代表可以交互的地方
"""
self.dic = {0: "road", 0.1: "roadv", 0.101: "roadc1", 0.102: "roadc2", 0.103: "roadc3", 0.104: "roadc4"}
# 放置地图
self.map = maps
# 是否放大两倍,图片的长、宽
self.two_size = transform2X
self.image_l = long
self.image_h = wide
# 计算整体地图的长宽
length = len(self.map)
max_long = 1
for i in range(length):
if max_long < len(self.map[i]):
max_long = len(self.map[i])
# 用来保存原始的地图
self.suf_m = pygame.Surface([self.image_h * max_long, self.image_l * length])
self.suf_m.fill([255, 255, 255])
# 用来显示地图
self.suf_s = pygame.Surface([1080, 720])
self.suf_s.set_colorkey([0, 0, 0])
绘制地图并更新
下面这个函数用于从地图中读取数据,根据字典读取图片并根据图片位置绘制地图更新到suf_m
,最后将suf_m
更新到suf_s
上
def print_map(self):
ci, ri = 0, 0
for c in self.map:
for r in c:
# 根据字典按行绘制
image = pygame.image.load(r"s\{}.png".format(self.dic[r]))
# 放大图片
if self.two_size:
image = pygame.transform.scale2x(image)
self.image_l, self.image_h = image.get_size()
self.suf_m.blit(image, (ri * self.image_l, ci * self.image_h))
ri = ri + 1
ci = ci + 1
ri = 0 # 初始化行标识
self.suf_s.blit(self.suf_m.copy(), (0, 0))
设置地图的中心点
确认在地图中的一个不变的点,spirit是用来储存角色信息的对象,获取主角的x坐标和y坐标
# 根据位置初始化角色位置矢量
def __move__init__(self, spirit):
self.x0, self.y0 = spirit.x, spirit.y
位移函数
尽量不要用scroll
,不然会有bug(图片移动到边缘有拖影),这里计算移动后的角色与初始化角色的位移,然后用blit
将suf_m
显示到suf_s
上。因为图片与人物的移动位置相反,所以带负号
# 位移函数
def center(self, x, y):
# 清除旧的图片,x, y是移动后角色的位置
self.suf_s.fill([255, 255, 255])
# 图片移动的方向与人物相反
self.suf_s.blit(self.suf_m, (- self.image_l * (x - self.x0), - self.image_h * (y - self.y0)))
开始移动
传入角色当前位置的信息、位移后的信息,判断位移是否能发生:
- x不超过地图
- y不超过地图
- 位移后的不是墙壁
如果可以则返回更新后的角色的位置矢量,否则返回原本角色的位置矢量。
# 向右/下移动一个单位为1,x,y为当前位置
def move(self, x, y, x_final, y_final):
if 0 <= y_final < len(self.map):
if 0 <= x_final < len(self.map[y_final]):
if self.map[y_final][x_final] < 1:
self.center(x_final, y_final)
return x_final, y_final
else:
return x, y
else:
return x, y
else:
return x, y
地图上的其他效果
下雨效果
在地图上随机绘制短线代表下雨
def print_rain(self):
for i in range(1000):
xj, yj, lj = random.randint(0, 2160), random.randint(0, 1030), random.randint(0, 20)
pygame.draw.line(self.suf_m, [255, 255, 255], (xj, yj), (xj, yj + lj), 1)
self.suf_s.blit(self.suf_m, (0, 0))
夜晚/日出效果
设置一个透明图层,绘制有颜色的矩形更新到suf_m
上,最后将suf_m
绘制到suf_s
上
def print_time(self, array=[255, 255, 255], alpha=50):
# 设置一个表现时间的图层
suf_night = pygame.Surface(self.suf_m.get_size())
suf_night.set_alpha(alpha)
# 绘制全屏矩形
rect = self.suf_m.get_rect()
pygame.draw.rect(suf_night, array, rect)
# 绘制到显示图层上
self.suf_m.blit(suf_night, (0, 0))
self.suf_s.blit(self.suf_m, (0, 0))
白天和夜晚颜色不同
# 白天
def print_night(self):
self.print_time([255, 255, 255])
# 夜晚
def print_night(self):
self.print_time([1, 2, 4])