initial commit
This commit is contained in:
commit
72c0a3d7bf
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
3984
Cargo.lock
generated
Normal file
3984
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
31
Cargo.toml
Normal file
31
Cargo.toml
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
[package]
|
||||||
|
edition = "2018"
|
||||||
|
name = "lyrix"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0.4"
|
||||||
|
bevy_console = "0.2.3"
|
||||||
|
bevy_egui = "0.8.0"
|
||||||
|
bevy_physimple = "0.2.0"
|
||||||
|
egui = "0.13.1"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
ron = "0.6.2"
|
||||||
|
spin = "0.9.2"
|
||||||
|
|
||||||
|
[dependencies.bevy_rapier2d]
|
||||||
|
features = ["simd-stable", "render"]
|
||||||
|
version = "0.11.0"
|
||||||
|
|
||||||
|
[dependencies.serde]
|
||||||
|
features = ["derive"]
|
||||||
|
version = "1"
|
||||||
|
|
||||||
|
[dependencies.bevy]
|
||||||
|
features = ["bevy_gltf", "bevy_winit", "render", "bevy_wgpu"]
|
||||||
|
version = "0.5.0"
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies.rhai]
|
||||||
|
features = ["sync", "only_i32", "no_optimize"]
|
||||||
|
version = "1.2.0"
|
BIN
assets/branding/icon.png
Normal file
BIN
assets/branding/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
202
assets/fonts/Roboto/LICENSE.txt
Normal file
202
assets/fonts/Roboto/LICENSE.txt
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
BIN
assets/fonts/Roboto/Roboto-Black.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Black.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-BlackItalic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-BlackItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Bold.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Bold.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-BoldItalic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Italic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Italic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Light.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Light.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-LightItalic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-LightItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Medium.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Medium.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-MediumItalic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-MediumItalic.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Regular.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Regular.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-Thin.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-Thin.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/Roboto/Roboto-ThinItalic.ttf
Normal file
BIN
assets/fonts/Roboto/Roboto-ThinItalic.ttf
Normal file
Binary file not shown.
5
assets/mods/NewSwordMod.lad
Normal file
5
assets/mods/NewSwordMod.lad
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
register_mod("NewSwordMod", "A simple mod to add a new sword");
|
||||||
|
register_weapon("sword", 0, 0);
|
||||||
|
register_object("hi");
|
||||||
|
print("hello there");
|
||||||
|
instance("sword", 1, 2);
|
4
assets/mods/asset.list
Normal file
4
assets/mods/asset.list
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
ModList (
|
||||||
|
value: 42,
|
||||||
|
vec: [Mod(name: "NewSwordMod", enabled: true)],
|
||||||
|
)
|
1
assets/mods/modlist.txt
Normal file
1
assets/mods/modlist.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
NewSwordMod
|
279
src/character_controller.rs
Normal file
279
src/character_controller.rs
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
use bevy::{prelude::*, render::camera::Camera};
|
||||||
|
use bevy_physimple::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Player {
|
||||||
|
double_jump: bool,
|
||||||
|
on_wall: Option<Vec2>,
|
||||||
|
on_floor: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Gravity(Vec2);
|
||||||
|
|
||||||
|
pub struct ModManager;
|
||||||
|
impl Plugin for ModManager {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
app // Basic setup of the app
|
||||||
|
.add_plugin(Physics2dPlugin)
|
||||||
|
// .add_system(bevy::input::system::exit_on_esc_system.system())
|
||||||
|
.add_startup_system(setup.system())
|
||||||
|
.add_system(controller_on_stuff.system())
|
||||||
|
.add_system(character_system.system())
|
||||||
|
.add_system(change_sensor_color.system())
|
||||||
|
.add_system(gravity.system())
|
||||||
|
.add_system(ray_head.system());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PlayerCam;
|
||||||
|
|
||||||
|
fn setup(mut coms: Commands, mut mats: ResMut<Assets<ColorMaterial>>, a_server: Res<AssetServer>) {
|
||||||
|
let wall = mats.add(Color::BLACK.into());
|
||||||
|
|
||||||
|
// insert a gravity struct
|
||||||
|
coms.insert_resource(Gravity(Vec2::new(0.0, -540.0)));
|
||||||
|
|
||||||
|
// Spawn character
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::splat(28.0)),
|
||||||
|
material: mats.add(Color::ALICE_BLUE.into()),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(KinematicBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::splat(28.0))),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert(Player::default());
|
||||||
|
|
||||||
|
// Spawn the damn camera
|
||||||
|
// coms.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
|
/*coms.spawn_bundle(OrthographicCameraBundle::new_2d())
|
||||||
|
.insert(PlayerCam);*/
|
||||||
|
|
||||||
|
// Controls
|
||||||
|
let style = TextStyle {
|
||||||
|
font: a_server.load("fonts/Roboto/Roboto-Black.ttf"),
|
||||||
|
font_size: 32.0,
|
||||||
|
color: Color::ANTIQUE_WHITE,
|
||||||
|
};
|
||||||
|
let alignment = TextAlignment {
|
||||||
|
vertical: VerticalAlign::Bottom,
|
||||||
|
horizontal: HorizontalAlign::Left,
|
||||||
|
};
|
||||||
|
let text = "A/D - Movement\nSpace/W - Jump/Double jump\nS - Stomp(when mid air)";
|
||||||
|
coms.spawn_bundle(Text2dBundle {
|
||||||
|
text: Text::with_section(text, style, alignment),
|
||||||
|
transform: Transform::from_xyz(-270.0, 360.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
coms.spawn_bundle(OrthographicCameraBundle::new_2d());
|
||||||
|
// center floor
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::new(2000.0, 230.0)),
|
||||||
|
material: wall.clone(),
|
||||||
|
transform: Transform::from_xyz(0.0, -400.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(StaticBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::new(2000.0, 230.0))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// side wall
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::new(40.0, 300.0)),
|
||||||
|
material: wall.clone(),
|
||||||
|
transform: {
|
||||||
|
let mut t = Transform::from_xyz(450.0, 0.0, 0.0);
|
||||||
|
t.rotation = Quat::from_rotation_z(-0.1 * 3.14);
|
||||||
|
t
|
||||||
|
},
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(StaticBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::new(40.0, 300.0))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// smaller other side wall
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::new(30.0, 90.0)),
|
||||||
|
material: wall.clone(),
|
||||||
|
transform: Transform::from_xyz(-150.0, -160.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(StaticBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::new(30.0, 90.0))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Floating platform
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::new(200.0, 30.0)),
|
||||||
|
material: wall.clone(),
|
||||||
|
transform: Transform::from_xyz(-150.0, 0.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(StaticBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::new(200.0, 30.0))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn the sensor
|
||||||
|
const SENSOR_SIZE: f32 = 50.0;
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::splat(SENSOR_SIZE)),
|
||||||
|
material: mats.add(Color::GOLD.into()),
|
||||||
|
transform: Transform::from_xyz(30.0, -150.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(SensorBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::splat(SENSOR_SIZE))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Spawn another cube which we will try to push or something
|
||||||
|
const CUBE_SIZE: f32 = 35.0;
|
||||||
|
coms.spawn_bundle(SpriteBundle {
|
||||||
|
sprite: Sprite::new(Vec2::splat(CUBE_SIZE)),
|
||||||
|
material: mats.add(Color::CRIMSON.into()),
|
||||||
|
transform: Transform::from_xyz(100.0, 0.0, 0.0),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.insert_bundle(KinematicBundle {
|
||||||
|
shape: CollisionShape::Square(Square::size(Vec2::splat(CUBE_SIZE))),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gravity(time: Res<Time>, grav: Res<Gravity>, mut q: Query<&mut Vel>) {
|
||||||
|
// Since the lib itself doesnt take care of gravity(for obv reasons) we need to do it here
|
||||||
|
let g = grav.0;
|
||||||
|
let t = time.delta_seconds();
|
||||||
|
|
||||||
|
for mut v in q.iter_mut() {
|
||||||
|
v.0 += t * g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn controller_on_stuff(
|
||||||
|
mut query: Query<(Entity, &mut Player)>,
|
||||||
|
mut colls: EventReader<CollisionEvent>,
|
||||||
|
) {
|
||||||
|
// Iterate over the collisions and check if the player is on a wall/floor
|
||||||
|
let (e, mut c) = query
|
||||||
|
.single_mut()
|
||||||
|
.expect("should be only one player :shrug:");
|
||||||
|
|
||||||
|
// clear the current data on c
|
||||||
|
c.on_floor = false;
|
||||||
|
c.on_wall = None;
|
||||||
|
|
||||||
|
for coll in colls.iter().filter(|&c| c.is_b_static) {
|
||||||
|
if coll.entity_a == e {
|
||||||
|
let n = coll.normal.dot(Vec2::Y);
|
||||||
|
|
||||||
|
if n > 0.7 {
|
||||||
|
c.on_floor = true;
|
||||||
|
} else if n.abs() <= 0.7 {
|
||||||
|
c.on_wall = Some(coll.normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn character_system(
|
||||||
|
input: Res<Input<KeyCode>>,
|
||||||
|
time: Res<Time>,
|
||||||
|
gravity: Res<Gravity>,
|
||||||
|
mut query: Query<(&mut Player, &mut Vel)>,
|
||||||
|
) {
|
||||||
|
let gravity = gravity.0;
|
||||||
|
|
||||||
|
for (mut controller, mut vel) in query.iter_mut() {
|
||||||
|
if let Some(normal) = controller.on_wall {
|
||||||
|
// If we are colliding with a wall, make sure to stick
|
||||||
|
vel.0 -= normal * 0.1;
|
||||||
|
// and limit our speed downwards
|
||||||
|
if vel.0.y < -1.0 {
|
||||||
|
vel.0.y = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There are 2 places in which we apply a jump, so i made a little colsure for code reusability
|
||||||
|
let jump = |body: &Player, vel: &mut Vel| {
|
||||||
|
vel.0 = vel.0.slide(gravity.normalize()) - gravity * 0.6;
|
||||||
|
let wall = body.on_wall.unwrap_or(Vec2::ZERO) * 250.0;
|
||||||
|
vel.0 += wall;
|
||||||
|
};
|
||||||
|
|
||||||
|
let should_jump = input.just_pressed(KeyCode::Space) || input.just_pressed(KeyCode::W);
|
||||||
|
if controller.on_floor || controller.on_wall.is_some() {
|
||||||
|
controller.double_jump = true;
|
||||||
|
if should_jump {
|
||||||
|
jump(&controller, &mut vel);
|
||||||
|
}
|
||||||
|
} else if controller.double_jump && should_jump {
|
||||||
|
controller.double_jump = false;
|
||||||
|
jump(&controller, &mut vel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is for the testing purpose of the continuous collision - aka "The Stomp"
|
||||||
|
if input.just_pressed(KeyCode::S) && !controller.on_floor {
|
||||||
|
vel.0 = Vec2::new(0.0, -500.0);
|
||||||
|
}
|
||||||
|
// REMINDER: Dont forget to multiply by `time.delta_seconds()` when messing with movement
|
||||||
|
let acc = Vec2::new(1000.0, 0.0) * time.delta_seconds();
|
||||||
|
if input.pressed(KeyCode::A) {
|
||||||
|
vel.0 -= acc;
|
||||||
|
} else if input.pressed(KeyCode::D) {
|
||||||
|
vel.0 += acc;
|
||||||
|
} else {
|
||||||
|
// This is not a good way to do friction
|
||||||
|
vel.0.x *= 1.0 - (10.0 * time.delta_seconds());
|
||||||
|
}
|
||||||
|
// terminal velocity
|
||||||
|
const TERMINAL_X: f32 = 500.0;
|
||||||
|
if vel.0.x.abs() > TERMINAL_X {
|
||||||
|
vel.0.x = TERMINAL_X.copysign(vel.0.x); // you can also do `TERMINAL_X * vel.0.x.signum()`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_sensor_color(
|
||||||
|
mut materials: ResMut<Assets<ColorMaterial>>,
|
||||||
|
q: Query<(&Sensor, &Handle<ColorMaterial>)>,
|
||||||
|
) {
|
||||||
|
// Simply change the color of the sensor if something is inside it
|
||||||
|
for (s, h) in q.iter() {
|
||||||
|
if let Some(mut m) = materials.get_mut(h) {
|
||||||
|
m.color = if s.bodies.len() == 0 {
|
||||||
|
Color::GOLD
|
||||||
|
} else {
|
||||||
|
Color::ALICE_BLUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ray_head(
|
||||||
|
mut ts: Query<&mut Transform, Without<RayCast>>,
|
||||||
|
q: Query<(&RayCast, &Children, &Transform)>,
|
||||||
|
) {
|
||||||
|
for (r, c, rt) in q.iter() {
|
||||||
|
if let Some(c) = c.first() {
|
||||||
|
if let Ok(mut t) = ts.get_mut(*c) {
|
||||||
|
// We use the offset in the `unwrap_or` because we want to offset the position to be where the ray "ends"
|
||||||
|
// while in the `map`(and `pos` by extension) we want the position relative to the transform component
|
||||||
|
// since `a.collision_point` is in global space
|
||||||
|
|
||||||
|
let pos = Vec2::new(rt.translation.x, rt.translation.y);
|
||||||
|
t.translation = r
|
||||||
|
.collision
|
||||||
|
.map(|a| a.collision_point - pos)
|
||||||
|
.unwrap_or(r.cast + r.offset)
|
||||||
|
.extend(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
src/console.rs
Normal file
72
src/console.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// use crate::dice;
|
||||||
|
// use crate::VERSION;
|
||||||
|
use bevy::{
|
||||||
|
app::{AppBuilder, EventReader, EventWriter, Plugin},
|
||||||
|
prelude::IntoSystem,
|
||||||
|
};
|
||||||
|
use bevy_console::{
|
||||||
|
ConsoleCommandEntered, ConsoleConfiguration, ConsolePlugin, HelpCommand, PrintConsoleLine,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct ConsoleManager;
|
||||||
|
impl Plugin for ConsoleManager {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
// add things to your app here
|
||||||
|
|
||||||
|
app.add_plugin(ConsolePlugin)
|
||||||
|
.insert_resource(ConsoleConfiguration {
|
||||||
|
help: vec![
|
||||||
|
HelpCommand::new(
|
||||||
|
"dice".to_string(),
|
||||||
|
"Usage: dice <number of dice>d<dice sides>".to_string(),
|
||||||
|
),
|
||||||
|
HelpCommand::new(
|
||||||
|
"version".to_string(),
|
||||||
|
"prints the client version".to_string(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.add_system(listen_to_console_events.system());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn listen_to_console_events(
|
||||||
|
mut console_events: EventReader<ConsoleCommandEntered>,
|
||||||
|
mut console_line: EventWriter<PrintConsoleLine>,
|
||||||
|
) {
|
||||||
|
for event in console_events.iter() {
|
||||||
|
let command: &str = &event.command;
|
||||||
|
|
||||||
|
// only useful for debuging
|
||||||
|
// println!("{:?}", event);
|
||||||
|
match command {
|
||||||
|
"hi" => {
|
||||||
|
console_line.send(PrintConsoleLine::new("Hello".to_string()));
|
||||||
|
}
|
||||||
|
"dice" => {
|
||||||
|
// console_line.send(PrintConsoleLine::new(dice(&event.args).to_string()));
|
||||||
|
}
|
||||||
|
"ban" => {
|
||||||
|
if &event.args == "" {
|
||||||
|
console_line.send(PrintConsoleLine::new("No user provided".to_string()));
|
||||||
|
} else {
|
||||||
|
let user_list = event.args.split(" ");
|
||||||
|
|
||||||
|
for user in user_list {
|
||||||
|
console_line.send(PrintConsoleLine::new(
|
||||||
|
format!("Banned {}", user).to_string(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"version" => {
|
||||||
|
let version = format!("Current client version is ");
|
||||||
|
console_line.send(PrintConsoleLine::new(version.to_string()));
|
||||||
|
}
|
||||||
|
error => console_line.send(PrintConsoleLine::new(format!(
|
||||||
|
"Command {} not found",
|
||||||
|
error
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
41
src/main.rs
Normal file
41
src/main.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
mod character_controller;
|
||||||
|
mod mods;
|
||||||
|
mod timesys;
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_console::ConsoleConfiguration;
|
||||||
|
|
||||||
|
use mods::mod_manager::ModManager;
|
||||||
|
mod console;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
|
enum AppState {
|
||||||
|
Menu,
|
||||||
|
InGame,
|
||||||
|
ModMenu,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Load mods after play is pressed
|
||||||
|
|
||||||
|
App::build()
|
||||||
|
.insert_resource(Msaa { samples: 4 })
|
||||||
|
.insert_resource(ClearColor(Color::rgb(0.4, 0.4, 0.4)))
|
||||||
|
.insert_resource(WindowDescriptor {
|
||||||
|
width: 1440.,
|
||||||
|
height: 900.,
|
||||||
|
title: "Lyrix".to_string(),
|
||||||
|
vsync: true,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.add_plugins(DefaultPlugins)
|
||||||
|
.insert_resource(ConsoleConfiguration {
|
||||||
|
// override config here
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
// .add_state(AppState::Menu)
|
||||||
|
.add_plugin(console::ConsoleManager)
|
||||||
|
.add_plugin(ModManager)
|
||||||
|
.add_plugin(character_controller::ModManager)
|
||||||
|
.run();
|
||||||
|
}
|
2
src/mods/mod.rs
Normal file
2
src/mods/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod mod_manager;
|
||||||
|
pub mod modding_api;
|
155
src/mods/mod_manager.rs
Normal file
155
src/mods/mod_manager.rs
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
use bevy::{
|
||||||
|
asset::{AssetLoader, LoadContext, LoadedAsset},
|
||||||
|
prelude::*,
|
||||||
|
reflect::TypeUuid,
|
||||||
|
utils::BoxedFuture,
|
||||||
|
};
|
||||||
|
use bevy_console::PrintConsoleLine;
|
||||||
|
use rhai::Engine;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::{sync::Arc, sync::RwLock};
|
||||||
|
|
||||||
|
use super::modding_api::{register_mod, register_object, register_weapon};
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, TypeUuid)]
|
||||||
|
#[uuid = "39cadc56-aa9c-4543-8640-a018b74b5051"]
|
||||||
|
pub struct Mod {
|
||||||
|
name: String,
|
||||||
|
enabled: bool,
|
||||||
|
}
|
||||||
|
#[derive(Debug, Deserialize, TypeUuid)]
|
||||||
|
#[uuid = "39cadc56-aa9c-4543-8640-a018b74b5050"]
|
||||||
|
pub struct LoadedMod {
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, TypeUuid)]
|
||||||
|
#[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"]
|
||||||
|
pub struct ModList {
|
||||||
|
pub value: i32,
|
||||||
|
pub vec: Vec<Mod>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ModListLoader;
|
||||||
|
impl AssetLoader for ModListLoader {
|
||||||
|
fn load<'a>(
|
||||||
|
&'a self,
|
||||||
|
bytes: &'a [u8],
|
||||||
|
load_context: &'a mut LoadContext,
|
||||||
|
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let custom_asset = ron::de::from_bytes::<ModList>(bytes)?;
|
||||||
|
load_context.set_default_asset(LoadedAsset::new(custom_asset));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extensions(&self) -> &[&str] {
|
||||||
|
&["list"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ModLoader;
|
||||||
|
impl AssetLoader for ModLoader {
|
||||||
|
fn load<'a>(
|
||||||
|
&'a self,
|
||||||
|
bytes: &'a [u8],
|
||||||
|
load_context: &'a mut LoadContext,
|
||||||
|
) -> BoxedFuture<'a, Result<(), anyhow::Error>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let custom_asset = LoadedMod {
|
||||||
|
name: std::str::from_utf8(bytes).unwrap().to_string(),
|
||||||
|
};
|
||||||
|
load_context.set_default_asset(LoadedAsset::new(custom_asset));
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extensions(&self) -> &[&str] {
|
||||||
|
&["rhai"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct State {
|
||||||
|
pub handle: Handle<ModList>,
|
||||||
|
pub mod_handle: Handle<LoadedMod>,
|
||||||
|
pub loaded: bool,
|
||||||
|
pub printed: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ModManager;
|
||||||
|
impl Plugin for ModManager {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
app.init_resource::<State>()
|
||||||
|
.add_asset::<ModList>()
|
||||||
|
.init_asset_loader::<ModListLoader>()
|
||||||
|
.add_asset::<LoadedMod>()
|
||||||
|
.init_asset_loader::<ModLoader>()
|
||||||
|
.add_startup_system(engine_settings.system())
|
||||||
|
.add_system(build_mods.system());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AddonState {
|
||||||
|
rebuild_addons: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_mods(
|
||||||
|
mut engine: ResMut<Engine>,
|
||||||
|
mut addon_state: ResMut<AddonState>,
|
||||||
|
|
||||||
|
mut console_line: EventWriter<PrintConsoleLine>,
|
||||||
|
) {
|
||||||
|
if !addon_state.rebuild_addons {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
println!("Rebuilt addons");
|
||||||
|
|
||||||
|
let logbook = Arc::new(RwLock::new(Vec::<String>::new()));
|
||||||
|
|
||||||
|
// Redirect print/debug output to 'log'
|
||||||
|
let log = logbook.clone();
|
||||||
|
engine.on_print(move |s| log.write().unwrap().push(format!("{}", s)));
|
||||||
|
|
||||||
|
let log = logbook.clone();
|
||||||
|
engine.on_debug(move |s, src, pos| {
|
||||||
|
log.write().unwrap().push(format!(
|
||||||
|
"DEBUG of {} at {:?}: {}",
|
||||||
|
src.unwrap_or("unknown"),
|
||||||
|
pos,
|
||||||
|
s
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = engine.run(include_str!("../../assets/mods/NewSwordMod.lad"));
|
||||||
|
match result {
|
||||||
|
Ok(_) => console_line.send(PrintConsoleLine::new("Mod Loaded".to_string())),
|
||||||
|
Err(error) => console_line.send(PrintConsoleLine::new(error.to_string())),
|
||||||
|
}
|
||||||
|
|
||||||
|
for entry in logbook.read().unwrap().iter() {
|
||||||
|
console_line.send(PrintConsoleLine::new(entry.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
addon_state.rebuild_addons = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn engine_settings(mut commands: Commands) {
|
||||||
|
let mut engine = Engine::new();
|
||||||
|
|
||||||
|
// Configure the engine
|
||||||
|
engine.set_max_array_size(50).set_max_operations(500);
|
||||||
|
|
||||||
|
engine.register_fn("register_mod", register_mod);
|
||||||
|
engine.register_fn("register_weapon", register_weapon);
|
||||||
|
engine.register_fn("register_object", register_object);
|
||||||
|
|
||||||
|
commands.insert_resource(engine);
|
||||||
|
commands.insert_resource(AddonState {
|
||||||
|
rebuild_addons: true,
|
||||||
|
});
|
||||||
|
}
|
67
src/mods/modding_api.rs
Normal file
67
src/mods/modding_api.rs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use rhai::{ImmutableString, INT};
|
||||||
|
use spin::Mutex;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Object {
|
||||||
|
name: String,
|
||||||
|
scripted: ScriptedBool,
|
||||||
|
}
|
||||||
|
// pub struct Weapon{}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Weapon {
|
||||||
|
name: String,
|
||||||
|
delay: u64,
|
||||||
|
damage: u8,
|
||||||
|
scripted: ScriptedBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ScriptedBool {
|
||||||
|
Scripted(String),
|
||||||
|
NotScripted,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref OBJECT_LIST: Mutex<Vec<Object>> = Mutex::new(vec![]);
|
||||||
|
static ref WEAPON_LIST: Mutex<Vec<Weapon>> = Mutex::new(vec![]);
|
||||||
|
static ref OBJECT_LIST3: Mutex<Vec<Object>> = Mutex::new(vec![]);
|
||||||
|
static ref OBJECT_LIST4: Mutex<Vec<Object>> = Mutex::new(vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn register_mod(name: ImmutableString, description: ImmutableString) {
|
||||||
|
println!("{}", name);
|
||||||
|
println!("{}", description);
|
||||||
|
}
|
||||||
|
/// register an unscripted weapon
|
||||||
|
pub fn register_weapon(name: ImmutableString, delay: INT, damage: INT) {
|
||||||
|
let mut list = WEAPON_LIST.lock();
|
||||||
|
let weapon = Weapon {
|
||||||
|
name: name.to_string(),
|
||||||
|
scripted: ScriptedBool::NotScripted,
|
||||||
|
delay: 0,
|
||||||
|
damage: 0,
|
||||||
|
};
|
||||||
|
list.push(weapon);
|
||||||
|
println!("{:?}", list);
|
||||||
|
}
|
||||||
|
/// Register a generic object without a script element
|
||||||
|
pub fn register_object(name: ImmutableString) {
|
||||||
|
let mut list = OBJECT_LIST.lock();
|
||||||
|
let object = Object {
|
||||||
|
name: name.to_string(),
|
||||||
|
scripted: ScriptedBool::NotScripted,
|
||||||
|
};
|
||||||
|
list.push(object);
|
||||||
|
println!("{:?}", list);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn register_scripted_object() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn register_scripted_weapon() {
|
||||||
|
todo!()
|
||||||
|
}
|
93
src/timesys.rs
Normal file
93
src/timesys.rs
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
use bevy::{
|
||||||
|
app::{AppBuilder, Plugin},
|
||||||
|
core::{Time, Timer},
|
||||||
|
ecs::system::{Res, ResMut},
|
||||||
|
prelude::IntoSystem,
|
||||||
|
};
|
||||||
|
struct TickTimer(Timer);
|
||||||
|
|
||||||
|
pub struct TimeDate {
|
||||||
|
pub tick: u64, // when hits 40 inc second
|
||||||
|
pub second: u64, // when hits 60 inc minute
|
||||||
|
pub minute: u64, // when hits 120 inc day
|
||||||
|
pub day: u8, // when hits 255 inc season
|
||||||
|
pub season: u8, // when hits 4 inc year and restart all previous counters
|
||||||
|
pub year: u64, // ahhhhhhhhh
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TickManager;
|
||||||
|
impl Plugin for TickManager {
|
||||||
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
|
app.insert_resource(TimeDate {
|
||||||
|
tick: 0, // when hits 40 inc second
|
||||||
|
second: 0, // when hits 60 inc minute
|
||||||
|
minute: 0, // when hits 120 inc day
|
||||||
|
day: 0, // when hits 255 inc season
|
||||||
|
season: 0, // when hits 4 inc year and restart all previous counters
|
||||||
|
year: 0, // ahhhhhhhhh
|
||||||
|
})
|
||||||
|
// the reason we call from_seconds with the true flag is to make the timer repeat itself
|
||||||
|
.insert_resource(TickTimer(Timer::from_seconds(0.0025, true)))
|
||||||
|
.add_system(game_tick.system())
|
||||||
|
.add_system(inc_sec.system())
|
||||||
|
.add_system(inc_min.system())
|
||||||
|
.add_system(inc_day.system())
|
||||||
|
.add_system(inc_season.system())
|
||||||
|
.add_system(inc_year.system());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn game_tick(time: Res<Time>, mut timer: ResMut<TickTimer>, mut timesys: ResMut<TimeDate>) {
|
||||||
|
if timer.0.tick(time.delta()).just_finished() {
|
||||||
|
timesys.tick += 1;
|
||||||
|
}
|
||||||
|
// Physics runs every tick
|
||||||
|
// Mob AI acts on its goal every tick
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_sec(mut timesys: ResMut<TimeDate>) {
|
||||||
|
if timesys.tick == 39 {
|
||||||
|
timesys.second += 1;
|
||||||
|
timesys.tick = 0;
|
||||||
|
//println!("Second {}", timesys.second)
|
||||||
|
}
|
||||||
|
// Mob AI updates goal every second
|
||||||
|
}
|
||||||
|
fn inc_min(mut timesys: ResMut<TimeDate>) {
|
||||||
|
if timesys.second == 59 {
|
||||||
|
timesys.second = 0;
|
||||||
|
timesys.minute += 1;
|
||||||
|
//println!("Minute {}", timesys.minute)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_day(mut timesys: ResMut<TimeDate>) {
|
||||||
|
if timesys.minute == 119 {
|
||||||
|
timesys.minute = 0;
|
||||||
|
timesys.day += 1;
|
||||||
|
//println!("Day {}", timesys.day)
|
||||||
|
}
|
||||||
|
// Run the calender check every day
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_season(mut timesys: ResMut<TimeDate>) {
|
||||||
|
/*
|
||||||
|
Jan 1 to Mar 14 Season one ()
|
||||||
|
Mar 14 to mar 26
|
||||||
|
Mar 26 to Aug 7
|
||||||
|
Aug 7 to Oct 19
|
||||||
|
oct 19 to Dec 31
|
||||||
|
*/
|
||||||
|
|
||||||
|
if timesys.day == 72 {
|
||||||
|
timesys.day = 0;
|
||||||
|
timesys.season += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc_year(mut timesys: ResMut<TimeDate>) {
|
||||||
|
if timesys.season == 4 {
|
||||||
|
timesys.season = 0;
|
||||||
|
timesys.year += 1;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue