Skip to content

Instantly share code, notes, and snippets.

@Abstrct
Created July 6, 2012 15:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Abstrct/3060931 to your computer and use it in GitHub Desktop.
Save Abstrct/3060931 to your computer and use it in GitHub Desktop.
CREATE OR REPLACE FUNCTION move_ships()
RETURNS boolean AS
$BODY$
DECLARE
ship_control_ record;
velocity point;
new_velocity point;
vector point;
delta_v numeric;
acceleration_angle numeric;
distance bigint;
current_tic integer;
BEGIN
IF NOT SESSION_USER = 'schemaverse' THEN
RETURN 'f';
END IF;
SELECT last_value INTO current_tic FROM tic_seq;
FOR ship_control_ IN SELECT SC.*, S.* FROM ship_control SC
INNER JOIN ship S ON S.id = SC.ship_id
WHERE (SC.target_speed <> SC.speed
OR SC.target_direction <> SC.direction
OR SC.speed <> 0)
AND S.destroyed='f' AND S.last_move_tic <> current_tic LOOP
-- If ship is being controlled by a set destination, adjust angle and speed appropriately
IF ship_control_.destination IS NOT NULL THEN
distance := (ship_control_.destination <-> ship_control_.location)::bigint;
IF distance < ship_control_.target_speed THEN
ship_control_.target_speed = distance::int;
END IF;
vector := ship_control_.destination - ship_control_.location;
ship_control_.target_direction := DEGREES(ATAN2(vector[1], vector[0]))::int;
IF ship_control_.target_direction < 0 THEN
ship_control_.target_direction := ship_control_.target_direction + 360;
END IF;
END IF;
velocity := point(COS(RADIANS(ship_control_.direction)) * ship_control_.speed,
SIN(RADIANS(ship_control_.direction)) * ship_control_.speed);
new_velocity := point(COS(RADIANS(ship_control_.target_direction)) * ship_control_.target_speed,
SIN(RADIANS(ship_control_.target_direction)) * ship_control_.target_speed);
vector := new_velocity - velocity;
delta_v := coalesce(velocity <-> new_velocity,0);
acceleration_angle := ATAN2(vector[1], vector[0]);
IF ship_control_.current_fuel < delta_v THEN
delta_v := ship_control_.current_fuel;
END IF;
new_velocity := velocity + point(COS(acceleration_angle)*delta_v, SIN(acceleration_angle)*delta_v);
ship_control_.direction = DEGREES(ATAN2(new_velocity[1], new_velocity[0]))::int;
IF ship_control_.direction < 0 THEN
ship_control_.direction := ship_control_.direction + 360;
END IF;
ship_control_.speed = (new_velocity <-> point(0,0))::integer;
ship_control_.current_fuel := ship_control_.current_fuel - delta_v::int;
-- Move the ship!
UPDATE ship S SET
last_move_tic = current_tic,
current_fuel = ship_control_.current_fuel,
location = ship_control_.location + point(COS(RADIANS(ship_control_.direction)) * ship_control_.speed,
SIN(RADIANS(ship_control_.direction)) * ship_control_.speed)
WHERE S.id = ship_control_.id;
UPDATE ship S SET
location_x = location[0],
location_y = location[1]
WHERE S.id = ship_control_.id;
UPDATE ship_control SC SET
speed = ship_control_.speed,
direction = ship_control_.direction
WHERE SC.ship_id = ship_control_.id;
END LOOP;
RETURN 't';
END
$BODY$
LANGUAGE plpgsql VOLATILE SECURITY DEFINER
COST 100;
ALTER FUNCTION move_ships()
OWNER TO schemaverse;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment