def update(self, walls, acceleration, friction): # Move by a given acceleration self.move(Vector(acceleration[0], acceleration[1])) # Iterate through all walls # and check for collisions for wall in walls: # Don't check walls if # they're too far from # a particle wallToLine = vector.subtract(wall.start, self.position) if (vector.magnitude(wallToLine) > vector.magnitude(wall.line)): continue # If the returned value is # greater than 0, the ball # is colliding with the wall clipVal = self.intersectsWall(wall) if (clipVal > 0): # Move the particle out of the wall dPos = vector.multiply(wall.normal, clipVal) self.position.addVector(dPos) # Bounce the particle off of the wall self.velocity = self.getReflection(copy.copy(wall.normal)) # Reduce the particle's velocity by # the friction coefficient self.velocity.scalarMultiply(friction)
def create_lr_matrix(self): """ create the left and right gaussian matrix :param input_matrix: list of rows (lists of numbers) :return: dictionary with the keys "l_matrix" and "r_matrix" and the matrices (list of rows) as values """ input_matrix = self._matrix l_matrix = create_standard(len(input_matrix)) for i in range(len(input_matrix)): divisor = float(1) / input_matrix[i][i] input_matrix[i] = [divisor * j for j in input_matrix[i]] l_matrix[i][i] *= divisor for remaining_rows in range(i + 1, len(input_matrix)): scalar = float( input_matrix[remaining_rows][i]) / input_matrix[i][i] input_matrix[remaining_rows] = \ vector.subtract(input_matrix[remaining_rows], vector.scale(scalar, input_matrix[i])) l_matrix[remaining_rows][i] -= scalar self._l_matrix = l_matrix self._r_matrix = input_matrix
def cast_ray(r): # walk the ray the distance to the nearest object start = r[0] for s in range(MAX_STEPS): if vector.length(vector.subtract(r[0], start)) > MAX_DISTANCE: break d, s = min_distance(r[0]) if d < TOLERANCE: return ray_colour(r, s) r[0] = vector.add(r[0], vector.scale(r[1], d)) return 0, 0, 0
def point_at(pos: Vector3, target: Vector3, up: Vector3): # Calculate new forward direction new_forward = vector.subtract(target, pos) new_forward.normalise() # Calculate new Up direction a: Vector3 = vector.multiply(new_forward, vector.dot_product(up, new_forward)) new_up: Vector3 = vector.subtract(up, a) new_up.normalise() # New Right direction is easy, its just cross product new_right: vector.Vector3 = vector.cross_product(new_up, new_forward) # Construct Dimensioning and Translation Matrix matrix = Matrix4() matrix.m[0][0] = new_right.x; matrix.m[0][1] = new_right.y; matrix.m[0][2] = new_right.z; matrix.m[0][3] = 0 matrix.m[1][0] = new_up.x; matrix.m[1][1] = new_up.y; matrix.m[1][2] = new_up.z; matrix.m[1][3] = 0 matrix.m[2][0] = new_forward.x; matrix.m[2][1] = new_forward.y; matrix.m[2][2] = new_forward.z; matrix.m[2][3] = 0 matrix.m[3][0] = pos.x; matrix.m[3][1] = pos.y; matrix.m[3][2] = pos.z; matrix.m[3][3] = 1 return matrix
def scroll(self, offset): """Scroll the view.""" # Clamp the view to the maprect. Subtle: the sprites are offset in the # opposite direction. clamped_rect = self.viewrect.move(offset) clamped_offset = vector.subtract(self.viewrect.topleft, clamped_rect.topleft) self.viewrect = clamped_rect self.cullrect.center = self.viewrect.center for sprite in self.all: sprite.scroll(clamped_offset)
def intersectsWall(self, wall1): # Get the directional vector # representing the wall wallDir = vector.normalize(wall1.line) # Get the length of the line # from the start of the wall # to the nearest point to the ball projectedMag = vector.dot(wallDir, vector.subtract(self.position, wall1.start)) # Scale the directional vector # by the projected magnitude wallDir.scalarMultiply(projectedMag) # Get the line between the # ball and the nearest point on the wall wallToBall = vector.subtract(vector.add(wallDir, wall1.start), self.position) # Return the amount the wall # is intersecting with the ball return self.size - vector.magnitude(wallToBall)
def updateForNewLocation(self, newLocationBasedOnActions): direction = vector.subtract(newLocationBasedOnActions, self.location) direction.normalize() direction.multiply(self.floorItSpeed) self.acceleration = direction; self.velocity.add(self.acceleration) self.velocity.limit(self.maxSpeed); self.velocity.stopIfSlowEnough(); self.velocity.divideByVector(vector=self.weight) self.location.add(self.velocity)
def bounce2(self, p2): """ More complicated bounce, should give better angles. Takes in the particle it is bouncing against and updates its speed too """ avgSpeed = vector.scale(vector.absAdd(self.speed, p2.speed), 0.5) # Average speed # Find the normalised vector from p1 to p2 n = vector.unit(vector.subtract(self.position, p2.position)) self.speed = vector.multiply(n, avgSpeed) p2.speed = vector.scale(vector.multiply(n, avgSpeed), -1) self.limitSpeed() p2.limitSpeed()
def animate(entity): x = 0 y = 0 difference = vector.subtract(entity.animation, entity.position) if vector.module(difference) > 5: animate_restore(entity) if entity.animation[X] < entity.position[X]: x = ANIMATION elif entity.animation[X] > entity.position[X]: x = -ANIMATION if entity.animation[Y] < entity.position[Y]: y = ANIMATION elif entity.animation[Y] > entity.position[Y]: y = -ANIMATION entity.animation = vector.add(entity.animation, (x, y))
def _fire(self): """Fire if the mouse button is held down.""" buttons = pygame.mouse.get_pressed() if buttons[0] and self.ammo and self.fire_wait_tick <= 0: pos = pygame.mouse.get_pos() velocity = vector.subtract(pos, self.rect.center) velocity = vector.normalize(velocity) velocity = vector.scalar_multiply(velocity, 10) velocity = vector.add(velocity, vector.intvector(self.velocity)) self.level.add(PlayerShot(velocity=list(velocity)), self.maprect.center) self.fire_wait_tick = 10 self.ammo -= 1 else: self.fire_wait_tick -= 1
def tick(): start_time = time.time() # user input keys = py.key.get_pressed() try: fps_mod = 1 / global_data.fps except ZeroDivisionError: fps_mod = 10 # movement forwards_movement = vector.multiply( global_data.camera_look_direction, global_data.camera_movement_speed * fps_mod) if keys[py.K_SPACE]: global_data.camera_position.y -= global_data.camera_movement_speed * fps_mod if keys[py.K_LSHIFT]: global_data.camera_position.y += global_data.camera_movement_speed * fps_mod if keys[py.K_d]: global_data.camera_position.x += global_data.camera_movement_speed * fps_mod if keys[py.K_a]: global_data.camera_position.x -= global_data.camera_movement_speed * fps_mod if keys[py.K_w]: global_data.camera_position = vector.add(global_data.camera_position, forwards_movement) if keys[py.K_s]: print(global_data.camera_position.z) global_data.camera_position = vector.subtract( global_data.camera_position, forwards_movement) # looking if keys[py.K_LEFT]: global_data.yaw += global_data.camera_movement_speed * fps_mod / 4 if keys[py.K_RIGHT]: global_data.yaw -= global_data.camera_movement_speed * fps_mod / 4 renderer.pygame_tick() renderer.draw_mesh(global_data.cube.triangles) global_data.tick += 1 global_data.fps = round(1 / (time.time() - start_time), 1) if global_data.tick % 10 == 0: py.display.set_caption(f'FPS: {global_data.fps}')
def create_source_ray(x, y): # https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-generating-camera-rays/generating-camera-rays cameraToWorld = scene['camera'] width = WIDTH / PIXEL_SCALE height = HEIGHT / PIXEL_SCALE a = math.tan(FOV / 2.0 * math.pi / 180.0) Px = (2.0 * ((x + 0.5) / width) - 1) * a * ASPECT_RATIO Py = (1.0 - 2.0 * ((y + 0.5) / height)) * a Rp = [Px, Py, -1.0] Ro = vector.origin() Row = matrix.apply(cameraToWorld, Ro) Rpw = matrix.apply(cameraToWorld, Rp) Rdw = vector.subtract(Rpw, Row) Rdw = vector.normalize(Rdw) return [Row, Rdw]
def hit(self): """Take additional damage. Add explosions and change the sprite to show damage, but don't destroy until hit several times. """ self.hits += 1 # Create an explosion slightly off-center. offset = vector.subtract(vector.randint(10, 10), (5, 5)) center = vector.add(self.maprect.center, offset) self.level.add(Explosion(), center) if self.hits == 3: # Change sprite to show damage. self.animation_view = self.__model__['damaged'].get_view() self._set_image(self.animation_view.frame) elif self.hits >= 5: # Destroy. self.destroy()
def getReflection(self, normal): # Get the dot product of the # wall's normal and the # particle's velocity wallNormalDot = vector.dot(self.velocity, normal) # Multiply the dot # product by 2 wallNormalDot *= 2 # Scale the normal by the # doubled dot product normal.scalarMultiply(wallNormalDot) # Subtract the scaled normal # from the velocity to get # the reflection vector reflection = vector.subtract(self.velocity, normal) # Return the reflection return reflection
def create_lr_matrix(self): """ create the left and right gaussian matrix :param input_matrix: list of rows (lists of numbers) :return: dictionary with the keys "l_matrix" and "r_matrix" and the matrices (list of rows) as values """ input_matrix = self._matrix l_matrix = create_standard(len(input_matrix)) for i in range(len(input_matrix)): divisor = float(1) / input_matrix[i][i] input_matrix[i] = [divisor * j for j in input_matrix[i]] l_matrix[i][i] *= divisor for remaining_rows in range(i + 1, len(input_matrix)): scalar = float(input_matrix[remaining_rows][i]) / input_matrix[i][i] input_matrix[remaining_rows] = \ vector.subtract(input_matrix[remaining_rows], vector.scale(scalar, input_matrix[i])) l_matrix[remaining_rows][i] -= scalar self._l_matrix = l_matrix self._r_matrix = input_matrix
# assertions.py from vector import (add, subtract, vector_sum, scalar_multiply, vector_mean, dot, sum_of_squares, magnitude, distance) from matrices import shape, identity_matrix, get_column, get_row, make_matrix # Vector assert add([1, 2, 3], [4, 5, 6]) == [5, 7, 9] assert subtract([5, 7, 9], [4, 5, 6]) == [1, 2, 3] assert vector_sum([[1, 2], [3, 4], [5, 6], [7, 8]]) == [16, 20] assert scalar_multiply(2, [1, 2, 3]) == [2, 4, 6] assert vector_mean([[1, 2], [3, 4], [5, 6]]) == [3, 4] assert dot([1, 2, 3], [4, 5, 6]) == 32 # 1 * 4 + 2 * 5 + 3 * 6 assert sum_of_squares([1, 2, 3]) == 14 # 1 * 1 + 2 * 2 + 3 * 3 assert magnitude([3, 4]) == 5 # Matrices assert shape([[1, 2, 3], [4, 5, 6]]) == (2, 3) # 2 rows, 3 columns assert identity_matrix(5) == [[1, 0, 0, 0, 0], [0, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]
def distance(position1, position2): return vector.module(vector.subtract(position1, position2))
def distance_to(sphere, point): # direction = sphere.p - point # distance = length(direction) - radius d = vector.subtract(point, sphere[0]) return vector.length(d) - sphere[1]
def view(self, sprite): """Center the viewrect on the sprite.""" offset = vector.subtract(sprite.rect.center, self.viewrect.center) self.scroll(offset)
def blue_loop(): blue.target = vector.add(pacman.position, vector.multiply_scalar(pacman.direction, 2)) difference = vector.subtract(blue.target, red.position) blue.target = vector.subtract(blue.target, difference) ghost_loop(blue)
def put_at(self, level, maploc): self.level = level self.maprect = self.rect.copy() self.maprect.center = maploc self.rect.center = vector.subtract(maploc, level.viewrect.topleft)
def normal(sphere, point): return vector.normalize(vector.subtract(point, sphere[0]))
def center(self, pos): offset = vector.subtract(pos, self.rect.center) super(Container, self).center(pos) for widget in self.contents: widget.move(offset)
#!/usr/bin/env python2 import vector import math v1 = 1,2,3 v2 = 3,4,5 n1 = vector.normalize(v1) assert vector.add(v1, v2) == (4, 6, 8) assert vector.subtract(v1, v2) == (-2, -2, -2) assert abs(n1[0] - 0.27) < 0.01 and \ abs(n1[1] - 0.53) < 0.01 and \ abs(n1[2] - 0.80) < 0.01 assert vector.dot(v1, v2) == 26 assert vector.cross(v1, v2) == (-2, 4, -2) print "All tests passed!"
#!/usr/bin/env python2 import vector import math v1 = [36.886, 53.177, 21.887] v2 = [38.323, 52.817, 21.996] v3 = [38.493, 51.553, 22.830] v4 = [39.483, 50.748, 22.463] n1 = vector.normalize(v1) n2 = vector.normalize(v2) v1 = n1 = 1,2,3 v2 = n2 = 3,4,5 print vector.add(v1, v2) print vector.subtract(v1, v2) print vector.normalize(v1) print vector.dot(n1, n2) print vector.cross(n1, n2) print vector.torsion(v1, v2, v3, v4)