Last active
April 1, 2025 13:16
-
-
Save abaines/5fd0352d55644da7c99cdd9d05c61be9 to your computer and use it in GitHub Desktop.
Oort scenario/tutorial https://oort.rs/scenario/tutorial
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Tutorial: Lead | |
// Destroy the enemy ship. Its position is given by the "target" function and velocity by the | |
// "target_velocity" function. Your ship is not able to accelerate in this scenario. | |
// | |
// This is where the game becomes challenging! You'll need to lead the target | |
// by firing towards where the target will be by the time the bullet gets there. | |
// | |
// Hint: target() + target_velocity() * t gives the position of the target after t seconds. | |
// | |
// You can scale a vector by a number: vec2(a, b) * c == vec2(a * c, b * c) | |
// | |
// p.s. You can change your username by clicking on it at the top of the page. | |
use oort_api::prelude::*; | |
const BULLET_SPEED: f64 = 1000.0; // m/s | |
pub struct Ship {} | |
impl Ship { | |
pub fn new() -> Ship { | |
Ship {} | |
} | |
pub fn radian_to_vec2(angle_radians: f64) -> Vec2 { | |
Vec2::new(angle_radians.cos(), angle_radians.sin()) | |
} | |
pub fn calculate() -> Vec2 { | |
let relative_position = target() - position(); | |
let a = target_velocity().dot(target_velocity()) - (BULLET_SPEED * BULLET_SPEED); | |
let b = 2.0 * relative_position.dot(target_velocity()); | |
let c = relative_position.dot(relative_position); | |
debug!("{} {} {}",a,b,c); | |
let discriminant = (b * b) - (4.0 * a * c); | |
let t1 = (-b + discriminant.sqrt()) / (2.0 * a); | |
let t2 = (-b - discriminant.sqrt()) / (2.0 * a); | |
let t = if t1 > 0.0 && t2 > 0.0 { | |
t1.min(t2) // Choose the earlier time. | |
} else if t1 > 0.0 { | |
t1 | |
} else if t2 > 0.0 { | |
t2 | |
} else { | |
// No positive time solution, target is behind us or we can't catch it. | |
-1.0 | |
}; | |
debug!("{}",t); | |
let intercept_position = target() + target_velocity() * t; | |
//let firing_direction = (intercept_position - position()).normalize(); | |
return intercept_position | |
} | |
pub fn tick(&mut self) { | |
//draw_line(position(), target(), 0x00ff00); | |
// let dp = target() - position(); | |
// debug!("distance to target: {}", dp.length()); | |
// let time_to_target_guess = dp.length() / BULLET_SPEED; | |
// debug!("time to target: {}", time_to_target_guess ); | |
// let predicted_target_pos = target()+(target_velocity()*time_to_target_guess ); | |
//draw_line(target(),predicted_target_pos ,0xaa0000); | |
//draw_line(position(),predicted_target_pos ,0x0000aa); | |
// let predicted_dp = predicted_target_pos - position(); | |
// let time_to_intercept = predicted_dp.length() / BULLET_SPEED; | |
// let intercept_point = target() + target_velocity() * time_to_intercept; | |
// draw_line(target(), intercept_point, 0xaaFF00); | |
// draw_line(position(), intercept_point, 0xFF00aa); | |
// let aim_angle = intercept_point.angle(); | |
// debug!("aim_angle {}",aim_angle); | |
let intercept_position = Self::calculate(); | |
draw_line(target(), intercept_position, 0xaaFF00); | |
draw_line(position(), intercept_position, 0xFF00aa); | |
let x:Vec2 = Self::radian_to_vec2(heading()); | |
draw_line(position(), 1000.0*x, 0xFFbbaa); | |
let aim_angle = intercept_position.angle(); | |
//debug!("calc {}",calc); | |
//debug!("calc.angle {}",calc.angle()); | |
let turn_angle = angle_diff(heading(), aim_angle ); | |
turn(turn_angle*99.0); | |
//fire(0); | |
debug!("turn_angle {}",turn_angle ); | |
if turn_angle.abs()<0.019 | |
{ | |
fire(0); | |
} | |
//turn(1.0); | |
//fire(0); | |
//debug!("{}",target_velocity()); | |
//debug!("{}",target_velocity().length()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Tutorial: Radar | |
// Destroy the enemy ships. Use your radar to find them. | |
// Hint: Press 'g' in-game to show where your radar is looking. | |
// Hint: Press 'n' to single-step. | |
// Hint: Use the set_radar_heading() function to keep your radar pointed at a | |
// target, or to search for a new one. | |
// | |
// Join the Discord at https://discord.gg/vYyu9EhkKH for Oort discussion and | |
// tournament results. | |
use oort_api::prelude::*; | |
const BULLET_SPEED: f64 = 1000.0; // m/s | |
pub struct Ship {} | |
impl Ship { | |
pub fn new() -> Ship { | |
Ship {} | |
} | |
pub fn radian_to_vec2(angle_radians: f64) -> Vec2 | |
{ | |
Vec2::new(angle_radians.cos(), angle_radians.sin()) | |
} | |
pub fn calculate() -> Vec2 { | |
let relative_position = target() - position(); | |
let a = target_velocity().dot(target_velocity()) - (BULLET_SPEED * BULLET_SPEED); | |
let b = 2.0 * relative_position.dot(target_velocity()); | |
let c = relative_position.dot(relative_position); | |
debug!("π€ {} {} {}",a,b,c); | |
let discriminant = (b * b) - (4.0 * a * c); | |
let t1 = (-b + discriminant.sqrt()) / (2.0 * a); | |
let t2 = (-b - discriminant.sqrt()) / (2.0 * a); | |
let t = if t1 > 0.0 && t2 > 0.0 { | |
t1.min(t2) // Choose the earlier time. | |
} else if t1 > 0.0 { | |
t1 | |
} else if t2 > 0.0 { | |
t2 | |
} else { | |
// No positive time solution, target is behind us or we can't catch it. | |
-1.0 | |
}; | |
debug!("β {}",t); | |
let intercept_position = relative_position + target_velocity() * t; | |
return intercept_position | |
} | |
pub fn tick(&mut self) { | |
let intercept_position = Self::calculate(); | |
draw_line(target(), intercept_position, 0xaaFF00); | |
draw_line(position(), intercept_position, 0xFF00aa); | |
let x:Vec2 = Self::radian_to_vec2(heading()); | |
draw_line(position(), 1000.0*x, 0xFFbbaa); | |
let aim_angle = intercept_position.angle(); | |
let turn_angle = angle_diff(heading(), aim_angle ); | |
turn(turn_angle*99.0); | |
//turn(0.3); | |
debug!("π§ {}",turn_angle ); | |
if turn_angle.abs()<0.019 | |
{ | |
fire(0); | |
} | |
if let Some(contact) = scan() { | |
debug!("π» {:?}",contact ); | |
set_radar_heading((contact.position-position()).angle()) | |
} | |
else { | |
debug!("π» {}","no contact" ); | |
set_radar_heading(radar_heading() - radar_width()/2.0); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Tutorial: Search | |
// Destroy the enemy ship. It is initially outside of your radar range. | |
// Hint: The set_radar_width() function can be used to create a tighter radar | |
// beam that's effective at longer distances. | |
use oort_api::prelude::*; | |
const BULLET_SPEED: f64 = 1000.0; // m/s | |
pub struct Ship {} | |
impl Ship { | |
pub fn new() -> Ship { | |
Ship {} | |
} | |
pub fn radian_to_vec2(angle_radians: f64) -> Vec2 | |
{ | |
Vec2::new(angle_radians.cos(), angle_radians.sin()) | |
} | |
pub fn calculate() -> Vec2 | |
{ | |
let relative_position = target() - position(); | |
let a = target_velocity().dot(target_velocity()) - (BULLET_SPEED * BULLET_SPEED); | |
let b = 2.0 * relative_position.dot(target_velocity()); | |
let c = relative_position.dot(relative_position); | |
debug!("π€ {} {} {}",a,b,c); | |
let discriminant = (b * b) - (4.0 * a * c); | |
let t1 = (-b + discriminant.sqrt()) / (2.0 * a); | |
let t2 = (-b - discriminant.sqrt()) / (2.0 * a); | |
let t = if t1 > 0.0 && t2 > 0.0 { | |
t1.min(t2) // Choose the earlier time. | |
} else if t1 > 0.0 { | |
t1 | |
} else if t2 > 0.0 { | |
t2 | |
} else { | |
// No positive time solution, target is behind us or we can't catch it. | |
-1.0 | |
}; | |
debug!("β {}",t); | |
let intercept_position = relative_position + target_velocity() * t; | |
return intercept_position | |
} | |
pub fn tick(&mut self) { | |
set_radar_width(0.2); | |
let intercept_position = Self::calculate(); | |
draw_line(target(), intercept_position, 0xaaFF00); | |
draw_line(position(), intercept_position, 0xFF00aa); | |
let x:Vec2 = Self::radian_to_vec2(heading()); | |
draw_line(position(), 1000.0*x, 0xFFbbaa); | |
let aim_angle = intercept_position.angle(); | |
let turn_angle = angle_diff(heading(), aim_angle ); | |
turn(turn_angle*99.0); | |
//turn(0.3); | |
debug!("π§ {}",turn_angle ); | |
if turn_angle.abs()<0.019 | |
{ | |
fire(0); | |
} | |
if let Some(contact) = scan() { | |
debug!("π» {:?}",contact ); | |
set_radar_heading((contact.position-position()).angle()) | |
} | |
else { | |
debug!("π» {}","no contact" ); | |
set_radar_heading(radar_heading() - radar_width()/2.0); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment