很常見的遊戲之一,實現原理並不複雜,而且參考了幾個相關的代碼。這邊主要仍是以學習編程語言和學習編程思路爲重點記錄一下吧。最近時間有點吃緊,只能匆忙記錄一下。用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()
主人公的控制相似通常的處理,這邊用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()
ps:最近愈來愈懶了,不知道當初訂的每週至少寫一篇隨筆的目標可否堅持下去。另外鄙視下12306上刷票的黃牛,刷了一天沒買到票,哎 不說了都是淚。