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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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()#游戏启动