Skip to content

Commit 867572b

Browse files
committed
game logic
1 parent 45e6d1a commit 867572b

7 files changed

+190
-1
lines changed

asteroid.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from circleshape import *
2+
from constants import *
3+
import random
4+
5+
class Asteroid(CircleShape):
6+
def __init__(self, x, y, radius):
7+
super().__init__(x, y, radius)
8+
9+
def split(self):
10+
self.kill()
11+
if self.radius <= ASTEROID_MIN_RADIUS:
12+
return
13+
angle = random.uniform(20, 51)
14+
velocity_1 = self.velocity.rotate(angle)
15+
velocity_2 = self.velocity.rotate(-angle)
16+
radius = self.radius - ASTEROID_MIN_RADIUS
17+
a_1 = Asteroid(self.position.x, self.position.y, radius)
18+
a_2 = Asteroid(self.position.x, self.position.y, radius)
19+
a_1.velocity = velocity_1 * 1.2
20+
a_2.velocity = velocity_2 * 1.2
21+
22+
def draw(self, screen):
23+
pygame.draw.circle(screen, "white", self.position, self.radius, 2)
24+
25+
def update(self, dt):
26+
self.position += self.velocity * dt
27+

asteroidfield.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import pygame
2+
import random
3+
from asteroid import Asteroid
4+
from constants import *
5+
6+
7+
class AsteroidField(pygame.sprite.Sprite):
8+
edges = [
9+
[
10+
pygame.Vector2(1, 0),
11+
lambda y: pygame.Vector2(-ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT),
12+
],
13+
[
14+
pygame.Vector2(-1, 0),
15+
lambda y: pygame.Vector2(
16+
SCREEN_WIDTH + ASTEROID_MAX_RADIUS, y * SCREEN_HEIGHT
17+
),
18+
],
19+
[
20+
pygame.Vector2(0, 1),
21+
lambda x: pygame.Vector2(x * SCREEN_WIDTH, -ASTEROID_MAX_RADIUS),
22+
],
23+
[
24+
pygame.Vector2(0, -1),
25+
lambda x: pygame.Vector2(
26+
x * SCREEN_WIDTH, SCREEN_HEIGHT + ASTEROID_MAX_RADIUS
27+
),
28+
],
29+
]
30+
31+
def __init__(self):
32+
pygame.sprite.Sprite.__init__(self, self.containers)
33+
self.spawn_timer = 0.0
34+
35+
def spawn(self, radius, position, velocity):
36+
asteroid = Asteroid(position.x, position.y, radius)
37+
asteroid.velocity = velocity
38+
39+
def update(self, dt):
40+
self.spawn_timer += dt
41+
if self.spawn_timer > ASTEROID_SPAWN_RATE:
42+
self.spawn_timer = 0
43+
44+
# spawn a new asteroid at a random edge
45+
edge = random.choice(self.edges)
46+
speed = random.randint(40, 100)
47+
velocity = edge[0] * speed
48+
velocity = velocity.rotate(random.randint(-30, 30))
49+
position = edge[1](random.uniform(0, 1))
50+
kind = random.randint(1, ASTEROID_KINDS)
51+
self.spawn(ASTEROID_MIN_RADIUS * kind, position, velocity)

circleshape.py

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ def __init__(self, x, y, radius):
1313
self.velocity = pygame.Vector2(0, 0)
1414
self.radius = radius
1515

16+
def is_colliding(self, other):
17+
distance = self.position.distance_to(other.position)
18+
return distance <= self.radius + other.radius
19+
1620
def draw(self, screen):
1721
# sub-classes must override
1822
pass

constants.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
SCREEN_WIDTH = 1280
22
SCREEN_HEIGHT = 720
3+
34
ASTEROID_MIN_RADIUS = 20
45
ASTEROID_KINDS = 3
56
ASTEROID_SPAWN_RATE = 0.8
6-
ASTEROID_MAX_RADIUS = ASTEROID_MIN_RADIUS * ASTEROID_KINDS
7+
ASTEROID_MAX_RADIUS = ASTEROID_MIN_RADIUS * ASTEROID_KINDS
8+
9+
PLAYER_RADIUS = 20
10+
PLAYER_TURN_SPEED = 300
11+
PLAYER_SPEED = 200
12+
PLAYER_SHOOT_SPEED = 500
13+
PLAYER_SHOOT_COOLDOWN = .3
14+
15+
SHOT_RADIUS = 5

