Как я могу заставить своих спрайтов двигаться (вражеских спрайтов) самостоятельно? - PullRequest
1 голос
/ 30 апреля 2019

Мне нужно, чтобы мои вражеские спрайты, определенные в функции drawGrid, двигались, я бы хотел, чтобы они переместились к краю сетки (по горизонтали) и, достигнув конца сетки, они опустились бы на определенную величину и начали перемещать противоположное горизонтальное направление. (Как инопланетяне в космических захватчиках.)

Я пытался переместить их безрезультатно.

import pygame
pygame.init()

window = pygame.display.set_mode((650, 630))

pygame.display.set_caption("PeaShooters")

avatar = pygame.image.load('Sprite 1 Red.png')
enemy1 = pygame.image.load('Sprite 3 Red.png')
enemy2 = pygame.image.load('Sprite 3 Yellow.png')
background = pygame.image.load('Bg.jpg')
white = (255, 255, 255)

class player(object):
    def __init__(self, x, y, width, height, shots):
        self.x = 300
        self.y = 500
        self.width = 40
        self.height = 60
        self.vel = shots


def drawGrid():
    window.blit(background, (0,0))
    window.blit(enemy1, (en.x, en.y))
    window.blit(enemy1, (200, en.y))
    window.blit(enemy1, (100, en.y))
    window.blit(enemy1, (400, en.y))
    window.blit(enemy1, (500, en.y))
    window.blit(enemy1, (en.x, en.y))
    window.blit(enemy2, (50, 200))
    window.blit(enemy2, (150, 200))
    window.blit(enemy2, (250, 200))
    window.blit(enemy2, (350, 200))
    window.blit(enemy2, (450, 200))
    window.blit(enemy2, (530, 200))
    window.blit(avatar, (av.x, av.y))
    pygame.draw.line(window, white, [50,50], [50, 600], 5)
    pygame.draw.line(window, white, [50,50], [600, 50], 5)
    pygame.draw.line(window, white, [600,600], [600, 50], 5)
    pygame.draw.line(window, white, [50,600], [600, 600], 5)
    pygame.draw.line(window, white, [50,450], [600, 450], 5)

    for bullet in bullets:
        bullet.draw(window)
    pygame.display.update()


class shots(object):
    def __init__(self, x, y, radius, colour):
        self.x = x
        self.y = y
        self.radius = radius
        self.colour = colour
        self.vel = shots

    def draw(self, window):
        pygame.draw.circle(window, self.colour, (self.x,self.y), self.radius)

class enemy(object):

    def __init__(self, x, y, width, height, end):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.end = end
        self.path = [self. x, self.end]
        self.vel = 4

    def draw(self,window):
        self.move()

    def move(self):
        pass

av = player(300, 500, 40, 60, 9)
en = enemy(300, 100, 40, 60, 500)

