Как изменить значение параметров в классе, используя библиотеку Pygame Python - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь написать космические захватчики, как игры. Первоначально я написал свой код, чтобы предоставить только один захватчик, чтобы дать мне что-то, на чем можно было бы строить. Когда я начал добавлять больше захватчиков, я решил создать класс, в котором я мог бы иметь списки захватчиков l oop over.

Я пытался изменить x-координату захватчика в методе из моего списка, но обнаружил, что он не меняет значение, поэтому захватчики остаются на месте. Любая помощь будет принята с благодарностью!

Вот класс, над которым я работаю:

import sys, pygame, random
from pygame.locals import *
import itertools
#from bullet import Invader

pygame.init()
screen_height = 600
screen_width = 1200
DISPLAYSURF = pygame.display.set_mode((screen_width, screen_height))
FPS = 200

score = 0

pygame.display.set_caption('Testing Pygame')
spaceship = pygame.image.load('spaceship copy.bmp')

spaceship_rect = spaceship.get_rect()
DISPLAYSURF_rect = DISPLAYSURF.get_rect()

FONT = pygame.font.Font('freesansbold.ttf', 32)
text = FONT.render('Score ' + str(score), True, (180, 180, 180))
text_rect = text.get_rect()
text_rect.centerx = DISPLAYSURF_rect.centerx
text_rect.centery = DISPLAYSURF_rect.centery

invader_right_movement = False
invader_left_movement = True

class Invader():

    def __init__(self, invader, invader_x, invader_y):
        self.invader = invader
        self.rect = invader.get_rect()
        self.rect.x = invader_x
        self.rect.y = invader_y

    def move_invader(self, movement):
        #self.x = self.rect.x
        #self.y = self.rect.y
        #Move invader
        if invader_right_movement == True:
            self.rect.x += movement
        if invader_left_movement == True:
            self.rect.x -= movement
        DISPLAYSURF.blit(self.invader, (self.rect.x, self.rect.y))

invaders_x = [10, 90, 170, 250, 330, 410, 490, 570, 650, 730]
invaders_y = 40

invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invaders_x:
    invaders.append(Invader(invader_image,x,invaders_y)) 

invaders_rect = []
for invader, x in zip(invaders, invaders_x):
    invader.centerx = x
    invader.centery = invaders_y


spaceship_rect.centerx = DISPLAYSURF_rect.centerx
spaceship_rect.centery = DISPLAYSURF_rect.bottom - 40

move_right = False
move_left = False
move_rate = 5

bullet_firing = False

#Testing bullet firing
RED = (240, 0, 0)
x = spaceship_rect.centerx - 3
y = spaceship_rect.top
width = 6
height = 24
#bullet = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
#bullet.centerx = spaceship_rect.centerx - 3
#bullet.centery = spaceship_rect.top + height
#bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))
bullets_fired = []
bullet_fired = False

while True:
    DISPLAYSURF.fill((0, 0, 0))
    DISPLAYSURF.blit(spaceship, spaceship_rect)
    DISPLAYSURF.blit(text, text_rect)


    #get invader to move 1-8 pixels randomly to one side before turning back
    num_movements = random.randint(1, 8)

    for invader in invaders:
        invader.move_invader(num_movements)

    for invader in invaders:
        if invader.rect.centerx >= screen_width - 30:
            invader_left_movement = True
            invader_right_movement = False
        if invader.rect.centerx <= 0 + 30:
            invader_left_movement = False
            invader_right_movement = True


    FPSCLOCK = pygame.time.Clock()

    #movement of bullet

    for bullet in range(len(bullets_fired)-1,-1,-1): 
        for invader in invaders:
            if invader.rect.colliderect(bullets_fired[bullet]):
                score += 1
                invader_x = DISPLAYSURF_rect.centerx
                invader_x = DISPLAYSURF_rect.top + 40
                del bullets_fired[bullet]
                bullet_fired = False
            elif bullets_fired[bullet].y > 0:
                bullet_fired = True
                bullets_fired[bullet].y -=  14
                pygame.draw.rect(DISPLAYSURF,RED,bullets_fired[bullet])


    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

        elif event.type == KEYDOWN:
            #Movement of player
            if event.key == K_RIGHT:
                move_right = True
            elif event.key == K_LEFT:
                move_left = True

            #Bullet firing
            elif event.key == K_SPACE:
                if bullet_fired == False:
                    rect = spaceship_rect
                    rect.x = spaceship_rect.centerx - 3
                    rect.y = spaceship_rect.top
                    bullets_fired.append(rect)

        elif event.type == KEYUP:
            #Movement of player
            if event.key == K_RIGHT:
                move_right = False
            elif event.key == K_LEFT:
                move_left = False

    text = FONT.render('Score ' + str(score), True, (180, 180, 180))

    if move_right == True and spaceship_rect.right <= screen_width:
        spaceship_rect.centerx += move_rate
    if move_left == True and spaceship_rect.left >= 0:
        spaceship_rect.centerx -= move_rate

    pygame.display.update()
    FPSCLOCK.tick(FPS)


