Skip to content

Instantly share code, notes, and snippets.

@matheusgomes28
Created July 18, 2013 00:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matheusgomes28/6025721 to your computer and use it in GitHub Desktop.
Save matheusgomes28/6025721 to your computer and use it in GitHub Desktop.
Simple Python game. This game was created to simulate some (not all) laws of physics and mathematics such as gravity, forces, vectors etc... Free to use and modify!
import pygame, sys
import pygame.gfxdraw
pygame.init()
class Obstacle(object):
""" The Obstacle class defines simple methods and properties of
obstacle objects such as rectangles and circles"""
def __init__(self, center, WIDTH, HEIGHT):
self.center = pygame.math.Vector2(center)
self.WIDTH = WIDTH
self.HEIGHT = HEIGHT
self.top_left = [(self.center[0] - (WIDTH / 2)),(self.center[1] - (HEIGHT / 2))]
def in_range(directions, width, height):
"""This method returns True if the object is
inside the range of another object (NOT CIRCLE!!!)"""
class Ball(Obstacle):
"""
This class defines a ball object
(surface, color, center, width/radius) -> GUI object.
"""
def __init__(self, SURFACE, COLOR, center, WIDTH):
assert (type(center) == tuple), "Center must be a coordinate"
Obstacle.__init__(self, center, WIDTH, WIDTH) # Width sent twice as the height = width.
self.SURFACE = SURFACE
self.COLOR = COLOR
self.RADIUS = int(self.WIDTH / 2)
def draw(self):
#pygame.draw.circle(self.SURFACE, self.COLOR, (int(self.center[0]), int(self.center[1])), self.RADIUS, 2)
pygame.gfxdraw.filled_circle(self.SURFACE, int(self.center[0]), int(self.center[1]), self.RADIUS, self.COLOR)
pygame.gfxdraw.aacircle(self.SURFACE, int(self.center[0]), int(self.center[1]), self.RADIUS, self.COLOR)
def move(self, valueX=0, valueY=0):
#Reassigning center vector
self.center[0] = ((self.center[0] + valueX) % 400)
self.center[1] = (self.center[1] + valueY)
self.draw()
class RecObstacle(Obstacle):
"""
The RecObstacle class creates a new rectangle instance and adds
methods and properties that allow the created rectangle to be
added to the 'display surface'
(surface, color, center, width, height) -> GUI object
[display obj, list, list, int, int]
"""
def __init__(self, SURFACE, COLOR, center, WIDTH, HEIGHT):
Obstacle.__init__(self,(center[0], center[1]), WIDTH, HEIGHT)
self.SURFACE = SURFACE
self.COLOR = COLOR
self.directions = [[0,1]]
def draw(self):
pygame.draw.rect(self.SURFACE, self.COLOR, (self.top_left[0], self.top_left[1], self.WIDTH, self.HEIGHT))
import pygame
pygame.init()
def calculate_accel(forces, m):
"""This function will calculate the acceleration
of an object using newton's law: F = MA
if mass = 1:
calculate_accel([0,10]) -> [0,10]
"""
temp = [0,0] # Temporary holder for resultant force
for i in forces:
temp[0] = temp[0] + i[0]
temp[1] = temp[1] + i[1]
return pygame.math.Vector2([round(temp[0] / m), round(temp[1] / m)])
def ball_collision(list_of_balls):
""" This function returns True if a ball
object collides with another ball object"""
for a1 in list_of_balls:
for a2 in list_of_balls:
if (a1.center.distance_to(a2.center)) <= (a1.RADIUS + a2.RADIUS):
if a1.center != a2.center:
return True
else:
return False
else:
return False
def handle_ground_collision(ball_obj, rec_obj):
"""This function works as a collision detection for
the ground and the ball. This is still a primitive
collision detector.
(all object, Rectangle object) -> Boolean"""
temp = pygame.math.Vector2((ball_obj.center[0], ball_obj.center[1] + ball_obj.RADIUS))
if temp.distance_to([ball_obj.center[0], rec_obj.center[1] - rec_obj.HEIGHT/2]) == 0:
return True
else:
return False
import pygame, classes, sys
from pygame.locals import *
from functions import *
pygame.init() #Initialising pygame functions and variables
#Colors R G B
BLACK = ( 0, 0, 0)
WHITE = (255,255,255)
BLUE = ( 0, 0,255)
FPS = 150 #Frames per second / display update time
#########################
### Movement settings ###
#########################
forces = [] # Empty forces list / holds forces acting on a particle / Forces in newtons
mass = 10 # Mass of the ball in kg.
g = 9.8 #universal gravity pull
ACCEL = pygame.math.Vector2((0, 0)) #Acceleration vector
velocity = pygame.math.Vector2([0,0]) #Velocity starting at 0
METRES = 200 # 200 pixels == 1 metres
friction = 3
is_vert_rest = False
def detect_collision(ball_center, rec_direction, rec_range):
"""Advanced collision detection, uses vectors in order
to triangulate positions and distances."""
pass
def main():
""" Main program precedure. This function contains
the game loop."""
global DISPLAY, FPSCLOCK, ball, rectangle #Canvas globals created inside main function / only initializes if this is "__main__"
global ACCEL, velocity, forces, is_vert_rest # Outside-created variables / Re-declaring so we can modify the values globally
# Display settings
DISPLAY = pygame.display.set_mode((400,600))
pygame.display.set_caption("Vector Test")
ball = classes.Ball(DISPLAY, BLUE, (200, 200), 40)
rectangle = classes.RecObstacle(DISPLAY, BLACK, (200,575), 400, 50)
FPSCLOCK = pygame.time.Clock()
while True:
## Constant updates of the game ###
DISPLAY.fill(WHITE)
rectangle.draw()
############################
### Dynamics of the ball ###
############################
forces.append([0, mass * g]) # Acceleration due to gravity
#Collision detection
if handle_ground_collision(ball, rectangle):
velocity[1] = -.8*(velocity[1])
velocity[0] = velocity[0] * (1 - (friction / FPS))
if velocity[1] < (1/FPS) and velocity[1] > -(1/FPS): #Limit of movement
is_vert_rest = True
else:
is_vert_rest = False
ball.draw()
#Velocity update
velocity[1] = velocity[1] + (ACCEL[1] / FPS)
if (ball.center[1] + ball.RADIUS) + (velocity[1] + (ACCEL[1] / FPS)) >= (rectangle.center[1] - (rectangle.HEIGHT / 2)):
ball.move(velocity[0], (rectangle.center[1] - rectangle.HEIGHT/2) - (ball.center[1] + ball.RADIUS))
else:
ball.move((velocity[0] * METRES) / FPS, (velocity[1] * METRES) / FPS)
############################
if is_vert_rest:
ACCEL[1] = 0
velocity[1] = 0
else:
ACCEL = calculate_accel(forces, mass) # Calculate acceleration
forces = []
mouse = pygame.mouse.get_pressed()
mouse_pos = pygame.mouse.get_pos()
if mouse[0]:
pygame.draw.aaline(DISPLAY, BLACK, mouse_pos, ball.center)
# QUIT event checking
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == MOUSEBUTTONUP :
velocity[0] = velocity[0] + (mouse_pos[0] - ball.center[0]) / (METRES / 4)
velocity[1] = velocity[1] + (mouse_pos[1] - ball.center[1]) / (METRES / 4)
pygame.display.update() # update the canvas
FPSCLOCK.tick(FPS)
if __name__ == "__main__":
main()
##################
# CODE BY: Matheus Gomes
# Open source
# Free to use and modify
##################
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment