Функция Python для координат - PullRequest
1 голос
/ 12 марта 2019

Я запрограммировал мумий в свою игру и хочу, чтобы они следовали за моим игроком. Я хочу создать функцию, которую я могу использовать для применения ко всем врагам, которых я выберу, но та, которая у меня есть, не совсем работает. Появятся мумии, но они не будут следовать за игроком. Как я могу изменить функцию, чтобы она работала?

import random
import pygame
import sys
import time
from pygame import mixer

screenx = 800
screeny = 600

clock = pygame.time.Clock()

#PICTURES
#name = pygame.display.set_caption('Brutal Survival')
#win = pygame.display.set_mode((screenx,screeny))
#player_right = pygame.image.load('maincharright.png')
#player_left = pygame.image.load('maincharleft.png')
#player_up = pygame.image.load('maincharup.png')
#player_down = pygame.image.load('mainchardown.png')
#background = pygame.image.load('background.jpg')
#mummychar = pygame.image.load('mummychar.png')

randomspawnabove = (random.randint(0, screenx), -100)
randomspawnbelow = (random.randint(0, screenx), (screeny + 100))
randomspawnleft = (-100, random.randint(0, screeny))
randomspawnright = ((screenx + 100), random.randint(0, screeny))

enemyalive = True
multiplier = 2
level = 1
nextlevel = True
spawn = True
up = True
down = False
left = False
right = False
run = True


class player():
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.alive = True
        self.vel = 5

class enemy():
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.alive = False
        self.vel = 2

def enemyfollow(self):
    if self.alive == True and self.x > mainChar.x:
        self.x = self.x - self.vel
    if self.alive == True and self.x < mainChar.x:
        self.x = self.x + self.vel
    if self.alive == True and self.y > mainChar.y:
        self.y = self.y - self.vel
    if self.alive == True and self.y < mainChar.y:
        self.y = self.y + self.vel


def redrawScreen():
    pygame.display.update()
    if run == True:
        win.blit(background, (0,0))
    if up == True and left == False and right == False and down == False:
        win.blit(player_up, (mainChar.x, mainChar.y))
    if up == False and left == False and right == False and down == True:
        win.blit(player_down, (mainChar.x, mainChar.y))
    if up == False and left == False and right == True and down == False:
        win.blit(player_right, (mainChar.x, mainChar.y))
    if up == False and left == True and right == False and down == False:
        win.blit(player_left, (mainChar.x, mainChar.y))
    if enemyalive == True:
        win.blit(mummychar, (mummy1.x, mummy1.y))
        enemyfollow(mummy1)


mainChar = player(screenx/2 - 30, screeny/2, 60, 60)
maxenemies = (level * multiplier)
mummy_Spawn = [randomspawnleft, randomspawnright, randomspawnabove, randomspawnbelow]
mummy1 = enemy(*random.choice(mummy_Spawn), 50, 50)

while run:
    clock.tick(60)

    keys = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
            pygame.quit()

    for x in range(maxenemies):
        Enemies.append(enemy(*random.choice(mummy_Spawn), 50, 50))

    if nextlevel == True:
        if level >= 1:
            enemyalive = True

    if keys[pygame.K_ESCAPE]:
        run = False
        pygame.quit()
    if keys[pygame.K_UP]:
        mainChar.y = mainChar.y - mainChar.vel
        up = True
        down = False
        left = False
        right = False
    if keys[pygame.K_DOWN]:
        mainChar.y = mainChar.y + mainChar.vel
        down = True
        left = False
        up = False
        right = False
    if keys[pygame.K_RIGHT]:
        mainChar.x = mainChar.x + mainChar.vel
        right = True
        left = False
        up = False
        down = False
    if keys[pygame.K_LEFT]:
        mainChar.x = mainChar.x - mainChar.vel
        left = True
        right = False
        down = False
        up = False
    if (mainChar.y + mainChar.height) > screeny:
        mainChar.y = mainChar.y - 5
    if mainChar.y < 0:
        mainChar.y = mainChar.y + 5
    if mainChar.x < 0:
        mainChar.x = mainChar.x + 5
    if (mainChar.x + mainChar.width) > screenx:
        mainChar.x = mainChar.x - 5

    redrawScreen()

Ответы [ 3 ]

0 голосов
/ 12 марта 2019

Таким образом, Мумии объекта необходимо следовать объекту Player.Уточнение этого описания проблемы далее:

Каждый раз, когда Мумия движется, она должна быть в направлении Игрока.

Так как же мысделать это?

Представьте, что мы рисуем стрелку из положения мумии к игроку.Это определит направление, в котором должна двигаться мама.В формальных (математических) терминах это направление вектор .Чтобы определить вектор направления, мы прорабатываем линию между двумя точками, затем нормализуем , разделив ее на длину.

В результате получаем простую x иy единичный вектор , составляющие которого можно умножить на скорость объекта, чтобы получить его следующую позицию.

В приведенном ниже примере есть 3 спрайта, которые будут перемещаться в направлении положения мыши.Важной частью является функция MySprite.update().Это захватывает положение мыши (в вашем случае это игрок) и местоположение спрайта (положение мумии), используя эти две точки для вычисления вектора.Как только вектор определен, компоненты используются вместе со скоростью спрайта для вычисления следующей позиции.Я сохраняю позицию внутри как поплавок, так что небольшие углы изменения и низкие скорости обрабатываются лучше.

import pygame
import random
import math

# Window size
WINDOW_WIDTH=400
WINDOW_HEIGHT=400

BLACK = (50,50,50)


class MySprite( pygame.sprite.Sprite ):
    def __init__( self, filename ):
        pygame.sprite.Sprite.__init__(self)
        self.image  = pygame.image.load(filename).convert_alpha()
        self.rect   = self.image.get_rect()
        self.speed  = random.randrange( 1, 3 )
        self.xfloat = random.randrange( 0, WINDOW_WIDTH )
        self.yfloat = random.randrange( 0, WINDOW_HEIGHT )
        self.rect.center = ( int( self.xfloat ), int( self.yfloat ) )

    def update( self ):
        # Re-compute our new movement vector based on the mouse every update
        # so we always move towards the mouse
        mouse_pos = pygame.mouse.get_pos()
        if ( mouse_pos != (0, 0) ):
            my_pos    = [ self.rect.centerx, self.rect.centery ]
            dir_vector= self.normalisedMovementVector( my_pos, mouse_pos )
            x_delta = self.speed * dir_vector[0]
            y_delta = self.speed * dir_vector[1]
            self.xfloat += x_delta
            self.yfloat += y_delta
            self.rect.center = ( int(self.xfloat), int(self.yfloat) )

    def lineLength( self, pointa, pointb ):
        """ Return the length of a line between the two points, in pixels """
        x1,y1 = pointa
        x2,y2 = pointb
        # length = sqrt((x2 - x1)^2 + (y2 - y1)^2)
        x_squared = (x2 - x1) * (x2 - x1)
        y_squared = (y2 - y1) * (y2 - y1)
        length = math.sqrt( x_squared + y_squared )
        return length

    def normalisedMovementVector( self, pointa, pointb ):
        """ Return a normalised vector between to points """
        # offset it from (0,0) to make calculations simpler
        # since it's a *direction* the actual positions don't matter
        pointb = (pointb[0]-pointa[0], pointb[1]-pointa[1])
        length = self.lineLength( (0,0), pointb )
        # normalise it (divide by it's own length)
        if ( length > 0 ):
            x = pointb[0] / length
            y = pointb[1] / length
            move_vector = ( x , y )
        else:
            # catch division by zero
            move_vector = ( 0, 0 )
        return move_vector




### MAIN
# Initialise the window
pygame.init()
SURFACE_TYPE = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE
WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE_TYPE )
pygame.display.set_caption("Follow Mouse")

# Add some sprites
SPRITES = pygame.sprite.Group()
for i in range(3):
    s = MySprite( 'tiny_alien.png' )
    SPRITES.add( s ) # Put in sprites group

# tick tick tick
clock = pygame.time.Clock()

# Main loop
done = False
while not done:

    # Move the sprites (nd checks for collisions)
    SPRITES.update()

    # Handle user input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.VIDEORESIZE ):
            WINDOW_WIDTH  = event.w
            WINDOW_HEIGHT = event.h
            WINDOW  = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), SURFACE_TYPE )

    # Paint the screen
    WINDOW.fill( BLACK )
    SPRITES.draw( WINDOW )
    pygame.display.flip()
    clock.tick_busy_loop( 60 )

# Bye
pygame.quit()

