天天看点

射杀外星人python实验_Python系统学习 - 项目篇(消灭外星人3)

哇~都这么久了,唉都怪广东这个天气,总是下雨,让人心情都变得沉闷,难搞哦,(其实主要还是工作原因,累死个人,剥削 + 10086)

今天我们学习了消灭外星人都最重要都一个环节:创建外星人飞船大军、子弹与外星人碰撞后的一些操作、游戏状态的实时记录、游戏重置,接下来,我们就来看看代码的改动,因为是最重要的一章,所以建议大家核对如下的所有代码,改动较大,望见谅哦!

1.alien.py:

# coding = utf8

import pygame

import os

os.path.abspath(".")

from pygame.sprite import Sprite

class Alien(Sprite):

# 表示单个 外星人的类

def __init__(self, settings_game, screen):

"""Init function to init a alien object

Args:

settings_game (Settings): Settings object

screen (Screen): Screen object

"""

# 初始化外星人并设置其起始位置

super(Alien, self).__init__()

self.screen = screen

self.settings = settings_game

# 加载外星人图像,并设置其rect属性

self.image = pygame.image.load("./alien_invasion_study/images/alien.bmp")

self.rect = self.image.get_rect()

# 初始化外星人在屏幕左上角附近

self.rect.x = self.rect.width / 2

self.rect.y = self.rect.height / 2

# 存储外星人的准确位置

self.x = float(self.rect.x)

def blitme(self):

# 在指定位置绘制外星人

self.screen.blit(self.image, self.rect)

# 更新外星人位置 - 移动

def update(self):

self.x += (self.settings.alien_speed_factor * self.settings.fleet_direction)

self.rect.x = self.x

# 如果外星人处于屏幕边缘,则返回True

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

if __name__ == "__main__":

pass

2.alien_invasion.py:

# coding = utf8

import os

import sys

import pygame

from settings import settings_game

from ship import ship_game

from game_function import game_function_game as gf

from pygame.sprite import Group

from alien import Alien

from game_stats import GameStats

os.path.abspath(".")

def run_game():

# 初始化游戏并创建一个屏幕对象

pygame.init()

settings_obj = settings_game()

screen = pygame.display.set_mode((settings_obj.width, settings_obj.height))

bg_color = settings_obj.bg_color

pygame.display.set_caption(settings_obj.caption)

# 创建一个用于存储游戏统计信息的实例

stats = GameStats(settings_obj)

# 创建一艘飞船

ship_obj = ship_game(screen)

# 创建一个用于存储子弹的编组

bullets = Group()

# 创建一个外星人对象

# alien = Alien(settings_obj, screen)

aliens = Group()

# 创建外星人群

gf.create_fleet(settings_obj, screen, ship_obj, aliens)

# 开始游戏主循环

while True:

# 监听键盘和鼠标事件

gf.check_events(ship_obj, settings_obj, screen, bullets)

if stats.game_active == True:

# 更新子弹

gf.update_bullets(settings_obj, screen, ship_obj, aliens, bullets)

# 更新外星人群位置

gf.update_aliens(ship_obj, settings_obj, aliens, stats, screen, bullets)

# 让最近绘制的屏幕可见

gf.update_screen(settings_obj, screen, ship_obj, bullets, aliens)

run_game()

3.bullet.py:

# coding = utf8

import os

os.path.abspath(".")

from pygame.sprite import Sprite

import pygame

class Bullet(Sprite):

"""

Image 代表图片本身,只提供图片的数据和基本操作,

Sprite代表一个由多帧组成的闪花,只负责只帧数、位置上操作。传入Image后,Sprite把Image分成多帧操作。

Sprite仅限只游戏框架范围内使用

Image是基本图片封装类型

Sprite可以认为是一个个小图片,一种可以在屏幕上移动的图形对象,并且可以与其他图形对象交互。精灵图像可以是使用pygame

绘制函数绘制的图像,也可以是原来就有的图像文件

当前类中使用Sprite类,通过使用精灵,可将游戏中相关元素编组,进而同时操作编组中的所有元素。

"""

