从各个方向随机产生玩家周围的敌人

时间:2019-08-05 15:07:08

标签: python pygame

敌人是从屏幕上方生成的,然后向中间的玩家移动,我想在屏幕周围从各个方向随机生成敌人,而不是在屏幕内部直接生成敌人,然后继续向玩家和敌人的精灵移动有时会加入结合并一起行动以击退敌人的精灵。

我尝试使用随机范围更改敌人对象的x,y坐标,但有时它们会在播放屏幕内生成对象,我希望敌人在播放窗口外生成。

class Mob(pg.sprite.Sprite):
    def __init__(self):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.image.load('enemy.png').convert_alpha()
        self.image = pg.transform.smoothscale(pg.image.load('enemy.png'), (33, 33))
        self.image_orig = self.image.copy()
        self.radius = int(29 * .80 / 2)
        self.rect = self.image.get_rect()
        self.rect.x = random.randrange(width - self.rect.width)
        self.rect.y = random.randrange(-100, -40)
        self.speed = 4
        self.rot = 0
        self.rot_speed = 5
        self.last_update = pg.time.get_ticks()

    def rotate(self):
        now = pg.time.get_ticks()
        if now - self.last_update > 50:
            self.last_update = now
            self.rot = (self.rot + self.rot_speed) % 360
            new_image = pg.transform.rotozoom(self.image_orig, self.rot, 1)
            old_center = self.rect.center
            self.image = new_image
            self.rect = self.image.get_rect()
            self.rect.center = old_center

    def update(self):
        self.rotate()
        dirvect = pg.math.Vector2(rotator.rect.x - self.rect.x,
                                  rotator.rect.y- self.rect.y)
        if dirvect.length_squared() > 0:
            dirvect = dirvect.normalize()

            # Move along this normalized vector towards the player at current speed.
        if dirvect.length_squared() > 0:
            dirvect.scale_to_length(self.speed)
        self.rect.move_ip(dirvect)
        if self.rect.top > height + 10 or self.rect.left < -25 or self.rect.right > width + 20:
            self.rect.x = random.randrange(width - self.rect.width)
            self.rect.y = random.randrange(-100, -40)
            self.speed = random.randrange(1, 4)

[更新] 这剩下的代码:

import math
import random
import os
import pygame as pg
import sys

pg.init()
height = 650
width = 1200

os_x = 100
os_y = 45
os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (os_x, os_y)

screen = pg.display.set_mode((width, height), pg.NOFRAME)
screen_rect = screen.get_rect()
background = pg.image.load('background.png').convert()
background = pg.transform.smoothscale(pg.image.load('background.png'), (width, height))
clock = pg.time.Clock()
running = True

font_name = pg.font.match_font('Bahnschrift', bold=True)


def draw_text(surf, text, size, x, y, color):
   [...]


class Mob(pg.sprite.Sprite):
[...]    

class Rotator(pg.sprite.Sprite):
    def __init__(self, screen_rect):
        pg.sprite.Sprite.__init__(self)
        self.screen_rect = screen_rect
        self.master_image = pg.image.load('spaceship.png').convert_alpha()
        self.master_image = pg.transform.smoothscale(pg.image.load('spaceship.png'), (33, 33))
        self.radius = 12
        self.image = self.master_image.copy()
        self.rect = self.image.get_rect(center=[width / 2, height / 2])
        self.delay = 10
        self.timer = 0.0
        self.angle = 0
        self.distance = 0
        self.angle_offset = 0

    def get_angle(self):
        mouse = pg.mouse.get_pos()
        offset = (self.rect.centerx - mouse[0], self.rect.centery - mouse[1])
        self.angle = math.degrees(math.atan2(*offset)) - self.angle_offset
        old_center = self.rect.center
        self.image = pg.transform.rotozoom(self.master_image, self.angle, 1)
        self.rect = self.image.get_rect(center=old_center)
        self.distance = math.sqrt((offset[0] * offset[0]) + (offset[1] * offset[1]))

    def update(self):
        self.get_angle()
        self.display = 'angle:{:.2f} distance:{:.2f}'.format(self.angle, self.distance)
        self.dx = 1
        self.dy = 1
        self.rect.clamp_ip(self.screen_rect)

    def draw(self, surf):
        surf.blit(self.image, self.rect)

    def shoot(self, mousepos):
        dx = mousepos[0] - self.rect.centerx
        dy = mousepos[1] - self.rect.centery
        if abs(dx) > 0 or abs(dy) > 0:
            bullet = Bullet(self.rect.centerx, self.rect.centery, dx, dy)
            all_sprites.add(bullet)
            bullets.add(bullet)

