项目介绍

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

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

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

1. 基础版本

首先进行一些初始化,初始化pygame以及物体的初始状态。 然后是主循环,游戏的主循环主要包含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 = 7

while 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 += 7

if event.key == pygame.K_UP:

player_speed -= 7

if event.type == pygame.KEYUP:

if event.key == pygame.K_DOWN:

player_speed -= 7

if event.key == pygame.K_UP:

player_speed += 7

# update

#ball_animation()

#player_animation()

#opponent_animation()

# draw

screen.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)

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

ball_animation()player_animation()opponent_animation()

def ball_animation():

"""更新球的运动"""

global ball_speed_x, ball_speed_y

ball.x += ball_speed_x

ball.y += ball_speed_y

if ball.top <= 0 or ball.bottom >= screen_height:

ball_speed_y *= -1

if ball.left <= 0 or ball.right >= screen_width:

ball_speed_x *= -1

ball_restart()

if ball.colliderect(player) or ball.colliderect(opponent):

ball_speed_x *= -1

def player_animation():

"""更新玩家的运动"""

player.y += player_speed

if player.top <= 0:

player.top = 0

if player.bottom >= screen_height:

player.bottom = screen_height

def opponent_animation():

"""更新对手的运动"""

if opponent.top < ball.y:

opponent.top += opponent_speed

if opponent.bottom > ball.y:

opponent.bottom -= opponent_speed

if opponent.top <= 0:

opponent.top = 0

if opponent.bottom >= screen_height:

opponent.bottom = screen_height

def ball_restart():

"""重置球的位置"""

global ball_speed_x, ball_speed_y

ball.center = (screen_width // 2, screen_height // 2)

ball_speed_y *= random.choice((1, -1))

ball_speed_x *= random.choice((1, -1))

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

2. 添加分数和时间

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

# 添加得分和计时器

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 = 7

# Text Variables

player_score = 0

opponent_score = 0

# 创建字体

game_font = pygame.font.Font("freesansbold.ttf", 32)

# Timer

score_time = True

def ball_animation():

global ball_speed_x, ball_speed_y

global player_score, opponent_score

global score_time

ball.x += ball_speed_x

ball.y += ball_speed_y

if ball.top <= 0 or ball.bottom >= screen_height:

ball_speed_y *= -1

if ball.left <= 0 or ball.right >= screen_width:

if ball.left <= 0:

player_score += 1

if ball.right >= screen_width:

opponent_score += 1

score_time = pygame.time.get_ticks()

if ball.colliderect(player) or ball.colliderect(opponent):

ball_speed_x *= -1

def player_animation():

player.y += player_speed

if player.top <= 0:

player.top = 0

if player.bottom >= screen_height:

player.bottom = screen_height

def opponent_animation():

if opponent.top < ball.y:

opponent.top += opponent_speed

if opponent.bottom > ball.y:

opponent.bottom -= opponent_speed

if opponent.top <= 0:

opponent.top = 0

if opponent.bottom >= screen_height:

opponent.bottom = screen_height

def ball_restart():

global ball_speed_x, ball_speed_y

global score_time

ball.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, 0

else:

ball_speed_y = 7 * random.choice((1, -1))

ball_speed_x = 7 * random.choice((1, -1))

score_time = None

while 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 += 7

if event.key == pygame.K_UP:

player_speed -= 7

if event.type == pygame.KEYUP:

if event.key == pygame.K_DOWN:

player_speed -= 7

if event.key == pygame.K_UP:

player_speed += 7

ball_animation()

player_animation()

opponent_animation()

# update

# draw

screen.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_y

global player_score, opponent_score

global score_time

ball.x += ball_speed_x

ball.y += ball_speed_y

if 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 += 1

if ball.right >= screen_width:

opponent_score += 1

score_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 *= -1

elif abs(ball.bottom - player.top) < 10 and ball_speed_y > 0:

ball_speed_y *= -1

elif abs(ball.top - player.bottom) < 10 and ball_speed_y < 0:

ball_speed_y *= -1

if ball.colliderect(opponent) and ball_speed_x < 0:

pong_sound.play()

if abs(ball.left - opponent.right) < 10:

ball_speed_x *= -1

elif 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 *= -1

def player_animation():

player.y += player_speed

if player.top <= 0:

player.top = 0

if player.bottom >= screen_height:

player.bottom = screen_height

def opponent_animation():

if opponent.top < ball.y:

opponent.top += opponent_speed

if opponent.bottom > ball.y:

opponent.bottom -= opponent_speed

if opponent.top <= 0:

opponent.top = 0

if opponent.bottom >= screen_height:

opponent.bottom = screen_height

def ball_restart():

global ball_speed_x, ball_speed_y

global score_time

ball.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, 0

else:

ball_speed_y = 7 * random.choice((1, -1))

ball_speed_x = 7 * random.choice((1, -1))

score_time = None

while 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 += 7

if event.key == pygame.K_UP:

player_speed -= 7

if event.type == pygame.KEYUP:

if event.key == pygame.K_DOWN:

player_speed -= 7

if event.key == pygame.K_UP:

player_speed += 7

ball_animation()

player_animation()

opponent_animation()

# update

# draw

screen.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)

精彩内容

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: