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()