master
mian 2 years ago
parent 956b8cf83f
commit 0927040d8d
  1. 57
      asteroid.py
  2. 27
      crosshair.py
  3. 227
      main.py
  4. 20
      ship.py
  5. 6
      torpedo.py

@ -0,0 +1,57 @@
import pygame as pg
from sprite import Sprite
from random import randint
class Asteroid(Sprite):
COOLTIME = 15
SPEED = 2
COLOR = (0,0,255)
BASE_SIZE = 30
N_CHILDREN = 2
def __init__(self, map_rect=None, map_pos=(0,0), velocity=(0, SPEED), size_lev=3):
self.size = size_lev * self.BASE_SIZE
self.size_lev = size_lev
super().__init__((self.size,)*2)
self.image.fill(self.image.get_colorkey())
pg.draw.circle(
self.image,
self.COLOR,
self.image.get_rect().center,
self.image.get_rect().width/2,
)
self.map_pos = pg.math.Vector2(map_pos)
if map_rect is not None:
if randint(0,1)==0:
self.map_pos.x = 0 if randint(0,1)==0 else map_rect.width -1
self.map_pos.y = randint(0,map_rect.height-1)
else:
self.map_pos.y = 0 if randint(0,1)==0 else map_rect.height -1
self.map_pos.x = randint(0,map_rect.width-1)
self.velocity = pg.math.Vector2(velocity)
self.velocity.rotate_ip(randint(0,359))
def update(self, map_rect):
self.map_pos += self.velocity
self.map_pos.x %= map_rect.w
self.map_pos.y %= map_rect.h
self.rect.x = (self.map_pos.x - self.rect.w/2 - map_rect.x) % map_rect.w
self.rect.y = (self.map_pos.y - self.rect.w/2 - map_rect.y) % map_rect.h
def breakup(self):
new_size = self.size_lev-1
self.kill()
children = list()
if new_size > 0:
for i in range(self.N_CHILDREN):
children.append(Asteroid(
map_pos=self.map_pos.copy(),
velocity=self.velocity.copy()*1.2,
size_lev=new_size,
))
return children

@ -0,0 +1,27 @@
import pygame as pg
from sprite import Sprite
SIZE = 24
UNIT = SIZE//4
COLOR =(255,0,0)
C_POINT = (2,2)
SHAPE = (
(0,1), C_POINT, (4,1),
(3,0), C_POINT, (3,4),
(4,3), C_POINT, (0,3),
(1,4), C_POINT, (1,0),
)
class Crosshair(Sprite):
def __init__(self, scr_rect):
super().__init__((SIZE,)*2)
self.rect.x = scr_rect.centerx - self.rect.width / 2
self.rect.y = scr_rect.centery - self.rect.height / 2
self.image.fill(self.image.get_colorkey())
scaled_shape = [(x*UNIT, y*UNIT) for x, y in SHAPE]
pg.draw.polygon(self.image, COLOR, scaled_shape)
def update(self, new_pos):
self.rect.x = new_pos.x - self.rect.width / 2
self.rect.y = new_pos.y - self.rect.height / 2

