0

The code currently works as intended except for the enemy updater function, it is only okayish. I dont have a problem detecting collision my problem is updating the enemy's positions based on it, some still merge together before they separate again. Wondering if there is other conditions I can add to make it work better.

i know my code is bad, and that I should use a self-class along with other classes, but this is my first project and id like to keep it simple for my to understand, yet i know it is disorganized.

This is my current code, any help would be appreciated.

import pygame
import random

# initialize pygame
pygame.init()

# create the window
window = pygame.display.set_mode((400, 300))


def shoot():
        flag = True
        closest_block = determine_closest_enemy()
        if closest_block:
            bullets.append((bullet_block, player_block_x, player_block_y, 0.0, 0.0))
            for i, bullet in enumerate(bullets):
                bullet[0].fill(block_color)
                x, y = closest_block[1], closest_block[2]
                direction_x, direction_y = x - bullet[1], y - bullet[2]
                distance = ((direction_x ** 2) + (direction_y ** 2)) ** 0.5
                speed = 1.3
                direction_x, direction_y = (direction_x / distance) * speed, (direction_y / distance) * speed
            bullets[i] = (block[0], player_block_x, player_block_y, direction_x, direction_y)
        flag = False
                
def determine_closest_enemy():
    closest_distance = float('inf')
    for i, block in enumerate(enemy_blocks):
        closest_block = block
        x = block[1]
        y = block[2]
        distance = ((x - player_block_x) ** 2 + (y - player_block_y) ** 2) ** 0.5
    if distance < closest_distance:
        closest_distance = distance
        closest_block = block
    return closest_block

def super_far_delete():
    global spawn_rate
    screen_distance = 500
    width = player_block_x 
    height = player_block_y
    for i, block in enumerate(enemy_blocks):
        distance = 320
        width = player_block_x 
        height = player_block_y
        enemy_x, enemy_y = block[1], block[2]
        if abs(enemy_x) > width + distance or abs(enemy_y) > height + distance:
            if block in enemy_blocks:
                enemy_blocks.remove(block)
                spawn_rate += 1
        if abs(bullet[1]) > width + screen_distance or abs(bullet[2]) > height + screen_distance:
            if bullet in bullets:
                    bullets.remove(bullet)
                            
def check_enemy_collision():
    distance = 15
    OFFSET = 0.14
    for i, block1 in enumerate(enemy_blocks):
        for j, block2 in enumerate(enemy_blocks):
            if i == j:
                continue
            enemy1_x, enemy1_y = block1[1], block1[2]
            enemy2_x, enemy2_y = block2[1], block2[2]
            x_diff = block1[1] - block2[1]
            y_diff = block1[2] - block2[2]
            if x_diff**2 <= distance**2:
                offset = OFFSET if x_diff > 0 else -OFFSET
                enemy1_x += offset
                enemy2_x -= offset
                enemy_blocks[i] = (block1[0], enemy1_x, enemy1_y)
                enemy_blocks[j] = (block2[0], enemy2_x, enemy2_y)
            if y_diff**2 <= distance**2:
                offset = OFFSET if y_diff > 0 else -OFFSET
                enemy1_y += offset
                enemy2_y -= offset
                enemy_blocks[i] = (block1[0], enemy1_x, enemy1_y)
                enemy_blocks[j] = (block2[0], enemy2_x, enemy2_y)

def check_collision_forplayer():
    for i, block in enumerate(enemy_blocks):
        distance = 20 # set the threshold distance collision to player
        x = block[1]
        y = block[2]
        if ((x - player_block_x) ** 2 + (y - player_block_y) ** 2) ** 0.5 <= distance:
            if block in enemy_blocks:
                enemy_blocks.remove(block)
    
    for i, block in enumerate(enemy_blocks):
        for i, bullet in enumerate(bullets):
            x = block[1]
            y = block[2]
            targetx = bullet[1] 
            targety = bullet[2]
            hitbox = 10 # set the hitbox of bullet
            if ((x - targetx) ** 2 + (y - targety) ** 2) ** 0.5 <= hitbox:
                if block in enemy_blocks:
                    enemy_blocks.remove(block)
                if bullet in bullets:
                    bullets.remove(bullet)
            super_far_delete()
def check_valid_spawn(enemy_block_x_randomreturn, enemy_block_y_randomreturn):
    for i, block in enumerate(enemy_blocks):
        distance = 40 # set the threshold distance of spawning
        x = block[1]
        y = block[2]
        if ((x - enemy_block_x_randomreturn) ** 2 + (y - enemy_block_y_randomreturn) ** 2) ** 0.5 <= distance:
            return False
    return True
