Last active
December 28, 2018 00:38
-
-
Save eshon/5e6789399542a13c6b6a371aa2cd9550 to your computer and use it in GitHub Desktop.
This file contains 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
# spaceinvaders.py | |
# | |
# a simple variation of Space Invaders | |
# a lot of logic is adapted from http://hairymnstr.com/files/tetris.py.txt | |
# because i wuz new to programming with curses :*/ | |
# | |
# run with 'python spaceinvader.py' | |
# | |
# works with Python 2.7.10 | |
# | |
import curses, random, time, threading, pdb, traceback | |
class constant: | |
SCORE_ROW = 1 | |
TOP_ROW = 4 | |
SHIP_ROW = 19 | |
LOWEST_ROW = 20 | |
RIGHT_COL = 40 | |
LEFT_COL = 0 | |
DEBUG_ROW = 35 | |
MIDDLE_COL = (RIGHT_COL - LEFT_COL) // 2 | |
MESSAGE_ROW = 26 | |
SCREEN_HT = LOWEST_ROW - TOP_ROW + 1 | |
SCREEN_WT = RIGHT_COL - LEFT_COL | |
SHIP_ROW_y = SHIP_ROW - TOP_ROW + 1 | |
class score: | |
player = 0 | |
aliens = 0 | |
# PLAYER SHIP CLASS | |
# user ship moves L and R | |
class game_ship: | |
def __init__(self): | |
self.height=1 | |
self.width=3 | |
self.pos = constant.MIDDLE_COL | |
self.row = constant.SHIP_ROW | |
def draw(self, v, screen): | |
p = abs(self.pos + v) | |
if p < constant.LEFT_COL + 1: | |
self.pos = constant.LEFT_COL + 1 | |
elif p > constant.RIGHT_COL - 1: | |
self.pos = constant.RIGHT_COL - 1 | |
else: | |
self.pos = self.pos + v | |
screen.addstr(constant.SHIP_ROW, self.pos, "^^^") | |
# TODO *********************************** | |
def shoot(self, screen): | |
start = self.pos | |
threading.Thread(target=game_notification, args=(screen, str("TODO: pew pew!"),2,) ).start() | |
# add shooting capability | |
# ALIEN CLASS | |
# aliens move L and R randomly while moving twds player ship | |
# if they get past the ship aliens earn a point | |
class game_alien: | |
def __init__(self): | |
self.create_alien() | |
# shape allows for different alien shapes later on | |
# 1's are aliens, 0's space between them | |
def create_alien(self): | |
self.shape = [[1,0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,0,1],[1,0,1,0,1,0,1,0,1]] | |
self.height = 4 | |
self.width = 9 | |
self.collided = 0 | |
def draw(self, y, x, screen, bits, ship): | |
self.cleft = 1 | |
self.cright = 1 | |
self.falling = 1 | |
for h in range(self.height): | |
for w in range(self.width): | |
if self.shape[h][w] == 1: | |
yt = y + h | |
xt = x + w | |
if xt < constant.SCREEN_WT: | |
screen.addstr(yt, xt, '@') | |
# check whether all aliens in one set have reached the bottom | |
# pdb.set_trace() | |
self.reached_bottom(screen, y, x, bits) | |
self.check_collision(screen, y, xt, ship, bits) | |
if x == 0: | |
self.cleft = 0 | |
if x > len(bits[0])-self.width: | |
self.cright = 0 | |
# do player ship and alien collide for game over? | |
def check_collision(self, screen, y, xt, ship_piece, bits): | |
# for h and w at ship_piece.pos does it collide | |
if y == constant.SHIP_ROW_y: | |
for w in range(ship_piece.width): | |
if (ship_piece.pos + w) == xt: | |
self.collided = 1 | |
self.falling = 0 | |
def reached_bottom(self, screen, y, x, bits): | |
if y <= len(bits)-1 and x <= len(bits[0])-1: # check for bad index | |
if bits[y][x] == 1: | |
threading.Thread(target=game_notification, args=(screen, "aliens have reached your defense line!",2,)).start() | |
self.stop_falling(y, x, bits) | |
def stop_falling(self, y, x, bits): | |
# check that the top row of aliens has reached the bottom | |
if self.falling and y >= constant.SCREEN_HT: | |
score.aliens = score.aliens + 1 | |
self.falling = 0 | |
# game notifications permanent | |
def final_game_notification(screen, message): | |
screen.addstr(constant.MESSAGE_ROW, constant.LEFT_COL, message, curses.A_REVERSE) | |
# temporary game notifications in another thread | |
def game_notification(screen, message, timeout): | |
screen.addstr(constant.MESSAGE_ROW, constant.LEFT_COL, message, curses.A_REVERSE) | |
time.sleep(timeout) | |
screen.move(constant.MESSAGE_ROW, constant.LEFT_COL) | |
screen.clrtoeol() | |
def draw_frame(): | |
frameborder_in = ["#" for k in range(constant.SCREEN_WT)] | |
frameborder = ''.join(frameborder_in); | |
spaceborder_in = [" " for w in range(constant.SCREEN_WT)] | |
spaceborder = ''.join(spaceborder_in); | |
myscreen.addstr(constant.TOP_ROW, constant.LEFT_COL, frameborder) | |
for n in range(constant.TOP_ROW + 1, constant.LOWEST_ROW): | |
myscreen.addstr(n, constant.LEFT_COL, spaceborder) | |
myscreen.addstr(constant.LOWEST_ROW , constant.LEFT_COL, frameborder) | |
# add game title | |
l_title_offset = (constant.SCREEN_WT // 2) - 8 | |
title_stars = ''.join(["*" for w in range(l_title_offset)]) | |
myscreen.addstr(0, constant.LEFT_COL, title_stars) | |
myscreen.addstr(0, constant.LEFT_COL + l_title_offset, " SPACE INVADERS") | |
myscreen.addstr(0, constant.LEFT_COL + l_title_offset + 16, title_stars) | |
myscreen.addstr(constant.LOWEST_ROW+2, 0, "Use arrow keys: L, R or up to shoot") | |
myscreen = curses.initscr() | |
myscreen.keypad(True) # for using arrow keys | |
curses.noecho() | |
curses.curs_set(0) | |
alien = game_alien() | |
ship = game_ship() | |
uiloop = 1 | |
while uiloop: | |
x = random.randint(constant.LEFT_COL, constant.RIGHT_COL-2) | |
y = constant.TOP_ROW | |
# Create a bits grid to keep track of collisions | |
bits=[[0 for k in range(constant.SCREEN_WT)] for i in range(constant.SCREEN_HT)] | |
ones_row = [1 for l in range(constant.SCREEN_WT)] | |
bits.append(ones_row) | |
curses.halfdelay(1) | |
t = time.time() | |
ship_move = 0 | |
alien.cleft = 0 | |
alien.cright = 0 | |
# Main UI loop | |
while 1: | |
c = myscreen.getch() | |
if c == ord('q'): | |
break | |
elif c == curses.KEY_UP: | |
ship.shoot(myscreen) | |
elif c == curses.KEY_LEFT: | |
ship_move = ship_move - 1 | |
elif c == curses.KEY_RIGHT: | |
ship_move = ship_move + 1 | |
else: | |
fall_temp = random.randint(0,1) | |
move_rand = random.randint(1,2) | |
if move_rand == 1: | |
x = x - alien.cleft | |
fall_temp = 0 | |
elif move_rand == 2: | |
x = x + alien.cright | |
fall_temp = 0 | |
draw_frame() | |
try: | |
alien.draw(y, x, myscreen, bits, ship) | |
ship.draw(ship_move, myscreen) | |
ship_move = 0 | |
except Exception, err: | |
print Exception, err | |
traceback.print_exc() | |
break | |
if time.time() - t > 0.5: | |
if alien.falling == 0: | |
x = random.randint(0, constant.RIGHT_COL - constant.LEFT_COL - alien.width) | |
y = constant.TOP_ROW + 1 | |
alien.create_alien() | |
y = y + alien.falling | |
fall_temp = not alien.falling | |
t = time.time() | |
myscreen.addstr(constant.SCORE_ROW, constant.LEFT_COL, "Your Score: "+str(score.player)) | |
myscreen.addstr(constant.SCORE_ROW+1, constant.LEFT_COL, "Aliens Score: "+str(score.aliens)) | |
if alien.collided: | |
final_game_notification(myscreen, "aliens have collided with your ship!") | |
break | |
myscreen.refresh() | |
myscreen.addstr(9, constant.MIDDLE_COL-6, "Game Over\n ") | |
myscreen.addstr(11, constant.MIDDLE_COL-6, "q to quit\n ") | |
while 1: | |
c = myscreen.getch() | |
if c == ord('q'): | |
uiloop = 0 | |
break | |
myscreen.refresh() | |
curses.echo() | |
curses.endwin() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment