# Tiny Colony (part 2)

In the previous post, I defined the scope of *Tiny Colony*: a small, 2D, grid-based colony simulator inspired by games like RimWorld, built mainly as a way to learn Rust and explore Bevy.

This post covers the next step: **rendering a grid, spawning pawns, and moving one of them using a fixed simulation tick**.

---

## The world is just a grid

At its core, the world is a fixed-size grid:

```rust
pub const MAP_W: i32 = 64;
pub const MAP_H: i32 = 64;
```

Tiles are stored as a flat vector:

```rust
#[derive(Clone, Copy)]
enum Tile {
    Ground,
    Tree,
    Stockpile,
}
```

There’s no map abstraction yet — just a `Vec<Tile>` and some helpers to translate between grid coordinates and world coordinates.

```rust
fn grid_to_world(x: i32, y: i32) -> Vec3 {
    let origin_x = -(MAP_W as f32) * TILE_SIZE * 0.5 + TILE_SIZE * 0.5;
    let origin_y = -(MAP_H as f32) * TILE_SIZE * 0.5 + TILE_SIZE * 0.5;

    Vec3::new(
        origin_x + x as f32 * TILE_SIZE,
        origin_y + y as f32 * TILE_SIZE,
        0.0,
    )
}
```

This keeps the simulation grid-centered and avoids camera math early on.

---

## Rendering tiles (brute force, yay!)

Each tile is rendered as a simple sprite, tinted by type:

```rust
commands.spawn((
    Sprite {
        color,
        custom_size: Some(Vec2::splat(TILE_SIZE - TILE_GAP)),
        ..default()
    },
    Transform::from_translation(world_pos),
));
```

This means spawning **64 × 64 = 4096 sprites** on startup.

Is that optimal? Probably not.  
Is it good enough for now? Absolutely.

One of the nice things about Bevy is how easy it is to brute-force something visible without caring about performance too early.

---

## Pawns are data first, visuals second

A pawn is deliberately boring:

```rust
#[derive(Component)]
struct Pawn {
    id: u32,
    x: i32,
    y: i32,
}
```

No animation, no state machine, no behavior tree.

Visually, pawns are just small circles rendered slightly above tiles:

```rust
commands.spawn((
    Pawn { id, x, y },
    Sprite {
        image: circle_image.clone(),
        color: Color::srgb(0.85, 0.85, 0.95),
        custom_size: Some(Vec2::splat(TILE_SIZE - 2.0)),
        ..default()
    },
    Transform::from_translation(world_pos + Vec3::Z),
));
```

The circle texture itself is generated in code, not loaded from disk. This keeps iteration fast and avoids asset management entirely at this stage.

---

## A fixed simulation tick

The most important step so far was introducing a **fixed simulation clock**.

```rust
struct Sim {
    paused: bool,
    speed: f32,
    tick: Timer,
    target: IVec2,
}
```

This separates:

* simulation time (deterministic)
    
* rendering time (best effort)
    

The tick runs at 10 Hz:

```rust
Timer::from_seconds(0.10, TimerMode::Repeating)
```

And can be paused or sped up independently from framerate.

---

## Moving one pawn (dumbest way possible)

With the simulation tick in place, I implemented the simplest possible behavior:

> Move pawn `id = 0` one grid tile per tick toward a fixed target.

```rust
if pawn.x < target.x {
    pawn.x += 1;
} else if pawn.x > target.x {
    pawn.x -= 1;
} else if pawn.y < target.y {
    pawn.y += 1;
} else if pawn.y > target.y {
    pawn.y -= 1;
}
```

After updating the grid position, the render transform is updated accordingly:

```rust
let pos = grid_to_world(pawn.x, pawn.y);
transform.translation = pos + Vec3::Z;
```

No smoothing, no interpolation, no pathfinding.

But once the pawn started moving, the project immediately felt more “alive”.

---

## Early lessons

A few things became clear very quickly:

* Bevy makes it easy to get something visible fast
    
* Rust’s borrow checker shows up early, but usually points to real design improvements
    
* Fixed-tick simulation feels *right* for this genre
    

Most importantly: keeping the scope small made it possible to actually finish these steps.

---

## Current state

At this point, Tiny Colony has:

* a grid-based world
    
* basic terrain
    
* multiple pawns as ECS entities
    
* a fixed simulation loop
    
* pause and speed controls
    
* one pawn moving deterministically
    

That’s enough of a foundation to start building *actual gameplay*.

The code at this stage is available on GitHub under the `post-1` tag: [https://github.com/GuzzoLM/tiny-colony/tree/post-1/tiny-colony](https://github.com/GuzzoLM/tiny-colony/tree/post-1/tiny-colony)
