как заставить змею расти в пигаме с помощью блиц? - PullRequest
0 голосов
/ 09 февраля 2019

Итак, я сейчас создаю игру со змеями, используя pygame, и я хочу сделать так, чтобы змея росла после того, как съела печенье.Я хочу, чтобы он просто добавил изображение, которое я использовал для головы, в конец змеи, но я не могу понять, как это сделать.

Я пытался объединить две линии змей после вызовамоя функция checkForConsump ().Он вернул сообщение об ошибке «TypeError: Аргумент должен быть объектом стиля прямоугольника».

import pygame, sys, random, time
screenWidth = 500
gameDisplay = pygame.display.set_mode((screenWidth,screenWidth))
#this begins the game
pygame.init()
#This sets a caption
pygame.display.set_caption("Picnic")
#Variables:
snakeFace = pygame.image.load('morrison.png')
screen = pygame.display.set_mode((screenWidth,screenWidth))
x= 50
y= 50
snakewidth = 30
snakeheight = 30
food1width = 40
food1height = 17
food2width = 25
food2height = 26
food3width = 27
food3height = 23
vel = 12
run = True
lastKey = None
food1 = pygame.image.load("thinMint.png")
food2 = pygame.image.load("cookie.png")
food3 = pygame.image.load("triscuit.png")
randFoodX1 = 0
randFoodY1 = 0
randFoodX2 = 0
randFoodY2 = 0

topWall=pygame.draw.rect(screen, (255,0,0), ( 0,0,490,10))
bottomWall=pygame.draw.rect(screen, (255,0,0), (0,490,490,10))
leftWall=pygame.draw.rect(screen, (255,0,0), ( 0,0,10,490))
rightWall=pygame.draw.rect(screen, (255,0,0), ( 490,0,10,490))
def generateFoodPosition():
    randFoodX1 = random.randrange(1, 40, 1) * 10
    randFoodY1 = random.randrange(1, 40, 1) * 10
    randFoodX2 = random.randrange(1, 40, 1) * 10
    randFoodY2 = random.randrange(1, 40, 1) * 10
    randFoodX3 = random.randrange(1, 40, 1) * 10
    randFoodY3 = random.randrange(1, 40, 1) * 10
    if randFoodX1 == randFoodX2 or randFoodY1 == randFoodY2 or 
randFoodY2==randFoodY3 or randFoodY1== randFoodY3 or randFoodX2 == 
randFoodX3 or randFoodX3 == randFoodX1:
        generateFoodPosition()
    else:
        return [randFoodX1, randFoodY1, randFoodX2, 
randFoodY2, randFoodX3, randFoodY3]
def checkForConsumption():
    if snakeRect.colliderect(food1Rect):
            foodPositions[0] = random.randrange(1, 40, 1) * 10
        foodPositions[1] = random.randrange(1, 40, 1) * 10
    if snakeRect.colliderect(food2Rect):
        foodPositions[2] = random.randrange(1, 40, 1) * 10
        foodPositions[3] = random.randrange(1, 40, 1) * 10
    if snakeRect.colliderect(food3Rect):
        foodPositions[4] = random.randrange(1, 40, 1) * 10
        foodPositions[5] = random.randrange(1, 40, 1) * 10
foodPositions = generateFoodPosition()
def checkForWallCollision():
    if snakeRect.colliderect(topWall):
        print("Poop")
        pygame.quit()
    if snakeRect.colliderect(bottomWall):
        print("Poop")
        pygame.quit()
    if snakeRect.colliderect(leftWall):
        print("Poop")
        pygame.quit()
    if snakeRect.colliderect(rightWall):
        print("Poop")
        pygame.quit()
def growSnake():
    if snakeRect.colliderect(food1Rect) or 
snakeRect.colliderect(food2Rect) or snakeRect.colliderect(food3Rect):
        pygame.Rect.union(snakeRect)
        print("yah")


while run:
    snakeRect = gameDisplay.blit(snakeFace,(x, y))
    food1Rect = gameDisplay.blit(food1, (foodPositions[0], 
foodPositions[1]))
    food2Rect = gameDisplay.blit(food2, (foodPositions[2], 
foodPositions[3]))
    food3Rect = gameDisplay.blit(food3, (foodPositions[4], 
foodPositions[5]))
    pygame.time.delay(10) #1/2 milisecond delay
     #this controls the "X" button
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            lastKey = event.key
#this controls the movement of the snake
    if lastKey == pygame.K_LEFT:# and x > vel:
        x-=vel
    if lastKey == pygame.K_RIGHT and x< screenWidth:# - 
snakewidth -vel:
        x+=vel
    if lastKey == pygame.K_DOWN and y < screenWidth:# - 
snakeheight - vel:
        y+= vel
    if lastKey == pygame.K_UP:# and y > vel:
        y-=vel

#if x == (foodPositions[0] or foodPositions[2] or foodPositions[4]) 
or y== (foodPositions[1] or foodPositions[3] or foodPositions[5]):
    checkForWallCollision()
    checkForConsumption()
    growSnake()

    gameDisplay.fill((0,0,0))
    gameDisplay.blit(snakeFace,(x, y))
    gameDisplay.blit(food1, (foodPositions[0], 
foodPositions[1]))
    gameDisplay.blit(food2, (foodPositions[2], 
foodPositions[3]))
    gameDisplay.blit(food3, (foodPositions[4], 
foodPositions[5]))
    pygame.draw.rect(screen, (255,0,0), ( 0,0,490,10))
    pygame.draw.rect(screen, (255,0,0), ( 0,490,490,15))
    pygame.draw.rect(screen, (255,0,0), ( 0,0,10,490))
    pygame.draw.rect(screen, (255,0,0), ( 490,0,15,490))
    pygame.display.update()

Я ожидал, что маленькая змея покажет другое изображение, прикрепленное к лицу, когда съест печенье, но просто съест печенье, а затем сразу же после выдачи ошибки ...

1 Ответ

0 голосов
/ 11 февраля 2019

Согласно моему комментарию, это можно реализовать, когда змея - это список / массив частей тела.Первый (0-й) элемент - это голова, а остальная часть тела хранится в порядке.Таким образом, body_parts[0] - это голова, а body_parts[-1] - это хвост.

Это позволяет змее относительно легко двигаться.Во-первых, для каждого элемента тела он перемещается от position-of-part[N] до position-of-part[N-1], то есть каждая часть тела перемещается в положение предыдущей части тела.Например, вторая часть (сразу после головы) перемещается в положение головы и т. Д., Смещаясь вниз по телу.

Когда каждая часть хранится в списке / массиве, это можно кодировать с помощью простогоОбход списка:

def slither( self ):
    # Move each body part to the location of the previous part
    # So we iterate over the tail-parts in reverse
    for i in range( len( self.body )-1, 0, -1 ):
        self.body[i].moveTo( self.body[i-1] )
    # Move the head (the only part that moves independently)
    self.head.move( self.direction )

Это позволяет коду использовать спрайты для каждой части тела или простые прямоугольники.

Итак ... как эта змея растет, как это работает?Если змея скажем движется влево (по прямой линии для обсуждения), имеет смысл, чтобы хвост "рос" вправо.Точно так же, если змея движется вверх, она должна расти вниз.

Это дает нам описание для позиционирования нового элемента хвоста:

def getGrowPosition( self ):
    # we grow against self.direction 
    # so if we're moving up, the tail grows down
    x,y = self.body[ -1 ].getRect().center # location of the last body piece

    if ( self.direction == 'up' ):
        y += self.body_size
    elif ( self.direction == 'down' ):
        y -= self.body_size
    elif ( self.direction == 'left' ):
        x += self.body_size
    elif ( self.direction == 'right' ):
        x -= self.body_size
    return (x,y)

def grow( self, by_size=1 ):
    for i in range( by_size ):
        # new body part needs to be added at the tail-position
        new_body_position = self.getGrowPosition()
        self.body.append( BodyPart( new_body_position ) )

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

import pygame
import random
import time
import sys

# Window size
WINDOW_WIDTH=400
WINDOW_HEIGHT=400

pygame.init()
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
SPRITES = pygame.sprite.Group()

pygame.display.set_caption("Snake Test")
HEAD_IMAGE = pygame.image.load('snake_head_32.png').convert_alpha()
BODY_IMAGE = pygame.image.load('snake_body_32.png').convert_alpha()

clock = pygame.time.Clock()

BLACK = (0,0,0)

STARTUP_MS = int(time.time() * 1000.0)  # Epoch time programme started
NOW_MS     = 0  # ms since we started

