Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Rigidbody and Actor interactions #73

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 80 additions & 24 deletions src/actors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,24 @@ use crate::prelude::*;
pub struct Actor {
pub width: u8,
pub height: u8,
pub pos: IVec2,
pub vel: Vec2,
}

//Called before simulations
pub fn fill_actors(
mut chunk_manager: ResMut<ChunkManager>,
actors: Query<&Actor>,
actors: Query<(&Actor, &Transform)>,
mut dirty_rects: ResMut<DirtyRects>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
) {
let materials = materials.0.get(materials.1 .0.clone()).unwrap();

for actor in actors.iter() {
for (actor, transform) in actors.iter() {
let actor_pos = transform.world_pos(actor).as_ivec2();

for x_off in 0..actor.width as i32 {
for y_off in 0..actor.height as i32 {
let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off));
let pos = global_to_chunk(actor_pos + ivec2(x_off, y_off));
if let Some(atom) = chunk_manager.get_mut_atom(pos) {
if materials[atom.id].is_void() {
*atom = Atom::object();
Expand All @@ -35,15 +36,17 @@ pub fn fill_actors(
//Called after simulation, before actor update
pub fn unfill_actors(
mut chunk_manager: ResMut<ChunkManager>,
actors: Query<&Actor>,
actors: Query<(&Actor, &Transform)>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
) {
let materials = materials.0.get(materials.1 .0.clone()).unwrap();

for actor in actors.iter() {
for (actor, transform) in actors.iter() {
let actor_pos = transform.world_pos(actor).as_ivec2();

for x_off in 0..actor.width as i32 {
for y_off in 0..actor.height as i32 {
let pos = global_to_chunk(actor.pos + ivec2(x_off, y_off));
let pos = global_to_chunk(actor_pos + ivec2(x_off, y_off));
if let Some(atom) = chunk_manager.get_mut_atom(pos) {
if materials[atom.id].is_object() {
*atom = Atom::default();
Expand All @@ -54,9 +57,14 @@ pub fn unfill_actors(
}
}

pub fn on_ground(chunk_manager: &ChunkManager, actor: &Actor, materials: &Materials) -> bool {
pub fn on_ground(
chunk_manager: &ChunkManager,
actor: &Actor,
pos: &IVec2,
materials: &Materials,
) -> bool {
for x_off in 0..actor.width {
let chunk_pos = global_to_chunk(actor.pos + ivec2(x_off as i32, actor.height as i32));
let chunk_pos = global_to_chunk(*pos + ivec2(x_off as i32, actor.height as i32));

if let Some(atom) = chunk_manager.get_atom(&chunk_pos) {
if materials[atom].is_powder() || materials[atom].is_solid() {
Expand All @@ -72,14 +80,15 @@ pub fn on_ground(chunk_manager: &ChunkManager, actor: &Actor, materials: &Materi

pub fn update_actors(
mut chunk_manager: ResMut<ChunkManager>,
mut actors: Query<&mut Actor>,
mut actors: Query<(&mut Actor, &mut Transform)>,
materials: (Res<Assets<Materials>>, Res<MaterialsHandle>),
) {
let materials = materials.0.get(materials.1 .0.clone()).unwrap();

for mut actor in actors.iter_mut() {
let mut prev = actor.pos;
for v in Line::new(actor.pos, actor.vel.as_ivec2()) {
for (mut actor, mut transform) in actors.iter_mut() {
let mut actor_pos = transform.world_pos(&actor).as_ivec2();
let mut prev = actor_pos;
for v in Line::new(actor_pos, actor.vel.as_ivec2()) {
let move_hor = match (prev.x != v.x, prev.y != v.y) {
(true, false) => true,
(false, true) => false,
Expand All @@ -91,30 +100,39 @@ pub fn update_actors(
let moved_x = move_x(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
(v.x - prev.x).signum(),
materials,
);
if on_ground(&chunk_manager, &actor, materials) {
let starting_y = actor.pos.y;
if on_ground(&chunk_manager, &actor, &actor_pos, materials) {
let starting_y = actor_pos.y;
match moved_x {
//If we can't move to the left or right
//Check if we can get up a stair-like structure
false => {
for i in 1..=UP_WALK_HEIGHT {
let moved_y = move_y(&mut chunk_manager, &mut actor, -1, materials);
let moved_y = move_y(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
-1,
materials,
);
//Abort if we couldn't move up, or if we moved up but couldn't move sideways on the last step
if !moved_y
|| i == UP_WALK_HEIGHT
&& !move_x(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
(v.x - prev.x).signum(),
materials,
)
{
abort_stair(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
starting_y,
1,
materials,
Expand All @@ -127,14 +145,20 @@ pub fn update_actors(
//Check if we can snap back to the ground
true => {
for i in 1..=DOWN_WALK_HEIGHT {
if !move_y(&mut chunk_manager, &mut actor, 1, materials)
&& on_ground(&chunk_manager, &actor, materials)
if !move_y(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
1,
materials,
) && on_ground(&chunk_manager, &actor, &actor_pos, materials)
{
break;
} else if i == DOWN_WALK_HEIGHT {
abort_stair(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
starting_y,
-1,
materials,
Expand All @@ -148,37 +172,42 @@ pub fn update_actors(
move_y(
&mut chunk_manager,
&mut actor,
&mut actor_pos,
(v.y - prev.y).signum(),
materials,
);
}

prev = v;
}

transform.update_world_pos(&actor, &actor_pos.as_vec2())
}
}

pub fn abort_stair(
chunk_manager: &mut ChunkManager,
actor: &mut Actor,
actor_pos: &mut IVec2,
starting_y: i32,
dir: i32,
materials: &Materials,
) {
for _ in 0..(starting_y - actor.pos.y) {
move_y(chunk_manager, actor, dir, materials);
for _ in 0..(starting_y - actor_pos.y) {
move_y(chunk_manager, actor, actor_pos, dir, materials);
}
}

pub fn move_x(
chunk_manager: &mut ChunkManager,
actor: &mut Actor,
actor_pos: &mut IVec2,
dir: i32,
materials: &Materials,
) -> bool {
//Check if we can move
for y_off in 0..actor.height as i32 {
let pos = actor.pos
let pos = *actor_pos
+ if dir > 0 {
// Moving right
ivec2(actor.width as i32, y_off)
Expand All @@ -200,20 +229,21 @@ pub fn move_x(
}
}

actor.pos.x += dir;
actor_pos.x += dir;

true
}

pub fn move_y(
chunk_manager: &mut ChunkManager,
actor: &mut Actor,
actor_pos: &mut IVec2,
dir: i32,
materials: &Materials,
) -> bool {
//Check if we can move
for x_off in 0..actor.width as i32 {
let pos = actor.pos
let pos = *actor_pos
+ if dir > 0 {
// Moving down
ivec2(x_off, actor.height as i32)
Expand All @@ -235,11 +265,37 @@ pub fn move_y(
}
}

actor.pos.y += dir;
actor_pos.y += dir;

true
}

pub trait WorldPos {
fn world_pos(&self, actor: &Actor) -> Vec2;
}

impl WorldPos for Transform {
fn world_pos(&self, actor: &Actor) -> Vec2 {
let mut pos = self.translation.xy();
pos.y *= -1.;

pos -= vec2(actor.width as f32, actor.height as f32) / 2.;

pos
}
}

pub trait UpdateWorldPos {
fn update_world_pos(&mut self, actor: &Actor, world_pos: &Vec2);
}

impl UpdateWorldPos for Transform {
fn update_world_pos(&mut self, actor: &Actor, world_pos: &Vec2) {
self.translation.x = world_pos.x + actor.width as f32 / 2.;
self.translation.y = -world_pos.y - actor.height as f32 / 2.;
}
}

pub struct ActorsPlugin;
impl Plugin for ActorsPlugin {
fn build(&self, app: &mut App) {
Expand Down
5 changes: 3 additions & 2 deletions src/chunk_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ pub fn update_manager_pos(
mut commands: Commands,
chunk_textures: Query<Entity, With<ChunksParent>>,
image_entities: Query<(&Parent, Entity, &Handle<Image>)>,
player: Query<&Actor, With<Player>>,
player: Query<(&Actor, &Transform), With<Player>>,
resources: (
ResMut<SavingTask>,
ResMut<ChunkManager>,
Expand All @@ -556,7 +556,8 @@ pub fn update_manager_pos(
) {
let (mut saving_task, mut chunk_manager, mut images) = resources;

let mut player_pos = player.single().pos;
let (actor, transform) = player.single();
let mut player_pos = transform.world_pos(actor).as_ivec2();
if player_pos.x < 0 {
player_pos.x -= CHUNK_LENGHT as i32
}
Expand Down
6 changes: 6 additions & 0 deletions src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use bevy::prelude::Color;
use bevy_rapier2d::geometry::Group;

// Chunk Length consts
// Chunk length MUST be divisible by 4
Expand Down Expand Up @@ -53,6 +54,11 @@ pub const PARTICLE_LAYER: f32 = 10.;
pub const AUTOMATA_LAYER: f32 = 100.;
pub const RIGIDBODY_LAYER: f32 = 1000.;

//Rapier2d collision groups
pub const RIGIDBODY_GROUP: Group = Group::GROUP_1;
//pub const WORLD_GROUP: Group = Group::GROUP_2;
pub const ACTOR_GROUP: Group = Group::GROUP_3;

//Buttons
pub const NORMAL_BUTTON: Color = Color::rgb(0.15, 0.15, 0.15);
pub const HOVERED_BUTTON: Color = Color::rgb(0.25, 0.25, 0.25);
Expand Down
9 changes: 5 additions & 4 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,12 @@ pub fn _delete_image(mut commands: Commands, debug_images: Query<Entity, With<De
#[derive(Component)]
pub struct DeleteImage;

fn render_actors(mut gizmos: Gizmos, actors: Query<&Actor>) {
for actor in actors.iter() {
fn render_actors(mut gizmos: Gizmos, actors: Query<(&Transform, &Actor)>) {
for (transform, actor) in actors.iter() {
let pos = transform.translation.xy();

gizmos.rect_2d(
vec2(actor.pos.x as f32, -actor.pos.y as f32)
+ vec2(actor.width as f32, -(actor.height as f32)) / 2.,
pos + vec2(actor.width as f32, -(actor.height as f32)) / 2.,
0.,
Vec2::new(actor.width as f32, actor.height as f32),
Color::rgba(0.75, 0.25, 0.25, 0.2),
Expand Down
Loading
Loading