Skip to content

Instantly share code, notes, and snippets.

@CRamsan
Last active August 29, 2015 14:00
Show Gist options
  • Save CRamsan/fa60a905d88f5ce2fa21 to your computer and use it in GitHub Desktop.
Save CRamsan/fa60a905d88f5ce2fa21 to your computer and use it in GitHub Desktop.
# 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