def sim_fn(g: Plotter): env = g.entity(components=[Action, State]) car = g.entity(components=[Velocity, Position]) # process car physics # compute velocity based on acceleration action & decceleration due to gravity acceleration, gravity, max_speed = 0.001, 0.0025, 0.07 # apply acceleration based on accelerate action: # 0: Accelerate to the Left # 1: Don't accelerate # 2: Accelerate to the Right car[Velocity].x += (env[Action].accelerate - 1) * acceleration # apply gravity inverse to the mountain path used by the car # the mountain is defined by y = sin(3*x) # as such we apply gravity inversely using y = cos(3*x) # apply negative gravity as gravity works in the opposite direction of movement car[Velocity].x += g.cos(3 * car[Position].x) * (-gravity) car[Velocity].x = g.clip(car[Velocity].x, min_x=-max_speed, max_x=max_speed) # compute new position from current velocity min_position, max_position = -1.2, 0.6 car[Position].x += car[Velocity].x car[Position].x = g.clip(car[Position].x, min_position, max_position) # collision: stop car when colliding with min_position if car[Position].x <= min_position: car[Velocity].x = 0.0 # resolve simulation state: reward and simulation completition env[State].reward = 0 if car[Position].x >= 0.5 else -1 env[State].ended = True if car[Position].x > 0.5 else False
def physics_sys(g: Plotter): # compute velocity from car's rotation and speed car = g.entity(components=[Movement, Velocity, Position, Meta]) # rotation heading_x, heading_y = g.cos( car[Movement].rotation), -g.sin(car[Movement].rotation) # speed car[Velocity].x = car[Movement].speed * heading_x car[Velocity].y = car[Movement].speed * heading_y # update car position based on current velocity car[Position].x += car[Velocity].x car[Position].y += car[Velocity].y