Added collisions
parent
ece82a8c1b
commit
2354971d8e
|
@ -99,6 +99,15 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
|
@ -273,7 +282,7 @@ version = "0.18.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"approx 0.4.0",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
|
@ -348,6 +357,30 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6eb9105919ca8e40d437fc9cbb8f1975d916f1bd28afe795a48aae32a2cc8920"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.4"
|
||||
|
@ -361,21 +394,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.16"
|
||||
version = "0.9.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa"
|
||||
checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"memoffset 0.9.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adc6598521bb5a83d491e8c1fe51db7296019d2ca3cb93cc6c2a20369a4d78a2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.17"
|
||||
version = "0.8.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f"
|
||||
checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
@ -538,9 +580,12 @@ dependencies = [
|
|||
"anyhow",
|
||||
"bytemuck",
|
||||
"cgmath",
|
||||
"crossbeam",
|
||||
"image",
|
||||
"nalgebra",
|
||||
"pollster",
|
||||
"rand",
|
||||
"rapier2d",
|
||||
"serde",
|
||||
"toml",
|
||||
"walkdir",
|
||||
|
@ -831,6 +876,12 @@ dependencies = [
|
|||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.2"
|
||||
|
@ -867,6 +918,16 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7574c1cf36da4798ab73da5b215bbf444f50718207754cb522201d78d1cd0ff2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
|
@ -891,15 +952,6 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.27.0"
|
||||
|
@ -957,6 +1009,33 @@ dependencies = [
|
|||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "307ed9b18cc2423f29e83f84fd23a8e73628727990181f18641a8b5dc2ab1caa"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"matrixmultiply",
|
||||
"nalgebra-macros",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra-macros"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91761aed67d03ad966ef783ae962ef9bbaca728d2dd7ceb7939ec110fffad998"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
|
@ -1004,7 +1083,7 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset 0.6.5",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1017,7 +1096,27 @@ dependencies = [
|
|||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset 0.6.5",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1048,6 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1193,6 +1293,27 @@ dependencies = [
|
|||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parry2d"
|
||||
version = "0.13.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "104ae65232e20477a98f9f1e75ca9850eae24a2ea846a2b1a0af03ad752136ce"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"arrayvec",
|
||||
"bitflags 1.3.2",
|
||||
"downcast-rs",
|
||||
"either",
|
||||
"nalgebra",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"rustc-hash",
|
||||
"simba",
|
||||
"slab",
|
||||
"smallvec",
|
||||
"spade",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
|
@ -1321,12 +1442,38 @@ version = "0.1.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab"
|
||||
|
||||
[[package]]
|
||||
name = "rapier2d"
|
||||
version = "0.17.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f94d294a9b96694c14888dd0e8ce77620dcc4f2f49264109ef835fa5e2285b84"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
"bitflags 1.3.2",
|
||||
"crossbeam",
|
||||
"downcast-rs",
|
||||
"nalgebra",
|
||||
"num-derive",
|
||||
"num-traits",
|
||||
"parry2d",
|
||||
"rustc-hash",
|
||||
"simba",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.8.0"
|
||||
|
@ -1371,6 +1518,12 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b"
|
||||
|
||||
[[package]]
|
||||
name = "robust"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
|
@ -1383,6 +1536,15 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f398075ce1e6a179b46f51bd88d0598b92b00d3551f1a2d4ac49e771b56ac354"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
|
@ -1446,12 +1608,34 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae"
|
||||
dependencies = [
|
||||
"approx 0.5.1",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slotmap"
|
||||
version = "1.0.7"
|
||||
|
@ -1486,6 +1670,18 @@ dependencies = [
|
|||
"wayland-protocols",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spade"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd774eb23cff002036706e6ea83c3f4ab4c80dad89da76fe16d49f77ab71682f"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"num-traits",
|
||||
"robust",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
|
@ -1655,6 +1851,12 @@ version = "0.20.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
|
@ -1958,6 +2160,16 @@ dependencies = [
|
|||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c68938b57b33da363195412cfc5fc37c9ed49aa9cfe2156fde64b8d2c9498242"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.0.2"
|
||||
|
|
|
@ -41,3 +41,6 @@ anyhow = "1.0"
|
|||
cgmath = "0.18.0"
|
||||
rand = "0.8.5"
|
||||
walkdir = "2.4.0"
|
||||
rapier2d = "0.17.2"
|
||||
nalgebra = "0.32.3"
|
||||
crossbeam = "0.8.3"
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
sprite = "ship::gypsum"
|
||||
size = 100
|
||||
|
||||
engines = [{ x = 0.0, y = -105, size = 50.0 }]
|
||||
guns = [{ x = 0.0, y = 100 }, { x = 10.0, y = 80 }, { x = -10.0, y = 80 }]
|
||||
engines = [{ x = 0.0, y = -1.05, size = 50.0 }]
|
||||
guns = [{ x = 0.0, y = 1 }, { x = 0.1, y = 0.80 }, { x = -0.1, y = 0.80 }]
|
||||
|
||||
|
|
|
@ -61,15 +61,20 @@ impl super::Build for Ship {
|
|||
|
||||
let mut out = Vec::new();
|
||||
for (ship_name, ship) in ship {
|
||||
let size = ship.size;
|
||||
|
||||
out.push(Self {
|
||||
name: ship_name.to_owned(),
|
||||
sprite: ship.sprite.to_owned(),
|
||||
size: ship.size,
|
||||
size,
|
||||
engines: ship
|
||||
.engines
|
||||
.iter()
|
||||
.map(|e| EnginePoint {
|
||||
pos: Point2 { x: e.x, y: e.y },
|
||||
pos: Point2 {
|
||||
x: e.x * size,
|
||||
y: e.y * size,
|
||||
},
|
||||
size: e.size,
|
||||
})
|
||||
.collect(),
|
||||
|
@ -77,7 +82,10 @@ impl super::Build for Ship {
|
|||
.guns
|
||||
.iter()
|
||||
.map(|e| GunPoint {
|
||||
pos: Point2 { x: e.x, y: e.y },
|
||||
pos: Point2 {
|
||||
x: e.x * size,
|
||||
y: e.y * size,
|
||||
},
|
||||
})
|
||||
.collect(),
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ use anyhow::{bail, Context, Result};
|
|||
use cgmath::{Deg, Point3};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use crate::physics::Polar;
|
||||
use crate::util::Polar;
|
||||
|
||||
pub(super) mod syntax {
|
||||
use super::HashMap;
|
||||
|
|
131
src/game/game.rs
131
src/game/game.rs
|
@ -1,27 +1,39 @@
|
|||
use cgmath::{Deg, Point2, Point3, Vector2};
|
||||
use std::time::Instant;
|
||||
use cgmath::Point3;
|
||||
use crossbeam::{self, channel::Receiver};
|
||||
use rapier2d::{
|
||||
dynamics::{RigidBodyBuilder, RigidBodyHandle},
|
||||
geometry::{ColliderBuilder, ColliderHandle, CollisionEvent},
|
||||
na::vector,
|
||||
pipeline::ChannelEventCollector,
|
||||
};
|
||||
use std::{collections::HashMap, time::Instant};
|
||||
use winit::event::{ElementState, MouseButton, MouseScrollDelta, TouchPhase, VirtualKeyCode};
|
||||
|
||||
use super::{ship, Camera, InputStatus, System};
|
||||
use super::{camera::Camera, physics::Physics, ship, system::System, util, InputStatus};
|
||||
use crate::{
|
||||
consts,
|
||||
content::Content,
|
||||
render::Spriteable,
|
||||
render::{Sprite, SpriteTexture},
|
||||
};
|
||||
|
||||
pub struct Projectile {
|
||||
pub position: Point2<f32>,
|
||||
pub velocity: Vector2<f32>,
|
||||
pub struct ProjectileBuilder {
|
||||
pub rigid_body: RigidBodyBuilder,
|
||||
pub collider: ColliderBuilder,
|
||||
pub sprite: SpriteTexture,
|
||||
pub lifetime: f32,
|
||||
pub size: f32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Projectile {
|
||||
pub rigid_body: RigidBodyHandle,
|
||||
pub sprite: SpriteTexture,
|
||||
pub angle: Deg<f32>,
|
||||
pub lifetime: f32,
|
||||
pub size: f32,
|
||||
}
|
||||
|
||||
impl Projectile {
|
||||
pub fn tick(&mut self, t: f32) {
|
||||
self.position += self.velocity * t;
|
||||
self.lifetime -= t;
|
||||
}
|
||||
|
||||
|
@ -38,16 +50,52 @@ pub struct Game {
|
|||
pub system: System,
|
||||
pub camera: Camera,
|
||||
paused: bool,
|
||||
pub projectiles: Vec<Projectile>,
|
||||
pub time_scale: f32,
|
||||
|
||||
pub projectiles: HashMap<ColliderHandle, Projectile>,
|
||||
|
||||
collision_handler: ChannelEventCollector,
|
||||
physics: Physics,
|
||||
|
||||
collision_recv: Receiver<CollisionEvent>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
pub fn new(ct: Content) -> Self {
|
||||
let r1 = RigidBodyBuilder::dynamic()
|
||||
.translation(vector![0.0, 0.0])
|
||||
.can_sleep(false)
|
||||
.build();
|
||||
let c1 = ColliderBuilder::ball(50.0)
|
||||
.restitution(0.7)
|
||||
.mass(1.0)
|
||||
.build();
|
||||
|
||||
let r2 = RigidBodyBuilder::dynamic()
|
||||
.translation(vector![200.0, 200.0])
|
||||
.build();
|
||||
let c2 = ColliderBuilder::ball(50.0)
|
||||
.restitution(0.7)
|
||||
.mass(100.0)
|
||||
.build();
|
||||
|
||||
let mut p = Physics::new();
|
||||
|
||||
let rh1 = p.rigid_body_set.insert(r1);
|
||||
p.collider_set
|
||||
.insert_with_parent(c1, rh1, &mut p.rigid_body_set);
|
||||
|
||||
let rh2 = p.rigid_body_set.insert(r2);
|
||||
p.collider_set
|
||||
.insert_with_parent(c2, rh2, &mut p.rigid_body_set);
|
||||
|
||||
let (collision_send, collision_recv) = crossbeam::channel::unbounded();
|
||||
let (contact_force_send, _) = crossbeam::channel::unbounded();
|
||||
|
||||
Game {
|
||||
last_update: Instant::now(),
|
||||
input: InputStatus::new(),
|
||||
projectiles: Vec::new(),
|
||||
projectiles: HashMap::new(),
|
||||
player: ship::Ship::new(
|
||||
&ct.ships[0],
|
||||
vec![
|
||||
|
@ -55,7 +103,7 @@ impl Game {
|
|||
ship::ShipOutfit::Gun(ship::ShipGun::new(ct.guns[0].clone(), 2)),
|
||||
ship::ShipOutfit::Engine(ct.engines[0].clone()),
|
||||
],
|
||||
(0.0, 0.0).into(),
|
||||
rh1,
|
||||
),
|
||||
camera: Camera {
|
||||
pos: (0.0, 0.0).into(),
|
||||
|
@ -65,7 +113,11 @@ impl Game {
|
|||
|
||||
paused: false,
|
||||
time_scale: 1.0,
|
||||
test: ship::Ship::new(&ct.ships[0], vec![], (100.0, 100.0).into()),
|
||||
test: ship::Ship::new(&ct.ships[0], vec![], rh2),
|
||||
|
||||
physics: p,
|
||||
collision_handler: ChannelEventCollector::new(collision_send, contact_force_send),
|
||||
collision_recv,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,16 +145,41 @@ impl Game {
|
|||
pub fn update(&mut self) {
|
||||
let t: f32 = self.last_update.elapsed().as_secs_f32() * self.time_scale;
|
||||
|
||||
self.projectiles.retain_mut(|p| {
|
||||
self.physics.step(t, &self.collision_handler);
|
||||
|
||||
self.projectiles.retain(|_, p| {
|
||||
p.tick(t);
|
||||
!p.is_expired()
|
||||
});
|
||||
|
||||
// Update player and handle result
|
||||
self.player.update_controls(&self.input);
|
||||
let mut p = self.player.tick(t);
|
||||
if p.projectiles.len() != 0 {
|
||||
self.projectiles.append(&mut p.projectiles);
|
||||
let p = self.player.tick(&mut self.physics.rigid_body_set, t);
|
||||
for p in p.projectiles {
|
||||
let r = self.physics.rigid_body_set.insert(p.rigid_body.build());
|
||||
let c = self.physics.collider_set.insert_with_parent(
|
||||
p.collider.build(),
|
||||
r,
|
||||
&mut self.physics.rigid_body_set,
|
||||
);
|
||||
self.projectiles.insert(
|
||||
c,
|
||||
Projectile {
|
||||
rigid_body: r,
|
||||
sprite: p.sprite,
|
||||
lifetime: p.lifetime,
|
||||
size: p.size,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
while let Ok(event) = self.collision_recv.try_recv() {
|
||||
if event.started() {
|
||||
self.projectiles.remove(&event.collider1());
|
||||
self.projectiles.remove(&event.collider2());
|
||||
// TODO: remove collider and rigid body,
|
||||
// cleanup, keep track of ships.
|
||||
}
|
||||
}
|
||||
|
||||
if self.input.v_scroll != 0.0 {
|
||||
|
@ -111,7 +188,10 @@ impl Game {
|
|||
self.input.v_scroll = 0.0;
|
||||
}
|
||||
|
||||
self.camera.pos = self.player.physicsbody.pos;
|
||||
// TODO: Camera physics
|
||||
let r = &mut self.physics.rigid_body_set[self.player.rigid_body];
|
||||
let ship_pos = util::rigidbody_position(r);
|
||||
self.camera.pos = ship_pos;
|
||||
|
||||
self.last_update = Instant::now();
|
||||
}
|
||||
|
@ -120,8 +200,8 @@ impl Game {
|
|||
let mut sprites: Vec<Sprite> = Vec::new();
|
||||
|
||||
sprites.append(&mut self.system.get_sprites());
|
||||
sprites.push(self.player.get_sprite());
|
||||
sprites.push(self.test.get_sprite());
|
||||
sprites.push(self.player.get_sprite(&self.physics.rigid_body_set));
|
||||
sprites.push(self.test.get_sprite(&self.physics.rigid_body_set));
|
||||
|
||||
// Make sure sprites are drawn in the correct order
|
||||
// (note the reversed a, b in the comparator)
|
||||
|
@ -131,16 +211,19 @@ impl Game {
|
|||
sprites.sort_by(|a, b| b.pos.z.total_cmp(&a.pos.z));
|
||||
|
||||
// Don't waste time sorting these, they should always be on top.
|
||||
for p in &self.projectiles {
|
||||
for (_, p) in &self.projectiles {
|
||||
let r = &self.physics.rigid_body_set[p.rigid_body];
|
||||
let pos = util::rigidbody_position(r);
|
||||
let ang = util::rigidbody_angle(r);
|
||||
sprites.push(Sprite {
|
||||
texture: p.sprite.clone(),
|
||||
pos: Point3 {
|
||||
x: p.position.x,
|
||||
y: p.position.y,
|
||||
x: pos.x,
|
||||
y: pos.y,
|
||||
z: 1.0,
|
||||
},
|
||||
size: p.size,
|
||||
angle: p.angle,
|
||||
angle: ang,
|
||||
children: None,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
mod camera;
|
||||
mod game;
|
||||
mod inputstatus;
|
||||
mod physics;
|
||||
mod ship;
|
||||
mod system;
|
||||
mod systemobject;
|
||||
mod util;
|
||||
|
||||
pub use camera::Camera;
|
||||
pub use game::Game;
|
||||
pub use inputstatus::InputStatus;
|
||||
pub use system::System;
|
||||
pub use systemobject::SystemObject;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
use rapier2d::{
|
||||
dynamics::{
|
||||
CCDSolver, ImpulseJointSet, IntegrationParameters, IslandManager, MultibodyJointSet,
|
||||
RigidBodySet,
|
||||
},
|
||||
geometry::{BroadPhase, ColliderSet, NarrowPhase},
|
||||
na::vector,
|
||||
pipeline::{EventHandler, PhysicsPipeline},
|
||||
};
|
||||
|
||||
pub struct Physics {
|
||||
pub rigid_body_set: RigidBodySet,
|
||||
pub collider_set: ColliderSet,
|
||||
|
||||
ip: IntegrationParameters,
|
||||
pp: PhysicsPipeline,
|
||||
im: IslandManager,
|
||||
bp: BroadPhase,
|
||||
np: NarrowPhase,
|
||||
ijs: ImpulseJointSet,
|
||||
mjs: MultibodyJointSet,
|
||||
ccd: CCDSolver,
|
||||
}
|
||||
|
||||
impl Physics {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
rigid_body_set: RigidBodySet::new(),
|
||||
collider_set: ColliderSet::new(),
|
||||
|
||||
ip: IntegrationParameters::default(),
|
||||
pp: PhysicsPipeline::new(),
|
||||
im: IslandManager::new(),
|
||||
bp: BroadPhase::new(),
|
||||
np: NarrowPhase::new(),
|
||||
ijs: ImpulseJointSet::new(),
|
||||
mjs: MultibodyJointSet::new(),
|
||||
ccd: CCDSolver::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn step(&mut self, t: f32, handler: &dyn EventHandler) {
|
||||
self.ip.dt = t;
|
||||
self.pp.step(
|
||||
&vector![0.0, 0.0],
|
||||
&self.ip,
|
||||
&mut self.im,
|
||||
&mut self.bp,
|
||||
&mut self.np,
|
||||
&mut self.rigid_body_set,
|
||||
&mut self.collider_set,
|
||||
&mut self.ijs,
|
||||
&mut self.mjs,
|
||||
&mut self.ccd,
|
||||
None,
|
||||
&(),
|
||||
handler,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ mod ship;
|
|||
pub use outfits::{ShipGun, ShipOutfit, ShipOutfits};
|
||||
pub use ship::Ship;
|
||||
|
||||
use super::{game::Projectile, InputStatus};
|
||||
use super::{game::ProjectileBuilder, InputStatus};
|
||||
|
||||
pub struct ShipControls {
|
||||
pub left: bool,
|
||||
|
@ -25,5 +25,5 @@ impl ShipControls {
|
|||
}
|
||||
|
||||
pub struct ShipTickResult {
|
||||
pub projectiles: Vec<Projectile>,
|
||||
pub projectiles: Vec<ProjectileBuilder>,
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
use cgmath::{Deg, EuclideanSpace, Matrix2, Point2, Vector2};
|
||||
use cgmath::{Deg, EuclideanSpace, Matrix2, Rad, Vector2};
|
||||
use nalgebra::vector;
|
||||
use rand::Rng;
|
||||
use rapier2d::dynamics::{RigidBodyBuilder, RigidBodyHandle, RigidBodySet};
|
||||
use rapier2d::geometry::ColliderBuilder;
|
||||
use rapier2d::pipeline::ActiveEvents;
|
||||
|
||||
use super::super::game::Projectile;
|
||||
use super::ShipOutfit;
|
||||
use super::{outfits::ShipOutfits, InputStatus, ShipControls, ShipTickResult};
|
||||
use super::super::util;
|
||||
use super::{outfits::ShipOutfits, InputStatus, ShipControls, ShipOutfit, ShipTickResult};
|
||||
use crate::game::game::ProjectileBuilder;
|
||||
use crate::{
|
||||
content,
|
||||
physics::PhysicsBody,
|
||||
render::{Sprite, SpriteTexture, Spriteable},
|
||||
render::{Sprite, SpriteTexture},
|
||||
};
|
||||
|
||||
pub struct Ship {
|
||||
pub physicsbody: PhysicsBody,
|
||||
pub rigid_body: RigidBodyHandle,
|
||||
pub controls: ShipControls,
|
||||
outfits: ShipOutfits,
|
||||
|
||||
|
@ -20,14 +23,14 @@ pub struct Ship {
|
|||
}
|
||||
|
||||
impl Ship {
|
||||
pub fn new(ct: &content::Ship, outfits: Vec<ShipOutfit>, pos: Point2<f32>) -> Self {
|
||||
pub fn new(ct: &content::Ship, outfits: Vec<ShipOutfit>, rigid_body: RigidBodyHandle) -> Self {
|
||||
let mut o = ShipOutfits::new(ct.engines.clone(), ct.guns.clone());
|
||||
for x in outfits.into_iter() {
|
||||
o.add(x)
|
||||
}
|
||||
|
||||
Ship {
|
||||
physicsbody: PhysicsBody::new(pos),
|
||||
rigid_body,
|
||||
controls: ShipControls::new(),
|
||||
|
||||
outfits: o,
|
||||
|
@ -43,9 +46,9 @@ impl Ship {
|
|||
self.controls.guns = input.key_guns;
|
||||
}
|
||||
|
||||
pub fn fire_guns(&mut self) -> Vec<Projectile> {
|
||||
pub fn fire_guns(&mut self, rigid_body_set: &RigidBodySet) -> Vec<ProjectileBuilder> {
|
||||
let r = &rigid_body_set[self.rigid_body];
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let mut out = Vec::new();
|
||||
|
||||
for (g, p) in self.outfits.iter_guns_points() {
|
||||
|
@ -55,23 +58,34 @@ impl Ship {
|
|||
|
||||
g.cooldown = g.kind.rate + rng.gen_range(-g.kind.rate_rng..=g.kind.rate_rng);
|
||||
|
||||
let pos = self.physicsbody.pos
|
||||
+ (Matrix2::from_angle(self.physicsbody.angle) * p.pos.to_vec());
|
||||
let ship_pos = util::rigidbody_position(r);
|
||||
let ship_ang: Deg<f32> = util::rigidbody_angle(r);
|
||||
let ship_ang_rad: Rad<f32> = ship_ang.into();
|
||||
let ship_vel = util::rigidbody_velocity(r);
|
||||
|
||||
let vel = self.physicsbody.vel
|
||||
let pos = ship_pos + (Matrix2::from_angle(ship_ang) * p.pos.to_vec());
|
||||
|
||||
let vel = ship_vel
|
||||
+ (Matrix2::from_angle(
|
||||
self.physicsbody.angle
|
||||
+ Deg(rng.gen_range(-(g.kind.spread.0 / 2.0)..=g.kind.spread.0 / 2.0)),
|
||||
ship_ang + Deg(rng.gen_range(-(g.kind.spread.0 / 2.0)..=g.kind.spread.0 / 2.0)),
|
||||
) * Vector2 {
|
||||
x: 0.0,
|
||||
y: g.kind.projectile.speed
|
||||
+ rng.gen_range(-g.kind.projectile.speed_rng..=g.kind.projectile.speed_rng),
|
||||
});
|
||||
|
||||
out.push(Projectile {
|
||||
position: pos,
|
||||
velocity: vel,
|
||||
angle: self.physicsbody.angle,
|
||||
let p_r = RigidBodyBuilder::kinematic_velocity_based()
|
||||
.translation(vector![pos.x, pos.y])
|
||||
.rotation(-ship_ang_rad.0)
|
||||
.linvel(vector![vel.x, vel.y]);
|
||||
|
||||
let p_c = ColliderBuilder::ball(5.0)
|
||||
.sensor(true)
|
||||
.active_events(ActiveEvents::COLLISION_EVENTS);
|
||||
|
||||
out.push(ProjectileBuilder {
|
||||
rigid_body: p_r,
|
||||
collider: p_c,
|
||||
sprite: SpriteTexture(g.kind.projectile.sprite.clone()),
|
||||
lifetime: g.kind.projectile.lifetime
|
||||
+ rng.gen_range(
|
||||
|
@ -84,42 +98,47 @@ impl Ship {
|
|||
return out;
|
||||
}
|
||||
|
||||
pub fn tick(&mut self, t: f32) -> ShipTickResult {
|
||||
pub fn tick(&mut self, rigid_body_set: &mut RigidBodySet, t: f32) -> ShipTickResult {
|
||||
let r = &mut rigid_body_set[self.rigid_body];
|
||||
let ship_ang = util::rigidbody_angle(r);
|
||||
|
||||
let engine_force = Matrix2::from_angle(ship_ang) * Vector2 { x: 0.0, y: 1.0 } * t;
|
||||
if self.controls.thrust {
|
||||
for e in self.outfits.iter_engines() {
|
||||
self.physicsbody.thrust(e.thrust * t);
|
||||
r.apply_impulse(vector![engine_force.x, engine_force.y] * e.thrust, true);
|
||||
}
|
||||
}
|
||||
|
||||
if self.controls.right {
|
||||
self.physicsbody.rot(Deg(35.0) * t);
|
||||
r.apply_torque_impulse(500.0 * t, true);
|
||||
}
|
||||
|
||||
if self.controls.left {
|
||||
self.physicsbody.rot(Deg(-35.0) * t);
|
||||
r.apply_torque_impulse(-500.0 * t, true);
|
||||
}
|
||||
|
||||
let p = if self.controls.guns {
|
||||
self.fire_guns()
|
||||
self.fire_guns(rigid_body_set)
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
self.physicsbody.tick(t);
|
||||
for i in self.outfits.iter_guns() {
|
||||
i.cooldown -= t;
|
||||
}
|
||||
|
||||
return ShipTickResult { projectiles: p };
|
||||
}
|
||||
}
|
||||
|
||||
impl Spriteable for Ship {
|
||||
fn get_sprite(&self) -> Sprite {
|
||||
pub fn get_sprite(&self, rigid_body_set: &RigidBodySet) -> Sprite {
|
||||
let r = &rigid_body_set[self.rigid_body];
|
||||
let ship_pos = util::rigidbody_position(r);
|
||||
let ship_ang = util::rigidbody_angle(r);
|
||||
|
||||
Sprite {
|
||||
pos: (self.physicsbody.pos.x, self.physicsbody.pos.y, 1.0).into(),
|
||||
pos: (ship_pos.x, ship_pos.y, 1.0).into(),
|
||||
texture: self.sprite.clone(), // TODO: sprite texture should be easy to clone
|
||||
angle: self.physicsbody.angle,
|
||||
angle: ship_ang,
|
||||
size: self.size,
|
||||
|
||||
children: if self.controls.thrust {
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
use cgmath::{Deg, InnerSpace, Point2, Vector2};
|
||||
use nalgebra;
|
||||
use rapier2d::dynamics::RigidBody;
|
||||
|
||||
pub fn rigidbody_position(r: &RigidBody) -> cgmath::Point2<f32> {
|
||||
Point2 {
|
||||
x: r.translation()[0],
|
||||
y: r.translation()[1],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rigidbody_angle(r: &RigidBody) -> Deg<f32> {
|
||||
Vector2 {
|
||||
x: r.rotation().re,
|
||||
y: r.rotation().im,
|
||||
}
|
||||
.angle(Vector2 { x: 1.0, y: 0.0 })
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn rigidbody_velocity(r: &RigidBody) -> cgmath::Vector2<f32> {
|
||||
let v = r.velocity_at_point(&nalgebra::Point2::new(
|
||||
r.translation()[0],
|
||||
r.translation()[1],
|
||||
));
|
||||
Vector2 { x: v.x, y: v.y }
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
mod consts;
|
||||
mod content;
|
||||
mod game;
|
||||
mod physics;
|
||||
mod render;
|
||||
mod util;
|
||||
|
||||
use anyhow::Result;
|
||||
use winit::{
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
use cgmath::{Angle, Deg, Point2, Vector2};
|
||||
|
||||
pub struct PhysicsBody {
|
||||
pub pos: Point2<f32>,
|
||||
pub vel: Vector2<f32>,
|
||||
pub mass: f32,
|
||||
pub angle: Deg<f32>,
|
||||
}
|
||||
|
||||
impl PhysicsBody {
|
||||
pub fn new(pos: Point2<f32>) -> Self {
|
||||
return PhysicsBody {
|
||||
pos,
|
||||
vel: (0.0, 0.0).into(),
|
||||
mass: 0.3,
|
||||
angle: Deg(0.0),
|
||||
};
|
||||
}
|
||||
|
||||
/// Calculate the position of this body after t seconds.
|
||||
pub fn tick(&mut self, t: f32) {
|
||||
self.pos += self.vel * t;
|
||||
}
|
||||
|
||||
/// Apply an instantaneous force to this object
|
||||
pub fn force(&mut self, v: Vector2<f32>) {
|
||||
self.vel += v / self.mass;
|
||||
}
|
||||
|
||||
/// Apply a force in the direction this object is pointing.
|
||||
pub fn thrust(&mut self, f: f32) {
|
||||
let l = Vector2 {
|
||||
x: -self.angle.sin(),
|
||||
y: self.angle.cos(),
|
||||
} * f;
|
||||
self.force(l);
|
||||
}
|
||||
|
||||
// Rotate this object
|
||||
pub fn rot(&mut self, a: Deg<f32>) {
|
||||
self.angle -= a;
|
||||
|
||||
// Wrap angles
|
||||
if self.angle.0.abs() > 180.0 {
|
||||
self.angle -= Deg(self.angle.0.signum() * 360.0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
mod body;
|
||||
mod polar;
|
||||
|
||||
// What kind of float shoud we use for physics?
|
||||
pub use body::PhysicsBody;
|
||||
pub use polar::Polar;
|
|
@ -7,7 +7,7 @@ mod texturearray;
|
|||
mod vertexbuffer;
|
||||
|
||||
pub use gpustate::GPUState;
|
||||
pub use sprite::{Sprite, Spriteable, SubSprite};
|
||||
pub use sprite::{Sprite, SubSprite};
|
||||
|
||||
/// A handle to a sprite texture
|
||||
/// TODO: This should be easy to copy,
|
||||
|
|
|
@ -41,7 +41,3 @@ pub struct SubSprite {
|
|||
/// subsprite's parent sprite.
|
||||
pub angle: Deg<f32>,
|
||||
}
|
||||
|
||||
pub trait Spriteable {
|
||||
fn get_sprite(&self) -> Sprite;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue