游戲框架分為兩部分
1.創(chuàng)建一個(gè)plane_main.py的主文件,寫出一個(gè)PlaneGame的主類。
import pygame
class PlaneGmae(object):
def __init__(self):
print('游戲初始化...')
def start_game(self):
print('游戲開始...')
if __name__ == '__main__':
# 創(chuàng)建游戲?qū)ο? game = PlaneGmae()
# 啟動(dòng)游戲
game.start_game()
運(yùn)行結(jié)果為
D:\python\python36\python.exe D:/PycharmProjects/feijidazhan_1/feiji.py
游戲初始化...
游戲開始...
2.另新建一個(gè)plane_sprite.py 的模塊
import pygame
class Game_Sprite(pygame.sprite.Sprite):#派生精靈子類
'''飛機(jī)大戰(zhàn)游戲精靈'''
def __init__(self,image_name,speed = 1):
# 繼承父類的__init__()
super().__init__()
# 定義對(duì)象的屬性
self.image =pygame.image.load(image_name)
self.rect = self.image.get_rect()
'''self.image的get_rect()返回pygame.Rect(0,0,width,height)'''
self.speed = speed
def update(self):
self.rect.y += self.speed
3. 主程序中設(shè)置游戲初始化的步驟
class PlaneGmae(object):
def __init__(self):
print('游戲初始化...')
# 1.創(chuàng)建游戲屏幕
self.screen = pygame.display.set_mode(SCREEN_RECT.size) #引入的常量
# 2.創(chuàng)建游戲時(shí)鐘
self.clock = pygame.time.Clock()
# 3.私有方法創(chuàng)建精靈和精靈組
self.__creat_sprite()
def __creat_sprite(self):
pass
4主程序中游戲的開始部分的步驟
class PlaneGmae(object):
游戲初始化部分...
.......
def start_game(self):
print('游戲開始...')
while True:
# 1.設(shè)置幀率
self.clock.tick(60)
# 2. 事件監(jiān)聽
self.__event_monitor()
# 3. 碰撞檢測(cè)
self.__check_collide()
# 4. 繪制圖像
self.__blit_photo()
# 5.刷新顯示
pygame.display.update()
5.為了讓程序可讀性高,便于維護(hù),建議是使用私有方法,由于上面的四個(gè)步驟都是私有方法,所以接下來(lái)在上面的主要類開始布置私有方法
def __event_monitor(self):
pass
def __check_collide(self):
pass
def __blit_photo(self):
pass
@staticmethod
def __game_over():
print('退出游戲')
# 卸載所有模塊
pygame.quit()
# 退出程序
exit()
- 需要注意的上面有一個(gè)靜態(tài)方法,由于這個(gè)方法調(diào)用這個(gè)類里的任何方法和屬性,所以要把它編程靜態(tài)方法,加修飾符@staticmethod 不用加self參數(shù)
- 代碼走到上面的這些就已經(jīng)把飛機(jī)大戰(zhàn)的游戲的整體框架搞定了
shift+f10 執(zhí)行一下代碼,顯示為:

image.png
6.接下來(lái)我們開始布置背景圖(這里用到一個(gè)小套路,讓背景圖在垂直方向上移動(dòng),這樣就可以讓英雄飛機(jī)相對(duì)運(yùn)動(dòng)了)
1.在模塊文檔那里開始寫背景類
class Background(Game_Sprite):
def __init__(self,is_alt = False):
super().__init__('./images/background.png')
if is_alt:
self.rect.bottom = 0
def update(self):
# 讓屏幕往下移動(dòng),所以可以用到父類的方法。所以可以繼承
super().update()
# 判斷底部照片是否超出屏幕
if self.rect.y > SCREEN_RECT.height:
self.rect.y =-SCREEN_RECT.height
2.回到主程序中的初始化部分那里,開始填寫__creat_sprite()私有方法
def __creat_sprite(self):
# 創(chuàng)造背景精靈和精靈組
bg1 = Background()
bg2 = Background(True)
self.bg_group = pygame.sprite.Group(bg1,bg2)
3.回到主程序中游戲開始部分那里,self.__blit_photo() 圖像繪制更新那里
def __blit_photo(self):
# 背景圖片的繪制
self.bg_group.update()
self.bg_group.draw(self.screen)
shift+f10 運(yùn)行的效果是一向下移動(dòng)的背景圖
7.為了方便后面測(cè)試程序,我們?cè)谶@里就開始寫事件監(jiān)聽的代碼,一旦檢測(cè)到退出的信號(hào)就直接退出
def __event_monitor(self):
for event in pygame.event.get():
# 判斷監(jiān)聽是否有退出動(dòng)作
if event.type == pygame.QUIT:
PlaneGmae. __game_over()
- 注意靜態(tài)方法的調(diào)用是直接類名.方法名
8.敵機(jī)的類的填寫以及精靈類和精靈組的填寫(由于敵機(jī)較多,要用到定時(shí)器)
class Enemy(Game_Sprite):
def __init__(self):
super().__init__('./images/enemy1')
# 敵機(jī)初始化位置
# 1.x軸上的隨機(jī)位置
Max_x = SCREEN_RECT.width-self.rect.width
self.rect.x = random.randint(0,Max_x)
# 2.y軸上的隨機(jī)位置
self.rect.bottom = 0
# 初始速度的設(shè)置
self.speed = random.randint(1,3)
def update(self):
# 繼承父類的update讓敵機(jī)向下移動(dòng)
super().update()
# 判斷敵機(jī)是否超出屏幕
if self.rect.y > SCREEN_RECT.height:
self.kill()
def __del__(self):
print('敵機(jī)掛了%s' % self.rect)
1.敵機(jī)定時(shí)器的三步驟:
a.在模塊文件中寫出定時(shí)器常量 eg:XXX = pygame.USEREVENT
b.在主程序的初始化中
pygame.time.set_timer(CREAT_TIMER,1000)
其中1000指的1000毫秒也就是1秒執(zhí)行一個(gè)定時(shí)器的動(dòng)作
c.在事件監(jiān)聽里
elif event.type == CREAT_TIMER:
print('產(chǎn)生敵機(jī)...')
那樣就可以1秒一個(gè)敵機(jī)出現(xiàn)
2.開始在初始化位置創(chuàng)建精靈組
# 創(chuàng)建敵機(jī)精靈組
self.enemy_group = pygame.sprite.Group()
3.在事件監(jiān)聽那里去寫精靈組,因?yàn)檫@是持續(xù)不斷的要精靈組的
elif event.type == CREAT_TIMER:
print('產(chǎn)生敵機(jī)...')
# 敵機(jī)精靈
enemy = Enemy()
# 敵機(jī)精靈組
self.enemy_group.add(enemy)
4.將敵機(jī)精靈組進(jìn)行繪制
# 敵機(jī)的繪制
self.enemy_group.update()
self.enemy_group.draw(self.screen)
-
此時(shí)屏幕開始持續(xù)出現(xiàn)敵機(jī)
image.png
9.開始英雄的類已經(jīng)精靈的布置
class Hero(Game_Sprite):
# 繼承父類,設(shè)置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 確定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
- 在創(chuàng)建精靈的私有方法里開始創(chuàng)建英雄的精靈和精靈組
# 創(chuàng)建英雄精靈和精靈組
self. hero_sprite = Hero() #此對(duì)象要在其他方法被調(diào)用所以加self
self.hero_sprite_group = pygame.sprite.Group(hero_sprite)
- 繪制圖像
# 英雄的繪制
self.hero_sprite_group.update()
self.hero_sprite_group.draw(self.screen)
-
shift + f10
image.png
10.開始讓飛機(jī)在左右移動(dòng)但是不能超出左右邊界
- 1.使用鍵盤按鍵獲取按鍵元組
# 使用鍵盤方法獲取按鍵元組
keys_pressed = pygame.key.get_pressed()
# 判斷元組中對(duì)應(yīng)按鍵索引值
if keys_pressed[pygame.K_RIGHT]:
self.hero_sprite.speed = 2
elif keys_pressed[pygame.K_LEFT]:
self.hero_sprite.speed = -2
else:
self.hero_sprite.speed = 0
這個(gè)按鍵元組的value值是1時(shí)鍵值就是左右的一種
此時(shí)的Hero類
class Hero(Game_Sprite):
# 繼承父類,設(shè)置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 確定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
def update(self):
# 因?yàn)槭亲笥乙苿?dòng),所以可以完全改寫父類方法
self.rect.x += self.speed
# 判斷英雄飛機(jī)是否飛出屏幕外
if self.rect.x < 0:
self.rect.x = 0
elif self.rect.x > SCREEN_RECT.width-self.rect.width:
self.rect.right = SCREEN_RECT.right
-
此時(shí)的效果為,英雄可以左右移動(dòng)但不會(huì)超出邊界
image.png
11.開始設(shè)置子彈
- 1.設(shè)置子彈的類
class Bullet(Game_Sprite):
def __init__(self):
# 繼承父類,加載圖片
super().__init__('./images/bullet1.png',-2)
# 初始位置先不要管,等到英雄類里再去弄
def update(self):
# 繼承父類方法,讓子彈移動(dòng)
super().update()
# 判斷子彈是否超出屏幕
if self.rect.bottom < 0:
self.kill()
def __del__(self):
print('超出子彈被銷毀%s'%self.rect)
注意下,這里不要設(shè)置子彈的初始位置,因?yàn)樽訌椀某跏嘉恢檬且陀⑿垡黄鹋?/strong>
- 2.設(shè)置子彈的定時(shí)器
# 子彈常量
HERO_FIRE = pygame.USEREVENT+1
# 5. 發(fā)射子彈的定時(shí)器調(diào)用
pygame.time.set_timer(HERO_FIRE,500)
elif event.type == HERO_FIRE:
self.hero_sprite.fire()
考慮到子彈是要和英雄一起弄的,我們把創(chuàng)建子彈精靈和精靈組放到英雄類中去
- 在英雄的類初始化方法里設(shè)置子彈精靈組
class Hero(Game_Sprite):
# 繼承父類,設(shè)置imgae和speed
def __init__(self):
super().__init__('./images/me1.png',0)
# 確定好英雄的初始位置
self.rect.centerx = SCREEN_RECT.centerx
self.rect.bottom = SCREEN_RECT.bottom-120
# 創(chuàng)建子彈精靈組
self.bullets = pygame.sprite.Group()
- 4 .開始設(shè)置在英雄類里設(shè)置fire()方法
elif event.type == HERO_FIRE:
self.hero_sprite.fire()
def fire(self):
print('發(fā)射子彈...')
for i in range(3):
# 創(chuàng)建子彈精靈
bullet = Bullet()
# 設(shè)置子彈的初始位置
bullet.rect.bottom = self.rect.y- i*20
bullet.rect.centerx = self.rect.centerx
# 設(shè)置子彈的精靈組
self.bullets.add(bullet)
- 5 .開始將子彈精靈組放到繪制圖像的方法里
# 子彈的繪制
self.hero_sprite.bullets.update()
self.hero_sprite.bullets.draw(self.screen)
呈現(xiàn)的效果為

image.png
12.開始碰撞檢測(cè)
def __check_collide(self):
# 子彈碰到飛機(jī)
pygame.sprite.groupcollide(self.hero_sprite.bullets,self.enemy_group,True,True)
# 敵機(jī)撞毀飛機(jī)
enemies = pygame.sprite.spritecollide(self.hero_sprite, self.enemy_group, True)
# 判斷列表是否有內(nèi)容
if len(enemies) > 0:
# 讓英雄犧牲
self.hero_sprite.kill()
# 結(jié)束游戲
PlaneGmae.__game_over()
shift +f10

image.png
碰撞的基礎(chǔ)知識(shí)

image.png

image.png


