用 Pygame 实现一个乒乓球游戏

news2024/11/15 19:58:40

用 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_velocity
    ball_y += ball_y_velocity

    # 碰到屏幕边界时反弹
    if ball_x - ball_radius < 0 or ball_x + ball_radius > S_W:
        ball_x_velocity *= -1
    if 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_velocity
    ball_y += ball_y_velocity

    # 边界反弹
    if ball_x - ball_radius < 0 or ball_x + ball_radius >

 S_W:
        ball_x_velocity *= -1
    if 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 -= 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

    # 碰撞检测
    if paddle1_x < ball_x - ball_radius < paddle1_x + paddle_width and paddle1_y < ball_y < paddle1_y + paddle_height:
        ball_x_velocity *= -1
    if 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 += 1
        ball_x, ball_y = S_W / 2, S_H / 2
    if ball_x + ball_radius > S_W:
        score1 += 1
        ball_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 = False

pygame.quit()

总结

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python文字转wav音频

借鉴博客 一.前期准备 1. pip install baidu-aip 2. pip install pydub 3. sudo apt-get install ffmpeg 二.代码 from aip import AipSpeech from pydub import AudioSegment import time#input your own APP_ID/API_KEY/SECRET_KEY APP_ID 14891501 API_KEY EIm2iXtvD…

【可变模板参数】

文章目录 可变参数模板的概念可变参数模板的定义方式参数包的展开方式递归展开参数包逗号表达式展开参数包 STL容器中的emplace相关接口函数 可变参数模板的概念 可变参数模板是C11新增的最强大的特性之一&#xff0c;它对参数高度泛化&#xff0c;能够让我们创建可以接受可变…

linux入门——“linux基本指令”下

1.mv指令 mv指令用于移动文件或者目录。语法是mv 源文件 目标文件。它的用法需要注意&#xff1a; 当目标文件不存在的时候&#xff0c;默认是将源文件进行重命名操作&#xff0c;名字就是目标文件的名字&#xff0c;当目标文件存在的时候才会把源文件移动到目标文件。 目标文…

centos 7.9安装k8s

前言 Kubernetes单词来自于希腊语&#xff0c;含义是领航员&#xff0c;生产环境级别的容器编排技术&#xff0c;可实现容器的自动部署扩容以及管理。Kubernetes也称为K8S&#xff0c;其中8代表中间8个字符&#xff0c;是Google在2014年的开源的一个容器编排引擎技术&#xff…

WebLogic 后台弱⼝令GetShell

漏洞描述 通过弱⼝令进⼊后台界⾯ , 上传部署war包 , getshell 影响范围 全版本&#xff08;前提后台存在弱⼝令&#xff09; 环境搭建 cd vulhub-master/weblogic/weak_password docker-compose up -d 漏洞复现 默认账号密码&#xff1a;weblogic/Oracle123 weblogic…

SQL编程题复习(24/9/19)

练习题 x25 10-145 查询S001学生选修而S003学生未选修的课程&#xff08;MSSQL&#xff09;10-146 检索出 sc表中至少选修了’C001’与’C002’课程的学生学号10-147 查询平均分高于60分的课程&#xff08;MSSQL&#xff09;10-148 检索C002号课程的成绩最高的二人学号&#xf…

34. 模型材质父类Material

学习到现在大家对threejs的材质都有简单的了解&#xff0c;本节课主要结合文档&#xff0c;从JavaScript语法角度&#xff0c;给大家总结一下材质API的语法。 材质父类Material 查询threejs文档&#xff0c;你可以看到基础网格材质MeshBasicMaterial、漫反射网格材质MeshLamb…

-bash: apt-get: command not found -bash: yum: command not found

1. 现象&#xff1a; 1.1. 容器内使用apt-get, yum 提示命令未找到 1.2. dockerfile制作镜像时候&#xff0c;使用apt-get, yum同样报此错误。 2.原因&#xff1a; 2.1. linux 分为&#xff1a; 1. RedHat系列&#xff1a; Redhat、Centos、Fedora等 2. Debian系列&#xff1a…

4G 网络下资源加载失败?一次运营商封禁 IP 的案例分享

在工作中&#xff0c;网络问题是不可避免的挑战之一。最近&#xff0c;我们在项目中遇到了一起网络资源加载异常的问题&#xff1a;某同事在使用 4G 网络连接公司 VPN 时&#xff0c;云服务的前端资源居然无法加载&#xff01;通过一系列的排查和分析&#xff0c;我们发现问题的…

