def __init__(self, pos, level): self.size = Vector(0.8, 1.2) self.pos = Vector(pos[0], pos[1]) - (self.size - Vector(1, 1)) self.level = level self.hp = 100 self.image = player_image self.velocity = Vector(0, 0)
def test_zero(self): v = Vector(0.0, 0.0) self.assertEqual(v.x, 0.0) self.assertEqual(v.y, 0.0) self.assertEqual(v.get_magnitude(), 0.0) self.assertEqual(v.get_angle(), None)
def __init__(self, location , mass , velocity = None): if velocity == None: self.velocity = Vector(0,0) else: self.velocity = velocity self.applied_force = Vector(0,0) self._location = location self._mass = mass self._object_type = ObjectType.DEFAULT
def __init__(self, wall_type, relevant_coord): if(wall_type == WallType.LEFT or wall_type == WallType.RIGHT): super().__init__(Vector(relevant_coord, 0), None) else: super().__init__(Vector(0, relevant_coord), None) self._object_type = ObjectType.WALL self.__wall_type = wall_type
def shoot(self): if World.main_character is not None: if KeyLogger.bindings['shoot'].check(): v = Vector(Mouse.get_real_coordinates() - World.main_character.get_firing_coordinates()) World.main_character.fire_normal_bullet(v.normalize()) return True return False
def test_init(self): v = Vector(1, 1) self.assertEqual(v.x, 1.0) self.assertEqual(v.y, 1.0) # Type check self.assertIsInstance(v.x, float) self.assertIsInstance(v.y, float) self.assertIsInstance(v.get_magnitude(), float) self.assertIsInstance(v.get_angle(), float)
def get_safe_distance(self, v, k=0): if k > 2: return Coordinates(0, 0) o = self.check_collision(v, type_exceptions=['walkable']) if o is not None: k += 1 d = Vector(v).normalize() * (Vector(self.distance(o, v)) * Vector(v).normalize()) return self.get_safe_distance( (Coordinates(d) * Coordinates(0.99, 0.99)).int(), k) else: return v
def resolve_ball_wall_collision(ball: PoolBall, wall: Direction): """ Sets the new velocity for this ball after it has collided with a wall. *Assumes wall is in one of 4 directions: N, E, S, or W* :param ball: pool ball :param wall: which wall (N, E, S, W) """ if wall == Direction.NORTH or wall == Direction.SOUTH: ball.vel = Vector(ball.vel.x, -ball.vel.y) # Reverse y-direction else: # EAST or WEST ball.vel = Vector(-ball.vel.x, ball.vel.y) # Reverse x-direction
def test_resolve_ball_ball_collision_2d_two_moving(self): # Initialize ball objects ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) # A enters from W (270 degrees), contacts B on its left (180 degrees) # A enters from E (0 degrees), contacts A on its right (0 degrees) # A and B should both reverse their direction ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-0.5, 0.0), Vector(1.0, 0.0), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.5, 0.0), Vector(-1.0, 0.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(-1.0, 0.0) b_vel_new = Vector(1.0, 0.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new) # A enters from W (270 degrees), contacts B on its left (180 degrees) # A enters from E (0 degrees), contacts A on its right (0 degrees) # A and B should both reverse their direction ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-0.5, 0.0), Vector(1.0, 0.0), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.5, 0.0), Vector(-1.0, 0.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(-1.0, 0.0) b_vel_new = Vector(1.0, 0.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new) """
def test_resolve_ball_ball_collision_1d_diagonal(self): # Initialize ball objects ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) # 2-D, stationary target ball ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, -1.0), Vector(2.0, 2.0), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(0.0, 0.0) b_vel_new = Vector(2.0, 2.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new) # 2-D, head-on collision, same speeds ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, -1.0), Vector(2.0, 2.0), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(-2.0, -2.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(-2.0, -2.0) b_vel_new = Vector(2.0, 2.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)
def collides_line(self, other, additional_coordinates): a = Vector(other.get_coordinates() - self.get_coordinates() - additional_coordinates) e1 = self.e e2 = other.e if e1**e2 == 0: if a**e1 != 0: return False else: if a.x == 0: if a.y == 0: return True else: lam1 = a.y / e1.y lam2 = (a.y + e2.y) / e1.y if 0 <= lam1 <= 1 or 0 <= lam2 <= 1: return lam1 * lam2 < 0 else: return True else: lam1 = a.x / e1.x lam2 = (a.x + e2.x) / e1.x if not 0 <= lam1 <= 1 or 0 <= lam2 <= 1: return lam1 * lam2 < 0 else: return True else: lam1 = (a**e2) / (e1**e2) lam2 = (a**e1) / (e1**e2) return 0 <= lam1 <= 1 and 0 <= lam2 <= 1
def future_shape(self, additional_coordinates): circle2 = Circle(self.gameobject, self.get_coordinates() + additional_coordinates, self.radius) v = Vector(additional_coordinates).normalize().right_angled() line1 = Line(self.gameobject, self.get_coordinates() + v * self.radius, self.get_coordinates() - v * self.radius) line2 = Line( self.gameobject, self.get_coordinates() - v * self.radius, self.get_coordinates() - v * self.radius + additional_coordinates) line3 = Line( self.gameobject, self.get_coordinates() - v * self.radius + additional_coordinates, self.get_coordinates() + v * self.radius + additional_coordinates) line4 = Line( self.gameobject, self.get_coordinates() + v * self.radius + additional_coordinates, self.get_coordinates() + v * self.radius) return [ self, circle2, MultilineObject(self.gameobject, self.coordinates, [line1, line2, line3, line4]) ]
def __init__(self, animations, velocity=Vector(0, 0), center_of_gravity=Coordinates(0, 0), mass=0.02): GameObject.__init__(self, animations) self.velocity = velocity self.mass = mass self.hit_exceptions = [] self.type_exceptions = ['shootable'] self.center_of_gravity = center_of_gravity self.thread = Thread(self.run, (), 'projectile thread')
def move(self, direction): v = self.walking_distance / target_fps * direction try: d = self.get_safe_distance(v) except RecursionError: print('Maximum recursion depth exceeded.') d = Vector(0, 0) self.reposition(self.coordinates + d)
class PhysicsObject(): __global_forces = vector.get_inert_vector(2) def __init__(self, location , mass , velocity = None): if velocity == None: self.velocity = Vector(0,0) else: self.velocity = velocity self.applied_force = Vector(0,0) self._location = location self._mass = mass self._object_type = ObjectType.DEFAULT def exert_force(self , force: Sequence): self.applied_force+=force def move(self): self.velocity.update( Vector.sum(self.applied_force,self.__global_forces, self.velocity)) self._location.update(self._location+self.velocity) @staticmethod def get_global_force()->Vector: return PhysicsObject.__global_forces.copy() @staticmethod def set_global_force(value: Sequence): if(not isinstance(value, Sequence) and len(value)!=2): raise ValueError PhysicsObject.__global_forces = Vector(*value) @staticmethod def check_collision(obj_a:'PhysicsObject', obj_b: 'PhysicsObject')->bool: x_distance = obj_a._location[0] - obj_b._location[0] y_distance = obj_a._location[0] - obj_b._location[0] if(obj_a._object_type==ObjectType.CIRCLE and obj_b._object_type==ObjectType.CIRCLE): radii_sum = obj_a._radius + obj_b._radius return radii_sum**2 < (x_distance**2) + (y_distance**2) if( obj_a._object_type == ObjectType.WALL and obj_b._object_type == ObjectType.CIRCLE or obj_a._object_type == ObjectType.CIRCLE and obj_b._object_type == ObjectType.WALL): if(obj_a._object_type== ObjectType.WALL): wall = obj_a else: wall = obj_b if(wall.wall_type == WallType.LEFT or wall.wall_type == WallType.RIGHT): return x_distance**2<=0 else: return y_distance**2<=0 return False
def check_ray_circle_intersection(p1: Coordinates, p2: Coordinates, c_mid: Coordinates, c_radius: float): """ Check whether a ray intersects a circle. :param p1: starting point of ray :param p2: end point of ray :param c_mid: coordinates for the center of the circle :param c_radius: radius of the circle :return: True if intersection; False otherwise """ # Source: https://stackoverflow.com/a/1084899 # d is direction vector of ray, from start to end # f is direction Vector from center sphere to ray start d = Vector(p2.y - p1.y, p2.x - p1.x) f = Vector(p1.y - c_mid.y, p1.x - c_mid.x) a = d.dot_product(d) b = 2 * f.dot_product(d) c = f.dot_product(f) - c_radius**2 discriminant = b * b - 4 * a * c if discriminant < 0: return False else: discriminant = np.sqrt(discriminant) t1 = (-b - discriminant) / (2 * a) t2 = (-b + discriminant) / (2 * a) return (0 <= t1 <= 1) or (0 <= t2 <= 1)
def on_frame(self): self.ball.body.add_force(Vector(0, 0.5)) self.ball.body.integrate_force() for rock in self.rocks: if self.collision.try_collide_polygon(rock.body, preserve=0.3): break self.draw_entity(self.ball)
def __init__(self, game_states): GameState.__init__(self) self.game_states = game_states self.add(self.move, 1 / target_fps) self.add(self.delete_gf, 1 / 10) self.add(self.shoot, 1 / 2) self.add(self.create_gravity_field, 1 / 2) self.add(self.back, 1 / 20) self.add(self.zoom_out, 1 / target_fps) self.add(self.zoom_in, 1 / target_fps) self.add(self.recenter, 1 / 3) self.add(self.change_perspective, 1 / 1) self.word_to_vector = { 'up': Vector(0, -1), 'down': Vector(0, 1), 'left': Vector(-1, 0), 'right': Vector(1, 0) }
def distance_line(self, other): c = Vector(self - other.get_coordinates()) lam = (c * other.e) / (other.e * other.e) if lam <= 0: return c * (-1) elif lam >= 1: return other.e - c else: eps = (c ** other.e) / (other.e * other.e) return other.e.right_angled() * eps * (-1)
def __init__(self, ball_type: BallType, pos: Coordinates, mass: float, radius: float, vel=None): self.ball_type = ball_type self.pos = pos self.mass = mass self.radius = radius if vel is None: self.vel = Vector(0, 0)
def test_init(self): name = '1' pos = Coordinates(0, 0) mass = 1.0 radius = 1.0 p = PoolBall(name, pos, mass, radius) self.assertEqual(p.type, name) self.assertEqual(p.pos, pos) self.assertEqual(p.mass, mass) self.assertEqual(p.radius, radius) self.assertEqual(p.vel, Vector(0, 0)) # Default should be 0
def distance_rectangle(self, other): c = other.get_coordinates() if self.x < c.x: if self.y < c.y: return Vector(c - self) elif self.y > c.y + other.b: return Vector(c + Coordinates(0, other.b) - self) else: return self.distance(other.get_lines()[0]) elif self.x > c.x + other.a: if self.y < c.y: return Vector(c + Coordinates(other.a, 0) - self) elif self.y > c.y + other.b: return Vector(c + Coordinates(other.a, other.b) - self) else: return self.distance(other.get_lines()[2]) else: if self.y < c.y: return self.distance(other.get_lines()[3]) elif self.y > c.y + other.b: return self.distance(other.get_lines()[1]) else: return Vector(0, 0)
def test_resolve_ball_ball_collision_2d_one_moving(self): # Initialize ball objects ball_a = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) ball_b = PoolBall(ball_type=BallType.CUE, pos=Coordinates(0.0, 0.0), mass=1.0, radius=0.5) # A enters from NW (135 degrees), contacts B on its left (180 degrees) # B is stationary, located at origin # A should exit S (270 degrees) # B should exit E (0 degrees) ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, 0.0), Vector(1.0, -1.0), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(0.0, -1.0) b_vel_new = Vector(1.0, 0.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new) # A enters from 122.3 degrees, contacts B on its left (180 degrees) # B is stationary, located at origin # A should exit S (270 degrees), with y-component of initial magnitude # B should exit E (0 degrees), with x-component of initial magnitude mag = 7.14 ang = 32.3 ball_a.pos, ball_a.vel, ball_a.mass = Coordinates(-1.0, 0.0), Vector(mag * np.cos(ang), -mag * np.sin(ang)), 3.0 ball_b.pos, ball_b.vel, ball_b.mass = Coordinates(0.0, 0.0), Vector(0.0, 0.0), 3.0 resolve_ball_ball_collision(ball_a, ball_b) a_vel_new = Vector(0.0, -mag * np.sin(ang)) b_vel_new = Vector(mag * np.cos(ang), 0.0) self.assertVectorAlmostEqual(ball_a.vel, a_vel_new) self.assertVectorAlmostEqual(ball_b.vel, b_vel_new)
def get_point_on_line_distance_from_point(line_start, line_end, point, distance) -> Coordinates: a_side = distance c_side = get_distance(line_start, point) v_point = Vector(point.x - line_start.x, point.y - line_start.y) v_line = Vector(line_end.x - line_start.x, line_end.y - line_start.y) dot = v_point.dot_product(v_line) a_angle = np.arccos(dot / v_point.get_magnitude() / v_line.get_magnitude()) from physics.trianglesolver import solve (a_side, b_side, c_side, a_angle, b_angle, c_angle) = solve(a=a_side, c=c_side, A=a_angle, ssa_flag='obtuse') assert a_angle + b_angle + c_angle == np.radians( 180), 'a_angle: {} \nb_angle: {}\nc_angle: {}\n'.format( a_angle, b_angle, c_angle) # Compute exact point angle = np.radians(get_angle(line_end, line_start)) x = line_start.x + b_side * np.cos(angle) y = line_start.y + b_side * np.sin(angle) return Coordinates(x, y)
def __init__(self, mass=1, position=Vector(0, 0), velocity=Vector(0, 0)): self.mass = mass self.position = position self.velocity = velocity self.acceleration = Vector(0, 0)
def __init__(self, actor): Thread.__init__(self, actor) self.gravity = 9.8 self.acceleration = Vector(0, self.gravity / 10) self.actor = actor self.force = actor.mass * self.gravity
import time import threading, multiprocessing import pygame from graphics.graphics_objects import Circle, PrimarySurface from graphics.graphics_engine import Renderer from physics.physics_objects import CirclePhysicsObject from physics.physics_engine import Engine from physics.vector import Vector screen_size = [800,800] base_surface = PrimarySurface(screen_size) my_location = Vector(500, 500) phys_obj = CirclePhysicsObject(my_location, 1, 5) graph_obj = Circle(base_surface, my_location, 5) phys_engine = Engine() phys_engine.register_object(phys_obj) renderer = Renderer(screen_size, base_surface) renderer.register_object(graph_obj, 1) # thread_lock = threading.Lock() # renderer.run(thread_lock) # phys_engine.run(thread_lock)
def newton_g(self, field): r = Vector(field.get_center_of_gravity() - self.get_center_of_gravity()) return r * (self.mass * field.mass / abs(r) ** 3 * constants.G)
# then calculates the shortest distance to move `object1` out of # `object2`, and returns a vector representing that movement. If # there is no collision, a vector (0, 0) will be returned. from physics.collision import get_exit_direction from physics.vector import Vector window = Window() paddle_image = load_image('paddle.png') paddle_image.anchor_x = paddle_image.width / 2 paddle_sprite = Sprite(paddle_image, 0, 10) ball_image = load_image('ball.png') ball_sprite = Sprite(ball_image, 10, 300) ball_velocity = Vector() ball_velocity.x = 50 ball_velocity.y = -50 @window.event def on_draw(): window.clear() paddle_sprite.draw() ball_sprite.draw() @window.event def on_mouse_motion(mouse_x, mouse_y, dx, dy): right_side = window.width - paddle_sprite.width / 2 left_side = paddle_sprite.width / 2 if mouse_x > right_side:
def set_global_force(value: Sequence): if(not isinstance(value, Sequence) and len(value)!=2): raise ValueError PhysicsObject.__global_forces = Vector(*value)
def gravity(self): v = Vector(0, 0) for field in World.gravity_fields: v += self.newton_g(field) return v
from pyglet.clock import schedule_interval from pyglet.app import run from physics.collision import get_exit_direction from physics.vector import Vector from physics.rect import Rect window = Window() paddle_image = load_image('paddle.png') paddle_sprite = Sprite(paddle_image, 0, 10) ball_image = load_image('ball.png') ball_sprite = Sprite(ball_image, 10, 300) ball_velocity = Vector.new(50, -50) left_wall = Rect.new(0, 0, 0, window.height) top_wall = Rect.new(0, window.height, window.width, 0) right_wall = Rect.new(window.width, 0, 0, window.height) walls = [left_wall, top_wall, right_wall, paddle_sprite] @window.event def on_draw(): window.clear() paddle_sprite.draw() ball_sprite.draw() @window.event def on_mouse_motion(mouse_x, mouse_y, dx, dy):