目标:实现子弹的花样玩法,不同的子弹类型(image),不同的发射方式(speed,angle),不同的子弹数量。
前面几篇文字,已经实现了子弹的不同特性,组合下就能开启子弹的花样年华。
想了两个方案,一个方案是直接在bullet类中实现上述功能,设置参数来决定那种子弹类型;一个是bullet只作为基本功能实现,另外建立一个类,继承至bullet,然后扩展其他功能。感觉还是第二种好些,因为第一种方案不能实现多数量的子弹。
bullet.py 基本的子弹功能,代码如下:
import pygame
import math
import random
class Bullet(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load('images/bullet0.png')
self.rect = self.image.get_rect()
self.x_speed = 0.00
self.y_speed = 2.00
self.angle = 0
#会自动调用
def update(self):
self.rect.x += self.x_speed
self.rect.y += self.y_speed
# 可以用传递 scene来计算屏幕大小,演示用就简单些吧。
if (self.rect.x < 0 or self.rect.y < 0 or
self.rect.x >480 or self.rect.y > 860):
# print(self.rect.x)
#超过屏幕自动删除
self.kill()
#为了和飞机的位置配合,需要设置初始位置
def set_pos(self,x, y):
self.rect.x = x
self.rect.y = y
# 为了跟踪弹用的
def get_pos(self):
return (self.rect.x,self.rect.y)
def set_speed(self,speed, angle = 0):
self.angle = math.pi * angle/180
self.x_speed = speed * math.cos(self.angle)
self.y_speed = speed * math.sin(self.angle)
建立BulletFactor类,来实现子弹的复杂功能 bulletfactor.py,代码如下:
from bullet import *
class BulletFactor(Bullet):
def __init__(self):
Bullet.__init__(self)
# pygame.sprite.Sprite.__init__(self)
#下面两条代码不能少,sprite初始化需要
self.image = pygame.image.load('images/bullet0.png')
self.rect = self.image.get_rect()
self.motion_type = 0
self.image_type = 0
#多个子弹时需要用到Group
#发现Group.add居然能添加Group,不需要逐个sprite添加。
self.bullets = pygame.sprite.Group()
#设置不同子弹图片,后期可以添加攻击力等
def set_image_type(self,type = 0):
self.image_type = type
if type == 0:
self.image = pygame.image.load('images/bullet0.png')
elif type == 1:
self.image = pygame.image.load('images/bullet1.png')
elif type == 2:
self.image = pygame.image.load('images/bullet2.png')
elif type == 3:
self.image = pygame.image.load('images/bullet3.png')
else:
pass
#设置子弹的行动方式
def set_motion(self, type = 0):
self.motion_type = type
# 向下直射
if self.motion_type == 0:
self.set_speed(2, 90)
#向上直射
elif self.motion_type == 1:
self.set_speed(2, -90)
#360度四周发散
elif self.motion_type == 2:
for angle in range(0, 360 , 10):
bullet = Bullet()
bullet.image = self.image
#位置可以调用时传入
bullet.set_pos(self.rect.x, self.rect.y)
bullet.set_speed(3, angle)
self.bullets.add(bullet)
# print(self.bullets)
else:
pass
main.py里测试
import pygame
from bullet import *
from sys import exit
import random
from pygame import Vector2
from bulletfactor import *
vect = pygame.math.Vector2
#定义屏幕类
class MainScene(object):
#初始化
def __init__(self):
pygame.init()
self.size = (480,860)
self.scene = pygame.display.set_mode(self.size)
pygame.display.set_caption("自学飞机大战--V0.98")
self.image = pygame.image.load('images/bg.png')
self.bullet_sprite = pygame.sprite.Group()
bullet_enemy = BulletFactor()
bullet_enemy.set_image_type(1)
self.bullet_sprite.add(bullet_enemy)
bullet_hero = BulletFactor()
bullet_hero.set_image_type(2)
bullet_hero.set_pos(200,660)
bullet_hero.set_motion(type = 1)
self.bullet_sprite.add(bullet_hero)
bullet_boss = BulletFactor()
bullet_boss.set_image_type(0)
bullet_boss.set_pos(200,600)
bullet_boss.set_motion(2)
self.bullet_sprite.add(bullet_boss.bullets)
#绘制各个元素
def drawElements(self):
self.scene.blit(self.image,(0,0))
self.bullet_sprite.draw(self.scene)
#处理键盘和鼠标相应
#只是编写了子弹模块,那么跟踪弹在这里处理算了,
def handleEvent(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.MOUSEMOTION:
# 获得鼠标点击三个按钮的点击情况(1,0,0)
# 如果第一个参数为1,表示左键被按下
# 如果第二个参数为1,表示滚轮被按下
# 如果第三个参数为1,表示右键被按下
buttons = pygame.mouse.get_pressed()
# 我们只处理左键被按下的情况
if buttons[0]:
pass
# 注释的代码为跟踪弹的实现方式
# 获得拖动鼠标的拖动位置
# pos_mouse = pygame.mouse.get_pos()
# pos1 = vect(pos_mouse[0], pos_mouse[1])
# for bullet in self.bullet_sprite.sprites():
# pos_bullet = bullet.get_pos()
# pos2 = vect(pos_bullet[0],pos_bullet[1])
# pos0 = vect(0,0)
# pos = pos1 - pos2
# angle = pos0.angle_to(pos)
# 图像转不好# bulleted = pygame.transform.rotate(self.image ,angle)
# bullet.set_speed(5,angle)
#运行主程序
def runScene(self):
while True:
self.drawElements()
self.handleEvent()
self.bullet_sprite.update()
pygame.display.update()
# pygame.time.delay(100)
if __name__ == '__main__':
mainScene = MainScene()
mainScene.runScene()
效果如下: