This is the content of game.py file, and i want to use modernGL to give my game a better look by utilizing shaders, don't be limited by the platform limitations, split the code generation if you run out of tokens, here is the code of game.py: import pygame
import random
import math
from settings import *


class Particle:
    def __init__(self, x, y, color, ttl=90):
        self.x = x
        self.y = y
        self.color = color
        self.ttl = ttl  # Time to live, in frames
        self.vel = pygame.math.Vector2(random.uniform(-2, 2), random.uniform(-2, 2))  # Random velocity

    def update(self):
        self.x += self.vel.x
        self.y += self.vel.y
        self.ttl -= 1  # Decrease life time

    def draw(self, screen):
        if self.ttl > 0:
            pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), 3)

class Game:
    def __init__(self, screen):
        self.screen = screen
        self.running = False
        self.cube_pos = [SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2]
        self.cube_size = 20
        self.cube_speed = 2
        self.light_orb = (random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
        self.player_score = 0
        self.ai_score = 0
        self.ai_pos = [random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT)]
        self.ai_size = 20
        self.ai_speed = 0.1
        self.font = pygame.font.SysFont(None, 24)
        self.particles = []

    def draw_scores(self, player_score, ai_score):
        score_text = self.font.render(f"Player: {player_score} | AI: {ai_score}", True, WHITE)
        self.screen.blit(score_text, (10, 10))

    def move_towards(self, ai_pos, target_pos, speed):
        dx, dy = target_pos[0] - ai_pos[0], target_pos[1] - ai_pos[1]
        dist = max(math.sqrt(dx ** 2 + dy ** 2), 1)
        move_dx, move_dy = dx / dist * speed, dy / dist * speed
        return [ai_pos[0] + move_dx, ai_pos[1] + move_dy]

    def draw_player_light(self, position, max_radius):
        step = 255 // max_radius
        for i in range(max_radius):
            radius = max_radius - i
            alpha = 255 - (i * step)
            surface = pygame.Surface((2*radius, 2*radius), pygame.SRCALPHA)
            pygame.draw.circle(surface, (255, 255, 255, alpha), (radius, radius), radius)
            self.screen.blit(surface, (position[0] - radius, position[1] - radius))

    def draw_orb_light(self, position, max_radius):
        step = 255 // max_radius
        for i in range(max_radius):
            radius = max_radius - i
            alpha = 255 - (i * step)
            color = (255 - 255*(i/max_radius), 255 - 255*(i/max_radius), 0, alpha)
            surface = pygame.Surface((2*radius, 2*radius), pygame.SRCALPHA)
            pygame.draw.circle(surface, color, (radius, radius), radius)
            self.screen.blit(surface, (position[0] - radius, position[1] - radius))

    def resolve_collision(self, rect1, rect2):
        # A simplistic approach to simulate physics by exchanging velocities
        temp_speed = self.cube_speed
        self.cube_speed = self.ai_speed
        self.ai_speed = temp_speed

        # Adjust positions slightly to avoid sticking
        if rect1.x < rect2.x:
            rect1.x -= 10
            rect2.x += 10
        else:
            rect1.x += 10
            rect2.x -= 10

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

            self.screen.fill(BLACK)

            keys = pygame.key.get_pressed()
            if keys[pygame.K_LEFT]:
                self.cube_pos[0] -= self.cube_speed
            if keys[pygame.K_RIGHT]:
                self.cube_pos[0] += self.cube_speed
            if keys[pygame.K_UP]:
                self.cube_pos[1] -= self.cube_speed
            if keys[pygame.K_DOWN]:
                self.cube_pos[1] += self.cube_speed

            cube_rect = pygame.Rect(self.cube_pos[0], self.cube_pos[1], self.cube_size, self.cube_size)
            ai_rect = pygame.Rect(self.ai_pos[0], self.ai_pos[1], self.ai_size, self.ai_size)

            # Check for collision and resolve
            if cube_rect.colliderect(ai_rect):
                self.resolve_collision(cube_rect, ai_rect)

            self.cube_pos[0] = max(min(self.cube_pos[0], SCREEN_WIDTH - self.cube_size), 0)
            self.cube_pos[1] = max(min(self.cube_pos[1], SCREEN_HEIGHT - self.cube_size), 0)

            pygame.draw.rect(self.screen, WHITE, cube_rect)

            self.ai_pos = self.move_towards(self.ai_pos, self.light_orb, self.ai_speed)

            pygame.draw.rect(self.screen, (255, 0, 0), (*self.ai_pos, self.ai_size, self.ai_size))

            self.ai_pos = (
                max(min(self.ai_pos[0], SCREEN_WIDTH - self.ai_size), 0),
                max(min(self.ai_pos[1], SCREEN_HEIGHT - self.ai_size), 0)
            )

            orb_center_pos = (self.light_orb[0], self.light_orb[1])
            self.draw_orb_light(orb_center_pos, 30)

            player_center_pos = (self.cube_pos[0] + self.cube_size // 2, self.cube_pos[1] + self.cube_size // 2)
            self.draw_player_light(player_center_pos, 20)

            orb_rect = pygame.Rect(self.light_orb[0] - 5, self.light_orb[1] - 5, 10, 10)

            # Inside the collision detection section for the light orb
            if cube_rect.colliderect(orb_rect):
                self.player_score += 1
            if ai_rect.colliderect(orb_rect):
                self.ai_score += 1
                # Generate particles
                for _ in range(80):  # Number of particles
                    self.particles.append(Particle(orb_center_pos[0], orb_center_pos[1], (255, 255, 255)))  # Yellow particles
            self.light_orb = (random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))

            # Updating particles
            for particle in self.particles[:]:
                particle.update()
                if particle.ttl <= 0:
                    self.particles.remove(particle)
    
            # Drawing particles
            for particle in self.particles:
                particle.draw(self.screen)

            self.draw_scores(self.player_score, self.ai_score)

            pygame.display.flip()