Обновите один спрайт среди группы спрайтов [Pygame] - PullRequest
0 голосов
/ 06 сентября 2018

Первый пост здесь.Поэтому я пытаюсь реализовать игру о движении типа Цивилизация.На данный момент у меня есть один спрайт в ячейке.Я могу щелкнуть по нему, а затем, если я нажму другую сетку, спрайт переместится туда.Теперь я хочу вызвать 5-6 таких спрайтов, а затем сделать то же самое.Нажмите на спрайт, затем нажмите на другую сетку, и этот конкретный спрайт перемещается туда, не затрагивая другие спрайты.Я не могу этого сделать.Я могу вызвать 5-6 случайных спрайтов на разных сетках, но когда я нажимаю на одну из них, а затем щелкаю на другой сетке, все остальные спрайты исчезают.Код ниже (не самый лучший, как я изучаю Pygame).Я понимаю, что мне нужно каким-то образом обновлять только спрайт, на который нажали, но я не уверен, как это сделать.

import pygame
import random

WIDTH = 900
HEIGHT = 700
FPS = 2


WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

TURN = "TeamOne"

def main():
    # Pygame sprite Example

    global x_lines
    global y_lines
    x_lines = [WIDTH-i*WIDTH/20 for i in range(20,0, -1)]
    y_lines = [HEIGHT-j*HEIGHT/20 for j in range(20,0, -1)]


    class TeamOne(pygame.sprite.Sprite):
        # sprite for the Player
        def __init__(self):
            # this line is required to properly create the sprite
            pygame.sprite.Sprite.__init__(self)
            # create a plain rectangle for the sprite image
            self.image = pygame.Surface((WIDTH / 20, HEIGHT / 20))
            self.image.fill(GREEN)
            # find the rectangle that encloses the image
            self.rect = self.image.get_rect()
            # center the sprite on the screen
            self.rect.center = ((random.randint(1,19)*2+1)* WIDTH/ 40, (random.randint(1,19)*2+1)*HEIGHT/40)



        def update(self, position):
            # any code here will happen every time the game loop updates
            (a, b) = position
            for index, i in enumerate(x_lines):
                if i > a:
                    self.rect.x = x_lines[index-1]
                    break
            for index, j in enumerate(y_lines):
                if j > b:
                    self.rect.y = y_lines[index-1]
                    break






        # initialize pygame and create window
    pygame.init()

    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("A Game")
    clock = pygame.time.Clock()
    clicked_sprites = pygame.sprite.Group()
    teamone_sprites = pygame.sprite.Group()

    for i in range(5):
        mob1 = TeamOne()
        teamone_sprites.add(mob1)



    # Game loop
    running = True
    j=0
    while running:
        # keep loop running at the right speed
        clock.tick(FPS)
        # Process input (events)
        for event in pygame.event.get():
            # check for closing window
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and j == 0:
                pos = pygame.mouse.get_pos()

                for s in teamone_sprites:
                    if s.rect.collidepoint(pos):
                        #teamone_sprites.add(s)
                        clicked_sprites.add(s)
                        print (clicked_sprites)
                        j = 1
            elif event.type == pygame.MOUSEBUTTONDOWN and j == 1:
                new_pos = pygame.mouse.get_pos()
                #teamone_sprites.update(new_pos)
                clicked_sprites.update(new_pos)
                j = 0



            # Update





                        # Draw / render
##                screen.fill(BLACK)
##                draw_grid(screen)
##
##                teamone_sprites.draw(screen)
##
##
##
##                # *after* drawing everything, flip the display
##                pygame.display.flip()
                                # Draw / render
        screen.fill(BLACK)
        draw_grid(screen)

        teamone_sprites.draw(screen)

        pygame.display.flip()






    pygame.quit()


def draw_grid(screen):
    for i in range(1, HEIGHT, int(HEIGHT/20)):
        pygame.draw.line(screen, GREEN, (1,i) ,(WIDTH,i), 2)

    for j in range(1, WIDTH, int(WIDTH/20)):
        pygame.draw.line(screen, GREEN, (j,1) ,(j,HEIGHT), 2)

if __name__ == '__main__':
    main()

1 Ответ

0 голосов
/ 06 сентября 2018

