Compare commits
5 Commits
update-fla
...
first_unit
| Author | SHA1 | Date | |
|---|---|---|---|
| f0a987fddb | |||
| d6b2a93eac | |||
| ef257f43e6 | |||
| ec3185f386 | |||
| fa4798910d |
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -644,6 +644,16 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bevy_ecs_tilemap"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a7176ff40586face39666fab2c3692c62bd5de67987164e6d8b316bc19e27d7"
|
||||||
|
dependencies = [
|
||||||
|
"bevy",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bevy_encase_derive"
|
name = "bevy_encase_derive"
|
||||||
version = "0.17.2"
|
version = "0.17.2"
|
||||||
@@ -4556,6 +4566,7 @@ name = "war-in-tunnels"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bevy",
|
"bevy",
|
||||||
|
"bevy_ecs_tilemap",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy = "0.17.2"
|
bevy = "0.17.2"
|
||||||
|
bevy_ecs_tilemap = "0.17.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 1
|
opt-level = 1
|
||||||
|
|||||||
BIN
assets/base_field.png
Normal file
BIN
assets/base_field.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/dirt_field.png
Normal file
BIN
assets/dirt_field.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/mole_unit.png
Normal file
BIN
assets/mole_unit.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
265
src/main.rs
265
src/main.rs
@@ -1,3 +1,264 @@
|
|||||||
fn main() {
|
use bevy::{prelude::*, window::WindowResolution};
|
||||||
println!("Hello, world!");
|
use bevy_ecs_tilemap::prelude::*;
|
||||||
|
|
||||||
|
const TILEMAP_WIDTH: u32 = 50;
|
||||||
|
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>) {
|
||||||
|
commands.spawn(Camera2d);
|
||||||
|
|
||||||
|
let dirt_texture_handle: Handle<Image> = asset_server.load("dirt_field.png");
|
||||||
|
let base_texture_handle: Handle<Image> = asset_server.load("base_field.png");
|
||||||
|
|
||||||
|
let tilemap_entity = commands.spawn_empty().id();
|
||||||
|
let base_tilemap_entity = commands.spawn_empty().id();
|
||||||
|
|
||||||
|
let mut tile_storage = TileStorage::empty(MAP_SIZE);
|
||||||
|
let mut base_tile_storage = TileStorage::empty(MAP_SIZE);
|
||||||
|
|
||||||
|
for x in 0..MAP_SIZE.x {
|
||||||
|
for y in 0..MAP_SIZE.y {
|
||||||
|
let tile_pos = TilePos { x, y };
|
||||||
|
let tile_entity = commands
|
||||||
|
.spawn(TileBundle {
|
||||||
|
position: tile_pos,
|
||||||
|
tilemap_id: TilemapId(tilemap_entity),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.id();
|
||||||
|
tile_storage.set(&tile_pos, tile_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut base_positions = Vec::new();
|
||||||
|
|
||||||
|
for x in 0..3 {
|
||||||
|
for y in 11..14 {
|
||||||
|
if x < MAP_SIZE.x && y < MAP_SIZE.y {
|
||||||
|
let tile_pos = TilePos { x, y };
|
||||||
|
base_positions.push(tile_pos);
|
||||||
|
let tile_entity = commands
|
||||||
|
.spawn(TileBundle {
|
||||||
|
position: tile_pos,
|
||||||
|
tilemap_id: TilemapId(base_tilemap_entity),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.id();
|
||||||
|
base_tile_storage.set(&tile_pos, tile_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for x in 47..50 {
|
||||||
|
for y in 11..14 {
|
||||||
|
if x < MAP_SIZE.x && y < MAP_SIZE.y {
|
||||||
|
let tile_pos = TilePos { x, y };
|
||||||
|
base_positions.push(tile_pos);
|
||||||
|
let tile_entity = commands
|
||||||
|
.spawn(TileBundle {
|
||||||
|
position: tile_pos,
|
||||||
|
tilemap_id: TilemapId(base_tilemap_entity),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.id();
|
||||||
|
base_tile_storage.set(&tile_pos, tile_entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
commands.insert_resource(BaseTilePositions {
|
||||||
|
positions: base_positions,
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.entity(tilemap_entity).insert(TilemapBundle {
|
||||||
|
grid_size: TILE_SIZE.into(),
|
||||||
|
map_type: TilemapType::default(),
|
||||||
|
size: MAP_SIZE,
|
||||||
|
storage: tile_storage,
|
||||||
|
texture: TilemapTexture::Single(dirt_texture_handle),
|
||||||
|
tile_size: TILE_SIZE,
|
||||||
|
anchor: TilemapAnchor::Center,
|
||||||
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 0.0)),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
commands.entity(base_tilemap_entity).insert(TilemapBundle {
|
||||||
|
grid_size: TILE_SIZE.into(),
|
||||||
|
map_type: TilemapType::default(),
|
||||||
|
size: MAP_SIZE,
|
||||||
|
storage: base_tile_storage,
|
||||||
|
texture: TilemapTexture::Single(base_texture_handle),
|
||||||
|
tile_size: TILE_SIZE,
|
||||||
|
anchor: TilemapAnchor::Center,
|
||||||
|
transform: Transform::from_translation(Vec3::new(0.0, 0.0, 1.0)),
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
App::new()
|
||||||
|
.add_plugins(
|
||||||
|
DefaultPlugins
|
||||||
|
.set(WindowPlugin {
|
||||||
|
primary_window: Some(Window {
|
||||||
|
title: String::from("War in Tunnels"),
|
||||||
|
resolution: WindowResolution::new(
|
||||||
|
TILEMAP_WIDTH * TILE_WIDTH as u32,
|
||||||
|
TILEMAP_HEIGHT * TILE_HEIGHT as u32,
|
||||||
|
)
|
||||||
|
.with_scale_factor_override(1.0),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..default()
|
||||||
|
})
|
||||||
|
.set(ImagePlugin::default_nearest()),
|
||||||
|
)
|
||||||
|
.add_plugins(TilemapPlugin)
|
||||||
|
.add_systems(Startup, (startup, setup_player))
|
||||||
|
.add_systems(Update, (handle_mouse_input, highlight_selected_unit))
|
||||||
|
.run();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user