Python-乒乓球小游戏【附完整源码】

乒乓球小游戏

乒乓球小游戏是一个简单而有趣的2D页面交互式游戏,玩家可以通过键盘输入来控制球拍上下移动来接球,从而体验乒乓球的乐趣。该游戏有单人和双人两种模式

运行效果:
在这里插入图片描述
在这里插入图片描述

一:主程序:

import sys
import cfg
import pygame
from modules import *'''定义按钮'''
def Button(screen, position, text, button_size=(200, 50)):left, top = positionbwidth, bheight = button_sizepygame.draw.line(screen, (150, 150, 150), (left, top), (left+bwidth, top), 5)pygame.draw.line(screen, (150, 150, 150), (left, top-2), (left, top+bheight), 5)pygame.draw.line(screen, (50, 50, 50), (left, top+bheight), (left+bwidth, top+bheight), 5)pygame.draw.line(screen, (50, 50, 50), (left+bwidth, top+bheight), (left+bwidth, top), 5)pygame.draw.rect(screen, (100, 100, 100), (left, top, bwidth, bheight))font = pygame.font.Font(cfg.FONTPATH, 30)text_render = font.render(text, 1, (255, 235, 205))return screen.blit(text_render, (left+50, top+10))'''
Function:开始界面
Input:--screen: 游戏界面
Return:--game_mode: 1(单人模式)/2(双人模式)
'''
def startInterface(screen):clock = pygame.time.Clock()while True:screen.fill((41, 36, 33))button_1 = Button(screen, (150, 175), '1 Player')button_2 = Button(screen, (150, 275), '2 Player')for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()if event.type == pygame.MOUSEBUTTONDOWN:if button_1.collidepoint(pygame.mouse.get_pos()):return 1elif button_2.collidepoint(pygame.mouse.get_pos()):return 2clock.tick(10)pygame.display.update()'''结束界面'''
def endInterface(screen, score_left, score_right):clock = pygame.time.Clock()font1 = pygame.font.Font(cfg.FONTPATH, 30)font2 = pygame.font.Font(cfg.FONTPATH, 20)msg = 'Player on left won!' if score_left > score_right else 'Player on right won!'texts = [font1.render(msg, True, cfg.WHITE),font2.render('Press ESCAPE to quit.', True, cfg.WHITE),font2.render('Press ENTER to continue or play again.', True, cfg.WHITE)]positions = [[120, 200], [155, 270], [80, 300]]while True:screen.fill((41, 36, 33))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_RETURN:returnelif event.key == pygame.K_ESCAPE:sys.exit()pygame.quit()for text, pos in zip(texts, positions):screen.blit(text, pos)clock.tick(10)pygame.display.update()'''运行游戏Demo'''
def runDemo(screen):# 加载游戏素材hit_sound = pygame.mixer.Sound(cfg.HITSOUNDPATH)goal_sound = pygame.mixer.Sound(cfg.GOALSOUNDPATH)pygame.mixer.music.load(cfg.BGMPATH)pygame.mixer.music.play(-1, 0.0)font = pygame.font.Font(cfg.FONTPATH, 50)# 开始界面game_mode = startInterface(screen)# 游戏主循环# --左边球拍(ws控制, 仅双人模式时可控制)score_left = 0racket_left = Racket(cfg.RACKETPICPATH, 'LEFT', cfg)# --右边球拍(↑↓控制)score_right = 0racket_right = Racket(cfg.RACKETPICPATH, 'RIGHT', cfg)# --球ball = Ball(cfg.BALLPICPATH, cfg)clock = pygame.time.Clock()while True:for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit(-1)screen.fill((41, 36, 33))# 玩家操作pressed_keys = pygame.key.get_pressed()if pressed_keys[pygame.K_UP]:racket_right.move('UP')elif pressed_keys[pygame.K_DOWN]:racket_right.move('DOWN')if game_mode == 2:if pressed_keys[pygame.K_w]:racket_left.move('UP')elif pressed_keys[pygame.K_s]:racket_left.move('DOWN')else:racket_left.automove(ball)# 球运动scores = ball.move(ball, racket_left, racket_right, hit_sound, goal_sound)score_left += scores[0]score_right += scores[1]# 显示# --分隔线pygame.draw.rect(screen, cfg.WHITE, (247, 0, 6, 500))# --球ball.draw(screen)# --拍racket_left.draw(screen)racket_right.draw(screen)# --得分screen.blit(font.render(str(score_left), False, cfg.WHITE), (150, 10))screen.blit(font.render(str(score_right), False, cfg.WHITE), (300, 10))if score_left == 11 or score_right == 11:return score_left, score_rightclock.tick(100)pygame.display.update()'''主函数'''
def main():# 初始化pygame.init()pygame.mixer.init()screen = pygame.display.set_mode((cfg.WIDTH, cfg.HEIGHT))pygame.display.set_caption('乒乓球')# 开始游戏while True:score_left, score_right = runDemo(screen)endInterface(screen, score_left, score_right)'''run'''
if __name__ == '__main__':main()

