This commit is contained in:
2025-01-19 23:50:23 +02:00
parent a646ea7e0f
commit 0469021ff3
7 changed files with 237 additions and 3 deletions

36
asteroid.py Normal file
View File

@@ -0,0 +1,36 @@
import pygame
from circleshape import CircleShape
from constants import *
import random
class Asteroid(CircleShape):
def __init__(self, x, y, radius):
super().__init__(x, y, radius)
def draw(self, screen):
pygame.draw.circle(screen, pygame.Color(255, 255, 255), self.position, self.radius, 2)
def update(self, dt):
self.position += self.velocity * dt
def split(self):
self.kill()
if self.radius <= ASTEROID_MIN_RADIUS:
return
angle = random.uniform(20, 50)
new1 = Asteroid(self.position.x, self.position.y, self.radius - ASTEROID_MIN_RADIUS)
new1.velocity = self.velocity
new1.velocity = new1.velocity.rotate(angle)
new1.velocity *= 1.2
new2 = Asteroid(self.position.x, self.position.y, self.radius - ASTEROID_MIN_RADIUS)
new2.velocity = self.velocity
new2.velocity = new2.velocity.rotate(-angle)
new2.velocity *= 1.2

51
asteroidfield.py Normal file
View File

@@ -0,0 +1,51 @@
import pygame
import random
from asteroid import Asteroid
from constants import *
class AsteroidField(pygame.sprite.Sprite):
edges = [
[
pygame.Vector2(1, 0),
lambda y: pygame.Vector2(-ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT),
],
[
pygame.Vector2(-1, 0),
lambda y: pygame.Vector2(
SCREEN_WIDTH + ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT
),
],
[
pygame.Vector2(0, 1),
lambda x: pygame.Vector2(x * SCREEN_WIDTH, -ASTEROID_MAX_RADIUS),
],
[
pygame.Vector2(0, -1),
lambda x: pygame.Vector2(
x * SCREEN_WIDTH, SCREEN_HEIGHT + ASTEROID_MAX_RADIUS
),
],
]
def __init__(self):
pygame.sprite.Sprite.__init__(self, self.containers)
self.spawn_timer = 0.0
def spawn(self, radius, position, velocity):
asteroid = Asteroid(position.x, position.y, radius)
asteroid.velocity = velocity
def update(self, dt):
self.spawn_timer += dt
if self.spawn_timer > ASTEROID_SPAWN_RATE:
self.spawn_timer = 0
# spawn a new asteroid at a random edge
edge = random.choice(self.edges)
speed = random.randint(40, 100)
velocity = edge[0] * speed
velocity = velocity.rotate(random.randint(-30, 30))
position = edge[1](random.uniform(0, 1))
kind = random.randint(1, ASTEROID_KINDS)
self.spawn(ASTEROID_MIN_RADIUS * kind, position, velocity)

29
circleshape.py Normal file
View File

@@ -0,0 +1,29 @@
import pygame
# Base class for game objects
class CircleShape(pygame.sprite.Sprite):
def __init__(self, x, y, radius):
# we will be using this later
if hasattr(self, "containers"):
super().__init__(self.containers)
else:
super().__init__()
self.position = pygame.Vector2(x, y)
self.velocity = pygame.Vector2(0, 0)
self.radius = radius
def draw(self, screen):
# sub-classes must override
pass
def update(self, dt):
# sub-classes must override
pass
def is_collission(self, obj):
distance = self.position.distance_to(obj.position)
if (distance <= self.radius + obj.radius):
return True
return False

View File

@@ -4,4 +4,12 @@ SCREEN_HEIGHT = 720
ASTEROID_MIN_RADIUS = 20
ASTEROID_KINDS = 3
ASTEROID_SPAWN_RATE = 0.8 # seconds
ASTEROID_MAX_RADIUS = ASTEROID_MIN_RADIUS * ASTEROID_KINDS
ASTEROID_MAX_RADIUS = ASTEROID_MIN_RADIUS * ASTEROID_KINDS
PLAYER_RADIUS = 20
PLAYER_TURN_SPEED = 300
PLAYER_SPEED = 200
PLAYER_SHOOT_SPEED = 500
SHOT_RADIUS = 5
PLAYER_SHOOT_COOLDOWN=0.3

45
main.py
View File

@@ -1,5 +1,10 @@
import pygame
import sys
from constants import *
from player import Player
from asteroid import Asteroid
from shot import Shot
from asteroidfield import AsteroidField
def main():
@@ -10,16 +15,52 @@ def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
updatable = pygame.sprite.Group()
drawable = pygame.sprite.Group()
asteroids = pygame.sprite.Group()
shots = pygame.sprite.Group()
clock = pygame.time.Clock()
dt = 0
player = Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
drawable.add(player)
updatable.add(player)
Player.containers = (updatable, drawable)
Asteroid.containers = (asteroids, updatable, drawable)
AsteroidField.containers = (updatable)
Shot.containers = (shots, updatable, drawable)
asteroidField = AsteroidField()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
return
dt = clock.tick(60)/1000
for entity in updatable:
entity.update(dt)
for entity in asteroids:
if player.is_collission(entity):
print("Game Over!")
sys.exit(0)
for bullet in shots:
if bullet.is_collission(entity):
entity.split()
bullet.kill()
continue
screen.fill(pygame.Color(0, 0, 0), pygame.Rect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT))
for entity in drawable:
entity.draw(screen)
pygame.display.flip()
if __name__ == "__main__":
main()

53
player.py Normal file
View File

@@ -0,0 +1,53 @@
from circleshape import CircleShape
from constants import *
from shot import Shot
import pygame
class Player(CircleShape):
def __init__(self, x, y):
super().__init__(x, y, PLAYER_RADIUS)
self.rotation = 0
self.cooldown = 0
# in the player class
def triangle(self):
forward = pygame.Vector2(0, 1).rotate(self.rotation)
right = pygame.Vector2(0, 1).rotate(self.rotation + 90) * self.radius / 1.5
a = self.position + forward * self.radius
b = self.position - forward * self.radius - right
c = self.position - forward * self.radius + right
return [a, b, c]
def draw(self, screen):
super().draw(screen)
pygame.draw.polygon(screen, pygame.Color(255, 255, 255), self.triangle(), 2)
def rotate(self, dt):
self.rotation += PLAYER_TURN_SPEED * dt
def update(self, dt):
keys = pygame.key.get_pressed()
self.cooldown -= dt
if keys[pygame.K_a]:
self.rotate(-dt)
if keys[pygame.K_d]:
self.rotate(dt)
if keys[pygame.K_w]:
self.move(dt)
if keys[pygame.K_s]:
self.move(-dt)
if keys[pygame.K_SPACE]:
self.shoot()
def move(self, dt):
forward = pygame.Vector2(0, 1).rotate(self.rotation)
self.position += forward * PLAYER_SPEED * dt
def shoot(self):
if self.cooldown > 0:
return
self.cooldown = PLAYER_SHOOT_COOLDOWN
shot = Shot(self.position.x, self.position.y)
shot.velocity = pygame.Vector2(0, 1).rotate(self.rotation) * PLAYER_SHOOT_SPEED

16
shot.py Normal file
View File

@@ -0,0 +1,16 @@
import pygame
from circleshape import CircleShape
from constants import *
class Shot(CircleShape):
def __init__(self, x, y):
super().__init__(x, y, SHOT_RADIUS)
def draw(self, screen):
pygame.draw.circle(screen, pygame.Color(255, 255, 255), self.position, self.radius, 2)
def update(self, dt):
self.position += self.velocity * dt