用 Pygame 实现一个乒乓球游戏

用 Pygame 实现一个乒乓球游戏

在这里插入图片描述

伸手需要一瞬间,牵手却要很多年,无论你遇见谁,他都是你生命该出现的人,绝非偶然。若无相欠,怎会相见。

引言

在这篇文章中,我将带领大家使用 Pygame 库开发一个简单的乒乓球游戏。Pygame 是 Python 中广泛使用的游戏开发库,提供了简单易用的 2D 游戏框架。我们将从最基本的游戏框架入手,逐步实现球的运动、球拍的移动、边界碰撞以及得分系统,最后为游戏添加一些细节优化,形成一个完整的乒乓球游戏。

开始之前

首先,你需要确保系统中已经安装了 Pygame。你可以使用以下命令进行安装:

pip install pygame

安装完 Pygame 后,我们可以开始编写代码了。

第一步:基本框架

我们先来创建一个基本的 Pygame 窗口,并在屏幕上绘制一个可移动的球。以下是初始的代码实现:

import pygame# 初始化Pygame
pygame.init()# 定义窗口大小和颜色
S_W, S_H = 800, 600
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)# 设置窗口
screen = pygame.display.set_mode((S_W, S_H))
pygame.display.set_caption("乒乓球")# 初始化球的属性
ball_x = S_W / 2
ball_y = S_H / 2
ball_radius = 20
ball_x_velocity = 3
ball_y_velocity = 3# 设置帧率
clock = pygame.time.Clock()# 游戏主循环
running = True
while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 移动球ball_x += ball_x_velocityball_y += ball_y_velocity# 碰到屏幕边界时反弹if ball_x - ball_radius < 0 or ball_x + ball_radius > S_W:ball_x_velocity *= -1if ball_y - ball_radius < 0 or ball_y + ball_radius > S_H:ball_y_velocity *= -1# 绘制背景和球screen.fill(BLACK)pygame.draw.circle(screen, (255, 0, 0), (int(ball_x), int(ball_y)), ball_radius)# 更新显示pygame.display.update()# 控制帧率clock.tick(60)# 退出游戏
pygame.quit()

解释

  1. 窗口设置:我们定义了窗口的宽度和高度(800x600),并设置窗口标题为"乒乓球"。
  2. 球的移动:我们通过更新球的 xy 坐标来实现球的移动,并在球碰到窗口边缘时反弹。
  3. 帧率控制pygame.time.Clock() 用于限制游戏的帧率,使游戏每秒钟刷新60次,保证运行的流畅性。

运行这段代码,你会看到一个红色的球在黑色背景上不断移动并在边界反弹。


第二步:添加球拍

现在我们要给游戏加入球拍。球拍可以通过键盘输入来控制,让它上下移动,从而和球进行交互。

# 球拍尺寸和初始位置
paddle_width, paddle_height = 25, 100
paddle1_x, paddle1_y = 50, (S_H - paddle_height) / 2  # 玩家1球拍
paddle2_x, paddle2_y = S_W - paddle_width - 50, (S_H - paddle_height) / 2  # 玩家2球拍# 更新球拍的位置
keys = pygame.key.get_pressed()
if keys[pygame.K_w] and paddle1_y > 0:paddle1_y -= 5
if keys[pygame.K_s] and paddle1_y < S_H - paddle_height:paddle1_y += 5
if keys[pygame.K_UP] and paddle2_y > 0:paddle2_y -= 5
if keys[pygame.K_DOWN] and paddle2_y < S_H - paddle_height:paddle2_y += 5# 绘制球拍
pygame.draw.rect(screen, WHITE, (paddle1_x, paddle1_y, paddle_width, paddle_height))
pygame.draw.rect(screen, WHITE, (paddle2_x, paddle2_y, paddle_width, paddle_height))

解释

  1. 球拍绘制:使用 pygame.draw.rect 函数绘制球拍,paddle1_xpaddle1_y 控制玩家1的球拍位置,而 paddle2_xpaddle2_y 控制玩家2的球拍。
  2. 球拍移动:通过 pygame.key.get_pressed() 检测按键输入,WS 键控制玩家1的球拍上下移动,UPDOWN 键控制玩家2的球拍。

第三步:碰撞检测

为了让游戏更加真实,我们需要检测球是否碰撞到球拍并实现反弹效果。下面是球拍碰撞的代码:

# 碰撞检测 - 玩家1球拍
if paddle1_x < ball_x - ball_radius < paddle1_x + paddle_width and paddle1_y < ball_y < paddle1_y + paddle_height:ball_x_velocity *= -1# 碰撞检测 - 玩家2球拍
if paddle2_x < ball_x + ball_radius < paddle2_x + paddle_width and paddle2_y < ball_y < paddle2_y + paddle_height:ball_x_velocity *= -1

解释

  1. 碰撞检测:我们通过检测球的坐标是否进入球拍的区域来判断碰撞。当球与球拍碰撞时,改变球的 x 方向速度,使其反弹。

第四步:得分系统

我们需要为游戏添加一个得分系统,当球越过一方边界时,另一方得分。下面是添加得分系统的代码:

# 初始化得分
score1 = 0
score2 = 0# 检测得分
if ball_x - ball_radius < 0:score2 += 1  # 玩家2得分ball_x, ball_y = S_W / 2, S_H / 2  # 重置球的位置
if ball_x + ball_radius > S_W:score1 += 1  # 玩家1得分ball_x, ball_y = S_W / 2, S_H / 2  # 重置球的位置

第五步:添加文字显示

为了在屏幕上显示得分,我们需要使用 Pygame 的字体功能。以下是实现代码:

# 初始化字体
font = pygame.font.Font(None, 36)# 绘制得分
text1 = font.render(f"Player 1: {score1}", True, WHITE)
text2 = font.render(f"Player 2: {score2}", True, WHITE)
screen.blit(text1, (50, 50))
screen.blit(text2, (S_W - 200, 50))

第六步:添加游戏结束条件

最后,我们可以为游戏添加一个结束条件,比如当某一方得分达到5分时游戏结束:

if score1 >= 5 or score2 >= 5:running = False  # 游戏结束

完整代码

以下是这个乒乓球游戏的完整代码:

import pygame# 屏幕和颜色设置
S_W, S_H = 800, 600
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)# 球和球拍设置
ball_x, ball_y = S_W / 2, S_H / 2
ball_radius = 20
ball_x_velocity, ball_y_velocity = 3, 3
paddle_width, paddle_height = 25, 100
paddle1_x, paddle1_y = 50, (S_H - paddle_height) / 2
paddle2_x, paddle2_y = S_W - paddle_width - 50, (S_H - paddle_height) / 2# 初始化Pygame
pygame.init()
screen = pygame.display.set_mode((S_W, S_H))
pygame.display.set_caption("乒乓球")
clock = pygame.time.Clock()# 初始化得分
score1, score2 = 0, 0
font = pygame.font.Font(None, 36)running = True
while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 球移动ball_x += ball_x_velocityball_y += ball_y_velocity# 边界反弹if ball_x - ball_radius < 0 or ball_x + ball_radius >S_W:ball_x_velocity *= -1if ball_y - ball_radius < 0 or ball_y + ball_radius > S_H:ball_y_velocity *= -1# 球拍移动keys = pygame.key.get_pressed()if keys[pygame.K_w] and paddle1_y > 0:paddle1_y -= 5if keys[pygame.K_s] and paddle1_y < S_H - paddle_height:paddle1_y += 5if keys[pygame.K_UP] and paddle2_y > 0:paddle2_y -= 5if keys[pygame.K_DOWN] and paddle2_y < S_H - paddle_height:paddle2_y += 5# 碰撞检测if paddle1_x < ball_x - ball_radius < paddle1_x + paddle_width and paddle1_y < ball_y < paddle1_y + paddle_height:ball_x_velocity *= -1if paddle2_x < ball_x + ball_radius < paddle2_x + paddle_width and paddle2_y < ball_y < paddle2_y + paddle_height:ball_x_velocity *= -1# 得分系统if ball_x - ball_radius < 0:score2 += 1ball_x, ball_y = S_W / 2, S_H / 2if ball_x + ball_radius > S_W:score1 += 1ball_x, ball_y = S_W / 2, S_H / 2# 绘制背景、球和球拍screen.fill(BLACK)pygame.draw.circle(screen, (255, 0, 0), (int(ball_x), int(ball_y)), ball_radius)pygame.draw.rect(screen, WHITE, (paddle1_x, paddle1_y, paddle_width, paddle_height))pygame.draw.rect(screen, WHITE, (paddle2_x, paddle2_y, paddle_width, paddle_height))# 显示得分text1 = font.render(f"Player 1: {score1}", True, WHITE)text2 = font.render(f"Player 2: {score2}", True, WHITE)screen.blit(text1, (50, 50))screen.blit(text2, (S_W - 200, 50))pygame.display.update()clock.tick(60)# 游戏结束if score1 >= 5 or score2 >= 5:running = Falsepygame.quit()

