def shoot(self): if self.ammo <= 0: self.removePower() pos = self.gunLocation() if self.weapon == Weapon.MACHINE_GUN: ball_speed = 20 power = 1 ball = Bullet( pos, geo.Vector2D( power * ball_speed * np.cos(np.radians(self.angle)), -power * ball_speed * np.sin(np.radians(self.angle)))) elif self.weapon == Weapon.LASER: info = pygame.display.Info() screenWidth, screenHeight = info.current_w, info.current_h ball = Laser( pos, geo.Vector2D( 2 * screenWidth * np.cos(np.radians(self.angle)), -2 * screenHeight * np.sin(np.radians(self.angle)))) pygame.mixer.Sound.play(ball.sound) self.ammo -= 1 self.lastShootTime = time.time() return ball
def update(self): # powerup logic if self.powerActive: timeSpentActivated = time.time() - self.lastPowerupTime self.power.timeLeft = self.power.startTimeLeft - timeSpentActivated if self.power.timeLeft <= 0: self.removePower() if self.hasPower() and self.power.timeLeft <= 0: self.removePower() if not self.invincible(): self.controlled = True # flying logic if self.controlled: if self.flying: self.a = geo.Vector2D(0, -self.WEIGHT) else: self.a = geo.Vector2D(0, self.WEIGHT) else: self.a = geo.Vector2D.zero() self.v = geo.Vector2D.zero() self.v += self.a self.rect.move_ip(*self.v)
def testAddition(self): actual = self.vectorQ1 + self.vectorQ2 expected = geometry.Vector2D(0, 8) self.assertEqual(actual, expected) actual = self.vectorQ1 + 3 expected = geometry.Vector2D(6, 7) self.assertEqual(actual, expected)
def testSubtraction(self): actual = self.vectorQ1 - self.vectorQ2 expected = geometry.Vector2D(6, 0) self.assertEqual(actual, expected) actual = self.vectorQ1 - 3 expected = geometry.Vector2D(0, 1) self.assertEqual(actual, expected)
def tearDown(self): self.assertTrue(self.vectorQ1 == geometry.Vector2D(3, 4)) self.assertTrue(self.vectorQ2 == geometry.Vector2D(-3, 4)) self.assertTrue(self.vectorQ3 == geometry.Vector2D(-1, -1)) self.assertTrue(self.vectorQ4 == geometry.Vector2D(6, -8)) self.assertTrue(self.vectorQ1 == [3, 4]) self.assertTrue(self.vectorQ2 == [-3, 4]) self.assertTrue(self.vectorQ3 == [-1, -1]) self.assertTrue(self.vectorQ4 == [6, -8])
def collided(left, right): topline = geo.Vector2D(*right.rect.topleft) - geo.Vector2D(*left.pos()) bottomline = geo.Vector2D(*right.rect.bottomleft) - geo.Vector2D(*left.pos()) if geo.Vector2D.angle_between(left.v, topline) < 0 < geo.Vector2D.angle_between(left.v, bottomline): return True else: return False
def testAdditionToSelf(self): actual = geometry.Vector2D.zero() actual += self.vectorQ1 expected = geometry.Vector2D(3, 4) self.assertEqual(actual, expected) actual = geometry.Vector2D(3, 4) actual += 3 expected = geometry.Vector2D(6, 7) self.assertEqual(actual, expected)
def testSubtractionToSelf(self): actual = geometry.Vector2D.zero() actual -= self.vectorQ1 expected = geometry.Vector2D(-3, -4) self.assertEqual(actual, expected) actual = geometry.Vector2D(3, 4) actual -= 3 expected = geometry.Vector2D(0, 1) self.assertEqual(actual, expected)
def setUp(self): # Vectors in each quadrant # Q1 is top right: x>0, y>0, and goes counter clockwise self.vectorQ1 = geometry.Vector2D(3, 4) self.vectorQ2 = geometry.Vector2D(-3, 4) self.vectorQ3 = geometry.Vector2D(-1, -1) self.vectorQ4 = geometry.Vector2D(6, -8) self.vectors = [ self.vectorQ1, self.vectorQ2, self.vectorQ3, self.vectorQ4 ]
def collided(laser, other): topline = geo.Vector2D(*other.rect.topleft)\ - geo.Vector2D(*laser.pos()) bottomline = geo.Vector2D(*other.rect.bottomleft)\ - geo.Vector2D(*laser.pos()) if geo.Vector2D.angle_between(laser.v, topline)\ < 0 < geo.Vector2D.angle_between(laser.v, bottomline): return True else: return False
def testAngles(self): north = geometry.Vector2D(0, 1) south = geometry.Vector2D(0, -1) west = geometry.Vector2D(-1, 0) east = geometry.Vector2D(1, 0) northeast = geometry.Vector2D(1, 1) northwest = geometry.Vector2D(-1, 1) southeast = geometry.Vector2D(1, -1) southwest = geometry.Vector2D(-1, -1) specialTriangle = geometry.Vector2D.create_from_angle(math.pi / 6, 2) self.assertEqual(north.angle(), math.pi / 2) self.assertEqual(south.angle(), -math.pi / 2) self.assertEqual(west.angle(), math.pi) self.assertEqual(east.angle(), 0) self.assertAlmostEqual(northeast.angle(), math.pi / 4, delta=0.01) self.assertAlmostEqual(northwest.angle(), 3 * math.pi / 4, delta=0.01) self.assertAlmostEqual(southeast.angle(), -math.pi / 4, delta=0.01) self.assertAlmostEqual(southwest.angle(), -3 * math.pi / 4, delta=0.01) self.assertAlmostEqual(specialTriangle.angle(), math.pi / 6, delta=0.01)
def generatePowerup(self): spawnPoint = geo.Vector2D(*self.rect.center) spawnPoint += geo.Vector2D.create_from_angle(self.rng.random() * 2 * np.pi, self.rng.random() * self.POWERUP_SPAWN_RADIUS) self.powerup = Powerup(spawnPoint.tuple(), PowerupType(int(self.rng.random() * PowerupType.NUMBER_POWERUPS.value))) self.timeUntilGeneration = self.rng.exponential(self.POWERUP_SPAWN_INTERVAL)
def testScalarMultiplication(self): actual = self.vectorQ1 * 2 expected = geometry.Vector2D(6, 8) self.assertEqual(actual, expected) actual = 2 * self.vectorQ1 self.assertEqual(actual, expected)
def __init__(self): SceneBase.__init__(self) self.v = geo.Vector2D.zero() self.a = geo.Vector2D(0, 1) self.elasticity = 0.8 self.friction = 0.1 self.starttime = time.time()
def draw(self, screen): t = (time.time() - self.shootTime) / self.LASER_TIME t = utilities.bound(0, t, 1) thickness = round((1 - t) * 3) color = colors.RED pygame.draw.line(screen, color, self.rect.topleft, (geo.Vector2D(*self.pos()) + self.v).tuple(), thickness)
def makeTracks(self): """Generate tracks based on the specified number of azimuthal angle, subdivisions, and track spacing. """ # Geometry preliminaries w = self.geometry.width # Width of 2D domain h = self.geometry.height # Height of 2D domain self.div = 2 # Azimuthal angle subdivision, e.g. div=2 is (0,pi) nangle = self.nangle // self.div # Num of azimuthal angles followed self.angles = [Angle() for i in range(nangle)] for i, a in enumerate(self.angles): p = 2 * pi / self.nangle * (0.5 + i) # Desired angles a.nx = int(abs(w / self.delta * sin(p)) + 1) # Num of intersections along x-axis a.ny = int(abs(h / self.delta * cos(p)) + 1) # Num of intersections along y-axis a.phi = arctan(h * a.nx / (w * a.ny)) # Actual angle if p > pi / 2: a.phi = pi - a.phi # Fix angles in (pi/2, pi) a.xprime = w / a.nx # Spacing between points along x-axis a.yprime = h / a.ny # Spacing between points along y-axis a.delta = a.xprime * sin(a.phi) # Actual track spacing # Determine azimuthal weight for i, a in enumerate(self.angles): if i + 1 < nangle: x1 = 0.5 * (self.angles[i + 1].phi - a.phi) else: x1 = 2 * pi / self.div - a.phi if i > 0: x2 = 0.5 * (a.phi - self.angles[i - 1].phi) else: x2 = a.phi a.weight = (x1 + x2) / (2 * pi) * a.delta**2 * self.div # Determine coordinates self.tracks = [] for a in self.angles: xin = zeros(a.nx + a.ny) yin = zeros(a.nx + a.ny) xin[:a.nx] = a.xprime * (0.5 + arange(a.nx)) yin[:a.nx] = 0 yin[a.nx:] = a.yprime * (0.5 + arange(a.ny)) if sin(a.phi) > 0 and cos(a.phi) > 0: xin[a.nx:] = 0 elif sin(a.phi) > 0 and cos(a.phi) < 0: xin[a.nx:] = w self.tracks.append([]) for x, y in zip(xin, yin): r_in = geom.Vector2D(x, y) r_out = self.geometry.endpoint(r_in, a.phi) newTrack = Track2D(r_in, r_out, a) self.tracks[-1].append(newTrack)
def collided(projectile, other): overlap = pygame.sprite.collide_mask(projectile, other) if not overlap: topline = geo.Vector2D(*other.rect.topleft)\ - geo.Vector2D(*projectile.lastPos) bottomline = geo.Vector2D(*other.rect.bottomleft)\ - geo.Vector2D(*projectile.lastPos) aimedAtOther = geo.Vector2D.angle_between(projectile.v, topline)\ < 0 < geo.Vector2D.angle_between(projectile.v, bottomline) validPos = projectile.lastPos[0] <= other.rect.right\ and projectile.pos()[0] >= other.rect.left passedThrough = aimedAtOther and validPos return overlap or passedThrough
def Update(self): mouse = pygame.mouse.get_pos() click = pygame.mouse.get_pressed() info = pygame.display.Info() screenWidth, screenHeight = info.current_w, info.current_h # follow mouse drag if time.time() - self.starttime > self.DELAY and click[0]: currentPos = geo.Vector2D(*mouse) self.v = currentPos - self.lastPos self.lastPos = currentPos self.ballrect.center = mouse if self.ballrect.left < 0: self.ballrect.left = 0 if self.ballrect.right > screenWidth: self.ballrect.right = screenWidth if self.ballrect.top < 0: self.ballrect.top = 0 if self.ballrect.bottom > screenHeight: self.ballrect.bottom = screenHeight else: self.lastPos = geo.Vector2D(*mouse) self.v += self.a self.ballrect.move_ip(*self.v) if self.ballrect.left < 0: self.v.x = -self.v.x * self.elasticity self.ballrect.left = 0 if self.ballrect.right > screenWidth: self.v.x = -self.v.x * self.elasticity self.ballrect.right = screenWidth if self.ballrect.top < 0: self.v.y = -self.v.y * self.elasticity self.ballrect.top = 0 if self.ballrect.bottom > screenHeight: self.v.y = int(-self.v.y * self.elasticity) if self.v.x > 0: self.v.x = int(self.v.x - self.friction) elif self.v.x < 0: self.v.x = int(self.v.x + self.friction) self.ballrect.bottom = screenHeight
def driveCPU(self, car): nextCheckpointIndex = (car.checkpoint + 1)\ % len(self.checkpoints) nextCheckpoint = self.checkpoints[nextCheckpointIndex] # randomize target around a circle target = geo.Vector2D(*nextCheckpoint.rect.center) target += geo.Vector2D.create_from_angle( self.rng.random() * 2 * np.pi, self.rng.random() * self.CPU_TARGET_RADIUS) car.driveTowards(target) self.quitButton.update()
def drivePlayer(self): mouse = pygame.mouse.get_pos() click = pygame.mouse.get_pressed() mousePos = geo.Vector2D(*mouse) # follow mouse drag if click[0]: # left click self.player.driveTowards(mousePos) elif click[2]: # right click self.player.driveAwayFrom(mousePos) else: self.player.idle()
def mousePressEvent(self, event): side, shift_width, shift_height = self.get_radius_and_shifts() click_point = geometry.Vector2D(event.x(), event.y()) circle_center = geometry.Vector2D( shift_width + side / 2, shift_height + side / 2) if click_point.distance_to(circle_center) > side / 2: return button = event.button() if button == QtCore.Qt.LeftButton: self.mouse_press_coordinates = event.pos() if button == QtCore.Qt.RightButton: nearest_star = self.get_nearest_star(click_point) self.selected_constellation = (None if not nearest_star else nearest_star.constellation) self.update() if button == QtCore.Qt.MiddleButton: nearest_star = self.get_nearest_star(click_point) if nearest_star: self.show_info_popup(event.x(), event.y(), nearest_star)
def makeSegments(self): """Generate a segment for each part of each track that goes through a different flat source region. This method is not completely general right now and takes advantage of the fact that I know I only have two regions """ g = self.geometry for stack in self.geometry: for r in stack: r.volume_calc = 0 r.segments = [] for track in self: r = track.r_in phi = track.angle.phi if phi > pi / 2: sgn = -1 else: sgn = 1 while not r.closeTo(track.r_out): # Figure out what axial stack we're in foundNode = False for stack in g: node = stack.cell r_test = r + geom.Vector2D(sgn * 1e-6, 1e-6) if node.contains(r_test): foundNode = True break if not foundNode: raise d = node.distance(r, phi) r_new = r + geom.Vector2D(d * cos(phi), d * sin(phi)) s = Segment(stack, r, r_new) track.segments.append(s) r = r_new
def shoot(self): pos = self.origin() if self.weapon == Weapon.CANNON: ball_speed = 30 ball = Cannonball(pos, geo.Vector2D(self.power * ball_speed * math.cos(math.radians(self.angle)), -self.power * ball_speed * math.sin(math.radians(self.angle)))) pygame.mixer.Sound.play(self.cannon_sound) else: if self.weapon == Weapon.BOMB: ball_speed = 30 ball = Bomb(pos, geo.Vector2D(self.power * ball_speed * math.cos(math.radians(self.angle)), -self.power * ball_speed * math.sin(math.radians(self.angle)))) pygame.mixer.Sound.play(self.cannon_sound) elif self.weapon == Weapon.MACHINE_GUN: ball_speed = 50 ball = Bullet(pos, geo.Vector2D(self.power * ball_speed * math.cos(math.radians(self.angle)), -self.power * ball_speed * math.sin(math.radians(self.angle)))) pygame.mixer.Sound.play(ball.sound) else: info = pygame.display.Info() screenWidth, screenHeight = info.current_w, info.current_h ball = Laser(pos, geo.Vector2D(2*screenWidth*math.cos(math.radians(self.angle)), -2*screenHeight*math.sin(math.radians(self.angle)))) pygame.mixer.Sound.play(ball.sound) self.ammo -= 1 if self.ammo == 0: self.weapon = Weapon.CANNON self.lastShootTime = time.time() return ball
def __init__(self): SceneBase.__init__(self) info = pygame.display.Info() screenWidth, screenHeight = info.current_w, info.current_h self.ball = utilities.load_image('ball.png') self.ball.set_colorkey(colors.WHITE) self.ballrect = self.ball.get_rect() self.v = geo.Vector2D.zero() self.g = geo.Vector2D(0, 1) self.elasticity = 0.8 self.friction = 0.1 size = 20 self.obj = pygame.Surface([size, size]) self.obj.fill(colors.RED) self.objrect = pygame.Rect(screenWidth / 2, screenHeight / 2, size, size) self.hitLast = False self.starttime = time.time()
def testAngleBetween(self): north = geometry.Vector2D(0, 1) south = geometry.Vector2D(0, -1) west = geometry.Vector2D(-1, 0) east = geometry.Vector2D(1, 0) northeast = geometry.Vector2D(1, 1) northwest = geometry.Vector2D(-1, 1) southeast = geometry.Vector2D(1, -1) southwest = geometry.Vector2D(-1, -1) self.assertAlmostEqual(geometry.Vector2D.angle_between(north, south), math.pi) self.assertAlmostEqual(geometry.Vector2D.angle_between(east, west), math.pi) self.assertAlmostEqual(geometry.Vector2D.angle_between(north, east), -math.pi / 2) self.assertAlmostEqual(geometry.Vector2D.angle_between(north, west), math.pi / 2) self.assertAlmostEqual( geometry.Vector2D.angle_between(southeast, south), -math.pi / 4) self.assertAlmostEqual( geometry.Vector2D.angle_between(southeast, northeast), math.pi / 2) self.assertAlmostEqual(geometry.Vector2D.angle_between( southeast, northwest), math.pi, places=5) self.assertAlmostEqual( geometry.Vector2D.angle_between(southeast, west), -3 * math.pi / 4) self.assertAlmostEqual( geometry.Vector2D.angle_between(southwest, north), -3 * math.pi / 4) self.assertAlmostEqual( geometry.Vector2D.angle_between(southwest, southeast), math.pi / 2) self.assertAlmostEqual( geometry.Vector2D.angle_between(southwest, west), -math.pi / 4) self.assertAlmostEqual( geometry.Vector2D.angle_between(southwest, southwest), 0, 5)
def __init__(self): SceneBase.__init__(self) self.gravity = geo.Vector2D(0, 1) self.elasticity = 0.8 self.friction = 0.1 self.tank = (Tank((0, 0), (255, 0, 0))) self.projectiles = pygame.sprite.Group() self.explosions = [] self.baddies = pygame.sprite.Group() self.score = 0 self.baddie_queue = [] self.balloons = pygame.sprite.Group() self.startTime = time.time() self.lastBalloonSpawnTime = self.startTime self.timeOfLastAdd = {} self.timeOfLastAdd['bats'] = time.time() self.timeOfLastAdd['zombies'] = time.time() self.timeOfLastAdd['runners'] = time.time() self.speeds = {} self.speeds['zombies'] = 0.3 self.speeds['bats'] = 0.5 self.speeds['runners'] = 2 self.bomb = None self.highscore = self.loadScore('score.save')
def testCopy(self): actual = self.vectorQ1.copy() actual += 3 expected = geometry.Vector2D(6, 7) self.assertEqual(actual, expected) self.assertNotEqual(actual, self.vectorQ1)
def testLength(self): actual = geometry.Vector2D(3, 4).length() expected = 5 self.assertEqual(actual, expected)
def testScalarDivision(self): actual = self.vectorQ1 / 2 expected = geometry.Vector2D(1.5, 2) self.assertEqual(actual, expected)
def shootTowards(self, pos): # shoot towards the mouse location dr = geo.Vector2D(*pos) - geo.Vector2D(*self.rect.center) self.angle = (np.degrees( geo.Vector2D.angle_between(dr, geo.Vector2D(1, 0)))) return self.shoot()