目标:實作子彈的花樣玩法,不同的子彈類型(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()
效果如下:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL1UEVNhXSYp1c4dVYohmMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL3MzN3UDOyMjM2EzMwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)