From 0927040d8dd13b9a927c9bd14447e6bb4b999e18 Mon Sep 17 00:00:00 2001 From: mian Date: Mon, 19 Sep 2022 14:12:56 +0300 Subject: [PATCH] made it --- asteroid.py | 57 +++++++++++++ crosshair.py | 27 ++++++ main.py | 227 +++++++++++++++++++++++++++++++-------------------- ship.py | 20 ++--- torpedo.py | 6 +- 5 files changed, 235 insertions(+), 102 deletions(-) create mode 100644 asteroid.py create mode 100644 crosshair.py diff --git a/asteroid.py b/asteroid.py new file mode 100644 index 0000000..0315e33 --- /dev/null +++ b/asteroid.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 + diff --git a/crosshair.py b/crosshair.py new file mode 100644 index 0000000..bca582b --- /dev/null +++ b/crosshair.py @@ -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 diff --git a/main.py b/main.py index 7a1024a..278611a 100755 --- a/main.py +++ b/main.py @@ -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() diff --git a/ship.py b/ship.py index 4614b07..a3ff200 100644 --- a/ship.py +++ b/ship.py @@ -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)) diff --git a/torpedo.py b/torpedo.py index 7b230c3..fb03864 100644 --- a/torpedo.py +++ b/torpedo.py @@ -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)