def __init__(self, screen, settings_game, ship):

"""Create a bullet object and contained theirs attributions

Args:

screen (Screen): Deliver into a screen object

settings_game (settings_game): Deliver into a settings_game object

ship (ship_obj): Deliver into a ship object

"""

# 在飞船位置处创建一个子弹对象

super(Bullet, self).__init__()

self.screen = screen

self.settings_game = settings_game

self.ship = ship

# 在(0, 0)位置绘制一个子弹的矩形,再设置后续位置

self.rect = pygame.Rect(0, 0, settings_game.bullet_width, settings_game.bullet_height)

self.rect.centerx = ship.rect.centerx

self.rect.top = ship.rect.top

# 存储小数子弹纵坐标表示其位置,后续位置移动使用

self.y = float(self.rect.y) # rect.y == rect.top

self.color = settings_game.bullet_color

self.speed_factor = settings_game.bullet_speed_factor

def update(self):

"""

更新子弹位置

"""

self.y -= self.speed_factor

self.rect.y = self.y

def draw_bullet(self):

"""

屏幕上绘制子弹

"""

pygame.draw.rect(self.screen, self.color, self.rect)

# 子弹需要不断更新位置,当绘制完成后需要更新子弹位置

self.update()

4.game_function.py(很多的改动):

# coding = utf8

import os

os.path.abspath(".")

import sys

import pygame

from bullet import Bullet

from alien import Alien

from time import sleep

class game_function_game():

def check_keydown_events(event, ship_obj, settings_obj, screen, bullets):

"""This is a function to control keydown events

Args:

event (Events): All event to accept for judgement from keyboard

ship_obj (ship_game): A ship_game object

settings_obj (settings_game): Deliver into a settings_game object

screen (Screen): Deliver into a screen object

bullets (Group) : Deliver into a bullet group

"""

if event.key == pygame.K_RIGHT:

# 向右移动飞船

ship_obj.moving_right = True

elif event.key == pygame.K_LEFT:

# 向左移动飞船

ship_obj.moving_left = True

elif event.key == pygame.K_UP:

# 向上移动飞船

ship_obj.moving_top = True

elif event.key == pygame.K_DOWN:

# 向下移动飞船

ship_obj.moving_bottom = True

elif event.key == pygame.K_SPACE:

# 创建一颗子弹并添加到编组bullets中, 同时限制在屏幕中出现的子弹是数量

game_function_game.fire_bullet(settings_obj, ship_obj, screen, bullets)

elif event.key == pygame.K_q:

# 快捷键结束游戏 - 键盘键Q

sys.exit()

def check_keyup_events(event, ship_obj):

"""This is a function to control keyup events

Args:

event (Events): All event to accept for judgement from keyboard

ship_obj (ship_game): A ship_game object

"""

if event.key == pygame.K_LEFT:

ship_obj.moving_left = False

elif event.key == pygame.K_RIGHT:

ship_obj.moving_right = False

elif event.key == pygame.K_UP:

ship_obj.moving_top = False

elif event.key == pygame.K_DOWN:

ship_obj.moving_bottom = False

def check_events(ship_obj, settings_obj, screen, bullets):

"""Main events distribution

Args:

ship_obj (ship_game): A ship_game object to response keyboard or other action

settings_obj (settings_game): Deliver into a settings_game object

screen (Screen): Deliver into a screen object

bullets (Group) : Deliver into a bullet group

"""

# 响应按键和鼠标事件

for event in pygame.event.get():

if event.type == pygame.QUIT:

sys.exit()

elif event.type == pygame.KEYDOWN:

game_function_game.check_keydown_events(event, ship_obj, settings_obj, screen, bullets)

elif event.type == pygame.KEYUP:

game_function_game.check_keyup_events(event, ship_obj)

def update_screen(settings_obj, screen, ship_obj, bullets, aliens):

"""A function to update screen, refresh the ship or other object's behaviour

Args:

settings_obj ([settings_game]): A settings_game object to gain some attributions

screen (Screen): Current screen's object as the game frame

ship_obj (ship_game): A ship_game object for ship update

bullets (Group) : Deliver into a bullet group

aliens (Group) : Deliver into a alien group

"""

# 更新屏幕图像,并切换到新屏幕

# 每次循环时重绘屏幕

# 更新飞船位置

screen.fill(settings_obj.bg_color)

# 重绘所有子弹

for bullet in bullets.sprites():

bullet.draw_bullet()

ship_obj.blitme()

aliens.draw(screen)

ship_obj.update(settings_obj)

# 更新整个待显示的Surface对象到屏幕上

pygame.display.flip()

def create_fleet(settings_obj, screen, ship, aliens):

"""Create a alien fleet display on screen

Args:

settings_obj (Settings): Settings object

screen (Screen): Screen object

ship (Ship): Ship object

aliens (Group): A alien's group

"""

# 创建外星人群

alien = Alien(settings_obj, screen)

alien_width = alien.rect.width

number_alien_x = game_function_game.get_number_aliens_x(settings_obj, alien_width)

number_rows = game_function_game.get_number_rows(settings_obj, ship.rect.height, alien.rect.height)

# 创建第number_rows行外星人

for number_row in range(int(number_rows)):

for alien_number in range(number_alien_x):

aliens_group = game_function_game.create_alien(settings_obj, screen, alien_number, aliens, number_row)

def get_number_aliens_x(settings_obj, alien_width):

"""Get the number of aliens can display on one row

Args:

settings_obj (Settings): Settings object

alien_width (Integer): Alien object's width

Returns:

[Integer]: The number of alien's in one row

"""

# 计算每行可容纳多少外星人

available_space_x = settings_obj.width - 2 * alien_width

number_aliens_x = int(available_space_x / (2 * alien_width))

return number_aliens_x

def get_number_rows(settings_obj,alien_height, ship_height):

"""Get the row number of aliens can display on screen

Args:

settings_obj (Settings): Settings object

alien_height (Integer): Alien object's height

ship_height (Integer): Ship object's

Returns:

[Integer]: The number of how many rows can display the aliens

"""

# 计算可容纳多少行外星人

available_space_y = settings_obj.height - 2 * alien_height - ship_height

number_rows = available_space_y / (2 * alien_height)

return number_rows

def create_alien(settings_obj, screen, alien_number, aliens, row_number):

"""Create a alien object into specific row

Args:

settings_obj (Settings): Settings object

screen (Screen): Screen object

alien_number (Integer): How many aliens can display on one row

aliens (Group): Alien's group

row_number (Integer): The number of how many rows can display the aliens

Returns:

Group: Alien's group

"""

# 创建一个外星人并将它放在当前行

alien = Alien(settings_obj, screen)

alien_width = alien.rect.width

alien.x = alien_width + 1.2 * alien_width * alien_number

alien.y = alien.rect.height + 1.2 * alien.rect.height * row_number

alien.rect.x = alien.x

alien.rect.y = alien.y

aliens.add(alien)

return aliens

def update_bullets(settings_obj, screen, ship, aliens, bullets):

"""Update bullets's stats

Args:

settings_obj (Settings): Settings object

screen (Screen): Screen object

ship (Ship): Ship object

aliens (Group): Alien's group

bullets (Group): Bullet's group

"""

# 删除已消失的子弹

bullets.update()

for bullet in bullets.copy():

if bullet.rect.bottom <= 0:

bullets.remove(bullet)

game_function_game.check_bullet_alien_collisions(settings_obj, bullets, aliens, screen, ship)

def check_bullet_alien_collisions(settings_obj, bullets, aliens, screen, ship):

"""Check bullet collapse the alien then make specific operation

Args:

settings_obj (Settings): Settings

bullets (Group): Bullet's group

aliens (Group): Alien's group

screen (Screen): Screen object

ship (Ship): Ship object

"""

