1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Python项目实战学习 外星人入侵 创建外星人飞船并实现外星人动态移动效果

Python项目实战学习 外星人入侵 创建外星人飞船并实现外星人动态移动效果

时间:2020-04-03 16:14:43

相关推荐

Python项目实战学习 外星人入侵 创建外星人飞船并实现外星人动态移动效果

外星人入侵

本篇博客紧接上一篇博客:设置飞船发出子弹/Ace_bb/article/details/104845723

本篇博客实现在游戏窗口中添加动态的外星人飞船。

外星人飞船

飞船图片资源:链接:/s/1onui_yfopP2ko1SoqtZ6EQ

提取码:snnw

根据游戏屏幕的大小,添加一定行数和列数的飞船,占满屏幕的固定区域。飞船左右移动,左右移动一个周期后向下移动一格。如此循环,实现移动飞船的逼近效果。

实现步骤:

添加单个飞船根据屏幕添加多个飞船实现飞船左右移动效果实现飞船向下移动效果

创建Alien类

Alien类和Ship类相似,设置了外星人的基本属性,包括外星人图片,位置,大小,边距等。

import pygamefrom pygame.sprite import Spriteclass Alien(Sprite):# 表示单个外星人的类def __init__(self,ai_settings,screen):# 初始化外星人并设置其起始位置super(Alien,self).__init__()self.screen = screenself.ai_settings = ai_settings# 加载外星人图像,并设置其screen属性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 blitme(self):# 在指定位置绘制外星人self.screen.blit(self.image,self.rect)def update(self):# 向左或向右移动外星人self.x += (self.ai_settings.alien_speed_factor*self.ai_settings.fleet_direction)self.rect.x = self.xdef check_edges(self):# 如果外星人位于屏幕边缘,就返回Truescreen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <=0:return True

这是Alien类的完整代码,有更新外星人位置的函数和判断是否移动到边界的函数,暂且不用管。

接下来,在alien_invasion.py主文件中创建一个外星人实例。

核心代码:

# 创建一个外星人alien = Alien(ai_settings,screen)

gf.update_screen(ai_settings, screen, ship,aliens,bullets)

完整代码:

import sysimport pygamefrom setting import Settingsfrom pygame.sprite import Groupfrom ship import Shipimport game_functions as gffrom alien import Alienfrom game_stats import GamStatsdef run_game():# 初始化游戏并创建一个屏幕对象pygame.init() #初始化背景设置ai_settings = Settings()screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))#创建一个sceen窗口pygame.display.set_caption("Alien Invasion")# 创建一个用于存储游戏统计信息的实例stats = GamStats(ai_settings)#创建一艘飞船ship = Ship(ai_settings,screen)# 创建一个外星人alien = Alien(ai_settings,screen)#设置背景颜色bg_color = (230, 230, 230)# 创建一个用于存储子弹的编组,存储所有有效的子弹,# 管理发射出去的子弹bullets = Group()# 创建一个空编组,用于存储全部外星人aliens=Group()# 创建外星人群gf.create_fleet(ai_settings,screen,ship,aliens)#开始游戏的主循环#循环控制管理屏幕更新while True:gf.check_events(ai_settings,screen,ship,bullets)if stats.game_active:ship.update()# 更新子弹运行轨迹gf.update_bullets(ai_settings,screen,ship,aliens,bullets)gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置gf.update_screen(ai_settings, screen, ship,aliens,bullets)run_game()

这个完整代码也是整个项目的alien_invasion.py的完整代码。

然后在屏幕上显示外星人飞船

核心代码:

def update_screen(ai_settings, screen, ship,aliens,bullets):# 更新屏幕上的图像, 并切换新屏幕#每次循环都会重绘制屏幕screen.fill(ai_settings.bg_color) #只能有一个参数for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()aliens.draw(screen)# 让最近绘制的屏幕可见pygame.display.flip()

显示多行多列外星人

计算一行可用容纳的外星人数量

# 计算每行可容纳多少个外星人# 计算外星人可创建的区域,与屏幕边缘有边距available_space_x = ai_settings.screen_width - 2*alien_width# 计算一行可用放的外星人数量number_aliens_x = int(available_space_x / (2*alien_width))

第一行代码计算去除一定的边距后每行可用有多大空间来存放外星人飞船,这个边距可用自己设定。

第二行通过计算的空位计算可用存放多少个外星人

计算可用显示多少行外星人

上下也应该有边距:

# 计算屏幕可容纳多少行外星人available_space_y = (ai_settings.screen_height - (3*alien_height)-ship_height)number_rows = int(available_space_y / (2*alien_height))

创建外星人群

在alien_invasion.py中修改:

# 管理发射出去的子弹bullets = Group()# 创建一个空编组,用于存储全部外星人aliens=Group()# 创建外星人群gf.create_fleet(ai_settings,screen,ship,aliens)

gf.update_screen(ai_settings, screen, ship,aliens,bullets)

game_functions.py中修改:

