写点什么

28 分钟完成一款 Python 游戏,《客服戏翻总裁牌》

发布于: 2 小时前

游戏背景

本篇博客创意来源:CSDN 新星计划 Python 赛道群本游戏开发难度:入门级游戏试用场景:年会抽奖少儿编程游戏需求描述:随机生成一定数量的格子,然后埋入总裁头像,抽中总裁奖励奥迪一辆

准备素材

没错,CSDN 总裁和副总裁,请把专业团队打在评论区。



稍后游戏中,我们将使用二者头像,制作一款充满金钱味道的游戏。


游戏使用的 Python 框架是 pygame,该库小巧轻便,非常好使。

制作游戏背景

为了让游戏充满 金钱 味道,我特意制作了一个游戏背景图片。接下来就使用 pygame 实现一下吧。


通过 pygame.image.load 加载背景图,如果背景图尺寸不合适,可以通过 pygame.transform.scale 对素材进行缩放。


import pygameimport sysfrom pygame.locals import *

class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((900, 600)) pygame.display.set_caption("总裁翻牌")
def set_bg(self): bg = pygame.image.load("images/bg.png") # width, height = bg.get_size() # 素材缩小 # pygame.transform.scale(bg,(width,height)) self.screen.blit(bg, (0, 0))
def run(self): while True: for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
self.set_bg() pygame.display.update()

if __name__ == '__main__': g = Game() g.run()
复制代码


缩放这部分可以学习如下内容:


# 快速缩放,size 相同,缩小后会增大像素密度pygame.transform.scale()
# 平滑缩放,size 会变化,像素密度比较平均pygame.transform.smoothscale()
复制代码


运行 Python 代码,一张充满金钱味道的图片展现在了眼前。


既然游戏设置了 900x600 大小,下面需要进行简单的计算,在此游戏窗口内可以放置多少总裁牌子。


为了让大家看的更加清晰,制作一张说明图,如下所示,除了各个方格之间的距离,注意下图各个方格的左上角坐标。



直接使用硬编码的办法,实现对方格渲染的计算,下述代码用到了 pygame 中的精灵类,Card 类继承自该类。


import pygameimport sysfrom pygame.locals import *

class Card(pygame.sprite.Sprite): def __init__(self, x, y): self.image = pygame.image.load("images/card.png") width, height = self.image.get_size() self.rect = (x, y, width, height)

class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((900, 600)) pygame.display.set_caption("总裁翻牌") self.clock = pygame.time.Clock() self.start_point = (40, 45)
def set_bg(self): bg = pygame.image.load("images/bg.png") # width, height = bg.get_size() # 素材缩小 # pygame.transform.scale(bg,(width,height)) self.screen.blit(bg, (0, 0))
# 绘制牌子 def set_card(self):
for num in range(7 * 4): if num // 7 == 0: x = num * 120 + 40 y = 45 elif num // 7 == 1: x = (num - 7) * 120 + 40 y = 175 elif num // 7 == 2: x = (num - 7 * 2) * 120 + 40 y = 305 elif num // 7 == 3: x = (num - 7 * 3) * 120 + 40 y = 435 card = Card(x, y) self.screen.blit(card.image, card.rect)
def run(self): x = 40 y = 45 while True: self.clock.tick(60) for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
self.set_bg() self.set_card()
pygame.display.update()

if __name__ == '__main__': g = Game() g.run()
复制代码


代码运行得到如下,卡片使用铜钱图片即可,素材提前进行了裁剪。


卡片点击事件

下面要实现的一个重要操作,鼠标可点击卡片区域。


基于上文的代码,进行了一点点的封装,具体实现如下:


import pygameimport sysfrom pygame.locals import *

class Card(pygame.sprite.Sprite): def __init__(self, x, y): self.image = pygame.image.load("images/card.png") width, height = self.image.get_size() self.rect = (x, y, width, height)

