猫史档案馆


【Python作品分享】火柴人街头跑酷V5.0【作品秀】

用户:淏芃淏芃查看:0 回复:1 评论:0 创建时间:2020-07-27T22:29:08


【作品展示】

center_image

 

【作品介绍】

pygame制作

新增速度等级

版本V5.0

 

【作品源代码】

# 修复缓动和已知bug,新增速度等级功能
"""速度等级规则"""
"""0分等级1"""
"""1000分等级2""" 
"""5000分等级3"""
"""10000分等级4"""
"""100000分等级5"""
"""1000000分等级10"""
#PS:SpeedLevel是速度等级,Score是分数
#小贴士:越过障碍物+100分,碰撞金币+1000分
'''      主程序      '''

import sys
import time
from initData import *
from easing import *
pygame.init()

# 障碍物列表
barrierList = []
# 自定义事件
ADDBARIER = pygame.USEREVENT + 1
# 自定义事件(角色动画)
ANIMATION = pygame.USEREVENT + 2
# 自定义事件(角色跳跃)
JUMP = pygame.USEREVENT + 3
# 自定义事件(角色掉落)
DROP = pygame.USEREVENT + 4
# 障碍物生成频率
BARRIERFPS = 0.6
# 主循环频率
FPS = 喵00000
# 获取时钟对象
clock = pygame.time.Clock()
# 游戏初始状态
gameState = GAMEREADY
# 记录游戏分数
score = 0
# 角色生命数
hp = 3
# 背景&地面&障碍物的移动速度
speed = 2
speed1 = 4
# 速度等级
speedLevel = 1
# 碰撞次数
pong = 0


def times(times):
    ctime = time.sleep(times)
    return ctime
# 启动定时器


def startTimer():
    pygame.time.set_timer(ADDBARIER, int(1000/BARRIERFPS))
    pygame.time.set_timer(ANIMATION, int(1000/player['animationFPS']))
# 停止定时器


def stopTimer():
    pygame.time.set_timer(ADDBARIER, 0)
    pygame.time.set_timer(ANIMATION, 0)
    pygame.time.set_timer(JUMP, 0)  # →→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→

#初始化窗口


def initScreen():
    global screen
    # 创建窗口对象
    screen = pygame.display.set_mode(SCREENSIZE)
    # 设置窗口标题
    pygame.display.set_caption('火柴人街头跑酷')
    # 设置标题logo
    pygame.display.set_icon(iconImg)

# 绘制


def draw():
    screen.blit(bg['img'], [bg['x'], bg['y']])
    screen.blit(bg['img'], [bg['x'] + bg['width'], bg['y']])
    screen.blit(gd['img'], [gd['x'], gd['y']])
    screen.blit(gd['img'], [gd['x'] + gd['width'], gd['y']])
    screen.blit(player['img'], [player['x'], player['y']])
    screen.blit(gold['img'], [gold['x'], gold['y']])
    for barrier in barrierList:
        screen.blit(barrier['img'], [barrier['x'], barrier['y']])
    if gameState == GAMEOVER:
        rect = overImg.get_rect()
        rect.center = screen.get_rect().center
        screen.blit(overImg, rect)
        drawText(str(score), 'center', 30)
    elif gameState == GAMERUNNING:
        drawText('score:' + str(score),
                 (SCREENSIZE[0] - 200, 20), size=35, color=[0, 0, 0])
        drawText('Speed Level:' + str(speedLevel),
                 (SCREENSIZE[0] - 400, 20), size=35, color=[0, 0, 0])
    # 绘制准备界面
    elif gameState == GAMEREADY:
        rect = readyImg.get_rect()
        rect.center = screen.get_rect().center
        screen.blit(readyImg, rect)

# 绘制文本


def drawText(text, coordinate, size=35, color=[255, 255, 255]):
    font = pygame.font.SysFont('SimHei', size)
    content = font.render(text, True, color)
    if coordinate == 'center':
        rect = content.get_rect()
        rect.center = screen.get_rect().center
        coordinate = rect
    screen.blit(content, coordinate)

# 移动


def move():
    # 获取速度等级
    speedlisten()
    # 移动背景&地面
    bg['x'] -= speed
    if bg['x'] <= -bg['width']:
        bg['x'] = 0
    gd['x'] -= speed1
    if gd['x'] <= -gd['width']:
        gd['x'] = 0
    # 移动障碍物
    # 因为要从列表中删除元素,所以需要倒序遍历列表
    for i in range(len(barrierList)-1, -1, -1):
        barrier = barrierList[i]
        # 感觉有多处需要自增自减,是否可以使用 -= 的形式
        barrier['x'] -= speed1
        if barrier['x'] <= -barrier['width']:
            # 移出屏幕就从障碍物列表中删除该元素
            barrierList.remove(barrierList[i])
    # 移动金币
    gold['x'] -= speed1
    if gold['x'] <= -gold['width']:
        setRandXY(gold, barrierList, player)

# 更新金币的坐标


def setRandXY(gold, group, player):
    if len(group) != 0:
        # 获取障碍物列表中的最后一个元素
        lastBarrier = group[-1]
        # 获取最后一个障碍物的x坐标
        x = lastBarrier['x']
    else:
        # 没有障碍物时也要保证金币不会瞬间出现
        x = SCREENSIZE[0]
    # 根据最后一个障碍物x坐标计算金币图片x坐标
    gold['x'] = x + random.randint(420, 750)
    gold['y'] = random.randint(220 - player['height'],  330 - gold['height'])

# 角色起跳时的数据


def jumpPlayer():
    # 主角在起跳时不能再执行起跳操作
    if player['state'] == 'jumping':
        while True:
            return
    # 更改主角状态为跳起
    player['state'] = 'jumping'
    # 主角跳起时要用的图片
    player['img'] = runImgList[4]
    # 跳起的起始时间
    player['jumpTime'] = 0
    # 跳起的起始Y坐标
    player['jumpBegin'] = player['y']
    # 跳起的高度
    player['jumpHeight'] = -150
    # 持续时间(分为跳起和落下两部分时间)
    player['jumpDuring'] = 400
    # 跳跃的状态,先跳起后落下
    player['jumpStatus'] = 'up'
    # 用于计算和设置主角跳起时的Y坐标
    pygame.time.set_timer(JUMP, 10)

# 计算和设置角色跳起时的Y坐标


def setJumpY():
    jumpTime = player['jumpTime']
    jumpBegin = player['jumpBegin']
    jumpHeight = player['jumpHeight']
    jumpDuring = player['jumpDuring']
    if player['jumpStatus'] == 'up':
        player['y'] = easeOut(jumpTime, jumpBegin, jumpHeight, jumpDuring)
        jumpTime += 10
        player['jumpTime'] = jumpTime
        if jumpTime > jumpDuring:
            player['jumpTime'] = 0
            player['jumpBegin'] = player['y']
            player['jumpHeight'] = -player['jumpHeight']
            player['jumpStatus'] = 'down'
    elif player['jumpStatus'] == 'down':
        player['y'] = easeIn(jumpTime, jumpBegin, jumpHeight, jumpDuring)
        jumpTime += 10
        player['jumpTime'] = jumpTime
        if jumpTime > jumpDuring:
            player['state'] = 'running'
            # 这行目的防止事件队列中仍有该事件
            player['jumpStatus'] = None
            # 清除定时器
            pygame.time.set_timer(JUMP, 0)

# 碰撞检测


def checkHit(ob1, ob2):
    ob1Top = ob1['y']
    ob1Bottom = ob1['y'] + ob1['height']
    ob1Left = ob1['x']
    ob1Right = ob1['x'] + ob1['width']

    ob2Top = ob2['y']
    ob2Bottom = ob2['y'] + ob2['height']
    ob2Left = ob2['x']
    ob2Right = ob2['x'] + ob2['width']

    if ob1Right >= ob2Left and ob1Left <= ob2Right:
        if ob1Bottom >= ob2Top and ob1Top <= ob2Bottom:
            return True
    # 这里的这个判断是星原哥为了防止学生使用该函数时传参顺序错误
    else:
        if 'ischeck' in ob1:
            if ob1['x'] <= ob2['x']:
                ob1['ischeck'] = True
        elif 'ischeck' in ob2:
            if ob2['x'] <= ob1['x']:
                ob2['ischeck'] = True
        # 讲解了函数没有返回值时默认返回None,None在判断时为False,此处是否要省略
        return False

# 根据碰撞检测结果作出响应


def check():
    global gameState, score, hp, pong
    # 检测障碍物
    for barrier in barrierList:
        if checkHit(player, barrier):
            gameState = GAMEOVER
            dropPlayer()
            break
        else:
            if barrier['ischeck'] and barrier['score']:
                score += barrier['score']
                barrier['score'] = None
            

    # 检测金币
    if checkHit(player, gold):
        setRandXY(gold, barrierList, player)
        score += 1000

# 主角掉落


def dropPlayer():
    # 更改主角状态为掉落
    player['status'] = 'dropping'
    # 主角掉落时的图片
    player['img'] = dropImg
    # 初始化角色掉落数据
    initDropData(player['x'], player['y'], 200,
                 SCREENSIZE[1] - player['y'] + 200, 600)
    # 用于计算和设置主角掉落时的X、Y坐标
    pygame.time.set_timer(DROP, 10)


# 用于存储主角掉落所需要的数据
dropData = {}

# 初始化主角要掉落时的数据
# x:起始X坐标,y:起始Y坐标,upHeight:要跳起的高度,downHeight:跳起后要下降的高度, during:整个跳起掉落持续的时间


def initDropData(x, y, upHeight, downHeight, during):
    # 存储当前计算出的X坐标值
    dropData['x'] = x
    # 存储当前计算出的Y坐标值
    dropData['y'] = y
    # 掉落的起始时间
    dropData['time'] = 0
    # 掉落的起始Y坐标
    dropData['begin'] = y
    # 用于存储跳起和下落的高度,初始值为要跳起的高度
    dropData['height'] = -upHeight
    # 掉落的下降高度
    dropData['downHeight'] = downHeight
    # 掉落的持续时间(分为跳起和下落)
    dropData['during'] = during
    # 掉落的状态,先跳起后下落
    dropData['status'] = 'up'

# 计算和设置主角掉落时的X、Y坐标


def setDropXY():
    x, y = getDropXY()
    # 如果掉落完成,关闭定时器
    if x == -1:
        pygame.time.set_timer(DROP, 0)
    else:
        player['x'] = x
        player['y'] = y

# 计算和设置主角掉落时的X、Y坐标


def getDropXY():
    time = dropData['time']
    begin = dropData['begin']
    height = dropData['height']
    during = dropData['during']
    if dropData['status'] == 'up':
        time += 10
        dropData['x'] += 3
        dropData['y'] = easeOut(time, begin, height, during)
        dropData['time'] = time
        if time >= during:
            dropData['time'] = 0
            dropData['begin'] = dropData['y']
            dropData['height'] = dropData['downHeight']
            dropData['status'] = 'down'
    elif dropData['status'] == 'down':
        time += 10
        dropData['x'] += 3
        dropData['y'] = easeIn(time, begin, height, during)
        dropData['time'] = time
        # 如果掉落动作完成,则返回-1
        if time > during:
            return -1, -1
    return dropData['x'], dropData['y']

#事件监听


def eventListen():
    global gameState, player, barrierList, gd, bg, gold, score, speedLevel
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            sys.exit()
        # 加入准备状态判断
        if gameState == GAMEREADY:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
                gameState = GAMERUNNING
                startTimer()
        elif gameState == GAMERUNNING:
            if event.type == ADDBARIER:
                barrierList.append(getBarrier())
            elif event.type == ANIMATION and player['state'] == 'running':
                animation(player)
            elif event.type == pygame.KEYDOWN and event.key in [pygame.K_SPACE, pygame.K_w, pygame.K_UP]:
                jumpPlayer()
            elif event.type == JUMP:
                setJumpY()
        elif gameState == GAMEOVER:
            if event.type == DROP:
                setDropXY()
            # 判断是否要进行重玩操作
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
                # 初始化数据
                # 角色
                player['x'] = 60
                player['y'] = 330 - runImgList[0].get_rect().height
                player['state'] = 'running'
                # 障碍物
                barrierList = []
                # 地面
                gd['x'] = 0
                gd['y'] = 330
                # 背景
                bg['x'] = 0
                bg['y'] = 0
                # 金币
                gold['x'] = 0
                gold['y'] = 0
                # 分数
                score = 0
                # 移动速度
                speedLecel = 1
                # 障碍物生成速度
                BERRIERFPS = 0.5
                # 启动定时器
                startTimer()
                # 更改游戏状态
                gameState = GAMERUNNING

# 角色动画


def animation(role):
    index = role['imgIndex'] + 1
    if index >= len(runImgList):
        index = 0
    role['img'] = runImgList[index]
    role['imgIndex'] = index


def speedlisten():
    global speed, speed1, BARRIERFPS, speedLevel
    if score <= 1000:
        speed = 2
        speed1 = 4
        speedLevel = 1
    if score >= 1000:
        speed = 4
        speed1 = 6
        speedLevel = 2
    if score >= 5000:
        speed = 7
        speed1 = 9
        speedLevel = 3
    if score >= 10000:
        speed = 10
        speed1 = 15
        speedLevel = 4
    if score >= 100000:
        speed = 15
        speed1 = 20
        speedLevel = 5
    if score >= 1000000:
        speed = 30
        speed1 = 40
        speedLevel = 10

initScreen()
setRandXY(gold, barrierList, player)

while True:
    clock.tick(FPS)
    # 监听窗口
    eventListen()
    draw()
    if gameState == GAMERUNNING:
        move()
        check()
    elif gameState == GAMEOVER:
        stopTimer()
    pygame.display.update()

 

【提示】

部分含有Python第三方库相关内容的作品,在海龟编辑器网页端无法运行哦!如遇到这种情况,可以打开下面的链接,下载海龟编辑器客户端:

https://python.codemao.cn


回复

上一页1 页 / 共 1下一页
开心地小电鼠开心地小电鼠

不错

点赞0


评论