def determine_spawn_side(screen_width, screen_height, enemy_blocks):
    while True:
        width, height = enemy_blocks.get_size()
        edge = random.choice(['left', 'right', 'top', 'bottom'])
        if edge == 'left':
            pos = (0 - width, random.randint(0, screen_height - height ))
            return pos
        elif edge == 'right':
            pos = (screen_width + width , random.randint(0, screen_height - height ))
            return pos
        elif edge == 'top':
            pos = (random.randint(0, screen_width + width), 0 - height)
            return pos
        elif edge == 'bottom':
            pos = (random.randint(0, screen_width - width ), screen_height + height )
            return pos
def converge_on_player():
    for i, block in enumerate(enemy_blocks):
        enemy1_x, enemy1_y = block[1], block[2]
        direction_x, direction_y = player_block_x - enemy1_x, player_block_y - enemy1_y
        distance = ((direction_x ** 2) + (direction_y ** 2)) ** 0.5
        speed = 1.25 - min(distance / 50.0, 1.0)
        direction_x, direction_y = direction_x / distance, direction_y / distance
        enemy1_x += direction_x * speed
        enemy1_y += direction_y * speed
        enemy_blocks[i] = (block[0], enemy1_x, enemy1_y)
        



# create the background
background = pygame.Surface((window.get_width(), window.get_height()))
# set the background color
background_color = (255, 255, 255)
background.fill(background_color)
# define the color of the block
block_color = (0, 128, 255)

# create the player block
player_block = pygame.Surface((40, 40))
player_block.fill(block_color)
# create bullet block
bullet_block = pygame.Surface((5, 5))

bullets = []
#flag to see if space is up to make it only shoot once
global flag
flag = True
# create a spawn requirments
spawn_count = 0
spawn_rate = 100
# create a list of enemy blocks
enemy_blocks = []
last_spawn = 0
last_shoot = 0
bullet_count = 0
enemy_block = pygame.Surface((10, 10))
# create the clock object
clock = pygame.time.Clock()
# run the game loop
running = True
while running:
    clock.tick(60)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    
    # get current time to compare
    current_time = pygame.time.get_ticks()
    # define the player position
    player_block_x = (window.get_width() - player_block.get_width()) / 2
    player_block_y = (window.get_height() - player_block.get_height()) / 2
    # get the state of the keyboard buttons
    keys = pygame.key.get_pressed()
    #movement inputs and movement increments
    x_velocity = 0
    y_velocity = 0
    if keys[pygame.K_UP]:
        y_velocity = -.6
    if keys[pygame.K_DOWN]:
        y_velocity = .6
    if keys[pygame.K_LEFT]:
        x_velocity = -.6
    if keys[pygame.K_RIGHT]:
        x_velocity = .6
    if keys[pygame.K_SPACE]:
        if flag == True:
            #changes how often u can shoot
            if current_time - last_shoot > 800:
                shoot()
                last_shoot = current_time
    if not keys[pygame.K_SPACE]:
            #changes amount of bullets fired
            if current_time - last_shoot > 800:
                flag = True
    

    #spawn enemies
    
    if spawn_count < spawn_rate and current_time - last_spawn > 400:#400 min before collison sucks
        if spawn_count == 0:
            enemy_block_x, enemy_block_y = determine_spawn_side(window.get_width(), window.get_height(), enemy_block)
            enemy_blocks.append((enemy_block, enemy_block_x, enemy_block_y))
            enemy_block.fill(block_color)
            spawn_count += 1
            last_spawn = current_time
        elif spawn_count >= 1:
            enemy_block_x_randomreturn, enemy_block_y_randomreturn = determine_spawn_side(window.get_width(), window.get_height(), enemy_block)
            if check_valid_spawn(enemy_block_x_randomreturn, enemy_block_y_randomreturn) == True:
                enemy_blocks.append((enemy_block, enemy_block_x_randomreturn, enemy_block_y_randomreturn))
                enemy_block.fill(block_color)
                spawn_count += 1
                last_spawn = current_time
    
    # draw the background to the window
    window.blit(background, (0, 0))

    #draw the bullets
    for i, bullet in enumerate(bullets):
        window.blit(bullet_block, (bullet[1], bullet[2]))
        bullets[i] = (bullet[0], bullet[1]-bullet[3] - x_velocity, bullet[2]-bullet[4] - y_velocity, bullet[3], bullet[4])

    # display enemies and update movement
    for i, block in enumerate(enemy_blocks):
        window.blit(block[0], (block[1], block[2]))
        enemy_blocks[i] = (block[0], block[1]-x_velocity, block[2]-y_velocity)
    
    # draw the player block to the window
    window.blit(player_block, (player_block_x, player_block_y))

    # converge enemys on player
    converge_on_player()
    # check for player enemy collison
    check_collision_forplayer()
    check_enemy_collision()


    # update the display
    pygame.display.update()
pygame.quit()

0 Answers0