动画类在https://blog.csdn.net/qq_36614557/article/details/91409885介绍。
一、Kinds文件夹
Kinds文件夹下定义了多个本机、敌机、子弹等单位类,每个类自成一个py文件,并以类名命名。
1.Ship类
Ship类除了定义了基本的初始化和刷新以外,还包括:
(1) update_revive函数,在刷新函数中被调用,用来显示复活界面,函数内直接使用Animation,并通过while循环计数来进行复活等待。
(2) active_animation函数,用来在进入新关卡时,显示关卡的进入动画(和游戏同时进行)。
(3) update_animation函数,用来刷新动画组。
(4) handleInit函数,调用Handle类的对象,在事件触发器添加键盘按钮和触发函数(事件)字典项。
(5) hit函数,空格键的触发函数,调用当前关卡的hit()函数,射出子弹。
(6) left/right/up/down_button,adwd键的触发函数,改变当前飞机是否朝某个方向前行的状态,该状态在Ship的初始化里,长按可实现连续朝某个方向前进。
(7) quitui函数,q键的触发函数,改变当前的状态,即game_active置False,ui_active置True,用来实现退出游戏,范围至主菜单界面。
(8) pause函数,p键的触发函数,改变当前的状态,暂停游戏打开商店或退出商店继续游戏。如果要打开商店,在此随机出现一个参数用来随机出现某限定道具。
(9) change函数,o键的触发函数,改变当前的状态,进入飞机颜色设计界面或退出界面并继续之前的页面。
(10) use函数,e键的触发函数,如果是第一关/第三关,则使用当前持有的道具,如果是第二关,则随机释放道具。
(11) random_reset函数,随机传送飞机至一定区域内任意位置[第四章 随机事件内]。
(12) drawachi函数,draw中调用,在屏幕右上角绘制“获得成就”以及对应的成就名和获得方式。
(13) reset函数,r键的触发函数,清除异常事件(HI.clear())并重置至指定位置。
(14) position_reset函数,血量恢复至100【第三章/第四章】,并并重置至指定位置。【复活后触发】
(15) drawBlood函数,通过使用pygame.draw.line函数在飞机头顶上画血条并随着飞机位置变化而变化【第三章/第四章】
(16) draw_background函数,根据当前的关卡数绘制关卡背景。
(17) boom_load函数,显示加载条,如果满了就提示可以按E释放。【第二章】
(18) draw_life/draw_bullet/draw_score函数,根据当前剩余生命值/子弹数/积分值/持有道具/道具进度条等在屏幕上端绘制出来。
(19) standardlize,类外函数,对输入的数字转化到K/M/G级别返回字符串。
初始化函数init()中包括贴图等的加载、状态的声明、数值的初始化等。
更新函数update()包括根据状态进行更新位置等。
绘制函数draw()包括以上各种绘制函数。
import pygame
import time
import random
from Codes.Base.Screen import SI
from Codes.Logic.GameStates import GStI
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.GameSettings import GSeI
from Codes.Input.Handle import HI
from Codes.Battles.Battle1 import BI as Battle1
from Codes.Battles.Battle2 import BI as Battle2
from Codes.Battles.Battle3 import BI as Battle3
from Codes.Battles.Battle4 import BI as Battle4
from Codes.Base.Animation import Animation
def returnbattle():
Battles=[Battle1,Battle2,Battle3,Battle4]
return Battles[GStI.current_checkpoint-1]
class Ship(DrawOn):
def __init__(self):
super().__init__()
super(Ship,self).definePriority(2)
def init(self):
self.ship_speed_factor=GSeI.ship_speed_factor*2
(w,h)=(GSeI.ship_width,GSeI.ship_height)
self.image_list=[]
self.image2_list=[]
for i in range(18):
filename='images/Ship/plane_'+str(i)+'_'
img=pygame.image.load(filename+'1.png').convert_alpha()
self.image_list.append(pygame.transform.scale(img,(w,h)))
img2=pygame.image.load(filename+'2.png').convert_alpha()
self.image2_list.append(pygame.transform.scale(img2,(w,h)))
cs=GSeI.color_select
self.image=self.image_list[cs]
self.image_wudi = pygame.image.load('images/Ship/plane_wudi_1.png').convert_alpha()
self.image2_wudi = pygame.image.load('images/Ship/plane_wudi_2.png').convert_alpha()
self.image_wudi = pygame.transform.scale(self.image_wudi,(w,h))
self.image2_wudi = pygame.transform.scale(self.image2_wudi,(w,h))
self.img_mini=pygame.transform.scale(self.image,(40,40))
self.bullet_mini=pygame.image.load('images/bullet_shotgun.png').convert_alpha()
self.bullet_mini=pygame.transform.scale(self.bullet_mini,(12,40))
self.image_achi=pygame.image.load('images/achi.jpg').convert_alpha()
self.image_achi=pygame.transform.scale(self.image_achi,(292,50))
self.rect = self.image.get_rect()
self.screen=SI.screen
self.screen_rect = SI.screen.get_rect()
self.rect.centerx = self.screen_rect.centerx
self.rect.centery = self.screen_rect.centery
self.rect.bottom = self.screen_rect.bottom
self.pos_x=float(self.rect.centerx)
self.pos_y=float(self.rect.centery)
self.moving_right=False
self.moving_left=False
self.moving_up=False
self.moving_down=False
self.handleInit()
self.chapter=[1]*4
self.j=1
self.info=[]
self.framerate = pygame.time.Clock()
self.framerate.tick(30)
self.group =pygame.sprite.Group()
self.boom=0
self.delay=20#boom_load的文字显示时延
self.image_chapter=[]
for i in range(4):
temp=pygame.image.load('images/bg_chapter_'+str(i+1)+'.jpg')
temp = pygame.transform.scale(temp,(1200,800))
self.image_chapter.append(temp)
def update(self,delta):
checkpoint=GStI.current_checkpoint-1
if self.chapter[checkpoint]==1:
self.active_animation(checkpoint)
if GStI.revive==True:
self.update_revive()
v_add=GSeI.sou*(7-GSeI.sou)*10
updown=1
if GSeI.updown>0:
updown=-1
if GSeI.shufu<=0:
if self.moving_right and self.rect.right < GSeI.screen_width:
self.pos_x += (self.ship_speed_factor+v_add)*delta*updown
if self.moving_left and self.rect.left > 0:
self.pos_x -= (self.ship_speed_factor+v_add)*delta*updown
if self.moving_down and self.rect.bottom < GSeI.screen_height:
self.pos_y += (self.ship_speed_factor+v_add)*delta*updown
if self.moving_up and self.rect.top > 0:
self.pos_y -= (self.ship_speed_factor+v_add)*delta*updown
self.rect.centerx=self.pos_x
self.rect.centery=self.pos_y
self.preDraw()
def update_revive(self):
self.revive=1
self.animation_scroll= Animation(self.screen,400,400)
self.animation_scroll.load("images\scroll\scroll.png", 415, 224, 4)
self.group.add(self.animation_scroll)
while self.revive<=3000:
ticks = pygame.time.get_ticks()
self.group.update(ticks)
self.group.draw(self.screen)
pygame.display.update()
self.revive=self.revive+1
GStI.revive=False
self.group.remove()
def active_animation(self,i):
self.animation = Animation(self.screen,0,250)
self.animation.load("images\chapter\chapter0"+str(i+1)+".png", 1200, 240, 6)
self.group.add(self.animation)
def update_animation(self,i):
if self.chapter[i]<=60:
ticks = pygame.time.get_ticks()
self.group.update(ticks)
self.group.draw(self.screen)
pygame.display.update()
self.chapter[i]=self.chapter[i]+1
if self.chapter[i]>60:
self.chapter[i]=0
self.group.empty()
def handleInit(self):
HI.add(pygame.K_a,self.left_Button)
HI.add(pygame.K_w,self.up_Button)
HI.add(pygame.K_s,self.down_Button)
HI.add(pygame.K_d,self.right_Button)
HI.add(pygame.K_p,self.pause)
HI.add(pygame.K_o,self.change)
HI.add(pygame.K_q,self.quitui)
HI.add(pygame.K_e,self.use)
HI.add(pygame.K_r,self.reset)
HI.add(pygame.K_SPACE,self.hit)
def hit(self):
BI=returnbattle()
if GStI.current_checkpoint<4:
BI.hit()
def left_Button(self):
self.moving_left=self.moving_left^1
def right_Button(self):
self.moving_right=self.moving_right^1
def up_Button(self):
self.moving_up=self.moving_up^1
def down_Button(self):
self.moving_down=self.moving_down^1
def quitui(self):
if GStI.game_active==True:
GStI.ui=True
GStI.game_active=False
def pause(self):
if GStI.current_checkpoint==1 or GStI.current_checkpoint==3:
if GStI.change_active==False and GStI.game_active==True:
GStI.game_active=False
GStI.store_active=True
tool=['至尊VIP','永久加成卡','清屏','屏障','超级加倍卡']
length=len(tool)-GSeI.vip-GSeI.pac
item=random.randint(0,length-1)
if length==len(tool)-2:
item+=2
elif length==len(tool)-1 and GSeI.vip==1:
item+=1
elif length==len(tool)-1 and GSeI.vip==0:
if item!=0:
item+=1
GSeI.item=item
elif GStI.store_active==True:
GStI.game_active=True
GStI.store_active=False
def change(self):
if GStI.game_active==True and GStI.store_active==False:
GStI.game_active=False
GStI.change_active=True
elif GStI.change_active==True:
GStI.game_active=True
GStI.change_active=False
def use(self):
BI=returnbattle()
if GStI.current_checkpoint==2:
if self.boom >= 100:
r = random.choice([1,2])
if r==1:
BI.boom()
if r==2:
BI.addbullet_s1()
self.boom = 0;
elif GStI.current_checkpoint!=4:
if GStI.game_active==True:
if GSeI.use==1:
BI.clear_aliens()
if GSeI.use==2:
GStI.wudi=True
GSeI.wudi_left=GSeI.wudi_time
if GSeI.use==3:
GStI.tac=True
GSeI.tac_left=GSeI.tac_time
if GSeI.use==4:
GSeI.ding=3
if GSeI.use==5:
GSeI.sou=7
if GSeI.use==6:
GSeI.xuruo=5
GSeI.use=0
def random_reset(self):
self.rect.centerx=random.randint(50,1150)
self.pos_x=self.rect.centerx
self.rect.centery=random.randint(50,750)
self.pos_y=self.rect.centery
self.moving_right=False
self.moving_left=False
self.moving_up=False
self.moving_down=False
def center_ship(self):
self.center=self.screen_rect.centerx
def preDraw(self):
DCI.add(self)
def draw(self):
self.draw_background()
self.print_information()
self.draw_life()
if GStI.current_checkpoint!=4:
self.draw_bullet()
cs=GSeI.color_select
if GStI.wudi==False:
if time.time()%1>0.5:
self.screen.blit(self.image_list[cs], self.rect)
else:
self.screen.blit(self.image2_list[cs], self.rect)
else:
if time.time()%1>0.5:
self.screen.blit(self.image_wudi, self.rect)
else:
self.screen.blit(self.image2_wudi, self.rect)
if GStI.current_checkpoint>=3:
self.drawBlood()
self.draw_score()
if GStI.current_checkpoint==2:
self.boom_load()
for i in range(16):
if GSeI.achi_active[i]==1: #如果某个成就动态开启 则调用函数
if self.j<60: #循环60帧
self.drawachi(i)
self.j+=1
else:
self.j=1
GSeI.achi_active[i]=0
checkpoint=GStI.current_checkpoint-1
if self.chapter[checkpoint]!=0:
self.update_animation(checkpoint)
def drawachi(self,i):#绘制获得第i个成就
self.screen.blit(self.image_achi,(800,0,292,50))
self.print_text('获得成就:'+GSeI.achiname[i],880,25,rgb=(255,0,0),textsize=18)
self.print_text(GSeI.achitext[i],900,43,rgb=(0,255,255),textsize=15)
def reset(self):
self.rect.centerx=GSeI.screen_width*0.5
self.pos_x=self.rect.centerx
self.rect.centery=GSeI.screen_height*0.8
self.pos_y=self.rect.centery
HI.clear()
self.handleInit()
self.moving_right=False
self.moving_left=False
self.moving_up=False
self.moving_down=False
def position_reset(self):
self.rect.centerx=GSeI.screen_width*0.5
self.pos_x=self.rect.centerx
self.rect.centery=GSeI.screen_height*0.8
self.pos_y=self.rect.centery
self.moving_right=False
self.moving_left=False
self.moving_up=False
self.moving_down=False
self.blood=100
def drawBlood(self):
if self.blood>=0:
blood=self.blood/100
if blood >=0.3:
blood_color=[0,255,0]
else:
blood_color=[255,0,0]
pygame.draw.line(self.screen,[0,0,0],(self.rect.left,self.rect.top-5),(self.rect.right,self.rect.top-5),3)
pygame.draw.line(self.screen,blood_color,(self.rect.left,self.rect.top-5),(self.rect.left+self.rect.width*blood,self.rect.top-5),3)
def draw_background(self):
if not GStI.ui and not GStI.die_active and not GStI.background:
point=GStI.current_checkpoint
self.screen.blit(self.image_chapter[point-1],self.image_chapter[point-1].get_rect())
def boom_load(self):
pygame.draw.rect(self.screen,[0,206,206],(20,160,105,10),3)
if self.boom < 100:
self.boom += 0.2
pygame.draw.line(self.screen,[241,88,88],(22,164),(22+self.boom,164),6)
font = pygame.font.Font("fonts/Amadeus.ttf",30)
text = font.render("(Press ’E‘ to use)",True,(0,206,206))
if self.boom >= 100:
if self.delay <= 0:
self.screen.blit(text,(220,70))
self.delay -= 1
if self.delay == -20:
self.delay = 20;
def draw_life(self):
life=GStI.ships_left
font = pygame.font.Font("fonts/TianGeKaiTi.TTF",30)
text = font.render("生命:",True,(0,206,206))
self.screen.blit(text,(20,55))
i=0
while i<=life:
self.screen.blit(self.img_mini,(100+40*i,60,40,40))
i+=1
def draw_bullet(self):
BI=returnbattle()
font = pygame.font.Font("fonts/TianGeKaiTi.TTF",30)
if GSeI.weapon!=1:#激光枪显示时间,其他显示剩余子弹数量
number= GSeI.bullets_allowed-len(BI.bullets)
text = font.render("子弹:",True,(0,206,206))
self.screen.blit(text,(20,100))
i=0
while i<=number:
self.screen.blit(self.bullet_mini,(150+15*i,100,12,40))
i+=1
else:#如果是激光枪,则显示剩余时间/充能时间
text=''
pygame.draw.rect(self.screen,[0,206,206],(130,116,105,10),3)
if GStI.shotgun_active==False:#如果武器未打开,则显示剩余充能时间
prop=100-GSeI.charge_left/GSeI.charge_time*100
text = font.render("Charge:",True,(10,240,10))
pygame.draw.line(self.screen,[10,240,20],(132,120),(132+prop,120),6)
else:
prop=GSeI.left_time/GSeI.max_time*100
text = font.render("Release:",True,(0,206,206))
pygame.draw.line(self.screen,[240,120,88],(132,120),(132+prop,120),6)
self.screen.blit(text,(20,100))
def draw_score(self):#显示积分 金币 道具
BI=returnbattle()
font = pygame.font.Font("fonts/TianGeKaiTi.TTF",30)
text=font.render("积分:"+standardlize(BI.score),True,(0,206,206))
self.screen.blit(text,(20,20))
if GStI.current_checkpoint==4:
if BI.gold==0:#显示子弹数量和 时间
text=font.render("时间:"+str(int(BI.time))+'s',True,(0,206,0))
self.screen.blit(text,(170,20))
else:
text=font.render("金币转化为积分中",True,(random.randint(0,255),random.randint(0,255),random.randint(0,255)))
self.screen.blit(text,(300,20))
else:
text=font.render("金币:"+standardlize(BI.gold),True,(255,215,0))
self.screen.blit(text,(170,20))
if GStI.current_checkpoint%2==1:
tool=['无','清屏','屏障','超级加倍卡','中娅沙漏','幽灵疾步','虚弱']
text=font.render("道具:"+tool[GSeI.use],True,(0,110,255))
self.screen.blit(text,(20,160))
text=[]
prop=[]
if GSeI.ding>0:
text.append('金身:')
prop.append(GSeI.ding/3*100)
if GSeI.sou>0:
text.append('疾步:')
prop.append(GSeI.sou/7*100)
if GStI.wudi==True:#如果处在无敌状态 则同时显示还有多少时间
text.append("无敌:")
prop.append(GSeI.wudi_left/10*100)
if GSeI.xuruo>0:
text.append('虚弱:')
prop.append(GSeI.xuruo/5*100)
if GSeI.shufu>0:
text.append('束缚:')
prop.append(GSeI.shufu/3*100)
if GSeI.updown>0:
text.append('颠倒:')
prop.append(GSeI.updown/10*100)
index=0
while index=1 and len_info>=len(self.info)-15:#最多显示15条
self.print_text(self.info[len_info-1],50,730-20*(len(self.info)-len_info),rgb=(255,255,255),texttype='fangsong',textsize=14)
len_info-=1
def standardlize(num):
if num>=pow(10,9):
num=round(num/pow(10,9),1)
return str(num)+'g'
elif num>=pow(10,6):
num=round(num/pow(10,6),1)
return str(num)+'m'
elif num>=pow(10,3):
num=round(num/pow(10,3),1)
return str(num)+'k'
else:
return str(round(num))
2.普通敌机类Aliens.py:
第一章/第二章/第三章常见的地方单位,结构简单。
第一、二章中碰到本机子弹就死亡,第三章中拥有血条且发射子弹。发射子弹通过元素time控制,并在Battle内发射。check_edges函数返回这个单位是否越界。在初始化函数中会随机敌机的位置、方向、速度等,并在刷新函数中根据速度等更新位置。
import pygame
import random
import math
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Logic.GameStates import GStI
from Codes.Base.Screen import SI
from Codes.Common.DrawBase import DrawOn,DCI
class Alien(Sprite,DrawOn):
def __init__(self):
super(Alien, self).__init__()
super(Alien,self).definePriority(3)
self.priority=3
self.screen=SI.screen
self.image_ = pygame.image.load('images/alien.png').convert_alpha()
self.image_ = pygame.transform.scale(self.image_,(int(GSeI.aliens_size),int(GSeI.aliens_size)))
self.rect = self.image_.get_rect()
self.dir=random.randint(30,150)#运动的偏转角度 取值为30度到150度
self.theta=self.dir*math.pi/180#转为弧度制 便于计算
self.image=pygame.transform.rotate(self.image_, 90-self.dir)
self.v=random.uniform(GSeI.aliens_v_min,GSeI.aliens_v_max)#初始速度
self.a=random.uniform(1,1.01)#加速度
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.rect.center=(random.randint(20,GSeI.screen_width-20),30)#随机生成点的位置
self.blood=50
self.x = float( self.rect.x )
self.y = float( self.rect.y )
self.time=0 #生存时间 每次update+1 每%4为1时候 发射子弹
def draw(self):
self.screen.blit(self.image, self.rect)
if GStI.current_checkpoint==3:
self.drawBlood()
def drawBlood(self):
if self.blood>=0:
blood=self.blood/50
if blood >=0.3:
blood_color=[0,255,0]
else:
blood_color=[255,0,0]
pygame.draw.line(self.screen,[0,0,0],(self.rect.left,self.rect.top-5),(self.rect.right,self.rect.top-5),3)
pygame.draw.line(self.screen,blood_color,(self.rect.left,self.rect.top-5),(self.rect.left+self.rect.width*blood,self.rect.top-5),3)
def preDraw(self):
DCI.add(self)
def update(self,delta):
if GSeI.ding<=0:
self.x+=math.cos(self.theta)*self.v
self.y+=math.sin(self.theta)*self.v
self.v*=self.a
self.rect.x =self.x
self.rect.y=self.y
self.rect.center=(self.x,self.y)
self.time+=1
if GStI.current_checkpoint==2:
if self.rect.left <= 0 or self.rect.right >= 1200: #碰壁之后掉头
self.kill()
self.preDraw()
def check_edges(self):
screen_rect =SI.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <=0:
return True
3.普通子弹类Bullets:
为了节省时间,本机的普通子弹和敌机(不包括BOSS)发射的子弹使用同一类,通过初始化的输入参数hostkind控制,更新函数同理。通过判断hostkind的值来区分本机子弹和敌机子弹。
import pygame
import math
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
class Bullet(Sprite,DrawOn):
def __init__(self):
super(Bullet, self).__init__()
super(Bullet,self).definePriority(3)
def init(self,host,theta,hostkind):#hostkind=1 机主子弹 hostkind=0 敌机
self.screen = SI.screen
if hostkind==1:
self.image = pygame.image.load('images/ship_bullet.png').convert_alpha()
self.image = pygame.transform.scale(self.image,\
(int(GSeI.bullet_width),int(GSeI.bullet_height)))
self.speed_factor = GSeI.bullet_speed_factor
else:
self.image = pygame.image.load('images/bullet.png').convert_alpha()
self.image = pygame.transform.scale(self.image,\
(int(GSeI.alien_bullet_width),int(GSeI.alien_bullet_height)))
self.speed_factor =GSeI.alien_bullet_speed
self.image=pygame.transform.rotate(self.image, 90-theta)
self.rect = self.image.get_rect()
self.rect.centerx = host.rect.centerx
self.rect.top = host.rect.top
self.y = float(self.rect.y)
self.x = float(self.rect.x)
self.theta=theta*math.pi/180
def update(self,delta,host):#host=1 机主 host=0 敌机
if host==1 or GSeI.ding<=0:
self.y-=self.speed_factor*delta*math.sin(self.theta)
self.x-=self.speed_factor*delta*math.cos(self.theta)
self.rect.y=self.y
self.rect.x=self.x
self.preDraw();
def preDraw(self):
DCI.add(self)
def draw(self):
self.screen.blit(self.image, self.rect)
在之后的设计开发阶段里,加入了大量的其他类,如BOSS、BOSS子弹、超级子弹、Bonus、陨石、流星、敌机阵列、Bonus组、三种新型武器、三种敌对子弹等,设计理念与以上三类大同小异,因此不在此过多介绍,贴出其中部分代码:
Alien_Boss.py:
第二章敌对单位BOSS,拥有血量,会发射大量子弹。
import pygame
from Codes.Kinds.Boss_Bullet import Boss_Bullet
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
from Codes.Base.GameSettings import GSeI
class Alien_Boss(pygame.sprite.Sprite,DrawOn):
def __init__(self):
super(Alien_Boss,self).__init__()
super(Alien_Boss,self).definePriority(3)
self.screen=SI.screen
image = pygame.image.load("images/alien.png").convert_alpha()
rect = image.get_rect()
self.image = pygame.transform.scale(image,(int(rect.width * 0.2),\
int(rect.height * 0.2)))
self.rect = self.image.get_rect()
self.blood = 50
self.active = True
self.rect.bottom = 0 - self.rect.height
self.rect.left = (1200 - self.rect.width) // 2
self.mask = pygame.mask.from_surface(self.image)
self.speed = 3
self.bullets = pygame.sprite.Group()
self.bg_size =[GSeI.screen_width,GSeI.screen_height]
self.go_down=True
def update(self):
if self.rect.top <=30:
self.go_down=True
if self.rect.top>=100:
self.go_down=False
if self.rect.top <= 30:
self.rect.top += abs(self.speed)
else:
if self.go_down:
self.rect.top += abs(self.speed)
else:
self.rect.top -= abs(self.speed)
if self.rect.right >= self.bg_size[0] or self.rect.left <= 0:
self.speed = -self.speed
self.rect.left += self.speed #BOSS先下落到一定距离,之后在一直左右移动
self.preDraw()
def drawBlood(self,screen):
if self.blood >= 0:
blood = self.blood / 50
if blood > 0.3:
blood_color = [0,255,0]
else:
blood_color = [255,0,0]
pygame.draw.line(screen,[0,0,0],(self.rect.left,self.rect.top -5),
(self.rect.right,self.rect.top - 5),3)
pygame.draw.line(screen,blood_color,(self.rect.left,self.rect.top -5),\
(self.rect.left + self.rect.width * blood,self.rect.top -5),3) #画血条
def shot(self):
for angle in range(-90,120,15):
b = Boss_Bullet(self.rect,angle)
self.bullets.add(b)
def draw(self):
self.screen.blit(self.image, self.rect)
self.drawBlood(self.screen)
def preDraw(self):
DCI.add(self)
Aliens_Group、Bonus、Stone、Meteor等几乎一样,只是插图和大小、速度等不一致,只列出一个:
Stone.py:
import pygame
import random
import math
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Base.Screen import SI
from Codes.Common.DrawBase import DrawOn,DCI
class Stone(Sprite,DrawOn):
def __init__(self):
super(Stone, self).__init__()
super(Stone,self).definePriority(3)
self.screen=SI.screen
self.image = pygame.image.load('images/stone.png').convert_alpha()
self.scale=random.randint(80,160)
self.image = pygame.transform.scale(self.image,(self.scale,self.scale))
self.r=random.randint(30,150)
self.image=pygame.transform.rotate(self.image, self.r)
self.rect = self.image.get_rect()
self.dir=random.randint(70,110)#运动的偏转角度 取值为30度到150度
self.theta=self.dir*math.pi/180#转为弧度制 便于计算
self.v=random.uniform(1,2)#总速度为100-300
self.a=random.uniform(1,1.01)#加速度
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.rect.center=(random.randint(10,GSeI.screen_width),30)#随机生成点的位置
self.x = float( self.rect.x )
self.y = float( self.rect.y )
def draw(self):
self.screen.blit(self.image, self.rect)
def preDraw(self):
DCI.add(self)
def update(self,delta):
self.x+=math.cos(self.theta)*self.v
self.y+=math.sin(self.theta)*self.v
self.v*=self.a
self.rect.x =self.x
self.rect.y=self.y
self.rect.center=(self.x,self.y)
self.preDraw()
def check_edges(self):
screen_rect =SI.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <=0:
return True
Boss_Bullet和Bullet很相似:
import pygame
import math
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
class Boss_Bullet(pygame.sprite.Sprite,DrawOn): #BOSS的子弹,初步想法为同时向不同方向发射子弹
def __init__(self,position,angle):
super(Boss_Bullet,self).__init__()
super(Boss_Bullet,self).definePriority(3)
self.speed = 5
self.angle = angle
self.screen=SI.screen
self.image = pygame.image.load("images/bullet.png").convert_alpha()
self.image = pygame.transform.rotate(self.image,angle)
self.rect = self.image.get_rect()
lenB = position.width // 2
self.rect.left = math.ceil(position.centerx + lenB * math.sin(math.radians(angle)))
self.rect.top = math.ceil(position.centery + lenB * math.cos(math.radians(angle)))
def update(self):
x_move = math.ceil(self.speed * math.sin(math.radians(self.angle)))
y_move = math.ceil(self.speed * math.cos(math.radians(self.angle)))
self.rect.left += x_move
self.rect.top += y_move
self.preDraw()
def draw(self):
self.screen.blit(self.image, self.rect)
def preDraw(self):
DCI.add(self)
特殊武器一——霰弹枪Shotgun:
似乎和Bullets也差不了太多。
import pygame
import math
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
class Bullet_Shotgun(Sprite,DrawOn):
def __init__(self):
super(Bullet_Shotgun, self).__init__()
super(Bullet_Shotgun,self).definePriority(3)
def init(self,host,theta):
self.screen = SI.screen
self.image = pygame.image.load('images/bullet_shotgun.png').convert_alpha()
self.image = pygame.transform.scale(self.image,(int(GSeI.bullet_width),int(GSeI.bullet_height)))
self.dir=theta#倾角,默认为90度
self.image=pygame.transform.rotate(self.image, 90-self.dir)
self.rect = self.image.get_rect()
self.rect.centerx = host.rect.centerx
self.rect.top = host.rect.top
self.y = float(self.rect.y)
self.x = float(self.rect.x)
self.speed_factor = GSeI.bullet_speed_factor
def update(self,delta):
self.theta=self.dir*math.pi/180
self.y-=self.speed_factor*delta*math.sin(self.theta)
self.x-=self.speed_factor*delta*math.cos(self.theta)
self.rect.y=self.y
self.rect.x=self.x
self.preDraw()
def preDraw(self):
DCI.add(self)
def draw(self):
self.screen.blit(self.image, self.rect)
特殊武器二——榴弹枪Bullet_Shotgun:
这个和Bullets除了贴图、大小不一样外其他基本一致。
特殊武器三——激光枪Bullet_Light:
这个和其他子弹有所不同,激光波不太好用子弹移动来实现,所以做了个激光的静态贴图来模拟动态激光,子弹设置为在一段时间内不断释放,初始化函数中贴图为一张超过屏幕的光条,刷新函数只需要根据飞机的位置更新其左右位置和贴图的下部位置即可。
import pygame
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
class Bullet_Light(Sprite,DrawOn):
def __init__(self):
super(Bullet_Light,self).__init__()
super(Bullet_Light,self).definePriority(30)
def init(self,host):
self.screen = SI.screen
self.image = pygame.image.load('images/flow.jpg').convert_alpha()
self.image = pygame.transform.scale(self.image,(int(GSeI.light_width),int(GSeI.light_height)))
self.rect = self.image.get_rect()
self.rect.centerx = host.rect.centerx
self.rect.bottom = host.rect.bottom
self.y = float(self.rect.y)
self.x = float(self.rect.x)
self.speed_factor = GSeI.bullet_speed_factor
def update(self,delta,host):
self.rect.y=self.y
self.rect.x=host.rect.x+60-0.5*GSeI.light_width
self.rect.bottom = host.rect.top
self.preDraw();
def preDraw(self):
DCI.add(self)
def draw(self):
self.screen.blit(self.image, self.rect)
子弹雨Bullet_Barrage:
第四章地方单位的主力输出,在初始化函数中随机出现在四边,其他相同。
import pygame
import math
import random
from pygame.sprite import Sprite
from Codes.Base.GameSettings import GSeI
from Codes.Common.DrawBase import DrawOn,DCI
from Codes.Base.Screen import SI
class Bullet_Barrage(Sprite,DrawOn):
def __init__(self):
super(Bullet_Barrage, self).__init__()
super(Bullet_Barrage,self).definePriority(3)
def init(self):
self.screen = SI.screen
self.image = pygame.image.load('images/bullet.png').convert_alpha()
self.image = pygame.transform.scale(self.image,\
(int(GSeI.alien_bullet_width),int(GSeI.alien_bullet_height)))
pos_x,pos_y=0,0
t=random.randint(0,3)#四个边 左下右上
if t%2==0:#左右
pos_y=random.randint(30,800)
if t==0:
pos_x=0
self.theta=random.randint(135,225)
else:
pos_x=1200
self.theta=random.randint(315,405)
else:
pos_x=random.randint(0,1200)
if t==1:
pos_y=800
self.theta=random.randint(45,135)
else:
pos_y=30
self.theta=random.randint(225,315)
self.image=pygame.transform.rotate(self.image, 90-self.theta)
self.rect = self.image.get_rect()
self.rect.bottomleft=(pos_x,pos_y)
self.y = float(self.rect.y)
self.x = float(self.rect.x)
self.speed_factor = GSeI.bullet_speed_factor
self.theta=self.theta*math.pi/180
def update(self,delta,host):#host=1 机主 host=0 敌机
v_delete=GSeI.xuruo*(5-GSeI.xuruo)/6.25
if host==1 or GSeI.ding<=0:
self.y-=self.speed_factor*delta*math.sin(self.theta)*(1-v_delete)
self.x-=self.speed_factor*delta*math.cos(self.theta)*(1-v_delete)
self.rect.y=self.y
self.rect.x=self.x
self.preDraw();
def preDraw(self):
DCI.add(self)
def draw(self):
self.screen.blit(self.image, self.rect)
反弹弹Bullet_Bound:
敌对单位,到达边缘后反弹,其他相同,其check_edge函数更新为:
def check_edges(self):
screen_rect =SI.screen.get_rect()
if self.rect.right >= screen_rect.right or self.rect.left <=0 :
return 1#theta-pi-thepa
elif self.rect.bottom >= screen_rect.bottom or self.rect.top <=0 :
return 2#theta=2*pi-theta
在Battle里控制,根据不同的返回值更改反弹。也可以在更新函数中调用。
跟踪弹:Bullet_Track:
第四章中敌方稳定指向性输出单位,每次刷新的朝向为当前飞机的位置,其他相同,其更新函数为:
def update(self,delta,host):
if GSeI.ding<=0:
distance_x=host.rect.centerx-self.x
distance_y=host.rect.centery-self.y
self.y+=self.speed_factor*delta*distance_y/math.sqrt(distance_x**2+distance_y**2)
self.x+=self.speed_factor*delta*distance_x/math.sqrt(distance_x**2+distance_y**2)
self.rect.y=self.y
self.rect.x=self.x
self.preDraw()
其中,host为飞机。
接下来介绍不同界面。