class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((900, 600)) pygame.display.set_caption("总裁翻牌") self.clock = pygame.time.Clock()
self.card_nums = 28 self.points = self.all_point() # 封装坐标计算函数 def all_point(self): points = [] for num in range(self.card_nums): if num // 7 == 0: x = num * 120 + 40 y = 45 elif num // 7 == 1: x = (num - 7) * 120 + 40 y = 175 elif num // 7 == 2: x = (num - 7 * 2) * 120 + 40 y = 305 elif num // 7 == 3: x = (num - 7 * 3) * 120 + 40 y = 435 points.append((x, y)) return points
def set_bg(self): bg = pygame.image.load("images/bg.png") # width, height = bg.get_size() # 素材缩小 # pygame.transform.scale(bg,(width,height)) self.screen.blit(bg, (0, 0))
# 绘制牌子 def set_card(self):
for num in self.points: x, y = num card = Card(x, y) self.screen.blit(card.image, card.rect)
# 计算鼠标点击卡片 def mouse_card(self, mosx, mosy): for x, y in self.points:
if (mosx >= x and mosx <= (x + 100)) and (mosy >= y and mosy <= (y + 100)): print("点了")
def run(self):
while True: self.clock.tick(60) for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
if event.type == MOUSEBUTTONDOWN: mosx, mosy = event.pos self.mouse_card(mosx, mosy)
self.set_bg() self.set_card()
pygame.display.update()
if __name__ == '__main__': g = Game() g.run()
复制代码


此时当你点击任意卡片的时候,会提示是否被点中,同时将坐标生成函数进行了封装与提炼。


 def all_point(self):        points = []        for num in range(self.card_nums):            if num // 7 == 0:                x = num * 120 + 40                y = 45            elif num // 7 == 1:                x = (num - 7) * 120 + 40                y = 175            elif num // 7 == 2:                x = (num - 7 * 2) * 120 + 40                y = 305            elif num // 7 == 3:                x = (num - 7 * 3) * 120 + 40                y = 435            points.append((x, y))        return points
复制代码


只获取被点中还不可以,还需要进行翻牌,这步操作需要使用 Python 中的 enumerate 函数,循环的同时获取序号。


   # 计算鼠标点击卡片    def mouse_card(self, mosx, mosy):        for i, (x, y) in enumerate(self.points):
if (mosx >= x and mosx <= (x + 100)) and (mosy >= y and mosy <= (y + 100)): print("翻牌,点到卡片序号为", i)
复制代码


翻总裁的牌

上文实现的是翻牌触发,下面实现牌面的转换。此时用到的依旧是对卡片顺序的验证,修改逻辑代码如下,只展示有变化部分代码。


import pygameimport sysfrom pygame.locals import *

class Card(pygame.sprite.Sprite): def __init__(self, x, y, card_state): self.image = pygame.image.load("images/card.png") width, height = self.image.get_size() self.rect = (x, y, width, height) # 切换卡片牌面 self.card_state = card_state
def update(self): # 当牌面为 2 时显示哭脸 if self.card_state == 2: self.image = pygame.image.load("images/cry.png")

class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((900, 600)) pygame.display.set_caption("总裁翻牌") self.clock = pygame.time.Clock()
self.card_nums = 28 self.points = self.all_point()
# 点击卡片记录数组 self.click_list = []
def set_bg(self): bg = pygame.image.load("images/bg.png") # width, height = bg.get_size() # 素材缩小 # pygame.transform.scale(bg,(width,height)) self.screen.blit(bg, (0, 0))
# 绘制牌子 def set_card(self): for i, num in enumerate(self.points): x, y = num card_state = 1 # 卡片是否被点击 if i in self.click_list: card_state = 2
card = Card(x, y, card_state) card.update() self.screen.blit(card.image, card.rect)
# 计算鼠标点击卡片 def mouse_card(self, mosx, mosy): for i, (x, y) in enumerate(self.points): if (mosx >= x and mosx <= (x + 100)) and (mosy >= y and mosy <= (y + 100)): print("翻牌,点到卡片序号为", i) self.click_list.append(i)
复制代码


