此项目仅为个人笔记,不适合学习…
学习自《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():
pygame
.init
()
ai_settings
= Settings
()
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
)
pygame
.display
.flip
()
2.飞船对象
/settings
.py
self
.ship_speed_factor
= 1.5
self
.ship_limit
= 3
/ship
.py
import pygame
class Ship():
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
()
self
.screen_rect
= screen
.get_rect
()
self
.rect
.centerx
= self
.screen_rect
.centerx
self
.rect
.bottom
= self
.screen_rect
.bottom
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
):
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
self
.rect
.centerx
= self
.center
self
.rect
.bottom
= self
.bottom
def blitme(self
):
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
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
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
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
self
.alien_speed_factor
= 1
self
.fleet_drop_speed
= 10
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
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是主要功能的文件:有检查事件、更新屏幕(绘制所有)、更新 子弹(因为越过窗口后要消失,前面的更新只是移动的位置)、创建外星人群实例函数、外星人越过下界、碰到左右两边的更新函数、子弹外星人碰撞、飞船外星人碰撞