1 个答案:

答案 0 :(得分:2)

这里没有太多信息,但是您可能需要检查播放窗口的x和y范围,并确保生成的随机生成坐标不在此范围内:

在您的初始化中:

# These are just example min/max values. Maybe pass these as arguments to your __init__ method.
min_x = min_y = -1000
max_x = max_y = 1000
min_playwindow_x = min_playwindow_y = 500
max_playwindow_x = max_playwindow_y = 600

self.x = (random.randrange(min_x, min_playwindow_x), random.randrange(max_playwindow_x, max_x))[random.randrange(0,2)]

self.y = (random.randrange(min_y, min_playwindow_y), random.randrange(max_playwindow_y, max_y))[random.randrange(0,2)]

该解决方案基本上可以在任何设置中工作。对于x和y,它将在播放窗口之外生成一个值的元组。然后,coinflip决定该值。这样只会生成对角线在运动场外的小怪,但始终会生成有效的随机坐标。

另一种方法是根据需要生成任意数量的随机变量,以获取有效的对,例如:


while min_playingwindow_x <= self.x <= max_playingwindow_x and 
      min_playingwindow_y <= self.y <= max_playingwindow_y:
    # While within screen(undesired) calculate new random positions
    self.x = random.randrange(min_x, max_x)
    self.y = random.randrange(min_y, max_y)

这真的很慢,但是如果您的有效职位数量(例如)仅为总职位的1%。

如果您需要真正充实的内容,则需要知道地图的角和实际显示的矩形,我认为这比整个地图要小(否则,您无法在视线之外生成敌人。

(0,0)
+----------------------+
|           A          |
|-----+-----------+----|
|  D  |      W    | B  |
|-----+-----------+----|
|          C           |
+----------------------+(max_x, max_y)

在此图中,W是玩家可以手动看到的窗口,而A,B,C,D一起是地图上当前不可见的部分。由于您只想在玩家视野之外生成生物,因此需要确保生成的坐标在地图内部和视野之外:

def generate_coordinates_outside_of_view(map_width=1000, map_height=1000, view_window_top_left=(100, 100),
                                         view_width=600, view_height=400):
    """
    A very over the top way to generate coordinates outside surrounding a rectangle within a map almost without bias
    :param map_width: width of map in pixels (note that 0,0 on the map is top left)
    :param map_height: height of map in pixels
    :param view_window_top_left: top left point(2-tuple of ints) of visible part of map
    :param view_width: width of view in pixels
    :param view_height: height of view in pixels
    """
    from random import randrange

    # generate 2 samples for each x and y, one guaranteed to be random, and one outside the view for sure.
    x = (randrange(0, map_width), (randrange(0, view_window_top_left[0]),
          randrange(view_window_top_left[0] + view_width, map_width))[randrange(0, 2)])
    y = (randrange(0, map_height), (randrange(0, view_window_top_left[1]),
          randrange(view_window_top_left[1] + view_height, map_height))[randrange(0, 2)])

    # now we have 4 values. To get a point outside our view we have to return a point where at least 1 of the
    # values x/y is guaranteed to be outside the view.

    if randrange(0, 2) == 1:  # to be almost completely unbiased we randomize the check
        selection_x = randrange(0, 2)
        selection_y = randrange(0, 2) if selection_x == 1 else 1
    else:
        selection_y = randrange(0, 2)
        selection_x = randrange(0, 2) if selection_y == 1 else 1

    return x[selection_x], y[selection_y]

HTH