总结

通过这篇博客,你可以看到如何从零开始开发一个简单的乒乓球游戏。我们逐步实现了球的移动、球拍控制、碰撞检测、得分系统和游戏结束条件。你可以根据自己的需求继续改进和扩展这个游戏,比如加入背景音乐、增加更复杂的物理效果等。希望你通过这次实践掌握了使用 Pygame 开发游戏的基础技能!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/431375.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SPSS26统计分析笔记——3 假设检验

1 假设检验原理 假设检验的基本原理源于“小概率事件”原理&#xff0c;是一种基于概率性质的反证法。其核心思想是小概率事件在一次试验中几乎不会发生。检验的过程首先假设原假设 H 0 {H_0} H0​成立&#xff0c;然后通过统计方法分析样本数据。如果样本数据引发了“小概率事…

Krita连接comfyui报错缺少节点如何解决

介绍一下我用的版本&#xff1a; krita5.2.3 ComfyUI-aki-v1.3 首先&#xff1a;文件夹必须严格按照ComfyUI进行命名&#xff0c;我不知道这个是不是必须得&#xff0c;但是看官方的文档以及我解决这个问题的过程时&#xff0c;是这样的。 报错信息如下图(这个报错图…

航拍工程车辆识别检测数据集 yolo数据集 共650张

航拍工程车识别检测数据集 yolo数据集 共650张 2 工程车辆识别数据集&#xff08;Engineering Vehicle Recognition Dataset, EVRD&#xff09; 摘要 EVRD 是一个专门针对航拍视角下的工程车辆识别而设计的数据集&#xff0c;旨在提供一种标准的训练和评估平台&#xff0c;用…

玩手机数据集 8201张玩手机的照片,有对应的xml和txt文件,可以用于yolo训练

玩手机数据集 8201张玩手机的照片&#xff0c;有对应的xml和txt文件&#xff0c;可以用于yolo训练 玩手机数据集&#xff08;Phone Usage Detection Dataset&#xff09; 数据集概述 该数据集专为检测人们使用手机的行为设计&#xff0c;旨在帮助研究人员和工程师开发高效的…

Uniapp时间戳转时间显示/时间格式

使用uview2 time 时间格式 | uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 <text class"cell-tit clamp1">{{item.create_time}} --- {{ $u.timeFormat(item.create_time, yyyy-mm-dd hh:MM:ss)}} </text>

从零开始的软件开发详解:数字药店系统源码与医保购药APP

很多小伙伴们疑问&#xff0c;医保购药APP是如何开发的&#xff0c;今天我将从零数字药店系统源码开始为大家提供一条清晰的实现方案。 一、技术架构设计 在开发医保购药APP之前&#xff0c;首先需要明确技术架构。一般来说&#xff0c;APP的技术架构可以分为前端和后端。 1…

手写SpringMVC(简易版)

在上一篇博客中说到这里我们要进行手写SpringMVC&#xff0c;因此最好是将上一篇博客中的SpringMVC源码分析那一块部分搞懂&#xff0c;或者观看动力节点老杜的SpringMVC源码分析再来看这里的书写框架。 首先我们要知道对于一个完整系统的参与者&#xff08;即一个完整的web项…

目标检测系列(三)yolov2的全面讲解

YOLOv2&#xff08;论文原名《YOLO9000: Better, Faster, Stronger》&#xff09;作为该系列的第二个版本&#xff0c;对原始YOLO进行了显著的改进&#xff0c;进一步提高了检测速度和准确度。在精度上利用一些列训练技巧&#xff0c;在速度上应用了新的网络模型DarkNet19&…

Vue3:自定义customRef

目录 一.性质 1.自定义性 2.工厂函数参数 3.track 和 trigger 函数 二.作用 1.防抖/节流 2.异步更新 3.条件性更新 4.精细控制依赖追踪 5.优化性能 三.使用 1.ts组件 2.vue.组件 四.代码 1.ts代码 2.vue代码 五.效果 在 Vue 3 中&#xff0c;customRef 是一个…

一、机器学习算法与实践_04信息论与决策树算法笔记

