sfml raycasting with movement and rotation in csharp

Here is an example of how to implement a simple raycasting engine using SFML, with movement and rotation controls:

main.cs
using SFML.Graphics;
using SFML.System;
using SFML.Window;

const float MOVE_SPEED = 0.1f;
const float ROT_SPEED = 1f;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int NUM_RAYS = 320;

class RaycastGame
{
    RenderWindow window_;
    RectangleShape wall_;
    Vector2f position_;
    float angle_;
    float[] distances_;

    public RaycastGame()
    {
        window_ = new RenderWindow(new VideoMode(SCREEN_WIDTH, SCREEN_HEIGHT), "Raycasting");
        wall_ = new RectangleShape(new Vector2f(1, SCREEN_HEIGHT));
        wall_.FillColor = Color.White;
        position_ = new Vector2f(3.456f, 3.456f);
        angle_ = 0f;
        distances_ = new float[NUM_RAYS];
    }

    public void Run()
    {
        Clock clock = new Clock();
        while (window_.IsOpen)
        {
            window_.DispatchEvents();
            float deltaTime = clock.Restart().AsSeconds();

            MovePlayer(deltaTime);
            CastRays();

            window_.Clear();

            for (int i = 0; i < NUM_RAYS; i++)
            {
                float distance = distances_[i];
                float lineHeight = SCREEN_HEIGHT / distance;
                wall_.Size = new Vector2f(1, lineHeight);
                wall_.Position = new Vector2f(i, SCREEN_HEIGHT / 2f - lineHeight / 2f);
                window_.Draw(wall_);
            }

            window_.Display();
        }
    }

    void MovePlayer(float deltaTime)
    {
        Vector2f forward = new Vector2f((float)Math.Cos(angle_ * Math.PI / 180f), (float)Math.Sin(angle_ * Math.PI / 180f));
        Vector2f right = new Vector2f((float)Math.Cos((angle_ + 90f) * Math.PI / 180f), (float)Math.Sin((angle_ + 90f) * Math.PI / 180f));

        if (Keyboard.IsKeyPressed(Keyboard.Key.W))
            position_ += forward * MOVE_SPEED * deltaTime;
        if (Keyboard.IsKeyPressed(Keyboard.Key.S))
            position_ -= forward * MOVE_SPEED * deltaTime;
        if (Keyboard.IsKeyPressed(Keyboard.Key.D))
            position_ += right * MOVE_SPEED * deltaTime;
        if (Keyboard.IsKeyPressed(Keyboard.Key.A))
            position_ -= right * MOVE_SPEED * deltaTime;
        if (Keyboard.IsKeyPressed(Keyboard.Key.Left))
            angle_ -= ROT_SPEED * deltaTime;
        if (Keyboard.IsKeyPressed(Keyboard.Key.Right))
            angle_ += ROT_SPEED * deltaTime;
    }

    void CastRays()
    {
        for (int i = 0; i < NUM_RAYS; i++)
        {
            float rayAngle = angle_ + (float)i / NUM_RAYS * 60f - 30f;
            Vector2f rayDir = new Vector2f((float)Math.Cos(rayAngle * Math.PI / 180f), (float)Math.Sin(rayAngle * Math.PI / 180f));

            float distance = 0f;
            Vector2f rayPos = position_;

            while (distance < 20f)
            {
                rayPos += rayDir * 0.02f;
                distance += 0.02f;

                if ((int)rayPos.X >= 0 && (int)rayPos.X < SCREEN_WIDTH && (int)rayPos.Y >= 0 && (int)rayPos.Y < SCREEN_HEIGHT)
                {
                    if (window_.GetPixel((uint)rayPos.X, (uint)rayPos.Y) != Color.Black)
                    {
                        // Hit a wall
                        distances_[i] = distance;
                        break;
                    }
                }
                else
                {
                    // Hit the edge of the world
                    distances_[i] = distance;
                    break;
                }
            }
        }
    }
}
3467 chars
108 lines

This code creates a simple 2D game window using SFML, with a player at the center of the screen. The player can move forward, backward, left, and right using the W, S, A, and D keys, and can rotate left and right using the left and right arrow keys.

Raycasting is done by casting a number of rays from the player's position, and checking if they intersect with any obstacles (in this case, just a background image with black walls). The distance to the first obstacle is stored in an array, which is then used to calculate the height of a wall on the screen. The wall is then drawn using an SFML RectangleShape.

Note that this implementation is quite basic and not optimized for performance, but should be good enough for simple game prototypes or experiments.

gistlibby LogSnag