commit
bd6a3f7492
7 changed files with 235 additions and 0 deletions
@ -0,0 +1,4 @@ |
|||||||
|
__pycache__ |
||||||
|
*/__pycache__/ |
||||||
|
venv/ |
||||||
|
|
@ -0,0 +1,121 @@ |
|||||||
|
#!/usr/bin/env python3 |
||||||
|
from sys import argv |
||||||
|
import pygame as pg |
||||||
|
# locals |
||||||
|
from ship import Ship |
||||||
|
from starfield import Starfield |
||||||
|
|
||||||
|
|
||||||
|
# Colors |
||||||
|
BLACK = (0,)*3 |
||||||
|
WHITE = (255,)*3 |
||||||
|
|
||||||
|
# Graphical Environment |
||||||
|
WIN_SIZE = (640, 480) |
||||||
|
MAX_FPS = 60 |
||||||
|
|
||||||
|
# Game constants |
||||||
|
|
||||||
|
# Sprite positions |
||||||
|
start = (0,0) |
||||||
|
|
||||||
|
# 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() |
||||||
|
|
||||||
|
map_rect = pg.Rect( |
||||||
|
(start[0]-scr_rect.width/2, |
||||||
|
start[1]-scr_rect.height/2), |
||||||
|
scr_rect.size |
||||||
|
) |
||||||
|
|
||||||
|
the_starfield = Starfield(screen); |
||||||
|
|
||||||
|
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(gems,blocks) |
||||||
|
|
||||||
|
# Game loop |
||||||
|
carry_on = True |
||||||
|
win = False |
||||||
|
|
||||||
|
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 ### |
||||||
|
|
||||||
|
mouse_events = pg.mouse.get_pressed() |
||||||
|
if mouse_events[0]: |
||||||
|
the_ship.deceleration = 0 |
||||||
|
the_ship.velocity += 1 |
||||||
|
if mouse_events[2]: |
||||||
|
the_ship.deceleration = 1 |
||||||
|
|
||||||
|
mousev = pg.math.Vector2(pg.mouse.get_pos()) |
||||||
|
mousev -= scr_rect.center |
||||||
|
|
||||||
|
# ship movement |
||||||
|
if mousev.length() > the_ship.SIZE/2: |
||||||
|
the_ship.direction += mousev.normalize()/(the_ship.velocity+1) |
||||||
|
the_ship.direction.normalize_ip() |
||||||
|
|
||||||
|
the_ship.velocity = max(the_ship.velocity - the_ship.deceleration, 0) |
||||||
|
if the_ship.velocity == 0: |
||||||
|
the_ship.deceleration = 0 |
||||||
|
|
||||||
|
# Move ship |
||||||
|
the_ship.change = (the_ship.velocity*the_ship.direction) |
||||||
|
the_ship.map_pos.x += round(the_ship.change.x) |
||||||
|
the_ship.map_pos.y += round(the_ship.change.y) |
||||||
|
|
||||||
|
# Move camera to follow ship |
||||||
|
map_rect.x = the_ship.map_pos.x - map_rect.w/2 |
||||||
|
map_rect.y = the_ship.map_pos.y - map_rect.h/2 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Display Logic ### |
||||||
|
screen.fill(BLACK) |
||||||
|
|
||||||
|
the_starfield.draw(screen, map_rect) |
||||||
|
|
||||||
|
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)) |
||||||
|
|
||||||
|
pg.display.flip() |
||||||
|
clock.tick(MAX_FPS) |
||||||
|
|
||||||
|
pg.quit() |
@ -0,0 +1,4 @@ |
|||||||
|
pip==22.2.2 |
||||||
|
pygame==2.1.2 |
||||||
|
setuptools==63.2.0 |
||||||
|
wheel==0.37.1 |
@ -0,0 +1,38 @@ |
|||||||
|
import pygame as pg |
||||||
|
from sprite import Sprite |
||||||
|
|
||||||
|
|
||||||
|
SHAPE = [(6,3), (1,5), (2,3), (1,1)] |
||||||
|
|
||||||
|
class Ship(Sprite): |
||||||
|
SIZE = 40 |
||||||
|
COLOR =(255,0,0) |
||||||
|
def __init__(self, pos, scr_rect): |
||||||
|
super().__init__((self.SIZE,)*2) |
||||||
|
self.map_pos = pg.math.Vector2(pos) |
||||||
|
u = self.SIZE//6 |
||||||
|
self.shape = [pg.math.Vector2(p[0]*u,p[1]*u) for p in SHAPE] |
||||||
|
self.rect.x = scr_rect.centerx - self.rect.width / 2 |
||||||
|
self.rect.y = scr_rect.centery - self.rect.height / 2 |
||||||
|
self.velocity = 0 |
||||||
|
self.deceleration = 0 |
||||||
|
self.direction = pg.math.Vector2((1,0)) |
||||||
|
self.change = pg.math.Vector2((0,0)) |
||||||
|
|
||||||
|
def update(self, rot_vector): |
||||||
|
center = self.SIZE/2 |
||||||
|
def rotate(p): |
||||||
|
x0 = p[0]-center |
||||||
|
y0 = p[1]-center |
||||||
|
x1 = x0 * rot_vector.x - y0 * rot_vector.y |
||||||
|
y1 = x0 * rot_vector.y + y0 * rot_vector.x |
||||||
|
return (x1 + center, y1 + center) |
||||||
|
new_shape = list(map(rotate, self.shape)) |
||||||
|
self.image.fill(self.image.get_colorkey()) |
||||||
|
pg.draw.polygon(self.image, self.COLOR, new_shape) |
||||||
|
|
||||||
|
@property |
||||||
|
def map_rect(self): |
||||||
|
return pg.Rect( |
||||||
|
(self.map_pos.x-self.SIZE/2+1, self.map_pos.y-self.SIZE/2+1), |
||||||
|
(self.SIZE-2, self.SIZE-2)) |
@ -0,0 +1,15 @@ |
|||||||
|
|
||||||
|
import pygame as pg |
||||||
|
|
||||||
|
PINK = (255,0,255) |
||||||
|
|
||||||
|
class Sprite(pg.sprite.Sprite): |
||||||
|
|
||||||
|
def __init__(self, size): |
||||||
|
super().__init__() |
||||||
|
self.image = pg.Surface(size) |
||||||
|
self.image.fill(PINK) |
||||||
|
self.image.set_colorkey(PINK) |
||||||
|
self.rect = self.image.get_rect() |
||||||
|
|
||||||
|
|
@ -0,0 +1,41 @@ |
|||||||
|
import pygame as pg |
||||||
|
import random |
||||||
|
|
||||||
|
WHITE = (255,)*3 |
||||||
|
|
||||||
|
def snap(x, scale): |
||||||
|
return int(x//scale)*scale |
||||||
|
|
||||||
|
|
||||||
|
class Starfield: |
||||||
|
|
||||||
|
def __init__(self, |
||||||
|
screen, |
||||||
|
inv_density=10, |
||||||
|
grid_step=31, |
||||||
|
paralax = 2, |
||||||
|
star_color=WHITE, |
||||||
|
star_size = 1): |
||||||
|
self.rng = random.Random() |
||||||
|
self.screen = screen |
||||||
|
self.inv_density = inv_density |
||||||
|
self.paralax = paralax |
||||||
|
self.grid_step = grid_step |
||||||
|
self.star_color = star_color |
||||||
|
self.star_size = star_size |
||||||
|
|
||||||
|
def draw(self, screen, map_pos): |
||||||
|
sky_pos = pg.math.Vector2((map_pos.x, map_pos.y))/self.paralax |
||||||
|
xstart = snap(sky_pos.x, self.grid_step) |
||||||
|
ystart = snap(sky_pos.y, self.grid_step) |
||||||
|
xstop = xstart + screen.get_rect().width |
||||||
|
ystop = ystart + screen.get_rect().width |
||||||
|
for x in range(xstart, xstop, self.grid_step): |
||||||
|
for y in range(ystart, ystop, self.grid_step): |
||||||
|
self.rng.seed(hash((x,y))) |
||||||
|
if self.rng.randint(0, self.inv_density) == 0: |
||||||
|
xoff = self.rng.randint(0, self.grid_step) |
||||||
|
yoff = self.rng.randint(0, self.grid_step) |
||||||
|
cx = x + xoff - sky_pos.x |
||||||
|
cy = y + yoff - sky_pos.y |
||||||
|
pg.draw.circle(screen, self.star_color, (cx,cy), self.star_size) |
@ -0,0 +1,12 @@ |
|||||||
|
import pygame as pg |
||||||
|
import pytest |
||||||
|
from ship import Ship |
||||||
|
|
||||||
|
def test_ship_constructor(): |
||||||
|
scr_rect = pg.Rect(0,0,100,100) |
||||||
|
a_ship = Ship((10+Ship.SIZE/2, 20+Ship.SIZE/2), scr_rect) |
||||||
|
assert a_ship.rect.centerx == scr_rect.centerx |
||||||
|
assert a_ship.rect.centery == scr_rect.centery |
||||||
|
assert a_ship.map_rect.left == 10+1 |
||||||
|
assert a_ship.map_rect.top == 20+1 |
||||||
|
|
Loading…
Reference in new issue