pygame-碰撞和列表

时间:2019-11-18 10:57:49

标签: python pygame

我正在尝试使用Python和Pygame编写我的第一款游戏。我对Python和编码一般还很陌生,所以对我的代码难以阅读感到抱歉。

有4个圆圈,从屏幕中间移动到4个边缘。 我正在将4个边缘的立方体(敌人)放到中间。目的是通过按键盘箭头来阻止这些多维数据集到达屏幕中间。我

现在,我正在研究生活逻辑。玩家有5条生命。 如果敌人到达屏幕中间,玩家将丧命。我有这部分。

玩家爬坡时也会丧命。我正在为这部分苦苦挣扎。 我可以看到一些情况。假设玩家单击“左”:

  • 左侧没有敌人->他丧命
  • 左侧有1个敌人,但没有碰撞->他丧生了
  • 左侧有1个以上的敌人,他单击了一个敌人。现在,即使单击右键,玩家也会在圈子外的每个敌人身上丧命。我找不到解决此问题的方法。我解决了以上两种情况。

有什么主意吗?

这是我的代码。

# ---------- Packages and Inits ----------

import pygame, random, math
pygame.init()

# ---------- Settings ----------

SCREEN_WIDTH  = 600
SCREEN_HEIGHT = 600
FPS = 60 
SPEED = 1
SPEED_ENEMIES = 0.5
CIRCLE_RADIUS = 50
ENEMY_SIZE = 40

red    = (255,000,000)
blue   = (000,000,255)
yellow = (255,255,000)
green  = (000,128,000)
pink   = (255,192,203)
black  = (000,000,000)

# ---------- Classes ----------

class Enemies:

    def __init__(self, x, y, size=ENEMY_SIZE, thick=5, color=blue, speed=SPEED_ENEMIES, position="top"):

        self.rect = pygame.Rect(0, 0, size, size)
        if ( x == 0 and y == 0 ):
            self.randomise()

        self.rect.centerx = x
        self.rect.centery = y
        self.size = size
        self.thick = thick
        self.color = color
        self.speed = speed
        self.calcDirection()
        self.position = position

    def calcDirection( self ):
        self.x_float = 1.0 * self.rect.centerx
        self.y_float = 1.0 * self.rect.centery

        # Determine direction vector from (x,y) to the centre of the screen
        self.position_vector = pygame.math.Vector2( self.x_float, self.y_float )
        self.velocity_vector = pygame.math.Vector2( SCREEN_WIDTH/2 - self.x_float, SCREEN_HEIGHT/2 - self.y_float )
        self.velocity_vector = self.velocity_vector.normalize()

    def update( self ):
        x_delta = self.speed * self.velocity_vector[0]
        y_delta = self.speed * self.velocity_vector[1]
        self.x_float += x_delta
        self.y_float += y_delta
        self.rect.centerx = int( self.x_float )
        self.rect.centery = int( self.y_float )

    def draw(self, screen):
        pygame.draw.rect(screen, self.color, self.rect )

    def reachedPoint( self, x, y ):
        return self.rect.collidepoint( x, y )

    def randomise( self ):
        self.rect.centerx = SCREEN_WIDTH//2
        self.rect.centery = SCREEN_HEIGHT//2
        side = random.randint( 0, 4 )
        if ( side == 0 ):
            self.rect.centery = SCREEN_HEIGHT
            self.color = green
            self.position= "bot"
        elif ( side == 1 ):
            self.rect.centery = 0
            self.color = yellow
            self.position= "top"
        elif ( side == 2 ):
            self.rect.centerx = 0
            self.color = blue
            self.position= "left"
        else:
            self.rect.centerx = SCREEN_WIDTH
            self.color = red
            self.position= "right"
        self.calcDirection()

class Circle:

    def __init__(self, x, y, radius=CIRCLE_RADIUS, thick=5, color=blue, speed=SPEED, position="top"):

        self.rect = pygame.Rect(0, 0, 2*radius, 2*radius)

        self.rect.centerx = x
        self.rect.centery = y
        self.radius = radius
        self.thick = thick
        self.color = color
        self.speed = speed
        self.position = position

        if speed >= 0:
            self.directionX = 'right'
            self.direction = 'up'
        else:
            self.directionX = 'left'
            self.direction = 'down'

    def draw(self, screen):
        pygame.draw.circle(screen, self.color, self.rect.center, self.radius, self.thick)

    def swing(self):
        if self.position == "top":
            self.rect.y -= self.speed

            if self.rect.top <= 0  and self.direction == 'up':
                self.direction = 'down'
                self.speed = -self.speed

            elif self.rect.bottom > int(SCREEN_HEIGHT/2) - self.radius  and self.direction == 'down':
                self.direction = 'up'
                self.speed = -self.speed

        if self.position == "bot":
            self.rect.y -= self.speed

            if self.rect.top < int(SCREEN_HEIGHT/2) + self.radius  and self.direction == 'up':
                self.direction = 'down'
                self.speed = -self.speed

            elif self.rect.bottom >= SCREEN_HEIGHT and self.direction == 'down':
                self.direction = 'up'
                self.speed = -self.speed

        if self.position == "left":
            self.rect.x -= self.speed

            if self.rect.right > int(SCREEN_WIDTH/2) - self.radius and self.directionX == 'left':
                self.directionX = 'right'
                self.speed = -self.speed

            elif self.rect.left <= 0 and self.directionX == 'right':
                self.directionX = 'left'
                self.speed = -self.speed

        if self.position == "right":
            self.rect.x -= self.speed

            if self.rect.left < int(SCREEN_WIDTH/2) + self.radius  and self.directionX == 'right':
                self.directionX = 'left'
                self.speed = -self.speed

            elif self.rect.right >= SCREEN_WIDTH and self.directionX == 'left':
                self.directionX = 'right'
                self.speed = -self.speed

    def isCollision(self, enemyX, enemyY, circleX, circleY):
        distance = math.sqrt((math.pow(enemyX-circleX,2))+(math.pow(enemyY-circleY,2)))
        if distance < 65:
            return True
        else:
            return False

