Gameplay Examples

Common gameplay systems and mechanics.

Health System

public class Health : Component
{
    public int MaxHealth = 100;
    public int CurrentHealth { get; private set; }
    
    protected override void OnStart()
    {
        CurrentHealth = MaxHealth;
    }
    
    public void TakeDamage(int amount)
    {
        CurrentHealth -= amount;
        if (CurrentHealth <= 0)
        {
            CurrentHealth = 0;
            OnDeath();
        }
    }
    
    public void Heal(int amount)
    {
        CurrentHealth = System.Math.Min(CurrentHealth + amount, MaxHealth);
    }
    
    private void OnDeath()
    {
        Log.Info($"{GameObject!.Name} died!");
        GameObject.Destroy();
    }
}

Collectible Item

public class Collectible : Component
{
    public int Points = 10;
    private Vector3 _basePos;
    
    protected override void OnStart()
    {
        _basePos = Transform!.Position;
    }
    
    protected override void OnUpdate()
    {
        // Bobbing animation
        var pos = _basePos;
        pos.Y += MathF.Sin(Time.Now * 3f) * 0.2f;
        Transform!.Position = pos;
        
        // Check collision with player
        var player = Scene?.FindByName("Player");
        if (player != null && Transform.Position.DistanceTo(player.Transform.Position) < 1f)
        {
            ScoreManager.AddScore(Points);
            GameObject!.Destroy();
        }
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        r.DrawSphere(Transform!.Position, 0.3f, Color.Yellow);
    }
}

Shooting System

public class Shooter : Component
{
    public float FireRate = 0.2f;
    public float BulletSpeed = 20f;
    private float _cooldown;
    
    protected override void OnUpdate()
    {
        _cooldown -= Time.Delta;
        
        if (RaylibInput.IsKeyDown(KeyCode.Space) && _cooldown <= 0)
        {
            _cooldown = FireRate;
            SpawnBullet();
        }
    }
    
    private void SpawnBullet()
    {
        var bullet = Scene!.CreateGameObject("Bullet", Transform!.Position + Vector3.Forward);
        var b = bullet.AddComponent<Bullet>();
        b.Speed = BulletSpeed;
        b.Direction = Vector3.Forward;
    }
}

public class Bullet : Component
{
    public float Speed = 20f;
    public Vector3 Direction = Vector3.Forward;
    public float Lifetime = 3f;
    
    protected override void OnUpdate()
    {
        Transform!.Position += Direction * Speed * Time.Delta;
        
        Lifetime -= Time.Delta;
        if (Lifetime <= 0)
            GameObject!.Destroy();
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        r.DrawSphere(Transform!.Position, 0.1f, Color.Yellow);
    }
}

Enemy Chaser

public class EnemyChaser : Component
{
    public float Speed = 3f;
    public float AttackRange = 1.5f;
    public int Damage = 10;
    
    protected override void OnUpdate()
    {
        var player = Scene?.FindByName("Player");
        if (player == null) return;
        
        float dist = Transform!.Position.DistanceTo(player.Transform.Position);
        
        if (dist > AttackRange)
        {
            var dir = (player.Transform.Position - Transform.Position).Normalized;
            Transform.Position += dir * Speed * Time.Delta;
        }
        else
        {
            // Attack player
            var health = player.GetComponent<Health>();
            health?.TakeDamage(Damage);
        }
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        r.DrawCube(Transform!.Position, new Vector3(0.8f), Color.Red);
    }
}

Enemy Spawner

public class EnemySpawner : Component
{
    public float SpawnInterval = 2f;
    public float SpawnRadius = 10f;
    public int MaxEnemies = 10;
    
    private float _timer;
    private XRandom _random = new();
    
    protected override void OnUpdate()
    {
        var enemies = Scene!.FindAllByName("Enemy");
        if (enemies.Count() >= MaxEnemies) return;
        
        _timer += Time.Delta;
        if (_timer >= SpawnInterval)
        {
            _timer = 0;
            SpawnEnemy();
        }
    }
    
    private void SpawnEnemy()
    {
        float angle = _random.Float(0, MathHelper.TwoPI);
        var pos = new Vector3(
            MathF.Cos(angle) * SpawnRadius,
            0.5f,
            MathF.Sin(angle) * SpawnRadius
        );
        
        var enemy = Scene!.CreateGameObject("Enemy", pos);
        enemy.AddComponent<EnemyChaser>();
        enemy.AddComponent<Health>().MaxHealth = 30;
    }
}

Power-Up

public class SpeedPowerup : Component
{
    public float BoostMultiplier = 2f;
    public float Duration = 5f;
    
    protected override void OnUpdate()
    {
        var player = Scene?.FindByName("Player");
        if (player == null) return;
        
        if (Transform!.Position.DistanceTo(player.Transform.Position) < 1f)
        {
            var movement = player.GetComponent<PlayerMovement>();
            if (movement != null)
            {
                movement.Speed *= BoostMultiplier;
                // Schedule reset (simplified)
            }
            GameObject!.Destroy();
        }
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        float bob = MathF.Sin(Time.Now * 4f) * 0.2f;
        r.DrawSphere(Transform!.Position + new Vector3(0, bob, 0), 0.4f, Color.Cyan);
    }
}

Proximity Trigger

public class ProximityTrigger : Component
{
    public float TriggerRadius = 3f;
    public string TargetName = "Player";
    
    private bool _triggered;
    
    protected override void OnUpdate()
    {
        var target = Scene?.FindByName(TargetName);
        if (target == null) return;
        
        float dist = Transform!.Position.DistanceTo(target.Transform.Position);
        bool inRange = dist < TriggerRadius;
        
        if (inRange && !_triggered)
        {
            _triggered = true;
            OnEnter();
        }
        else if (!inRange && _triggered)
        {
            _triggered = false;
            OnExit();
        }
    }
    
    protected virtual void OnEnter()
    {
        Log.Info("Entered trigger zone!");
    }
    
    protected virtual void OnExit()
    {
        Log.Info("Exited trigger zone!");
    }
}

Game Timer

public class GameTimer : Component
{
    public float Duration = 60f;
    public float TimeRemaining { get; private set; }
    public bool IsRunning { get; private set; }
    
    public void StartTimer()
    {
        TimeRemaining = Duration;
        IsRunning = true;
    }
    
    protected override void OnUpdate()
    {
        if (!IsRunning) return;
        
        TimeRemaining -= Time.Delta;
        if (TimeRemaining <= 0)
        {
            TimeRemaining = 0;
            IsRunning = false;
            OnTimeUp();
        }
    }
    
    private void OnTimeUp()
    {
        Log.Info("Time's up!");
    }
    
    protected override void OnRender(RaylibRenderer r)
    {
        int minutes = (int)(TimeRemaining / 60);
        int seconds = (int)(TimeRemaining % 60);
        r.DrawText($"{minutes:D2}:{seconds:D2}", 600, 10, 40, Color.White);
    }
}