今天是2月21日,我開始去跟著書本去寫一個python小游戲,沒想到一個小游戲,我每天大概看兩個小時左右,沒想到我寫到了今天,
沒想到一個小游戲,對我來說資訊量竟然這么多
飛機大戰外星人
- 前言
- 飛機大戰外星人的歷程
- 最終代碼(五個模塊)
- 飛機大戰主程式模塊[alien_invasion]
- 飛機大戰子彈模塊[bullet]
- 飛船模塊[ship]
- 游戲狀態模塊[game_stats]
- 外星人模塊[alien]
- 游戲整體設定模塊[settings]
- 專案源代碼
- 最后一點點想說的
前言
我寫的這個游戲主要是想對于我學習面向物件編程的一種復習和知識再現,里面主要是,類(類方法,類屬性,多型)的使用,如果對面向編程比較模糊不如試著去分析一下代碼,飛機大戰外星人的歷程過于長,大部分都是我個人的總結和感悟,可以不看,直接點擊上方藍色字體(代碼)即可傳送到最終代碼處進行分析代碼!
這是我第二篇文章,非常非常感謝我博客第一篇文章《大一的第一篇文章》中各位前輩的支持






也許沒有他們的支持,我可能沒有堅持去寫博客的動力!我真的很謝謝你們,





還有這些前輩的建議,正是因為有你們的建議,我才能成長,CSDN里的氛圍真的很好,是一個很好的學習分享平臺!
3月2日補充
截止今天


謝謝大家的支持,有你們的支持,堅定了我要堅持下去的理由,真的很謝謝大家!
飛機大戰外星人的歷程
首先學完面向物件編程后,我和大部分剛學完面向物件編程的一樣,對于面向物件編程有點懵,這玩意兒是在是有點抽象,在程式中就行上帝一樣去創造一類東西,就比如說女媧造人,我們寫程式就像女媧在造人一樣,去創造 人這一類東西,人就是一類東西的總稱,人有眼睛和鼻子,這就是人的屬性,人會生火,人會制造工具,那么生火和制造工具不就是類的方法,我目前來說是這么淺顯的理解,如果哪里有錯誤或者不足歡迎大佬前輩斧正,非常感謝,
正是因為我學習的時候理解的比較淺顯,再加上我正好看到了這個專案,所以我就跟著書本的思路去寫這個游戲代碼,帶著疑問去專案當中,去進行一個知識的復現,
剛一開始就遇到了困難 ,我因為pip沒有更新一直在轉圈
,所以一直匯入不了pygame這個庫,又沒有發現問題的所在,因為pycharm是一個比較成熟的軟體,所以問題出在我本身
如果你的pycharm沒有出現紅框這個版本號,可能的原因是pip需要更新了,更新了就可以加入庫了,
解決好問題后我開始跟著代碼去撰寫程式,因為pycharm自動補寫功能過于強大,有一些縮進總是過了或忘了,這里建議剛學語法的時候先別用一寫集成編譯軟體,黑視窗命令列python就好,
——————————————————分割線——————————————————
2.28日
因為最近是開學季,明天要去送朋友去車站,因為我是河北學生,開學延期了,3月1號要開始網課生活,所以從今天以后可能寫不了太多

已經從飛機的實體的創建到飛機的武裝了,我已經把我的飛機裝上了子彈,但是為了外星人的公平和建議玩家有效攻擊,限制了子彈為3發子彈,


