Skip to content

Instantly share code, notes, and snippets.

@eshon
Last active December 28, 2018 00:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eshon/5e6789399542a13c6b6a371aa2cd9550 to your computer and use it in GitHub Desktop.
Save eshon/5e6789399542a13c6b6a371aa2cd9550 to your computer and use it in GitHub Desktop.
# 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