def _update_movement(self, dt): new_joy_direction = (euclid.Vector2(self.joystick.rx, -self.joystick.ry) if self.joystick is not None else None) if (new_joy_direction is not None and new_joy_direction.magnitude_squared() > 0.1): new_joy_direction.normalize() direction = new_joy_direction self.direction = new_joy_direction.xy else: direction = euclid.Vector2(self.direction[0], self.direction[1]) velocity = euclid.Vector2(0, 0) if (self.joystick is None or self.joystick.x * self.joystick.x + self.joystick.y * self.joystick.y < 0.05 and self.keyboard is not None): if self.keyboard[key.W]: velocity += direction if self.keyboard[key.S]: velocity -= direction if self.keyboard[key.D]: velocity += direction.cross() if self.keyboard[key.A]: velocity -= direction.cross() velocity.normalize() else: velocity += (self.joystick.x, -self.joystick.y) velocity *= velocity.magnitude_squared() if velocity.magnitude_squared() > 1.0: # This can never be True on physical analog sticks, # but should still be checked, as the driver theoretically allows this. velocity.normalize() velocity *= self.speed self.velocity = velocity.xy
def turn_by_angle(self, angle): turn = euclid.Matrix3.new_rotate(angle) self.direction = ( turn * euclid.Vector2(self.direction[0], self.direction[1])).xy self.velocity = (turn * euclid.Vector2(self.velocity[0], self.velocity[1])).xy self._state_update.update({ "velocity": self.velocity, "direction": self.direction })
def __get_d_h(delta, axis): if axis == HelixMovement.Axis.xy: d = euclid3.Vector2(delta.x, delta.y) h = delta.z elif axis == HelixMovement.Axis.yz: d = euclid3.Vector2(delta.y, delta.z) h = delta.x else: d = euclid3.Vector2(delta.z, delta.x) h = delta.y return d, h
def __find_tangents(start_to_center, end_to_center, ccw, big): p0 = euclid3.Vector2(-start_to_center.y, start_to_center.x) p1 = euclid3.Vector2(-end_to_center.y, end_to_center.x) p0 = p0 / p0.magnitude() p1 = p1 / p1.magnitude() if ccw: p0 *= -1 p1 *= -1 return p0, p1
def checar_bordas(self): if self.posicao.x <= self.raio: self.posicao.x = 2 * self.raio - self.posicao.x self.velocidade = self.velocidade.reflect(eu.Vector2( 1, 0)) * self.coef_elastico elif self.posicao.x > pyxel.width - self.raio: self.posicao.x = 2 * (pyxel.width - self.raio) - self.posicao.x self.velocidade = self.velocidade.reflect(eu.Vector2( 1, 0)) * self.coef_elastico elif self.posicao.y <= self.raio: self.posicao.y = 2 * self.raio - self.posicao.y self.velocidade = self.velocidade.reflect(eu.Vector2( 0, 1)) * self.coef_elastico elif self.posicao.y > pyxel.height + self.raio: self.permanecer = False
def time_step(self, game_state, dt): """ ROTTN game state update. Simulates enemies and game world objects. """ done = False hit = False if 0 in self.player_characters.keys(): r_player = euclid.Vector2( self.player_characters[0].position[0], self.player_characters[0].position[1], ) r_enemy = euclid.Vector2( self.npc_actors[0].position[0], self.npc_actors[0].position[1] ) r = r_player - r_enemy distance = r.magnitude() if distance > 900: done = True sys.stderr.write("Left arena\n") elif distance < 140 and self.npc_actors[0].is_attacking(): d_enemy = euclid.Vector2( self.npc_actors[0].direction[0], self.npc_actors[0].direction[1] ) angle = r.angle(d_enemy) if angle < 1.4 or (distance < 50 and angle < 1.57): hit = True sys.stderr.write("Hit\n") global GRAPH with GRAPH.as_default(): if 0 in self.player_characters.keys(): self.npc_actors[0].observe_and_act(self.player_characters[0], done, hit) if self.learn_counter >= 68: self.npc_actors[0]._agent.replay(66) self.learn_counter = 0 else: self.learn_counter += 1 update = {"npcs": {}} for npc_id, actor in self.npc_actors.items(): if done or hit: rand_angle = random.random() * 2 * math.pi actor.position = ( r_player.x + 600 * math.sin(rand_angle), r_player.y + 600 * math.cos(rand_angle), ) else: update["npcs"][npc_id] = actor.update(dt) return update
def __init__( self, position=(0, 0), direction=(0, 1), joystick=None, mouse_and_keyboard=True, speed=BASE_SPEED, ): super().__init__() self.position = position self.direction = (euclid.Vector2(0, 0) + direction).normalize().xy self.joystick = joystick if joystick is None: try: self.joystick = pyglet.input.get_joysticks()[0] except IndexError: print("Controller not found.") if self.joystick is not None: self.joystick.push_handlers(self) try: self.joystick.open(window=director.window) except OSError: pass # Controller was already openend if mouse_and_keyboard: self.keyboard = key.KeyStateHandler() director.window.push_handlers(self.keyboard) director.window.push_handlers(self) else: self.keyboard = None self.speed = speed self._speed = speed self.velocity = (0, 0) if cocos.actions.Move not in map(lambda x: x.__class__, self.actions): self.do(cocos.actions.Move()) self.schedule(self._update_movement)
def __find_geometry_from_r(delta, radius, ccw): D = delta.magnitude() big_arc = radius < 0 radius = abs(radius) if D == 0: raise Exception("Empty movement") if radius < D / 2: raise Exception("Too small radius") # distance from arc center to horde s = (radius**2 - (D / 2)**2)**0.5 if (ccw is False and not big_arc) or (ccw is True and big_arc): # Clock wise or ccw with angle > 180 # Center is right to horde center_side = 1 else: # Counter clock wise or cw with angle > 180 # Center is left to horde center_side = -1 horde_center_distance = s * center_side right = HelixMovement.__right_ortogonal_vector(delta) start_to_center = euclid3.Vector2( right.x * horde_center_distance + delta.x / 2, right.y * horde_center_distance + delta.y / 2) end_to_center = euclid3.Vector2( right.x * horde_center_distance - delta.x / 2, right.y * horde_center_distance - delta.y / 2) p0, p1 = HelixMovement.__find_tangents(start_to_center, end_to_center, ccw, big_arc) sina = D / (2 * radius) if sina > 1 and sina < 1 + threshold: sina = 1 if sina < -1 and sina > -1 - threshold: sina = -1 arc_angle = 2 * math.asin(sina) if big_arc: arc_angle = 2 * math.pi - arc_angle return start_to_center, p0, p1, arc_angle
def __init__(self): pyxel.init(255, 255) pyxel.mouse(True) self.gravidade = eu.Vector2(0, 0.5) self.bolas = [] self.segmentos = [] self.segmentos.append(Segmento(10.0, 120.0, 140.0, 180.0)) self.segmentos.append(Segmento(200.0, 120.0, 100.0, 90.0)) self.segmentos.append(Segmento(240.0, 180.0, 160.0, 200.0)) pyxel.run(self.atualizar, self.desenhar)
def atualizar(self): if pyxel.btn(pyxel.KEY_LEFT_BUTTON): bola = Bola(eu.Point2(pyxel.mouse_x, pyxel.mouse_y), eu.Vector2(0, 0), self.gravidade, 0.2) self.bolas.append(bola) for i, b in enumerate(self.bolas): b.atualizar() for s in self.segmentos: b.checar_colisao(s) for b2 in self.bolas[i + 1:]: b.checar_colisao(b2)
def find_geometry(source, target, ccw, axis, **kwargs): d, h = HelixMovement.__get_d_h(target - source, axis) # Now we don't support 'h'! if abs(h) > 1e-4: raise Exception("Arc don't support 'h'!") if "r" in kwargs.keys(): radius = kwargs["r"] start_to_center, tan0, tan1, arc_angle = HelixMovement.__find_geometry_from_r( d, radius, ccw) else: if axis == HelixMovement.Axis.xy: start_to_center = euclid3.Vector2(kwargs["i"], kwargs["j"]) elif axis == HelixMovement.Axis.yz: start_to_center = euclid3.Vector2(kwargs["j"], kwargs["k"]) else: start_to_center = euclid3.Vector2(kwargs["k"], kwargs["i"]) radius, tan0, tan1, arc_angle = HelixMovement.__find_geometry_from_ijk( d, start_to_center, ccw) if axis == HelixMovement.Axis.xy: dir_0 = euclid3.Vector3(tan0.x, tan0.y, 0) dir_1 = euclid3.Vector3(tan1.x, tan1.y, 0) center = source + euclid3.Vector3(start_to_center[0], start_to_center[1], 0) elif axis == HelixMovement.Axis.yz: dir_0 = euclid3.Vector3(0, tan0.x, tan0.y) dir_1 = euclid3.Vector3(0, tan1.x, tan1.y) center = source + euclid3.Vector3(0, start_to_center[0], start_to_center[1]) elif axis == HelixMovement.Axis.zx: dir_0 = euclid3.Vector3(tan0.y, 0, tan0.x) dir_1 = euclid3.Vector3(tan1.y, 0, tan1.x) center = source + euclid3.Vector3(start_to_center[1], 0, start_to_center[0]) return center, dir_0, dir_1, arc_angle
def atualizar(self): if pyxel.btnr(pyxel.MOUSE_LEFT_BUTTON): bola = Bola(eu.Point2(pyxel.mouse_x, pyxel.mouse_y), eu.Vector2(0, 0), self.gravidade, 0.8) self.bolas.append(bola) for i, b in enumerate(self.bolas): b.atualizar() if b.permanecer: for s in self.segmentos: b.checar_colisao(s) for b2 in self.bolas[i + 1:]: b.checar_colisao(b2) self.bolas = list(filter(lambda b: b.permanecer, self.bolas))
def observe_and_act(self, player: character_bases.Character, done=False, hit=False): # observe current state r_self = euclid.Vector2(self.position[0], self.position[1]) v_self = euclid.Vector2(self.velocity[0], self.velocity[1]) r_player = euclid.Vector2(player.position[0], player.position[1]) v_player = euclid.Vector2(player.velocity[0], player.velocity[1]) r_rel = r_player - r_self v_rel = v_player - v_self n = euclid.Vector2(self.direction[0], self.direction[1]) basis = [n, n.cross()] r = euclid.Vector2(r_rel.dot(basis[0]), r_rel.dot(basis[1])) v = euclid.Vector2(v_rel.dot(basis[0]), v_rel.dot(basis[1])) observation = numpy.array([[r.x, r.y, v.x, v.y]], dtype=float) # calculate reward for last action and remember # Problem with this reward: Not attacking and staying near the player is the best policy # to accumulate infinite reward if self._last_observation is not None: distance = r.magnitude() delta_distance = distance - self._last_observation[0][0] reward = (1.0 / (distance + 0.02) - 10.0 * delta_distance + 1 / (r.angle(euclid.Vector2(0, 1)) + 0.04)) if self.is_attacking() and not hit: reward -= 300.0 elif hit: reward += 1500.0 if done: reward -= 40.0 # penalty for going to far away self._agent.remember(self._last_observation, self._last_action, reward, observation, done) # act action = self._agent.predict_best_action(observation) self.perform_action(self.action_space[action]) # store stuff self._last_observation = observation self._last_action = action
def _update_animation_state(self, dt): #pylint: disable=w0613 v_squared = euclid.Vector2( self.moving_parent.velocity[0], self.moving_parent.velocity[1] ).magnitude_squared() if v_squared > 30 and self.animation_state == AnimationState.Idle: for character_part in self.sprites[self.animation_state]: self.sprites[self.animation_state][character_part][ self.direction_state ].visible = False self.sprites[AnimationState.Running][character_part][ self.direction_state ].visible = True self.animation_state = AnimationState.Running elif v_squared < 30 and self.animation_state == AnimationState.Running: for character_part in self.sprites[self.animation_state]: self.sprites[self.animation_state][character_part][ self.direction_state ].visible = False self.sprites[AnimationState.Idle][character_part][ self.direction_state ].visible = True self.animation_state = AnimationState.Idle
def update(self, dt): """ Updates the state of the test enemy NPC. """ if self.velocity != (0, 0): self.position = ( self.position[0] + self.velocity[0] * dt, self.position[1] + self.velocity[1] * dt, ) self._state_update.update({"position": self.position}) if self.is_attacking(): self.attack_counter -= dt if self.attack_counter <= 0: self.attack_counter = 0 self.velocity = ( ENEMY_VELOCITY * euclid.Vector2(self.direction[0], self.direction[1])).xy self._state_update.update({"velocity": self.velocity}) self._state_update.update({"attack_counter": self.attack_counter}) update = self._state_update.copy() self._state_update.clear() return update
def __right_ortogonal_vector(d): D = d.magnitude() right = euclid3.Vector2(d.y / D, -d.x / D) return right
def on_mouse_motion(self, x, y, dx, dy): turn = euclid.Matrix3.new_rotate(-0.01 * dx) self.direction = ( turn * euclid.Vector2(self.direction[0], self.direction[1])).xy