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

avatar
作者
筋斗云
阅读量:4

乒乓球小游戏

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

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

一:主程序:

import sys import cfg import pygame from modules import *  '''定义按钮''' def Button(screen, position, text, button_size=(200, 50)):     left, top = position     bwidth, bheight = button_size     pygame.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 1                 elif button_2.collidepoint(pygame.mouse.get_pos()):                     return 2         clock.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:                     return                 elif 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 = 0     racket_left = Racket(cfg.RACKETPICPATH, 'LEFT', cfg)     # --右边球拍(↑↓控制)     score_right = 0     racket_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_right         clock.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 = cfg         self.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_x         self.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 += 1             scores = [0, 0]             hit_sound.play()         # 撞到上侧的墙         elif self.rect.top == 0:             self.direction_y = 1             self.speed += 1             scores = [0, 0]         # 撞到下侧的墙         elif self.rect.top == self.cfg.HEIGHT - self.rect.height:             self.direction_y = -1             self.speed += 1             scores = [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 // 2         self.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 = cfg         self.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 // 2         self.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

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

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!