@ -1,31 +1,31 @@
#!/usr/bin/env python3
from sys import argv
from sys import argv, exit
import pygame as pg
# locals
from ship import Ship
from starfield import Starfield
from torpedo import Torpedo
from asteroid import Asteroid
# Colors
BLACK = (0,)*3
WHITE = (255,)*3
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
# Graphical Environment
WIN_SIZE = (1280, 960)
MAX_FPS = 60
# Game constants
## Game constants
N_ASTEROIDS_START = 3
# Sprite positions
start = (0,0)
start = (WIN_SIZE[0]//2,WIN_SIZE[1]//2)
# Setup
## Setup
pg.init()
clock = pg.time.Clock()
font = pg.font.SysFont('Courier',24)
pg.display.set_caption(f"Space Collector")
screen = pg.display.set_mode(WIN_SIZE)
scr_rect = screen.get_rect()
@ -38,88 +38,137 @@ map_rect = pg.Rect(
scr_rect.size
)
the_starfield = Starfield(screen, grid_step=40, paralax=1);
the_ship = Ship(start,scr_rect)
the_ship.rect.x = scr_rect.centerx - the_ship.rect.width / 2
the_ship.rect.y = scr_rect.centery - the_ship.rect.height / 2
disp_sprites = pg.sprite.Group()
moving = pg.sprite.Group()
# Game loop
carry_on = True
win = False
cooling = 0
while carry_on:
# Quitting states
for event in pg.event.get():
if event.type == pg.QUIT:
carry_on = False
elif event.type==pg.KEYDOWN:
if event.key==pg.K_ESCAPE:
carry_on = False
### Game Logic ###
mousev = pg.math.Vector2(pg.mouse.get_pos())
mousev -= scr_rect.center
keyboard_events = pg.key.get_pressed()
# ship direction
if mousev.length() > the_ship.SIZE/2:
the_ship.direction += mousev.normalize()
the_ship.direction.normalize_ip()
font = pg.font.SysFont('Sans',24)
big_font = pg.font.SysFont('Sans',56)
if keyboard_events[pg.key.key_code('w')]:
the_ship.velocity += the_ship.direction / 2**0.5
# Move ship
the_ship.map_pos.x += round(the_ship.velocity.x) % map_rect.w
the_ship.map_pos.y += round(the_ship.velocity.y) % map_rect.h
# Move camera to follow ship
map_rect.x = (the_ship.map_pos.x - map_rect.w/2) % map_rect.w
map_rect.y = (the_ship.map_pos.y - map_rect.h/2) % map_rect.h
# Torpedoes
if keyboard_events[pg.key.key_code("space")] and cooling <= 0:
disp_sprites.add(Torpedo(scr_rect, the_ship.map_pos, the_ship.direction, the_ship.velocity))
cooling = Torpedo.COOLTIME
elif cooling > 0:
cooling -= 1
### Display Logic ###
screen.fill(BLACK)
the_starfield.draw(screen, map_rect, (map_rect.w, map_rect.h))
disp_sprites.update(map_rect=map_rect)
disp_sprites.draw(screen)
the_ship.update(rot_vector= the_ship.direction)
screen.blit(the_ship.image, the_ship.rect)
if True:
elapsed_time = pg.time.get_ticks()/1000
elapsed_minutes = int(elapsed_time // 60)
elapsed_seconds = int(elapsed_time // 1) % 60
time_string = f"{elapsed_minutes:d}:{elapsed_seconds:02d}"
time_label = font.render(time_string, 1, WHITE)
time_pos = (screen.get_width()-10-time_label.get_width(),10)
screen.blit(time_label, time_pos)
gem_str = f"Level Complete!"
gem_label = font.render(gem_str,True, WHITE)
screen.blit(gem_label, (10, 10))
the_starfield = Starfield(screen, grid_step=40, paralax=1);
pg.display.flip()
clock.tick(MAX_FPS)
while True:
# Game setup
start_time = pg.time.get_ticks()
the_ship = Ship(start,scr_rect)
the_ship.rect.x = scr_rect.centerx - the_ship.rect.width / 2
the_ship.rect.y = scr_rect.centery - the_ship.rect.height / 2
moving = pg.sprite.Group()
asteroids = pg.sprite.Group()
torpedoes = pg.sprite.Group()
for i in range(N_ASTEROIDS_START):
tmp = Asteroid(map_rect)
asteroids.add(tmp)
moving.add(tmp)
gun_cooldown = 0
win = False
lose = False
carry_on = True
# Game loop
while carry_on:
# Quitting states
for event in pg.event.get():
if event.type == pg.QUIT:
pg.quit()
exit()
elif event.type==pg.KEYDOWN:
if event.key==pg.K_ESCAPE:
pg.quit()
exit()
elif event.key == pg.K_r:
carry_on = False
if not (win or lose):
### Game Logic ###
mousev = pg.math.Vector2(pg.mouse.get_pos()) - scr_rect.center
keyboard_events = pg.key.get_pressed()
mouse_events = pg.mouse.get_pressed()
# ship direction
if mousev.length() > the_ship.SIZE/2:
the_ship.direction += mousev.normalize()
the_ship.direction.normalize_ip()
# Move ship
if keyboard_events[pg.K_SPACE]:
the_ship.velocity += the_ship.direction / 2
the_ship.map_pos.x += round(the_ship.velocity.x) % map_rect.w
the_ship.map_pos.y += round(the_ship.velocity.y) % map_rect.h
# Move camera to follow ship
map_rect.x = (the_ship.map_pos.x - map_rect.w/2) % map_rect.w
map_rect.y = (the_ship.map_pos.y - map_rect.h/2) % map_rect.h
# Torpedoes
if mouse_events[0] and gun_cooldown <= 0:
tmp = Torpedo(
scr_rect,
the_ship.map_pos,
the_ship.direction,
the_ship.velocity,
)
moving.add(tmp)
torpedoes.add(tmp)
gun_cooldown = Torpedo.COOLTIME
elif gun_cooldown > 0:
gun_cooldown -= 1
# Collisions
for an_asteroid in asteroids:
for a_torpedo in moving.sprites():
if an_asteroid.rect.colliderect(a_torpedo.rect):
if isinstance(a_torpedo, Torpedo):
a_torpedo.kill()
children = an_asteroid.breakup()
moving.add(children)
asteroids.add(children)
if an_asteroid.rect.colliderect(the_ship.rect):
lose = True
# Win state
if len([s for s in moving if isinstance(s, Asteroid)]) == 0:
win = True
### Display Logic ###
screen.fill(BLACK)
the_starfield.draw(screen, map_rect, (map_rect.w, map_rect.h))
moving.update(map_rect=map_rect)
moving.draw(screen)
the_ship.update(rot_vector= the_ship.direction)
screen.blit(the_ship.image, the_ship.rect)
if not (win or lose):
elapsed_time = (pg.time.get_ticks()-start_time)/1000
elapsed_minutes = int(elapsed_time // 60)
elapsed_seconds = int(elapsed_time // 1) % 60
time_string = f"{elapsed_minutes:d}:{elapsed_seconds:02d}"
time_label = font.render(time_string, 1, WHITE)
time_pos = (screen.get_width()-10-time_label.get_width(),10)
screen.blit(time_label, time_pos)
if win or lose:
if win:
big_label = big_font.render("You win!",1, GREEN, BLACK)
else:
big_label = big_font.render("You lose!",1, BLUE, BLACK)
big_pos = (
(screen.get_width()-big_label.get_width())/2,
(screen.get_height()-big_label.get_height())/2,
)
screen.blit(big_label, big_pos)
pg.display.flip()
clock.tick(MAX_FPS)
pg.quit()

@ -1,18 +1,18 @@
import pygame as pg
from sprite import Sprite
COLOR =(0,255,0)
SIZE = 40
U = SIZE // 6
SHAPE = [(6,3), (1,5), (2,3), (1,1)]
class Ship(Sprite):
COLOR =(0,255,0)
SIZE = 40
U = SIZE // 6
SHAPE = [(6,3), (1,5), (2,3), (1,1)]
def __init__(self, pos, scr_rect):
super().__init__((SIZE,)*2)
super().__init__((self.SIZE,)*2)
self.map_pos = pg.math.Vector2(pos)
self.shape = [pg.math.Vector2(p[0]*U,p[1]*U) for p in SHAPE]
self.shape = [pg.math.Vector2(p[0]*self.U,p[1]*self.U) for p in self.SHAPE]
self.rect.x = scr_rect.centerx - self.rect.width / 2
self.rect.y = scr_rect.centery - self.rect.height / 2
self.velocity = pg.math.Vector2((0,0))
@ -30,10 +30,10 @@ class Ship(Sprite):
return (x1 + center, y1 + center)
new_shape = list(map(rotate, self.shape))
self.image.fill(self.image.get_colorkey())
pg.draw.polygon(self.image, COLOR, new_shape)
pg.draw.polygon(self.image, self.COLOR, new_shape)
@property
def map_rect(self):
return pg.Rect(
(self.map_pos.x-SIZE/2+1, self.map_pos.y-SIZE/2+1),
(SIZE-2, SIZE-2))
(self.map_pos.x-self.SIZE/2+1, self.map_pos.y-self.SIZE/2+1),
(self.SIZE-2, self.SIZE-2))

@ -1,13 +1,13 @@
import pygame as pg
from sprite import Sprite
SPEED = 4
SPEED = 6
COLOR = (255,0,0)
SIZE = 12
LIFETIME = 60
LIFETIME = 90
class Torpedo(Sprite):
COOLTIME = 15
COOLTIME = 10
def __init__(self, scr_rect, map_pos, direction, velocity):
super().__init__((SIZE,)*2)

Loading…
Cancel
Save