bullets = []
running = True
while running:
    pygame.time.delay(100) 

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    for bullet in bullets:
        if bullet.y < 600 and bullet.y > 70:
            bullet.y -= 8
        else:
            bullets.pop(bullets.index(bullet))

    keys = pygame.key.get_pressed()

    if keys[pygame.K_w] and av.y > 440:
        av.y -= av.vel

    if keys[pygame.K_a] and av.x > 65:
        av.x -= av.vel

    if keys[pygame.K_s] and av.y < 535:
        av.y += av.vel

    if keys[pygame.K_d] and av.x < 530:
        av.x += av.vel

    if keys[pygame.K_SPACE]:
        if len(bullets) < 5:
            bullets.append(shots(round(av.x + av.width//2), round(av.y + av.height//2), 6, (0,0,0)))


    drawGrid()

window.blit(enemy, (en.x, en.y))
window.blit(avatar, (x,y))

pygame.quit()

Я ожидаю, что враги будут двигаться, как я описал, но они вообще не двигаются.

Ответы [ 2 ]

2 голосов
/ 30 апреля 2019

Вот несколько вещей, которые я хотел бы сделать, чтобы приблизиться к игре, которую вы ищете:

  1. Создать больше вражеских объектов

Прямо сейчас вы создаете 1враг тут: en = enemy(300, 100, 40, 60, 500) и просто киньте вражеские картинки на экран в кучу мест.Чтобы действительно использовать класс Enemy, я бы сделал что-то вроде этого:

enemiesList = []
for i in range (MAX_ENEMIES_I_WANT):
    enemiesList.append(enemy(300, 100*i, 40, 60, 500))

Примечание: вам нужно будет определить, где вы размещаете своих врагов по-разному, если вы хотите, чтобы они падали в определенную форму,Для традиционных космических захватчиков вы можете выполнить цикл дважды, один раз для координат y, один раз для x.

уничтожьте своих врагов из вашего класса врагов

Вместо того, чтобы делать то, что есть у вас сейчас, я бы добавил метод blitToScreen() в ваш класс врагов.Что-то вроде:

def BlitToScreen(self,screen):
    screen.blit(self.sprite, self.x, self.y)

Затем, перетаскивание всех ваших врагов на экран становится двумя строками:

for e in enemiesList:
    e.BlitToScreen(window)
Наконец, к вашему вопросу: если мы действительно подражаем космическим захватчикам, каждый враг перемещает одинаковое количество кадров в каждом кадре, чтобы мы могли вносить одинаковые изменения в каждый объект врага.

Если у вас есть frame номер, он будет выглядеть примерно так:

tomove = [0,0]
if(frame%100 == 99):
    tomove[0] += 50 # Move down
else if(frame/100%2 == 0):
    tomove[1] +=50 # Move right
else:
    tomove[1] -=50 # Move left

for e in enemies:
    e.x += tomove[0]
    e.y += tomove[1]

Надеюсь, это полезно для вас!

1 голос
/ 01 мая 2019

@ Ответ Хуга в основном охватывает основы того, что не так с кодом ОП, и как заставить его работать.

Однако OP действительно должен рассмотреть возможность использования класса спрайтов PyGame для каждого "вражеского" объекта (ну, на самом деле, всех объектов на самом деле). Да , изначально немного сложнее настроить, но он предоставляет настолько много дополнительных (предварительно оптимизированных) функций, что в противном случае вам пришлось бы кодировать.Это отнимает часть утомительной работы в программировании и позволяет тратить больше времени на написание интересной игры.

Преобразовать существующие объекты в спрайты довольно тривиально:

class Enemy( pygame.sprite.Sprite ):
    def __init__( self, bitmap, x, y, end=None ):
        pygame.sprite.Sprite.__init__( self )
        self.image  = bitmap
        self.rect   = bitmap.get_rect()
        self.rect.x = x
        self.rect.y = y
        self.vel    = 4
        self.end    = end

   def update():
       # TODO - handle any sort of sprite movement

Создайте группу спрайтов, согласно предложению @ Hoog, за исключением использования группы спрайтов для их удержания:

enemy_image1 = pygame.image.load('Sprite 3 Red.png')
enemy_image2 = pygame.image.load('Sprite 3 Yellow.png')

...

enemies_list = pygame.sprite.Group()
for j in range( ENEMY_LINE_COUNT ):
    for i in range( ENEMY_PER_LINE_COUNT ):
         enemy_x = 50 + ( i * 30 )
         enemy_y = 50 + ( j * 40 )
         enemies_list.append( Enemy( enemy_image1, enemy_x, enemy_y ) )

Перемещение и рисование можно легко обрабатывать в основном цикле, используя возможности (иeasy) группы Sprite:

while running:
    ...
    enemies_list.update()        # re-position the sprites
    enemies_list.draw( window )  # draw the entire sprite-group to the window
    ...

Вызов группы Sprite .update() (в основном цикле) вызовет функцию Enemy.update() для каждого спрайта, содержащегося в группе.

Это приводит нас к движению часть вашего вопроса.Давайте подумаем о том, как Space Invaders двигаются - справа налево, вниз, слева направо, вниз, больше скорости, повтор ... Для меня это звучит как программа;)

Итак, я предлагаю контролировать движение, напишите программу, которой должен следовать каждый захватчик:

# In Enemy.__init__() ~
self.move_program = 'rrrrrrrrrrrrrdllllllllllllds'  #TODO - make better
self.move_cursor  = 0

Где каждая буква self.move_program влияет на движение на каждом «тике».Это приводит нас к функции .update() спрайта:

# In Enemy class ~
def update( self ):
    move_instruction = self.move_program[ self.move_cursor ]
    self.move_cursor += 1
    # If the movement program has ended, restart
    if ( self.move_cursor == len( self.move_program ) ):
        self.move_cursor = 0
    # Interpret the movement instruction
    if ( instruction == 'r' ):   # right
        self.rect.x = self.rect.x + 10
    elif ( instruction == 'l' ): # left
        self.rect.x = self.rect.x - 10
    elif ( instruction == 'd' ): # down
        self.rect.y = self.rect.y + 10
    elif ( instruction == 's' ): # speedup
        self.vel += 1

Очевидно, что вы можете иметь любые инструкции, которые вам нравятся.Разные наборы инструкций могут быть даны разным спрайтам как часть конструктора.

Размещение игровых снарядов и игроков в спрайтах позволит коду легко находить столкновения и т. Д., Но это другой ответ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...