user13695798
user13695798

Reputation:

How do I randomly spawn enemy elsewhere after collision in pygame?

for some reason when I collide with the enemy it randomly spawns elsewhere which is all fine but when I un-collide the enemy goes back to its original position here is the full code down below. If you run this code see what happens. Im looking for the red block to spawn in a random other location when the blue box collides with it.

import pygame
import random

# places where enemies can spawn (2 to make it simple at first)
enemy_locations = [100, 200]


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

# frames per second
fps = 30

# colors
background_color = (255, 255, 255)
player_color = (0, 0, 255)
enemy_color = (255, 0, 0)

# width and height of screen
width = 1000
height = 800

# screen
screen = pygame.display.set_mode((width, height))

# x, y coordinates player
player_x = 300
player_y = 300

# ememy x, y coordinates
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)

# new x, y coordinates for enemy player
new_x = random.choice(enemy_locations)
new_y = random.choice(enemy_locations)

# draw player
def draw():
    enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
    player_rect = pygame.Rect(player_x, player_y, 25, 25)

    if player_rect.colliderect(enemy_rect):
        enemy = pygame.draw.rect(screen, enemy_color, (new_x, new_y, 25, 25))
    else:
        enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)

    player = pygame.draw.rect(screen, player_color, player_rect)

# pygame loop (always include)
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # controls for player object
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player_x -= 10
            if event.key == pygame.K_RIGHT:
                player_x += 10
            if event.key == pygame.K_UP:
                player_y -= 10
            if event.key == pygame.K_DOWN:
                player_y += 10

    draw()
    pygame.display.update()
    screen.fill(background_color)
    clock.tick(fps)

Upvotes: 1

Views: 505

Answers (3)

Rabbid76
Rabbid76

Reputation: 210909

You have to create a new random enemy position when the player collides with the enemy

if player_rect.colliderect(enemy_rect):
    enemy_x = random.choice(enemy_locations)
    enemy_y = random.choice(enemy_locations)

Use the global statement, to interpreted the variables enemy_x and enemy_y as global. With the statement global it is possible to write to variables in the global namespace within a function:

global enemy_x, enemy_y

Function draw:

def draw():
    global enemy_x, enemy_y

    enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
    player_rect = pygame.Rect(player_x, player_y, 25, 25)

    if player_rect.colliderect(enemy_rect):
        enemy_x = random.choice(enemy_locations)
        enemy_y = random.choice(enemy_locations)
        
    enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
    player = pygame.draw.rect(screen, player_color, player_rect)

Upvotes: 1

Benjamin
Benjamin

Reputation: 3448

The draw method explicitly states to draw enemy rect either in the initial point or in some ONE random point. The random point is selected only once - during the start of an application. You should set the random point every time there is a collision in a draw method, e.g.

if player_rect.colliderect(enemy_rect):
    enemy_x = random.choice(enemy_locations)
    enemy_y = random.choice(enemy_locations)

Upvotes: 1

kaktus_car
kaktus_car

Reputation: 986

As others have said you either need to add more "locations" to the list or better, use random.randint(), and also enemy's coordinates does not "get random"(or updated in any way) after every collision, but only once when you initialize them. I added new function get_new_coord() which will return the random number(I use these limits so the enemy won't go off the screen), which gets called once for every coordinate after each collision. Also I moved player_rect and enemy_rect outside of the loop, and now draw() returns enemy_rect so it can stay updated if collision occurs.

This is a quick fix to your code, you should consider using Classes. And of course if you want to do so, I could help you with transforming the code.

import pygame
import random

# places where enemies can spawn (2 to make it simple at first)
enemy_locations = [100, 200]


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

# frames per second
fps = 30

# colors
background_color = (255, 255, 255)
player_color = (0, 0, 255)
enemy_color = (255, 0, 0)

# width and height of screen
width = 1000
height = 800

# screen
screen = pygame.display.set_mode((width, height))

# x, y coordinates player
player_x = 300
player_y = 300

# ememy x, y coordinates
enemy_x = random.choice(enemy_locations)
enemy_y = random.choice(enemy_locations)

# new x, y coordinates for enemy player
new_x = random.choice(enemy_locations)
new_y = random.choice(enemy_locations)

def get_new_coord():
    return random.randint(0, 800-25)

# draw player
def draw(player_rect, enemy_rect):

    screen.fill(background_color)

    if player_rect.colliderect(enemy_rect):
        enemy_rect = pygame.Rect(get_new_coord(), get_new_coord(), 25, 25)
        enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)
    else:
        enemy = pygame.draw.rect(screen, enemy_color, enemy_rect)

    player = pygame.draw.rect(screen, player_color, player_rect)

    pygame.display.update()

    return enemy_rect


# pygame loop (always include)
running = True
enemy_rect = pygame.Rect(enemy_x, enemy_y, 25, 25)
player_rect = pygame.Rect(player_x, player_y, 25, 25)

while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # controls for player object
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player_rect.x -= 10
            if event.key == pygame.K_RIGHT:
                player_rect.x += 10
            if event.key == pygame.K_UP:
                player_rect.y -= 10
            if event.key == pygame.K_DOWN:
                player_rect.y += 10

    enemy_rect = draw(player_rect, enemy_rect)

    clock.tick(fps)

Upvotes: 0

Related Questions