# ---------- Main ----------

def main():

    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    screen_rect = screen.get_rect()
    clock = pygame.time.Clock()
    game_over = False
    lifes = 5
    score = 0
    myFont = pygame.font.SysFont("monospace", 25)

    # Start with 4 enemies
    all_enemies = [
        Enemies(int(SCREEN_WIDTH/2)    , 0                       , color = yellow, position = "top"),
        Enemies(int(SCREEN_WIDTH/2)    , SCREEN_HEIGHT-ENEMY_SIZE, color = green , position = "bot"),
        Enemies(0                      ,int(SCREEN_HEIGHT/2)     , color = blue  , position = "left"),
        Enemies(SCREEN_WIDTH-ENEMY_SIZE, int(SCREEN_HEIGHT/2)    , color = red   , position = "right")
    ]

    # Start with 4 circles
    all_circles = [
        Circle(screen_rect.centerx, screen_rect.centery - 2*CIRCLE_RADIUS, position="top"),
        Circle(screen_rect.centerx, screen_rect.centery + 2*CIRCLE_RADIUS, position="bot"),
        Circle(screen_rect.centerx + 2*CIRCLE_RADIUS, screen_rect.centery, position="right"),
        Circle(screen_rect.centerx - 2*CIRCLE_RADIUS, screen_rect.centery, position="left")
    ]



    while not game_over:
        screen.fill(black)

        # Reference enemy lists
        left_enemies = [x for x in all_enemies if x.position == "left"]
        right_enemies = [x for x in all_enemies if x.position == "right"]
        top_enemies = [x for x in all_enemies if x.position == "top"]
        bot_enemies = [x for x in all_enemies if x.position == "bot"]

        # Place and swing 4 circles (the player)
        for c in all_circles:
            c.draw(screen)
            c.swing()

        # The enemy reaches the middle
        for e in all_enemies:
            e.update()
            if ( e.reachedPoint( SCREEN_WIDTH//2, SCREEN_HEIGHT//2 ) ):
                lifes -=1
                e.randomise()
            e.draw( screen )


        # Score points with keyboard arrow
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            for c in all_circles:

                if event.type == pygame.KEYDOWN:

                    # LEFT
                    if event.key == pygame.K_LEFT and c.position == "left":
                        if not left_enemies :
                            lifes -=1

                        for e in left_enemies:
                            collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
                            if e.position == "left" and collision == True :
                                score +=1
                                e.randomise()
                            else:
                                lifes -=1 

                    # RIGHT
                    if event.key == pygame.K_RIGHT and c.position == "right":
                        if not right_enemies :
                            lifes -=1

                        for e in right_enemies:
                            collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
                            if e.position == "right" and collision == True :
                                score +=1
                                e.randomise()
                            else:
                                lifes -=1 

                    # TOP
                    if event.key == pygame.K_UP and c.position == "top":
                        if not top_enemies :
                            lifes -=1

                        for e in top_enemies:
                            collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
                            if e.position == "top" and collision == True :
                                score +=1
                                e.randomise()
                            else:
                                lifes -=1 

                    # BOT
                    if event.key == pygame.K_DOWN and c.position == "bot":
                        if not bot_enemies :
                            lifes -=1

                        for e in bot_enemies:
                            collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
                            if e.position == "bot" and collision == True :
                                score +=1
                                e.randomise()
                            else:
                                lifes -=1 

        print_lifes = myFont.render("Lifes:" + str(lifes), 1, red)
        screen.blit(print_lifes, (10, SCREEN_HEIGHT-50))

        print_score = myFont.render("Score:" + str(score), 1, red)
        screen.blit(print_score, (10, 10))

        pygame.display.update()
        clock.tick(FPS)
main()
pygame.quit()

1 个答案:

答案 0 :(得分:3)

您的规则可以分解为一个简单的规则:

  

如果玩家按下某个键,则查看圆圈下是否有敌人。

因此,在KEYDOWN上,过滤所有与圆碰撞的敌人的敌人列表,然后检查数字是否大于0。

替换检查/循环:

if not left_enemies:
    lifes -=1

for e in left_enemies:
    collision = c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery)
    if e.position == "left" and collision == True :
        score +=1
        e.randomise()
    else:
        lifes -=1 

具有这样的内容:

hits = [e for e in left_enemies if c.isCollision(e.rect.centerx,e.rect.centery,c.rect.centerx,c.rect.centery) and position == "left"]
if not hits:
    lifes -=1
for e in hits:
    score +=1
    e.randomise()