python项目1:外星人大战

    科技2022-08-08  113

    此项目仅为个人笔记,不适合学习…

    学习自《python编程从入门到实践》 学习目的:加深对python多文件编程、重构以及类使用的理解,而不是pygame

    1. 初始化窗口
    /settings class Settings(): """存储所有设置""" def __init__ (self): #屏幕设置 self.screen_width = 1200 self.screen_height = 800 self.bg_color = (255,250,250) /alien_invasion.py import sys, pygame from settings import Settings def run_game(): #初始化游戏并创建屏幕对象(display) pygame.init() ai_settings = Settings() #获取设置的数据 屏幕 飞船 UFO 子弹呀 screen = pygame.display.set_mode((ai_settings.screen_width,ai_settings.screen_height)) pygame.display.set_caption("Alien Invasion (Make by Jeff)") settings中设置窗口的width和height,实际大小可以根据自己的屏幕大小调整(不要吝惜运行程序看看大小如何)color用的是RGB配色, 可以在RGB配色表选择喜欢的颜色sys库用来退出游戏,pygame有开发所需功能pygame.init()初始化背景设置,然后ai_settings获取Settings中的所有数据(类转移术??),screen为窗口对象,pygame,display.set_mode(宽,高)创建窗口.set_caption标题

    更多display的功能查询:display文档

    //更新屏幕(游戏运行时就是屏幕不断更新,都是些绘制函数)

    def update_screen(ai_settings,screen,ship,alien,bullets): #每次循环都重新绘制屏幕 screen.fill(ai_settings.bg_color) #填充色 for bullet in bullets.sprites(): bullet.draw_bullet() ship.blitme() #绘制飞船 alien.draw(screen) #alien.blitme() #让最近绘制的屏幕可见 pygame.display.flip()
    2.飞船对象
    /settings.py #飞船设置 self.ship_speed_factor = 1.5 self.ship_limit = 3 /ship.py import pygame class Ship(): #screen 告诉程序飞船要画在什么地方 def __init__(self,ai_settings,screen): self.screen = screen self.ai_settings = ai_settings #加载飞船图像并获取外接矩形 self.image = pygame.image.load('images/spaceship.bmp') self.rect = self.image.get_rect() #飞船的矩形or大小 self.screen_rect = screen.get_rect() #将每艘飞船放在屏幕底部中间 self.rect.centerx = self.screen_rect.centerx self.rect.bottom = self.screen_rect.bottom #在飞船属性center中存储小数值 self.center = float(self.rect.centerx) self.bottom = float(self.rect.bottom) #移动标志 self.moving_right = False self.moving_left = False self.moving_back = False self.moving_front = False def update(self): #更新飞船的center值而不是rect if self.moving_right and self.rect.right < self.screen_rect.right: self.center += self.ai_settings.ship_speed_factor elif self.moving_left and self.rect.left > 0 : self.center -= self.ai_settings.ship_speed_factor elif self.moving_front and self.rect.top > 0 : self.bottom -= self.ai_settings.ship_speed_factor elif self.moving_back and self.rect.bottom < self.screen_rect.bottom: self.bottom += self.ai_settings.ship_speed_factor #根据center更改rect对象 self.rect.centerx = self.center self.rect.bottom = self.bottom def blitme(self): #在指定位置绘制飞船 blit self.screen.blit(self.image,self.rect) def center_ship(self): self.center = self.screen_rect.centerx pygame.image.load()返回一个飞船的表面然后存储到self.image中。get_rect()获得相应表面的属性rect,python可以像处理矩形一样处理游戏元素。rect的相关属性:center\centerx\centery(中心坐标)\x\y\bottom\top\left\rightpygame中,(0,0)位于左上角,然后向下向右扩展首先得到飞船图像的属性,然后得到屏幕属性,初始化飞船位置:在屏幕下方、中间(bottom and centerx),默认类型为int,所以float强制转换存储到临时变量中(因为设置飞船speed是1.5)然后判断飞船是否越界,根据上面说的坐标系的表示方式,以及移动标志 blitme函数将根据self.rect指定位置绘制图像(screen的底部和中间)

    然后是键盘响应:

    /game_function.py def check_keydown_events(event,ai_settings,screen,ship,bullets): if event.key == pygame.K_RIGHT: #飞船向👉移动 ship.moving_right =True elif event.key == pygame.K_LEFT: ship.moving_left = True elif event.key == pygame.K_UP: ship.moving_front = True elif event.key == pygame.K_DOWN: ship.moving_back = True elif event.key == pygame.K_SPACE: if len(bullets) <ai_settings.bullet_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 = False elif event.key == pygame.K_LEFT: ship.moving_left = False elif event.key == pygame.K_UP: ship.moving_front = False elif event.key == pygame.K_DOWN: ship.moving_back = False def check_events(ai_settings,screen,ship,bullets): #监控鼠标和键盘事件 for event in pygame.event.get(): if event.type == 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) 首先要检查事件check_event(ai_settings,screen,ship,bullets).用一个循环来检查每一个事件,event.get()获取事件,event.type是事件类型,如果QUIT,则sys.exit(),如果KEYDOWN,则跳转到函数check_keydown_events,如果是KEYUP,则跳转到check_keyup_events然后KEYDOWN和KEYUP设置移动标志,移动标志对应着ship.py中的update函数飞船的移动通过改变center和bottom两个变量来实现,而center和bottom其实就是飞船图像的centerx和bottom。

    //alien_invasion.py中创建实例

    /alien_invasion.py #创建外星人实例 aliens = Alien(ai_settings,screen) ... while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update()
    3.子弹

    子弹不另外加载图片,自己绘制

    /settings.py ##bullet set self.bullet_speed_factor = 1 self.bullet_width = 100 self.bullet_height = 15 self.bullet_color = (0,0,0) self.bullet_allowed = 3 /buttets.py import pygame from pygame.sprite import Sprite class Bullet(Sprite): def __init__(self,ai_settings,screen,ship): super().__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.centerx self.rect.top = ship.rect.top #存储小数点子弹位置 self.y = float(self.rect.y) self.color = ai_settings.bullet_color self.speed_factor = ai_settings.bullet_speed_factor def update(self): #向上移动子弹 #更新表示子弹位置的小数 self.y -= self.speed_factor #更新表示子弹位置的rect self.rect.y = self.y def draw_bullet(self): #在屏幕上绘制子弹 pygame.draw.rect(self.screen,self.color,self.rect) /game_function.py elif event.key == pygame.K_SPACE: if len(bullets) <ai_settings.bullet_allowed: new_bullet = Bullet(ai_settings,screen,ship) bullets.add(new_bullet) /alien_invasion.py #创建子弹编组 bullets = Group() ... while True: gf.check_events(ai_settings,screen,ship,bullets) if stats.game_active: ship.update() bullets.update() gf.update_bullets(ai_settings,screen,ship,aliens,bullets) 首先设置子弹的帅气模样,super().__init__是初始化父类,然后绘制子弹矩形,然后设置位置,颜色和移动速度。update函数更新子弹每次移动的位置,draw_bullet()在屏幕上绘制子弹主程序循环检查键盘鼠标事件,然后如果是KEYSPACE,则判断子弹数目是否超过三个,如果不是,则创建新子弹对象,然后add到编组中,然后update子弹位置,然后刷新屏幕。
    4. 外星人
    /settings.py #alien self.alien_speed_factor = 1 self.fleet_drop_speed = 10 # -1 表示右移, 1表示左移 self.fleet_direction = 1 /aliens.py import pygame from pygame.sprite import Sprite class Alien(Sprite): def __init__(self,ai_settings,screen): super().__init__() self.screen = screen self.ai_settings = ai_settings ##加载外星人图像 self.image = pygame.image.load('images/ufo.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.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction) self.rect.x = self.x def check_edges(self): screen_rect = self.screen.get_rect() if self.rect.right >= screen_rect.right: return True elif self.rect.left <= 0: return True def blitme(self): #在指定位置绘制外星人 self.screen.blit(self.image,self.rect) /game_function.py #每一行的aliens数目 def get_number_aliens_x(ai_settings,alien_width): available_space_x = ai_settings.screen_width - 2* alien_width number_alien_x = int(available_space_x / (2 * alien_width)) return number_alien_x #可以同时存在几行 def 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_rows #创建单个外星人,加入到编组 def create_alien(ai_settings,screen,aliens,alien_number,row_number): alien = Alien(ai_settings,screen) 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 aliens.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 update_aliens(ai_settings,stats,screen,ship,aliens,bullets): check_fleet_edges(ai_settings,aliens) #检查是否到边缘 aliens.update() check_alien_bottom(ai_settings,stats,screen,ship,aliens,bullets) #检查碰撞(接收编组和飞船) if pygame.sprite.spritecollideany(ship,aliens): ship_hit(ai_settings,stats,screen,ship,aliens,bullets) def check_fleet_edges(ai_settings,aliens): for alien in aliens.sprites(): if alien.check_edges(): change_fleet_direction(ai_settings,aliens) break def change_fleet_direction(ai_settings,aliens): for alien in aliens.sprites(): alien.rect.y += ai_settings.fleet_drop_speed ai_settings.fleet_direction *= -1 def check_alien_bottom(ai_settings,stats,screen,ship,aliens,bullets): screen_rect = screen.get_rect() for alien in aliens.sprites(): if alien.rect.bottom >= screen_rect.bottom: ship_hit(ai_settings,stats,screen,ship,aliens,bullets) break /子弹与外星人撞击 def update_bullets(ai_settings,screen,ship,aliens,bullets): for bullet in bullets.copy(): if bullet.rect.bottom <= 0: bullets.remove(bullet) check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets) def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets): collisions = pygame.sprite.groupcollide(bullets,aliens,True,True) if len(aliens) == 0: bullets.empty() create_fleet(ai_settings,screen,ship,aliens) #检查飞机和外星飞船碰撞 def ship_hit(ai_settings,stats,screen,ship,aliens,bullets): stats.ship_left -= 1 if stats.ship_left <=0: stats.game_active = False else: #清空 aliens.empty() bullets.empty() #创建新外星人群 create_fleet(ai_settings,screen,ship,aliens) ship.center_ship() #暂停 sleep(0.5)

    心得: 本项目是屏幕、飞船、子弹、UFO的联动 其中屏幕主要作用为:创建背景、刷新背景、给飞船子弹UFO的位置设置参考。 alien_invasion.py文件主要用于创建背景、创建实例以及循环事件(循环中检查事件、更新各元素以及刷新屏幕) settings.py用来存储元素的参数(初始化用以及速度) ship.py首先__init__()初始化飞船对象(图像,rect,移动标志),然后update更新飞船位置(如果需要的话),blitme绘制飞船 bullet.py也是如此:初始化、更新、绘制 aliens.py也是如此:初始化、更新、绘制以及检查是否到边界(这个也可以写在game_function中)

    game_function.py是主要功能的文件:有检查事件、更新屏幕(绘制所有)、更新 子弹(因为越过窗口后要消失,前面的更新只是移动的位置)、创建外星人群实例函数、外星人越过下界、碰到左右两边的更新函数、子弹外星人碰撞、飞船外星人碰撞

    Processed: 0.010, SQL: 8