二:配置文件 - cfg.py

import os'''屏幕长宽'''
WIDTH = 500
HEIGHT = 500
'''游戏素材路径'''
CURRPATH = os.getcwd()
RESOURCESDIRPATH = os.path.join(CURRPATH, 'resources')
AUDIOSDIRPATH = os.path.join(RESOURCESDIRPATH, 'audios')
FONTDIRPATH = os.path.join(RESOURCESDIRPATH, 'font')
IMAGESDIRPATH = os.path.join(RESOURCESDIRPATH, 'images')
BALLPICPATH = os.path.join(IMAGESDIRPATH, 'ball.png')
RACKETPICPATH = os.path.join(IMAGESDIRPATH, 'racket.png')
FONTPATH = os.path.join(FONTDIRPATH, 'font.TTF')
GOALSOUNDPATH = os.path.join(AUDIOSDIRPATH, 'goal.wav')
HITSOUNDPATH = os.path.join(AUDIOSDIRPATH, 'hit.wav')
BGMPATH = os.path.join(AUDIOSDIRPATH, 'bgm.mp3')
'''颜色'''
WHITE = (255, 255, 255)

三:文件包 - modules

(1)__init__.py

'''初始化'''
from .sprites import Ball, Racket

(2)sprites.py

import random
import pygame
from .utils import *'''乒乓球'''
class Ball(pygame.sprite.Sprite):def __init__(self, imgpath, cfg, **kwargs):pygame.sprite.Sprite.__init__(self)self.cfg = cfgself.image = loadImage(imgpath)self.rect = self.image.get_rect()self.reset()'''移动'''def move(self, ball, racket_left, racket_right, hit_sound, goal_sound):self.rect.left = self.rect.left + self.speed * self.direction_xself.rect.top = min(max(self.rect.top + self.speed * self.direction_y, 0), self.cfg.HEIGHT - self.rect.height)# 撞到球拍if pygame.sprite.collide_rect(ball, racket_left) or pygame.sprite.collide_rect(ball, racket_right):self.direction_x, self.direction_y = -self.direction_x, random.choice([1, -1])self.speed += 1scores = [0, 0]hit_sound.play()# 撞到上侧的墙elif self.rect.top == 0:self.direction_y = 1self.speed += 1scores = [0, 0]# 撞到下侧的墙elif self.rect.top == self.cfg.HEIGHT - self.rect.height:self.direction_y = -1self.speed += 1scores = [0, 0]# 撞到左边的墙elif self.rect.left < 0:self.reset()racket_left.reset()racket_right.reset()scores = [0, 1]goal_sound.play()# 撞到右边的墙elif self.rect.right > self.cfg.WIDTH:self.reset()racket_left.reset()racket_right.reset()scores = [1, 0]goal_sound.play()# 普通情况else:scores = [0, 0]return scores'''初始化'''def reset(self):self.rect.centerx = self.cfg.WIDTH // 2self.rect.centery = random.randrange(self.rect.height // 2, self.cfg.HEIGHT - self.rect.height // 2)self.direction_x = random.choice([1, -1])self.direction_y = random.choice([1, -1])self.speed = 1'''绑定到屏幕上'''def draw(self, screen):screen.blit(self.image, self.rect)'''乒乓球拍'''
class Racket(pygame.sprite.Sprite):def __init__(self, imgpath, type_, cfg, **kwargs):pygame.sprite.Sprite.__init__(self)self.cfg = cfgself.type_ = type_self.image = loadImage(imgpath, False)self.rect = self.image.get_rect()self.reset()'''移动'''def move(self, direction):if direction == 'UP':self.rect.top = max(0, self.rect.top - self.speed)elif direction == 'DOWN':self.rect.bottom = min(self.cfg.HEIGHT, self.rect.bottom + self.speed)else:raise ValueError('[direction] in Racket.move is %s, expect %s or %s...' % (direction, 'UP', 'DOWN'))'''电脑自动移动'''def automove(self, ball):if ball.rect.centery - 25 > self.rect.centery:self.move('DOWN')if ball.rect.centery + 25 < self.rect.centery:self.move('UP')'''初始化'''def reset(self):# 左/右边的拍self.rect.centerx = self.cfg.WIDTH - self.rect.width // 2 if self.type_ == 'RIGHT' else self.rect.width // 2self.rect.centery = self.cfg.HEIGHT // 2# 速度self.speed = 5'''绑定到屏幕上'''def draw(self, screen):screen.blit(self.image, self.rect)