alias 后门从入门到应急响应

目录 1. alias 后门介绍 2. alias 后门注入方式 2.1 方式一(以函数的方式执行) 2.2 方式二(执行python脚本) 3.应急响应 3.1 查看所有连接 3.2 通过PID查看异常连接的进程&#xff0c;以及该进程正在执行的命令行命令 3.3 查看别名 3.4 其他情况 3.5 那么检查这些…

Arthas jvm(查看当前JVM的信息)

文章目录 二、命令列表2.1 jvm相关命令2.1.3 jvm&#xff08;查看当前JVM的信息&#xff09; 二、命令列表 2.1 jvm相关命令 2.1.3 jvm&#xff08;查看当前JVM的信息&#xff09; 基础语法&#xff1a; jvm [arthas18139]$ jvmRUNTIME …

C++_21_模板

模板 简介&#xff1a; 一种用于实现通用编程的机制。 通过使用模板我们可以编写可复用的代码&#xff0c;可以适用于多种数据类型。 C模板的语法使用角括号 < > 来表示泛型类型&#xff0c;并使用关键字 template 来定义和声明模板 概念&#xff1a; c范式编程 特点&…

OSPFv3协议几类LSA介绍

OSPFv3协议介绍 与OSPFv2相比&#xff0c;OSPFv3在工作机制上与OSPFv2基本相同&#xff1b;但为了支持IPv6地址格式&#xff0c;OSPFv3对OSPFv2做了一些改动。OSPFv3基于OSPFv2基本原理增强&#xff0c;是一个独立的路由协议&#xff08;v3不兼容v2&#xff09;协议号仍然是89…

java -versionbash:/usr/lib/jvm/jdk1.8.0_162/bin/java:无法执行二进制文件:可执行文件格式错误

实验环境&#xff1a;Apple M1在VMwareFusion使用Utubun Jdk文件错误 &#xfffc; 尝试&#xff1a; 1、重新在网盘下载java1.8 2、在终端通过命令下载 3、确保 JDK 正确安装在系统中&#xff0c;可以通过 echo $JAVA_HOME 检查 JAVA_HOME 环境变量是否设置正确。 &#xfff…

前端JavaScript导出excel,并用excel分析数据,使用SheetJS导出excel

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f…

C语言的文件基础知识

一、文件存在的意义 ① 文件的定义是什么&#xff1f; 文件是以单个名称在计算机上存储的信息集合。文件可以是文本文档、图片、程序等等。文件通常具有三个字母的文件扩展名&#xff0c;用于指示文件类型&#xff08;例如&#xff0c;图片文件常常以 JPEG 格式保存并且文件扩…

【技术编辑与写作】优秀文章整理——如何做个好编辑

【技术编辑与写作】优秀文章整理——如何做个好编辑 本文适用人群&#xff1a; 本文不是严谨教程贴&#xff0c;更多的是好文搜集、经验分享和闲聊&#xff0c;适用于感兴趣想简单了解运营、编辑等行业的人&#xff0c;如果是追求高精尖和专业的&#xff0c;已有N年经验人士请…

【HTTP】方法(method)以及 GET 和 POST 的区别

文章目录 方法&#xff08;method&#xff09;登录上传GET 和 POST 有什么区别&#xff08;面试&#xff09;区别不准确的说法 方法&#xff08;method&#xff09; 首行中的第一部分。首行是由方法、URL 和版本号组成 方法描述了这次请求想干什么&#xff0c;最主要的是&…

无人机之激光避障篇

无人机的激光避障技术是通过激光传感器来感知和避开周围障碍物的一种高级技术。以下是关于无人机激光避障技术的详细解析&#xff1a; 一、技术原理 激光避障技术利用激光束的直线传播和反射特性&#xff0c;通过发送激光束并接收反射回来的信号&#xff0c;来检测和计算周围障…

植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面

一、介绍 植物病害识别系统。本系统使用Python作为主要编程语言&#xff0c;通过收集水稻常见的四种叶片病害图片&#xff08;‘细菌性叶枯病’, ‘稻瘟病’, ‘褐斑病’, ‘稻瘟条纹病毒病’&#xff09;作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算…