本文主要是介绍python小游戏毕设 热血足球游戏设计与实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 0 项目简介
- 1 游戏介绍
- 2 实现效果
- 3 开发工具
- 3.1 环境配置
- 3.2 Pygame介绍
- 4 具体实现
- 5 最后
0 项目简介
🔥 Hi,各位同学好呀,这里是L学长!
🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品
热血足球游戏设计与实现
🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分)
-
难度系数:3分
-
工作量:3分
-
创新点:4分
1 游戏介绍
利用Python实现的简单的足球小游戏。
游戏规则:
比较简单,就不过多介绍了,按WASD控制上下左右,空格键射门。
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 具体实现
这里简单介绍一下原理吧,首先我们整个简单的开始界面吧:
'''定义游戏开始界面'''
def StartInterface(screen, resource_loader, cfg):clock = pygame.time.Clock()font, flag, count = resource_loader.fonts['default30'], True, 0font_render = font.render('按任意键开始游戏', False, cfg.RED)while True:count += 1if count > 20: count, flag = 0, not flagfor event in pygame.event.get():if event.type == pygame.QUIT:QuitGame()elif event.type == pygame.KEYDOWN:return Truescreen.blit(resource_loader.images['background_start'], (0, 0))if flag: screen.blit(font_render, ((cfg.SCREENSIZE[0] - font.size('按任意键开始游戏')[0]) // 2, cfg.SCREENSIZE[1] - 200))clock.tick(cfg.FPS)pygame.display.update()
效果大概是这样子的:
方便起见,我们设置成了按任意键都可以开始游戏。
接下来,我们来定义一下球员类,球员分为电脑自动控制和我们手动控制两种类型,其中我们手动控制的核心代码如下:
'''更新'''
def update(self, screen_size, ball):# 电脑自动控制if self.auto_control:self.autoupdate(screen_size, ball)return# 静止状态if not self.is_moving: return# 切换人物动作实现动画效果self.switch()# 根据方向移动人物ori_position = self.position.copy()speed = self.speed * self.direction[0], self.speed * self.direction[1]self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)self.rect.left, self.rect.top = self.positionif self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):self.position = ori_positionself.rect.left, self.rect.top = self.position# 设置为静止状态self.is_moving = False
电脑自动控制的核心代码如下:
'''自动更新'''
def autoupdate(self, screen_size, ball):# 守门员if self.player_type == 'goalkeeper':self.speed = 1# --沿着门漫步def wondering(self):self.switch()self.position[1] = min(max(305, self.position[1] + self.direction[1] * self.speed), 459)self.rect.left, self.rect.top = self.positionif self.rect.top == 305 or self.rect.top == 459: self.direction = self.direction[0], -self.direction[1]self.setdirection(self.direction)# --有球就随机射球if ball.taken_by_player == self:if self.group_id == 1:if random.random() > 0.8 or self.prepare_for_kicking:self.prepare_for_kicking = Trueself.setdirection((1, 0))if self.prepare_for_kicking:self.prepare_for_kicking_count += 1if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:self.prepare_for_kicking_count = 0self.prepare_for_kicking = Falseball.kick(self.direction)self.setdirection(random.choice([(0, 1), (0, -1)]))else:wondering(self)else:if random.random() > 0.8 or self.prepare_for_kicking:self.prepare_for_kicking = Trueself.setdirection((-1, 0))if self.prepare_for_kicking:self.prepare_for_kicking_count += 1if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:self.prepare_for_kicking_count = 0self.prepare_for_kicking = Falseball.kick(self.direction)self.setdirection(random.choice([(0, 1), (0, -1)]))else:wondering(self)# --没球来回走else:wondering(self)# 其他球员跟着球走else:if ball.taken_by_player == self:self.switch()if self.group_id == 1:self.direction = min(max(1150 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)else:self.direction = min(max(350 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)self.setdirection(self.direction)if (random.random() > 0.9 and self.position[0] > 350 and self.position[0] < 1150) or self.prepare_for_kicking:if self.group_id == 1:self.direction = min(max(1190 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)else:self.direction = min(max(310 - self.rect.left, -1), 1), min(max(405 - self.rect.top, -1), 1)self.setdirection(self.direction)self.prepare_for_kicking = Trueif self.prepare_for_kicking:self.prepare_for_kicking_count += 1if self.prepare_for_kicking_count > self.prepare_for_kicking_freq:self.prepare_for_kicking_count = 0self.prepare_for_kicking = Falseball.kick(self.direction)else:speed = self.speed * self.direction[0], self.speed * self.direction[1]ori_position = self.position.copy()self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)self.rect.left, self.rect.top = self.positionif self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):self.position = ori_positionself.rect.left, self.rect.top = self.positionelse:self.switch()if (ball.rect.centery > 400 and self.player_type == 'bottomhalf') or (ball.rect.centery <= 400 and self.player_type == 'upperhalf') or self.player_type == 'common':self.direction = min(max(ball.rect.left - self.rect.left, -1), 1), min(max(ball.rect.top - self.rect.top, -1), 1)self.direction = self.direction[0] * random.random(), self.direction[1] * random.random()else:if self.keep_direction_count >= self.keep_direction_freq:self.direction = random.choice([-1, 0, 1]), random.choice([-1, 0, 1])self.keep_direction_count = 0else:self.keep_direction_count += 1self.setdirection(self.direction)speed = self.speed * self.direction[0], self.speed * self.direction[1]ori_position = self.position.copy()self.position[0] = min(max(0, self.position[0] + speed[0]), screen_size[0] - 48)self.position[1] = min(max(0, self.position[1] + speed[1]), screen_size[1] - 48)self.rect.left, self.rect.top = self.positionif self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75):self.position = ori_positionself.rect.left, self.rect.top = self.position
逻辑比较简单,大概是这样子的:
-
守门员:就在球门边上来回走
-
负责上半场的球员:在上半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;
-
负责下半场的球员:在下半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;
-
负责全场的球员:往球的位置移动,果捕获到了球,则往对方球门移动并随机射门。
接下来定义一下足球类:
'''定义足球类'''
class Ball(pygame.sprite.Sprite):def __init__(self, images, position):pygame.sprite.Sprite.__init__(self)self.images = imagesself.image = self.images[0]self.rect = self.image.get_rect()self.rect.centerx, self.rect.centery = positionself.mask = pygame.mask.from_surface(self.image)# 球的速度self.speed = 0# 球的方向self.direction = [0, 0]# 控制球的球员self.taken_by_player = None# 用于切换球动作的变量self.action_pointer = 0self.count = 0self.switch_frequency = 3# 是否在运动状态self.is_moving = False'''更新'''def update(self, screen_size):# 静止状态if not self.is_moving: return# 切换球动作实现动画效果self.count += 1if self.count == self.switch_frequency:self.count = 0self.action_pointer = (self.action_pointer + 1) % len(self.images)self.image = self.images[self.action_pointer]# 如果球是被球员控制的if self.taken_by_player is not None:self.setdirection(self.taken_by_player.direction)if self.taken_by_player.direction[0] < 0:self.rect.left, self.rect.top = self.taken_by_player.rect.left - 15, self.taken_by_player.rect.top + 30elif self.taken_by_player.direction[0] > 0:self.rect.left, self.rect.top = self.taken_by_player.rect.left + 30, self.taken_by_player.rect.top + 30elif self.taken_by_player.direction[1] < 0:self.rect.left, self.rect.top = self.taken_by_player.rect.left + 15, self.taken_by_player.rect.top - 15elif self.taken_by_player.direction[1] > 0:self.rect.left, self.rect.top = self.taken_by_player.rect.left + 10, self.taken_by_player.rect.top + 50return# 根据方向移动球ori_position = self.rect.left, self.rect.right, self.rect.top, self.rect.bottomself.speed = max(self.speed - 1.7 * 0.05, 0.0)if self.speed == 0.0: self.is_moving = Falsevector = [self.speed * self.direction[0], self.speed * self.direction[1]]vector[0] = vector[0] / math.pow(self.direction[0] ** 2 + self.direction[1] ** 2, 0.5)vector[1] = vector[1] / math.pow(self.direction[0] ** 2 + self.direction[1] ** 2, 0.5)self.rect.left = min(max(0, self.rect.left + vector[0]), screen_size[0] - 48)if self.rect.left == 0 or self.rect.left == screen_size[0] - 48: self.direction = self.direction[0] * -0.8, self.direction[1]self.rect.top = min(max(0, self.rect.top + vector[1]), screen_size[1] - 48)if ori_position[1] > 1121 or ori_position[0] < 75:if self.rect.bottom > 305 and self.rect.top < 505:if self.direction[1] > 0:self.rect.bottom = 305self.direction = self.direction[0], self.direction[1] * -0.8elif self.direction[1] < 0:self.rect.top = 505self.direction = self.direction[0], self.direction[1] * -0.8if self.rect.top == 0 or self.rect.top == screen_size[1] - 48:self.direction = self.direction[0], self.direction[1] * -0.8'''设置方向'''def setdirection(self, direction):self.is_moving = Trueself.direction = direction'''踢球'''def kick(self, direction):self.speed = 12self.direction = directionself.taken_by_player = Noneself.is_moving = True'''在屏幕上显示'''def draw(self, screen):screen.blit(self.image, self.rect)
比较简单,主要就是两种状态:
-
被球员捕获,跟着球员走;
-
被球员踢出去之后根据球员踢的方向和设定的初速度进行减速运动,如果碰到边界则反方向弹出。
最后写个主循环就大功告成啦:
# 游戏主循环
clock = pygame.time.Clock()
while True:# --基础背景绘制screen.fill(cfg.LIGHTGREEN)pygame.draw.circle(screen, cfg.WHITE, (600, 400), 80, 5)pygame.draw.rect(screen, cfg.WHITE, (10, 10, 600, 790), 5)pygame.draw.rect(screen, cfg.WHITE, (600, 10, 590, 790), 5)pygame.draw.rect(screen, cfg.WHITE, (10, 150, 300, 500), 5)pygame.draw.rect(screen, cfg.WHITE, (890, 150, 300, 500), 5)screen.blit(resource_loader.images['doors'][0].convert(), (8, 305))screen.blit(resource_loader.images['doors'][1].convert(), (1121, 305))screen.blit(score_board, (565, 15))# --事件监听for event in pygame.event.get():if event.type == pygame.QUIT:QuitGame()elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:QuitGame()pressed_keys = pygame.key.get_pressed()direction = [0, 0]if pressed_keys[pygame.K_w]: direction[1] -= 1if pressed_keys[pygame.K_d]: direction[0] += 1if pressed_keys[pygame.K_s]: direction[1] += 1if pressed_keys[pygame.K_a]: direction[0] -= 1if direction != [0, 0]: player_controlled.setdirection(direction)if pressed_keys[pygame.K_SPACE] and player_controlled == ball.taken_by_player: ball.kick(player_controlled.direction)# --更新玩家for item in players_group1:if pygame.sprite.collide_mask(item, ball) and ball.taken_by_player != item: ball.is_moving = Trueball.taken_by_player = itemfor item in players_group2:if pygame.sprite.collide_mask(item, ball) and ball.taken_by_player != item: ball.is_moving = Trueball.taken_by_player = itemfor item in players_group1:item.update(cfg.SCREENSIZE_GAMING, ball)for item in players_group2:item.update(cfg.SCREENSIZE_GAMING, ball)# --更新球ball.update(cfg.SCREENSIZE_GAMING)# --更新屏幕ball.draw(screen)players_group1.draw(screen)players_group2.draw(screen)clock.tick(cfg.FPS)pygame.display.update()# --计算得分if ball.rect.bottom > 305 and ball.rect.top < 505:if ball.rect.right > 1121: return 1elif ball.rect.left < 75: return 2
5 最后
这篇关于python小游戏毕设 热血足球游戏设计与实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!