• 写简单游戏,学编程语言-python篇:大鱼吃小鱼


      很常见的游戏之一,实现原理并不复杂,并且参考了几个相关的代码。这边主要还是以学习编程语言和学习编程思路为重点记录一下吧。最近时间有点吃紧,只能匆忙记录一下。用pygame做的大鱼吃小鱼的游戏截图如下:(有些鱼的图片背景没有做透明处理,这块确实需要点美工时间,只能先凑合了)。

       

    下面的图片是网上随便找的素材,这里用于切换主角的图片有三张,其他则是其他小鱼和boss鱼。我们控制的主人鱼的大小范围来决定加载不同的图片。以上准备的素材,其中一些背景色没有时间做处理,所以游戏中会有难看的背景色,只能凑合着用。。。

    一、玩法及逻辑相关:

      控制你的鱼,有个初始大小,当碰到比你小的鱼的时候,你会吃掉它,并且会变大;遇到比你大的鱼,受到一点伤害,当总生命值为0时,失败游戏结束;当你控制的鱼大小增大最大时,游戏获胜。当鱼受到伤害时,有一段时间是无敌时间,且会闪烁。下面是主要的逻辑处理代码

      

     1        flashIsOn=round(time.time(),1)*10%2==1
     2         if not gameOverMode and not (invulnerableMode and flashIsOn):
     3             playerobj['rect']=pygame.Rect((playerobj['x']-camerax,playerobj['y']
     4                                            -cameray,playerobj['size'],playerobj['size']))
     5             SCREEN.blit(playerobj['surface'],playerobj['rect'])
     6         for event in pygame.event.get():
     7             if event.type == QUIT:
     8                 pygame.quit()
     9                 sys.exit()
    10             elif event.type==KEYDOWN:
    11                 if event.key in (K_UP,K_w):
    12                     moveDown =False
    13                     moveUp = True
    14                 elif event.key in (K_DOWN,K_s):
    15                     moveDown =True
    16                     moveUp = False
    17                 elif event.key in (K_LEFT,K_a):
    18                     moveRight = False
    19                     moveLeft= True
    20                     if playerobj['facing']==RIGHT:
    21                         playerobj['surface']=playersurfaceset(playerobj['size'], True)
    22                     playerobj['facing']=LEFT
    23                 elif event.key in (K_RIGHT,K_d):
    24                     moveRight = True
    25                     moveLeft= False
    26                     if playerobj['facing']==LEFT:
    27                         playerobj['surface']=playersurfaceset(playerobj['size'], False)
    28                     playerobj['facing']=RIGHT
    29                 elif winMode and event.key == K_r:
    30                     return
    31             elif event.type==KEYUP:
    32                     if event.key in (K_LEFT,K_a):
    33                         moveLeft=False
    34                     elif event.key in (K_RIGHT,K_d):
    35                         moveRight=False
    36                     elif event.key in (K_UP,K_w):
    37                         moveRight=False
    38                     elif event.key in (K_DOWN,K_s):
    39                         moveRight=False
    40             if not gameOverMode:
    41                 if moveLeft:
    42                     playerobj['x']-=MOVESPEED
    43                 if moveRight:
    44                     playerobj['x']+=MOVESPEED
    45                 if moveUp:
    46                     playerobj['y']-=MOVESPEED
    47                 if moveDown:
    48                     playerobj['y']+=MOVESPEED
    49                 for i in range(len(fishobjs)-1,-1,-1):
    50                     obj=fishobjs[i]
    51                     if 'rect' in obj and playerobj['rect'].colliderect(obj['rect']):
    52                         if obj['width']*obj['height']<=playerobj['size']**2:
    53                             playerobj['size']+=int((obj['width']*obj['height'])**0.2)
    54                             del fishobjs[i]
    55                             if playerobj['face']== LEFT:
    56                                 playerobj['surface']=playersurfaceset(playerobj['size'],True)
    57                             if playerobj['face']== RIGHT:
    58                                     playerobj['surface']=playersurfaceset(playerobj['size'],False)                 
    59                             if playerobj['size']>WINSIZE:
    60                                 winMode=True
    61                         elif not invulnerableMode:
    62                             invulnerableMode=True
    63                             invulnerableStartTime=time.time()
    64                             playerobj['health']-=1
    65                             if playerobj['health']==0:
    66                                 gameOverMode =True
    67                                 gameOverStartTime=time.time()
    View Code

    主人公的控制类似一般的处理,这边用flashIsonl来生成时间差(偶数值时间为真)playersurfaceset()函数决定主人公的图片类型。

    二、敌方鱼的生成处理

      上篇做的敌方的处理会在当前视口随即出现,这个突兀感太强,鱼的出现也不能随机显示在当前视口,应该由摄像机视角之外生成才符合常理。并且当鱼离摄像区域太远的距离,需要删除掉鱼对象。

    1 for i in range(len(fishobjs)-1,-1,-1):
    2             if isOutsideArea(camerax,cameray,fishobjs[i]):
    3                 del fishobjs[i]
    4         while len(fishobjs)<10:
    5             fishobjs.append(makeNewfish(camerax,cameray))
     1 def makeNewfish(camerax,cameray):
     2     sq={}
     3     generalSize=random.randint(5,25)
     4     multiplier = random.randint(1,3)
     5     sq['width'] = (generalSize +random.randint(0,10))*multiplier
     6     sq['height']= (generalSize +random.randint(0,10))*multiplier
     7     sq['x'],sq['y']=getRandomoffCameraPos(camerax,cameray,sq['width'],sq['height'])
     8     sq['movx'] = getRandomVelcocity()
     9     sq['movy'] = getRandomVelcocity()
    10     if sq['movx']<0:
    11         sq['surface']=surfaceset(sq['width'],sq['height'],True)
    12     else:
    13         sq['surface']=surfaceset(sq['width'],sq['height'],False)
    14     return sq

    三、跟随视角的处理

        这个主要是跟随主人公视角的问题,计算出主人公的中心点距离摄像机中心点的距离,当距离偏大的时候,需要移动摄像机的位置,具体处理代码如下:

      

     1         playerCenterx=playerobj['x']+int(playerobj['size']/2)
     2         playerCentery=playerobj['y']+int(playerobj['size']/2)
     3         if (camerax+HALF_WINWIDTH)-playerCenterx>CAMERASLACK:
     4             camerax=playerCenterx+CAMERASLACK-HALF_WINWIDTH
     5         elif playerCenterx-(camerax+HALF_WINWIDTH)>CAMERASLACK:
     6             camerax=playerCenterx-CAMERASLACK-HALF_WINWIDTH
     7         if (cameray+HALF_WINHEIGHT)-playerCentery>CAMERASLACK:
     8             cameray=playerCentery+CAMERASLACK-HALF_WINHEIGHT
     9         elif playerCentery-(camerax+HALF_WINHEIGHT)>CAMERASLACK:
    10             cameray=playerCentery-CAMERASLACK-HALF_WINHEIGHT

     大部分应该介绍的应该就这些了,只能说游戏这块水比较深,只能浅尝辄止一番,python做游戏只能简单玩玩,这块不是他的优势。有人感兴趣的话可以研究它,推荐一本不错的书《Making games with python $ pygame》,哎 只能说有巨人的肩膀上站真好。

     园友交流群:21735072  有兴趣请加入~欢迎来灌水~~~~ 注明:博客园     

    附全部源代码如下,比较粗陋,建议以书上源码学习为主:

    import pygame,sys,time,random
    from pygame.locals import *
    WINWIDTH=640
    WINHEIGHT=480
    CAMERASLACK=70
    lfish_img=[]
    FISHSIZE=8
    PLAYERSIZE=3
    SCREEN=None
    rfish_img=[]
    lplayer_img=[]
    rplayer_img=[]
    backgroundimg=None
    rboss_img=None
    lboss_img=None
    FPS=30
    WHITE=[255,255,255]
    MAXHEALTH=3
    MINSPEED=3
    MAXSPEED=9
    MOVESPEED=7
    HALF_WINWIDTH=int(WINWIDTH/2)
    HALF_WINHEIGHT=int(WINHEIGHT/2)
    WINSIZE=300
    def main():
        global FPSCLOCK,SCREEN,lfish_img,rfish_img,lplayer_img,rplayer_img,BASICFONT
                ,rboss_img,lboss_img,backgroundimg
        pygame.init()
        FPSCLOCK=pygame.time.Clock()
        SCREEN=pygame.display.set_mode((WINWIDTH,WINHEIGHT))
        pygame.display.set_caption("fish eat fish")
        BASICFONT=pygame.font.Font("freesansbold.ttf",32)
        for i in range(FISHSIZE):
            fishimg=pygame.image.load("Fish%s.bmp" % i)
            fishimg.set_colorkey(WHITE)
            lfish_img.append(fishimg)
            rfishimg=pygame.transform.flip(fishimg,True,False)
            
            rfish_img.append(rfishimg)
        for i in range(PLAYERSIZE):
            playerimg=pygame.image.load("player%s.png" % i)
            playerimg.set_colorkey(WHITE)   
            lplayer_img.append(playerimg)
            rplayerimg=pygame.transform.flip(playerimg,True,False)
            rplayerimg.set_colorkey(WHITE)
            rplayer_img.append(rplayerimg)
        bossimg=pygame.image.load("boss.png")
    #     bossimg.set_colorkey([0,0,0])
    #     SCREEN.blit(bossimg,(0,0))
        lboss_img=bossimg
        rbossimg=pygame.transform.flip(bossimg,True,False)
        rboss_img=rbossimg
        
        backgroundimg=pygame.image.load("background.jpg")
        
        while True:
            runGame()
    def runGame(): 
        invulnerableMode=False
        invulnerableStartTime=0
        gameOverMode=False
        gameOverStartTime=0
        winMode = False
        
        gameOverSurf=BASICFONT.render('Game Over',True,WHITE)
        gameOverRect=gameOverSurf.get_rect()
        gameOverRect.center=(HALF_WINWIDTH,HALF_WINHEIGHT)
        
        winSurf=BASICFONT.render('you succeed',True,WHITE)
        winRect=winSurf.get_rect()
        winRect.center=(HALF_WINWIDTH,HALF_WINHEIGHT)
        
        winSurf2=BASICFONT.render('you succeed',True,WHITE)
        winRect2=winSurf2.get_rect()
        winRect2.center=(HALF_WINWIDTH,HALF_WINHEIGHT+30)
        
        camerax=0
        cameray=0
        LEFT=0
        RIGHT=1
        fishobjs=[]
        playerobj={'surface':pygame.transform.scale(lplayer_img[0],(25,25)),
                   'size':25,
                   'facing':LEFT,
                   'x':HALF_WINWIDTH,
                   'y':HALF_WINHEIGHT,
                   'health':MAXHEALTH}
        moveLeft = False
        moveRight = False
        moveUp = False
        moveDown = False
        
        while True:
            if invulnerableMode and time.time() - invulnerableStartTime>2:
                invulnerableMode =False
            for sobj in fishobjs:
                sobj['x']+=sobj['movx']
                sobj['y']+=sobj['movy']
                
            for i in range(len(fishobjs)-1,-1,-1):
                if isOutsideArea(camerax,cameray,fishobjs[i]):
                    del fishobjs[i]
            while len(fishobjs)<5:
                fishobjs.append(makeNewfish(camerax,cameray))
            playerCenterx=playerobj['x']+int(playerobj['size']/2)
            playerCentery=playerobj['y']+int(playerobj['size']/2)
            if (camerax+HALF_WINWIDTH)-playerCenterx>CAMERASLACK:
                camerax=playerCenterx+CAMERASLACK-HALF_WINWIDTH
            elif playerCenterx-(camerax+HALF_WINWIDTH)>CAMERASLACK:
                camerax=playerCenterx-CAMERASLACK-HALF_WINWIDTH
            if (cameray+HALF_WINHEIGHT)-playerCentery>CAMERASLACK:
                cameray=playerCentery+CAMERASLACK-HALF_WINHEIGHT
            elif playerCentery-(camerax+HALF_WINHEIGHT)>CAMERASLACK:
                cameray=playerCentery-CAMERASLACK-HALF_WINHEIGHT
            backrect=pygame.Rect((camerax-WINWIDTH,cameray-WINHEIGHT,WINWIDTH*3,WINHEIGHT*3))
            newbackgroundimg=pygame.transform.scale(backgroundimg,(WINWIDTH*3,WINHEIGHT*3))
            SCREEN.blit(newbackgroundimg,backrect)
            
            for obj in fishobjs:
                obj['rect']=pygame.Rect((obj['x']-camerax,obj['y']-cameray,obj['width']
                                         ,obj['height']))
                SCREEN.blit(obj['surface'],obj['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,playerobj['size'],playerobj['size']))
                SCREEN.blit(playerobj['surface'],playerobj['rect'])
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                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']=playersurfaceset(playerobj['size'], True)
                        playerobj['facing']=LEFT
                    elif event.key in (K_RIGHT,K_d):
                        moveRight = True
                        moveLeft= False
                        if playerobj['facing']==LEFT:
                            playerobj['surface']=playersurfaceset(playerobj['size'], False)
                        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):
                            moveRight=False
                        elif event.key in (K_DOWN,K_s):
                            moveRight=False
                if not gameOverMode:
                    if moveLeft:
                        playerobj['x']-=MOVESPEED
                    if moveRight:
                        playerobj['x']+=MOVESPEED
                    if moveUp:
                        playerobj['y']-=MOVESPEED
                    if moveDown:
                        playerobj['y']+=MOVESPEED
                    for i in range(len(fishobjs)-1,-1,-1):
                        obj=fishobjs[i]
                        if 'rect' in obj and playerobj['rect'].colliderect(obj['rect']):
                            if obj['width']*obj['height']<=playerobj['size']**2:
                                playerobj['size']+=int((obj['width']*obj['height'])**0.2)
                                del fishobjs[i]
                                if playerobj['face']== LEFT:
                                    playerobj['surface']=playersurfaceset(playerobj['size'],True)
                                if playerobj['face']== RIGHT:
                                        playerobj['surface']=playersurfaceset(playerobj['size'],False)                 
                                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()
                    if winMode:
                        SCREEN.blit(winSurf,winRect)
                        SCREEN.blit(winSurf2,winRect2)         
            pygame.display.update()
            FPSCLOCK.tick(FPS)
    def isOutsideArea(camerax,cameray,fishobj):            
        boundsLeftEdge =camerax-WINWIDTH
        boundsTopEdge=cameray-WINHEIGHT
        boundsRect=pygame.Rect(boundsLeftEdge,boundsTopEdge,WINWIDTH*3,WINHEIGHT*3)
        objRect=pygame.Rect(fishobj['x'],fishobj['y'],fishobj['width'],fishobj['height'])
        return not boundsRect.colliderect(objRect)
    def makeNewfish(camerax,cameray):
        sq={}
        generalSize=random.randint(5,25)
        multiplier = random.randint(1,3)
        sq['width'] = (generalSize +random.randint(0,10))*multiplier
        sq['height']= (generalSize +random.randint(0,10))*multiplier
        sq['x'],sq['y']=getRandomoffCameraPos(camerax,cameray,sq['width'],sq['height'])
        sq['movx'] = getRandomVelcocity()
        sq['movy'] = getRandomVelcocity()
        if sq['movx']<0:
            sq['surface']=surfaceset(sq['width'],sq['height'],True)
        else:
            sq['surface']=surfaceset(sq['width'],sq['height'],False)
        return sq
    def playersurfaceset(size,Face):
        surface=None
        if size<100:
            if Face ==True:
                surface= pygame.transform.scale(lplayer_img[0],(size,size))
            else:
                surface= pygame.transform.scale(rplayer_img[0],(size,size))
        elif size<200 and size>=100:
            if Face ==True:
                surface= pygame.transform.scale(lplayer_img[1],(size,size))
            else:
                surface= pygame.transform.scale(rplayer_img[1],(size,size))
        else:
            if Face ==True:
                surface= pygame.transform.scale(lplayer_img[2],(size,size))
            else:
                surface= pygame.transform.scale(rplayer_img[2],(size,size))
        return surface
    def surfaceset(width,height,Face):
        surface=None
        if width*height>200*200:
            if Face == True:
                surface= pygame.transform.scale(lboss_img,(width,height))
            else:
                surface= pygame.transform.scale(rboss_img,(width,height))
        else:
            index= int((width*height)%(FISHSIZE-1))
            if Face == True:
                surface= pygame.transform.scale(lfish_img[index],(width,height))
            else:
                surface= pygame.transform.scale(rfish_img[index],(width,height))
        return surface       
    def getRandomVelcocity():
        speed=random.randint(MINSPEED,MAXSPEED)
        if random.randint(0,1):
            return speed
        else:
            return -speed
        
    def getRandomoffCameraPos(camerax,cameray,objwidth,objheight):
        cameraRect=pygame.Rect(camerax,cameray,WINWIDTH,WINHEIGHT)
        while True:
            x=random.randint(camerax-WINWIDTH,camerax+2*(WINWIDTH))
            y=random.randint(camerax-WINHEIGHT,camerax+2*(WINHEIGHT))
            objrect=pygame.Rect(x,y,objwidth,objheight) 
            if not objrect.colliderect(cameraRect):
                return x,y                
    if __name__ == '__main__':
        main()
    View Code

    ps:最近越来越懒了,不知道当初订的每周至少写一篇随笔的目标能否坚持下去。另外鄙视下12306上刷票的黄牛,刷了一天没买到票,哎 不说了都是泪。

  • 相关阅读:
    Display a image in ssrs
    How to transfer parameters from AX to SSRS
    How to get a datatable from AX to SSRS report
    MySQL 8.0 plan optimization 源码阅读笔记
    2017 ES GZ Meetup分享:Data Warehouse with ElasticSearch in Datastory
    JVM服务进程挂掉问题定位查询思路
    [HACK] docker runtime 挂载宿主机目录
    maven 禁止连接外网仓库
    旧项目Makefile 迁移CMake的一种方法:include Makefile
    HBase MVCC 机制介绍
  • 原文地址:https://www.cnblogs.com/lophy/p/3513938.html
Copyright © 2020-2023  润新知