Last active
August 29, 2015 14:00
-
-
Save CRamsan/fa60a905d88f5ce2fa21 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
# Import a library of functions called 'pygame' | |
import pygame | |
import math | |
import random | |
# Define some colors | |
BLACK = ( 0, 0, 0) | |
WHITE = ( 255, 255, 255) | |
BLUE = ( 0, 0, 255) | |
GREEN = ( 0, 255, 0) | |
RED = ( 255, 0, 0) | |
PI = 3.141592653 | |
class Point: | |
def __init__(self, x=0, y=0): | |
self.x = x | |
self.x = y | |
class Collision: | |
class PolygonCollisionResult: | |
def __init__(self): | |
self.WillIntersect = None | |
self.Intersect = None | |
self.MinimumTranslationVector = None | |
def PolygonCollision(polygonA, polygonB, velocity): | |
result = PolygonCollisionResult() | |
result.Intersect = True | |
result.WillIntersect = True | |
edgeCountA = len(polygonA.Edges) | |
edgeCountB = len(polygonB.Edges) | |
minIntervalDistance = float("inf") | |
translationAxis = Vector() | |
edge = None | |
while edgeIndex < edgeCountA + edgeCountB: | |
if edgeIndex < edgeCountA: | |
edge = polygonA.edges[edgeIndex] | |
else: | |
edge = polygonB.edges[edgeIndex - edgeCountA] | |
axis = Vector(-edge.y, edge.x) | |
axis.normalize() | |
minA = 0 | |
minB = 0 | |
maxA = 0 | |
maxB = 0 | |
(minA, maxA) = self.ProjectPolygon(axis, polygonA, minA, maxA); | |
(minB, maxB) = self.ProjectPolygon(axis, polygonB, minB, maxB); | |
if (self.IntervalDistance(minA, maxA, minB, maxB) > 0): | |
result.Intersect = false | |
velocityProjection = axis.dot_product(velocity) | |
if velocityProjection < 0: | |
minA += velocityProjection | |
else: | |
maxA += velocityProjection | |
intervalDistance = self.IntervalDistance(minA, maxA, minB, maxB) | |
if intervalDistance > 0: | |
result.WillIntersect = false | |
if not result.Intersect and not result.WillIntersect: | |
break | |
intervalDistance = math.fabs(intervalDistance) | |
if intervalDistance < minIntervalDistance: | |
minIntervalDistance = intervalDistance | |
translationAxis = axis; | |
d = polygonA.get_center().substract(polygonB.get_center()) | |
if d.dot_product(translationAxis) < 0: | |
translationAxis = -translationAxis | |
edgeIndex+=1 | |
if result.WillIntersect: | |
result.MinimumTranslationVector = translationAxis * minIntervalDistance | |
return result; | |
def IntervalDistance(minA, maxA, minB, maxB): | |
if minA < minB: | |
return minB - maxA | |
else: | |
return minA - maxB | |
def ProjectPolygon(self, axis, polygon, _min, _max): | |
d = axis.dot_product(polygon.points[0]) | |
_min = d | |
_max = d | |
for point in polygon.points: | |
d = point.dot_product(axis) | |
if d < _min: | |
_min = d; | |
else: | |
if d > _max: | |
_max = d | |
return (_min, _max) | |
class Polygon(object): | |
def __init__(self): | |
self.points = [] | |
self.edges = [] | |
def build_edges(self): | |
Vector_p1; | |
Vector_p2; | |
edges = []; | |
list_size = len(points) | |
for x in range(list_size): | |
Vector_p1 = points[x] | |
if Vector_p1 is points[-1]: | |
vector_p2 = points[0] | |
else: | |
Vector_p2 = points[x + 1] | |
edges.append(Vector_p2 - Vector_p1) | |
def get_center(self): | |
totalX = 0; | |
totalY = 0; | |
for point in points: | |
totalX += point.x | |
totalY += point.y | |
return Vector(totalX / len(points), totalY / len(points)) | |
def offset(self, Vector): | |
self.offset(Vecot.x, Vector.y); | |
def offset(x, y): | |
list_size = len(self.points) | |
for x in range(list_size): | |
Vector = self.points[x] | |
self.points[x] = Vector(Vector.x + x, Vector.y + y) | |
class Vector: | |
def __init__(self, x=0, y=0): | |
self.x = x | |
self.y = y | |
def from_point(Point): | |
return fro_point(Point.x, Point.y) | |
def from_point(x, y): | |
return Vector(x, y) | |
def get_magnitude(self): | |
return math.sqrt(self.x * self.x + self.y * self.y) | |
def normalize(self): | |
magnitude = get_magnitude() | |
self.x /= magnitude | |
self.y /= magnitude | |
def get_normalized(self): | |
magnitude = get_magnitude() | |
return Vector(self.x / get_magnitude(), self.y / get_magnitude()) | |
def dot_product(Vector): | |
return self.x * Vector.x + self.y * Vector.y | |
def distance_to(Vector): | |
return math.sqrt(math.pow(Vector.x - self.x, 2) + math.pow(Vector.y - self.t, 2)) | |
def add(Vector_a, Vector_b): | |
return Vector(Vector_a.x + Vector_b.x, Vector_a.y + Vector_b.y) | |
def negate(Vector): | |
return Vector(-Vector.x, -Vector.y) | |
def substract(Vector_a, Vector_b): | |
return Vector(Vector_a.x - Vector_b.x, Vector_a.y - Vector_b.y) | |
def multiply(Vector, magnitude): | |
return Vector(Vector.x * magnitude, Vector.y * magnitude) | |
def equals (self, Vector): | |
return self.x == Vector.x and self.y == Vector.y; | |
class Asteroid(Polygon): | |
def __init__(self, x, y, power, orientation, size): | |
super(Asteroid, self).__init__() | |
self.x = x | |
self.y = y | |
self.size = size | |
self.orientation = orientation | |
rads = orientation * PI / 180 | |
self.dx = power * math.cos(rads) | |
self.dy = power * math.sin(rads) | |
self.destroyed = False | |
def update(self): | |
self.x+=self.dx | |
self.y+=self.dy | |
if self.x > size[0]: | |
self.x -= size[0] | |
elif self.x < 0: | |
self.x += size[0] | |
if self.y > size[1]: | |
self.y -= size[1] | |
elif self.y < 0: | |
self.y += size[1] | |
def draw(self, screen): | |
pygame.draw.ellipse(screen, RED, (self.x - self.size/2, self.y - self.size/2, self.size, self.size), 2) | |
def get_power(self): | |
return math.sqrt((self.dx * self.dx) + (self.dy * self.dy)) | |
class Bullet: | |
def __init__(self, x, y, dx, dy, orientation): | |
self.x = x | |
self.y = y | |
rads = orientation * PI / 180 | |
self.dx = dx + 10 * math.cos(rads) | |
self.dy = dy + 10 * math.sin(rads) | |
def update(self): | |
self.x+=self.dx | |
self.y+=self.dy | |
def draw(self, screen): | |
pygame.draw.ellipse(screen, WHITE, (self.x - 1, self.y - 1, 2, 2), 1) | |
class Ship(Polygon): | |
def __init__(self, x, y): | |
super(Ship, self).__init__() | |
self.dx = 0 | |
self.dy = 0 | |
self.x = x | |
self.y = y | |
self.orientation = 90 | |
self.size = 10 | |
self.bullets = [] | |
self.power = 100 | |
self.health = 100 | |
self.alive = True | |
self.barrier = False | |
self.score = 0 | |
def accelerate(self, power=0.01): | |
rads = self.orientation * PI / 180 | |
dx = power * math.cos(rads) | |
dy = power * math.sin(rads) | |
self.dx += dx | |
self.dy += dy | |
def reverse(self, power=0.005): | |
rads = self.orientation * PI / 180 | |
self.dx-= power * math.cos(rads) | |
self.dy-= power * math.sin(rads) | |
def turn_left(self): | |
if self.orientation > 360: | |
self.orientation-=360 | |
self.orientation-=2 | |
def turn_right(self): | |
if self.orientation < -360: | |
self.orientation+=360 | |
self.orientation+=2 | |
def shoot(self): | |
if len(self.bullets) < 12: | |
bullet = Bullet(self.x, self.y, self.dx, self.dy, self.orientation) | |
self.bullets.append(bullet) | |
self.reverse(0.005) | |
def shoot_multi(self): | |
if len(self.bullets) < 8: | |
self.bullets.append(Bullet(self.x, self.y, self.dx, self.dy, self.orientation + 15)) | |
self.bullets.append(Bullet(self.x, self.y, self.dx, self.dy, self.orientation + 30)) | |
self.bullets.append(Bullet(self.x, self.y, self.dx, self.dy, self.orientation - 15)) | |
self.bullets.append(Bullet(self.x, self.y, self.dx, self.dy, self.orientation - 30)) | |
self.reverse(0.02) | |
def shield(self): | |
if self.power >= 100 : | |
self.barrier = True | |
def dash(self, power=0): | |
if self.power > 85: | |
rads = (self.orientation + 90) * PI / 180 | |
dx = power * math.cos(rads) | |
dy = power * math.sin(rads) | |
self.dx += dx | |
self.dy += dy | |
self.power -= 85 | |
def update(self): | |
if not self.alive: | |
return | |
self.x+=self.dx | |
self.y+=self.dy | |
if self.x > size[0]: | |
self.x -= size[0] | |
elif self.x < 0: | |
self.x += size[0] | |
if self.y > size[1]: | |
self.y -= size[1] | |
elif self.y < 0: | |
self.y += size[1] | |
list_size = len(self.bullets) | |
counter = 0 | |
if self.barrier: | |
self.power -= 1.5 | |
if self.power <= 0: | |
self.barrier = False | |
if self.power < 100: | |
self.power += 1 | |
for i in range(list_size): | |
bullet = self.bullets[counter] | |
bullet.update() | |
if bullet.x > size[0]: | |
self.bullets.remove(bullet) | |
counter-=1 | |
elif bullet.x < 0: | |
self.bullets.remove(bullet) | |
counter-=1 | |
elif bullet.y > size[1]: | |
self.bullets.remove(bullet) | |
counter-=1 | |
elif bullet.y < 0: | |
self.bullets.remove(bullet) | |
counter-=1 | |
counter+=1 | |
list_size = len(self.bullets) | |
counter = 0 | |
for i in range(list_size): | |
bullet = self.bullets[counter] | |
for asteroid in asteroids: | |
if math.sqrt((asteroid.x - bullet.x)*(asteroid.x - bullet.x) + | |
(asteroid.y - bullet.y)*(asteroid.y - bullet.y)) < asteroid.size/2: | |
asteroid.destroyed = True | |
self.bullets.remove(bullet) | |
self.score += 269 | |
counter -= 1 | |
break | |
counter+=1 | |
for asteroid in asteroids: | |
if math.sqrt((asteroid.x - self.x)*(asteroid.x - self.x) + | |
(asteroid.y - self.y)*(asteroid.y - self.y)) < asteroid.size/2 + self.size/2: | |
asteroid.destroyed = True | |
if not self.barrier : | |
self.health -= asteroid.size | |
if self.health <= 0 : | |
self.alive = False | |
other_player = None | |
if self == player_1 : | |
other_player = player_2 | |
else: | |
other_player = player_1 | |
if other_player.barrier: | |
return | |
list_size = len(self.bullets) | |
counter = 0 | |
for i in range(list_size): | |
bullet = self.bullets[counter] | |
if math.sqrt( (other_player.x - bullet.x)*(other_player.x - bullet.x) + | |
(other_player.y - bullet.y)*(other_player.y - bullet.y)) < other_player.size: | |
other_player.health -= 2 | |
if other_player.health <= 0: | |
other_player.alive = False | |
self.bullets.remove(bullet) | |
counter -= 1 | |
counter+=1 | |
def point_list(self): | |
rads = self.orientation * PI / 180 | |
rads_br = (self.orientation + 140) * PI / 180 | |
rads_bl = (self.orientation - 140) * PI / 180 | |
point_list = ((self.x + 1.1 * self.size * math.cos(rads), self.y + 1.1 * self.size * math.sin(rads)), | |
(self.x + 1.1 * self.size * math.cos(rads_br), self.y + 1.1 * self.size * math.sin(rads_br)), | |
(self.x + 1.1 * self.size * math.cos(rads_bl), self.y + 1.1 * self.size * math.sin(rads_bl))) | |
return point_list | |
def draw(self, screen): | |
if not self.alive: | |
return | |
draw_points = self.point_list() | |
pygame.draw.polygon(screen, WHITE, draw_points, 1) | |
fps = space_font.render("Score: " + str(self.score), 1, (255,255,255)) | |
if self == player_1: | |
pygame.draw.rect(screen, WHITE, [5, 5, 100, 10], 2) | |
pygame.draw.rect(screen, GREEN, [5, 5, self.power, 10]) | |
pygame.draw.rect(screen, WHITE, [5, 20, 100, 10], 2) | |
pygame.draw.rect(screen, RED, [5, 20, self.health, 10]) | |
screen.blit(fps, (5, 35)) | |
else : | |
pygame.draw.rect(screen, WHITE, [size[0] - 105, 5, 100, 10], 2) | |
pygame.draw.rect(screen, GREEN, [size[0] - 105, 5, self.power, 10]) | |
pygame.draw.rect(screen, WHITE, [size[0] - 105, 20, 100, 10], 2) | |
pygame.draw.rect(screen, RED, [size[0] - 105, 20, self.health, 10]) | |
screen.blit(fps, (size[0] - 105, 35)) | |
if self.barrier: | |
pygame.draw.ellipse(screen, BLUE, [self.x - self.size*2, self.y - self.size*2, self.size*4, self.size*4], 3) | |
for bullet in self.bullets: | |
bullet.draw(screen) | |
def create_asteroid(): | |
side = random.randrange(4) | |
power = (random.randrange(30)/10) + 1 | |
orientation = random.randrange(0, 360) | |
asteroid_size = random.randrange(30) + 25 | |
if side == 0 : | |
return Asteroid(random.randrange(size[1]), | |
0, | |
power, orientation, asteroid_size) | |
elif side == 1 : | |
return Asteroid(size[0], | |
random.randrange(size[1]), | |
power, orientation, asteroid_size) | |
elif side == 2 : | |
return Asteroid(random.randrange(size[0]), | |
size[1], | |
power, orientation, asteroid_size) | |
elif side ==3 : | |
return Asteroid(0, | |
random.randrange(size[1]), | |
power, orientation, asteroid_size) | |
# Initialize the game engine | |
pygame.init() | |
# Set the height and width of the screen | |
size = (900, 600) | |
screen = pygame.display.set_mode(size, pygame.RESIZABLE | pygame.DOUBLEBUF) | |
#Loop until the user clicks the close button. | |
done = False | |
clock = pygame.time.Clock() | |
#Variables used to keep a constant timesstep for the physics simulation | |
t = 0.0 | |
dt = 0.01 | |
currentTime = 0.0 | |
accumulator = 0.0 | |
step = 0 | |
player_1 = Ship(size[0]/3, size[1]/2) | |
player_2 = Ship(2 * size[0]/3, size[1]/2) | |
asteroids = [] | |
space_font = pygame.font.SysFont("monospace", 15) | |
for x in range(3): | |
asteroids.append(create_asteroid()) | |
# Loop as long as done == False | |
while not done: | |
clock.tick() | |
for event in pygame.event.get(): # User did something | |
if event.type == pygame.QUIT: # If user clicked close | |
done = True # Flag that we are done so we exit this loop | |
if event.type == pygame.VIDEORESIZE: | |
screen = pygame.display.set_mode(event.dict['size'], pygame.RESIZABLE | pygame.DOUBLEBUF) | |
size = event.dict['size'] | |
pygame.display.flip() | |
if event.type == pygame.KEYDOWN : | |
if event.key == pygame.K_1 : | |
player_1 = Ship(size[0]/3, size[1]/2) | |
if event.key == pygame.K_2 : | |
player_2 = Ship(2 * size[0]/3, size[1]/2) | |
if event.key == pygame.K_LCTRL : | |
player_1.shoot() | |
if event.key == pygame.K_LALT : | |
player_1.shoot_multi() | |
if event.key == pygame.K_SPACE : | |
player_1.dash(-1.5) | |
if event.key == pygame.K_LSHIFT : | |
player_1.shield() | |
if event.key == pygame.K_a : | |
player_2.shoot() | |
if event.key == pygame.K_s : | |
player_2.shoot_multi() | |
if event.key == pygame.K_q : | |
player_2.dash(-1.5) | |
if event.key == pygame.K_w : | |
player_2.shield() | |
newTime = pygame.time.get_ticks() | |
deltaTime = (newTime - currentTime) / 1000.0 | |
currentTime = newTime | |
# If deltaTime is too huge things get a little out of control, so | |
# this places a cap that will only be hit if the game is runn5555ing | |
# very slowly. | |
if (deltaTime > 0.25): | |
deltaTime = 0.25 | |
accumulator = accumulator + deltaTime | |
while (accumulator >= dt): | |
accumulator = accumulator - dt | |
move_ticker = 0 | |
keys=pygame.key.get_pressed() | |
if keys[pygame.K_KP4]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_1.turn_left() | |
if keys[pygame.K_KP6]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_1.turn_right() | |
if keys[pygame.K_KP8]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_1.accelerate() | |
if keys[pygame.K_KP2]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_1.reverse() | |
if keys[pygame.K_d]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_2.turn_left() | |
if keys[pygame.K_g]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_2.turn_right() | |
if keys[pygame.K_r]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_2.accelerate() | |
if keys[pygame.K_f]: | |
if move_ticker == 0: | |
move_ticker = 10 | |
player_2.reverse() | |
if move_ticker > 0: | |
move_ticker -= 1 | |
if step % 500 == 0 and len(asteroids) < 25: | |
print "New asteroid detected" | |
asteroids.append(create_asteroid()) | |
player_1.update() | |
player_2.update() | |
list_size = len(asteroids) | |
counter = 0 | |
for i in range(list_size): | |
asteroid = asteroids[counter] | |
if asteroid.destroyed : | |
asteroids.remove(asteroid) | |
if asteroid.size > 30 : | |
power = asteroid.get_power() | |
asteroids.append(Asteroid(asteroid.x, | |
asteroid.y, | |
power * 1.2, | |
asteroid.orientation + 45, | |
asteroid.size / 2)) | |
asteroids.append(Asteroid(asteroid.x, | |
asteroid.y, | |
power * 1.2, | |
asteroid.orientation - 45, | |
asteroid.size / 2) ) | |
asteroids.append(Asteroid(asteroid.x, | |
asteroid.y, | |
power * 1.2, | |
asteroid.orientation + 135, | |
asteroid.size / 2)) | |
asteroids.append(Asteroid(asteroid.x, | |
asteroid.y, | |
power * 1.2, | |
asteroid.orientation - 135, | |
asteroid.size / 2)) | |
counter -= 1 | |
counter+=1 | |
for asteroid in asteroids : | |
asteroid.update() | |
t = t + dt | |
step += 1 | |
# All drawing code happens after the for loop and but | |
# inside the main while not done loop. | |
# Clear the screen and set the screen background | |
screen.fill(BLACK) | |
for asteroid in asteroids : | |
asteroid.draw(screen) | |
player_1.draw(screen) | |
player_2.draw(screen) | |
#fps = space_font.render("FPS: " + str(clock.get_fps()), 1, (255,255,255)) | |
#screen.blit(fps, (5, size[1] - 30)) | |
pygame.display.flip() | |
pygame.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment