所以我回到制作游戏的过程中,我在游戏机制中进行编码(这是躲闪的子弹,我在制造子弹)子弹应该从顶部精灵(Minty)不断产生并不断扩散(相信我,我花了很多时间阅读和搜索东西。)这就是应该的样子:(顶部的精灵是对手,白色的小方块是玩家,顺便说一下,紫色圆圈是子弹)
应该如何:
但是它是这样的:
我只是不明白为什么会这样?
这是我的代码:
import sys
import time
import pygame
from pygame.locals import *
pygame.init()
#INITIALISE THE WINDOW.
#CONSTANTS ARE CAPITAL, VARIABLES ARE LOWERCASE
SCREENWIDTH = 1000
SCREENHEIGHT = 650
SCREENSIZE = [SCREENWIDTH, SCREENHEIGHT]
screen = pygame.display.set_mode(SCREENSIZE)
BG_COL = [255, 123, 67]
S1_COL = (0, 255, 188)
clock = pygame.time.Clock()
screen.fill(BG_COL)
pygame.draw.rect(screen, S1_COL,(50, 50, 900, 575), 0)
pygame.display.update()
clock.tick(60)
class Player(pygame.sprite.Sprite):
def __init__(self, sprite):
self.sprite = sprite
self.x = 445
self.y = 550
class Opponent(pygame.sprite.Sprite):
def __init__(self, sprite):
self.sprite = sprite
self.x = 445
self.y = 30
class Bullet:
def __init__(self, sprite, length, width):
self.sprite = sprite
self.x = 460
self.y = 50
self.length = length
self.width = width
self.area = self.sprite.get_rect(x=self.x, y=self.y)
self.area.clamp_ip((50, 50, 900, 575))
class BulletGroup(pygame.sprite.Group):
def __init__(self, typeof, numof):
self.typeof = typeof
self.numof = numof
self.listof = []
for i in range(0, self.numof):
self.listof.append(typeof)
player = Player(pygame.image.load("Sprites/player.png"))
Minty = Opponent(pygame.image.load("Sprites/minty.png"))
purple_glow = Bullet(pygame.image.load("Sprites/purple-glowey.png"), 70, 65)
test_bullets = BulletGroup(purple_glow, 5)
#make functions
def background(colour): #to make it easier to draw the background each time
screen.fill(BG_COL)
pygame.draw.rect(screen, colour,(50, 50, 900, 575), 0)
def handle_keys():
""" Handles Keys """
key = pygame.key.get_pressed()
dist = 2
if key[pygame.K_DOWN]: # down key
player.y += dist # move down
elif key[pygame.K_UP]: # up key
player.y -= dist # move up
if key[pygame.K_RIGHT]: # right key
player.x += dist # move right
elif key[pygame.K_LEFT]: # left key
player.x -= dist # move left
#MAIN GAME LOOP
running = True
while running:
for events in pygame.event.get():
if events.type == QUIT:
pygame.quit()
exit()
running = False
if events.type == KEYDOWN:
background(S1_COL)
#BULLETS:
def move_bullets(bullets, xchange, ychange):
#MOVE THE CLONED BULLETS IN ONE CONSTANT DIRECTION
for b in bullets.listof:
b.x += xchange
b.y += ychange
screen.blit(b.sprite, (b.x, b.y))
pygame.draw.rect(screen, S1_COL, b.area, 0)
xchange += 10
pygame.time.delay(50)
#STAGE1 MAKE
screen.blit(pygame.transform.scale(Minty.sprite, (130, 140)), [Minty.x, Minty.y])
for events in pygame.event.get():
screen.blit(pygame.transform.scale(Minty.sprite, (130, 140)), [Minty.x, Minty.y]) #i'm going to change image size on phone later on
print(test_bullets.listof[0].x)
print(test_bullets.listof[0].y)
#IF KEY PRESSED
#MOVE PLAYER SPRITE
screen.blit(player.sprite, (player.x, player.y))
handle_keys()
move_bullets(test_bullets, -10, 10)
pygame.display.update()
任何反馈,解释,编辑建议或类似内容将不胜感激。
答案 0 :(得分:3)
您应该按预期使用Sprite
类:至少定义一个image
和rect
属性,并将每个游戏对象的逻辑放入update
方法中。无需自己画图。
然后,您的主循环将变得非常清晰,而经典的三部分循环将按以下顺序进行:
这是它的外观(请注意我在解释某些内容时的注释):
import pygame
import itertools
pygame.init()
SCREENWIDTH = 1000
SCREENHEIGHT = 650
screen = pygame.display.set_mode([SCREENWIDTH, SCREENHEIGHT])
screen.fill((255, 123, 67))
pygame.draw.rect(screen, (0, 255, 188), (50, 50, 900, 575), 0)
# let's create a background surface that we can reuse instead of
# drawing manually to the screen
background = screen.copy()
clock = pygame.time.Clock()
class Player(pygame.sprite.Sprite):
# the player sprite is constant, so let's use a class variable
sprite = pygame.image.load("Sprites/player.png")
def __init__(self, *groups):
# we want to use sprites, so we have to call __init__ of the Sprite class
# groups is a list of groups we want this sprite to add to
super().__init__(*groups)
# the image of the sprite needs to be in an attribute called 'image'
self.image = Player.sprite
# for pygame to know where to draw the sprite, we need a 'rect' attribute
self.rect = self.image.get_rect(topleft=(445, 550))
def update(self):
# moving by keyboard is unique to the player class, so let's to this here
key = pygame.key.get_pressed()
dist = 3
# we just update our rect's position to move the sprite
# we should use vectors here, too, but for now this is good enough
if key[pygame.K_DOWN]:
self.rect.y += dist
elif key[pygame.K_UP]:
self.rect.y -= dist
if key[pygame.K_RIGHT]:
self.rect.x += dist
elif key[pygame.K_LEFT]:
self.rect.x -= dist
class Opponent(pygame.sprite.Sprite):
def __init__(self, sprite, *groups):
super().__init__(*groups)
self.image = sprite
self.rect = self.image.get_rect(topleft=(445, 30))
# we keep an additional attribute 'pos' to store the postion
# it's a vector so we can use some vector math
self.pos = pygame.Vector2(self.rect.topleft)
# we want to move the Opponent in a specific pattern
# so let's keep a list of points we want to move to
# 'cycle' will generate and "endless loop" of this points
self.path = itertools.cycle(((445, 30), (345, 235), (90, 115), (490, 80), (850, 250), (745, 110)))
# we can use 'next' to get the next position
self.next_point = pygame.Vector2(next(self.path))
# maybe we want to change the speed of the opponent
self.speed = 1
# we use ticks to store the milliseconds since the game started later
# this allows us to do thing over time
self.ticks = 1000
# a list of bullets we want to shoot later
self.queue = []
def update(self):
# so we want to move to a specific point
# we use some vector math to get the direction we have to move to
move = self.next_point - self.pos
move_length = move.length()
if move_length != 0:
# since 'move' is the vector between 'pos' and 'next_point'
# we have to normalize it so it just points into the right
# direction at a certain length instead of all the way from
# 'pos' and 'next_point'
move.normalize_ip()
move = move * self.speed
self.pos += move
# if we are already at the target position (or overshoot it)
# we take the next position from 'path'
if move.length() == 0 or move_length < self.speed:
self.next_point = pygame.Vector2(next(self.path))
# we update the 'rect' position so pygame draws the sprite at the right position on the screen
self.rect.topleft = self.pos
# so let's count some time. Every 3000ms passed, we want to shoot some bullets
if pygame.time.get_ticks() - self.ticks > 3000:
self.ticks = pygame.time.get_ticks()
self.shoot()
# see how much time passed since the last shooting
time_gone = pygame.time.get_ticks() - self.ticks
for bullet in self.queue:
# the first value of the tuples in the 'queue' describes when to shoot the bullet
if bullet[0] <= time_gone:
# create the bullet and add them to the 'sprites' and 'bullets' groups
# 'bullets' isn't used yet, but you can use it later for collision detection
Bullet(self.rect.center, bullet[1], sprites, bullets)
# now remove all bullets that have been fired
self.queue = [bullet for bullet in self.queue if bullet[0] > time_gone]
def shoot(self):
bullet_speed = 4
# this list describes the pattern of the attack
# the first value is the time when to shoot the bullet (afer X ms)
# the second value is the movement vector of the bullet
pattern = ((0, pygame.Vector2(-0.5, 1) * bullet_speed),
(0, pygame.Vector2( 0, 1) * bullet_speed),
(0, pygame.Vector2(0.5, 1) * bullet_speed),
(150, pygame.Vector2(-0.5, 1) * bullet_speed),
(150, pygame.Vector2( 0, 1) * bullet_speed),
(150, pygame.Vector2(0.5, 1) * bullet_speed),
(300, pygame.Vector2(-0.5, 1) * bullet_speed),
(300, pygame.Vector2( 0, 1) * bullet_speed),
(300, pygame.Vector2(0.5, 1) * bullet_speed))
self.queue = pattern
class Bullet(pygame.sprite.Sprite):
sprite = pygame.image.load("Sprites/purple-glowey.png")
def __init__(self, pos, direction, *groups):
super().__init__(*groups)
self.image = Bullet.sprite
self.rect = self.image.get_rect(topleft=pos)
self.direction = direction
self.pos = pygame.Vector2(self.rect.topleft)
def update(self):
# just move along the direction
self.pos += self.direction
self.rect.topleft = (self.pos.x, self.pos.y)
# if no longer on screen, remove from all groups
if not screen.get_rect().colliderect(self.rect):
self.kill()
sprites = pygame.sprite.Group()
bullets = pygame.sprite.Group()
player = Player(sprites)
Minty = Opponent(pygame.image.load("Sprites/minty.png"), sprites)
def main():
running = True
while running:
for events in pygame.event.get():
if events.type == pygame.QUIT:
return
# update all sprites, a.k.a. game logic
sprites.update()
# draw everything
screen.blit(background, (0, 0))
sprites.draw(screen)
pygame.display.update()
clock.tick(60)
if __name__ == '__main__':
main()
答案 1 :(得分:1)
您的问题出在BulletGroup
类中:您一直将相同的对象附加到列表中,因此实际上没有像您期望的那样有5个项目符号的列表,而是实际上有5个引用同一项目符号的列表。
当您在该列表上运行并更改坐标时,即在更改相同的项目符号并绘制相同的项目符号。
您应该使用copy
复制第一个项目符号。