在一群精灵中更新一个精灵[Pygame]

2024-04-26 12:46:08 发布

您现在位置:Python中文网/ 问答频道 /正文

第一个帖子在这里。所以我尝试实现一个文明型的动作游戏。现在,我的牢房里有一个精灵。我可以单击它,然后如果我单击另一个网格,精灵就会移动到那里。我现在想要的是繁殖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()

Tags: theinposselfforwidthscreenpygame
1条回答
网友
1楼 · 发布于 2024-04-26 12:46:08

给你的一些建议:

  • 保持主回路清洁
  • 把逻辑放在属于它的地方
  • 只调用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

相关问题 更多 >