软件工程课程第二次个人作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/SE2024
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13253
这个作业的目标 利用python和AIGC设计一个消除类小游戏;学会基础的游戏设计过程和完成方法
学号 102201140

Markdown编辑器


0.前言

作业要求生成一个“羊了个羊”风格的消除类小游戏。鉴于作者本人更喜欢翻卡牌式的记忆消除游戏,因此,在设计游戏时选择将这两种游戏风格进行结合。

  • 使用翻卡牌效果代替卡牌堆叠,并且保留羊了个羊游戏的卡槽识别消除功能。
  • 由于游戏设计临近中秋,因此游戏的设计选择以中秋为主题,创建“中秋消消乐”游戏。
    具体游戏介绍以及实现过程如下。具体代码请访问我的github主页https://github.com/pear-09/pear-09

1.游戏展示

* 初始界面

* play界面

* 游戏失败界面

* 游戏获胜界面

* 游戏游玩概览

由于视频转gif,画质相当模糊。原游戏界面比较高清。

2.游戏实现前期准备

(1)游戏逻辑简介

初始界面设置START和QUIT按钮,选择开始或者退出游戏

游戏规则如下

  • 卡牌随机生成排放位置,共8种卡牌,每种卡牌的个数为3的倍数

  • 点击卡牌背面,卡牌会移动至屏幕下方的卡槽,并且显示卡牌正面图案

  • 卡槽共设置3个卡位,如果卡牌数满足3个,则判别是否是3张相同卡牌。是,则消除这3张卡牌;不是,则将3张卡牌返回其原始位置,并且翻回卡牌背面。

  • 游戏为倒计时制,总计60秒,如果时间到达上限,则显示DEFEAT界面,游戏失败。可以选择RESTART或者QUIT;如果在倒计时内游戏胜利,则显示VICTORY界面,游戏胜利。同样可以选择RESTART或者QUIT。

  • 游戏设置积分制,起始分数为100分,游戏每进行一秒则扣除一分。最低分为0分。(因此,玩家可以知道,如果倒计时结束,得分为40分,具体用意可以继续阅读

  • 拓展功能为Reset time,可以重置时间为起始时间,为自己争取更多卡牌匹配时间。但是玩家们请注意:重置时间并不会重置当前分数。因此,如果玩家企图通过无限次重置时间来匹配卡牌,最后得分可能会比直接失败更低哦!(游戏道具不是捷径,加油匹配才是王道

(2)页面美化

这一部分花费了作者大量的时间。
由于游戏设计之初,屏幕像素设计为(800*600)比较小,导致卡牌只能设计较低尺寸,卡牌特别模糊,如下:


因此,为了提高玩家的游玩体验,选择增大游戏屏幕像素(1620*760),并且重新进行了页面设计,如上文提到的游戏各种界面。

美化过程

美化需求确定

  • 游戏登录主界面背景
  • START以及QUIT按钮设计
  • play界面背景
  • 卡牌背面
  • 8种卡牌正面
  • 游戏胜利界面
  • 游戏失败界面

生成过程

  • 选择使用即梦ai,生成游戏背景。但是由于ai技术有限,无法达到作者要求,因此只使用ai生成图片的部分,结合花瓣网上免费商用的图片素材进行ps创作,重新得到符合中秋主题,并且清晰度够高的图片。

即梦ai

花瓣网

以下为部分生成图片概览

3.具体实现、代码展示

主循环

主要实现游戏状态监控、鼠标点击等功能

# 主循环 state = 'initial' pygame.mixer_music.load("背景音乐.ogg") pygame.mixer_music.set_volume(0.5) pygame.mixer_music.play() while True: pygame.mixer_music.load("背景音乐.ogg") pygame.mixer_music.set_volume(0.5) pygame.mixer_music.play() if state == 'initial': state = initial_screen() elif state == 'play': result = game() if result == 'victory' or result == 'defeat': choice = show_end_screen(result) if choice == 'restart': state = 'initial' elif choice == 'quit': pygame.quit() break elif result == 'exit': pygame.quit() break elif state == 'exit': # 确保在退出状态时也正确处理退出 pygame.quit() break

游戏主函数

主要实现游戏play界面的集中功能,包括倒计时和积分等,具体见代码

`def game():
global start_time, score, slot_cards, slot_animation_time
global play_time
start_time = pygame.time.get_ticks() # 重置开始时间
score = 100 # 重置分数

game_over = False
while not game_over:
    current_time = pygame.time.get_ticks() - start_time

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            return 'exit'
        elif event.type == pygame.MOUSEBUTTONDOWN:
            process_mouse_event(event, cards, screen)
            # 检测技能按钮是否被点击
            if skill_button_rect.collidepoint(event.pos):
                play_time += current_time
                start_time = pygame.time.get_ticks()  # 重置开始时间

    screen.blit(game_background, (0, 0))  # 先绘制背景
    move_to_slot()
    update_score()  # 更新分数
    check_cards()

    # 显示游戏时间和分数
    remaining_time = GAME_DURATION * 1000 - current_time
    time_text = font.render(f"Time: {remaining_time // 1000:02d}", True, BLACK)
    screen.blit(time_text, (80, 35))
    score_text = font.render(f"Score: {score}", True, BLACK)
    screen.blit(score_text, (WIDTH - score_text.get_width() - 80, 35))

    # 绘制技能按钮
    pygame.draw.rect(screen, skill_button_color, skill_button_rect)
    screen.blit(font.render(skill_button_text, True, BLACK), (skill_button_rect.x +3, skill_button_rect.y + 3))

    for i, info in images_info.items():
        if info['show_back']:
            screen.blit(card_back, info['rect'].topleft)
        elif info['show_front']:
            screen.blit(info['image_front'], info['rect'].topleft)

    pygame.display.update()
    clock.tick(FPS)

    result = check_victory_or_defeat()
    if result:
        game_over = True
        return result

return 'end'  # 返回游戏结果`

游戏其他函数

由于游戏包括的函数过多,因此将以游戏实现的功能为顺序逐一讲解,但是每种函数只包括部分。具体可以查阅的我github主页。

(1)播放游戏背景音乐(玩游戏的时候需要一些东西调节心情)

pygame.mixer_music.load("背景音乐.ogg") pygame.mixer_music.set_volume(0.5) pygame.mixer_music.play()

(2)倒计时系统以及分数更新的实现

def format_time(milliseconds): return f"{(milliseconds // 1000) % 60:02d}:{(milliseconds % 1000) // 10:02d}"

`def update_score():
global score, start_time
global play_time
current_time = pygame.time.get_ticks() - start_time
elapsed_seconds = (current_time + play_time) // 1000

score = max(100 - elapsed_seconds, 0)  # 每过一秒减1分,不低于0`

# 显示游戏时间和分数 remaining_time = GAME_DURATION * 1000 - current_time time_text = font.render(f"Time: {remaining_time // 1000:02d}", True, BLACK) screen.blit(time_text, (80, 35)) score_text = font.render(f"Score: {score}", True, BLACK) screen.blit(score_text, (WIDTH - score_text.get_width() - 80, 35))

(3)卡牌翻面以及移动效果

def move_to_slot(): for i in slot_cards: info = images_info[i] if (pygame.time.get_ticks() - info['start_time']) > 1: # 0.5秒后移动 slot_index = slot_cards.index(i) x, y = slot_positions[slot_index] info['rect'].topleft = (x, y) # 更新图片位置 screen.blit(info['image_front'], info['rect'].topleft)

`def process_mouse_event(event, cards, screen):
global slot_cards, slot_animation_time # 声明全局变量
mosx, mosy = event.pos
index = None

for i, info in images_info.items():
    if info['rect'].collidepoint(mosx, mosy) and info['show_back']:
        index = i
        break

if index is not None:
    if len(slot_cards) < 3:
        img_path = cards[index]
        image = pygame.image.load(img_path)
        images_info[index] = {
            'show_back': False,
            'show_front': True,
            'image_front': image,
            'rect': image.get_rect(topleft=images_info[index]['rect'].topleft),
            'start_time': pygame.time.get_ticks()
        }
        screen.blit(image, images_info[index]['rect'].topleft)
        slot_cards.append(index)
        slot_animation_time.append(pygame.time.get_ticks())  # 记录动画时间
        if len(slot_cards) == 3:
            check_cards()`

(4)卡牌匹配是否正确以及移动回原始卡位

def check_cards(): global correct_match global slot_cards, slot_animation_time # 声明 slot_cards 和 slot_animation_time 为全局变量 if len(slot_cards) == 3: if (pygame.time.get_ticks() - max(slot_animation_time) > 1000): card_paths = [cards[i] for i in slot_cards] if card_paths.count(card_paths[0]) == 3: # 所有卡片都一致 for i in slot_cards: images_info[i]['show_front'] = False images_info[i]['show_back'] = False slot_cards = [] # 清空卡槽 slot_animation_time = [] # 清空动画时间记录 correct_match = True else: # 卡片不一致,移回原位 for i in slot_cards: images_info[i]['show_front'] = False images_info[i]['show_back'] = True x = (i % 6) * TILE_SIZE + 130 y = 150 + 120 * (i // 6) images_info[i]['rect'].topleft = (x, y) slot_cards = [] # 清空卡槽 slot_animation_time = [] # 清空动画时间记录 correct_match = False

(5)技能按钮Reset time实现

elif event.type == pygame.MOUSEBUTTONDOWN: process_mouse_event(event, cards, screen) # 检测技能按钮是否被点击 if skill_button_rect.collidepoint(event.pos): play_time += current_time start_time = pygame.time.get_ticks() # 重置开始时间
其余相关技能不一一赘述。

游戏功能总结

基础功能 拓展功能
实现图案的随机摆放 卡牌翻面效果
将卡牌移动至卡槽 游戏倒计时系统设置
对卡槽的卡牌进行匹配识别 游戏分数系统
重复进行游戏 增加道具功能,重置时间

4.AIGC表格

子任务名称 任务详情 借助何种AIGC技术 实际实现效果
初始化游戏环境 设置游戏窗口大小、标题、帧率等。初始化全局变量,如分数、时间、卡牌状态等。加载和设置游戏资源,如背景图片、卡牌背面图片等。 可以自行完成
游戏资源加载 加载卡牌的正面图像和背景图像。将卡牌图像存储在字典中,以便后续使用。 可以自行完成
游戏逻辑处理 处理玩家点击事件,判断点击的是否为卡牌背面,并进行相应的翻转操作。检查玩家是否选择了三张卡牌,并对这三张卡牌进行匹配检查。更新游戏分数和时间。检查游戏是否胜利或失败,并进行相应的处理。 kimi 可以正确实现功能,但是存在实现后续功能就忘记前面的功能
游戏界面绘制 绘制游戏背景、卡牌、计分板、时间显示等。绘制技能按钮,并处理技能按钮的点击事件。 即梦 绘制效果不佳,需要后续自行处理
游戏状态管理 管理游戏的不同状态,如初始界面、游戏进行中、游戏胜利/失败界面等。处理游戏状态之间的转换,如从初始界面进入游戏,或从游戏胜利/失败界面重启游戏。 ChatGPT 可完成,但是会导致一些死循环
游戏结束处理 显示游戏结束界面,包括胜利或失败的提示。处理玩家在游戏结束界面的操作,如重启游戏或退出游戏 ChatGPT 很好地完成

5.PSP表格

任务ID 任务描述 预计时间(小时) 实际时间(小时))
1 项目启动和规划 1 1
2 设计游戏界面 5 8
3 编写游戏逻辑代码 40 40
4 加载和处理游戏资源 1 1
5 测试游戏功能和修复bug 10 15
6 总结工作经验 3 5
posted @ 2024-09-18 01:04  黎曼1  阅读(42)  评论(0编辑  收藏  举报