4

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

 3 years ago
source link: https://blog.csdn.net/hihell/article/details/117338769
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

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

零基础学python要多久 python自学行吗 免费python全套教程
稍后游戏中,我们将使用二者头像,制作一款充满金钱味道的游戏。

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

制作游戏背景

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

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

import pygame
import sys
from 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 代码,一张充满金钱味道的图片展现在了眼前。

零基础学python要多久 python自学行吗 免费python全套教程

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

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

零基础学python要多久 python自学行吗 免费python全套教程
直接使用硬编码的办法,实现对方格渲染的计算,下述代码用到了 pygame 中的精灵类,Card 类继承自该类。

import pygame
import sys
from 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()

代码运行得到如下,卡片使用铜钱图片即可,素材提前进行了裁剪。
零基础学python要多久 python自学行吗 免费python全套教程

卡片点击事件

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

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

import pygame
import sys
from 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)

零基础学python要多久 python自学行吗 免费python全套教程

翻总裁的牌

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

import pygame
import sys
from 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)

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

零基础学python要多久 python自学行吗 免费python全套教程

翻开 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 pygame
import sys
from 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()

零基础学python要多久 python自学行吗 免费python全套教程
完整代码下载:下载地址

上一篇博客中奖ID如下:

恭喜 Xiao_Chen001,抓紧联系擦姐吧。

零基础学python要多久 python自学行吗 免费python全套教程

只要评论数过 50
随机抽取一名幸运读者
奖励 39.9 元爬虫 100 例专栏 1 折购买券一份,只需 3.99 元

今天是持续写作的第 158 / 200 天。
求点赞、求评论、求收藏。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK