lophy

以案例研究与demo实现驱动知识汲取,坚持进步,内心要强大,拿梦想做赌注,你怎么舍得输!
写简单游戏,学编程语言-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上刷票的黄牛,刷了一天没买到票,哎 不说了都是泪。

posted on 2014-01-10 19:00  lophy  阅读(6527)  评论(2编辑  收藏  举报