当前位置: 首页 > news >正文

使用Pygame做一个乒乓球游戏

项目介绍

使用Pygame做一个乒乓球游戏。左侧为电脑,右侧为玩家。

在这里插入图片描述

视频地址-YT
视频搬运-B站
视频教程约90分钟。
代码地址

环境:需要pygame库,可用pip安装:pip install pygame

1. 基础版本

v1-1

首先进行一些初始化,初始化pygame以及物体的初始状态。
然后是主循环,游戏的主循环主要包含3个内容

  1. 处理事件(这里主要是键盘按键)
  2. 更新物体的状态
  3. 在屏幕上绘制
# 基础 ping pang游戏
import sys
import random
import pygame# 初始化
pygame.init()
clock = pygame.time.Clock()screen_width = 1280
screen_height = 720
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("PingPang")
# 使用长方形表示球和球拍
ball = pygame.Rect(screen_width // 2 - 15, screen_height // 2 - 15, 30, 30)
player = pygame.Rect(screen_width - 20, screen_height // 2 - 70, 10, 140)
opponent = pygame.Rect(10, screen_height // 2 - 70, 10, 140)bg_color = pygame.Color('grey12')
light_grey = (200, 200, 200)ball_speed_x = 7 * random.choice((1, -1))
ball_speed_y = 7 * random.choice((1, -1))    
player_speed = 0
opponent_speed = 7while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_DOWN:player_speed += 7if event.key == pygame.K_UP:player_speed -= 7if event.type == pygame.KEYUP:if event.key == pygame.K_DOWN:player_speed -= 7if event.key == pygame.K_UP:player_speed += 7# update#ball_animation()#player_animation()#opponent_animation()# drawscreen.fill(bg_color)pygame.draw.rect(screen, light_grey, player)pygame.draw.rect(screen, light_grey, opponent)pygame.draw.ellipse(screen, light_grey, ball)pygame.draw.aaline(screen, light_grey, (screen_width / 2, 0), (screen_width / 2, screen_height))pygame.display.flip()clock.tick(60)

v1-2

然后我们实现上面的三个更新逻辑,更新物体状态。

  • ball_animation()
  • player_animation()
  • opponent_animation()
def ball_animation():"""更新球的运动"""global ball_speed_x, ball_speed_yball.x += ball_speed_xball.y += ball_speed_yif ball.top <= 0 or ball.bottom >= screen_height:ball_speed_y *= -1if ball.left <= 0 or ball.right >= screen_width:ball_speed_x *= -1ball_restart()if ball.colliderect(player) or ball.colliderect(opponent):ball_speed_x *= -1def player_animation():"""更新玩家的运动"""player.y += player_speedif player.top <= 0:player.top = 0if player.bottom >= screen_height:player.bottom = screen_heightdef opponent_animation():"""更新对手的运动"""if opponent.top < ball.y:opponent.top += opponent_speedif opponent.bottom > ball.y:opponent.bottom -= opponent_speedif opponent.top <= 0:opponent.top = 0if opponent.bottom >= screen_height:opponent.bottom = screen_heightdef ball_restart():"""重置球的位置"""global ball_speed_x, ball_speed_yball.center = (screen_width // 2, screen_height // 2)ball_speed_y *= random.choice((1, -1))ball_speed_x *= random.choice((1, -1))

实现了这3个函数后,记得在主循环中的# update 处调用这个三个函数。

2. 添加分数和时间

  1. 为游戏添加分数显示:添加字体并渲染出分数。
  2. 发球时有3秒倒计时:通过pygame.time.get_ticks() 获得时间。

在这里插入图片描述

# 添加得分和计时器
import sys
import random
import pygamepygame.init()
clock = pygame.time.Clock()screen_width = 1280
screen_height = 720
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("PingPang")ball = pygame.Rect(screen_width // 2 - 15, screen_height // 2 - 15, 30, 30)
player = pygame.Rect(screen_width - 20, screen_height // 2 - 70, 10, 140)
opponent = pygame.Rect(10, screen_height // 2 - 70, 10, 140)bg_color = pygame.Color('grey12')
light_grey = (200, 200, 200)ball_speed_x = 7 * random.choice((1, -1))
ball_speed_y = 7 * random.choice((1, -1))    
player_speed = 0
opponent_speed = 7# Text Variables
player_score = 0
opponent_score = 0
# 创建字体
game_font = pygame.font.Font("freesansbold.ttf", 32)# Timer
score_time = Truedef ball_animation():global ball_speed_x, ball_speed_yglobal player_score, opponent_scoreglobal score_timeball.x += ball_speed_xball.y += ball_speed_yif ball.top <= 0 or ball.bottom >= screen_height:ball_speed_y *= -1if ball.left <= 0 or ball.right >= screen_width:    if ball.left <= 0:player_score += 1if ball.right >= screen_width:opponent_score += 1score_time = pygame.time.get_ticks()if ball.colliderect(player) or ball.colliderect(opponent):ball_speed_x *= -1def player_animation():player.y += player_speedif player.top <= 0:player.top = 0if player.bottom >= screen_height:player.bottom = screen_heightdef opponent_animation():if opponent.top < ball.y:opponent.top += opponent_speedif opponent.bottom > ball.y:opponent.bottom -= opponent_speedif opponent.top <= 0:opponent.top = 0if opponent.bottom >= screen_height:opponent.bottom = screen_heightdef ball_restart():global ball_speed_x, ball_speed_yglobal score_timeball.center = (screen_width // 2, screen_height // 2)# 计算耗时,并显示剩余时间# 获得当前时间current_time = pygame.time.get_ticks()# 与上次得分时间比较if current_time - score_time < 700:number_three = game_font.render("3", False, light_grey)screen.blit(number_three, (screen_width // 2 - 10, screen_height // 2 + 20))if 700 < current_time - score_time < 1400:number_two = game_font.render("2", False, light_grey)screen.blit(number_two, (screen_width // 2 - 10, screen_height // 2 + 20))if 1400 < current_time - score_time < 2100:number_one = game_font.render("1", False, light_grey)screen.blit(number_one, (screen_width // 2 - 10, screen_height // 2 + 20))if current_time - score_time < 2100:ball_speed_x, ball_speed_y = 0, 0else:ball_speed_y = 7 * random.choice((1, -1))ball_speed_x = 7 * random.choice((1, -1))score_time = Nonewhile True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_DOWN:player_speed += 7if event.key == pygame.K_UP:player_speed -= 7if event.type == pygame.KEYUP:if event.key == pygame.K_DOWN:player_speed -= 7if event.key == pygame.K_UP:player_speed += 7ball_animation()player_animation()opponent_animation()# update# drawscreen.fill(bg_color)pygame.draw.rect(screen, light_grey, player)pygame.draw.rect(screen, light_grey, opponent)pygame.draw.ellipse(screen, light_grey, ball)pygame.draw.aaline(screen, light_grey, (screen_width / 2, 0), (screen_width / 2, screen_height))# 显示得分player_text = game_font.render(f"{player_score}", False, light_grey)screen.blit(player_text, (660, 360))opponent_text = game_font.render(f"{opponent_score}", False, light_grey)screen.blit(opponent_text, (600, 360))if score_time:ball_restart()pygame.display.flip()clock.tick(60)

3. 优化碰撞逻辑、添加声音

如果你运行了第2节的程序,你会发现有时候球的反弹有时很奇怪,比如有时候会在球拍上。
本节我们将

  • 优化碰撞逻辑:在ball_animation()通过判断球与球拍的位置,修改球的运动。
  • 添加碰撞和得分音效: pygame.mixer.Sound
# 添加得分和计时器
# 基础 ping pang游戏
import sys
import random
import pygame# setup
pygame.init()
pygame.mixer.pre_init(44100, -16, 2, 512)
clock = pygame.time.Clock()screen_width = 1280
screen_height = 720
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption("PingPang")# Reactangles
ball = pygame.Rect(screen_width // 2 - 15, screen_height // 2 - 15, 30, 30)
player = pygame.Rect(screen_width - 20 , screen_height // 2 - 70, 10, 140)
opponent = pygame.Rect(10, screen_height // 2 - 70, 10, 140)bg_color = pygame.Color('grey12')
light_grey = (200, 200, 200)ball_speed_x = 7 * random.choice((1, -1))
ball_speed_y = 7 * random.choice((1, -1))    
player_speed = 0
opponent_speed = 7# Text Variables
player_score = 0
opponent_score = 0
game_font = pygame.font.Font("freesansbold.ttf", 32)# Timer
score_time = True# Sound
pong_sound = pygame.mixer.Sound("pong.ogg")
score_sound = pygame.mixer.Sound("score.ogg")def ball_animation():global ball_speed_x, ball_speed_yglobal player_score, opponent_scoreglobal score_timeball.x += ball_speed_xball.y += ball_speed_yif ball.top <= 0 or ball.bottom >= screen_height:pong_sound.play()ball_speed_y *= -1# score if ball.left <= 0 or ball.right >= screen_width:    score_sound.play()if ball.left <= 0:player_score += 1if ball.right >= screen_width:opponent_score += 1score_time = pygame.time.get_ticks()if ball.colliderect(player) and ball_speed_x > 0: pong_sound.play()if abs(ball.right - player.left) < 10 :ball_speed_x *= -1elif abs(ball.bottom - player.top) < 10 and ball_speed_y > 0:ball_speed_y *= -1elif abs(ball.top - player.bottom) < 10 and ball_speed_y < 0:ball_speed_y *= -1if ball.colliderect(opponent) and ball_speed_x < 0:pong_sound.play()if abs(ball.left - opponent.right) < 10:ball_speed_x *= -1elif abs(ball.bottom - opponent.top) < 10 and ball_speed_y > 0:ball_speed_y *= -1     elif abs(ball.top - opponent.bottom) < 10 and ball_speed_y < 0:ball_speed_y *= -1def player_animation():player.y += player_speedif player.top <= 0:player.top = 0if player.bottom >= screen_height:player.bottom = screen_heightdef opponent_animation():if opponent.top < ball.y:opponent.top += opponent_speedif opponent.bottom > ball.y:opponent.bottom -= opponent_speedif opponent.top <= 0:opponent.top = 0if opponent.bottom >= screen_height:opponent.bottom = screen_heightdef ball_restart():global ball_speed_x, ball_speed_yglobal score_timeball.center = (screen_width // 2, screen_height // 2)current_time = pygame.time.get_ticks()if current_time - score_time < 700:number_three = game_font.render("3", False, light_grey)screen.blit(number_three, (screen_width // 2 - 10, screen_height // 2 + 20))if 700 < current_time - score_time < 1400:number_two = game_font.render("2", False, light_grey)screen.blit(number_two, (screen_width // 2 - 10, screen_height // 2 + 20))if 1400 < current_time - score_time < 2100:number_one = game_font.render("1", False, light_grey)screen.blit(number_one, (screen_width // 2 - 10, screen_height // 2 + 20))if current_time - score_time < 2100:ball_speed_x, ball_speed_y = 0, 0else:ball_speed_y = 7 * random.choice((1, -1))ball_speed_x = 7 * random.choice((1, -1))score_time = Nonewhile True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_DOWN:player_speed += 7if event.key == pygame.K_UP:player_speed -= 7if event.type == pygame.KEYUP:if event.key == pygame.K_DOWN:player_speed -= 7if event.key == pygame.K_UP:player_speed += 7ball_animation()player_animation()opponent_animation()# update# drawscreen.fill(bg_color)pygame.draw.rect(screen, light_grey, player)pygame.draw.rect(screen, light_grey, opponent)pygame.draw.ellipse(screen, light_grey, ball)pygame.draw.aaline(screen, light_grey, (screen_width / 2, 0), (screen_width / 2, screen_height))player_text = game_font.render(f"{player_score}", False, light_grey)screen.blit(player_text, (660, 360))opponent_text = game_font.render(f"{opponent_score}", False, light_grey)screen.blit(opponent_text, (600, 360))if score_time:ball_restart()pygame.display.flip()clock.tick(60)

相关文章:

使用Pygame做一个乒乓球游戏

项目介绍 使用Pygame做一个乒乓球游戏。左侧为电脑&#xff0c;右侧为玩家。 视频地址-YT 视频搬运-B站 视频教程约90分钟。 代码地址 环境&#xff1a;需要pygame库&#xff0c;可用pip安装&#xff1a;pip install pygame 1. 基础版本 首先进行一些初始化&#xff0c;初始…...

力扣---完全平方数

思路&#xff1a; 还是比较好想的&#xff0c;g[i]定义为和为 i 的完全平方数的最少数量。那么递推关系式是g[i]min(g[i-1],g[i-4],g[i-9],...)1&#xff0c;数组初始化是g[0]0,g[1]1。注意这里要对g[0]初始化&#xff0c;&#xff08;举个例子&#xff09;因为在遍历到g[4]时&…...

接口测试、postman、测试点提取【主】

接口测试是测试系统组件间接口的一种测试 接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点 测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系 文章目录 HTTP接口 & Web Service接口RESTful接口…...

C++ list详解及模拟实现

目录 本节目标 1. list的介绍及使用 1.2 list的使用 2.list的模拟实现 1.对list进行初步的实现 2.头插和任意位置的插入 3.pos节点的删除&#xff0c;头删&#xff0c;尾删 4.销毁list和析构函数 5.const迭代器 6.拷贝构造和赋值操作 3.完整代码 本节目标 1. list的…...

【tls招新web部分题解】

emowebshell (php7.4.21版本漏洞) 非预期 题目提示webshell&#xff0c;就直接尝试一下常见的后门命名的规则 如 shell.php这里运气比较好&#xff0c;可以直接shell.php就出来 要是不想这样尝试的话&#xff0c;也可以直接dirsearch进行目录爆破 然后在phpinfo中直接搜素c…...

力扣热门算法题 52. N 皇后 II,53. 最大子数组和,54. 螺旋矩阵

52. N 皇后 II&#xff0c;53. 最大子数组和&#xff0c;54. 螺旋矩阵&#xff0c;每题做详细思路梳理&#xff0c;配套Python&Java双语代码&#xff0c; 2024.03.20 可通过leetcode所有测试用例。 目录 52. N 皇后 II 解题思路 完整代码 Python Java 53. 最大子数组…...

【OpenVINO】解决OpenVINO在GPU推理中报错的方法

1. 问题描述 使用OpenVINO进行深度学习推理时&#xff0c;通常会借助GPU以提升计算速度。然而&#xff0c;有时候运行程序时候会出现如下错误&#xff1a; <kernel>:8153:2: error: expected identifier or (unroll_for (int i 0; i < TILE_SIZE; i) {^ <kernel…...

AES加密的中文乱码与Java默认编码

0. 背景 win11环境下 java8 idea 开发的项目接口有加密需求,暂时使用AES完成,AES工具类代码如下 public static String aesEncrypt(String content, String key) throws Exception {//指定加密算法Cipher cipher Cipher.getInstance("AES");//创建加密规则&#…...

Node.js笔记 (二)浏览器和服务器

Ajax Ajax是什么 全称&#xff1a;Asynchronous Javascript And Xml. 用javascript执行异步网络请求&#xff0c;可以说是定义了一种编程行为/习惯。 通信双方&#xff1a;浏览器 和 服务器 特点&#xff1a;异步&#xff0c;所以可以在异步请求服务器&#xff0c;在不刷新页…...

面试经典-32-判断子序列

题目 给定字符串 s 和 t &#xff0c;判断 s 是否为 t 的子序列。 字符串的一个子序列是原始字符串删除一些&#xff08;也可以不删除&#xff09;字符而不改变剩余字符相对位置形成的新字符串。&#xff08;例如&#xff0c;"ace"是"abcde"的一个子序列…...

windows使用知识

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言windows使用知识 一、cmd鼠标选中后&#xff0c;程序不运行的解决方案总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; windows使用…...

用python如何实现智能合约?如何使用remix编写solidity智能合约并部署上链

目录 用python如何实现智能合约? 直接展示下成功界面 下面分步骤说: remix代码 python链接remix代码...

Electron窗口管理详解:使用BrowserWindow API打造个性化界面

Electron窗口管理详解&#xff1a;使用BrowserWindow API打造个性化界面 创建和初始化窗口窗口定制化窗口操作与事件监听多窗口管理和工作区布局结语 在当今跨平台桌面应用开发领域&#xff0c;Electron 凭借其 JavaScript 与 HTML5 技术栈结合原生操作系统 API 的能力&#xf…...

19---时钟电路设计

视频链接 时钟硬件电路设计01_哔哩哔哩_bilibili 时钟电路设计 晶振是数字电路的心脏&#xff0c;数字电路需要一个稳定的工作时钟信号&#xff0c;时钟电路至关重要&#xff01; 1、晶振概述 晶振一般指晶体振荡器。晶体振荡器是指从一块石英晶体上按一定方位角切下薄片&…...

PSNR/SSIM/LPIPS图像质量评估三件套(含代码)

在图像质量评估上&#xff0c;有三个重要指标&#xff1a;PSNR&#xff0c;SSIM&#xff0c;LPIPS。本文提供简易脚本分别实现。 PSNR&#xff0c;峰值信噪比&#xff0c;是基于MSE的像素比较低质量评估&#xff0c;一般30dB以上质量就不错&#xff0c;到40dB以上肉眼就很难分…...

20240318uniapp怎么引用组件

在script中增加 import index from "/pages/index/index.vue" 把index直接整个作为一个组件引入 然后注册组件 在export default中增加 components: {index:index }, 注册了index组件&#xff0c;内容为import的index 然后就可以在template里使用 <index&…...

扩展以太网(数据链路层)

目录 一、在物理层扩展以太网 二、在数据链路层扩展以太网 三、以太网交换机的特点 四、以太网交换机的交换方式 五、以太网交换机的自学习功能 六、小结 一、在物理层扩展以太网 使用光纤扩展&#xff1a; • 主机使用光纤&#xff08;通常是一对光纤&#xff09;和…...

每日一练 | 华为认证真题练习Day202

1、在组播网络环境中&#xff0c;如果IGMPv2主机和IGMP V1路由器&#xff08;以下简称版本2主机和版本1路由器&#xff09;共同处于同一局域网当中&#xff0c;那他们是如何协同工作的&#xff1f;&#xff08;多选&#xff09; A. 版本1路由器把IGMPv2报告看作无效的IGMP信息…...

基于python+vue的幼儿园管理系统flask-django-php-nodejs

随着信息时代的来临&#xff0c;过去的传统管理方式缺点逐渐暴露&#xff0c;对过去的传统管理方式的缺点进行分析&#xff0c;采取计算机方式构建幼儿园管理系统。本文通过课题背景、课题目的及意义相关技术&#xff0c;提出了一种活动信息、课程信息、菜谱信息、通知公告、家…...

【java】java环境变量分类

测试代码&#xff1a; public class TestSys {public static void main(String[] args) {/*** 获取所有的系统环境变量*/Map<String, String> map System.getenv();map.forEach((key, value) -> System.out.printf("env&#xff1a;key:%s->value:%s%n"…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

PostgreSQL——环境搭建

一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在&#xff0…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

深度学习之模型压缩三驾马车:模型剪枝、模型量化、知识蒸馏

一、引言 在深度学习中&#xff0c;我们训练出的神经网络往往非常庞大&#xff08;比如像 ResNet、YOLOv8、Vision Transformer&#xff09;&#xff0c;虽然精度很高&#xff0c;但“太重”了&#xff0c;运行起来很慢&#xff0c;占用内存大&#xff0c;不适合部署到手机、摄…...

记一次spark在docker本地启动报错

1&#xff0c;背景 在docker中部署spark服务和调用spark服务的微服务&#xff0c;微服务之间通过fegin调用 2&#xff0c;问题&#xff0c;docker容器中服务器来后&#xff0c;注册中心都有&#xff0c;调用服务也正常&#xff0c;但是调用spark启动任务后报错&#xff0c;报错…...

数据库优化实战指南:提升性能的黄金法则

在现代软件系统中&#xff0c;数据库性能直接影响应用的响应速度和用户体验。面对数据量激增、访问压力增大&#xff0c;数据库性能瓶颈经常成为项目痛点。如何科学有效地优化数据库&#xff0c;提升查询效率和系统稳定性&#xff0c;是每位开发与运维人员必备的技能。 本文结…...

Spring Boot SQL数据库功能详解

Spring Boot自动配置与数据源管理 数据源自动配置机制 当在Spring Boot项目中添加数据库驱动依赖&#xff08;如org.postgresql:postgresql&#xff09;后&#xff0c;应用启动时自动配置系统会尝试创建DataSource实现。开发者只需提供基础连接信息&#xff1a; 数据库URL格…...

Java毕业设计:办公自动化系统的设计与实现

JAVA办公自动化系统 一、系统概述 本办公自动化系统基于Java EE平台开发&#xff0c;实现了企业日常办公的数字化管理。系统包含文档管理、流程审批、会议管理、日程安排、通讯录等核心功能模块&#xff0c;采用B/S架构设计&#xff0c;支持多用户协同工作。系统使用Spring B…...