1 Ответ

0 голосов
/ 07 апреля 2020

Проблема в том, что вы вызываете класс в каждом кадре, который возвращает его значения значениям, присвоенным в __init__. Вы должны вызывать класс один раз в начале, а затем вызывать методы каждый кадр. Вот ссылка , чтобы узнать больше о занятиях.

Чтобы исправить свой код, сделайте это:

while True:

    #do other stuff

    for invader in invaders:
        invader.move_invader()

    #do other stuff

, и, поскольку все захватчики имеют одинаковое изображение, вы можете иметь

invader_image = pygame.image.load('invader.bmp')
invaders = []
for x in invader_x:
    invaders.append(Invader(invader_image,x,40,1))

, это должно переместить каждого захватчика на 1 пиксель каждый кадр


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

class Invader
    def __init__(self, invader, invader_x, invader_y, movement):
        self.rect = invader.get_rect()
        self.rect.x = invader_x
        self.rect.y = invader_y
        #rest of code

    def move_invader(self):
        #if moveing move x
        self.rect.x = x
        #rest of code

и для столкновения

for bullet in range(len(bullets_fired)-1,-1,-1): 
    for invader in invaders:
        if invader.rect.colliderect(bullets_fired[bullet]):
            score += 1
            invader_x = DISPLAYSURF_rect.centerx
            invader_x = DISPLAYSURF_rect.top + 40
            del bullets_fired[bullet]
            invaders.remove(invader) #to get rid of the invader too
            bullet_fired = False
            break
       elif bullets_fired[bullet].y > 0:
            bullet_fired = True
            bullets_fired[bullet].y -=  14
            bullet_rect = pygame.draw.rect(DISPLAYSURF, RED, (x, y, width, height))

для столкновения я зациклился назад, потому что если вы удалите 2-ю пулю в списке, 3-я станет 2-й, а l oop перейдет к 3-й (которая была 4-й), пропустив пулю. Но если вы go назад, если вы удалите пулю, уже проверенные пули будут перемещены, и вы можете продолжать проверять следующую.


для пули, у вас есть bullet и bullet_rect, которые это то же самое, и у вас есть список для пуль, лично я бы избавился от bullet_rect

bullet = pygame.draw.rect(screen,RED,(x,y,w,y))

для

pygame.draw.rect(screen,RED,bullets_fired[bullet]

теперь для того, где вы добавляете пули, когда вы нажимаете пробел вместо получения y просто получите прямоугольник

elif event.key == K_SPACE:
    if bullet_fired == False:
        rect = spaceship_rect.copy() # this makes the bullet the same size as the ship
        #you could also do rect = pygame.rect(0,0,0,0)
        rect.x = spaceship_rect.centerx - 3
        rect.y = spaceship_rect.top
        #rect.w = width
        #rect.h = height
        bullets_fired.append(rect)

и снова в столкновении l oop замените y на bullets_fired [bullet] .y

...