先把第一步代碼分享一下,這是游戲的運行代碼
import pygame
import sys
from settings import Settings
from ship import Ship
from bullet import Bullet
class AlienInvasion(object):
'''管理游戲資源和行為的類'''
def __init__(self):
'''初始化游戲并創建游戲資源'''
pygame.init()
self.settings = Settings()
# 設定背景色
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption('Alin Invasion')
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
def run_game(self):
'''開始游戲的主回圈'''
while True:
# 監視鍵盤和滑鼠事件
self._check_events()
self._update_bullets()
self.bullets.update()
self._updata_screen()
# 每次回圈時都重繪螢屏
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
# 讓最近繪制的螢屏可見
pygame.display.flip()
def _check_events(self):
'''回應按鍵和滑鼠事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
elif event.type == pygame.KEYUP:
self._check_keyup_events(event)
def _updata_screen(self):
'''更新螢屏上的影像,并切換到新螢屏'''
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
pygame.display.flip()
def _fire_bullet(self):
'''創建一顆子彈,并將其加入編組bullets中'''
if len(self.bullets) < self.settings.bullet_allowed:
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _check_keydown_events(self,event):
'''回應按鍵'''
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
self.ship.moving_left = True
# 按q關閉界面
elif event.key == pygame.K_q:
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
def _check_keyup_events(self,event):
'''回應松開'''
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
def _update_bullets(self):
'''更新的子彈位置并洗掉消失的子彈'''
# 更新子彈位置
self.ship.update()
# 洗掉消失的子彈
for bullet in self.bullets.copy():
if bullet.rect.bottom <= 0:
self.bullets.remove(bullet)
if __name__ == '__main__':
# 創建實體并運行游戲
ai = AlienInvasion()
ai.run_game()
下面這個是游戲的設定代碼,其中的方法名字定義顧名思義,英語有點硬傷的可以有道翻譯一下
class Settings():
'''存盤《外星人入侵》所有設定的類'''
def __init__(self):
'''初始化游戲的設定'''
# 螢屏設定
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230,230,230)
# 飛船設定
self.ship_speed = 1.5
# 子彈設定
self.bullet_speed = 1.0
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60,60,60)
#allowed 允許 允許子彈發射的數目
self.bullet_allowed = 3
這個下面的代碼是飛船的設定,可以根據自己喜好改變飛船的繪制
import pygame
class Ship():
'''管理飛船的類'''
def __init__(self,ai_game):
'''初始化飛船并設定其初始位置'''
self.screen = ai_game.screen
self.settings = ai_game.settings
self.screen_rect = ai_game.screen.get_rect()
# 加載飛船影像并獲取其外接矩形
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# 對于每艘新飛船,都將其放在螢屏底部中央
self.rect.midbottom = self.screen_rect.midbottom
# 在飛船的屬性x中存小數值
self.x = float(self.rect.x)
# 移動標志
self.moving_right = False
self.moving_left = False
def update(self):
'''根據移動標志調整飛船的位置'''
# 更新飛船而不是rect物件的x值
if self.moving_right and self.rect.right <self.screen_rect.right:
self.x += self.settings.ship_speed
if self.moving_left and self.rect.left > 0:
self.x -= self.settings.ship_speed
# 根據self.x更新rect物件
self.rect.x = self.x
def blitme(self):
'''在指定位置繪制飛船'''
self.screen.blit(self.image,self.rect)
這段代碼是飛船影像的檔案,可以根據自己喜好改變飛船的樣子

接下來就是子彈的繪制代碼
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
'''管理所有發射的子彈'''
def __init__(self,ai_game):
# 在飛船當前位置創建一個子彈物件
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
self.color = self.settings.bullet_color
# 在(0,0)處創建一個表示字典的矩形,再設定正確的位置
self.rect = pygame.Rect(0,0,self.settings.bullet_width,
self.settings.bullet_height)
self.rect.midtop = ai_game.ship.rect.midtop
# 存盤用小數表示的子彈位置
self.y = float(self.rect.y)
def update(self):
'''向上移動子彈'''
# 更新表示子彈位置的小數值
self.y -= self.settings.bullet_speed
# 更新表示子彈的rect的位置
self.rect.y = self.y
def draw_bullet(self):
'''在螢屏上繪制子彈'''
pygame.draw.rect(self.screen,self.color,self.rect)
截止到這段代碼,你寫完之后就可以把飛船和發射子彈的行為做出來,
3.1

成功吧外星人創建出來了
下一步就是把外星人寫出來
截止2021年3月3日23:30分
我終于吧基本配置完畢,合張影留個紀念吧!!!

最終代碼(五個模塊)
飛機大戰主程式模塊[alien_invasion]
import pygame
import sys
from time import sleep
import alien
from settings import Settings
from game_stats import GameStats
from ship import Ship
from bullet import Bullet
from alien import Alien
class AlienInvasion(object):
'''管理游戲資源和行為的類'''
def __init__(self):
'''初始化游戲并創建游戲資源'''
pygame.init()
self.settings = Settings()
# 設定背景色
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption('Alin Invasion')
# 創建一個用于存盤游戲統計資訊的實體
self.stats = GameStats(self)
self.ship = Ship(self)
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
self._create_fleet()
def run_game(self):
'''開始游戲的主回圈'''
while True:
# 監視鍵盤和滑鼠事件
self._check_events()
if self.stats.game_active:
self.ship.update()
self._update_bullets()
self._update_aliens()
self.bullets.update()
# 每次回圈時都重繪螢屏
# self.screen.fill(self.settings.bg_color)
self.ship.blitme()
# 讓最近繪制的螢屏可見
pygame.display.flip()
self._update_screen()
def _check_events(self):
'''回應按鍵和滑鼠事件'''
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
self._check_keydown_events(event)
elif event.type == pygame.KEYUP:
self._check_keyup_events(event)
def _update_screen(self):
'''更新螢屏上的影像,并切換到新螢屏'''
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
self.aliens.draw(self.screen)
pygame.display.flip()
def _fire_bullet(self):
'''創建一顆子彈,并將其加入編組bullets中'''
if len(self.bullets) < self.settings.bullet_allowed:
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _check_keydown_events(self, event):
'''回應按鍵'''
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
self.ship.moving_left = True
# 按q關閉界面
elif event.key == pygame.K_q:
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
def _check_keyup_events(self, event):
'''回應松開'''
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
def _update_bullets(self):
'''更新的子彈位置并洗掉消失的子彈'''
# 更新子彈位置
self.ship.update()
# 洗掉消失的子彈
for bullet in self.bullets.copy():
if bullet.rect.bottom <= 0:
self.bullets.remove(bullet)
self._check_bullet_allien_collisions()
def _check_bullet_allien_collisions(self):
'''回應子彈和外星人碰撞'''
# 洗掉發生碰撞的子彈和外星人
collisions = pygame.sprite.groupcollide(
self.bullets, self.aliens, True, True)
if not self.aliens:
# 洗掉現有的子彈并新建一群外星人
self.bullets.empty()
self._create_fleet()
def _create_fleet(self):
'''創建外星人群'''
# 創建一個外星人
# 創建一個外星人并計算一行可容納多少外星人
# 外星人間距為外星人寬度
alien = Alien(self)
alien_width, alien_height = alien.rect.size
alien_width = alien.rect.width
available_space_x = self.settings.screen_width - (2 * alien_width)
number_aliens_x = available_space_x // (2 * alien_width)
# 計算螢屏可容納多少外星人
ship_height = self.ship.rect.height
available_space_y = (self.settings.screen_height -
(3 * alien_height) - ship_height)
number_rows = available_space_y // (2 * alien_height)
# 創建外星人群
for row_number in range(number_rows):
# 創建第一行外星人
for alien_number in range(number_aliens_x):
# 創建一個外星人并將其加入當前行
self._create_alien(alien_number, row_number)
def _create_alien(self, alien_number, row_number):
'''創建一個外星人并將其放在當前行'''
alien = Alien(self)
alien_width, alien_heidth = alien.rect.size
alien_width = alien.rect.width
alien.x = alien_width + 2 * alien_width * alien_number
alien.rect.x = alien.x
alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
self.aliens.add(alien)
def _update_aliens(self):
'''更新外星人群中所有外星人的位置'''
self.aliens.update()
'''檢查是否有外星人位于螢屏邊緣并更新整群外星人的位置'''
self._check_fleet_edges()
# 檢測外星人和飛船之間的碰撞
if pygame.sprite.spritecollideany(self.ship, self.aliens):
self._ship_hit()
# 檢查是否有外星人到達了螢屏底端
self._check_aliens_bottom()
def _check_fleet_edges(self):
'''有外星人到達邊緣時采取回應措施'''
for alien in self.aliens.sprites():
if alien.check_edges():
self._change_fleet_direction()
break
def _change_fleet_direction(self):
'''將整群外星人下移,并改變它們的方向'''
for alien in self.aliens.sprites():
alien.rect.y += self.settings.fleet_drop_speed
self.settings.fleet_direction *= -1
def _ship_hit(self):
'''回應飛船被外星人撞到'''
# 將ship_left減1
if self.stats.ship_left > 0:
self.stats.ship_left -= 1
# 清空余下的外星人和子彈
self.aliens.empty()
self.bullets.empty()
# 創建一群新的外星人,并將飛船放到螢屏底端或中央
self._create_fleet()
self.ship.center_ship()
# 暫停
sleep(0.5)
else:
self.stats.game_active = False
def _check_aliens_bottom(self):
'''檢查是否有外星人到達了螢屏底端'''
screen_rect = self.screen.get_rect()
for alien in self.aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# 像飛船被撞到一樣處理
self._ship_hit()
break
if __name__ == '__main__':
# 創建實體并運行游戲
ai = AlienInvasion()
ai.run_game()
飛機大戰子彈模塊[bullet]
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
'''管理所有發射的子彈'''
def __init__(self, ai_game):
# 在飛船當前位置創建一個子彈物件
super().__init__()
self.screen = ai_game.screen
self.settings = ai_game.settings
self.color = self.settings.bullet_color
# 在(0,0)處創建一個表示字典的矩形,再設定正確的位置
self.rect = pygame.Rect(0, 0, self.settings.bullet_width,
self.settings.bullet_height)
self.rect.midtop = ai_game.ship.rect.midtop
# 存盤用小數表示的子彈位置
self.y = float(self.rect.y)
def update(self):
'''向上移動子彈'''
# 更新表示子彈位置的小數值
self.y -= self.settings.bullet_speed
# 更新表示子彈的rect的位置
self.rect.y = self.y
def draw_bullet(self):
'''在螢屏上繪制子彈'''
pygame.draw.rect(self.screen, self.color, self.rect)
飛船模塊[ship]
import pygame
class Ship():
'''管理飛船的類'''
def __init__(self,ai_game):
'''初始化飛船并設定其初始位置'''
self.screen = ai_game.screen
self.settings = ai_game.settings
self.screen_rect = ai_game.screen.get_rect()
# 加載飛船影像并獲取其外接矩形
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# 對于每艘新飛船,都將其放在螢屏底部中央
self.rect.midbottom = self.screen_rect.midbottom
# 在飛船的屬性x中存小數值
self.x = float(self.rect.x)
# 移動標志
self.moving_right = False
self.moving_left = False
def update(self):
'''根據移動標志調整飛船的位置'''
# 更新飛船而不是rect物件的x值
if self.moving_right and self.rect.right <self.screen_rect.right:
self.x += self.settings.ship_speed
if self.moving_left and self.rect.left > 0:
self.x -= self.settings.ship_speed
# 根據self.x更新rect物件
self.rect.x = self.x
def blitme(self):
'''在指定位置繪制飛船'''
self.screen.blit(self.image,self.rect)
def center_ship(self):
'''讓飛船在螢屏底端居中'''
self.rect.midbottom = self.screen_rect.midbottom
self.x = float(self.rect.x)
游戲狀態模塊[game_stats]
class GameStats:
'''跟蹤游戲的統計資訊'''
def __init__(self, ai_game):
'''初始化統計資訊'''
self.settings = ai_game.settings
self.reset_stats()
# 游戲剛啟動處于活動狀態
self.game_active = True
def reset_stats(self):
'''初始化在游戲運行期間可能變化的統計資訊'''
self.ship_left = self.settings.ship_limit
外星人模塊[alien]
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
'''表示外星人的類'''
def __init__(self, ai_game):
'''初始化外星人并設定起始位置'''
super().__init__()
self.settings = ai_game.settings
self.screen = ai_game.screen
# 加載外星人影像并設定其screen屬性
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# 每個外星人最初都在螢屏的左上角附近
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# 存盤外星人的精準水平位置
self.x = float(self.rect.x)
def update(self):
'''向左或右移動外星人'''
self.x += (self.settings.alien_speed*
self.settings.fleet_direction)
self.rect.x = self.x
def check_edges(self):
'''如果外星人位于螢屏邊緣,就回傳Ture'''
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right or self.rect.left < 0:
return True
游戲整體設定模塊[settings]
class Settings():
'''存盤《外星人入侵》所有設定的類'''
def __init__(self):
'''初始化游戲的設定'''
# 螢屏設定
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
# 飛船設定
self.ship_speed = 1.5
self.ship_limit = 3
# 子彈設定
self.bullet_speed = 1.5
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60, 60, 60)
# allowed 允許 允許子彈發射的數目
self.bullet_allowed = 3
# 外星人設定
self.alien_speed = 0.5
self.fleet_drop_speed = 10
# fleet_direction 為1表示向右移,為-1表示向左移
self.fleet_direction = 1
專案源代碼
文章過長,需要專案源代碼的,我已經打包好了,直接下載即可
百度云:
鏈接:https://pan.baidu.com/s/1iRRaUhWOj1321XRrTbp4VQ
提取碼:0oo8
復制這段內容后打開百度網盤手機App,操作更方便哦
最后一點點想說的
寫了這么多,最后真的是寫不動了,我剛開始寫這篇文章還想著最后說點什么總結一下,但是真的到這天了,我卻一點也寫不動了,我做這個專案對我來說真的很辛苦,但是提升也很大,我發表出來記錄一下自己的成長程序!
如果您覺得我寫的不錯(就算寫的不好,也挺辛苦的),麻煩您動動小手,點贊評論關注,您的支持就我堅持寫下去,堅持記錄自己成長的最大動力,謝謝您的支持,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/266381.html
標籤:python
