Your First Game
Build a simple collector game where you move a player to collect items while avoiding enemies.
What We'll Build
In this tutorial, you'll create a complete game with:
- A player that moves with WASD keys
- Collectible items that increase your score
- A simple camera that follows the player
- A score display on screen
Step 1: Project Setup
Create a new project and set up the basic engine:
using Xengine.Core;
using Xengine.Engine;
using Xengine.Math;
using Xengine.Scene;
using Xengine.Rendering;
var config = new ApplicationConfig
{
WindowWidth = 1280,
WindowHeight = 720,
WindowTitle = "Collector Game"
};
using var engine = new Engine(config);
engine.Initialize();
var scene = engine.LoadScene("GameScene");
// We'll add game objects here...
engine.Run();
Step 2: Create the Player
Create a player component with WASD movement:
public class Player : Component
{
public float Speed = 5f;
public static int Score = 0;
protected override void OnUpdate()
{
var move = Vector3.Zero;
if (RaylibInput.IsKeyDown(KeyCode.W)) move.Z += 1;
if (RaylibInput.IsKeyDown(KeyCode.S)) move.Z -= 1;
if (RaylibInput.IsKeyDown(KeyCode.A)) move.X -= 1;
if (RaylibInput.IsKeyDown(KeyCode.D)) move.X += 1;
if (move.LengthSquared > 0)
{
move = move.Normalized * Speed * Time.Delta;
Transform.Position += move;
}
}
protected override void OnRender(RaylibRenderer r)
{
r.DrawCube(Transform.Position, Vector3.One, Color.Blue);
}
}
Step 3: Add Collectibles
Create items that the player can collect:
public class Collectible : Component
{
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)
{
float dist = Transform.Position.DistanceTo(player.Transform.Position);
if (dist < 1.2f)
{
Player.Score += 10;
Log.Info($"Score: {Player.Score}");
GameObject.Destroy();
}
}
}
protected override void OnRender(RaylibRenderer r)
{
r.DrawSphere(Transform.Position, 0.3f, Color.Yellow);
}
}
Step 4: Add Camera
Create a camera that follows the player:
public class FollowCamera : Component
{
public Vector3 Offset = new Vector3(0, 10, -8);
public float SmoothSpeed = 5f;
private Vector3 _currentPos;
protected override void OnStart()
{
_currentPos = Offset;
}
protected override void OnUpdate()
{
var player = Scene.FindByName("Player");
if (player == null) return;
var targetPos = player.Transform.Position + Offset;
_currentPos = Vector3.Lerp(_currentPos, targetPos, SmoothSpeed * Time.Delta);
RaylibRenderer.Instance?.SetCamera(_currentPos, player.Transform.Position, 60f);
}
}
Step 5: Add Score UI
Display the score on screen:
public class ScoreUI : Component
{
protected override void OnRender(RaylibRenderer r)
{
r.DrawText($"Score: {Player.Score}", 20, 20, 32, Color.White);
r.DrawText("WASD to move, collect the yellow orbs!", 20, 60, 18, Color.Gray);
}
}
Step 6: Add Ground
Create a simple ground plane:
public class Ground : Component
{
protected override void OnRender(RaylibRenderer r)
{
r.DrawPlane(Vector3.Zero, new Vector2(30, 30), new Color(0.2f, 0.25f, 0.2f));
r.DrawGrid(30, 1f);
}
}
Step 7: Put It All Together
Add all objects to the scene:
using Xengine.Core;
using Xengine.Engine;
using Xengine.Math;
using Xengine.Scene;
using Xengine.Rendering;
var config = new ApplicationConfig
{
WindowWidth = 1280,
WindowHeight = 720,
WindowTitle = "Collector Game"
};
using var engine = new Engine(config);
engine.Initialize();
var scene = engine.LoadScene("GameScene");
// Create player
var player = scene.CreateGameObject("Player", new Vector3(0, 0.5f, 0));
player.AddComponent<Player>();
// Create camera
var camera = scene.CreateGameObject("Camera");
camera.AddComponent<FollowCamera>();
// Create ground
scene.CreateGameObject("Ground").AddComponent<Ground>();
// Create collectibles
var random = new XRandom(42);
for (int i = 0; i < 15; i++)
{
var pos = new Vector3(
random.Float(-12, 12),
0.8f,
random.Float(-12, 12)
);
var item = scene.CreateGameObject($"Item{i}", pos);
item.AddComponent<Collectible>();
}
// Create UI
scene.CreateGameObject("UI").AddComponent<ScoreUI>();
engine.Run();
// === Component Classes Below ===
public class Player : Component
{
public float Speed = 5f;
public static int Score = 0;
protected override void OnUpdate()
{
var move = Vector3.Zero;
if (RaylibInput.IsKeyDown(KeyCode.W)) move.Z += 1;
if (RaylibInput.IsKeyDown(KeyCode.S)) move.Z -= 1;
if (RaylibInput.IsKeyDown(KeyCode.A)) move.X -= 1;
if (RaylibInput.IsKeyDown(KeyCode.D)) move.X += 1;
if (move.LengthSquared > 0)
Transform.Position += move.Normalized * Speed * Time.Delta;
}
protected override void OnRender(RaylibRenderer r)
{
r.DrawCube(Transform.Position, Vector3.One, Color.Blue);
}
}
public class Collectible : Component
{
private Vector3 _basePos;
protected override void OnStart() => _basePos = Transform.Position;
protected override void OnUpdate()
{
Transform.Position = _basePos + new Vector3(0, MathF.Sin(Time.Now * 3f) * 0.2f, 0);
var player = Scene.FindByName("Player");
if (player != null && Transform.Position.DistanceTo(player.Transform.Position) < 1.2f)
{
Player.Score += 10;
GameObject.Destroy();
}
}
protected override void OnRender(RaylibRenderer r) => r.DrawSphere(Transform.Position, 0.3f, Color.Yellow);
}
public class FollowCamera : Component
{
private Vector3 _offset = new(0, 10, -8);
private Vector3 _pos;
protected override void OnStart() => _pos = _offset;
protected override void OnUpdate()
{
var player = Scene.FindByName("Player");
if (player == null) return;
_pos = Vector3.Lerp(_pos, player.Transform.Position + _offset, 5f * Time.Delta);
RaylibRenderer.Instance?.SetCamera(_pos, player.Transform.Position, 60f);
}
}
public class Ground : Component
{
protected override void OnRender(RaylibRenderer r)
{
r.DrawPlane(Vector3.Zero, new Vector2(30, 30), new Color(0.2f, 0.25f, 0.2f));
r.DrawGrid(30, 1f);
}
}
public class ScoreUI : Component
{
protected override void OnRender(RaylibRenderer r)
{
r.DrawText($"Score: {Player.Score}", 20, 20, 32, Color.White);
r.DrawText("WASD to move, collect the yellow orbs!", 20, 60, 18, Color.Gray);
}
}
Next Steps
Congratulations! You've built your first game. Here are some ideas to expand it:
- Add enemies that chase the player
- Add a health system
- Add sound effects when collecting items
- Add a timer or win condition
- Add different types of collectibles