You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

198 lines
12 KiB

6 months ago
import pygame, sys
import random
class Person(): # 金枪小帅的属性
def __init__(self, surf=None, y=None):
self.surface = surf#初始化surface对象
self.y = y # y坐标
self.w = surf.get_width()/ 12 # 宽度
self.h = surf.get_height() / 2 # 高度
self.cur_frame = -1 # 当前的运动状态帧
self.state = 0 # 0代表跑步状态1代表跳跃状态,2代表连续跳跃
self.gravity = 1 # 重力加速度
self.velocity_y = 0 # y方向的速度
self.vy_start = -20 # 起跳开始速度
def getPos(self): # 获取当前的位置坐标,用于碰撞检测,是否与障碍物坐标一致
return (0, self.y + 12, self.w, self.h)#0表y向的速度
class Obstacle(object): # 障碍物的属性
def __init__(self, surf, x=0, y=0):
self.surface = surf#初始化surface对象
self.x = x#放置的x坐标
self.y = y#放置的y坐标
self.w = surf.get_width()#获取宽度
self.h = surf.get_height()#获取高度
self.cur_frame = random.randint(0, 7) # 随机获取一种障碍物的类型共7种类型
self.w = 100#设置初始宽度
self.h = 100#设置初始高度
def getPos(self): # 获取人物角色金枪小帅或者障碍物当前的坐标信息分别是x坐标y坐标宽度w高度h
return (self.x, self.y, self.w, self.h)#返回坐标信息
def judgeCollision(self, rect1, rect2): # 碰撞检测,即是判断金枪小帅和障碍物的坐标是否一致,以及考虑障碍物的大小
if (rect2[0] >= rect1[2] - 20) or (rect1[0] + 40 >= rect2[2]) or (rect1[1] + rect1[3] < rect2[1] + 20) or (
rect2[1] + rect2[3] < rect1[1] + 20):
return False
return True
class BackGround(object): # 背景类属性设计继承于object
def __init__(self, surf):
self.surface = surf # 初始化Surface对象
self.dx = -10
self.w = surf.get_width() # 返回 Surface 对象的宽度
self.rect = surf.get_rect() # 获取 Surface 对象的矩形区域
class PaoKu(object):#游戏运作过程
def __init__(self):
pygame.init()#初始化Pygame所有模块
pygame.mixer.init()#初始化Pygame的声音混合器模块
self.width = 1200 # 设置游戏窗口宽度
self.height = 500 # 设置游戏窗口高度
self.size = (self.width, self.height)#保存初始设置宽度,高度
self.screen = pygame.display.set_mode(self.size)#调用pygame.display打开size内容大小的窗口
pygame.display.set_caption('ygc0417版本跑酷小游戏')#调用display.set_caption设置游戏的title内容
self.score = 0 # 游戏取得的分数
self.font1 = pygame.font.Font("resource/simkai.ttf", 32) # 字体文件问题处理
self.font2 = pygame.font.Font("resource/simkai.ttf", 64) # 字体文件问题处理
self.obstacle_pic = pygame.image.load("resource/obstacles.png").convert_alpha() # 从image下载障碍物图片convert_alpha转变成字母
self.game_over = pygame.image.load("resource/gameover.bmp").convert_alpha() # 从image下载游戏结束图片convert_alpha转变成字母
self.bg = BackGround(pygame.image.load("resource/bg.png").convert_alpha()) # 从image下载背景对象作BackGround类的对象convert_alpha转变成字母
self.person = Person(pygame.image.load("resource/person.png").convert_alpha(), 500 - 85) # 从image下载人物对象图片convert_alpha转变成字母
self.screen.blit(self.bg.surface, [0, 0]) # 初始化游戏背景初始坐标0,0
self.obstacle_list = [] # 以空列表作障碍物对象数组
self.game_state = 0 # 设置游戏状态0表示游戏中1表示游戏结束
self.life = 3 # 初始的生命值假如是3即是可以碰撞的次数为0则游戏自动结束重新开始计分数
self.clock = pygame.time.Clock() # pygame.time.Clock从系统时间来用来时钟记时用clock记录
self.bg_music = pygame.mixer.Sound(r"resource\bgm.wav").play(0, 0, 0) # 循环播放音乐
def startGame(self, screen): # 开始游戏界面设置的函数
gameStart = pygame.image.load("resource/start1new.png")#从image下载开始游戏界面的图片给gameStart
screen.blit(gameStart, (0, 0))#调用blit放置开始游戏界面的背景图初始化0,0坐标
font = pygame.font.SysFont("resource/simkai.ttf", 70) # 设置字体格式
tip = font.render("Press Any Key To Start!, Press Esc To Quit", True, (65, 105, 225))#调用font.render显示游戏开始的提示内容
screen.blit(tip, (self.width / 2 - 550, self.height / 2 + 150))#tip提示内容放置在窗口位置的设置
pygame.display.update()#调用pygame.display.update()更新整个屏幕显示
while True:#设置一个无限循环
for event in pygame.event.get(): # 关闭窗口的位置
if event.type == pygame.QUIT:#操作event.type=256后满足条件退出游戏
self.terminate()#调用游戏结束函数terminate()
elif event.type == pygame.KEYDOWN:#操作event.type=768后满足条件退出游戏
if (event.key == pygame.K_ESCAPE): # 按下ESC键退出游戏
self.terminate()#调用游戏结束函数terminate()
else:
return
def addObstacle(self): # 添加障碍物函数设置,相当于游戏的困难程度
rate = 3
#是否生成障碍物
if not random.randint(0, 300) < rate:#避免生成多余设置的障碍物,多余设置的数量就返回开始游戏阶段
return#返回上一步
y = random.choice([self.height - 100, self.height - 200, self.height - 300, self.height - 400])#调用choice随机设置y坐标
obstacle = Obstacle(self.obstacle_pic, self.width + 40, y)#随机获取障碍物图片,并且设置它在窗口的坐标
self.obstacle_list.append(obstacle)#将获取的障碍物添加到obstacle_list空列表内
# 监听键盘事件,并做处理
def ListenKeyBoard(self): # 键盘事件处理函数设置
for event in pygame.event.get():
if event.type == pygame.QUIT:#256判断条件
sys.exit()#退出系统函数
elif event.type == pygame.KEYDOWN:#768判断条件
if self.game_state == 0:# 设置游戏状态0为开始
if event.key == pygame.K_SPACE:#设置空格键跳跃
pygame.mixer.Sound(r"resource\jump.wav").play()#开始游戏就循环播放音乐BGM
if self.person.state == 0:#初始角色状态
self.person.state = 1
self.person.velocity_y = self.person.vy_start
elif self.person.state == 1:
self.person.state = 2
self.person.velocity_y = self.person.vy_start#y坐标的速度设置开始起跳速度为-20
elif self.game_state == 1:#游戏结束
if event.key == pygame.K_RETURN: # 重新开始游戏K_RETURN=13
self.bg_music.stop()#在结束界面,音乐结束
self.__init__()#游戏运作函数调用
if self.game_state == 0:#游戏开始中设置
# 以下BackGorund的运动
self.bg.dx += 10#这是游戏进程的设置??
if self.bg.dx == 1200:#游戏进程为1200吗
self.bg.dx = 0
# Person的移动
if self.person.state == 0:#人物为跑步状态中
self.person.cur_frame += 1#角色运动帧选择+1
if self.person.cur_frame == 12:#判断运动帧是否到了最后一帧
self.person.cur_frame = 0#重新设置为0帧
else:#人物出去跳跃状态中
self.person.y += self.person.velocity_y#人物坐标加上在人物起跳y坐标的初始速度
self.person.velocity_y += self.person.gravity#人物起跳y坐标的初始速度+重力加速度1
if self.person.y >= 500 - 85:#当人物跳跃结束后,重新设置人物坐标
self.person.y = 500 - 85#结束跳跃状态后设置好人物的y坐标
self.person.state = 0#结束跳跃状态后人物状态设置为跑步0
# bstacle的操作
self.addObstacle()#调用障碍物函数生成障碍物
for obstacle in self.obstacle_list:#self.obstacle_list障碍物列表清单
obstacle.x -= 10 # obstacle向左移动十个像素
if obstacle.x + obstacle.w <= 0: # 当obstacle离开界面时
self.obstacle_list.remove(obstacle)#从obstacle_list列表移除掉这个障碍物
self.score += 100 # 每避开一个障碍物加100分分数获取
if obstacle.judgeCollision(self.person.getPos(), obstacle.getPos()): # 碰撞检测,当前的人物坐标与障碍物坐标作为形参
if obstacle.cur_frame == 6:#判断是否碰撞到的是金币
self.obstacle_list.remove(obstacle)#移除这个金币障碍物
self.score += 1000 # 吃金币加1000分
coin_sound = pygame.mixer.Sound(
r"resource/coin.wav")#coin_sound保存用pygame.mixer.Sound调用的音乐BGM碰撞金币音效
coin_sound.play()#播放音效
else:
self.life -= 1#每碰撞到其他障碍物就减少1点生命值
self.obstacle_list.remove(obstacle)#从obstacle_list移除障碍物
if self.life <= 0:#生命值为0
self.game_state = 1 # 游戏失败,到结束游戏界面
die_sound = pygame.mixer.Sound(
r"resource\die.wav") # 添加碰撞之后产生的音效
die_sound.play()#播放音效
# 更新显示界面
def updateScreen(self, screen):
screen.blit(self.bg.surface, [-self.bg.dx, 0]) # 背景的贴图,并且设置坐标位置
screen.blit(self.bg.surface, [1200 - self.bg.dx, 0])#游戏进程完成后的界面显示,并且设置坐标位置
text = self.font1.render("score:%d" % self.score, True, (128, 128, 128)) # 调用render分数的贴图显示对象self.score设置颜色
screen.blit(text, (500, 20))#绘制对象text分数的贴图设置放置坐标
del text
rest_life = self.font1.render("life:%d" % self.life, True, (128, 128, 128)) # 剩余生命显示
screen.blit(rest_life, (400, 20))#生命显示的贴图绘制对象rest_life
del rest_life
screen.blit(self.person.surface, [0, self.person.y], [int(self.person.cur_frame) * self.person.w, 0, self.person.w, self.person.h]) # 人物的贴图
for obstacle in self.obstacle_list: # 障碍物的贴图显示
screen.blit(obstacle.surface, [obstacle.x, obstacle.y],
[int(obstacle.cur_frame) * obstacle.w, 0, obstacle.w, obstacle.h])
# 判断游戏的状态
def judgeState(self, screen):
if self.game_state == 0:
self.updateScreen(screen)
return
elif self.game_state == 1:
screen.blit(self.game_over, [0, 0])
text = self.font1.render("GameOver Score:%d Press Enter to restart" % self.score, True, (255, 0, 0))#显示对象self.score并且设置颜色(255, 0, 0)
screen.blit(text, (self.width / 2 - 350, self.height / 2 + 150))
# 游戏结束函数设置
def terminate(self):
pygame.quit()#退出窗口
sys.exit()#退出系统
# 游戏主入口函数
def main(self):
self.startGame(self.screen)#开始游戏
while True:
self.clock.tick(40) # 获取设置时钟频率
self.judgeState(self.screen)#识别游戏状态是否启动成功
self.ListenKeyBoard()#键盘处理函数调用
pygame.display.flip()#更新屏幕
if __name__ == '__main__':
paoku = PaoKu()#游戏运作
paoku.main()#游戏启动