基于Python制作的热血足球小游戏

基于 Python 制作的热血足球小游戏 导语 最近有读者说我发的文章太水了,都是炒冷饭的,那就带大家整点新鲜的东西吧,反正估计今年都得"坐牢"了,炒冷饭的机会有得是

本文包含相关资料包-----> 点击直达获取<-------

基于 Python 制作的热血足球小游戏

导语

最近有读者说我发的文章太水了,都是炒冷饭的,那就带大家整点新鲜的东西吧,反正估计今年都得"坐牢"了,炒冷饭的机会有得是。

好像好久没带大家写新的小游戏了,那么今天就来带大家写个简单的足球小游戏咯(与近期热点绝对无关,狗头戏谑),废话不多说,让我们愉快地开始吧~

开发工具

Python 版本:3.7.8

相关模块:

pygame 模块;

以及一些 python 自带的模块。

环境搭建

安装 Python 并添加到环境变量,pip 安装需要的相关模块即可。

游戏实现

这里简单介绍一下原理吧,首先我们整个简单的开始界面吧:

```python

'''定义游戏开始界面''' def StartInterface(screen, resource_loader, cfg): clock = pygame.time.Clock() font, flag, count = resource_loader.fonts['default30'], True, 0 font_render = font.render('按任意键开始游戏', False, cfg.RED) while True: count += 1 if count > 20: count, flag = 0, not flag for event in pygame.event.get(): if event.type == pygame.QUIT: QuitGame() elif event.type == pygame.KEYDOWN: return True screen.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.position if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75): self.position = ori_position self.rect.left, self.rect.top = self.position # 设置为静止状态 self.is_moving = False

电脑自动控制的核心代码如下:

```python

'''自动更新''' 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.position if 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 = True self.setdirection((1, 0)) if self.prepare_for_kicking: self.prepare_for_kicking_count += 1 if self.prepare_for_kicking_count > self.prepare_for_kicking_freq: self.prepare_for_kicking_count = 0 self.prepare_for_kicking = False ball.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 = True self.setdirection((-1, 0)) if self.prepare_for_kicking: self.prepare_for_kicking_count += 1 if self.prepare_for_kicking_count > self.prepare_for_kicking_freq: self.prepare_for_kicking_count = 0 self.prepare_for_kicking = False ball.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 = True if self.prepare_for_kicking: self.prepare_for_kicking_count += 1 if self.prepare_for_kicking_count > self.prepare_for_kicking_freq: self.prepare_for_kicking_count = 0 self.prepare_for_kicking = False ball.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.position if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75): self.position = ori_position self.rect.left, self.rect.top = self.position else: 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 = 0 else: self.keep_direction_count += 1 self.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.position if self.rect.bottom > 305 and self.rect.top < 505 and (self.rect.right > 1121 or self.rect.left < 75): self.position = ori_position self.rect.left, self.rect.top = self.position ```

逻辑比较简单,大概是这样子的:

  • 守门员:就在球门边上来回走
  • 负责上半场的球员:在上半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;
  • 负责下半场的球员:在下半场出现球的时候就往球的位置移动,如果捕获到了球,则往对方球门移动并随机射门,否则随机移动;
  • 负责全场的球员:往球的位置移动,果捕获到了球,则往对方球门移动并随机射门。

接下来定义一下足球类:

python '''定义足球类''' class Ball(pygame.sprite.Sprite): def __init__(self, images, position): pygame.sprite.Sprite.__init__(self) self.images = images self.image = self.images[0] self.rect = self.image.get_rect() self.rect.centerx, self.rect.centery = position self.mask = pygame.mask.from_surface(self.image) # 球的速度 self.speed = 0 # 球的方向 self.direction = [0, 0] # 控制球的球员 self.taken_by_player = None # 用于切换球动作的变量 self.action_pointer = 0 self.count = 0 self.switch_frequency = 3 # 是否在运动状态 self.is_moving = False '''更新''' def update(self, screen_size): # 静止状态 if not self.is_moving: return # 切换球动作实现动画效果 self.count += 1 if self.count == self.switch_frequency: self.count = 0 self.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 + 30 elif 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 + 30 elif 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 - 15 elif 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 + 50 return # 根据方向移动球 ori_position = self.rect.left, self.rect.right, self.rect.top, self.rect.bottom self.speed = max(self.speed - 1.7 * 0.05, 0.0) if self.speed == 0.0: self.is_moving = False vector = [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 = 305 self.direction = self.direction[0], self.direction[1] * -0.8 elif self.direction[1] < 0: self.rect.top = 505 self.direction = self.direction[0], self.direction[1] * -0.8 if 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 = True self.direction = direction '''踢球''' def kick(self, direction): self.speed = 12 self.direction = direction self.taken_by_player = None self.is_moving = True '''在屏幕上显示''' def draw(self, screen): screen.blit(self.image, self.rect)

比较简单,主要就是两种状态:

  • 被球员捕获,跟着球员走;
  • 被球员踢出去之后根据球员踢的方向和设定的初速度进行减速运动,如果碰到边界则反方向弹出。

最后写个主循环就大功告成啦:

```python

游戏主循环

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] -= 1 if pressed_keys[pygame.K_d]: direction[0] += 1 if pressed_keys[pygame.K_s]: direction[1] += 1 if pressed_keys[pygame.K_a]: direction[0] -= 1 if 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 = True ball.taken_by_player = item for item in players_group2: if pygame.sprite.collide_mask(item, ball) and ball.taken_by_player != item: ball.is_moving = True ball.taken_by_player = item for 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 1 elif ball.rect.left < 75: return 2 ```

比较简单,就不过多介绍了,按 WASD 控制上下左右,空格键射门。

完整源代码详见相关文件~

效果展示

首先安装最新版本的 cpgames:

pip install cpgames==0.1.2

然后写如下代码调用即可运行:

``` from cpgames import cpgames

game_client = cpgames.CPGames() game_client.execute('bloodfootball') ```

效果如下:

参考文献

  • 基于J2EE的球队纪念品销售管理系统的设计与实现(中国地质大学(北京)·王英杰)
  • 基于SSH的大学生联谊交友管理系统设计与实现(华中科技大学·王海波)
  • 面向高职信息技术教育的严肃游戏设计与实施(大连理工大学·王晓姝)
  • 基于ASP.NET开发技术的BBS论坛研究与设计(中国海洋大学·马章勤)
  • 3D云游戏平台的设计与实现(北京交通大学·闫璐)
  • 基于VF的社区物业信息管理系统的设计与实现(电子科技大学·徐玮)
  • 3D云游戏平台的设计与实现(北京交通大学·闫璐)
  • 基于Android的足球球迷综合服务平台的设计与实现(北京工业大学·陈鑫)
  • 基于轻量级J2EE的网络游戏虚拟物品交易系统的设计与实现(北京邮电大学·曹鹃)
  • 基于.NET自定义控件的社区网站系统研究与实现(武汉理工大学·刘亚)
  • 基于云平台的校园足球管理系统的设计与实现(内蒙古大学·张艳秋)
  • 基于SSH架构的个人空间交友网站的设计与实现(北京邮电大学·隋昕航)
  • 基于.NET平台的游戏门户系统设计与实现(电子科技大学·余胜鹏)
  • 基于云平台的校园足球管理系统的设计与实现(内蒙古大学·张艳秋)
  • 基于J2ME的Java手机软件——足球彩票手机投注系统(华侨大学·许向锋)

本文内容包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主题。发布者:源码货栈 ,原文地址:https://m.bishedaima.com/yuanma/36070.html

相关推荐

  • 基于SpringBoot框架的企业客户管理系统

    这是一套采用🔥🔥SpringBoot框架构建的企业级客户管理系统的源代码,主要编程语言为Java,并结合了Vue技术进行开发,开发工具可选用Idea或Eclipse,此系统适合作为毕业设计或课程设计的任务
    2024年05月23日
    2 1 1
  • 基于Java+SSM的校园二手交易平台

    校园二手交易平台在当今大学生活中扮演着重要角色,随着互联网技术的迅速发展,基于Java+SSM的校园二手交易平台日益受到关注,这种平台为校友提供了一个便捷的渠道,可以轻松地发布和购买二手商品
    2024年05月07日
    6 1 1
  • 汽车资讯网站

    这是一个🔥🔥基于SpringBoot框架的汽车资讯网站设计与实现🔥🔥的项目源码,开发语言Java,框架使用的SpringBoot+vue技术,开发环境Idea/Eclipse
    2024年05月23日
    5 1 1
  • 在线文档管理系统

    这是一个🔥🔥基于SpringBoot框架的在线文档管理系统设计与实现🔥🔥的项目源码,开发语言Java,框架使用的SpringBoot+vue技术,开发环境Idea/Eclipse
    2024年05月23日
    1 1 1
  • C++模拟爱奇艺web视频上传

    c++模拟爱奇艺web视频上传 说明 此次学习的是HTTP的post协议,使用使用multipart form-data上传文件, 理解HTTP消息头 (五)——使用multipart/form-data上传文件 写的比较好的一篇帖子 https://www
    2024年05月14日
    3 1 3
  • 基于Java和Servlet实现的教务管理系统

    基于Java和Servlet实现的教务管理系统 第1章 引言 1,1 开发背景 随着科技的发展,基本上所有的具有一定数据的机构都开始使用计算机数据库来做管理
    2024年05月14日
    20 1 2
  • 基于SSM框架的考勤签到请假系统

    这是一个🔥🔥基于SSM框架的考勤签到请假系统🔥🔥的项目源码,开发语言Java,开发环境Idea/Eclipse,这个 考勤请假系统开发技术栈为SSM项目,可以作为毕业设计课程设计作业使用SSM框架+shiro实现一个支持三个角色(管理员 员工 经理)的员工考勤系统
    2024年05月23日
    39 1 7
  • 基于SpringBoot框架的游戏交易系统

    这是一套采用Java语言开发的🔥🔥SpringBoot游戏交易系统源代码🔥🔥,框架结合了SpringBoot和Vue技术,适用于Idea或Eclipse开发环境,此项目可作为毕业设计或课程设计的任务
    2024年05月23日
    19 1 1
  • 基于SpringBoot框架的网上点餐系统

    这是一套采用Java编程语言,基于SpringBoot框架构建的在线订餐系统源代码,项目中运用了SpringBoot和Vue技术栈,开发工具为Idea或Eclipse
    2024年05月23日
    10 1 1
  • 基于Python的预测商品销售数据

    预测商品销售数据 实验目的 通过使用一个具有挑战性的时间序列数据集,该数据集由每日销售数据,由俄罗斯最大的软件公司之一 1C 公司提供, 数据集中提供了 2013 年 1 月到 2015 年 10 月每日每个店铺中的商品历史销售数据
    2024年05月14日
    4 1 1

发表回复

登录后才能评论