class SnakeSprite(pygame.sprite.Sprite):
    """ A SnakeSprite holds the image and location of a snake body-segment.
        It also implements the screen wrapping, so moving off-screen moves
        the sprite back-on to the opposite side"""
    def __init__( self, part_image, position ):
        pygame.sprite.Sprite.__init__(self)
        self.image = part_image
        self.rect = self.image.get_rect()
        self.rect.center = position 
        self.move_step = self.image.get_rect().width # pixels per move step

    def wrapAroundScreen(self):
        # Stay on the screen, and wrap around
        if (self.rect.left >= WINDOW_WIDTH ):
            self.rect.right = 0
        elif (self.rect.right <= 0 ):
            self.rect.left = WINDOW_WIDTH
        if (self.rect.top >= WINDOW_HEIGHT ):
            self.rect.bottom = 0
        elif (self.rect.bottom <= 0):
            self.rect.top = WINDOW_HEIGHT

    def move( self, direction ):
        if ( direction == 'up' ):
            self.rect.y -= self.move_step
        elif ( direction == 'down' ):
            self.rect.y += self.move_step
        elif ( direction == 'left' ):
            self.rect.x -= self.move_step
        elif ( direction == 'right' ):
            self.rect.x += self.move_step
        else:
            print(" MOVE ERROR - "+direction)
        self.wrapAroundScreen()

    def moveTo( self, body_part ):
        self.rect.center = body_part.rect.center

    def getRect( self ):
        return self.rect

    def update(self):
        pass


class Snake():
    """ A Snake object is basically a list of SnakeSprites.
        The 0th / first element is the snake head, the other
        elements are "tail" parts"""
    def __init__( self, size=3 ):
        global SPRITES
        # Create the head sprite positioned 64px left of the middle-screen
        self.head = SnakeSprite( HEAD_IMAGE, ( (WINDOW_WIDTH//2)-64, WINDOW_HEIGHT//2 ) )
        # The sprites are positioned by the width of the sprite image
        self.body_size = self.head.image.get_rect().width # pixels per move step
        self.direction = 'left';
        self.body = [ self.head ]
        SPRITES.add( self.head )
        self.grow( size )

    def changeDirection( self, new_direction ):
        self.direction = new_direction
        self.slither()

    def slither( self ):
        # Move each body part to the location of the previous part
        # So we iterate over the tail-parts in reverse
        for i in range( len( self.body )-1, 0, -1 ):
            self.body[i].moveTo( self.body[i-1] ) 
        # Move the head
        self.head.move( self.direction )

    def getGrowPosition( self ):
        # we grow against self.direction 
        # so if we're moving up, the tail grows down
        x,y = self.body[ -1 ].getRect().center
        if ( self.direction == 'up' ):
            y += self.body_size
        elif ( self.direction == 'down' ):
            y -= self.body_size
        elif ( self.direction == 'left' ):
            x += self.body_size
        elif ( self.direction == 'right' ):
            x -= self.body_size
        return (x,y)

    def grow( self, by_size=1 ):
        global SPRITES
        for i in range( by_size ):
            # new body part needs to be added at the tail-position
            new_body_part = SnakeSprite( BODY_IMAGE, self.getGrowPosition() )
            self.body.append( new_body_part )
            SPRITES.add( new_body_part )



def drawGameWindow(screen, sprites):
    global WINDOW_WIDTH, WINDOW_HEIGHT, SPRITES
    screen.fill(BLACK)
    SPRITES.draw(screen)
    pygame.display.update()
    pygame.display.flip()

### MAIN
my_snake = Snake()
last_move = STARTUP_MS
last_grow = STARTUP_MS

clock = pygame.time.Clock()
done = False
while not done:
    NOW_MS = int(time.time() * 1000.0) 

    SPRITES.update()

    # Move every 500ms
    if ( NOW_MS - STARTUP_MS > 3000 and NOW_MS - last_move >= 500 ):
        print("Moving...")
        my_snake.slither()
        last_move = NOW_MS

    # Grow every 2 seonds
    if ( NOW_MS - STARTUP_MS > 3000 and NOW_MS - last_grow >= 2000 ):
        print("Growing...")
        my_snake.grow( 1 )
        last_grow = NOW_MS

    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.VIDEORESIZE ):
            # resize-window
            WINDOW_WIDTH  = event.w
            WINDOW_HEIGHT = event.h
            WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE )
        elif (event.type == pygame.KEYDOWN):
            # Movement keys
            keys = pygame.key.get_pressed()
            if ( keys[pygame.K_UP] ):
                my_snake.changeDirection("up")
            elif ( keys[pygame.K_DOWN] ):
                my_snake.changeDirection("down")
            elif ( keys[pygame.K_LEFT] ):
                my_snake.changeDirection("left")
            elif ( keys[pygame.K_RIGHT] ):
                my_snake.changeDirection("right")

    drawGameWindow(WINDOW, SPRITES)
    clock.tick_busy_loop(60)

pygame.quit()

snake_head_32.png snake_body_32.png

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