C:\> Rostislav Persion's Projects

.:: Ray Casting Demo ::.
Simple 3d walk through


This is a quick simple attempt at creating a 3D level using ray casting. Ray casting is when you shoot a beam out of the avatar. When the beam hits a wall you use the distance variable to draw walls in the output canvas. If the ray hits something close then the wall segment will be large. If the ray hits something far away then the wall segment will be small. You have to shoot many rays out of the avatar in order to make a complete set of walls.











This project is a demo of a 3D walk through game written in c# using ray casting.

Nothing too special.

Q + ENTER = Go forward
A + ENTER = Go backward
Z + ENTER = Turn left
X + ENTER = Turn right


Here is the code I wrote.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace ConsoleApp9
{

    class Ray
    {
        public double dist;
        public int col;
    }

    class Program
    {

        static void DrawWalls(Stack<Ray> h1)
        {

            Console.ForegroundColor = ConsoleColor.Green;
            Console.Clear();

            int frm = 10;
            int cnt = 0;
            int lastn = 0;

            foreach (Ray n in h1)
            {
                cnt++;
                if (n.col == 1) { Console.ForegroundColor = ConsoleColor.Green; }
                if (n.col == 2) { Console.ForegroundColor = ConsoleColor.Blue; }
                if (n.col == 3) { Console.ForegroundColor = ConsoleColor.Yellow; }

                Console.SetCursorPosition(cnt, frm - (10 - (int)n.dist));
                Console.Write("#");
                Console.SetCursorPosition(cnt, frm + (10 - (int)n.dist));
                Console.Write("#");


                if (n.dist != lastn)
                {

                    for (int i = (frm - (10 - (int)n.dist)); i < (frm + (10 - (int)n.dist)); i++)
                    {
                        Console.SetCursorPosition(cnt, i);
                        Console.Write("|");
                    }

                }

                lastn = (int)n.dist;
            }


        }

        static void Main(string[] args)
        {




            double playerX = 2;
            double playerY = 2;
            double playerAngle = 45;
            Stack<Ray> stk1 = new Stack<Ray>();

            double slopeX = 0;
            double slopeY = 0;

            // create level
            int[,] level1 = new int[12, 12];
            for (int y = 0; y < 12; y++)
            {
                for (int x = 0; x < 12; x++)
                {

                    if ((x == 0) || (x == 11) || (y == 0) || (y == 11))
                    {
                        level1[x, y] = 1;
                    }
                }
            }

            level1[5, 5] = 2;
            level1[5, 6] = 2;
            level1[5, 7] = 2;
            level1[5, 8] = 2;
            level1[5, 9] = 2;
            level1[5, 10] = 2;
            level1[5, 11] = 2;

            level1[8, 8] = 3;






            while (true)
            {
                // user input
                string btn1 = Console.ReadLine();
                if (btn1 == "q")
                {


                    slopeX = Math.Cos(playerAngle * (3.14 / 180));
                    slopeY = Math.Sin(playerAngle * (3.14 / 180));
                    playerX += slopeX;
                    playerY += slopeY;

                }
                if (btn1 == "a")
                {

                    slopeX = Math.Cos(playerAngle * (3.14 / 180));
                    slopeY = Math.Sin(playerAngle * (3.14 / 180));
                    playerX -= slopeX;
                    playerY -= slopeY;

                }
                if (btn1 == "x")
                {
                    playerAngle -= 10;
                }
                if (btn1 == "z")
                {
                    playerAngle += 10;
                }


                // raster angle
                stk1.Clear();
                for (double j = playerAngle - 35; j < playerAngle + 35; j++)
                {


                    slopeX = Math.Cos(j * (3.14 / 180));
                    slopeY = Math.Sin(j * (3.14 / 180));
                    double xx = playerX;
                    double yy = playerY;

                    double dstcount = 0;

                    while (true)
                    {
                        xx += slopeX;
                        yy += slopeY;
                        dstcount++;
                        //if ((xx > 12) || (xx < 0) || (yy > 12) || (yy < 0)) { break; }
                        if (level1[(int)xx, (int)yy] > 0) { break; }
                    }

                    Ray ry1 = new Ray();
                    ry1.dist = dstcount;
                    ry1.col = level1[(int)xx, (int)yy];
                    stk1.Push(ry1);

                }



                Console.Clear();

                DrawWalls(stk1);


                Console.ForegroundColor = ConsoleColor.Red;
                for (int y = 0; y < 12; y++)
                {
                    for (int x = 0; x < 12; x++)
                    {
                        Console.SetCursorPosition(x, y);
                        if (level1[x, y] > 0)
                        {
                            Console.Write("#");

                        }
                        else
                        {
                            Console.Write(".");
                        }
                    }
                }

                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.SetCursorPosition((int)playerX, (int)playerY);
                Console.Write("X");

                Thread.Sleep(30);



            }





        }
    }
}