我有两种类型的结构:
Ship
具有2D位置和速度Target
站着我有一个包含所有Ship
s的向量,另一个包含所有Target
s的向量。我想知道Ship
与另一个Ship
或Target
发生碰撞,所以我会检查所有船只并检查是否有碰撞。
我知道这是一堆代码,但我确实想提供一个完整的例子。
use std::any::Any;
trait AsAny {
fn as_any(&self) -> &Any;
}
impl<T: Any> AsAny for T {
fn as_any(&self) -> &Any {
self
}
}
trait AsPoint {
fn as_point(&self) -> &Point;
}
impl<T: Point> AsPoint for T {
fn as_point(&self) -> &Point {
self
}
}
trait Point: AsPoint {
fn x(&self) -> i32;
fn y(&self) -> i32;
fn distance(&self, rhs: &Point) -> i32 {
(( ((self.x() - rhs.x()) as f64).powi(2) +
((self.y() - rhs.y()) as f64).powi(2)
)as f64).sqrt().round() as i32
}
}
struct Ship {
x: i32,
y: i32,
radius: i32,
vx: i32,
vy: i32,
}
struct Target {
x: i32,
y: i32,
radius: i32,
}
struct Collision<'a> {
pub a: &'a mut (Element + 'a),
pub b: &'a mut (Element + 'a),
}
trait Element: Point + AsAny {
fn radius(&self) -> i32;
fn apply_collision(&mut self, rhs: &mut Element);
}
impl Point for Target {
fn x(&self) -> i32 {
self.x
}
fn y(&self) -> i32 {
self.y
}
}
impl Point for Ship {
fn x(&self) -> i32 {
self.x
}
fn y(&self) -> i32 {
self.y
}
}
impl Element for Ship {
fn apply_collision(&mut self, rhs: &mut Element) {
if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
self.collision_with_target(as_target);
} else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
self.collision_with_ship(as_ship);
}
}
fn radius(&self) -> i32 {
self.radius
}
}
impl Element for Target {
fn radius(&self) -> i32 {
self.radius
}
fn apply_collision(&mut self, rhs: &mut Element) {
match rhs.as_any().downcast_ref::<Ship>() {
Some(ref mut as_ship ) => {
as_ship.vx = -as_ship.vx;
as_ship.vy = -as_ship.vy;
},
None => panic!(), // should never happen
}
}
}
impl Ship {
fn collision_with_target(&mut self, target: &Target) {
self.vx = -self.vx;
self.vy = -self.vy;
}
fn collision_with_ship(&mut self, ship: &mut Ship) {
let vx = self.vx;
let vy = self.vy;
self.vx = ship.vx;
self.vy = ship.vy;
ship.vx = vx;
ship.vy = vy;
}
}
fn collide<'a>(u1: &'a mut Element, u2: &'a mut Element) -> Option<Collision<'a>> {
if u1.as_point().distance(u2.as_point()) < u1.radius() + u2.radius() {
Some(Collision { a: u1, b: u2 })
} else {None}
}
fn handle_collisions(ships : &mut Vec<Ship>, targets: &mut Vec<Target>) {
for ship in ships.iter_mut() {
for other_ship in &mut ships[1..] {
let collision = collide(ship, other_ship);
if let Some(col) = collision {
col.a.apply_collision(col.b);
}
}
for target in targets.iter_mut() {
let collision = collide(ship,target);
if let Some(col) = collision {
col.a.apply_collision(col.b);
}
}
}
}
fn main() {
let ships: Vec<Ship> = vec![Ship {
x: 10,
y: 10,
radius: 20,
vx: 5,
vy: 5,
}, Ship {
x: 20,
y: 20,
radius: 10,
vx: 100,
vy: 100,
}];
let targets = vec![ Target{
x: 15,
y: 15,
radius: 10,
}];
handle_collisions(&mut ships, &mut targets);
}
Here是代码的操场链接。
编译器输出:
Compiling playground v0.0.1 (file:///playground)
error[E0477]: the type `&mut Element` does not fulfill the required lifetime
--> src/main.rs:84:51
|
84 | } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^
|
= note: type must satisfy the static lifetime
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:82:46
|
82 | if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 80:5...
--> src/main.rs:80:5
|
80 | / fn apply_collision(&mut self, rhs: &mut Element) {
81 | |
82 | | if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
83 | | self.collision_with_target(as_target);
... |
86 | | }
87 | | }
| |_____^
note: ...so that the reference type `&mut Element` does not outlive the data it points at
--> src/main.rs:82:42
|
82 | if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
| ^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&mut Element` will meet its required lifetime bounds
--> src/main.rs:82:46
|
82 | if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
| ^^^^^^
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:84:51
|
84 | } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 80:5...
--> src/main.rs:80:5
|
80 | / fn apply_collision(&mut self, rhs: &mut Element) {
81 | |
82 | | if let Some(ref mut as_target) = rhs.as_any().downcast_ref::<Target>() {
83 | | self.collision_with_target(as_target);
... |
86 | | }
87 | | }
| |_____^
note: ...so that the reference type `&mut Element` does not outlive the data it points at
--> src/main.rs:84:47
|
84 | } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&mut Element` will meet its required lifetime bounds
--> src/main.rs:84:51
|
84 | } else if let Some(ref mut as_ship) = rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^
error[E0477]: the type `&mut Element` does not fulfill the required lifetime
--> src/main.rs:99:20
|
99 | match rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^
|
= note: type must satisfy the static lifetime
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> src/main.rs:99:20
|
99 | match rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the method body at 98:5...
--> src/main.rs:98:5
|
98 | / fn apply_collision(&mut self, rhs: &mut Element) {
99 | | match rhs.as_any().downcast_ref::<Ship>() {
100| | Some(ref mut as_ship ) => {
101| | as_ship.vx = -as_ship.vx;
... |
105| | }
106| | }
| |_____^
note: ...so that the reference type `&mut Element` does not outlive the data it points at
--> src/main.rs:99:16
|
99 | match rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^^^^^^^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&mut Element` will meet its required lifetime bounds
--> src/main.rs:99:20
|
99 | match rhs.as_any().downcast_ref::<Ship>() {
| ^^^^^^