Created
September 19, 2018 11:59
-
-
Save kyb3r/04414b7560625af5ab7d1d5efbff7d12 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from functools import partial | |
| import random | |
| class Point: | |
| def __init__(self, row=0, col=0): | |
| self.r = row | |
| self.c = col | |
| def __eq__(self, other): | |
| return self.r == other.r and self.c == other.c | |
| class Part(Point): | |
| def __repr__(self): | |
| return 'x' | |
| class Entity(Point): | |
| '''Represents an entity that can be interacted with in the game''' | |
| def __init__(self, *position, game): | |
| super().__init__(*position) | |
| self.game = game | |
| def is_inside_grid(self, r, c): | |
| return ( | |
| r < len(self.game.grid) | |
| and r >= 0 | |
| and c < len(self.game.grid[0]) | |
| and c >= 0 | |
| ) | |
| def move(self): | |
| raise NotImplemented | |
| class Missile(Entity): | |
| '''Represents a missile''' | |
| def destroy(self): | |
| '''Removes the missile from game''' | |
| self.game.missiles.remove(self) | |
| def move(self): | |
| '''Moves the missile down''' | |
| if not self.is_inside_grid(self.r + 1, self.c): | |
| self.destroy() | |
| else: | |
| self.r += 1 | |
| def __repr__(self): | |
| return '#' | |
| class Player(Entity): | |
| '''Represents the player and all it's parts''' | |
| def __init__(self, row, col, game): | |
| super().__init__(row, col, game=game) | |
| self.health = 20 | |
| self.parts = [ # modify this to change player structure | |
| self, # midpoint | |
| Part(row, col+1), | |
| Part(row, col-1), | |
| Part(row+1, col+1), | |
| Part(row+1, col-1), | |
| Part(row-1, col), | |
| Part(row-2, col), | |
| Part(row-3, col) | |
| ] | |
| def __repr__(self): | |
| return 'o' | |
| @property | |
| def lifeleft(self): | |
| self.health -= 1 | |
| if self.health == 0: | |
| return False | |
| else: | |
| return True | |
| def move(self, delta): | |
| '''Updates the location of the player and all its parts''' | |
| if any(not self.is_inside_grid(part.r + delta[0], part.c + delta[1]) for part in self.parts): | |
| return # moving would go outside grid so dont do it | |
| for part in self.parts: | |
| part.r += delta[0] | |
| part.c += delta[1] | |
| print(f'Moving: {delta}') | |
| def rotate(self, direction): | |
| '''Rotates all parts with the player location being the pivot''' | |
| new_locations = [] | |
| for part in self.parts[1:]: | |
| new_row = (direction) * (part.c - self.c) + self.r | |
| new_col = (-direction) * (part.r - self.r) + self.c | |
| new_locations.append(Point(new_row, new_col)) | |
| if any(not self.is_inside_grid(point.r, point.c) for point in new_locations): | |
| return | |
| for i, part in enumerate(self.parts[1:]): | |
| part.r = new_locations[i].r | |
| part.c = new_locations[i].c | |
| print(f'Rotating: {direction}') | |
| class Game: | |
| '''Algorithms assignment game implemented in python cos i was bored''' | |
| def __init__(self): | |
| self.running = True | |
| self.reset() | |
| def reset(self): | |
| '''Resets everything''' | |
| self.player = Player(10, 5, game=self) | |
| self.ticks = 0 | |
| self.max_missiles = 2 # number of missiles on screen | |
| self.missiles = [] | |
| self.clear_grid() | |
| def clear_grid(self): | |
| '''Clears the grid''' | |
| self.grid = [['.'] * 20 for _ in range(20)] | |
| def display(self): | |
| '''Prints out the grid in an aesthetically pleasing way''' | |
| for row in self.grid: | |
| print(" ".join(str(i) for i in row)) | |
| print(f'Health: {self.player.health}/20') | |
| def run(self): | |
| '''Game loop''' | |
| while self.running: | |
| if not self.ticks: # display initial grid | |
| self.update_grid() | |
| self.display() | |
| mappings = { # cleaner than a million if elifs | |
| "w": partial(self.player.move, delta=(-1, 0)), | |
| "a": partial(self.player.move, delta=(0, -1)), | |
| "d": partial(self.player.move, delta=(0, 1)), | |
| "q": partial(self.player.rotate, direction=-1), | |
| "e": partial(self.player.rotate, direction=1), | |
| "quit": self.end, | |
| "": lambda *args: None # do nothing | |
| } | |
| cmd = input('> ').strip().lower() | |
| function = mappings.get( | |
| cmd, lambda *args: print("Invalid command entered.") | |
| ) | |
| function() # do the thing u wanted to do | |
| if cmd != 'w': # move down anyways | |
| self.player.move(delta=(1, 0)) | |
| for missile in self.missiles: | |
| missile.move() # move missiles down | |
| self.check_collisions() | |
| self.spawn_missiles() | |
| self.update_grid() | |
| self.display() | |
| self.ticks += 1 | |
| self.max_missiles = 2 + self.ticks // 10 # increase max misiles by one every 10 moves | |
| # u could add ur own retarded progression system | |
| print('Game over.') | |
| restart = input("Restart? (y/n) > ") | |
| if restart == 'y': | |
| self.running = True | |
| self.reset() | |
| self.run() | |
| else: | |
| print("Bye!") | |
| def spawn_missiles(self): | |
| '''only let the max_missiles amount of missiles be on the screen at any one time''' | |
| for _ in range(self.max_missiles - len(self.missiles)): | |
| random_pos = (0, random.randint(0, len(self.grid[0]) - 1)) | |
| self.missiles.append(Missile(*random_pos, game=self)) | |
| @property | |
| def entities(self): | |
| '''A generator that yields everything that will be displayed''' | |
| yield from self.missiles | |
| yield from self.player.parts | |
| def check_collisions(self): | |
| '''Checks for collisions and ends the game if no health left''' | |
| for part in self.player.parts: | |
| for missile in self.missiles: | |
| if missile == part: # collided | |
| if not self.player.lifeleft: # decrement health and check if lifeleft | |
| return self.end() | |
| missile.destroy() | |
| def update_grid(self): | |
| '''Updates the grid with the locations of all entities''' | |
| self.clear_grid() | |
| for entity in self.entities: | |
| self.grid[entity.r][entity.c] = entity | |
| def end(self): | |
| self.running = False | |
| game = Game() | |
| game.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment