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.