一、初始pygame
1.游戏框架搭建
- pygame游戏框架搭建大体分为四个步骤,如下图所示:
参考代码:
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:480,高:700
# 游戏退出
pygame.quit()
2.添加循环
以上代码执行后,游戏窗口闪一下就关闭了。我们需要在窗口下方添加一个无限循环,让窗口一直显示。
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 添加无限循环,让窗口一直显示
while True:
pass
# 游戏退出
pygame.quit()
3.监听事件
以上代码执行后,窗口可以一直显示,但无法关闭。所以我们需要监听事件消息,例如关闭窗口事件,按下键盘事件等等。
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
4.最终代码
基本设置完成后,我们可以设置窗口标题,更改背景颜色等等
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 窗口标题
pygame.display.set_caption('原神')
# 自定义颜色
bg_color1 = (255,0,0)
# 游戏窗口背景颜色
screen.fill(bg_color1)
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
以上代码结束后,颜色无法更改,我们需要加一行代码pygame.display.flip,去刷新屏幕。代码如下:
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 窗口标题
pygame.display.set_caption('原神')
# 自定义颜色
bg_color1 = (255,0,0)
# 游戏窗口背景颜色
screen.fill(bg_color1)
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
# 刷新屏幕
pygame.display.flip()
二、Pygame进阶
1.游戏窗口坐标系
2.画圆
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 窗口标题
pygame.display.set_caption('原神')
# 自定义颜色
bg_color1 = (255,0,0)
# 游戏窗口背景颜色
screen.fill(bg_color1)
# 绘制一个蓝色实心的圆形,其中[60,250]表示圆心的位置,40为半径,width默认为0
pygame.draw.circle(screen, (0, 0, 255), [60, 250], 40,0)
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
# 刷新屏幕
pygame.display.flip()
3.插入图片
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 窗口标题
pygame.display.set_caption('原神')
ball = pygame.image.load("ball.jpg") # 加载图片
WHITE = (255, 255, 255) #白色
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
screen.fill(WHITE) #重新背景颜色为白色
screen.blit(ball,(0,0))# 在原点位置放置图片
pygame.display.update()# 刷新屏幕
4.让图片移动
# 导入pygame
import pygame
import time
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
ball = pygame.image.load("ball.jpg") # 加载图片
RED = (255, 0, 0) # 红色
ballrect = ball.get_rect() #获取矩形的区域
speed = [5,5] #偏移量
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
ballrect = ballrect.move(speed) #让图片移动
screen.fill(RED) # 背景颜色为红色
screen.blit(ball, ballrect)# 将图片画到窗口
pygame.display.flip()# 刷新屏幕
time.sleep(0.1) #间接控制图片移动速度,越短越快
5.碰撞反弹
# 导入pygame
import pygame
import time
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
ball = pygame.image.load("ball.jpg") # 加载图片
RED = (255, 0, 0) # 红色
ballrect = ball.get_rect() #获取矩形的区域
speed = [5,5] #偏移量
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
# 碰到左右边缘反弹
if ballrect.left < 0 or ballrect.right > 480:
speed[0] = - speed[0]
# 碰到上下边缘反弹
if ballrect.top < 0 or ballrect.bottom > 700:
speed[1] = - speed[1]
ballrect = ballrect.move(speed) #让图片移动
screen.fill(RED) # 背景颜色为红色
screen.blit(ball, ballrect)# 将图片画到窗口
pygame.display.flip()# 刷新屏幕
time.sleep(0.1) #间接控制图片移动速度,越短越快
三、Pygame进阶(一)
1.绘制矩形
# 导入pygame
import pygame
import time
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
RED = (255, 0, 0) # 红色
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
pygame.draw.rect(screen,RED,(50,50,150,50),0) #绘制矩形,第三个参数为矩形的范围:(left,top,width,height),最后一个参数,0表示填充矩形
pygame.draw.rect(screen, RED, (250, 50, 150, 50), 1)
pygame.draw.rect(screen, RED, (50, 150, 150, 50), 10)
pygame.display.flip()# 刷新屏幕
2.绘制三角形
# 导入pygame
import pygame
import time
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
BLACK = (0, 0, 0) # 黑色
WHITE = (255, 255, 255) # 白色
RED = (255, 0, 0) # 红色
GREEN = (0, 255, 0) # 绿色
BLUE = (0, 0, 255) # 蓝色
screen.fill(WHITE) # 填充背景色
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
"""绘制三角形"""
points = [(60,0),(0,50),(120,50)]
pygame.draw.polygon(screen, GREEN, points, 0)
"""绘制多边形"""
points = [(200, 75), (300, 25), (400, 75), (450, 25), (450, 125), (400, 75), (300, 125)]
pygame.draw.polygon(screen, RED, points, 0)
pygame.display.flip()# 刷新屏幕
3.显示文字
# 导入pygame
import pygame
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((480, 700)) # 宽:640,高:700
# 窗口标题
pygame.display.set_caption('原神')
# 定义颜色
BLACK = (0, 0, 0) # 黑色
WHITE = (255, 255, 255) # 白色
RED = (255, 0, 0) # 红色
GREEN = (0, 255, 0) # 绿色
BLUE = (0, 0, 255) # 蓝色
#循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
text = pygame.font.SysFont("SimHei", 60) # 创建一个font文本对象
text_font = text.render("游戏结束", 1, RED, BLUE) # 渲染文本对象
screen.blit(text_font, (100,200)) # 绘制文本内容
pygame.display.update()# 刷新屏幕
3.乒乓球创意
# 导入pygame
import pygame
import time
# 初始化游戏
pygame.init()
# 游戏代码【这里写我们的游戏代码主体部分,比如游戏窗口,标题,背景颜色等等】
# 游戏窗口
screen = pygame.display.set_mode((600, 550)) # 宽:600,高:550
# 窗口标题
pygame.display.set_caption('乒乓球争霸赛')
# 定义颜色
BLACK = (0, 0, 0) # 黑色
WHITE = (255, 255, 255) # 白色
RED = (255, 0, 0) # 红色
GREEN = (0, 255, 0) # 绿色
BLUE = (0, 0, 255) # 蓝色
Orange = (225, 121, 21) # 橙色
x = 120 # 乒乓球的x坐标
y = 120 # 乒乓球的y坐标
vx = 1 # 乒乓球的x轴初始速度
vy = 1 # 乒乓球的y轴初始速度
# boost = 0 # boost是加速器,如果接了10次,那么加速
score = 0 # score是分数,接到一次乒乓球就加分
# Bpc= 1 # 基础加分量英文:Basic plus component的缩写
# 打印文本
def printtext(font, text, x, y, color):
# 渲染文本
text_font = font.render(text, True, color)
# 绘制文本
screen.blit(text_font, (x, y))
#循环
while True:
screen.fill(Orange) # 填充背景为橙色
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
### 显示文字 ###
script1 = pygame.font.SysFont('stkaiti', 24)# 文字:移动鼠标控制乒乓板左右移动
script2 = pygame.font.SysFont('stkaiti', 20)# 文字:得分
printtext(script1, "移动鼠标控制乒乓板左右移动", 10, 12, BLACK)
printtext(script2, "得分", 550, 12, BLACK)
printtext(script2, str(score), 560, 32, WHITE)
### 乒乓球和球拍 ###
mx, my = pygame.mouse.get_pos() # 获得鼠标的x,y坐标
pygame.draw.circle(screen, BLUE, (x, y), 40, 0) # 绘制乒乓球
pygame.draw.rect(screen, GREEN, (mx, 530, 100, 20), 0) # 绘制球板【鼠标x坐标就是乒乓板的坐标,因此移动鼠标乒乓板也移动】
#改变乒乓球的速度
x = x + vx
y = y + vy
# 如果乒乓球碰到左右屏幕边缘,vx取反
if x > 550 or x < 40:
vx = -vx
# # 如果碰到上边缘时,vy取反
if y < 40:
vy = -vy
# 乒乓球与乒乓板碰撞检测
if (y + 40 > 530) and (y < 530 + 20) and (x > mx) and (x < mx+100):
score = score + 1
# 如果乒乓球是从下往上碰到乒乓板,则反弹
if vy > 0:
vy = -vy
# 如果判定没落到球板,则游戏结束,跳出循环
elif y > 530 and abs(mx - x) > 50:
print("游戏结束!")
break
pygame.display.update()# 刷新屏幕
四、滑雪大冒险
1.第一节课
# -*-coding:GBK -*-
# 导入pygame
import pygame
# 导入时间库
import time
# 滑雪者方向不同对应不同的图片
skier_images = ['./ images/skier_forward.png',
"./ images/skier_right1.png",
"./ images/skier_right2.png",
"./ images/skier_left2.png",
"./ images/skier_left1.png"]
# 滑雪者类
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
# 创建一个pygame Sprite类的子类
pygame.sprite.Sprite.__init__(self)
# 初始化加载滑雪者向下滑的图片
self.image = pygame.image.load('./ images/skier_fall.png')
# 初始化获取图片的矩形大小
self.rect = self.image.get_rect()
# 指定滑雪者的中心位置
self.rect.center = [320, 100]
# 初始化默认标记滑雪者当前面对的方向(0:代表向下滑)
self.angle = 0
# 转弯
def turn(self, direction):
# 滑雪者当前的移动速度
self.angle += direction
# 用于将滑雪者的移动方式固定到这3个方式当中
if self.angle < -2:
self.angle = -2
if self.angle > 2:
self.angle = 2
#获取人的位置
center = self.rect.center
# 加载滑雪者此时应有的图片
self.image = pygame.image.load(skier_images[self.angle])
#初始化图形,注意这里改变了位置
self.rect = self.image.get_rect()
#重新定位到人的位置
self.rect.center = center
# # # 滑雪者左右移动
def move(self, speed):
# 更改滑雪者所在的横向位置
self.rect.centerx += speed
# 滑雪者所在位置不应该超过的最大最小值
if self.rect.centerx < 20:
self.rect.centerx = 20
if self.rect.centerx > 620:
self.rect.centerx = 620
# 初始化游戏
pygame.init()
# 游戏窗口
screen = pygame.display.set_mode((640, 640)) # 宽:640,高:640
# 窗口标题
pygame.display.set_caption('滑雪大冒险')
# 创建滑雪者类的实例对象
skier = SkierClass()
# 设置移动的x轴距离
speed = 0
#设置时钟
clock = pygame.time.Clock()
#循环
while True:
clock.tick(30) #每秒钟执行30次
# 监听所有事件
for event in pygame.event.get():
# 点击?号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
if event.type == pygame.KEYDOWN:
# 如果点击左键则向左转
if event.key == pygame.K_LEFT:
skier.turn(-1)
speed = -1
# 如果点击右键则向右转
elif event.key == pygame.K_RIGHT:
skier.turn(1)
speed = 1
# 滑雪者移动
skier.move(speed)
# 白色背景
screen.fill([255, 255, 255])
# 绘制滑雪者
screen.blit(skier.image,skier.rect)
# 刷新屏幕
pygame.display.flip()
2.第二节课
# -*-coding:GBK -*-
# 导入pygame
import pygame
# 导入时间库
import time
# 导入随机库
import random
# 滑雪者方向不同对应不同的图片
skier_images = ['./ images/skier_forward.png',
"./ images/skier_right1.png",
"./ images/skier_right2.png",
"./ images/skier_left2.png",
"./ images/skier_left1.png"]
# 滑雪者类
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
# 创建一个pygame Sprite类的子类
pygame.sprite.Sprite.__init__(self)
# 初始化加载滑雪者向下滑的图片
self.image = pygame.image.load('./ images/skier_fall.png')
# 初始化获取图片的矩形大小
self.rect = self.image.get_rect()
# 指定滑雪者的中心位置
self.rect.center = [320, 100]
# 初始化默认标记滑雪者当前面对的方向(0:代表向下滑)
self.angle = 0
# 转弯
def turn(self, direction):
# 滑雪者当前的移动速度
self.angle += direction
# 用于将滑雪者的移动方式固定到这3个方式当中
if self.angle < -2:
self.angle = -2
if self.angle > 2:
self.angle = 2
#获取人的位置
center = self.rect.center
# 加载滑雪者此时应有的图片
self.image = pygame.image.load(skier_images[self.angle])
#初始化图形,注意这里改变了位置
self.rect = self.image.get_rect()
#重新定位到人的位置
self.rect.center = center
# # # 滑雪者左右移动
def move(self, speed):
# 更改滑雪者所在的横向位置
self.rect.centerx += speed
# 滑雪者所在位置不应该超过的最大最小值
if self.rect.centerx < 20:
self.rect.centerx = 20
if self.rect.centerx > 620:
self.rect.centerx = 620
# 树类
class TreeClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
# 加载树的图片
self.image = pygame.image.load('./ images/tree.png')
# 初始化树的位置
self.location = location
# 获取图片大小
self.rect = self.image.get_rect()
# 指定图片中心位置
self.rect.center = location
# 移动
def update(self):
global speedy
self.rect.centery -=speedy
# 判断树是否移除屏幕
if self.rect.centery < -32:
self.kill()
# 旗子类
class FlagClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
# 加载旗子的图片
self.image = pygame.image.load('./ images/flag.png')
# 初始化位置
self.location = location
# 获取图片大小
self.rect = self.image.get_rect()
# 指定图片中心位置
self.rect.center = location
# 移动
def update(self):
global speedy
self.rect.centery -=speedy
# 判断树是否移除屏幕
if self.rect.centery < -32:
self.kill()
# 创建一个窗口,生成随机的树和小旗
def create_map():
global obstacles # 全局变量声明
locations = []
for i in range(30): # 每屏30个障碍物
row = random.randint(0, 9) # 获得随机数在 start-end之间
col = random.randint(0, 9)
location = [row * 64 + 32, col * 64 + 32 + 640] # 确定障碍物所在位置(x,y)
if not (location in locations): # 确保没有将两个障碍物放在同一个位置
locations.append(location)
# 将树添加到游戏
obstacle_tree = TreeClass(location)
# 将旗子添加到游戏
obstacle_flag = FlagClass(location)
# 将树或者旗子随机放入
obstacles.add(random.choice([obstacle_tree,obstacle_flag]))
# 初始化游戏
pygame.init()
# 游戏窗口
screen = pygame.display.set_mode((640, 640)) # 宽:640,高:640
# 窗口标题
pygame.display.set_caption('滑雪大冒险')
# 创建滑雪者类的实例对象
skier = SkierClass()
# 设置移动的x轴距离
speed = 0
#设置时钟
clock = pygame.time.Clock()
# 创建独立运动的组织
obstacles = pygame.sprite.Group()
# 调用函数,生成树和旗子
create_map()
# 设置移动的x轴距离
speedy = 6
# 创建一个记录树和旗子移动到哪里的变量
map_position = 0
#循环
while True:
# time.sleep(0.03)
map_position += speedy
if map_position >=640:
create_map()
map_position = 0
clock.tick(30) #每秒钟执行30次
# 监听所有事件
for event in pygame.event.get():
# 点击?号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
if event.type == pygame.KEYDOWN:
# 如果点击左键则向左转
if event.key == pygame.K_LEFT:
skier.turn(-1)
speed = -1
# 如果点击右键则向右转
elif event.key == pygame.K_RIGHT:
skier.turn(1)
speed = 1
# 滑雪者移动
skier.move(speed)
# 白色背景
screen.fill([255, 255, 255])
# 把树和旗子绘制到窗口
obstacles.draw(screen)
# 屏幕更新显示
obstacles.update()
# 绘制滑雪者
screen.blit(skier.image,skier.rect)
# 刷新屏幕
pygame.display.flip()
3.第三节课
# -*-coding:GBK -*-
# 导入pygame
import pygame
# 导入时间库
import time
# 导入随机库
import random
# 滑雪者方向不同对应不同的图片
skier_images = ['./ images/skier_forward.png',
"./ images/skier_right1.png",
"./ images/skier_right2.png",
"./ images/skier_left2.png",
"./ images/skier_left1.png"]
# 滑雪者类
class SkierClass(pygame.sprite.Sprite):
def __init__(self):
# 创建一个pygame Sprite类的子类
pygame.sprite.Sprite.__init__(self)
# 初始化加载滑雪者向下滑的图片
self.image = pygame.image.load('./ images/skier_fall.png')
# 初始化获取图片的矩形大小
self.rect = self.image.get_rect()
# 指定滑雪者的中心位置
self.rect.center = [320, 100]
# 初始化默认标记滑雪者当前面对的方向(0:代表向下滑)
self.angle = 0
# 转弯
def turn(self, direction):
# 滑雪者当前的移动速度
self.angle += direction
# 用于将滑雪者的移动方式固定到这3个方式当中
if self.angle < -2:
self.angle = -2
if self.angle > 2:
self.angle = 2
#获取人的位置
center = self.rect.center
# 加载滑雪者此时应有的图片
self.image = pygame.image.load(skier_images[self.angle])
#初始化图形,注意这里改变了位置
self.rect = self.image.get_rect()
#重新定位到人的位置
self.rect.center = center
# 滑雪者左右移动
def move(self, speed):
# 更改滑雪者所在的横向位置
self.rect.centerx += speed
# 滑雪者所在位置不应该超过的最大最小值
if self.rect.centerx < 20:
self.rect.centerx = 20
if self.rect.centerx > 620:
self.rect.centerx = 620
# 树类
class TreeClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
# 加载树的图片
self.image = pygame.image.load('./ images/tree.png')
# 初始化树的位置
self.location = location
# 获取图片大小
self.rect = self.image.get_rect()
# 指定图片中心位置
self.rect.center = location
self.type = 'tree'
# 移动
def update(self):
global speedy
self.rect.centery -=speedy
# 判断树是否移除屏幕
if self.rect.centery < -32:
self.kill()
# 旗子类
class FlagClass(pygame.sprite.Sprite):
def __init__(self, location):
pygame.sprite.Sprite.__init__(self)
# 加载旗子的图片
self.image = pygame.image.load('./ images/flag.png')
# 初始化位置
self.location = location
# 获取图片大小
self.rect = self.image.get_rect()
# 指定图片中心位置
self.rect.center = location
self.type = 'flag'
# 移动
def update(self):
global speedy
self.rect.centery -=speedy
# 判断树是否移除屏幕
if self.rect.centery < -32:
self.kill()
# 创建一个窗口,生成随机的树和小旗
def create_map():
global obstacles # 全局变量声明
locations = []
for i in range(30): # 每屏30个障碍物
row = random.randint(0, 9) # 获得随机数在 start-end之间
col = random.randint(0, 9)
location = [row * 64 + 32, col * 64 + 32 + 640] # 确定障碍物所在位置(x,y)
if not (location in locations): # 确保没有将两个障碍物放在同一个位置
locations.append(location)
# 将树添加到游戏
obstacle_tree = TreeClass(location)
# 将旗子添加到游戏
obstacle_flag = FlagClass(location)
# 将树或者旗子随机放入
obstacles.add(random.choice([obstacle_tree,obstacle_flag]))
# 更新游戏页面
def updateGame():
skier.move(speed) # 滑雪者移动
# 指定背景颜色为白色
screen.fill([255, 255, 255])
obstacles.draw(screen) # 绘制障碍物在窗口中
obstacles.update() # 屏幕更新显示
# 绘制图
screen.blit(skier.image, skier.rect)
# 屏幕更新显示
pygame.display.update()
# 初始化游戏
pygame.init()
# 初始化音频
pygame.mixer.init()
pygame.mixer.music.load("./music/bg_music.mp3") # 加载音乐
pygame.mixer.music.set_volume(0.4) # 音量设置为0.4
pygame.mixer.music.play(-1) # 无线循环播放
# 游戏窗口
screen = pygame.display.set_mode((640, 640)) # 宽:640,高:640
# 窗口标题
pygame.display.set_caption('滑雪大冒险')
# 创建滑雪者类的实例对象
skier = SkierClass()
# 设置移动的x轴距离
speed = 0
#设置时钟
clock = pygame.time.Clock()
# 创建独立运动的组织
obstacles = pygame.sprite.Group()
# 调用函数,生成树和旗子
create_map()
# 设置移动的x轴距离
speedy = 6
# 创建一个记录树和旗子移动到哪里的变量
map_position = 0
# 创建分数变量score
score = 0
# 创建一个font对象,控制字体大小
font = pygame.font.Font(None, 50)
#循环
while True:
# time.sleep(0.03)
map_position += speedy
if map_position >=640:
create_map()
map_position = 0
clock.tick(30) #每秒钟执行30次
# 监听所有事件
for event in pygame.event.get():
# 点击?号关闭,退出游戏
if event.type == pygame.QUIT:
#游戏退出
pygame.quit()
if event.type == pygame.KEYDOWN:
# 如果点击左键则向左转
if event.key == pygame.K_LEFT:
skier.turn(-1)
speed = -1
# 如果点击右键则向右转
elif event.key == pygame.K_RIGHT:
skier.turn(1)
speed = 1
# 碰撞检测
hit = pygame.sprite.spritecollide(skier, obstacles, False)
if hit:
# 如果碰到树
if hit[0].type == 'tree':
score -=50
# 将树隐藏
hit[0].kill()
# 显示碰撞的图片
skier.image = pygame.image.load("./ images/skier_fall.png")
updateGame()
# 摔倒后暂停一会重新再站起来
time.sleep(1)
skier.image = pygame.image.load('./ images/skier_forward.png')
skier.angle = 0
speed = 0
elif hit[0].type == 'flag':
score += 10
hit[0].kill()
updateGame()
# 滑雪者移动
skier.move(speed)
# 白色背景
screen.fill([255, 255, 255])
# 把树和旗子绘制到窗口
obstacles.draw(screen)
# 屏幕更新显示
obstacles.update()
# 绘制滑雪者
screen.blit(skier.image,skier.rect)
# 显示得分
score_text = font.render("Score: " + str(score), 1, (0, 0, 0))
# 将分数绘制在指定位置
screen.blit(score_text, [10, 10])
# 刷新屏幕
pygame.display.flip()
五、玛丽冒险
1.第一节课
# 导入pygame
import pygame
SCREENWIDTH = 673 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 224 # 窗口高度根据地图高度定
FPS = 30 # 4.更新画面时间
# 定义一个移动地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/ditutu.png").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
def map_rolling(self):
if self.x < -673: # 小于-673说明地图已经完全移动完毕
self.x = 673 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化游戏
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.游戏窗口
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.窗口标题
pygame.display.set_caption('玛丽冒险')
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(673, 0)
# 循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
# 游戏退出
pygame.quit()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_update()
bg2.map_rolling()
# 5.更新整个窗体
pygame.display.update()
# 6.循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()
思考:以上代码执行后,为何图片可以进行无缝衔接的滚动?
回答:代码的逻辑实现了图片的无缝衔接滚动,主要是通过以下步骤和机制实现的:
地图图片的加载: MyMap 类在初始化时加载了一个背景图片 ditutu.png,并设置了其 alpha通道(意味着该图片可能包含透明区域)。
双地图机制: 创建了两个 MyMap 对象(bg1 和 bg2),它们分别表示屏幕上的两个相同的背景图。其中,bg1 初始位置在 (0,0),而 bg2 初始位置在 (673, 0)(与屏幕宽度相同,因此它在屏幕外开始)。
地图的滚动: 在每个游戏循环中,map_rolling 方法会更新 bg1 和 bg2 的 x 坐标,使其向左移动 5 个像素。当 bg1的 x 坐标小于 -673(即完全移出屏幕)时,它会被重置到 673(即屏幕的右侧边界),这样它就可以再次从屏幕右侧开始滚动。由于 bg2始终与 bg1 保持相同的距离(673 像素),当 bg1 滚动并重新出现在屏幕右侧时,bg2 也会正好从屏幕左侧消失,从而实现无缝衔接。
地图的绘制: 在每个游戏循环中,map_update 方法会在屏幕上绘制两个地图图片。由于 bg1 和 bg2 的初始位置以及它们的滚动方式,它们会在屏幕上形成一个连续的、无缝衔接的背景。
屏幕更新: 在每个游戏循环的末尾,使用 pygame.display.update() 更新整个屏幕,显示最新的游戏状态。
帧率控制: 通过 fpsclock.tick(FPS),游戏循环被限制为每秒运行 FPS(在这里是 30)次。这确保了游戏的流畅性和稳定性。
通过上述机制,当 bg1 从屏幕右侧重新出现时,bg2 正好从左侧消失,玩家看到的是两个图片的无缝衔接滚动,从而实现了地图的循环滚动效果。
2.第二节课
# 导入pygame
import pygame
from itertools import cycle # 导入迭代工具
SCREENWIDTH = 673 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 224 # 窗口高度根据地图高度定
FPS = 30 # 4.更新画面时间
# 定义一个移动地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/ditutu.png").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
def map_rolling(self):
if self.x < -673: # 小于-673说明地图已经完全移动完毕
self.x = 673 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 玛丽类
class Marie():
def __init__(self):
# 初始化玛丽矩形
self.rect = pygame.Rect(0, 0, 0, 0)
self.x = 50 # 绘制玛丽的x坐标
self.lowest_y = 170 # 最低坐标
self.y = self.lowest_y # 绘制玛丽的y坐标
self.rect.topleft = (self.x, self.y)
# 加载玛丽图片
self.adventure_img = (
pygame.image.load("image/A.png").convert_alpha(),
pygame.image.load("image/An.png").convert_alpha()
)
# 玛丽动图索引
# self.marieIndex = 0
self.marieIndexGen = cycle([0, 1])
self.jumpState = False # 跳跃的状态
self.jumpHeight = 100 # 跳跃的高度
self.jumpValue = 0 # 跳跃增变量
self.jump_music = pygame.mixer.Sound("music/jump.wav") # 跳音效
# 绘制玛丽
def draw_marie(self):
# 匹配玛丽动图
marieIndex = next(self.marieIndexGen)
# 绘制玛丽
screen.blit(self.adventure_img[marieIndex], (self.x, self.rect.y))
# 跳状态
def jump(self):
self.jumpState = True
# 玛丽移动
def move(self):
# 当起跳的时候
if self.jumpState:
# 如果站在地上
if self.rect.y >= self.lowest_y:
# 以5个像素值向上移动
self.jumpValue = -5
# 玛丽到达顶部回落
if self.rect.y <= self.lowest_y - self.jumpHeight:
# 以5个像素值向下移动
self.jumpValue = 5
# 通过循环改变玛丽的y坐标
self.rect.y += self.jumpValue
# 如果玛丽回到地面
if self.rect.y >= self.lowest_y:
# 关闭跳跃状态
self.jumpState = False
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化游戏
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.游戏窗口
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.窗口标题
pygame.display.set_caption('玛丽冒险')
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(673, 0)
# 创建玛丽对象
marie = Marie()
# 循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
# 游戏退出
pygame.quit()
# 按下键盘上的空格键,开启跳的状态
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 1.如果玛丽在地面上
if marie.rect.y >= marie.lowest_y:
# 2.播放玛丽跳跃音效
marie.jump_music.play()
# 3.开启玛丽跳的状态
marie.jump()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_update()
bg2.map_rolling()
# 绘制玛丽
marie.draw_marie()
# 玛丽移动
marie.move()
# 5.更新整个窗体
pygame.display.update()
# 6.循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()
3.第三节课
# 导入pygame
import pygame
from itertools import cycle # 导入迭代工具
import random
SCREENWIDTH = 673 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 224 # 窗口高度根据地图高度定
FPS = 30 # 4.更新画面时间
# 定义一个移动地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/ditutu.png").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
def map_rolling(self):
if self.x < -673: # 小于-673说明地图已经完全移动完毕
self.x = 673 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 玛丽类
class Marie():
def __init__(self):
# 初始化玛丽矩形
self.rect = pygame.Rect(0, 0, 0, 0)
self.x = 50 # 绘制玛丽的x坐标
self.lowest_y = 170 # 最低坐标
self.y = self.lowest_y # 绘制玛丽的y坐标
self.rect.topleft = (self.x, self.y)
# 加载玛丽图片
self.adventure_img = (
pygame.image.load("image/A.png").convert_alpha(),
pygame.image.load("image/An.png").convert_alpha()
)
# 玛丽动图索引
# self.marieIndex = 0
self.marieIndexGen = cycle([0, 1])
self.jumpState = False # 跳跃的状态
self.jumpHeight = 100 # 跳跃的高度
self.jumpValue = 0 # 跳跃增变量
self.jump_music = pygame.mixer.Sound("music/jump.wav") # 跳音效
# 绘制玛丽
def draw_marie(self):
# 匹配玛丽动图
marieIndex = next(self.marieIndexGen)
# 绘制玛丽
screen.blit(self.adventure_img[marieIndex], (self.x, self.rect.y))
# 跳状态
def jump(self):
self.jumpState = True
# 玛丽移动
def move(self):
# 当起跳的时候
if self.jumpState:
# 如果站在地上
if self.rect.y >= self.lowest_y:
# 以5个像素值向上移动
self.jumpValue = -5
# 玛丽到达顶部回落
if self.rect.y <= self.lowest_y - self.jumpHeight:
# 以5个像素值向下移动
self.jumpValue = 5
# 通过循环改变玛丽的y坐标
self.rect.y += self.jumpValue
# 如果玛丽回到地面
if self.rect.y >= self.lowest_y:
# 关闭跳跃状态
self.jumpState = False
# 障碍物类
class obstacle():
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.missile = pygame.image.load("image/missile.png")
self.pipe = pygame.image.load("image/pipe.png")
# 0和1随机数判断是管道还是导弹
number = random.randint(0, 1)
if number == 0: # 如果随机数为0显示导弹障碍物相反显示管道
self.image = self.missile # 显示导弹障碍
self.move = 15 # 导弹移动速度加快
self.obstacle_y = 150 # 导弹坐标在天上
else:
self.image = self.pipe # 显示管道障碍
self.move = 5 # 管道移动速度慢
self.obstacle_y = 160 # 管道在地面上
# 障碍物绘制坐标
self.rect.x = 673
self.rect.y = self.obstacle_y
# 障碍物移动
def obstacle_move(self):
self.rect.x -= self.move
# 绘制障碍物
def draw_obstacle(self):
screen.blit(self.image, (self.rect.x, self.rect.y))
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化游戏
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.游戏窗口
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.窗口标题
pygame.display.set_caption('玛丽冒险')
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(673, 0)
# 创建玛丽对象
marie = Marie()
# 添加障碍物的时间
addobstacleTimer = 0
# 障碍物对象列表
list = []
# 循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
# 游戏退出
pygame.quit()
# 按下键盘上的空格键,开启跳的状态
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 1.如果玛丽在地面上
if marie.rect.y >= marie.lowest_y:
# 2.播放玛丽跳跃音效
marie.jump_music.play()
# 3.开启玛丽跳的状态
marie.jump()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_update()
bg2.map_rolling()
# 绘制玛丽
marie.draw_marie()
# 玛丽移动
marie.move()
# 计算障碍物间隔时间
if addobstacleTimer >= 1200:
# 创建障碍物对象
obs = obstacle()
# 将障碍物对象添加到列表中
list.append(obs)
# 重置添加障碍物时间
addobstacleTimer = 0
# 循环遍历障碍物
for i in range(len(list)):
# 障碍物移动
list[i].obstacle_move()
# 绘制障碍物
list[i].draw_obstacle()
# 增加障碍物时间
addobstacleTimer += 20
# 5.更新整个窗体
pygame.display.update()
# 6.循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()
4.第四节课
# 导入pygame
import pygame
from itertools import cycle # 导入迭代工具
import random
SCREENWIDTH = 673 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 224 # 窗口高度根据地图高度定
FPS = 40 # 4.更新画面时间
# 游戏结束
def game_over():
bump_music = pygame.mixer.Sound("music/bump.wav") # 撞击
bump_music.play() # 播放撞击音效
# 加载游戏结束的图片
over_img = pygame.image.load("image/gameover.png")
# 将游戏结束的图片绘制在窗体的中间位置
screen.blit(over_img, (230, 90))
def mainGame():
score = 0 # 得分
over = False # 游戏结束标记
global screen
# 1.初始化游戏
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.游戏窗口
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.窗口标题
pygame.display.set_caption('玛丽冒险')
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(673, 0)
# 创建玛丽对象
marie = Marie()
# 添加障碍物的时间
addobstacleTimer = 0
# 障碍物对象列表
list = []
# 循环
while True:
# 监听所有事件
for event in pygame.event.get():
# 点击❌号关闭,退出游戏
if event.type == pygame.QUIT:
# 游戏退出
pygame.quit()
# 按下键盘上的空格键,开启跳的状态
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 1.如果玛丽在地面上
if marie.rect.y >= marie.lowest_y:
# 2.播放玛丽跳跃音效
marie.jump_music.play()
# 3.开启玛丽跳的状态
marie.jump()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_update()
bg2.map_rolling()
# 绘制玛丽
marie.draw_marie()
# 玛丽移动
marie.move()
# 计算障碍物间隔时间
if addobstacleTimer >= 1200:
# 创建障碍物对象
obs = obstacle()
# 将障碍物对象添加到列表中
list.append(obs)
# 重置添加障碍物时间
addobstacleTimer = 0
list1 = []
# 循环遍历障碍物
for i in range(len(list)):
# 障碍物移动
list[i].obstacle_move()
# 绘制障碍物
list[i].draw_obstacle()
if list[i].rect.x < -50:
# 加分
score += 1
list1.append(list[i])
# 判断玛丽与障碍物是否碰撞
if pygame.sprite.collide_rect(marie, list[i]):
# 碰撞后开启结束开关
over = True
# 调用游戏结束的方法
game_over()
# 显示分数
list[i].showScore(score)
for i in list1:
list.remove(i)
# 增加障碍物时间
addobstacleTimer += 20
# 5.更新整个窗体
pygame.display.update()
# 6.循环应该多长时间运行一次
fpsclock.tick(FPS)
# 地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/ditutu.png").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
# 地图滚动
def map_rolling(self):
if self.x < -673: # 小于-673说明地图已经完全移动完毕
self.x = 673 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 玛丽类
class Marie():
def __init__(self):
# 初始化玛丽矩形
self.rect = pygame.Rect(0, 0, 0, 0)
self.x = 50 # 绘制玛丽的x坐标
self.lowest_y = 170 # 最低坐标
self.y = self.lowest_y # 绘制玛丽的y坐标
self.rect.topleft = (self.x, self.y)
# 加载玛丽图片
self.adventure_img = (
pygame.image.load("image/A.png").convert_alpha(),
pygame.image.load("image/An.png").convert_alpha()
)
self.marieIndexGen = cycle([0, 1])
self.jumpState = False # 跳跃的状态
self.jumpHeight = 100 # 跳跃的高度
self.jumpValue = 0 # 跳跃增变量
self.jump_music = pygame.mixer.Sound("music/jump.wav") # 跳音效
self.rect.size = self.adventure_img[0].get_size()
# 绘制玛丽
def draw_marie(self):
# 匹配玛丽动图
marieIndex = next(self.marieIndexGen)
# 绘制玛丽
screen.blit(self.adventure_img[marieIndex], (self.x, self.rect.y))
# 跳状态
def jump(self):
self.jumpState = True
# 玛丽移动
def move(self):
# 当起跳的时候
if self.jumpState:
# 如果站在地上
if self.rect.y >= self.lowest_y:
# 以5个像素值向上移动
self.jumpValue = -5
# 玛丽到达顶部回落
if self.rect.y <= self.lowest_y - self.jumpHeight:
# 以5个像素值向下移动
self.jumpValue = 5
# 通过循环改变玛丽的y坐标
self.rect.y += self.jumpValue
# 如果玛丽回到地面
if self.rect.y >= self.lowest_y:
# 关闭跳跃状态
self.jumpState = False
# 障碍物类
class obstacle():
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.missile = pygame.image.load("image/missile.png")
self.pipe = pygame.image.load("image/pipe.png")
# 加载分数图片
self.numbers = (pygame.image.load("image/0.png"),
pygame.image.load("image/1.png"),
pygame.image.load("image/2.png"),
pygame.image.load("image/3.png"),
pygame.image.load("image/4.png"),
pygame.image.load("image/5.png"),
pygame.image.load("image/6.png"),
pygame.image.load("image/7.png"),
pygame.image.load("image/8.png"),
pygame.image.load("image/9.png"))
# 0和1随机数判断是管道还是导弹
number = random.randint(0, 1)
if number == 0: # 如果随机数为0显示导弹障碍物相反显示管道
self.image = self.missile # 显示导弹障碍
self.move = 15 # 导弹移动速度加快
self.obstacle_y = 150 # 导弹坐标在天上
self.rect.size = self.image.get_size()
else:
self.image = self.pipe # 显示管道障碍
self.move = 5 # 管道移动速度慢
self.obstacle_y = 160 # 管道在地面上
self.rect.size = self.image.get_size()
# 障碍物绘制坐标
self.rect.x = 673
self.rect.y = self.obstacle_y
# 障碍物移动
def obstacle_move(self):
self.rect.x -= self.move
# 绘制障碍物
def draw_obstacle(self):
screen.blit(self.image, (self.rect.x, self.rect.y))
# 显示分数
def showScore(self, score):
# 分数横向位置
X = 546
a = list(str(score))
for i in a:
# 绘制分数
screen.blit(self.numbers[int(i)], (X, 22.4))
# 随着数字增加改变位置
X += 24
if __name__ == '__main__':
mainGame()
六、创意课-flappy bird
1.地图
import pygame
import random
# 游戏窗口
SCREENWIDTH = 500 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 375 # 窗口高度根据地图高度定
FPS = 30 # 更新画面时间
# 地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/地图.jpg").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
# 地图滚动
def map_rolling(self):
if self.x < -490: # 地图已经完全移动完毕
self.x = 500 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 游戏主入口
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化窗口
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.设置窗口大小
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.设置窗口标题
pygame.display.set_caption("钢管鸟")
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(500, 0)
while True:
# 获取单击事件
for event in pygame.event.get():
# 如果单击了关闭窗体就将窗体关闭
if event.type == pygame.QUIT:
pygame.quit() # 退出窗口
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
bg2.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_rolling()
# 更新整个窗体
pygame.display.update()
# 循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()
2.鸟类
import pygame
import random
# 游戏窗口
SCREENWIDTH = 500 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 375 # 窗口高度根据地图高度定
FPS = 30 # 更新画面时间
# 地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/地图.jpg").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
# 地图滚动
def map_rolling(self):
if self.x < -490: # 地图已经完全移动完毕
self.x = 500 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 鸟类
class Bird():
def __init__(self):
# 初始化矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载图片
self.adventure_img = pygame.image.load("image/鸟.png")
self.rect.size = self.adventure_img.get_size()
self.x = 150 # 绘制x坐标
self.y = 150
self.rect.topleft = (self.x, self.y)
# 绘制
def draw_marie(self):
screen.blit(self.adventure_img, (self.x, self.rect.y))
#鸟上升20
def jump(self):
self.rect.y -= 20
#鸟下降2
def move(self):
print(666)
self.rect.y += 2
# 游戏主入口
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化窗口
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.设置窗口大小
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.设置窗口标题
pygame.display.set_caption("钢管鸟")
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(500, 0)
bird = Bird()
while True:
# 获取单击事件
for event in pygame.event.get():
# 如果单击了关闭窗体就将窗体关闭
if event.type == pygame.QUIT:
pygame.quit() # 退出窗口
# 按下键盘上的空格键,开启跳的状态
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 跳
bird.jump()
if over == True:
mainGame()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
bg2.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_rolling()
# 绘制小鸟
bird.draw_marie()
# 小鸟移动
bird.move()
# 更新整个窗体
pygame.display.update()
# 循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()
3.管道
在这里插入代码片
4.最终代码
import pygame
import random
SCREENWIDTH = 500 # 窗口宽度根据地图宽度定
SCREENHEIGHT = 375 # 窗口高度根据地图高度定
FPS = 30 # 更新画面时间
# 定义一个移动地图类
class MyMap():
def __init__(self, x, y):
# 加载背景图片
self.bg = pygame.image.load("image/地图.jpg").convert_alpha()
# 初始化x的坐标
self.x = x
# 初始化y的坐标
self.y = y
# 地图滚动
def map_rolling(self):
if self.x < -490: # 地图已经完全移动完毕
self.x = 500 # 给地图一个新的坐标点
else:
self.x -= 5 # 向左移动5个像素
# 更新地图
def map_update(self):
screen.blit(self.bg, (self.x, self.y))
# 鸟类
class Bird():
def __init__(self):
# 初始化矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载图片
self.adventure_img = pygame.image.load("image/鸟.png")
self.rect.size = self.adventure_img.get_size()
self.x = 150 # 绘制x坐标
self.y = 150
self.rect.topleft = (self.x, self.y)
# 绘制
def draw_marie(self):
screen.blit(self.adventure_img, (self.x, self.rect.y))
#鸟上升20
def jump(self):
self.rect.y -= 20
#鸟下降2
def move(self):
self.rect.y += 2
# 下管道类
class Wall():
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.image = pygame.image.load("image/上管道.png")
# 纵坐标随机生成
number = random.randint(190, 300)
self.rect.size = self.image.get_size()
self.move = 10 # 移动速度
# 障碍物绘制坐标
self.rect.x = 520
self.rect.y = number
# 障碍物移动
def obstacle_move(self):
self.rect.x -= self.move
if self.rect.x < -100:
self.rect.x = 520
self.rect.y = random.randint(190, 300)
# 绘制障碍物
def draw_obstacle(self):
screen.blit(self.image, (self.rect.x, self.rect.y))
# 上管道类
class Wall2():
def __init__(self):
# 初始化障碍物矩形
self.rect = pygame.Rect(0, 0, 0, 0)
# 加载障碍物图片
self.image = pygame.image.load("image/下管道.png")
# 纵坐标随机生成
number = random.randint(-150, -30)
self.rect.size = self.image.get_size()
self.move = 10 # 墙移动速度
# 障碍物绘制坐标
self.rect.x = 520
self.rect.y = number
# 障碍物移动
def obstacle_move(self):
self.rect.x -= self.move
if self.rect.x < -100:
self.rect.x = 520
self.rect.y = random.randint(-150, -30)
# 绘制障碍物
def draw_obstacle(self):
screen.blit(self.image, (self.rect.x, self.rect.y))
# 游戏主函数入口
def mainGame():
over = False # 游戏结束标记
global screen
# 1.初始化窗口
pygame.init()
# 2.使用python时钟控制每个循环多长时间运行一次,在使用时钟前必须先创建clock对象的一个实例
fpsclock = pygame.time.Clock()
# 3.设置窗口大小
screen = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
# 4.设置窗口标题
pygame.display.set_caption("钢管鸟")
# 创建地图对象
bg1 = MyMap(0, 0)
bg2 = MyMap(500, 0)
# 创建鸟对象
bird = Bird()
# 创建下管道对象
wall = Wall()
# 创建上管道对象
wall2 = Wall2()
while True:
# 获取单击事件
for event in pygame.event.get():
# 如果单击了关闭窗体就将窗体关闭
if event.type == pygame.QUIT:
pygame.quit() # 退出窗口
# 按下键盘上的空格键,开启跳的状态
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
# 跳
bird.jump()
if over == True:
mainGame()
if over == False:
# 绘制地图,起到更新地图的作用
bg1.map_update()
bg2.map_update()
# 地图移动
bg1.map_rolling()
bg2.map_rolling()
# 绘制小鸟
bird.draw_marie()
# 小鸟移动
bird.move()
# 绘制管道
wall.draw_obstacle()
wall2.draw_obstacle()
# 管道移动
wall.obstacle_move()
wall2.obstacle_move()
# 判断碰撞
if pygame.sprite.collide_rect(bird, wall) or pygame.sprite.collide_rect(bird, wall2):
# 碰撞后开启结束开关
over = True
# 更新整个窗体
pygame.display.update()
# 循环应该多长时间运行一次
fpsclock.tick(FPS)
if __name__ == '__main__':
mainGame()