结对编程作业
https://github.com/zhangzh123455/zzh/tree/main/pokegame
成员 | 姓名 | 博客链接 | 分工 |
---|---|---|---|
成员1 | 吴杰 | 博客 | 设计原型,编辑博客,辅助设计原型的实现 |
成员2 | 张梓晗 | 博客 | 游戏主要的功能实现,原型设计的实现 |
一、原型设计
-
(1.1)此次结对作业的设计说明
https://8gzfq3.axshare.com
(PS:网页初次加载缓慢,请稍等片刻,频繁操作可能出现BUG,不小心把原型分辨率做成全屏了,请点击右上角调整大小)
-
本次作业采用的原型工具:Axure RP9
-
原型是本着功能随便加,做不做的出来再说的原则设计的,主要有三个页面
-
开始界面
用于展示一个初始简洁的形象和功能以及链接到其他子界面
-
游戏过程
点击双人对战后便会进入游戏过程页面
该页面用交互效果展示了游戏的一整个流程和游戏玩法,包括翻牌、吃牌、出牌,途中随时可以返回开始界面,原型将玩家的手牌分为了四个不同的花色区域,翻出的手牌将会存储在该区域内,点击该区域则可以打出该区域的手牌,如果点击卡组则会翻牌。游戏中点击开始该区域会显示玩家的回合,在翻牌或出牌后回合会交替
花色相同即会吃牌
演示完后会出现下一步跳完胜利演示界面 -
胜利界面
用于演示用户获得胜利后的界面并可点击“RETURN”返回 -
设置界面
开始界面中点击游戏设置进入该界面
-
-
-
(1.2)遇到的困难及解决方法
- 困难:
- 之前从未接触过原型,也是这次作业之后才掌握了一个原型工具
- 素材缺乏,原型设计需要的图片、字体、音乐等等资源,才知道没素材创作者寸步难行的痛苦
- 解决过程:
- 对于原型工具只能老老实实去下载安装,然后去网上寻找视频或文字资料去学习原型工具的使用
- 素材缺乏通过搜索引擎和一些资源网站获取
- 收获
- 学习了原型工具的使用,以后做项目也可以参与产品的设计,UI等方面工作
- 提高了自己学习和寻找资源的效率
- 困难:
二、原型设计实现
- (2.1)代码实现思路:
- 网络接口的使用
由于能力(用不明白)和时间的不足,本次作业我们小组未能完成在线对战,所以没有用到接口这块。希望以后有时间能回过头来完善吧。 - 代码的组织与内部实现设计
本次作业是通过python的pygame模块来实现的,由于pygame本身的原因,是较为底层的游戏实现方式。很多东西都得自己写,而本次实验又是我们第一次使用pygame,代码难免有点混乱。
在本次代码中,我们编写了两个模块:
①一个是button模块,它用来创建矩形按钮,其内置函数可实现按钮的点击效果动画,以及判断按钮是否被点击。
②一个是pictureevent模块,它用来判断图片是否被点击,由于游戏中是通过点击对应的手牌位置打出不同花色的牌,以及点击卡组区来摸牌,需要多次判断图片是否被点击,于是写了这个模块减少代码行数。
写了五个函数:,
①poker_nn(poke)函数,是将列表中存放的['花色','数字']转化为poker列表中对应牌的下标,方便调用卡牌图片;
②drawnum()函数是画出各个地方(卡组、放置区、手牌)中不同花色的数量;
③draw2()函数是吃牌操作后显示各个地方花色的数量;
④fapai1()函数是玩家1吃牌后,将放置区的牌发给玩家1
⑤fapai2()函数是玩家2吃牌后,将放置区的牌发给玩家2
主代码通过调用以上类和函数进行游戏操作 - 说明算法的关键与关键实现部分流程图
当玩家摸牌摸出或打出与放置区顶相同花色的牌时,将存放放置区的列表元素一个个pop出来,再判断是什么花色,添加到对应玩家不同花色的列表中,同时调用fapai1/fapai2函数进行吃牌后的发牌动画的实现
- 贴出你认为重要的/有价值的代码片段,并解释
- 网络接口的使用
# 当花色一样时,放置区的牌清空,并依次放入对应玩家不同花色的手牌区
if int(p / 13) == int(t_p2 / 13):
for i in range(l2):
pii = placed_poker.pop()
n1 = poker_nn(pii)
move_list.append(pii)
if 0 <= n1 <= 12:
player1_poker1.append(pii)
elif 13 <= n1 <= 25:
player1_poker2.append(pii)
elif 26 <= n1 <= 38:
player1_poker3.append(pii)
elif 39 <= n1 <= 51:
player1_poker4.append(pii)
实现吃牌操作的动画效果
for movepoke in move_list:
n1 = poker_nn(movepoke)
if 0 <= n1 <= 12:
while y1_speed1 >= p1_y1 - place_y:
window.blit(begin_screen, (0, 0))
window.blit(picture_list[n1], (place_x + k11 * y1_speed1, place_y + y1_speed1))
y1_speed1 -= 1
drawnum()
pygame.display.update()
y1_speed1 = -1
elif 13 <= n1 <= 25:
while y2_speed1 >= p1_y2 - place_y:
window.blit(begin_screen, (0, 0))
window.blit(picture_list[n1], (place_x + k12 * y2_speed1, place_y + y2_speed1))
y2_speed1 -= 1
drawnum()
pygame.display.update()
y2_speed1 = -1
elif 26 <= n1 <= 38:
while y3_speed1 >= p1_y3 - place_y:
window.blit(begin_screen, (0, 0))
window.blit(picture_list[n1], (place_x + k13 * y3_speed1, place_y + y3_speed1))
y3_speed1 -= 1
drawnum()
pygame.display.update()
y3_speed1 = -1
elif 39 <= n1 <= 51:
while y4_speed1 >= p1_y4 - place_y:
window.blit(begin_screen, (0, 0))
window.blit(picture_list[n1], (place_x + k14 * y4_speed1, place_y + y4_speed1))
y4_speed1 -= 1
drawnum()
pygame.display.update()
y4_speed1 = -1
move_list = []
-
性能分析与改进
由于pygame需要用一个死循环来维持游戏框架,于是我测试了完成一次双人对局后的代码性能分析,如下图。发现调用次数较多的是Python内置模块builtins,以及事件位置记录pygame.event.pos的调用较多。builtins模块查找了一下搜索引擎,说是与内建函数有关,而event事件包含鼠标的移动事件,多是正常的。所以应该没有啥要优化的地方(大概,也许)
-
改进思路
事件记录太多次了致使耗时最多,那我能想到的办法只有玩游戏时鼠标非必要情况下不要乱动了 -
(2.2)Github的代码签入记录。
-
(2.3)遇到的代码模块异常或结对困难及解决方法。
- 问题:由于两个人都是菜鸟,代码模块化不太会用,只是分成了三个简单的模块。
- 解决方法:我们的分工是一个人进行原型设计,寻找游戏图片、字体等材料,并导入,以及博客的主要编写任务,并做一些简单的代码工作。而由另一个人来实现代码的主要功能的实现。
- 收获:第一次在一个比较大的工程上实现代码模块化,认识到当代码量较大时分模块的重要性以及对代码可读性的帮助之大。
-
(2.4)评价你的队友。
- 对成员1的评价:
- 值得学习的地方:找资源的本事很强,能找到适合的素材,原型设计对成员2有很大帮助
- 需要改进的地方:对Python使用不熟练
- 对成员2的评价:
- 值得学习的地方:非常认真,能加班肝项目,代码能力比较强
- 需要改进的地方:对于接口方面还不熟练
- 对成员1的评价:
-
(2.5)此次结对作业的PSP和学习进度条
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 30 | 60 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 200 | 300 |
· Design Spec | · 生成设计文档 | 90 | 120 |
· Design Review | · 设计复审 | 20 | 40 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 | 90 |
· Design | · 具体设计 | 120 | 240 |
· Coding | · 具体编码 | 1200 | 1500 |
· Code Review | · 代码复审 | 200 | 400 |
· Test | · 测试(自我测试,修改代码,提交修改) | 60 | 90 |
Reporting | 报告 | ||
· Test Repor | · 测试报告 | 20 | 30 |
· Size Measurement | · 计算工作量 | 20 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 20 |
· 合计 | 2010 | 2920 |
第N周 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
1 | 0 | 0 | 15 | 15 | 学习html,了解原型和原型工具 |
2 | 0 | 0 | 15 | 30 | 学习了html和css的一部分, 找视频深入学习原型工具,并初步设计出一个模型 |
3 | 300 | 300 | 20 | 50 | 学习Python中pygame模块的基本函数使用,原型设计完毕修改,讨论实现原型的思路开始写功能模块 |
4 | 1200 | 1500 | 32 | 82 | 学习了pygame的动画实现,修修改改做游戏 |
三、心得
吴杰:
- 早在敏感词做完后就觉得结对编程肯定又是一个熬夜秃头学习敲代码的项目,果然,这次作业做一个小游戏对于没有经验的人来说还是有挑战性的。而且功能难度分层,至少完成个本地人人对战还是很有必要的。
- 被逼迫加快了进一步学习Python的步伐,还有原型工具从啥都不会到了解,最后能做出个
能动就行的游戏模型感觉还是学了挺多东西。 - 虽然代码的大部分工作由队友承担了,不过我们也过了一遍流程,讨论了实现思路,顺便一提搜索引擎直接搜索的效率太低,还是找一些资源整合的网站效率快得多。
张梓晗:
- 本次结对作业的题目刚发布时我整个人都是懵的,从来没实践过通过编程实现游戏的我,一时间不知道该从哪入手,后面问了一些大佬和查找了资料,知道可以用前后端的编程方法实现游戏,也可以通过不同语言里的一些库之类的来实现。由于我在我的团队小组中任务是后端辅助,而我的队友是前端辅助,我们最开始是打算用前后端分离的方式来做这次作业。然后刚开始以为时间有一个月觉得很充足,前面的学习进度不温不热的,到第三周的时候又突然有几门课结课,然后一堆事情,基本每天都学到很晚。第三周的周三左右发现学不完了。于是放弃了前后端的方法,跑去速成pygame。这也是一个教训吧,以后不管时间有多充裕都得提前做好时间不足的准备(
麻了为什么要这么卷)。 - 在本次作业中我的任务是完成游戏主要代码的实现。本次作业是我第一次代码量超过1q行的编程实践。在本次作业中我充分认识到良好的编程习惯是多么重要,包包括注释、空格、缩进等等要注意的东西。以前代码只有小两三百行时感觉不大,但是这次代码量很多时没有注释是真的看不懂自己的代码这部分是在干什么。
- 最后是因为实现的方式是pygame,这是一个比较基层的游戏开发工具,大部分功能都得自己打代码实现,这使得代码行数变得很多。为了减少代码行数了解到代码模块化这个概念,但是第一次使用,对模块类的封装编写什么的不是很熟练,不过还是尝到了甜头,以后多实践熟悉熟悉对我代码编程一定有很大的帮助。