游戲編程思維導圖
第一次做思維導圖,做的有點亂
解釋:跟著《python編程從入門到實踐》寫完游戲程序后,寫一下自己的心得體會。可以把這個游戲分為幾塊來理解。如果想要設計一款小游戲,第一是對游戲的屏幕進行設置,包括游戲屏幕的大小,背景顏色,背景音樂等(這本書里沒有加音樂,以后可以再加)。
設置好游戲屏幕后,第二是對游戲中的元素依次進行設置。首先是飛船,通過載入圖片把飛船畫在屏幕正下方并使其通過鍵盤上的左右鍵進行移動。
第三是子彈:設置一個大小相當的方塊,讓他初始位置位于初始飛船的頂部,并通過減少Y軸距離向屏幕上方移動,當按下空格鍵觸發子彈移動。(游戲屏幕的左上角位置是(0, 0))同時設置屏幕上同時出現子彈的最大數量,當子彈與外星人碰撞或飛出游戲屏幕外要把子彈刪掉。
第四是外星人:游戲是要設置一群外星人不斷往下移動,然后飛船射出子彈消滅外星人。所以,在設置外星人時,首先要計算游戲上方區域能容納多少外星人。通過先畫一個外星人,然后再畫一圈外星人來實現。畫完外星人后,使其初始按右移動,當碰到游戲右界面是向下移動,再向左移動。這時,游戲屏幕上可以顯示飛船左右自由移動,按下空格子彈飛出,一群外星人向下移動。
第五是設置游戲開始鍵:把游戲初始化設置成暫停,當按下開始鍵后開始玩游戲。
第六是實現碰撞檢測:外星人撞到飛船,子彈擊中外新人入和外星人碰到游戲界面底部
第七是得分系統:設置消滅外星人的分數,并設置得分顯示在屏幕上
第八是提升游戲難度:設置玩家每局有幾條命,提高子彈,外星人的移動速度,并把得分,最高分和等級顯示在屏幕上
對應函數模塊
# 《外星人入侵》主程序
import sys
import pygame
from pygame.sprite import Groupfrom settings import Settings
from ship import Ship
import game_functions as gf
from alien import Alien
from game_stats import GameStats
from button import Button
from scoreboard import ScoreBoarddef run_game():# 初始化pygame pygame.init()# 初始化游戲屏幕、游戲名設置,屏幕大小設置時要加括號ai_settings = Settings() # 初始設置類的實例化screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))pygame.display.set_caption("Alien Invasion")# 創建一艘飛船、一個子彈編組和一個外星人組ship = Ship(ai_settings, screen)bullets = Group()aliens = Group()# 創建外星人群gf.create_fleet(ai_settings, screen, ship, aliens)# 創建Play按鈕play_button = Button(ai_settings, screen, "Play")# 創建一個用于存儲游戲統計信息的實例,并創建記分牌stats = GameStats(ai_settings)sb = ScoreBoard(ai_settings, screen, stats)# 開始游戲的主循環while True:# 監視鍵盤和鼠標事件gf.check_events(ai_settings, screen, stats, sb, play_button,ship, aliens, bullets)if stats.game_active:# 更新飛機移動ship.update()# 更新子彈gf.update_bullets(ai_settings, screen, stats, sb, ship,aliens,bullets)# 更新外星人gf.update_aliens(ai_settings, screen, stats, sb, ship,aliens, bullets)# 填充屏幕背景,飛機,并進行刷新gf.update_screen(ai_settings, screen, stats, sb, ship,aliens, bullets, play_button)run_game()
# 創建設置類
class Settings():'''存儲《外星人入侵》的所有初始設置的參數'''def __init__(self):'''初始化游戲的設置''''''初始化游戲的靜態設置'''# 屏幕設置self.screen_width = 1200self.screen_height = 800self.bg_color = (230, 230, 230)# 設置游戲命數,這樣已經是有三條命self.ship_limit = 2# 設置飛船移動速度self.ship_speed_factor = 1.5# 子彈設置self.bullet_width = 3self.bullet_height = 15self.bullet_color = 60, 60, 60# 屏幕上可以同時出現多少顆子彈self.bullets_allowed = 6# 外星人設置self.fleet_drop_speed = 10# 以什么樣的速度加快游戲節奏self.speedup_scale = 1.1# 提高外星人分值self.score_scale = 1.5self.initialize_dynamic_settings()def initialize_dynamic_settings(self):'''初始化隨游戲進行而變化的設置'''self.ship_speed_factor = 1.5self.bullet_speed_factor = 3self.alien_speed_factor = 1# 消滅飛船得分self.alien_points = 50# fleet_direction為1表示向右移,-1表示向左移self.fleet_direction = 1def increase_speed(self):'''提高速度和外星人分值設置'''self.ship_speed_factor *= self.speedup_scaleself.bullet_speed_factor *= self.speedup_scaleself.alien_speed_factor *= self.speedup_scaleself.alien_points = int(self.alien_points * self.score_scale)
# 創建ship類,管理飛船的大部分行為
import pygame
from pygame.sprite import Spriteclass Ship(Sprite):def __init__(self, ai_settings, screen):'''初始化飛船并設置其初始位置'''super(Ship, self).__init__()self.screen = screenself.ai_settings = ai_settings# 加載飛船圖像并獲取其外接矩形self.screen_rect = screen.get_rect() # 獲得屏幕大小參數self.image = pygame.image.load(r'images/ship.bmp')self.rect = self.image.get_rect() # 獲得飛船圖像大小參數# 將每艘新飛船放在屏幕底部中央self.rect.centerx = self.screen_rect.centerxself.rect.bottom = self.screen_rect.bottom# 在飛船的屬性center中存儲小數值self.center = float(self.rect.centerx) # ????# 移動標志,初始不可以移動self.moving_right = Falseself.moving_left = Falsedef center_ship(self):'''讓飛船在屏幕上居中'''self.center = self.screen_rect.centerx def update(self):'''根據移動標志調整飛船的位置,使飛船可以移動'''# 更新飛船的center值,而不是rect,并且考慮飛船移動的范圍if self.moving_right and self.rect.right < self.screen_rect.right:self.center += self.ai_settings.ship_speed_factorif self.moving_left and self.rect.left > 0:self.center -= self.ai_settings.ship_speed_factor# 根據self.center更新rect對象self.rect.centerx = self.centerdef blitme(self):'''在指定位置繪制飛船'''self.screen.blit(self.image, self.rect)
# 創建子彈
import pygame
from pygame.sprite import Spriteclass Bullet(Sprite):'''一個對飛船發射的子彈進行管理的類'''def __init__(self, ai_settings, screen, ship):'''在飛船所處的位置創建一個子彈對象'''super(Bullet, self).__init__()self.screen = screen# 在(0, 0)處創建一個表示子彈的矩形,再設置正確的位置self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,ai_settings.bullet_height)self.rect.centerx = ship.rect.centerxself.rect.top = ship.rect.top# 存儲用小數表示的子彈位置self.y = float(self.rect.y)self.color = ai_settings.bullet_colorself.speed_factor = ai_settings.bullet_speed_factordef update(self):'''向上移動子彈'''# 更新表示子彈位置的小數值self.y -= self.speed_factor# 更新表示子彈的rect的位置self.rect.y = self.ydef draw_bullet(self):"""畫子彈"""pygame.draw.rect(self.screen, self.color, self.rect)
# 創建外星人
import pygame
from pygame.sprite import Spriteclass Alien(Sprite):'''表示單個外星人的類'''def __init__(self, ai_settings, screen):'''初始化外星人并設置起始位置'''super(Alien, self).__init__()self.screen = screenself.ai_settings = ai_settings# 加載外星人圖像,并設置其rect屬性self.image = pygame.image.load('images/alien.bmp')self.rect = self.image.get_rect()# 每個外星人初始都在屏幕左上角附近self.rect.x = self.rect.widthself.rect.y = self.rect.height# 存儲外星人的準確位置self.x = float(self.rect.x)def update(self):'''向右移動外星人'''self.x += (self.ai_settings.alien_speed_factor *self.ai_settings.fleet_direction)self.rect.x = self.xdef check_edges(self):'''如果外星人位于屏幕邊緣,就返回True'''screen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return True # 用于分函數的判斷elif self.rect.left <= 0:return Truedef blitme(self):'''在指定位置繪制外星人'''self.screen.blit(self.image, self.rect)
# 創建游戲按鈕
import pygame.fontclass Button():def __init__(self, ai_settings, screen, msg):'''初始化按鈕的屬性'''self.screen = screenself.screen_rect = screen.get_rect()# 設置按鈕的尺寸和其他屬性self.width, self.height = 200, 50self.button_color = (0, 255, 0)self.text_color = (255, 255, 255)self.font = pygame.font.SysFont(None, 48)# 創建按鈕的rect對象,并使其居中self.rect = pygame.Rect(0, 0, self.width, self.height)self.rect.center = self.screen_rect.center# 按鈕的標簽只需創建一次self.prep_msg(msg)def prep_msg(self, msg):'''將msg渲染為圖像,并使其在按鈕上居中'''self.msg_image = self.font.render(msg, True, self.text_color,self.button_color)self.msg_image_rect = self.msg_image.get_rect()self.msg_image_rect.center = self.rect.centerdef draw_button(self):'''繪制一個用顏色填充的按鈕,在繪制文本'''self.screen.fill(self.button_color, self.rect)self.screen.blit(self.msg_image, self.msg_image_rect)
# 創建游戲的統計信息class GameStats():'''跟蹤游戲的統計信息'''def __init__(self, ai_settings):'''初始化統計信息'''self.ai_settings = ai_settingsself.reset_stats()# 讓游戲一開始處于非活躍狀態self.game_active = False# 在任何情況下都不應該重置最高得分self.high_score = 0def reset_stats(self):'''初始化在游戲運行期間可能變化的統計信息'''self.ships_left = self.ai_settings.ship_limitself.score = 0self.level = 1
# 在屏幕上顯示得分信息
import pygame.font
from pygame.sprite import Groupfrom ship import Shipclass ScoreBoard():'''顯示得分信息的類'''def __init__(self, ai_settings, screen, stats):'''初始化顯示得分涉及的屬性'''self.screen = screenself.screen_rect = screen.get_rect()self.ai_settings = ai_settingsself.stats = stats# 顯示得分信息時使用的字體設置self.text_color = (30, 30, 30)self.font = pygame.font.SysFont(None, 48)# 準備初始得分和最高得分、等級和游戲命數圖像self.prep_score()self.prep_high_score()self.prep_level()self.prep_ships()def prep_score(self):'''將得分轉換為一幅渲染的圖案'''rounded_score = round(self.stats.score, -1)# 將得分在千分位插入逗號score_str = "{:,}".format(rounded_score)self.score_image = self.font.render(score_str, True,self.text_color, self.ai_settings.bg_color)# 將得分放在屏幕右上角self.score_rect = self.score_image.get_rect()self.score_rect.right = self.screen_rect.right - 20self.score_rect.top = 20def prep_high_score(self):'''將最高得分轉換為渲染的圖案'''high_score = round(self.stats.high_score, -1)high_score_str = "{:,}".format(high_score)self.high_score_image = self.font.render(high_score_str, True,self.text_color, self.ai_settings.bg_color)# 將最高得分放在屏幕頂部中央self.high_score_rect = self.high_score_image.get_rect()self.high_score_rect.centerx = self.screen_rect.centerxself.high_score_rect.top = self.score_rect.topdef prep_level(self):'''將等級轉換為渲染的圖像'''self.level_image = self.font.render(str(self.stats.level),True, self.text_color, self.ai_settings.bg_color)#將等級放在得分下方self.level_rect = self.level_image.get_rect()self.level_rect.right = self.score_rect.rightself.level_rect.top = self.score_rect.bottom + 10def prep_ships(self):'''顯示還剩余多少艘飛船'''self.ships = Group()for ship_number in range(self.stats.ships_left):ship = Ship(self.ai_settings, self.screen)ship.rect.x = 10 + ship_number * ship.rect.widthship.rect.y = 10self.ships.add(ship)def show_score(self):'''在屏幕上顯示飛船和得分'''self.screen.blit(self.score_image, self.score_rect)self.screen.blit(self.high_score_image, self.high_score_rect)self.screen.blit(self.level_image, self.level_rect)# 繪制顯示命的飛船self.ships.draw(self.screen)
# 重構模塊:將一些函數代碼分離主函數,主函數簡易可觀察,分函數修改更方便
import sys
import pygame
from time import sleepfrom bullet import Bullet
from alien import Alien
from ship import Ship'''飛船移動,子彈發射'''def check_events(ai_settings, screen, stats, sb, play_button, ship,aliens, bullets):'''響應按鍵和鼠標事件'''for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit()elif event.type == pygame.KEYDOWN:check_keydown_events(event, ai_settings, screen, ship, bullets) elif event.type == pygame.KEYUP:check_keyup_events(event, ship)elif event.type == pygame.MOUSEBUTTONDOWN:mouse_x, mouse_y = pygame.mouse.get_pos()check_play_button(ai_settings, screen, stats, sb, play_button,ship, aliens, bullets, mouse_x, mouse_y)def check_keydown_events(event, ai_settings, screen, ship, bullets):'''對鍵盤操作做出反應'''if event.key == pygame.K_RIGHT:ship.moving_right = Trueelif event.key == pygame.K_LEFT:ship.moving_left = Trueelif event.key == pygame.K_SPACE:fire_bullet(ai_settings, screen, ship, bullets)elif event.key == pygame.K_q:pygame.quit()sys.exit()def fire_bullet(ai_settings, screen, ship, bullets):# 創建新子彈,并將其加入到編組bullets中# 如果還沒有到達限制,就發射一顆子彈if len(bullets) < ai_settings.bullets_allowed:new_bullet = Bullet(ai_settings, screen, ship)bullets.add(new_bullet)def check_keyup_events(event, ship):'''對松開鍵盤按鍵的反應'''if event.key == pygame.K_RIGHT:ship.moving_right = Falseelif event.key == pygame.K_LEFT:ship.moving_left = False'''外星人數量設置'''def get_number_aliens_x(ai_settings, alien_width):'''計算每行可容納多少外星人'''available_space_x = ai_settings.screen_width - 2 * alien_widthnumber_aliens_x = int(available_space_x / (2 * alien_width)) return number_aliens_xdef get_number_rows(ai_settings, ship_height, alien_height):'''計算屏幕可容納多少外星人'''available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)number_rows = int(available_space_y / (2 * alien_height))return number_rowsdef create_alien(ai_settings, screen, aliens, alien_number, row_number):'''創建一個外星人并將其放在當前行'''alien = Alien(ai_settings, screen)alien_width = alien.rect.widthalien.x = alien_width + 2 * alien_width * alien_numberalien.rect.x = alien.xalien.rect.y = alien.rect.height + 2 * alien.rect.height * row_numberaliens.add(alien) def create_fleet(ai_settings, screen, ship, aliens):'''創建外星人群'''# 創建一個外星人,并計算一行可容納多少個外星人alien = Alien(ai_settings, screen)number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)number_rows = get_number_rows(ai_settings, ship.rect.height,alien.rect.height)# 創建外星人群for row_number in range(number_rows):for alien_number in range(number_aliens_x):create_alien(ai_settings, screen, aliens, alien_number, row_number)'''外星人移動'''def check_fleet_edges(ai_settings, aliens):'''有外星人到達邊緣時采取相應措施'''for alien in aliens.sprites():if alien.check_edges():change_fleet_direction(ai_settings, aliens)breakdef change_fleet_direction(ai_settings, aliens):'''將整群外星人下移,并改變他們的方向'''for alien in aliens.sprites():alien.rect.y += ai_settings.fleet_drop_speedai_settings.fleet_direction *= -1'''碰撞檢測'''def ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets):'''響應被外星人撞到的飛船'''if stats.ships_left > 0:# 將ships_left減1stats.ships_left -= 1# 更新記分牌sb.prep_ships() else:stats.game_active = Falsepygame.mouse.set_visible(True)# 清空外星人列表和子彈列表aliens.empty()bullets.empty()# 創建一群新的外星人,并將飛船放到屏幕低端中央create_fleet(ai_settings, screen, ship, aliens)ship.center_ship()# 暫停sleep(1)def check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,aliens, bullets):'''響應子彈和外星人的碰撞'''# 刪除發生碰撞的子彈和外星人collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)if collisions:for aliens in collisions.values():stats.score += ai_settings.alien_points * len(aliens)sb.prep_score()check_high_score(stats, sb)if len(aliens) == 0:# 如果整群外星人被消滅,就提高一級bullets.empty()ai_settings.increase_speed()# 提高等級stats.level += 1sb.prep_level()create_fleet(ai_settings, screen, ship, aliens)def check_aliens_bottom(ai_settings, screen, stats, sb, ship, aliens, bullets):'''檢查是否有外星人到達了屏幕底端'''screen_rect = screen.get_rect()for alien in aliens.sprites():if alien.rect.bottom >= screen_rect.bottom:# 像飛船被撞到一樣進行處理ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets)# 只要有一個外星人到達底部就輸了,所有直接退出循環break'''更新屏幕信息'''def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):'''更新子彈的位置,并刪除已消失的子彈'''bullets.update()# 刪除屏幕外的子彈for bullet in bullets.copy():if bullet.rect.bottom <= 0:bullets.remove(bullet)check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship,aliens, bullets)def update_aliens(ai_settings, screen, stats, sb, ship, aliens, bullets):'''檢查是否有外星人位于屏幕邊緣,并更新整群外星人的位置'''check_fleet_edges(ai_settings, aliens)aliens.update()#檢測外星人和飛船之間的碰撞if pygame.sprite.spritecollideany(ship, aliens):ship_hit(ai_settings, screen, stats, sb, ship, aliens, bullets)# 檢查是否有外星人到達屏幕底端check_aliens_bottom(ai_settings, screen, stats, sb, ship,aliens, bullets) def check_high_score(stats, sb):'''檢查是否誕生新的最高得分'''if stats.score > stats.high_score:stats.high_score = stats.scoresb.prep_high_score()def check_play_button(ai_settings, screen, stats, sb, play_button,ship, aliens, bullets, mouse_x, mouse_y):'''在玩家點擊play按鈕時開始游戲'''botton_click = play_button.rect.collidepoint(mouse_x, mouse_y)if botton_click and not stats.game_active:# 重置游戲設置ai_settings.initialize_dynamic_settings()# 隱藏光標pygame.mouse.set_visible(False)#重置游戲統計信息stats.reset_stats()stats.game_active = True# 重置記分牌圖像sb.prep_score()sb.prep_level()sb.prep_ships()# 清空外星人和子彈列表aliens.empty()bullets.empty()# 創建一群新的外星人,并讓飛船居中create_fleet(ai_settings,screen, ship, aliens)ship.center_ship()def update_screen(ai_settings, screen, stats, sb, ship,aliens, bullets, play_button):'''更新屏幕上的圖像,并切換到新屏幕'''# 用設置的背景色填充窗口# 填充背景后再畫飛船,確保飛船在背景前面screen.fill(ai_settings.bg_color)# 在飛船和外星人后面重繪所有子彈for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()aliens.draw(screen)# 顯示得分sb.show_score()# 如果游戲處于非活躍狀態,就會繪制Play按鈕# 放在最后繪制,覆蓋在其他圖案上if not stats.game_active:play_button.draw_button()# 讓最近繪制的圖像屏幕上可見pygame.display.flip()
用到的圖片
總結
經過上面代碼的鍛煉,讓我對于寫游戲代碼有了一點小小的感悟。明白了在設置游戲時需要先把界面里的元素進行分割,每個部分去完成實現。就像上面這個項目,在編寫函數依次去實現不同功能:
寫代碼還是需要多練,有時候一個字符錯誤可能都要花很長時間去找,復制一遍代碼和自己手動輸入一遍代碼真的是很不一樣
強烈推薦typora編輯器,好用方便,很簡潔
下面是游戲視頻效果,不過鼠標聲音有點響
https://www.zhihu.com/video/1159858591287992320
總結
以上是生活随笔為你收集整理的外星人入侵 python 飞船位置_《python从入门到实践》项目一:外星人入侵的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。