(3)utils.py

import pygame'''导入图片'''
def loadImage(imgpath, transparent=True):img = pygame.image.load(imgpath)img = img.convert()if transparent:color = img.get_at((0, 0))img.set_colorkey(color, pygame.RLEACCEL)return img

四:素材包 - resources

素材包大家根据配置文件自己配置就好,或者私信我发你

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

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

相关文章

Jupyter Notebook: 交互式数据科学和编程工具

Jupyter Notebook: 功能强大的交互式编程和数据科学工具 简介 Jupyter Notebook是一个开源的Web应用程序&#xff0c;广泛用于数据分析、科学计算、可视化以及机器学习等领域。它允许创建和共享包含实时代码、方程式、可视化和解释性文本的文档。总而言之&#xff0c;我认为它…

3D Font

在游戏中使用3D文本 只需添加预制件并立即生成您的文本。 特点: *真实3D字母&#xff0c;可用作游戏对象*移动友好低聚 *VR兼容 *WebGL兼容 *30种以上不同字体 *材料和颜色可定制 WebGL演示 https://indiechest.itch.io/3d-font-engine 下载&#xff1a; ​​Unity资源商店链…

【tips】base64编码怎么反显出图片

格式 <img width"400" height"300" src"data:image/jpeg;base64,这里存放base64的图片内容/>实际的数据展示是这样的 然后把以上的文件内容放置到html文件中 最终展示样例 点击这个 展示出来是这样的

opencv 十五 红外图像中虹膜的提取

一、算法需求 在医疗检测中&#xff0c;需要使用红外相机拍摄眼睛照片&#xff0c;然后提取出虹膜的区域。在拍摄过程瞳孔需要进行运动&#xff0c;其通常不在正前方&#xff0c;无法形成圆形&#xff0c;不能使用常规的霍夫圆检测进行提取定位。且在在红外图像中&#xff0c;…

将输入的字符串反向输出(c语言)

#include<stdio.h> #include<string.h> int main() {int i, j, k;char s[50], temp;gets(s);//输入k strlen(s);//计算字符的长度//反向输出for (i 0, j k - 1;i < k / 2;i, j--){temp s[i];s[i] s[j];s[j] temp;}puts(s);//输出 }

ARM TZC-400原理及配置方式

吧ARM TZC-400是一种TrustZone Controller&#xff0c;用于ARM Cortex-A系列处理器中的硬件支持。TrustZone是ARM提供的一种安全技术&#xff0c;通过在处理器上创建两个不同的安全区域&#xff08;Secure Zone和Non-Secure Zone&#xff09;来提供硬件级别的安全隔离。 TZC-4…

最近面试了一位5年的测试,一问三不知,还反怼我...

最近看了很多简历&#xff0c;很多候选人年限不小&#xff0c;但是做的都是一些非常传统的项目&#xff0c;想着也不能通过简历就直接否定一个人&#xff0c;何况现在大环境越来 越难&#xff0c;大家找工作也不容易&#xff0c;于是就打算见一见。 在沟通中发现&#xff0c;由…

MD5解密详解

MD5解密详解 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; MD5解密揭秘&#xff1a;解谜编码的神奇之路 在信息安全领域&#xff0c;MD5&#xff08;Message Di…

GB28181学习(十八)——图像抓拍

前言 本文主要介绍图像抓拍功能&#xff0c;通过自研的sip库&#xff08;mysipsdk.dll&#xff09;对接真实设备&#xff0c;使用http方式实现图像数据传输&#xff0c;最终达到图像抓拍与保存的目的。 基本要求 图像格式宜使用JPEG&#xff1b;图像分辨率宜采用与主码流相同…

