def render(direction: math.Vector2, window_size: tuple, surface: Surface) -> None: start_pos = math.Vector2 (window_size[0]/2, window_size[1]/2) if direction is None or direction.length() < 0.05: draw.circle(surface, (255, 0, 0), start_pos, 5, 1) else: # copy, no reference vector = math.Vector2(direction) length = vector.length() vector.scale_to_length(length * 100) draw.aaline(surface, (0, 255, 0), start_pos, start_pos + vector)
def apply_vector(self, vector: Vector): """Applique un vecteur à la position de la voiture Parameters ---------- vector: Vecteur à appliquer""" self.position[0] += vector.x self.position[1] += vector.y self.distance += vector.length()
def at_least(value: Vector2, minimum: [int, float]) -> Vector2: """ :param value - vector to be truncated :param minimum - vector minimum length :return pygame.math.Vector2 object Returns a vector object that has at least the given length. Vector will inherit the angle of the given value vector. """ if value.length() < minimum: value.scale_to_length(minimum) return value
def truncate(value: Vector2, maximum: [int, float]) -> Vector2: """ :param value - vector to be truncated :param maximum - vector length limit :return pygame.math.Vector2 object Returns a vector object that is limited a given length. Vector will inherit the angle of the given value vector. """ if value.length() > maximum: value.scale_to_length(maximum) return value
def trigger(self, ev_manager): super().trigger(ev_manager) ev_manager.post( EventRadiusNotMoveStart(self.player_list[self.player_index])) self.duration = model_const.radius_not_move_duration self.active = True position = self.player_list[self.player_index].position for player in self.player_list: if player.index != self.player_index and \ Vec.length(position - player.position) <= model_const.radius_not_move_radius + player.radius: player.freeze = True self.freeze_list.append(player)
def test_katkaise_vektori(self): """ Tarkastaa etta vektori lyhennetaan tarvittaessa ja etta sita ei lyhenneta kun ei tarvitse. """ vektori = Vector(3,3) alkuperainen_pituus = vektori.length() maksimi_pienempi = 0.5*alkuperainen_pituus maksimi_isompi = 2*alkuperainen_pituus self.yksilo.katkaise_vektori(vektori,maksimi_pienempi) self.assertTrue(vektori.length() == maksimi_pienempi, "Vektorin katkaisu ei toimi") vektori = Vector(3,3) self.yksilo.katkaise_vektori(vektori,maksimi_isompi) self.assertTrue(vektori.length() == alkuperainen_pituus, "Vektorin katkaisemattomuus ei toimi")
def seinamaetaisyys(self,yksilo): """ Palauttaa vektorin, joka menee yksilosta lahimpaan seinaan """ lyhin = Vector(1000,1000) for seina in self.seinien_paikkavektorit: etaisyys = seina - yksilo.paikka if (etaisyys.length() < lyhin.length()): lyhin = etaisyys return lyhin
class Missile(Entity): def __init__(self, player, entities, xpos, ypos): super().__init__(entities, xpos, ypos, 2 * missile_prox, 2 * missile_prox) self.target = player self.a = Vec(0, 0) self.v = Vec(0, 0) self.prox = missile_prox self.state_counter = 0 self.explosion_radius = missile_explosion_radius self.max_speed = missile_max_speed self.sfd = False # Drawing surface and state counter self.set_state(MissileState.WAITING) def get_bbox(self): return (self.pos - (missile_radius, missile_radius), self.pos + (missile_radius, missile_radius)) def set_state(self, state): if state == MissileState.WAITING: self.a = Vec(0, 0) self.v = Vec(0, 0) self._surface = mk_wait_surface(self.xsize, self.ysize, self.center) elif state == MissileState.TARGETING: self.a = Vec(0, 0) self.v = Vec(0, 0) self._surface = mk_target_surface(self.xsize, self.ysize, self.center) elif state == MissileState.EXPLODING: self.a = Vec(0, 0) self.v = Vec(0, 0) self._surface = mk_exploding_surface(self.xsize, self.ysize, self.center) self.state = state def update(self, time, entities): if (self.state == MissileState.WAITING): # Trigger if the player is close if get_dist(self, self.target) < self.prox: self.set_state(MissileState.TARGETING) # Trigger if the player clicks on something close elif self.target.target is not None: if get_dist(self, self.target.target) < self.prox: self.set_state(MissileState.TARGETING) elif (self.state == MissileState.TARGETING): # Collision with solids for e in entities: if e.is_solid and collide(self, e): self.die("") # Explode near the player if vec_from(self, self.target).length( ) < missile_explosion_radius + self.target.xsize / 2: self.die("") # Accelerate towards the player da = vec_from(self, self.target) da += self.target.v * time da = da.normalize() da *= missile_homingness self.a = da elif (self.state == MissileState.EXPLODING): # TODO: lower velocity self.state_counter += 1 # 10 frames of missile explosion # TODO: time-based? if self.state_counter == 10: self.sfd = True # Kill player if they are close if get_dist(self, self.target ) < missile_explosion_radius + self.target.xsize: self.target.die("Blown up by a missile.") # Physics self.v += self.a if self.v.length() > missile_max_speed: self.v.scale_to_length(missile_max_speed) self.pos += self.v * time self.pos = wrap_around(self.pos) def draw(self, screen): if self.target is not None and self.state == MissileState.TARGETING: draw_line(screen, self.pos, self.target.pos, missile_explosion_color) super().draw(screen) def die(self, msg): self.set_state(MissileState.EXPLODING)
class Yksilo(object): def __init__(self, x ,y , size=5, color = (0,0,255), width = 0): self.x = x self.y = y self.size = size self.color = color self.width = width self.massa = 1. self.paikka = Vector(x,y) self.nopeus = Vector(0,0) self.suunta = Vector(0,0) self.voima = Vector(0,0) self.max_voima= 1.0 self.max_nopeus = 1.7 def laske_uusi_paikka(self): self.edellinen_paikka = self.paikka if (self.voima.length() != 0): self.katkaise_vektori(self.voima, self.max_voima) kiihtyvyys = self.voima/self.massa nopeus = self.nopeus + kiihtyvyys self.katkaise_vektori(nopeus,self.max_nopeus) #laske uusi paikkavektori uusi_paikka = nopeus+self.paikka #paivita katsomissuunta ja nopeus self.nopeus = nopeus self.suunta = nopeus.normalize() else: uusi_paikka = self.paikka #uusi paikka paivitetaan vasta kaytosmallissa return uusi_paikka def jarruta(self): """ asettaa ohjausvoiman nollaan, eli pysayttaa yksilon valittomasti """ self.voima -= self.voima def katkaise_vektori(self,vektori, maksimi): """ lyhentaa parametria vektori jos se on pidempi kuin parametri maksimi. suunta pysyy ennallaan """ if (vektori.length()>maksimi): vektori.scale_to_length(maksimi)
def _target_close(target_dist: Vector2) -> bool: return target_dist.length() < DETECT_RADIUS
class Entity(Sprite): """Base class for all moving Entities""" # Keep a group of all entities for the purpose of updating and drawing group = SpriteGroup() def __init__(self, size=(1, 1), pos=(0, 0)): Sprite.__init__(self) # Radius attribute for collision detection, circle centered on pos self.radius = size[0] / 2 self.image = Surface(size).convert() self.image.set_colorkey(COLOR.BLACK) # set black as transparency color self.orig_img = self.image # Keep an original copy for rotation purposes self.rect = self.image.get_rect(center=pos) self.position = Vector(pos) self.velocity = Vector(0, 0) self.angle = 0 self.rotation_speed = 0 self.max_velocity = 10 self.max_rotation = 10 Entity.group.add(self) def calc_position(self): """Calculates the next position based on velocity""" if self.velocity.length() > self.max_velocity: # Scale velocity to max self.velocity.scale_to_length(self.max_velocity) return self.position + self.velocity def calc_rotation(self): """Calculates the next angle in the rotation""" if self.rotation_speed > self.max_rotation: self.rotation_speed = self.max_rotation if self.rotation_speed < -self.max_rotation: self.rotation_speed = -self.max_rotation return self.angle + self.rotation_speed def move(self, pos=Vector(0, 0)): """Moves the position to the Vector2 given""" # Wrap around the screen if pos.x > SCREEN_WIDTH: pos.x = 0 elif pos.x < 0: pos.x = SCREEN_WIDTH if pos.y > SCREEN_HEIGHT: pos.y = 0 elif pos.y < 0: pos.y = SCREEN_HEIGHT self.position = pos # Set the center of the rect to the position self.rect.center = self.position def rotate(self, angle=0): """Rotates the angle and the sprite image""" # Normalize angle into 360 deg if angle > 360: angle -= 360 elif angle < 360: angle += 360 self.angle = angle self.image = rotate(self.orig_img, -self.angle) self.rect = self.image.get_rect(center=self.rect.center) def update(self): """Called every tick to update the state of the Entity""" self.rotate(self.calc_rotation()) self.move(self.calc_position())