1 信息论基础知识介绍 信息论是运用概率论与数理统计的方法&#xff0c;去研究信息、信息熵、通信系统、数据传输、密码学、数据压缩等问题的应用数学学科&#xff0c;熵&#xff08;Entropy&#xff09;是信息论中的一个重要概念&#xff0c;由克劳德香农&#xff08;Claude …

深入理解端口、端口号及FTP的基本工作原理

FTP是TCP/IP的一种具体应用&#xff0c;FTP工作在OSI模型的第七层&#xff0c;TCP模型的第四层上&#xff0c;即应用层&#xff0c;FTP使用的是传输层的TCP传输而不是UDP&#xff0c;这样FTP客户在和服务器建立连接前就要经过一个被广为熟知的“三次握手”的过程&#xff0c;其…

制作炫酷个人网页:用 HTML 和 CSS3 展现你的风格

你是否觉得自己的网站应该看起来更炫酷&#xff1f;今天我将教你如何使用 HTML 和 CSS3 制作一个拥有炫酷动画和现代设计风格的个人网页&#xff0c;让它在任何设备上看起来都无敌酷炫&#xff01; 哈哈哈哈哈哈哈哈,我感觉自己有点中二哈哈哈哈~ 目录 炫酷设计理念构建 HTML …

Unity 热更新(HybridCLR+Addressable)-设置打包路径和加载路径、打开Hosting服务、打包

四、设置打包和加载路径 五、打开Hosting服务 六、打包 打包完成后路径在Assets同级目录下的ServerData 但是目前没有资源文件对比 修改上面设置后再次打包 里面多了哈希和JSON文件&#xff0c;这俩个就是用于资源对比

若依生成主子表

一、准备工作 确保你已经部署了若依框架&#xff0c;并且熟悉基本的开发环境配置。同时&#xff0c;理解数据库表结构对于生成代码至关重要。 主子表代码结构如下&#xff08;字表中要有一个对应主表ID的字段作为外键&#xff0c;如下图的customer_id&#xff09; -- ------…

无线感知会议系列【4】【基于WiFi和4G/5G的非接触无线感知:挑战、理论和应用-2】

前言&#xff1a; 本篇重点分享一下该论文 《Human Respiration Detection with Commodity Wifi Devices: Do User Location and Body Orientation Matter》 接 2020年北京智源大会 张大庆老师的一个报告 参考&#xff1a; https://blog.csdn.net/chengxf2/article/detai…

2024 Redis 全部

1. 单机部署 1.1 检查环境&#xff0c;创建目录。 # 本地运行&#xff0c;不需要考虑安装的原因&#xff0c;可以卸载防火墙 # 关闭防火墙 systemctl stop firewalld.service# 查看防火强状态 firewall-cmd --state# redis 是基于gcc 环境的&#xff0c;查看是否有 gcc 环境 …

Bug:ThreadPoolTaskScheduler搭配CronTask完成定时任务,关闭scheduler后CronTask任务仍然执行?

【问题】执行下面代码后&#xff0c;关闭ThreadPoolTaskScheduler&#xff0c;CronTask仍然继续执行。 Configuration public class config {Beanpublic String getString() throws InterruptedException {Runnable runnable () -> {try {System.out.println("hello r…

科研绘图系列:R语言分组堆积图(stacked barplot)

文章目录 介绍加载R包导入数据数据预处理画图导出数据系统信息介绍 堆积图是一种数据可视化图表,它通过将不同类别的数据以堆叠的形式展现在同一个图表中,来展示各个类别之间的相对大小和它们之间的总和。堆积图可以是柱状图、条形图或面积图的形式,其中每个堆叠的块或区域…

Servlet入门:服务端小程序的初试(自己学习整理的资料)

目录 一.前言 二.建立基础结构​编辑 三.具体步骤 找到Tomcat文件并打开Tomcat。 在webapps中创建一个自己的文件夹。 在classes中新建一个Java文件。 在lib中导入需要的jar文件包。 配置环境变量 在Java文件的目录下打开cmd并输入 javac -d . HelloServlet.java进行…

【UE5】将2D切片图渲染为体积纹理,最终实现使用RT实时绘制体积纹理【第三篇-着色器光照】

在前两篇文章中&#xff0c;我们分别拆解描述了实现原理&#xff0c;并进行了基础的着色器制作。在这一篇文章中&#xff0c;我们将为它实现光照效果 简单的概述 当光线射入体积时&#xff0c;随着光线射入距离的增加&#xff0c;体积中的介质会对光线产生反射和吸收作用&…