运行代码得到如下效果,点一个哭一个。


翻开 CSDN 总裁之牌

游戏已经到了最后一步,下面可以实现抽总裁卡,Card 类增加几个状态,即可实现。


    def update(self):        # 当牌面为 2 时显示哭脸        if self.card_state == 2:            self.image = pygame.image.load("images/cry.png")
if self.card_state == 3: self.image = pygame.image.load("images/fuzong.png") self.image = pygame.transform.scale(self.image, (100, 100))
if self.card_state == 4: self.image = pygame.image.load("images/zong.jpg") self.image = pygame.transform.scale(self.image, (100, 100))
复制代码


为了游戏的趣味性,加入随机效果,使用 numpy 搞定。


 # 随机生成数组,中奖为1,不中奖为0        self.win_list = list(np.random.randint(0, 3, 28))        print(self.win_list)
复制代码


最终的游戏代码为:


import pygameimport sysfrom pygame.locals import *import numpy as np

class Card(pygame.sprite.Sprite): def __init__(self, x, y, card_state): self.image = pygame.image.load("images/card.png") width, height = self.image.get_size() self.rect = (x, y, width, height) # 切换卡片牌面 self.card_state = card_state
def update(self): # 当牌面为 2 时显示哭脸 if self.card_state == 2: self.image = pygame.image.load("images/cry.png")
if self.card_state == 3: self.image = pygame.image.load("images/fuzong.png") self.image = pygame.transform.scale(self.image, (100, 100))
if self.card_state == 4: self.image = pygame.image.load("images/zong.jpg") self.image = pygame.transform.scale(self.image, (100, 100))

class Game: def __init__(self): pygame.init() self.screen = pygame.display.set_mode((900, 600)) pygame.display.set_caption("总裁翻牌") self.clock = pygame.time.Clock()
self.card_nums = 28 self.points = self.all_point()
# 点击卡片记录数组 self.click_list = []
# 随机生成数组,中奖为1,不中奖为0 self.win_list = list(np.random.randint(0, 3, 28))
def all_point(self): pass
def set_bg(self): bg = pygame.image.load("images/bg.png") # width, height = bg.get_size() # 素材缩小 # pygame.transform.scale(bg,(width,height)) self.screen.blit(bg, (0, 0))
# 绘制牌子 def set_card(self): for i, num in enumerate(self.points): x, y = num card_state = 1 # 卡片是否被点击 if i in self.click_list: card_state = 2 # 卡片是否被点击 if i in self.click_list and self.win_list[i] == 1: card_state = 3 # 卡片是否被点击 if i in self.click_list and self.win_list[i] == 2: card_state = 4
card = Card(x, y, card_state) card.update() self.screen.blit(card.image, card.rect)
# 计算鼠标点击卡片 def mouse_card(self, mosx, mosy): for i, (x, y) in enumerate(self.points): if (mosx >= x and mosx <= (x + 100)) and (mosy >= y and mosy <= (y + 100)): print("翻牌,点到卡片序号为", i) self.click_list.append(i)
def run(self):
while True: self.clock.tick(60) for event in pygame.event.get(): if event.type == QUIT: pygame.quit() sys.exit()
if event.type == MOUSEBUTTONDOWN: mosx, mosy = event.pos self.mouse_card(mosx, mosy)
self.set_bg() self.set_card()
pygame.display.update()

if __name__ == '__main__': g = Game() g.run()
复制代码



完整代码下载:下载地址


发布于: 2 小时前阅读数: 7
用户头像

爬虫 100 例作者,蓝桥签约作者,博客专家 2021.02.06 加入

6 年产品经理+教学经验,3 年互联网项目管理经验; 互联网资深爱好者; 沉迷各种技术无法自拔,导致年龄被困在 25 岁; CSDN 爬虫 100 例作者。 个人公众号“梦想橡皮擦”。

评论

发布
暂无评论
28分钟完成一款Python游戏,《客服戏翻总裁牌》