# 检查是否有子弹击中了外星人,如果是这样,删除对应的子弹和外星人, 后面两个True分别表示是否删除碰撞后的子弹和外星人

# 如果是穿甲弹,可以将第一个Bullets的True设置成False,即碰撞后不会销毁改子弹,会一直穿行直到屏幕顶部后消失

collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)

if len(aliens) == 0:

# 删除现有子弹并新建一群外星人

bullets.empty()

game_function_game.create_fleet(settings_obj, screen, ship, aliens)

def fire_bullet(settings_obj, ship_obj, screen, bullets):

"""Describe a function to fire bullet

Args:

settings_obj (settings_game): Deliver into a settings_game object

ship_obj (ship_game): A ship_game object for ship update

screen (Screen): Deliver into a screen object

bullets (Group) : Deliver into a bullet group

"""

# 发射子弹函数

if len(bullets) < settings_obj.bullet_allowed:

new_bullet = Bullet(screen, settings_obj, ship_obj)

bullets.add(new_bullet)

def update_aliens(ship, settings_obj, aliens, stats, screen, bullets):

"""Update alien's group stats and do specific operation

Args:

ship (Ship): Ship object

settings_obj (settings_game): Deliver into a settings_game object

aliens (Group): Alien's group

stats (GameStats): GameStats object

screen (Screen): Screen object

bullets (Group): Bullet's group

"""

# 更新外星人群中所有外星人的位置

game_function_game.check_fleet_edges(settings_obj, aliens)

aliens.update()

# 检测外星人和飞船之间的碰撞

if pygame.sprite.spritecollideany(ship, aliens):

game_function_game.ship_hit(settings_obj, stats, screen, ship, aliens, bullets)

game_function_game.check_aliens_bottom(settings_obj, stats, screen, ship, aliens, bullets)

def ship_hit(settings, stats, screen, ship, aliens, bullets):

"""Ship hit function

Args:

settings (Settings): Settings object

stats (GameStats): GameStats object

screen (Screen): Screen object

ship (Ship): Ship object

aliens (Group): Alien's group

bullets (Group): Bullet's group

"""

if stats.ship_left > 0:

# 响应被外星人撞到的飞船

stats.ship_left -= 1

# 清空外星人列表和子弹列表

aliens.empty()

bullets.empty()

# 创建一群新的外星人, 并将飞船放到屏幕底端中央

game_function_game.create_fleet(settings, screen, ship, aliens)

ship.center_ship(screen)

# 暂停

sleep(1)

else:

# 没有飞船了,设置为False

stats.game_active = False

def check_fleet_edges(settings_obj, aliens):

"""The operation to adjust alien fleet's motion when collapse the edges

Args:

settings_obj (Settings): Settings object

aliens (Group): Alien's group

"""

# 外星人到达边缘时采取的措施

for alien in aliens.sprites():

if alien.check_edges():

game_function_game.change_fleet_direction(settings_obj, aliens)

break

def change_fleet_direction(settings_obj, aliens):

"""Change alien fleet's direction

Args:

settings_obj (Settings): Settings object

aliens (Group): Alien's group

"""

# 整群外星人下移,并改变它们的方向

for alien in aliens.sprites():

alien.rect.y += settings_obj.fleet_drop_speed

settings_obj.fleet_direction *= -1

def check_aliens_bottom(settings, stats, screen, ship, aliens, bullets):

"""When alien' fleet arrived screen bottom will handle it

Args:

settings (Settings): Settings object

stats (GameStats): GameStats object

screen (Screen): Screen object

ship (Ship): Ship object

aliens (Group): Alien's group

bullets (Group): Bullet's group

"""

# 检查是否有外星人到达了底端

screen_rect = screen.get_rect()

for alien in aliens.sprites():

if alien.rect.bottom >= screen_rect.bottom:

# 像飞船被撞一样处理

game_function_game.ship_hit(settings, stats, screen, ship, aliens, bullets)

break

5.game_stats.py:(添加的一个新的类,用于记录游戏进行时的信息)

# coding = utf8

import os

os.path.abspath(".")

class GameStats():

"""

跟着游戏的统计信息

"""

def __init__(self, settings):

"""GameStats's init function

Args:

settings (Settings): Settings object

"""

# 初始化统计信息

self.settings = settings

self.reset_stats()

# 游戏刚启动时处于活跃状态

self.game_active = True

def reset_stats(self):

# 初始化游戏运行期间可能变化的统计信息

self.ship_left = self.settings.ship_limit

6.settings.py:

# coding = utf8

import os

os.path.abspath(".")

class settings_game():

def __init__(self):

# 屏幕属性

self.width = 800

self.height = 600

self.bg_color = (230, 230, 230)

self.caption = "Alien Invasion"

# 飞船属性

# 设置飞船移动速度

self.ship_speed_factor = 10

self.ship_limit = 2

# 子弹属性

self.bullet_speed_factor = 6

self.bullet_width = 10

self.bullet_height = 15

self.bullet_color = (60, 60, 60)

self.bullet_allowed = 5

# 外星人属性

self.alien_speed_factor = 10

self.fleet_drop_speed = 50

# fleet_direction为1表示右移,-1表示左移

self.fleet_direction = 1

if __name__ == "__main__":

pass

7.ship.py:

# coding = utf8

import os

os.path.abspath(".")

import pygame

class ship_game():

def __init__(self, screen):

"""Ship's init function to define the ship's attributions

Args:

screen (Screen): Current screen's object as the game frame

"""

# 初始化飞船并设置其初始位置

self.screen = screen

# 加载初始飞船图像并获取其外接矩形

self.image = pygame.image.load("./alien_invasion_study/images/ship.bmp")

self.rect = self.image.get_rect()

self.screen_rect = self.screen.get_rect()

# 将每艘飞船放在屏幕底部中央

self.rect.centerx = self.screen_rect.centerx # 左右移动的中心点

self.rect.bottom = self.screen_rect.bottom

self.rect.centery = self.rect.centery # 上下移动的中心点

# 飞船移动标志

self.moving_right = False

self.moving_left = False

self.moving_top = False

self.moving_bottom = False

# 存储小数值的飞船的centerx centery

self.centerx_float = float(self.rect.centerx)

self.centery_float = float(self.rect.centery)

def blitme(self):

# 在指定位置绘制飞船

# blit是用来绘制基本图片的

# draw是用来绘制基本图形的

self.screen.blit(self.image, self.rect)

def update(self, settings_obj):

"""A function to adjust ship's position

Args:

settings_obj (settings_game): A settings_game object to gain some attributions

"""

# 根据移动标志调整飞船位置

# 左移

if self.moving_left and self.rect.left > 0:

self.centerx_float -= settings_obj.ship_speed_factor

# 右移

if self.moving_right and self.rect.right < self.screen_rect.right:

self.centerx_float += settings_obj.ship_speed_factor

# 上移

if self.moving_top and self.rect.top > 0:

self.centery_float -= settings_obj.ship_speed_factor

# 下移

if self.moving_bottom and self.rect.bottom < self.screen_rect.bottom:

self.centery_float += settings_obj.ship_speed_factor

# 最后将最终的飞船的中心点位置重新赋值进而更新飞船位置

self.rect.centerx = self.centerx_float

self.rect.centery = self.centery_float

def center_ship(self, screen):

"""Make ship on screen center to reset Ship position

Args:

screen (Screen): Screen object

"""

# 让飞船在屏幕上底部居中

self.rect.centerx = self.screen_rect.centerx

self.rect.bottom = self.screen_rect.bottom

self.rect.centery = self.rect.centery

self.centerx_float = float(self.rect.centerx)

self.centery_float = float(self.rect.centery)

if __name__ == "__main__":

pass

附加一个效果图:

好了,这个项目马上就要接近尾声了,我们下一章就来完成整个项目,因此下一章会完善游戏的记分功能等,敬请期待吧(没办法,宝宝心累~)

关注 + 收藏 + 点赞哦,谢谢啦~