# 获取外星人数量def get_number_aliens_x(ai_settings,alien_width):# 计算每行可容纳多少个外星人# 计算外星人可创建的区域,与屏幕边缘有边距available_space_x = ai_settings.screen_width - 2*alien_width# 计算一行可用放的外星人数量number_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_rows# 创建外星人def 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.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)

alien_invasion.py 中修改:

# 创建外星人群gf.create_fleet(ai_settings,screen,ship,aliens)

实现外星人移动

settings.py文件中作如下修改:

设置飞船的移动速度

# 外星人参数设置self.alien_speed_factor = 1# 外星人撞到屏幕边缘时,外星人群向下移动self.fleet_drop_speed = 10# fleet_direction 为1表示向右移动,-1表示向左移self.fleet_direction = 1

alien.py外星人类Alien中做如下修改:

def update(self):# 向左或向右移动外星人self.x += (self.ai_settings.alien_speed_factor*self.ai_settings.fleet_direction)self.rect.x = self.x

alien_invasion.py中修改:

#开始游戏的主循环#循环控制管理屏幕更新while True:gf.check_events(ai_settings,screen,ship,bullets)if stats.game_active:ship.update()# 更新子弹运行轨迹gf.update_bullets(ai_settings,screen,ship,aliens,bullets)gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置gf.update_screen(ai_settings, screen, ship,aliens,bullets)

检查外星人是否移动到边缘:

alien.py中

def check_edges(self):# 如果外星人位于屏幕边缘,就返回Truescreen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <=0:return True

向下移动并改变外星人移动方向

game_function.py

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 *=-1def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):# 检查外星人是否到达边缘check_fleet_edges(ai_settings,aliens)# 更新外星人群中所有外星人的位置aliens.update()# 检测外星人和飞船之间的碰撞# spritecollideany接受两个参数,一个精灵和一个编组。# 它检查编组是否有成员与精灵发生了碰撞,如果没有发生碰撞,返回Noneif pygame.sprite.spritecollideany(ship,aliens):print("Ship hit!!!")if pygame.sprite.spritecollideany(ship,aliens):ship_hit(ai_settings,stats,screen,ship,aliens,bullets)check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets)

alien_invasion.py中

#开始游戏的主循环#循环控制管理屏幕更新while True:gf.check_events(ai_settings,screen,ship,bullets)if stats.game_active:ship.update()# 更新子弹运行轨迹gf.update_bullets(ai_settings,screen,ship,aliens,bullets)gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置gf.update_screen(ai_settings, screen, ship,aliens,bullets)

几个文件中的完整代码:

alien.py文件中

import pygamefrom pygame.sprite import Spriteclass Alien(Sprite):# 表示单个外星人的类def __init__(self,ai_settings,screen):# 初始化外星人并设置其起始位置super(Alien,self).__init__()self.screen = screenself.ai_settings = ai_settings# 加载外星人图像,并设置其screen属性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 blitme(self):# 在指定位置绘制外星人self.screen.blit(self.image,self.rect)def update(self):# 向左或向右移动外星人self.x += (self.ai_settings.alien_speed_factor*self.ai_settings.fleet_direction)self.rect.x = self.xdef check_edges(self):# 如果外星人位于屏幕边缘,就返回Truescreen_rect = self.screen.get_rect()if self.rect.right >= screen_rect.right:return Trueelif self.rect.left <=0:return True

setting.py文件中:

class Settings():""" 存储 游戏 的所有设置的类,存放一些基本参数"""def __init__(self):""" 初始化游戏的设置"""#屏幕设置self.screen_width = 900self.screen_height = 600self.bg_color = (230,230,230)# 飞船设置# 设置属性ship_speed_factor来控制飞船的速度# 移动飞船时移动1.5 个像素self.ship_speed_factor = 1.0self.ship_limit = 3# 子弹设置self.bullet_speed_factor = 1 # 子弹速度self.bullet_width = 3 self.bullet_height = 15self.bullet_color = 60, 60, 60self.bullets_allowed = 10 # 限制子弹数量# 外星人参数设置self.alien_speed_factor = 1# 外星人撞到屏幕边缘时,外星人群向下移动self.fleet_drop_speed = 10# fleet_direction 为1表示向右移动,-1表示向左移self.fleet_direction = 1

game_function.py文件中

import sysimport pygamefrom bullet import Bulletfrom alien import Alienfrom time import sleep# 设置键盘按钮事件def check_keydown_events(event,ai_settings,screen,ship,bullets):# 响应按键 右方向键# 通过读取event.key,检查按下的是否是右箭头键if event.key == pygame.K_RIGHT:# 向右移动飞船# ship.rect.centerx += 1 飞船向右移动ship.moving_right = Trueelif event.key == pygame.K_LEFT:# 向左移动飞船# ship.rect.centerx -= 1ship.moving_left = Trueelif event.key == pygame.K_SPACE: # 设置开火指令fire_bullet(ai_settings, screen, ship, bullets)# 按下Q时退出游戏elif event.key == pygame.K_q:sys.exit()def check_keyup_events(event ,ship):# 响应松开if event.key == pygame.K_RIGHT:ship.moving_right = Falseelif event.key == pygame.K_LEFT:ship.moving_left = Falsedef check_events(ai_settings,screen,ship,bullets):""" 响应按键和鼠标事件,在这个方法中指定需要检查的事件 """# 事件都是通过pygame.event.get()方法获取for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()# 每次按键都会注册一个KEYDOWN# 检测到KEYDOWN事件时,我们需要检查按下的是否是特定的键elif event.type == pygame.KEYDOWN:check_keydown_events(event,ai_settings,screen,ship,bullets)# 松开方向键时触发的事件,将moving_right or moving_left设为falseelif event.type == pygame.KEYUP:check_keyup_events(event,ship)def update_screen(ai_settings, screen, ship,aliens,bullets):# 更新屏幕上的图像, 并切换新屏幕#每次循环都会重绘制屏幕screen.fill(ai_settings.bg_color) #只能有一个参数for bullet in bullets.sprites():bullet.draw_bullet()ship.blitme()aliens.draw(screen)# 让最近绘制的屏幕可见pygame.display.flip()def update_bullets(ai_settings,screen,ship,aliens,bullets):# 更新子弹的位置, 并删除已消失的子弹 4303987588749bullets.update()# 清楚越界的子弹,防止占用内存# 遍历子弹编组的副本,在副本中检查每颗子弹,判断是否到顶端for bullet in bullets.copy():# 如果子弹到顶端则删除if bullet.rect.bottom<=0:bullets.remove(bullet)# print(len(bullets)) # 打印输出剩余的子弹数量check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets)def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):# groupcollide遍历编组bullets中的所有子弹和编组aliens中的所有外星人。# 当有子弹和外星人的rect重叠时,groupcollide返回一个键值对collisions = pygame.sprite.groupcollide(bullets,aliens,True,True)if len(aliens) ==0 :# 删除现有的子弹并创建一群外星人bullets.empty()create_fleet(ai_settings,screen,ship,aliens)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 get_number_aliens_x(ai_settings,alien_width):# 计算每行可容纳多少个外星人# 计算外星人可创建的区域,与屏幕边缘有边距available_space_x = ai_settings.screen_width - 2*alien_width# 计算一行可用放的外星人数量number_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_rows# 创建外星人def 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.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 *=-1def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):# 检查外星人是否到达边缘check_fleet_edges(ai_settings,aliens)# 更新外星人群中所有外星人的位置aliens.update()# 检测外星人和飞船之间的碰撞# spritecollideany接受两个参数,一个精灵和一个编组。# 它检查编组是否有成员与精灵发生了碰撞,如果没有发生碰撞,返回Noneif pygame.sprite.spritecollideany(ship,aliens):print("Ship hit!!!")if pygame.sprite.spritecollideany(ship,aliens):ship_hit(ai_settings,stats,screen,ship,aliens,bullets)check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets)def ship_hit(ai_settings,stats,screen,ship,aliens,bullets):# 响应被外星人撞到的飞船# 将ships_left减1if stats.ships_left > 0:stats.ships_left -= 1# 清空外星人列表和子弹列表aliens.empty()bullets.empty()# 创建一群新的外星人, 并将飞船放到屏幕底端中央create_fleet(ai_settings,screen,ship,aliens)ship.center_ship()# 暂停sleep(0.5)else:stats.geme_active = Falsedef check_aliens_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

alien_invasion.py 中

import sysimport pygamefrom setting import Settingsfrom pygame.sprite import Groupfrom ship import Shipimport game_functions as gffrom alien import Alienfrom game_stats import GamStatsdef run_game():# 初始化游戏并创建一个屏幕对象pygame.init() #初始化背景设置ai_settings = Settings()screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))#创建一个sceen窗口pygame.display.set_caption("Alien Invasion")# 创建一个用于存储游戏统计信息的实例stats = GamStats(ai_settings)#创建一艘飞船ship = Ship(ai_settings,screen)# 创建一个外星人alien = Alien(ai_settings,screen)#设置背景颜色bg_color = (230, 230, 230)# 创建一个用于存储子弹的编组,存储所有有效的子弹,# 管理发射出去的子弹bullets = Group()# 创建一个空编组,用于存储全部外星人aliens=Group()# 创建外星人群gf.create_fleet(ai_settings,screen,ship,aliens)#开始游戏的主循环#循环控制管理屏幕更新while True:gf.check_events(ai_settings,screen,ship,bullets)if stats.game_active:ship.update()# 更新子弹运行轨迹gf.update_bullets(ai_settings,screen,ship,aliens,bullets)gf.update_aliens(ai_settings,stats,screen,ship,aliens,bullets) # 更新外星人位置gf.update_screen(ai_settings, screen, ship,aliens,bullets)run_game()

给出的实际上是整个游戏的完整代码,因为是全部写完后再写的博客,所以没有再去拆分,可用先全部看一遍,再拆开看,读代码能力强的其实直接看代码就好了。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。