main.py

+35
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import pygame
22
from constants import *
3+
from player import *
4+
from asteroid import *
5+
from asteroidfield import *
6+
from shot import *
37

48
def main():
59
print("Starting asteroids!")
@@ -9,11 +13,42 @@ def main():
913
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
1014
clock = pygame.time.Clock()
1115
dt = 0
16+
updatable = pygame.sprite.Group()
17+
drawable = pygame.sprite.Group()
18+
asteroids = pygame.sprite.Group()
19+
shots = pygame.sprite.Group()
20+
21+
Player.containers = (updatable, drawable)
22+
player = Player(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
23+
24+
Asteroid.containers = (asteroids, updatable, drawable)
25+
AsteroidField.containers = (updatable)
26+
asteroid_field = AsteroidField()
27+
28+
Shot.containers = (shots, updatable, drawable)
29+
1230
while True:
1331
for event in pygame.event.get():
1432
if event.type == pygame.QUIT:
1533
return
34+
35+
for obj in updatable:
36+
obj.update(dt)
37+
38+
for asteroid in asteroids:
39+
for shot in shots:
40+
if shot.is_colliding(asteroid):
41+
asteroid.split()
42+
break
43+
if asteroid.is_colliding(player):
44+
raise SystemExit("Game over!")
45+
46+
1647
screen.fill((0, 0, 0))
48+
49+
for obj in drawable:
50+
obj.draw(screen)
51+
1752
pygame.display.flip()
1853
dt = clock.tick(60) / 1000
1954

player.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from circleshape import *
2+
from constants import *
3+
from shot import *
4+
5+
class Player(CircleShape):
6+
7+
def __init__(self, x, y):
8+
super().__init__(x, y, PLAYER_RADIUS)
9+
self.rotation = 0
10+
self.shot_cooldown = 0
11+
12+
# in the player class
13+
def triangle(self):
14+
forward = pygame.Vector2(0, 1).rotate(self.rotation)
15+
right = pygame.Vector2(0, 1).rotate(self.rotation + 90) * self.radius / 1.5
16+
a = self.position + forward * self.radius
17+
b = self.position - forward * self.radius - right
18+
c = self.position - forward * self.radius + right
19+
return [a, b, c]
20+
21+
def draw(self, screen):
22+
pygame.draw.polygon(screen, "white", self.triangle(), 2)
23+
24+
def rotate(self, dt):
25+
self.rotation += PLAYER_TURN_SPEED * dt
26+
27+
def move(self, dt):
28+
self.position += pygame.Vector2(0, 1).rotate(self.rotation) * PLAYER_SPEED * dt
29+
30+
def shoot(self):
31+
if self.shot_cooldown > 0:
32+
return
33+
self.shot_cooldown = PLAYER_SHOOT_COOLDOWN
34+
shot = Shot(self.position.x, self.position.y)
35+
shot.velocity = pygame.Vector2(0, 1).rotate(self.rotation) * PLAYER_SHOOT_SPEED
36+
37+
def update(self, dt):
38+
keys = pygame.key.get_pressed()
39+
self.shot_cooldown -= dt
40+
41+
if keys[pygame.K_a]:
42+
self.rotate(dt * -1)
43+
if keys[pygame.K_d]:
44+
self.rotate(dt)
45+
if keys[pygame.K_w]:
46+
self.move(dt)
47+
if keys[pygame.K_s]:
48+
self.move(dt * -1)
49+
if keys[pygame.K_SPACE]:
50+
self.shoot()

shot.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from circleshape import *
2+
from constants import *
3+
4+
class Shot(CircleShape):
5+
def __init__(self, x, y):
6+
super().__init__(x, y, SHOT_RADIUS)
7+
8+
def update(self, dt):
9+
self.position += self.velocity * dt
10+
11+
def draw(self, screen):
12+
return pygame.draw.circle(screen, "white", self.position, self.radius, 2)
13+

0 commit comments

Comments
 (0)