软件工程课程第二次个人作业
这个作业属于哪个课程 | 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 |