寫簡單遊戲,學編程語言-python篇:大魚吃小魚

 

  很常見的遊戲之一,實現原理並不複雜,而且參考了幾個相關的代碼。這邊主要仍是以學習編程語言和學習編程思路爲重點記錄一下吧。最近時間有點吃緊,只能匆忙記錄一下。用pygame作的大魚吃小魚的遊戲截圖以下:(有些魚的圖片背景沒有作透明處理,這塊確實須要點美工時間,只能先湊合了)。python

   

 

下面的圖片是網上隨便找的素材,這裏用於切換主角的圖片有三張,其餘則是其餘小魚和boss魚。咱們控制的主人魚的大小範圍來決定加載不一樣的圖片。以上準備的素材,其中一些背景色沒有時間作處理,因此遊戲中會有難看的背景色,只能湊合着用。。。編程

1、玩法及邏輯相關:app

  控制你的魚,有個初始大小,當碰到比你小的魚的時候,你會吃掉它,而且會變大;遇到比你大的魚,受到一點傷害,當總生命值爲0時,失敗遊戲結束;當你控制的魚大小增大最大時,遊戲獲勝。當魚受到傷害時,有一段時間是無敵時間,且會閃爍。下面是主要的邏輯處理代碼dom

  

 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()函數決定主人公的圖片類型。編程語言

2、敵方魚的生成處理ide

  上篇作的敵方的處理會在當前視口隨即出現,這個突兀感太強,魚的出現也不能隨機顯示在當前視口,應該由攝像機視角以外生成才符合常理。而且當魚離攝像區域太遠的距離,須要刪除掉魚對象。函數

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

3、跟隨視角的處理學習

    這個主要是跟隨主人公視角的問題,計算出主人公的中心點距離攝像機中心點的距離,當距離偏大的時候,須要移動攝像機的位置,具體處理代碼以下:ui

  

 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》,哎 只能說有巨人的肩膀上站真好。spa

 園友交流羣: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上刷票的黃牛,刷了一天沒買到票,哎 不說了都是淚。

相關文章
相關標籤/搜索