Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Drawing;
- using System.Windows.Forms;
- namespace Raycast {
- public class Raycaster : Form {
- #region Map info
- private const int MAPWIDTH = 24;
- private const int MAPHEIGHT = 24;
- private int[,] worldMap = new int[MAPHEIGHT, MAPWIDTH] {
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 2, 0, 1, 0, 2, 0, 0, 0, 0, 3, 0, 4, 0, 3, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 2, 2, 0, 2, 2, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 4, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 4, 0, 0, 0, 0, 5, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
- {1, 4, 0, 4, 0, 0, 0, 0, 4, 0, 0, 0, 0, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 1},
- {1, 4, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1},
- {1, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 3, 0, 0, 0, 2, 3, 0, 1},
- {1, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1},
- {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
- };
- #endregion
- #region Vars
- const double rotateMultiplier = 2, moveMultiplier = 2.5;
- double posX = 22, posY = 12;
- double dirX = -1, dirY = 0;
- double planeX = 0, planeY = 0.66;
- UInt32 time = 0, oldTime = 0;
- UInt32 startTick = (UInt32)Environment.TickCount;
- double rotSpeed = 0, moveSpeed = 0;
- bool goingLeft = false, goingRight = false, goingForward = false, goingBackward = false;
- #endregion Vars
- public Raycaster() {
- #region Setup form
- Width = 606; // Gives ClientRectangle width of 600
- Height = 428; // Gives ClientRectangle height of 400
- Text = "Raycaster";
- MaximizeBox = false;
- FormBorderStyle = FormBorderStyle.FixedSingle;
- StartPosition = FormStartPosition.CenterScreen;
- #endregion Setup form
- SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint |
- ControlStyles.OptimizedDoubleBuffer, true);
- }
- #region Overridden methods
- protected override void OnPaint(PaintEventArgs e) {
- double FPS = 0d;
- Bitmap buffer = new Bitmap(ClientRectangle.Width, ClientRectangle.Height);
- using (Graphics gfx = Graphics.FromImage(buffer)) {
- gfx.Clear(Color.White);
- double width = buffer.Width;
- double height = buffer.Height;
- // Check each column of the screen
- for (int x = 0; x < width; x++) {
- // Calculate ray position and direction
- double cameraX = 2 * x / width - 1; // X-coordinate in camera space
- double rayPosX = posX;
- double rayPosY = posY;
- double rayDirX = dirX + planeX * cameraX;
- double rayDirY = dirY + planeY * cameraX;
- // Get the actual map location
- int mapX = (int)rayPosX;
- int mapY = (int)rayPosY;
- // Length of ray from current position to next X- or Y-side
- double sideDistX;
- double sideDistY;
- // Length of ray from one X- or Y-side to next X- or Y-side
- double deltaDistX = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
- double deltaDistY = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
- double perpWallDist;
- // What direction to step in X or Y (+1 / -1)
- int stepX;
- int stepY;
- int hit = 0; // Was there a wall hit?
- int side = 0; // Was the hit NS or EW?
- // Calculate step and initial side distance
- if (rayDirX < 0) {
- stepX = -1;
- sideDistX = (rayPosX - mapX) * deltaDistX;
- } else {
- stepX = 1;
- sideDistX = (mapX + 1.0d - rayPosX) * deltaDistX;
- }
- if (rayDirY < 0) {
- stepY = -1;
- sideDistY = (rayPosY - mapY) * deltaDistY;
- } else {
- stepY = 1;
- sideDistY = (mapY + 1.0d - rayPosY) * deltaDistY;
- }
- // Perform DDA
- while (hit == 0) {
- // Jump to next map square, OR in X-direction, OR in Y-direction
- if (sideDistX < sideDistY) {
- sideDistX += deltaDistX;
- mapX += stepX;
- side = 0;
- }
- else {
- sideDistY += deltaDistY;
- mapY += stepY;
- side = 1;
- }
- // Check if ray has hit a wall
- if (worldMap[mapY, mapX] > 0) hit = 1;
- }
- // Calculate distance projected on camera direction
- // (oblique distance will give fisheye effect)
- if (side == 0)
- perpWallDist = Math.Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
- else
- perpWallDist = Math.Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
- // Calculate height of line to draw on screen
- int lineHeight = Math.Abs((int)(height / perpWallDist));
- // Calculate lowest and highest pixel to fill in current strip
- int drawStart = (int)(-lineHeight / 2 + height / 2);
- if (drawStart < 0) drawStart = 0;
- int drawEnd = (int)(lineHeight / 2 + height / 2);
- if (drawEnd >= height) drawEnd = (int)height - 1;
- // Choose wall color
- #region Wall color
- Pen color;
- switch (worldMap[mapY, mapX]) {
- case 1:
- if (side == 1)
- color = Pens.DarkRed;
- else
- color = Pens.Red;
- break;
- case 2:
- if (side == 1)
- color = Pens.DarkGreen;
- else
- color = Pens.Green;
- break;
- case 3:
- if (side == 1)
- color = Pens.DarkBlue;
- else
- color = Pens.Blue;
- break;
- case 4:
- if (side == 1)
- color = Pens.DarkGray;
- else
- color = Pens.Gray;
- break;
- default:
- color = Pens.LightGray;
- break;
- }
- #endregion Wall color
- // Draw the strip
- gfx.DrawLine(color, x, drawStart, x, drawEnd);
- }
- // Get timing for input and FPS
- oldTime = time;
- time = (UInt32)Environment.TickCount - startTick;
- double frameTime = (time - oldTime) / 1000.0d;
- FPS = 1.0d / frameTime;
- // Speed modifiers
- moveSpeed = frameTime * moveMultiplier;
- rotSpeed = frameTime * rotateMultiplier;
- }
- e.Graphics.DrawImageUnscaled(buffer, new Point(0, 0));
- e.Graphics.DrawString(((int)FPS).ToString() + " FPS",
- new Font("Consolas", 10f), Brushes.Black, new PointF(0, 0));
- e.Graphics.DrawString("Move Speed: " + moveSpeed,
- new Font("Consolas", 10f), Brushes.Black, new PointF(0, 12));
- e.Graphics.DrawString("Rotate Speed: " + rotSpeed,
- new Font("Consolas", 10f), Brushes.Black, new PointF(0, 24));
- MovePlayer();
- Invalidate();
- System.Threading.Thread.Sleep(10);
- }
- protected override void OnPaintBackground(PaintEventArgs e) { }
- protected override void OnKeyDown(KeyEventArgs e) {
- switch (e.KeyData) {
- case Keys.A:
- case Keys.Left:
- goingLeft = true;
- break;
- case Keys.D:
- case Keys.Right:
- goingRight = true;
- break;
- case Keys.W:
- case Keys.Up:
- goingForward = true;
- break;
- case Keys.S:
- case Keys.Down:
- goingBackward = true;
- break;
- case Keys.Escape:
- Application.Exit();
- break;
- }
- base.OnKeyDown(e);
- }
- protected override void OnKeyUp(KeyEventArgs e) {
- switch (e.KeyData) {
- case Keys.A:
- case Keys.Left:
- goingLeft = false;
- break;
- case Keys.D:
- case Keys.Right:
- goingRight = false;
- break;
- case Keys.W:
- case Keys.Up:
- goingForward = false;
- break;
- case Keys.S:
- case Keys.Down:
- goingBackward = false;
- break;
- }
- base.OnKeyUp(e);
- }
- #endregion Overridden methods
- protected void MovePlayer() {
- if (goingLeft && !goingRight) {
- double oldDirX = dirX;
- dirX = dirX * Math.Cos(rotSpeed) - dirY * Math.Sin(rotSpeed);
- dirY = oldDirX * Math.Sin(rotSpeed) + dirY * Math.Cos(rotSpeed);
- double oldPlaneX = planeX;
- planeX = planeX * Math.Cos(rotSpeed) - planeY * Math.Sin(rotSpeed);
- planeY = oldPlaneX * Math.Sin(rotSpeed) + planeY * Math.Cos(rotSpeed);
- } else if (goingRight && !goingLeft) {
- double oldDirX = dirX;
- dirX = dirX * Math.Cos(-rotSpeed) - dirY * Math.Sin(-rotSpeed);
- dirY = oldDirX * Math.Sin(-rotSpeed) + dirY * Math.Cos(-rotSpeed);
- double oldPlaneX = planeX;
- planeX = planeX * Math.Cos(-rotSpeed) - planeY * Math.Sin(-rotSpeed);
- planeY = oldPlaneX * Math.Sin(-rotSpeed) + planeY * Math.Cos(-rotSpeed);
- }
- if (goingForward && !goingBackward) {
- int newMapX = (int)(posX + dirX * moveSpeed);
- int newMapY = (int)(posY + dirY * moveSpeed);
- if (worldMap[(int)posY, newMapX] == 0)
- posX += dirX * moveSpeed;
- if (worldMap[newMapY, (int)posX] == 0)
- posY += dirY * moveSpeed;
- } else if (goingBackward && !goingForward) {
- int newMapX = (int)(posX - dirX * moveSpeed);
- int newMapY = (int)(posY - dirY * moveSpeed);
- if (worldMap[(int)posY, newMapX] == 0)
- posX -= dirX * moveSpeed;
- if (worldMap[newMapY, (int)posX] == 0)
- posY -= dirY * moveSpeed;
- }
- }
- /// <summary>
- /// The main entry point for the application.
- /// </summary>
- [STAThread]
- static void Main() {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(true);
- using (Raycaster rayc = new Raycaster())
- Application.Run(rayc);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement