文章目录
0 项目简介1 游戏介绍2 实现效果3 开发工具3.1 环境配置3.2 Pygame介绍4 具体实现4.1 实现游戏主循环4.2 制作游戏开始和结束界面5 最后0 项目简介
🔥 Hi,各位同学好呀,这里是L学长!
🥇今天向大家分享一个今年()最新完成的毕业设计项目作品
python小游戏毕设 坦克大战小游戏设计与实现 (源码)
🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分)
难度系数:3分
工作量:3分
创新点:4分
项目获取:
/sinonfin/L-javaWebSha/tree/master
1 游戏介绍
《坦克大战》是由日本南梦宫Namco游戏公司开发的一款平面射击游戏,于1985年发售。游戏以坦克战斗及保卫基地为主题,属于策略型联机类。
同时也是FC平台上少有的内建关卡编辑器的几个游戏之一,玩家可自己创建独特的关卡,并通过获取一些道具使坦克和基地得到强化。
今天我们利用python实现简易版坦克大战游戏。
2 实现效果
3 开发工具
3.1 环境配置
Python版本:3.6.4
相关模块:
pygame模块;
以及一些Python自带的模块。
3.2 Pygame介绍
简介
Pygame是一系列专门为编写电子游戏而设计的Python模块(modules)。Pygame在已经非常优秀的SDL库的基础上增加了许多功能。这让你能够用Python语言编写出丰富多彩的游戏程序。
Pygame可移植性高,几乎能在任何平台和操作系统上运行。
Pygame已经被下载过数百万次。
Pygame免费开源。它在LGPL许可证(Lesser General Public License,GNU宽通用公共许可证)下发行。使用Pygame,你可以创造出免费开源,可共享,或者商业化的游戏。详情请见LGPL许可证。
优点
能够轻松使用多核CPU(multi core CPUs) :如今双核CPU很常用,8核CPU在桌面系统中也很便宜,而利用好多核系统,能让你在你的游戏中实现更多东西。特定的pygame函数能够释放令人生畏的python GIL(全局解释器锁),这几乎是你用C语言才能做的事。
核心函数用最优化的C语言或汇编语言编写:C语言代码通常比Python代码运行速度快10-20倍。而汇编语言编写的代码(assembly code)比Python甚至快到100多倍。
安装便捷:一般仅需包管理程序或二进制系统程序便能安装。
真正地可移植:支持Linux (主要发行版), Windows (95, 98, ME, 2000, XP, Vista, 64-bit Windows,), Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX等操作系统.也能支持AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS and OS/2,但是还没有受到官方认可。你也可以在手持设备,游戏控制台, One Laptop Per Child (OLPC) computer项目的电脑等设备中使用pygame.
用法简单:无论是小孩子还是大人都能学会用pygame来制作射击类游戏。
很多Pygame游戏已发行:其中包括很多游戏大赛入围作品、非常受欢迎的开源可分享的游戏。
由你来控制主循环:由你来调用pygame的函数,pygame的函数并不需要调用你的函数。当你同时还在使用其他库来编写各种各种的程序时,这能够为你提供极大的掌控权。
不需要GUI就能使用所有函数:仅在命令行中,你就可以使用pygame的某些函数来处理图片,获取游戏杆输入,播放音乐……
对bug反应迅速:很多bug在被上报的1小时内就能被我们修复。虽然有时候我们确实会卡在某一个bug上很久,但大多数时候我们都是很不错的bug修复者。如今bug的上报已经很少了,因为许多bug早已被我们修复。
代码量少:pygame并没有数以万计的也许你永远用不到的冗杂代码。pygame的核心代码一直保持着简洁特点,其他附加物诸如GUI库等,都是在核心代码之外单独设计研发的。
模块化:你可以单独使用pygame的某个模块。想要换着使用一个别的声音处理库?没问题。pygame的很多核心模块支持独立初始化与使用。
最小开发框架
import pygame,sys #sys是python的标准库,提供Python运行时环境变量的操控pygame.init() #内部各功能模块进行初始化创建及变量设置,默认调用size = width,height = 800,600 #设置游戏窗口大小,分别是宽度和高度screen = pygame.display.set_mode(size) #初始化显示窗口pygame.display.set_caption("小游戏程序") #设置显示窗口的标题内容,是一个字符串类型while True: #无限循环,直到Python运行时退出结束for event in pygame.event.get(): #从Pygame的事件队列中取出事件,并从队列中删除该事件if event.type == pygame.QUIT: #获得事件类型,并逐类响应sys.exit() #用于退出结束游戏并退出pygame.display.update() #对显示窗口进行更新,默认窗口全部重绘
代码执行流程
4 具体实现
4.1 实现游戏主循环
# 主函数def main():# 初始化pygame.init()screen = pygame.display.set_mode((630, 630))pygame.display.set_caption("坦克大战")# 加载图片bg_img = pygame.image.load("./图片/others/background.png")# 开始界面num_player = show_start_interface(screen, 630, 630)# 关卡stage = 0num_stage = 2# 游戏是否结束is_gameover = False# 时钟clock = pygame.time.Clock()# 主循环while not is_gameover:# 关卡stage += 1if stage > num_stage:breakshow_switch_stage(screen, 630, 630, stage)# 该关卡坦克总数量enemytanks_total = min(stage * 18, 80)# 场上存在的敌方坦克总数量enemytanks_now = 0# 场上可以存在的敌方坦克总数量enemytanks_now_max = min(max(stage * 2, 4), 8)# 精灵组tanksGroup = pygame.sprite.Group()mytanksGroup = pygame.sprite.Group()enemytanksGroup = pygame.sprite.Group()bulletsGroup = pygame.sprite.Group()mybulletsGroup = pygame.sprite.Group()enemybulletsGroup = pygame.sprite.Group()myfoodsGroup = pygame.sprite.Group()# 自定义事件# -生成敌方坦克事件genEnemyEvent = pygame.constants.USEREVENT + 0pygame.time.set_timer(genEnemyEvent, 100)# -敌方坦克静止恢复事件recoverEnemyEvent = pygame.constants.USEREVENT + 1pygame.time.set_timer(recoverEnemyEvent, 8000)# -我方坦克无敌恢复事件noprotectMytankEvent = pygame.constants.USEREVENT + 2pygame.time.set_timer(noprotectMytankEvent, 8000)# 关卡地图map_stage = scene.Map(stage)# 我方坦克tank_player1 = tanks.myTank(1)tanksGroup.add(tank_player1)mytanksGroup.add(tank_player1)if num_player > 1:tank_player2 = tanks.myTank(2)tanksGroup.add(tank_player2)mytanksGroup.add(tank_player2)is_switch_tank = Trueplayer1_moving = Falseplayer2_moving = False# 为了轮胎的动画效果time = 0# 敌方坦克for i in range(0, 3):if enemytanks_total > 0:enemytank = tanks.enemyTank(i)tanksGroup.add(enemytank)enemytanksGroup.add(enemytank)enemytanks_now += 1enemytanks_total -= 1# 大本营myhome = home.Home()# 出场特效appearance_img = pygame.image.load("./图片/others/appear.png").convert_alpha()appearances = []appearances.append(appearance_img.subsurface((0, 0), (48, 48)))appearances.append(appearance_img.subsurface((48, 0), (48, 48)))appearances.append(appearance_img.subsurface((96, 0), (48, 48)))# 关卡主循环while True:if is_gameover is True:breakif enemytanks_total < 1 and enemytanks_now < 1:is_gameover = Falsebreakfor event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == genEnemyEvent:if enemytanks_total > 0:if enemytanks_now < enemytanks_now_max:enemytank = tanks.enemyTank()if not pygame.sprite.spritecollide(enemytank, tanksGroup, False, None):tanksGroup.add(enemytank)enemytanksGroup.add(enemytank)enemytanks_now += 1enemytanks_total -= 1if event.type == recoverEnemyEvent:for each in enemytanksGroup:each.can_move = Trueif event.type == noprotectMytankEvent:for each in mytanksGroup:mytanksGroup.protected = False# 检查用户键盘操作key_pressed = pygame.key.get_pressed()# 玩家一# WSAD -> 上下左右# 空格键射击if key_pressed[pygame.K_w]:tanksGroup.remove(tank_player1)tank_player1.move_up(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player1)player1_moving = Trueelif key_pressed[pygame.K_s]:tanksGroup.remove(tank_player1)tank_player1.move_down(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player1)player1_moving = Trueelif key_pressed[pygame.K_a]:tanksGroup.remove(tank_player1)tank_player1.move_left(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player1)player1_moving = Trueelif key_pressed[pygame.K_d]:tanksGroup.remove(tank_player1)tank_player1.move_right(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player1)player1_moving = Trueelif key_pressed[pygame.K_SPACE]:if not tank_player1.bullet.being:tank_player1.shoot()# 玩家二# ↑↓←→ -> 上下左右# 小键盘0键射击if num_player > 1:if key_pressed[pygame.K_UP]:tanksGroup.remove(tank_player2)tank_player2.move_up(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player2)player2_moving = Trueelif key_pressed[pygame.K_DOWN]:tanksGroup.remove(tank_player2)tank_player2.move_down(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player2)player2_moving = Trueelif key_pressed[pygame.K_LEFT]:tanksGroup.remove(tank_player2)tank_player2.move_left(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player2)player2_moving = Trueelif key_pressed[pygame.K_RIGHT]:tanksGroup.remove(tank_player2)tank_player2.move_right(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(tank_player2)player2_moving = Trueelif key_pressed[pygame.K_KP0]:if not tank_player2.bullet.being:tank_player2.shoot()# 背景screen.blit(bg_img, (0, 0))# 石头墙for each in map_stage.brickGroup:screen.blit(each.brick, each.rect)# 钢墙for each in map_stage.ironGroup:screen.blit(each.iron, each.rect)# 冰for each in map_stage.iceGroup:screen.blit(each.ice, each.rect)# 河流for each in map_stage.riverGroup:screen.blit(each.river, each.rect)# 树for each in map_stage.treeGroup:screen.blit(each.tree, each.rect)time += 1if time == 5:time = 0is_switch_tank = not is_switch_tank# 我方坦克if tank_player1 in mytanksGroup:if is_switch_tank and player1_moving:screen.blit(tank_player1.tank_0, (tank_player1.rect.left, tank_player1.rect.top))player1_moving = Falseelse:screen.blit(tank_player1.tank_1, (tank_player1.rect.left, tank_player1.rect.top))if tank_player1.protected:screen.blit(tank_player1.protected_mask1, (tank_player1.rect.left, tank_player1.rect.top))if num_player > 1:if tank_player2 in mytanksGroup:if is_switch_tank and player2_moving:screen.blit(tank_player2.tank_0, (tank_player2.rect.left, tank_player2.rect.top))player1_moving = Falseelse:screen.blit(tank_player2.tank_1, (tank_player2.rect.left, tank_player2.rect.top))if tank_player2.protected:screen.blit(tank_player1.protected_mask1, (tank_player2.rect.left, tank_player2.rect.top))# 敌方坦克for each in enemytanksGroup:# 出生特效if each.born:if each.times > 0:each.times -= 1if each.times <= 10:screen.blit(appearances[2], (3+each.x*12*24, 3))elif each.times <= 20:screen.blit(appearances[1], (3+each.x*12*24, 3))elif each.times <= 30:screen.blit(appearances[0], (3+each.x*12*24, 3))elif each.times <= 40:screen.blit(appearances[2], (3+each.x*12*24, 3))elif each.times <= 50:screen.blit(appearances[1], (3+each.x*12*24, 3))elif each.times <= 60:screen.blit(appearances[0], (3+each.x*12*24, 3))elif each.times <= 70:screen.blit(appearances[2], (3+each.x*12*24, 3))elif each.times <= 80:screen.blit(appearances[1], (3+each.x*12*24, 3))elif each.times <= 90:screen.blit(appearances[0], (3+each.x*12*24, 3))else:each.born = Falseelse:if is_switch_tank:screen.blit(each.tank_0, (each.rect.left, each.rect.top))else:screen.blit(each.tank_1, (each.rect.left, each.rect.top))if each.can_move:tanksGroup.remove(each)each.move(tanksGroup, map_stage.brickGroup, map_stage.ironGroup, myhome)tanksGroup.add(each)# 我方子弹for tank_player in mytanksGroup:if tank_player.bullet.being:tank_player.bullet.move()screen.blit(tank_player.bullet.bullet, tank_player.bullet.rect)# 子弹碰撞敌方子弹for each in enemybulletsGroup:if each.being:if pygame.sprite.collide_rect(tank_player.bullet, each):tank_player.bullet.being = Falseeach.being = FalseenemybulletsGroup.remove(each)breakelse:enemybulletsGroup.remove(each)# 子弹碰撞敌方坦克for each in enemytanksGroup:if each.being:if pygame.sprite.collide_rect(tank_player.bullet, each):if each.is_red == True:myfood = food.Food()myfood.generate()myfoodsGroup.add(myfood)each.is_red = Falseeach.blood -= 1each.color -= 1if each.blood < 0:each.being = FalseenemytanksGroup.remove(each)enemytanks_now -= 1tanksGroup.remove(each)else:each.reload()tank_player.bullet.being = Falsebreakelse:enemytanksGroup.remove(each)tanksGroup.remove(each)# 子弹碰撞石头墙if pygame.sprite.spritecollide(tank_player.bullet, map_stage.brickGroup, True, None):tank_player.bullet.being = False'''# 等价方案(更科学点)for each in map_stage.brickGroup:if pygame.sprite.collide_rect(tank_player.bullet, each):tank_player.bullet.being = Falseeach.being = Falsemap_stage.brickGroup.remove(each)break'''# 子弹碰钢墙if tank_player.bullet.stronger:if pygame.sprite.spritecollide(tank_player.bullet, map_stage.ironGroup, True, None):tank_player.bullet.being = Falseelse:if pygame.sprite.spritecollide(tank_player.bullet, map_stage.ironGroup, False, None):tank_player.bullet.being = False'''# 等价方案(更科学点)for each in map_stage.ironGroup:if pygame.sprite.collide_rect(tank_player.bullet, each):tank_player.bullet.being = Falseif tank_player.bullet.stronger:each.being = Falsemap_stage.ironGroup.remove(each)break'''# 子弹碰大本营if pygame.sprite.collide_rect(tank_player.bullet, myhome):tank_player.bullet.being = Falsemyhome.set_dead()is_gameover = True# 敌方子弹for each in enemytanksGroup:if each.being:if each.can_move and not each.bullet.being:enemybulletsGroup.remove(each.bullet)each.shoot()enemybulletsGroup.add(each.bullet)if not each.born:if each.bullet.being:each.bullet.move()screen.blit(each.bullet.bullet, each.bullet.rect)# 子弹碰撞我方坦克for tank_player in mytanksGroup:if pygame.sprite.collide_rect(each.bullet, tank_player):if not tank_player.protected:tank_player.life -= 1if tank_player.life < 0:mytanksGroup.remove(tank_player)tanksGroup.remove(tank_player)if len(mytanksGroup) < 1:is_gameover = Trueelse:tank_player.reset()each.bullet.being = FalseenemybulletsGroup.remove(each.bullet)break# 子弹碰撞石头墙if pygame.sprite.spritecollide(each.bullet, map_stage.brickGroup, True, None):each.bullet.being = FalseenemybulletsGroup.remove(each.bullet)'''# 等价方案(更科学点)for one in map_stage.brickGroup:if pygame.sprite.collide_rect(each.bullet, one):each.bullet.being = Falseone.being = FalseenemybulletsGroup.remove(one)break'''# 子弹碰钢墙if each.bullet.stronger:if pygame.sprite.spritecollide(each.bullet, map_stage.ironGroup, True, None):each.bullet.being = Falseelse:if pygame.sprite.spritecollide(each.bullet, map_stage.ironGroup, False, None):each.bullet.being = False'''# 等价方案(更科学点)for one in map_stage.ironGroup:if pygame.sprite.collide_rect(each.bullet, one):each.bullet.being = Falseif each.bullet.stronger:one.being = Falsemap_stage.ironGroup.remove(one)break'''# 子弹碰大本营if pygame.sprite.collide_rect(each.bullet, myhome):each.bullet.being = Falsemyhome.set_dead()is_gameover = Trueelse:enemytanksGroup.remove(each)tanksGroup.remove(each)# 家screen.blit(myhome.home, myhome.rect)# 食物for myfood in myfoodsGroup:if myfood.being and myfood.time > 0:screen.blit(myfood.food, myfood.rect)myfood.time -= 1for tank_player in mytanksGroup:if pygame.sprite.collide_rect(tank_player, myfood):# 消灭当前所有敌人if myfood.kind == 0:enemytanksGroup = pygame.sprite.Group()enemytanks_total -= enemytanks_nowenemytanks_now = 0# 敌人静止if myfood.kind == 1:for each in enemytanksGroup:each.can_move = False# 子弹增强if myfood.kind == 2:tank_player.bullet.stronger = True# 使得大本营的墙变为钢板if myfood.kind == 3:map_stage.protect_home()# 坦克获得一段时间的保护罩if myfood.kind == 4:for tank_player in mytanksGroup:tank_player.protected = True# 坦克升级if myfood.kind == 5:tank_player.up_level()# 坦克生命+1if myfood.kind == 6:tank_player.life += 1myfood.being = FalsemyfoodsGroup.remove(myfood)breakelse:myfood.being = FalsemyfoodsGroup.remove(myfood)pygame.display.flip()clock.tick(60)if not is_gameover:show_end_interface(screen, 630, 630, True)else:show_end_interface(screen, 630, 630, False)
4.2 制作游戏开始和结束界面
# 开始界面显示def show_start_interface(screen, width, height):tfont = pygame.font.Font('./font/simkai.ttf', width//4)cfont = pygame.font.Font('./font/simkai.ttf', width//20)title = tfont.render(u'坦克大战', True, (255, 0, 0))content1 = cfont.render(u'按1键进入单人游戏', True, (0, 0, 255))content2 = cfont.render(u'按2键进入双人人游戏', True, (0, 0, 255))trect = title.get_rect()trect.midtop = (width/2, height/4)crect1 = content1.get_rect()crect1.midtop = (width/2, height/1.8)crect2 = content2.get_rect()crect2.midtop = (width/2, height/1.6)screen.blit(title, trect)screen.blit(content1, crect1)screen.blit(content2, crect2)pygame.display.update()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()elif event.type == pygame.KEYDOWN:if event.key == pygame.K_1:return 1if event.key == pygame.K_2:return 2
# 结束界面显示def show_end_interface(screen, width, height, is_win):bg_img = pygame.image.load("./图片/others/background.png")screen.blit(bg_img, (0, 0))if is_win:font = pygame.font.Font('./font/simkai.ttf', width//10)content = font.render(u'恭喜通关!', True, (255, 0, 0))rect = content.get_rect()rect.midtop = (width/2, height/2)screen.blit(content, rect)else:fail_img = pygame.image.load("./图片/others/gameover.png")rect = fail_img.get_rect()rect.midtop = (width/2, height/2)screen.blit(fail_img, rect)pygame.display.update()while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()
# 关卡切换def show_switch_stage(screen, width, height, stage):bg_img = pygame.image.load("./图片/others/background.png")screen.blit(bg_img, (0, 0))font = pygame.font.Font('./font/simkai.ttf', width//10)content = font.render(u'第%d关' % stage, True, (0, 255, 0))rect = content.get_rect()rect.midtop = (width/2, height/2)screen.blit(content, rect)pygame.display.update()delay_event = pygame.constants.USEREVENTpygame.time.set_timer(delay_event, 1000)while True:for event in pygame.event.get():if event.type == QUIT:sys.exit()if event.type == delay_event:return
5 最后
项目获取:
/sinonfin/L-javaWebSha/tree/master
如果觉得《python小游戏毕设 坦克大战小游戏设计与实现 (源码)》对你有帮助,请点赞、收藏,并留下你的观点哦!