Next Steps
Congratulations on learning the basics of Pill! Here are some directions to take your game development further.
Building Game Features
Player Movement and Controls
Implement responsive player controls:
rust
fn player_movement_system(engine: &mut Engine) -> Result<()> {
let dt = engine.get_global_component::<TimeComponent>()?.delta_time;
let input = engine.get_global_component::<InputComponent>()?;
for (_, transform, player) in engine.iterate_two_components_mut::<
TransformComponent,
PlayerController,
>()? {
let mut movement = Vector3f::zeros();
// WASD movement
if input.is_key_pressed(KeyCode::W) {
movement.z -= 1.0;
}
if input.is_key_pressed(KeyCode::S) {
movement.z += 1.0;
}
if input.is_key_pressed(KeyCode::A) {
movement.x -= 1.0;
}
if input.is_key_pressed(KeyCode::D) {
movement.x += 1.0;
}
// Normalize and apply speed
if movement.magnitude() > 0.0 {
movement = movement.normalize() * player.speed * dt;
transform.position += movement;
}
// Mouse look
let mouse_delta = input.mouse_delta();
transform.rotation *= Quaternionf::from_euler_angles(
-mouse_delta.y * 0.001,
-mouse_delta.x * 0.001,
0.0
);
}
Ok(())
}Camera Systems
Create different camera types:
Follow Camera
rust
fn follow_camera_system(engine: &mut Engine) -> Result<()> {
// Get player position
let player_pos = {
let mut pos = Vector3f::zeros();
for (_, transform, _) in engine.iterate_two_components::<
TransformComponent,
PlayerTag,
>()? {
pos = transform.position;
break;
}
pos
};
// Update camera position
for (_, camera_transform, _) in engine.iterate_two_components_mut::<
TransformComponent,
CameraComponent,
>()? {
let offset = Vector3f::new(0.0, 5.0, 10.0);
let target = player_pos + offset;
// Smooth lerp
let alpha = 5.0 * engine.get_global_component::<TimeComponent>()?.delta_time;
camera_transform.position = camera_transform.position.lerp(&target, alpha);
// Look at player
camera_transform.look_at(player_pos, Vector3f::y());
}
Ok(())
}Orbit Camera
rust
fn orbit_camera_system(engine: &mut Engine) -> Result<()> {
let input = engine.get_global_component::<InputComponent>()?;
for (_, transform, orbit) in engine.iterate_two_components_mut::<
TransformComponent,
OrbitCamera,
>()? {
// Mouse input for orbiting
let mouse_delta = input.mouse_delta();
orbit.yaw -= mouse_delta.x * 0.003;
orbit.pitch -= mouse_delta.y * 0.003;
orbit.pitch = orbit.pitch.clamp(-1.5, 1.5);
// Mouse wheel for zoom
orbit.distance -= input.mouse_wheel_delta() * 0.5;
orbit.distance = orbit.distance.clamp(2.0, 50.0);
// Calculate position
let x = orbit.distance * orbit.pitch.cos() * orbit.yaw.sin();
let y = orbit.distance * orbit.pitch.sin();
let z = orbit.distance * orbit.pitch.cos() * orbit.yaw.cos();
transform.position = orbit.target + Vector3f::new(x, y, z);
transform.look_at(orbit.target, Vector3f::y());
}
Ok(())
}Physics Integration
Use physics for realistic gameplay:
rust
// Create dynamic physics object
engine.build_entity(scene)
.with_component(TransformComponent::builder()
.position(Vector3f::new(0.0, 10.0, 0.0))
.build())
.with_component(MeshRenderingComponent::builder()
.mesh(&mesh)
.material(&material)
.build())
.with_component(RigidBodyComponent::builder()
.body_type(RigidBodyType::Dynamic)
.linear_damping(0.5) // Air resistance
.angular_damping(0.5) // Rotation resistance
.build())
.with_component(ColliderComponent::builder()
.shape(SharedShape::ball(1.0))
.mass(10.0)
.restitution(0.7) // Bounciness
.friction(0.5)
.build())
.build();Applying Forces
rust
fn apply_force_system(engine: &mut Engine) -> Result<()> {
let input = engine.get_global_component::<InputComponent>()?;
for (_, rigidbody, _) in engine.iterate_two_components_mut::<
RigidBodyComponent,
PlayerTag,
>()? {
if input.is_key_just_pressed(KeyCode::Space) {
// Apply upward impulse
rigidbody.apply_impulse(Vector3f::new(0.0, 500.0, 0.0));
}
if input.is_key_pressed(KeyCode::W) {
// Apply forward force
rigidbody.apply_force(Vector3f::new(0.0, 0.0, -100.0));
}
}
Ok(())
}AI and Behavior
Implement simple AI systems:
rust
define_component!(AIComponent {
state: AIState,
target: Option<EntityHandle>,
patrol_points: Vec<Vector3f>,
current_patrol: usize,
});
enum AIState {
Idle,
Patrol,
Chase,
Attack,
}
fn ai_system(engine: &mut Engine) -> Result<()> {
let dt = engine.get_global_component::<TimeComponent>()?.delta_time;
// Get player position
let player_pos = get_player_position(engine)?;
for (entity, transform, ai) in engine.iterate_two_components_mut::<
TransformComponent,
AIComponent,
>()? {
let distance_to_player = (player_pos - transform.position).magnitude();
match ai.state {
AIState::Patrol => {
// Move to patrol point
let target = ai.patrol_points[ai.current_patrol];
move_towards(transform, target, 2.0 * dt);
// Check if reached
if (target - transform.position).magnitude() < 0.5 {
ai.current_patrol = (ai.current_patrol + 1) % ai.patrol_points.len();
}
// Check for player
if distance_to_player < 10.0 {
ai.state = AIState::Chase;
}
}
AIState::Chase => {
// Chase player
move_towards(transform, player_pos, 3.0 * dt);
// Check if in attack range
if distance_to_player < 2.0 {
ai.state = AIState::Attack;
}
// Check if lost player
else if distance_to_player > 15.0 {
ai.state = AIState::Patrol;
}
}
AIState::Attack => {
// Attack logic
look_at(transform, player_pos);
if distance_to_player > 3.0 {
ai.state = AIState::Chase;
}
}
_ => {}
}
}
Ok(())
}Networking Multiplayer Games
Setting Up Networking
Enable networking in your Cargo.toml:
toml
[dependencies]
pill_engine = { path = "../Pill-Engine/engine/pill_engine", features = ["net"] }Client Setup
rust
#[cfg(feature = "net")]
{
use pill_engine::{NetState, NetworkStateComponent};
use rand::Rng;
// Create client instance
let client_id = rand::thread_rng().gen_range(1..=10_000_000);
let server_addr = "127.0.0.1:5000";
engine.add_global_component(NetState::new_client(server_addr, client_id)?)?;
// Add network component to player
engine.add_component_to_entity(
scene,
player_entity,
NetworkStateComponent {
net_entity_id: rand::thread_rng().gen_range(1..=1000),
owner_id: client_id,
state: NetEntityState::Spawn,
transform: Some(initial_transform.clone()),
},
)?;
}Server Setup
rust
#[cfg(feature = "net")]
{
let port = 5000;
engine.add_global_component(NetState::new_server(port)?)?;
// Add networking system
engine.add_system("NetworkingServer", pill_engine::networking_system_server)?;
}Advanced Topics
Custom Shaders
While Pill handles shaders internally, you can customize rendering:
rust
// Future: Custom shader support
// Check res/shaders/ for built-in shadersPost-Processing Effects
Add screen-space effects:
rust
// Future: Post-processing API
// Currently configured through renderer settingsScene Management
Switch between multiple scenes:
rust
// Create multiple scenes
let menu_scene = engine.create_scene("Menu")?;
let game_scene = engine.create_scene("Game")?;
let pause_scene = engine.create_scene("Pause")?;
// Switch scenes
engine.set_active_scene(game_scene)?;
// Later...
fn pause_game(engine: &mut Engine) -> Result<()> {
let pause_scene = engine.get_scene("Pause")?;
engine.set_active_scene(pause_scene)?;
Ok(())
}Save/Load System
Implement game state persistence:
rust
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct SaveData {
player_position: Vector3f,
score: i32,
level: i32,
inventory: Vec<Item>,
}
fn save_game(engine: &Engine) -> Result<()> {
let save_data = SaveData {
player_position: get_player_position(engine)?,
score: engine.get_global_component::<GameState>()?.score,
level: engine.get_global_component::<GameState>()?.level,
inventory: get_player_inventory(engine)?,
};
let json = serde_json::to_string_pretty(&save_data)?;
std::fs::write("save.json", json)?;
Ok(())
}
fn load_game(engine: &mut Engine) -> Result<()> {
let json = std::fs::read_to_string("save.json")?;
let save_data: SaveData = serde_json::from_str(&json)?;
// Restore game state
set_player_position(engine, save_data.player_position)?;
engine.get_global_component_mut::<GameState>()?.score = save_data.score;
// ... restore other data
Ok(())
}Learning Resources
Example Projects
Study the included examples:
- Empty: Starting template - minimal setup
- Floating-Pills: Basic rendering and entities
- Trucks: Physics, controls, and camera systems
- Italian-Brainrot: Advanced features showcase
- Net-Minimal: Networking basics
Community and Support
- GitHub Issues: Report bugs and request features
- Discussions: Ask questions and share projects
- Examples: Browse example projects for patterns
Rust Game Development
Expand your knowledge:
- Rust Book - Learn Rust fundamentals
- Game Development in Rust - Rust gamedev ecosystem
- Rapier Physics - Physics engine documentation
Performance Optimization
Profiling
Measure performance to find bottlenecks:
rust
use std::time::Instant;
fn expensive_system(engine: &mut Engine) -> Result<()> {
let start = Instant::now();
// Your system logic
let elapsed = start.elapsed();
if elapsed.as_millis() > 16 {
println!("Warning: System took {}ms", elapsed.as_millis());
}
Ok(())
}Optimization Tips
- Minimize entity iteration: Only query what you need
- Cache lookups: Store frequently accessed data
- Use spatial partitioning: For collision detection and visibility
- Batch operations: Group similar entities together
- LOD systems: Use lower detail for distant objects
Memory Management
rust
// Remove entities when no longer needed
engine.destroy_entity(scene, entity_handle)?;
// Unload unused resources
engine.remove_resource::<Mesh>(&unused_mesh_handle)?;Debugging Tips
Visual Debugging
Draw debug information:
rust
fn debug_draw_system(engine: &mut Engine) -> Result<()> {
// Future: Debug drawing API
// For now, use temporary entities
Ok(())
}Logging
Use Rust's logging:
rust
use log::{info, warn, error, debug};
fn my_system(engine: &mut Engine) -> Result<()> {
info!("System running");
debug!("Entity count: {}", entity_count);
warn!("Low health detected");
error!("Critical error occurred");
Ok(())
}What's Next?
You now have the knowledge to build complete games with Pill. Here are some project ideas:
Beginner Projects
- Collect the Pills: Simple collection game
- Physics Playground: Experiment with physics
- Walking Simulator: Exploration game
Intermediate Projects
- Tower Defense: Strategy and AI
- Racing Game: Vehicle physics and tracks
- Platformer: Jumping and obstacles
Advanced Projects
- Multiplayer Arena: Networking and combat
- Open World: Large environments and streaming
- Procedural Generation: Dynamic content
Remember to check the Troubleshooting page if you encounter any issues!