linux ksm实现与代码简述

KSM 全称是 Kernel Samepage Merging&#xff0c;表示相同的物理页只映射一份拷贝。 原理 在ksm初始化时&#xff08;ksm_init&#xff09;&#xff0c;注册了一个ksm_scan_thread线程&#xff0c;这个线程的核心入口是ksm_do_scan。当对一个进程第一次通过madvice(MADV_MERGE…

Linux高级管理-基于域名的虚拟Web主机搭建

客服机限制地址 通过 Require 配置项&#xff0c;可以根据主机的主机名或P地址来决定是否允许客户端访问。在httpd服 务器的主配置文件的<Location>&#xff0c;<Directory>、<Files>、<Limit>配置段中均可以使用Require 配置 项来控制客户端的访问。使…

Java基础:如何创建多层文件夹

一、单层多个 代码实现如下&#xff1a; public class Main {public static void main(String[] args) {//在D盘中创建File file new File("D:"File.separator"docum");file.mkdir();//在D盘中的docum目录中创建file new File("D:\\docum" Fi…

Redission从入门到入门

1. Redisson简介 Redisson 是一个在 Java 环境中使用的 Redis 客户端库。它提供了丰富的功能&#xff0c;使得在 Java 应用中与 Redis 交互变得更加简单和高效。Redisson 不仅提供了基本的 Redis 操作&#xff0c;还提供了许多高级功能&#xff0c;使其成为在 Java 项目中实现…

以下是一些自然语言处理(NLP)技术的例子:

以下是一些自然语言处理&#xff08;NLP&#xff09;技术的例子&#xff1a; 语音识别&#xff1a;将说话者的语音转换为文本形式&#xff0c;从而使机器能够理解和分析语音内容。 文本分类&#xff1a;将大量的文本分成不同的类别&#xff0c;例如新闻、评论、博客等。 情感…

IO / 线程同步互斥概念总结

1. 为什么要引入线程同步互斥机制 线程共享用户空间&#xff0c;当多个线程访问临界资源时会产生竟态&#xff0c;引入线程同步互斥机制是为了保护临界资源 2. 同步互斥的基本概念 临界资源&#xff1a;多线程任务执行时&#xff0c;能够同时访问的公共资源叫做临界资源临界区…

富时中国a50指数期货论文

富时中国A50指数期货概述 富时中国A50指数期货是中国境内市场上的一种衡量蓝筹股表现的期货合约&#xff0c;其跟踪富时中国A50指数的表现。富时中国A50指数是由富时罗素指数有限公司编制的一种反映中国大陆A股市场50只流动性好、市值大的股票的指数。 市场背景与意义 富时中…

kafka 详细介绍

目录 前言 分布式架构&#xff1a; 消息发布-订阅模型&#xff1a; 持久性存储&#xff1a; 分区和副本&#xff1a; 水平扩展&#xff1a; 高性能&#xff1a; 生态系统&#xff1a; 我的其他博客 前言 Kafka 是由 Apache 软件基金会开发的一种开源流处理平台&#xf…

微信小程序自定义提示框组件并使用插槽 tooltip

创建tooltip组件引用 创建一个自定义组件&#xff0c;例如命名为 tooltip tooltip.wxml&#xff1a;用于定义组件的结构&#xff1b; <!--components/tooltip/tooltip.wxml--> <view class"tooltip-wrapper" hidden"{{hidden}}" style"lef…

纺织辅料小程序商城制作全攻略

随着互联网的普及和移动支付的便捷性&#xff0c;越来越多的消费者喜欢在线购物&#xff0c;尤其是购买纺织辅料这类产品。为了满足消费者的需求&#xff0c;纺织辅料企业或商家需要制作一个专业的小程序商城&#xff0c;以便更好地展示和销售自己的产品。本文将详细介绍如何制…

linux命令awk使用

awk是一条命令&#xff0c;也可以说是一种编程语言, 数据来源可以来自stdin&#xff0c;一个或多个文件。它支持用户自定义函数和动态正则表达式等先进功能&#xff0c;是linux/unix下的一个强大编程工具。awk有很多内建的功能&#xff0c;比如数组、函数等&#xff0c;这是它和…