Несколько советов для вас:

  • Содержите основной цикл в чистоте
  • Поместите логику туда, где она принадлежит
  • Только звонить pygame.display.flip() / pygame.display.update() один раз
  • Не используйте имена переменных, такие как j
  • Поскольку ваша игра основана на сетке, у вас должен быть способ перевода координат сетки и координат экрана

Вот простой исполняемый пример, который я взломал вместе (см. Комментарии для некоторых объяснений):

import pygame
import random

WIDTH = 900
HEIGHT = 700
ROWS = 20
COLUMNS = 20
TILE_SIZE = WIDTH / COLUMNS, HEIGHT / ROWS
TILE_W, TILE_H = TILE_SIZE
FPS = 60

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

TURN = "TeamOne"

# some functions to translate grid <-> screen coordinates
def posToScreen(pos):
    column, row = pos
    return column * TILE_W, row * TILE_H

def screenToPos(pos):
    column, row = pos
    return column / TILE_W, row / TILE_H    

def draw_grid(screen):
    for i in range(1, HEIGHT, TILE_H):
        pygame.draw.line(screen, GREEN, (1,i) ,(WIDTH,i), 2)

    for j in range(1, WIDTH, TILE_W):
        pygame.draw.line(screen, GREEN, (j,1) ,(j,HEIGHT), 2)

# a class that handles selecting units
class Cursor(pygame.sprite.Sprite):
    def __init__(self, units, *groups):
        pygame.sprite.Sprite.__init__(self, *groups)

        # group of the units that can be controlled
        self.units = units

        # we create two images
        # to indicate if we are selecting or moving
        self.image = pygame.Surface(TILE_SIZE)
        self.image.set_colorkey((43,43,43))
        self.image.fill((43,43,43))
        self.rect = self.image.get_rect()
        self.selected_image = self.image.copy()
        pygame.draw.rect(self.image, pygame.Color('red'), self.image.get_rect(), 4)
        pygame.draw.rect(self.selected_image, pygame.Color('purple'), self.image.get_rect(), 4)
        self.base_image = self.image

        self.selected = None

    def update(self):
        # let's draw the rect on the grid, based on the mouse position
        pos = pygame.mouse.get_pos()
        self.rect.topleft = posToScreen(screenToPos(pos))

    def handle_click(self, pos):
        if not self.selected:
            # if we have not selected a unit, do it now
            for s in pygame.sprite.spritecollide(self, self.units, False):
                self.selected = s
                self.image = self.selected_image
        else:
            # if we have a unit selected, just set its target attribute, so it will move on its own
            self.selected.target = posToScreen(screenToPos(pos))
            self.image = self.base_image
            self.selected = None

class TeamOne(pygame.sprite.Sprite):
    def __init__(self, *groups):
        pygame.sprite.Sprite.__init__(self, *groups)
        self.image = pygame.Surface(TILE_SIZE)
        self.image.fill(GREEN)
        self.pos = random.randint(0, COLUMNS), random.randint(0, ROWS)
        self.rect = self.image.get_rect(topleft = posToScreen(self.pos))
        self.target = None

    def update(self):
        # do nothing until target is set
        # (maybe unset it if we reached our target)
        if self.target:
            if self.rect.x < self.target[0]:
                self.rect.move_ip(1, 0)
            elif self.rect.x > self.target[0]:
                self.rect.move_ip(-1, 0)
            elif self.rect.y < self.target[1]:
                self.rect.move_ip(0, 1)
            elif self.rect.y > self.target[1]:
                self.rect.move_ip(0, -1)
        self.pos = screenToPos(self.rect.topleft)

def main():
    pygame.init()

    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("A Game")
    clock = pygame.time.Clock()

    all_sprites = pygame.sprite.LayeredUpdates()
    team_ones = pygame.sprite.Group()
    for i in range(5):
        TeamOne(all_sprites, team_ones)
    cursor = Cursor(team_ones, all_sprites)

    # a nice, simple, clean main loop
    running = True
    while running:
        clock.tick(FPS)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

            # we could also pass all events to all sprites
            # so we would not need this special clause for the cursor...
            if event.type == pygame.MOUSEBUTTONDOWN:
                cursor.handle_click(event.pos)

        all_sprites.update()
        screen.fill(BLACK)
        draw_grid(screen)
        all_sprites.draw(screen)

        pygame.display.flip()

if __name__ == '__main__':
    main()

enter image description here

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