3 Commits

2 changed files with 165 additions and 9 deletions

BIN
assets/mole_unit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,8 +1,41 @@
use bevy::{prelude::*, window::WindowResolution}; use bevy::{prelude::*, window::WindowResolution};
use bevy_ecs_tilemap::prelude::*; use bevy_ecs_tilemap::prelude::*;
const MAP_SIZE: TilemapSize = TilemapSize { x: 50, y: 25 }; const TILEMAP_WIDTH: u32 = 50;
const TILE_SIZE: TilemapTileSize = TilemapTileSize { x: 25.0, y: 25.0 }; const TILEMAP_HEIGHT: u32 = 25;
const TILE_WIDTH: f32 = 25.0;
const TILE_HEIGHT: f32 = 25.0;
const MAP_SIZE: TilemapSize = TilemapSize {
x: TILEMAP_WIDTH,
y: TILEMAP_HEIGHT,
};
const TILE_SIZE: TilemapTileSize = TilemapTileSize {
x: TILE_WIDTH,
y: TILE_HEIGHT,
};
#[derive(Component)]
struct Unit {
health: u32,
position: Vec2,
digging_power: u32,
}
#[derive(Component)]
struct MoleUnit;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Selected;
#[derive(Resource)]
struct BaseTilePositions {
positions: Vec<TilePos>,
}
fn startup(mut commands: Commands, asset_server: Res<AssetServer>) { fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d); commands.spawn(Camera2d);
@@ -30,10 +63,13 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
} }
} }
for x in 0..5 { let mut base_positions = Vec::new();
for y in 10..15 {
for x in 0..3 {
for y in 11..14 {
if x < MAP_SIZE.x && y < MAP_SIZE.y { if x < MAP_SIZE.x && y < MAP_SIZE.y {
let tile_pos = TilePos { x, y }; let tile_pos = TilePos { x, y };
base_positions.push(tile_pos);
let tile_entity = commands let tile_entity = commands
.spawn(TileBundle { .spawn(TileBundle {
position: tile_pos, position: tile_pos,
@@ -46,10 +82,11 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
} }
} }
for x in 45..50 { for x in 47..50 {
for y in 10..15 { for y in 11..14 {
if x < MAP_SIZE.x && y < MAP_SIZE.y { if x < MAP_SIZE.x && y < MAP_SIZE.y {
let tile_pos = TilePos { x, y }; let tile_pos = TilePos { x, y };
base_positions.push(tile_pos);
let tile_entity = commands let tile_entity = commands
.spawn(TileBundle { .spawn(TileBundle {
position: tile_pos, position: tile_pos,
@@ -62,6 +99,10 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
} }
} }
commands.insert_resource(BaseTilePositions {
positions: base_positions,
});
commands.entity(tilemap_entity).insert(TilemapBundle { commands.entity(tilemap_entity).insert(TilemapBundle {
grid_size: TILE_SIZE.into(), grid_size: TILE_SIZE.into(),
map_type: TilemapType::default(), map_type: TilemapType::default(),
@@ -87,6 +128,117 @@ fn startup(mut commands: Commands, asset_server: Res<AssetServer>) {
}); });
} }
fn setup_player(mut commands: Commands, asset_server: Res<AssetServer>) {
let tile_pos = TilePos { x: 1, y: 12 };
let world_pos = tile_pos_to_world_pos(tile_pos);
commands.spawn((
Sprite {
image: asset_server.load("mole_unit.png"),
custom_size: Some(Vec2::new(TILE_WIDTH, TILE_HEIGHT)),
..Default::default()
},
Transform::from_translation(Vec3::new(world_pos.x, world_pos.y, 2.0)),
Player,
MoleUnit {},
Unit {
health: 100,
position: world_pos,
digging_power: 5,
},
));
}
fn tile_pos_to_world_pos(tile_pos: TilePos) -> Vec2 {
let half_map_width = (TILEMAP_WIDTH as f32 * TILE_WIDTH) / 2.0;
let half_map_height = (TILEMAP_HEIGHT as f32 * TILE_HEIGHT) / 2.0;
Vec2::new(
(tile_pos.x as f32 * TILE_WIDTH) - half_map_width + (TILE_WIDTH / 2.0),
(tile_pos.y as f32 * TILE_HEIGHT) - half_map_height + (TILE_HEIGHT / 2.0),
)
}
fn world_pos_to_tile_pos(world_pos: Vec2) -> TilePos {
let half_map_width = (TILEMAP_WIDTH as f32 * TILE_WIDTH) / 2.0;
let half_map_height = (TILEMAP_HEIGHT as f32 * TILE_HEIGHT) / 2.0;
let x = ((world_pos.x + half_map_width - (TILE_WIDTH / 2.0)) / TILE_WIDTH).floor() as u32;
let y = ((world_pos.y + half_map_height - (TILE_HEIGHT / 2.0)) / TILE_HEIGHT).floor() as u32;
TilePos { x, y }
}
fn handle_mouse_input(
mut commands: Commands,
mouse_button: Res<ButtonInput<MouseButton>>,
windows: Query<&Window>,
camera_q: Query<(&Camera, &GlobalTransform)>,
mut player_query: Query<(Entity, &mut Transform, &mut Unit), (With<Player>, With<MoleUnit>)>,
selected_query: Query<Entity, (With<Player>, With<MoleUnit>, With<Selected>)>,
base_tiles: Res<BaseTilePositions>,
) {
let Some(window) = windows.iter().next() else {
return;
};
let Some((camera, camera_transform)) = camera_q.iter().next() else {
return;
};
if let Some(cursor_position) = window.cursor_position() {
if let Ok(world_pos) = camera.viewport_to_world_2d(camera_transform, cursor_position) {
if mouse_button.just_pressed(MouseButton::Left) {
for entity in selected_query.iter() {
commands.entity(entity).remove::<Selected>();
}
for (entity, transform, _) in player_query.iter() {
let distance = transform.translation.truncate().distance(world_pos);
if distance < TILE_WIDTH / 2.0 {
commands.entity(entity).insert(Selected);
println!("Zaznaczono jednostkę gracza");
break;
}
}
}
if mouse_button.just_pressed(MouseButton::Right) {
if let Some(selected_entity) = selected_query.iter().next() {
let target_tile_pos = world_pos_to_tile_pos(world_pos);
if base_tiles.positions.contains(&target_tile_pos) {
if let Ok((_, mut transform, mut unit)) =
player_query.get_mut(selected_entity)
{
let new_world_pos = tile_pos_to_world_pos(target_tile_pos);
transform.translation.x = new_world_pos.x;
transform.translation.y = new_world_pos.y;
unit.position = new_world_pos;
println!("Przeniesiono jednostkę na pozycję {:?}", target_tile_pos);
}
} else {
println!("Nie można się przemieścić na ten tile - to nie jest base tile!");
}
}
}
}
}
}
fn highlight_selected_unit(
mut gizmos: Gizmos,
selected_query: Query<&Transform, (With<Player>, With<Selected>)>,
) {
for transform in selected_query.iter() {
gizmos.circle_2d(
transform.translation.truncate(),
TILE_WIDTH / 2.0 + 2.0,
Color::srgb(1.0, 1.0, 0.0),
);
}
}
fn main() { fn main() {
App::new() App::new()
.add_plugins( .add_plugins(
@@ -94,8 +246,11 @@ fn main() {
.set(WindowPlugin { .set(WindowPlugin {
primary_window: Some(Window { primary_window: Some(Window {
title: String::from("War in Tunnels"), title: String::from("War in Tunnels"),
resolution: WindowResolution::new(1250, 625) resolution: WindowResolution::new(
.with_scale_factor_override(1.0), TILEMAP_WIDTH * TILE_WIDTH as u32,
TILEMAP_HEIGHT * TILE_HEIGHT as u32,
)
.with_scale_factor_override(1.0),
..Default::default() ..Default::default()
}), }),
..default() ..default()
@@ -103,6 +258,7 @@ fn main() {
.set(ImagePlugin::default_nearest()), .set(ImagePlugin::default_nearest()),
) )
.add_plugins(TilemapPlugin) .add_plugins(TilemapPlugin)
.add_systems(Startup, startup) .add_systems(Startup, (startup, setup_player))
.add_systems(Update, (handle_mouse_input, highlight_selected_unit))
.run(); .run();
} }