为什么我会得到第二张精灵图片,它不会旋转而且不应该出现在那里?
Why am I getting a second image of sprite that won't rotate and shouldn't be there?
我正在尝试创建一个从我的火箭飞船后部出来的 TractorBeam(或推力),当然,精灵将随着火箭飞船一起旋转。它似乎工作正常,但我得到了同一个 TractorBeam 图像的第二张图像,该图像在火箭船旋转和 TractorBeam 图像旋转时保持在相同的垂直位置。我对它的编程与从前面出来的激光相同(除了不同的速度、寿命等),而且激光似乎没有这个未知的第二个图像。
关于我哪里出错或如何消除第二个不需要的图像的任何建议?
import pygame as pg
import os
from random import uniform
vec = pg.math.Vector2
TITLE = "GRAVITAR"
WIDTH = 800
HEIGHT = 600
FPS = 60
GREY = (211, 211, 211)
# Player properties
ROCKET_SHIP = 'Images/Rocket_Ship.png'
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.00
PLAYER_GRAV = 0.1
PLAYER_ROT_SPEED = 200
LASER = 'Images/Laser_1.png'
LASER_SPEED = 400
LASER_LIFETIME = 1500
LASER_RATE = 150
LASER_COUNT = 1
LASER_SPREAD = 3
LASER_OFFSET = vec(20, -1)
TRACTOR_BEAM = 'Images/TractorBeam_1.png'
TRACTOR_BEAM_SPEED = 400
TRACTOR_BEAM_LIFETIME = 25
TRACTOR_BEAM_RATE = 25
TRACTOR_BEAM_COUNT = 1
TRACTOR_BEAM_SPREAD = 1
TRACTOR_BEAM_OFFSET = vec(-12, 0)
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = game.rocket_ship
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.rot = 90
self.last_shot = 0
self.thrust = False
self.frame = 0
self.last_update = 0
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.vel += vec(PLAYER_ACC, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
if keys[pg.K_t]:
self.tractor_beam()
self.vel += self.acc + self.vel * PLAYER_FRICTION
max_vel = 1.75
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
self.pos += self.vel
def shoot(self):
now = pg.time.get_ticks()
if now - self.last_shot > LASER_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot)
pos = self.pos + LASER_OFFSET.rotate(-self.rot)
for i in range(LASER_COUNT):
spread = uniform(-LASER_SPREAD, LASER_SPREAD)
Laser(self.game, pos, dir.rotate(spread), self)
def tractor_beam(self):
now = pg.time.get_ticks()
if now - self.last_shot > TRACTOR_BEAM_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot + 180)
pos = self.pos + TRACTOR_BEAM_OFFSET.rotate(-self.rot)
spread = uniform(-TRACTOR_BEAM_SPREAD, TRACTOR_BEAM_SPREAD)
TractorBeam(self.game, pos, dir.rotate(spread), self)
def update(self):
self.get_keys()
self.rot = (self.rot + self.rot_speed * self.game.dt) % 360
self.image = pg.transform.rotate(self.game.rocket_ship, self.rot)
self.rect = self.image.get_rect()
self.pos += self.vel * self.game.dt
self.rect.center = self.pos
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
if self.pos.y > HEIGHT:
self.pos.y = 0
if self.pos.y < 0:
self.pos.y = HEIGHT
class Laser(pg.sprite.Sprite):
def __init__(self, game, pos, dir, player):
self.groups = game.all_sprites # , game.bullet
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.player = player
self.image = game.laser
self.rect = self.image.get_rect()
self.pos = vec(pos)
self.rect.center = pos
self.vec = dir * LASER_SPEED * uniform(0.9, 1.1)
self.spawn_time = pg.time.get_ticks()
self.rot = 90
def update(self):
self.image = pg.transform.rotate(self.game.laser, self.player.rot - 90)
self.rect = self.image.get_rect()
self.pos += self.vec * self.game.dt
self.rect.center = self.pos
if pg.time.get_ticks() - self.spawn_time > LASER_LIFETIME:
self.kill()
class TractorBeam(pg.sprite.Sprite):
def __init__(self, game, pos, dir, player):
self.groups = game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.player = player
self.image = game.tractor_beam
self.rect = self.image.get_rect()
self.pos = vec(pos)
self.rect.center = pos
self.pos = vec(pos)
self.vec = dir * TRACTOR_BEAM_SPEED * uniform(0.9, 1.1)
self.spawn_time = pg.time.get_ticks()
self.rot = 0
def update(self):
self.image = pg.transform.rotate(self.game.tractor_beam, self.player.rot - 90)
self.rect = self.image.get_rect()
self.pos += self.vec * self.game.dt
self.rect.center = self.pos
if pg.time.get_ticks() - self.spawn_time > TRACTOR_BEAM_LIFETIME:
self.kill()
class Game:
def __init__(self):
# Initialize pygame and create window
pg.init()
pg.mixer.init()
pg.key.set_repeat(10, 50)
os.environ['SDL_VIDEO_WINDOW_POS'] = '568, 101'
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.load_data()
def load_data(self):
self.rocket_ship = pg.image.load(ROCKET_SHIP).convert_alpha()
self.rocket_ship = pg.transform.scale(self.rocket_ship, (36, 18))
self.laser = pg.image.load(LASER).convert_alpha()
self.laser = pg.transform.scale(self.laser, (3, 8))
self.tractor_beam = pg.image.load(TRACTOR_BEAM).convert_alpha()
self.tractor_beam = pg.transform.scale(self.tractor_beam, (30, 30))
def new(self):
# Start a new game
self.all_sprites = pg.sprite.Group()
self.lasers = pg.sprite.Group()
self.tractorBeams = pg.sprite.Group()
self.player = Player(self, WIDTH / 2, HEIGHT / 4)
self.all_sprites.add(self.player)
self.run()
def run(self):
# Game loop
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000.0
self.events()
self.update()
self.draw()
def update(self):
# Game loop update
self.all_sprites.update()
def events(self):
# Game loop events
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
def draw(self):
# Game loop draw
pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
self.screen.fill(GREY)
self.all_sprites.draw(self.screen)
# After drawing everything, flip display
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
似乎有 2 个牵引光束,但实际上只有一个。但是,TractorBeam
实例的 update
方法在绘制它的第一帧中没有被调用。它是在 player
的 Group 的 update
循环中构建的。在 update
期间添加到 Group 的 Sprites 不会在这一帧更新,而是在下一帧更新。
您必须手动调用 update
一次:
class Player(pg.sprite.Sprite):
# [...]
def tractor_beam(self):
now = pg.time.get_ticks()
if now - self.last_shot > TRACTOR_BEAM_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot + 180)
pos = self.pos + TRACTOR_BEAM_OFFSET.rotate(-self.rot)
spread = uniform(-TRACTOR_BEAM_SPREAD, TRACTOR_BEAM_SPREAD)
beam = TractorBeam(self.game, pos, dir.rotate(spread), self)
beam.update()
激光也有同样的问题,但几乎没有引起注意。
我正在尝试创建一个从我的火箭飞船后部出来的 TractorBeam(或推力),当然,精灵将随着火箭飞船一起旋转。它似乎工作正常,但我得到了同一个 TractorBeam 图像的第二张图像,该图像在火箭船旋转和 TractorBeam 图像旋转时保持在相同的垂直位置。我对它的编程与从前面出来的激光相同(除了不同的速度、寿命等),而且激光似乎没有这个未知的第二个图像。
关于我哪里出错或如何消除第二个不需要的图像的任何建议?
import pygame as pg
import os
from random import uniform
vec = pg.math.Vector2
TITLE = "GRAVITAR"
WIDTH = 800
HEIGHT = 600
FPS = 60
GREY = (211, 211, 211)
# Player properties
ROCKET_SHIP = 'Images/Rocket_Ship.png'
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.00
PLAYER_GRAV = 0.1
PLAYER_ROT_SPEED = 200
LASER = 'Images/Laser_1.png'
LASER_SPEED = 400
LASER_LIFETIME = 1500
LASER_RATE = 150
LASER_COUNT = 1
LASER_SPREAD = 3
LASER_OFFSET = vec(20, -1)
TRACTOR_BEAM = 'Images/TractorBeam_1.png'
TRACTOR_BEAM_SPEED = 400
TRACTOR_BEAM_LIFETIME = 25
TRACTOR_BEAM_RATE = 25
TRACTOR_BEAM_COUNT = 1
TRACTOR_BEAM_SPREAD = 1
TRACTOR_BEAM_OFFSET = vec(-12, 0)
class Player(pg.sprite.Sprite):
def __init__(self, game, x, y):
pg.sprite.Sprite.__init__(self)
self.game = game
self.image = game.rocket_ship
self.rect = self.image.get_rect()
self.rect.center = (x, y)
self.vel = vec(0, 0)
self.pos = vec(x, y)
self.rot = 90
self.last_shot = 0
self.thrust = False
self.frame = 0
self.last_update = 0
def get_keys(self):
self.rot_speed = 0
self.acc = vec(0, PLAYER_GRAV)
keys = pg.key.get_pressed()
if keys[pg.K_LEFT]:
self.rot_speed = PLAYER_ROT_SPEED
if keys[pg.K_RIGHT]:
self.rot_speed = -PLAYER_ROT_SPEED
if keys[pg.K_UP]:
self.vel += vec(PLAYER_ACC, 0).rotate(-self.rot)
if keys[pg.K_SPACE]:
self.shoot()
if keys[pg.K_t]:
self.tractor_beam()
self.vel += self.acc + self.vel * PLAYER_FRICTION
max_vel = 1.75
self.vel[0] = max(-max_vel, min(max_vel, self.vel[0]))
self.vel[1] = max(-max_vel, min(max_vel, self.vel[1]))
self.pos += self.vel
def shoot(self):
now = pg.time.get_ticks()
if now - self.last_shot > LASER_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot)
pos = self.pos + LASER_OFFSET.rotate(-self.rot)
for i in range(LASER_COUNT):
spread = uniform(-LASER_SPREAD, LASER_SPREAD)
Laser(self.game, pos, dir.rotate(spread), self)
def tractor_beam(self):
now = pg.time.get_ticks()
if now - self.last_shot > TRACTOR_BEAM_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot + 180)
pos = self.pos + TRACTOR_BEAM_OFFSET.rotate(-self.rot)
spread = uniform(-TRACTOR_BEAM_SPREAD, TRACTOR_BEAM_SPREAD)
TractorBeam(self.game, pos, dir.rotate(spread), self)
def update(self):
self.get_keys()
self.rot = (self.rot + self.rot_speed * self.game.dt) % 360
self.image = pg.transform.rotate(self.game.rocket_ship, self.rot)
self.rect = self.image.get_rect()
self.pos += self.vel * self.game.dt
self.rect.center = self.pos
if self.pos.x > WIDTH:
self.pos.x = 0
if self.pos.x < 0:
self.pos.x = WIDTH
if self.pos.y > HEIGHT:
self.pos.y = 0
if self.pos.y < 0:
self.pos.y = HEIGHT
class Laser(pg.sprite.Sprite):
def __init__(self, game, pos, dir, player):
self.groups = game.all_sprites # , game.bullet
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.player = player
self.image = game.laser
self.rect = self.image.get_rect()
self.pos = vec(pos)
self.rect.center = pos
self.vec = dir * LASER_SPEED * uniform(0.9, 1.1)
self.spawn_time = pg.time.get_ticks()
self.rot = 90
def update(self):
self.image = pg.transform.rotate(self.game.laser, self.player.rot - 90)
self.rect = self.image.get_rect()
self.pos += self.vec * self.game.dt
self.rect.center = self.pos
if pg.time.get_ticks() - self.spawn_time > LASER_LIFETIME:
self.kill()
class TractorBeam(pg.sprite.Sprite):
def __init__(self, game, pos, dir, player):
self.groups = game.all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.game = game
self.player = player
self.image = game.tractor_beam
self.rect = self.image.get_rect()
self.pos = vec(pos)
self.rect.center = pos
self.pos = vec(pos)
self.vec = dir * TRACTOR_BEAM_SPEED * uniform(0.9, 1.1)
self.spawn_time = pg.time.get_ticks()
self.rot = 0
def update(self):
self.image = pg.transform.rotate(self.game.tractor_beam, self.player.rot - 90)
self.rect = self.image.get_rect()
self.pos += self.vec * self.game.dt
self.rect.center = self.pos
if pg.time.get_ticks() - self.spawn_time > TRACTOR_BEAM_LIFETIME:
self.kill()
class Game:
def __init__(self):
# Initialize pygame and create window
pg.init()
pg.mixer.init()
pg.key.set_repeat(10, 50)
os.environ['SDL_VIDEO_WINDOW_POS'] = '568, 101'
self.screen = pg.display.set_mode((WIDTH, HEIGHT))
pg.display.set_caption(TITLE)
self.clock = pg.time.Clock()
self.running = True
self.load_data()
def load_data(self):
self.rocket_ship = pg.image.load(ROCKET_SHIP).convert_alpha()
self.rocket_ship = pg.transform.scale(self.rocket_ship, (36, 18))
self.laser = pg.image.load(LASER).convert_alpha()
self.laser = pg.transform.scale(self.laser, (3, 8))
self.tractor_beam = pg.image.load(TRACTOR_BEAM).convert_alpha()
self.tractor_beam = pg.transform.scale(self.tractor_beam, (30, 30))
def new(self):
# Start a new game
self.all_sprites = pg.sprite.Group()
self.lasers = pg.sprite.Group()
self.tractorBeams = pg.sprite.Group()
self.player = Player(self, WIDTH / 2, HEIGHT / 4)
self.all_sprites.add(self.player)
self.run()
def run(self):
# Game loop
self.playing = True
while self.playing:
self.dt = self.clock.tick(FPS) / 1000.0
self.events()
self.update()
self.draw()
def update(self):
# Game loop update
self.all_sprites.update()
def events(self):
# Game loop events
for event in pg.event.get():
if event.type == pg.QUIT:
if self.playing:
self.playing = False
self.running = False
def draw(self):
# Game loop draw
pg.display.set_caption("{:.2f}".format(self.clock.get_fps()))
self.screen.fill(GREY)
self.all_sprites.draw(self.screen)
# After drawing everything, flip display
pg.display.flip()
def show_start_screen(self):
pass
def show_go_screen(self):
pass
g = Game()
g.show_start_screen()
while g.running:
g.new()
g.show_go_screen()
pg.quit()
似乎有 2 个牵引光束,但实际上只有一个。但是,TractorBeam
实例的 update
方法在绘制它的第一帧中没有被调用。它是在 player
的 Group 的 update
循环中构建的。在 update
期间添加到 Group 的 Sprites 不会在这一帧更新,而是在下一帧更新。
您必须手动调用 update
一次:
class Player(pg.sprite.Sprite):
# [...]
def tractor_beam(self):
now = pg.time.get_ticks()
if now - self.last_shot > TRACTOR_BEAM_RATE:
self.last_shot = now
dir = vec(1, 0).rotate(-self.rot + 180)
pos = self.pos + TRACTOR_BEAM_OFFSET.rotate(-self.rot)
spread = uniform(-TRACTOR_BEAM_SPREAD, TRACTOR_BEAM_SPREAD)
beam = TractorBeam(self.game, pos, dir.rotate(spread), self)
beam.update()
激光也有同样的问题,但几乎没有引起注意。