猫史档案馆


【Python作品分享】松鼠争霸【奇遇之旅】【作品秀】

用户:英俊小子英俊小子查看:0 回复:7 评论:0 创建时间:2021-07-13T12:07:10


【作品展示】

center_image

 

【作品介绍】

你能成为长隆喵地上的松鼠霸主吗?

(按上下左右、wasd移动。吃掉比你小的松鼠,不要去招惹比你大的松鼠。喵地很大,没有边界)

 

【作品源代码】

import random,sys,time,math,pygame
from pygame.locals import*

fps=30
kuan=喵0
gao=480
x_kuan=int(kuan/2)
x_gao=int(gao/2)
caos=(24,255,0)
bai=(255,255,255)
hong=(255,0,0)
cameraslack = 90  # 松鼠移动相机前离中心多远
moverate = 9  # 玩家移动的速度
bouncerate = 6  # 玩家弹跳的速度(大的更慢)
bounceheight = 30  # 玩家弹跳的高度
startsize = 25  # 播放器开始时有多大
winsize = 300  # 玩家需要多大才能获胜
invulntime = 2  # 玩家被击中后喵时间的秒数
gameovertime = 3  # “游戏结束”文本在屏幕上停留的时间(以秒为单位)
maxhealth = 3  # 玩家开始时的生命值

numgrass = 80  # 活动区域的喵物体数量ttf
numsquirrels = 30  # 活动区域的松鼠数量
squirrelminspeed = 3  # 最慢的松鼠速度
squirrelmaxspeed = 7  # 最快的松鼠速度
dirchangefreq = 2  # % 每帧方向改变的机会
left = 'left'
right='right'
"""
该程序具有三种数据结构,分别代表玩家、敌对松鼠和喵背景对象。数据结构是具有以下键的字典:

所有三种数据结构使用的键:
    'x' - 游戏世界中对象的左边缘坐标(不是屏幕上的像素坐标)
    'y' - 游戏世界中对象的上边缘坐标(不是屏幕上的像素坐标)
    'rect' - pygame.Rect 对象,表示对象在屏幕上的位置。
播放器数据结构键:
    'surface' - pygame.Surface 对象,用于存储将被绘制到屏幕上的松鼠图像。
    'face' - 设置为 LEFT 或 RIGHT,存储玩家面向的方向。
    'size' - 播放器的宽度和高度(以像素为单位)。(宽度和高度始终相同。)
    'bounce' - 表示玩家在弹跳中的哪个点。0 表示站立(没有弹跳),直到 BOUNCERATE(弹跳完成)
    'health' - 一个整数,显示玩家在喵亡之前可以被更大的松鼠击中多少次。
Enemy Squirrel 数据结构键:
    'surface' - pygame.Surface 对象,用于存储将被绘制到屏幕上的松鼠图像。
    'movex' - 每帧松鼠水平移动的像素数。负整数向左移动,正整数向右移动。
    'movey' - 每帧松鼠垂直移动的像素数。负整数向上移动,正整数向下移动。
    'width' - 松鼠图像的宽度,以像素为单位
    'height' - 松鼠图像的高度,以像素为单位
    'bounce' - 表示玩家在弹跳中的哪个点。0 表示站立(没有弹跳),直到 BOUNCERATE(弹跳完成)
    'bouncerate' - 松鼠弹跳的速度。较低的数字意味着更快的反弹。
    'bounceheight' - 松鼠弹跳的高度(以像素为单位)
喵数据结构键:
    'grassImage' - 一个整数,指的是用于此喵对象的 GRASSIMAGES 中 pygame.Surface 对象的索引
"""
def main():
    global fpsclock,displaysurf,basicfont,l_squir_img,r_squir_img,grassimages
    pygame.init()
    fpsclock=pygame.time.Clock()
    pygame.display.set_icon(pygame.image.load('gameicon.png')) 
    displaysurf=pygame.display.set_mode((kuan,gao))
    pygame.display.set_caption('松鼠争霸')
    basicfont = pygame.font.Font('a.ttf', 32)
    l_squir_img = pygame.image.load('squirrel.png')
    r_squir_img=pygame.transform.flip(l_squir_img,True,False)
    grassimages=[]
    for i in range(1,5):
        grassimages.append(pygame.image.load('grass%s.png'%i))
    while True:
        runGame()


def runGame():
    # 为新游戏的开始设置变量
    invulnerablemode=False# 如果玩家喵
    invulnerablestarttime=0# 玩家变得喵的时间
    gameovermode=False#如果玩家输了
    gameoverstarttime=0# 玩家失败的时间
    winmode=False# 如果玩家赢了

     # 创建表面来保存游戏文本
    gameoversurf=basicfont.render('你输了',True,bai)
    gameoverrect=gameoversurf.get_rect()
    gameoverrect.center=(x_kuan,x_gao)

    winsurf=basicfont.render('你成为了长隆喵地上的霸主',True,bai)
    winrect=winsurf.get_rect()
    winrect.center=(x_kuan,x_gao)

    winsurf2=basicfont.render('(点击r重新开始)',True,bai)
    winrect2=winsurf2.get_rect()
    winrect2.center=(x_kuan,x_gao+30)
     # camerax 和 cameray 是相机视图所在位置的左上角
    camerax=0
    cameray=0

    grassobjs=[]# 存储游戏中的所有喵对象
    squirrelobjs=[]# 存储所有非玩家松鼠对象
    # 存储玩家对象:
    playerobj={'surface':pygame.transform.scale(l_squir_img,(startsize,startsize)),
                'facing':left,
                'size':startsize,
                'x':x_kuan,
                'y':x_gao,
                'bounce':0,
                'health':maxhealth}

    moveleft=False
    moveright=False
    moveup=False
    movedown=False

# 从屏幕上的一些随机喵图像开始
    for i in range(10):
        grassobjs.append(makenewgrass(camerax,cameray))
        grassobjs[i]['x']=random.randint(0,kuan)
        grassobjs[i]['y']=random.randint(0,gao)
    
    while True:# 主游戏循环
        # 检查我们是否应该关闭喵
        if invulnerablemode and time.time()-invulnerablestarttime>invulntime:
            invulnerablemode=False 
         # 移动所有的松鼠
        for sobj in squirrelobjs:
             # 移动松鼠,并调整它们的弹跳
            sobj['x'] += sobj['movex']
            sobj['y'] += sobj['movey']
            sobj['bounce'] += 1
            if sobj['bounce']>sobj['bouncerate']:
                sobj['bounce'] = 0  # 重置反弹量

            # 他们改变方向的随机机会
            if random.randint(0,99) 0:  # 面朝右
                    sobj['surface'] = pygame.transform.scale(
                        r_squir_img, (sobj['kuan'], sobj['gao']))
                else:#面朝左
                    sobj['surface'] = pygame.transform.scale(
                        l_squir_img, (sobj['kuan'], sobj['gao']))

            # 遍历所有对象,看看是否有需要删除的对象
        for i in range(len(grassobjs)-1 ,-1 ,-1):
            if isoutsiedactivearea(camerax,cameray,grassobjs[i]):
                del grassobjs[i]
        for i in range(len(squirrelobjs)-1, -1, -1):
            if isoutsiedactivearea(camerax, cameray, squirrelobjs[i]):
                del squirrelobjs[i]

            # 如果我们没有足够的喵和松鼠,请添加更多的喵和松鼠
        while len(grassobjs) cameraslack:
            camerax = playercenterx + cameraslack - x_kuan
        elif playercenterx - (camerax + x_kuan) > cameraslack:
            camerax = playercenterx - cameraslack - x_kuan
        if (cameray + x_gao) - playercentery > cameraslack:
            cameray = playercentery + cameraslack - x_gao
        elif playercentery - (cameray + x_gao) > cameraslack:
            cameray = playercentery - cameraslack - x_gao

        # 绘制绿色背景
        displaysurf.fill(caos)
        # 在屏幕上绘制所有喵物体
        for gobj in grassobjs:
            grect=pygame.Rect( (gobj['x']-camerax,
                                gobj['y']-cameray,
                                gobj['kuan'],
                                gobj['gao']))
            displaysurf.blit(grassimages[gobj['grassimage']],grect)
        # 绘制其他松鼠
        for sobj in squirrelobjs:
            sobj['rect']=pygame.Rect((sobj['x']-camerax,
                                      sobj['y']-cameray-getBounceAmount(sobj['bounce'],sobj['bouncerate'],sobj['bounceheight']),
                                      sobj['kuan'],
                                      sobj['gao']))
            displaysurf.blit(sobj['surface'],sobj['rect'])
         # 绘制玩家松鼠
        flashison=round(time.time(),1)*10%2==1
        if not gameovermode and not (invulnerablemode and flashison):
            playerobj['rect']=pygame.Rect((playerobj['x']-camerax,
                                           playerobj['y']-cameray-getBounceAmount(playerobj['bounce'],bouncerate,bounceheight),
                                           playerobj['size'],
                                           playerobj['size']))
            displaysurf.blit(playerobj['surface'], playerobj['rect'])
         # 绘制健康表
        drawhealthmeter(playerobj['health'])

        for event in pygame.event.get():  # 事件处理循环
            if event.type==QUIT:
                terminate()
            elif event.type==KEYDOWN:
                if event.key in (K_UP,K_w):
                    movedown=False
                    moveup=True
                elif event.key in (K_DOWN, K_s):
                    movedown = True
                    moveup = False
                elif event.key in (K_LEFT, K_a):
                    moveright = False
                    moveleft = True
                    if playerobj['facing']==right:#调换图像
                        playerobj['surface']=pygame.transform.scale(
                            l_squir_img,(playerobj['size'],playerobj['size']))
                    playerobj['facing']=left
                elif event.key in (K_RIGHT, K_d):
                    moveright = True
                    moveleft = False
                    if playerobj['facing'] == left:
                        playerobj['surface'] = pygame.transform.scale(
                            r_squir_img, (playerobj['size'], playerobj['size']))
                    playerobj['facing'] = right
                elif winmode and event.key==K_r:
                    return

            elif event.type==KEYUP:
                #松开按键
                if event.key in (K_LEFT,K_a):
                    moveleft=False
                elif event.key in (K_RIGHT, K_d):
                    moveright = False
                elif event.key in (K_UP, K_w):
                    moveup = False
                elif event.key in (K_DOWN, K_s):
                    movedown = False
                
                elif event.key==K_ESCAPE:
                    terminate()


        if not gameovermode:
            # 实际移动玩家
            if moveleft:
                playerobj['x']-=moverate
            if moveright:
                playerobj['x']+=moverate
            if moveup:
                playerobj['y']-=moverate
            if movedown:
                playerobj['y']+=moverate

            if (moveleft or moveright or moveup or movedown) or playerobj['bounce']!=0:
                playerobj['bounce']+=1
            if playerobj['bounce']>bouncerate:
                playerobj['bounce'] = 0  # 重置反弹量
            
            # 检查玩家是否与任何松鼠发生碰撞
            for i in range(len(squirrelobjs)-1,-1,-1):
                sqobj=squirrelobjs[i]
                if 'rect' in sqobj and playerobj['rect'].colliderect(sqobj['rect']):
                    # 发生了玩家/松鼠碰撞
                    if sqobj['kuan']*sqobj['gao']<=playerobj['size']**2:
                        # 玩家更大,吃松鼠
                        playerobj['size']+=int((sqobj['kuan']*sqobj['gao'])**0.2)+1
                        del squirrelobjs[i]

                        if playerobj['facing']==left:
                            playerobj['surface']=pygame.transform.scale(
                                l_squir_img,(playerobj['size'],playerobj['size']))
                        if playerobj['facing'] == right:
                            playerobj['surface'] = pygame.transform.scale(
                                r_squir_img, (playerobj['size'], playerobj['size']))

                        if playerobj['size']>winsize:
                            winmode = True  # 打开“赢模式”

                    elif not invulnerablemode:
                        # 玩家变小并受到伤害
                        invulnerablemode=True
                        invulnerablestarttime=time.time()
                        playerobj['health']-=1
                        if playerobj['health']==0:
                            gameovermode = True  # 开启“游戏结束模式”
                            gameoverstarttime = time.time()

        else:  # 游戏结束,显示“游戏结束”文本
            displaysurf.blit(gameoversurf,gameoverrect)
            if time.time()-gameoverstarttime>gameovertime: 
                return  # 结束当前游戏

         # 检查玩家是否赢了
        if winmode:
            displaysurf.blit(winsurf,winrect)
            displaysurf.blit(winsurf2, winrect2)

        pygame.display.update()
        fpsclock.tick(fps) 


def drawhealthmeter(currenthealth):
    for i in range(currenthealth):#绘制生命表红块
        pygame.draw.rect(displaysurf,hong,(15,5+(10*maxhealth)-i*10,20,10))
    for i in range(maxhealth):#绘制生命表白色轮廓
        pygame.draw.rect(displaysurf, bai,(15, 5+(10*maxhealth)-i*10, 20, 10),1)

def terminate():
    pygame.quit()
    sys.exit()

def getBounceAmount(currentbounce,bouncerate,bouncegao):
    # 根据反弹返回要偏移的像素数。
    # 较大的反弹率意味着较慢的反弹。
    # 更大的反弹高度意味着更高的反弹。
    # currentbounce 总是小于bouncerate
    return int(math.sin((math.pi/float(bouncerate))*currentbounce)*bouncegao)
    
def getrandomvelocity():
    speed=random.randint(squirrelminspeed,squirrelmaxspeed)
    if random.randint(0,1)==0:
        return speed
    else:
        return -speed

def getrandomoffcamerapos(camerax,cameray,objkuan,objgao):
    # 创建一个相机视图的矩形
    camerarect=pygame.Rect(camerax,cameray,kuan,gao)
    while True:
        x=random.randint(camerax-kuan,camerax+(2*kuan))
        y=random.randint(cameray-gao,cameray+(2*gao))
        # 创建一个带有随机坐标的 Rect 对象并使用colliderect()
        # 确保右边缘不在相机视图中。
        objrect=pygame.Rect(x,y,objkuan,objgao)
        if not objrect.colliderect(camerarect):
            return x,y

def makenewsquirrel(camerax,cameray):
    sq={}
    generalSize = random.randint(5, 25)
    multiplier = random.randint(1, 3)
    sq['kuan'] = (generalSize + random.randint(0, 10)) * multiplier
    sq['gao'] = (generalSize + random.randint(0, 10)) * multiplier
    sq['x'], sq['y'] = getrandomoffcamerapos(
        camerax, cameray, sq['kuan'], sq['gao'])
    sq['movex'] = getrandomvelocity()
    sq['movey'] = getrandomvelocity()

    if sq['movex'] < 0:  # 松鼠面向左边
        sq['surface'] = pygame.transform.scale(
            l_squir_img, (sq['kuan'], sq['gao']))
    else:  # 松鼠向右边
        sq['surface'] = pygame.transform.scale(
            r_squir_img, (sq['kuan'], sq['gao']))
    sq['bounce'] = 0
    sq['bouncerate'] = random.randint(10, 18)
    sq['bounceheight'] = random.randint(10, 50)
    return sq

def makenewgrass(camerax,cameray):
    gr={}
    gr['grassimage']=random.randint(0,len(grassimages)-1)
    gr['kuan']=grassimages[0].get_width()
    gr['gao'] = grassimages[0].get_height()
    gr['x'],gr['y']=getrandomoffcamerapos(camerax,cameray,gr['kuan'],gr['gao'])
    gr['rect']=pygame.Rect((gr['x'],gr['y'],gr['kuan'],gr['gao']))
    return gr

def isoutsiedactivearea(camerax,cameray,obj):
    # 如果camerax和cameray超过
    #一半,则返回False - 超出窗口边缘的窗口长度。
    boundsleftedge=camerax-kuan
    boundstopedge=cameray-gao
    boundsrect=pygame.Rect(boundsleftedge,boundstopedge,kuan*3,gao*3)
    objrect=pygame.Rect(obj['x'],obj['y'],obj['kuan'],obj['gao'])
    return not boundsrect.colliderect(objrect)

if __name__ == '__main__':
    main()

 

【提示】

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

https://python.codemao.cn


回复

上一页1 页 / 共 1下一页
英俊小子英俊小子

center_image把它改成gameicon

点赞0


评论


英俊小子英俊小子

把它改成grass1center_image

点赞0


评论


英俊小子英俊小子

center_image把它改成grass2

点赞0


评论


英俊小子英俊小子

center_image把它改成grass3

点赞0


评论


英俊小子英俊小子

center_image把它改成grass4

点赞0


评论


英俊小子英俊小子

center_image把它改成squirrel

点赞0


评论


英俊小子英俊小子

再弄一个名为a.ttf的文字数据,如果没有,可以把61行的a.ttf改成freesansbold.ttf,只不过这个不支持中文,你可以把80,84,88行的中文改成英文

点赞0


评论