Любое изображение PNG можно заменить на tiny_alien.png.

follow_mouse.gif

(анимированный .gif немного резвый, но на экране он плавный)

0 голосов
/ 12 марта 2019

Эта версия вашего кода работает.Я думаю, что основная проблема - это комбинация enemy.alive по умолчанию False, и я не уверен в порядке перерисовки.

Поскольку мне приходилось заменять растровые изображения некоторыми собственными, я внес дополнительные изменения в параметры постоянного размера, в частности размер 50x50, но были и другие.

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

import random
import pygame
import sys
import time
from pygame import mixer

screenx = 800
screeny = 600

clock = pygame.time.Clock()

#PICTURES
name = pygame.display.set_caption('Brutal Survival')
win = pygame.display.set_mode((screenx,screeny))
player_right = pygame.image.load('maincharright.png')
player_left = pygame.image.load('maincharleft.png')
player_up = pygame.image.load('maincharup.png')
player_down = pygame.image.load('mainchardown.png')
background = pygame.image.load('background.jpg')
mummychar = pygame.image.load('mummychar.png')

# stretch background to fit window
background = pygame.transform.smoothscale( background, ( screenx, screeny) )

randomspawnabove = (random.randint(0, screenx), -100)
randomspawnbelow = (random.randint(0, screenx), (screeny + 100))
randomspawnleft = (-100, random.randint(0, screeny))
randomspawnright = ((screenx + 100), random.randint(0, screeny))

enemyalive = True
multiplier = 2
level = 1
nextlevel = True
spawn = True
up = True
down = False
left = False
right = False
run = True


class player():
    def __init__(self, x, y, width, height):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.alive = True
        self.vel = 5

class enemy():
    def __init__(self, x, y, width, height):
        self.x      = x
        self.y      = y
        self.width  = width
        self.height = height
        self.alive  = True
        self.vel    = 2

    def enemyfollow(self, player_pos):
        play_x, play_y = player_pos
        if self.alive == True and self.x > play_x:
            self.x = self.x - self.vel
        elif self.alive == True and self.x < play_x:
            self.x = self.x + self.vel
        if self.alive == True and self.y > play_y:
            self.y = self.y - self.vel
        elif self.alive == True and self.y < play_y:
            self.y = self.y + self.vel


def redrawScreen( player_image, Enemies ):
    win.blit(background, (0,0))
    win.blit(player_image, (mainChar.x, mainChar.y))
    for e in Enemies:
        if e.alive == True:
            win.blit(mummychar, (e.x, e.y))
    pygame.display.update()


mainChar     = player(screenx/2 - 30, screeny/2, 60, 60)
maxenemies   = (level * multiplier)
mummy_Spawn  = [randomspawnleft, randomspawnright, randomspawnabove, randomspawnbelow]
player_image = player_left

# Create some enemies:
Enemies = []
for x in range(maxenemies):
    Enemies.append(enemy(random.randrange(0, screenx), random.randrange(0, screeny), mummychar.get_rect().width, mummychar.get_rect().height))

while run:
    clock.tick(60)

    keys = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    for i in range(maxenemies):
        Enemies[i].enemyfollow( (mainChar.x, mainChar.y) )

    if nextlevel == True:
        if level >= 1:
            enemyalive = True

    if keys[pygame.K_ESCAPE]:
        run = False
    if keys[pygame.K_UP]:
        mainChar.y = mainChar.y - mainChar.vel
        player_image = player_up
    if keys[pygame.K_DOWN]:
        mainChar.y = mainChar.y + mainChar.vel
        player_image = player_down
    if keys[pygame.K_RIGHT]:
        mainChar.x = mainChar.x + mainChar.vel
        player_image = player_right
    if keys[pygame.K_LEFT]:
        mainChar.x = mainChar.x - mainChar.vel
        player_image = player_left

    if (mainChar.y + mainChar.height) > screeny:
        mainChar.y = mainChar.y - 5
    if mainChar.y < 0:
        mainChar.y = mainChar.y + 5
    if mainChar.x < 0:
        mainChar.x = mainChar.x + 5
    if (mainChar.x + mainChar.width) > screenx:
        mainChar.x = mainChar.x - 5

    redrawScreen( player_image, Enemies )

pygame.quit()
0 голосов
/ 12 марта 2019

часть оператора if была if self == True, но self было False

...