From bd6a3f74929d2a02274e3e8bb8ec0738a2d2a930 Mon Sep 17 00:00:00 2001 From: mian Date: Fri, 16 Sep 2022 11:16:20 +0300 Subject: [PATCH] Init; Striped down SpaceCollector --- .gitignore | 4 ++ main.py | 121 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ++ ship.py | 38 +++++++++++++++ sprite.py | 15 ++++++ starfield.py | 41 ++++++++++++++++ test_units.py | 12 +++++ 7 files changed, 235 insertions(+) create mode 100644 .gitignore create mode 100755 main.py create mode 100644 requirements.txt create mode 100644 ship.py create mode 100644 sprite.py create mode 100644 starfield.py create mode 100644 test_units.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a7f42e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +*/__pycache__/ +venv/ + diff --git a/main.py b/main.py new file mode 100755 index 0000000..51c7e83 --- /dev/null +++ b/main.py @@ -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() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..eaac041 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +pip==22.2.2 +pygame==2.1.2 +setuptools==63.2.0 +wheel==0.37.1 diff --git a/ship.py b/ship.py new file mode 100644 index 0000000..8e2d5a3 --- /dev/null +++ b/ship.py @@ -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)) diff --git a/sprite.py b/sprite.py new file mode 100644 index 0000000..d36dd9c --- /dev/null +++ b/sprite.py @@ -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() + + diff --git a/starfield.py b/starfield.py new file mode 100644 index 0000000..0c11a82 --- /dev/null +++ b/starfield.py @@ -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) diff --git a/test_units.py b/test_units.py new file mode 100644 index 0000000..5d45e74 --- /dev/null +++ b/test_units.py @@ -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 +