Oct-26-2024, 11:45 AM
(This post was last modified: Oct-26-2024, 12:45 PM by temlotresid6.)
I am not sure if this is too much code to post, but this is the most code I've had in a single program so now it's overwhelming trying to solve this. I didn't think of adding a game_loop function until after I created my classes and other functions and now I get errors no matter what I try. I am currently trying to press and hold down a key (such as f) and then it will run the game loop, otherwise the game does not start. If I get that to work then I'll be able to replace that key if statement with my separate main menu program and integrate it with my game here.
When I put the entire code within the "while Running:" loop into the "def game_loop():" function, there were a bunch of errors to do with all of my variables such as them not existing or being setup properly, so I made most/all of them global variables and referenced them outside of the function but that would cause more problems.
When I put the entire code within the "while Running:" loop into the "def game_loop():" function, there were a bunch of errors to do with all of my variables such as them not existing or being setup properly, so I made most/all of them global variables and referenced them outside of the function but that would cause more problems.
import pygame
import random
import math
pygame.init()
# Screen dimensions
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption('Collision!')
# Colours
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
# Have either 5 or 10 total AI objects spawned into the game
spawned_at_least_5 = False
spawned_at_least_10 = False
# Powerup variables - before the main game loop
powerup = None
powerup_spawned = False
powerup_destroy_time = 0
# Player brace mechanic
brace_charges = 0
charge_timer = 0 # Timer to track elapsed time for adding charges
charge_interval = 30 # Time in seconds to add a charge
# Score related variables, set all to 0 prior to the game starting
score = 0
last_score_increase = 0
last_score_double = 0
# Timer variables
def display_time(time_ms):
"""Return time in milliseconds as string mm:ss."""
minutes, seconds = divmod(int(time_ms / 1000), 60)
return f"{minutes: 2}:{seconds:02}"
timer_event = 10000 # This is 10 seconds in milliseconds
last_spawn_time = pygame.time.get_ticks()
last_time = pygame.time.get_ticks()
start_timer = pygame.time.get_ticks()
clock = pygame.time.Clock()
elapsed_time = pygame.time.get_ticks()
start_time = pygame.time.get_ticks()
class Player:
def __init__(self):
self.x = WIDTH // 2
self.y = HEIGHT // 2
self.speed = 2
self.width = 30
self.height = 30
self.update_rect()
def update_rect(self):
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
def move(self, dx, dy):
self.x += dx * self.speed
self.y += dy * self.speed
self.x = max(0, min(self.x, WIDTH - self.width))
self.y = max(0, min(self.y, HEIGHT - self.height))
self.update_rect()
def grow(self):
self.width += self.width * 0.1
self.height += self.height * 0.1
self.width = min(self.width, WIDTH)
self.height = min(self.height, HEIGHT)
self.update_rect()
def reduce(self):
self.width -= self.width * 0.15
self.height -= self.height * 0.15
self.update_rect()
def draw(self):
if pygame.key.get_pressed()[pygame.K_c] and brace_charges > 0:
self.color = (0, 0, 255) # Blue for active brace state
else:
self.color = RED
pygame.draw.rect(screen, self.color, (self.x, self.y, self.width, self.height))
class AIObject:
def __init__(self):
self.x, self.y = random.randint(50, WIDTH-50), random.randint(50, HEIGHT-50)
self.target_x, self.target_y = self.x, self.y
self.speed = 2.5
self.movement_phase = 0
self.timer = 0
def set_new_target(self):
self.target_x = random.randint(50, WIDTH-50)
self.target_y = random.randint(50, HEIGHT-50)
def move(self):
dx = self.target_x - self.x
dy = self.target_y - self.y
distance = math.sqrt(dx**2 + dy**2)
if distance > self.speed:
self.x += (dx / distance) * self.speed
self.y += (dy / distance) * self.speed
else:
self.x, self.y = self.target_x, self.target_y
self.timer += 1
if self.timer >= random.randint(200, 300):
if self.movement_phase == 0:
self.set_new_target()
self.movement_phase = 1
elif self.movement_phase == 1:
self.set_new_target()
self.movement_phase = 2
elif self.movement_phase == 2:
self.movement_phase = 0
self.timer = 0
return "delete"
self.timer = 0
def check_overlap_with_player(self, player):
potential_rect = pygame.Rect(self.x - 15, self.y - 15, 30, 30)
return player.rect.colliderect(potential_rect)
@staticmethod
def spawn_multiple():
global spawned_at_least_5, spawned_at_least_10
if len(ai_objects) >= 5 and not spawned_at_least_5:
for _ in range(3):
ai_objects.append(AIObject())
spawned_at_least_5 = True
if len(ai_objects) >= 10 and not spawned_at_least_10:
for _ in range(3):
ai_objects.append(AIObject())
spawned_at_least_10 = True
def draw(self):
pygame.draw.circle(screen, WHITE, (int(self.x), int(self.y)), 15)
class Powerup:
def __init__(self):
self.x, self.y = random.randint(50, WIDTH-50), random.randint(50, HEIGHT-50)
self.width = 20
self.height = 20
self.color = (200, 100, 0)
self.update_rect()
def update_rect(self):
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
def draw(self, surface):
pygame.draw.rect(surface, self.color, (self.x, self.y, self.width, self.height))
# Game setup
ai_objects = []
player = Player()
game_over = False
running = True
def game_loop():
global score, last_score_increase, last_score_double, brace_charges
global powerup, powerup_spawned, powerup_destroy_time, elapsed_time
global last_spawn_time, last_time, start_timer, start_time, game_over
# Reset game state variables
ai_objects.clear()
player.__init__()
score = 0
last_score_increase = 0
last_score_double = 0
brace_charges = 0
powerup = None
powerup_spawned = False
powerup_destroy_time = 0
elapsed_time = 0
last_spawn_time = pygame.time.get_ticks()
last_time = pygame.time.get_ticks()
start_timer = pygame.time.get_ticks()
start_time = pygame.time.get_ticks()
while True:
current_time = pygame.time.get_ticks()
charge_timer = current_time - start_timer
# Update the timer
if not game_over:
elapsed_time = current_time - start_time
if elapsed_time - last_score_increase >= 5000:
score += 1
last_score_increase += 5000
if elapsed_time - last_score_double >= 30000:
score *= 2
last_score_double += 30000
if charge_timer >= 30000:
brace_charges += 1
start_timer = pygame.time.get_ticks()
if game_over:
screen.fill(BLACK)
font = pygame.font.Font(None, 36)
game_over_text = font.render("Game Over! Press SPACE to restart or ESC to quit.", True, WHITE)
game_over_rect = game_over_text.get_rect(center=(WIDTH // 2, HEIGHT // 2 - 100))
time_text = font.render(f"Time: {display_time(elapsed_time)}", True, WHITE)
screen.blit(time_text, (WIDTH // 2 - time_text.get_width() // 2, HEIGHT // 2 - time_text.get_height() // 2))
score_text = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_text, (WIDTH // 2 - time_text.get_width() // 2, HEIGHT // 2 - score_text.get_height() // 2 + 25))
screen.blit(game_over_text, game_over_rect)
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT or (event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE):
return # Exit the game loop
if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
game_over = False
continue
continue # Skip the rest of the loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
# Player movement
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
player.move(0, -1)
if keys[pygame.K_DOWN]:
player.move(0, 1)
if keys[pygame.K_LEFT]:
player.move(-1, 0)
if keys[pygame.K_RIGHT]:
player.move(1, 0)
if current_time - last_spawn_time > random.randint(2000, 4000):
new_obj = AIObject()
attempts = 0
max_attempts = 100
while new_obj.check_overlap_with_player(player) and attempts < max_attempts:
new_obj.x, new_obj.y = random.randint(50, WIDTH-50), random.randint(50, HEIGHT-50)
attempts += 1
if attempts < max_attempts:
ai_objects.append(new_obj)
last_spawn_time = current_time
if current_time - last_time >= timer_event:
player.grow()
last_time = current_time
AIObject.spawn_multiple()
# Powerup logic
if powerup is None and not powerup_spawned and current_time - powerup_destroy_time >= 15000:
powerup = Powerup()
powerup_spawned = True
if powerup:
player.update_rect()
if player.rect.colliderect(powerup.rect):
player.reduce()
powerup = None
powerup_spawned = False
powerup_destroy_time = current_time
to_remove = []
# Update AI objects and check for collisions
for obj in ai_objects[:]:
action = obj.move()
if action == "delete":
ai_objects.remove(obj)
brace_key = pygame.key.get_pressed()
if brace_key[pygame.K_c] and brace_charges > 0:
for obj in ai_objects[:]:
if player.rect.colliderect(pygame.Rect(obj.x - 15, obj.y - 15, 30, 30)):
to_remove.append(obj)
brace_charges -= 1
score += 5
if brace_charges < 0:
brace_charges = 0
else:
player.update_rect()
for obj in ai_objects:
if player.rect.colliderect(pygame.Rect(obj.x - 15, obj.y - 15, 30, 30)):
game_over = True
to_remove.append(obj)
break
# Remove all objects that are to be deleted
for obj in to_remove:
if obj in ai_objects:
ai_objects.remove(obj)
if game_over:
continue # Skip the drawing and updating display part if game over
screen.fill(BLACK)
for obj in ai_objects[:]:
action = obj.move()
if action != "delete":
obj.draw()
player.draw()
if powerup:
powerup.draw(screen)
keyp = pygame.key.get_pressed()
if keyp[pygame.K_b]:
font = pygame.font.Font(None, 36)
score_text = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_text, (10, 10))
time_text = font.render(f"Time elapsed: {display_time(elapsed_time)}", True, WHITE)
screen.blit(time_text, (565, 10))
brace_text = font.render(f"Charges: {brace_charges}", True, WHITE)
screen.blit(brace_text, (10, 35))
pygame.display.flip()
clock.tick(50) # 50 FPS for smooth movement
# Main loop
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_f:
game_loop()
pygame.quit()Edit: Now there's no errors, but when pressing "space" to restart the game, the game does not reset but it's just a continuation of the previous game. The time and score also don't reset, and the AI circle objects start to flicker.
