Skip to content

Instantly share code, notes, and snippets.

@rdeioris
Created May 29, 2019 13:53
Show Gist options
  • Save rdeioris/b3e80b88487d18bce8c58444b3591999 to your computer and use it in GitHub Desktop.
Save rdeioris/b3e80b88487d18bce8c58444b3591999 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aiv.Fast2D;
using OpenTK;
namespace Raycasting1B
{
class Program
{
static void Main(string[] args)
{
Window window = new Window(800, 800, "Raycasting");
window.SetDefaultOrthographicSize(20);
Sprite player = new Sprite(2, 2);
Sprite enemy = new Sprite(3, 3);
enemy.position = new Vector2(10, 11);
Ray ray = new Ray();
Vector2 aim = Vector2.Zero;
while (window.IsOpened)
{
// manage input
if (window.GetKey(KeyCode.D))
player.position += new Vector2(3, 0) * window.deltaTime;
if (window.GetKey(KeyCode.A))
player.position += new Vector2(-3, 0) * window.deltaTime;
if (window.GetKey(KeyCode.W))
player.position += new Vector2(0, -3) * window.deltaTime;
if (window.GetKey(KeyCode.S))
player.position += new Vector2(0, 3) * window.deltaTime;
if (window.GetKey(KeyCode.Right))
aim += new Vector2(3, 0) * window.deltaTime;
if (window.GetKey(KeyCode.Left))
aim += new Vector2(-3, 0) * window.deltaTime;
if (window.GetKey(KeyCode.Up))
aim += new Vector2(0, -3) * window.deltaTime;
if (window.GetKey(KeyCode.Down))
aim += new Vector2(0, 3) * window.deltaTime;
// compute ray coordinates
ray.Origin = player.position + new Vector2(player.Width, player.Height * 0.5f);
ray.SetDirection(new Vector2(1, 1), 8);
ray.End += aim;
// check collision
bool isIntersecting = ray.Intersects(enemy.position, enemy.Width, enemy.Height);
// draw
player.DrawSolidColor(255, 0, 0);
if (isIntersecting)
{
enemy.DrawSolidColor(255, 0, 255);
}
else
{
enemy.DrawSolidColor(0, 0, 255);
}
ray.Draw();
window.Update();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aiv.Fast2D;
using OpenTK;
namespace Raycasting1B
{
public class Ray
{
public Vector2 Origin;
public Vector2 End;
private Sprite sprite;
private float t0;
private float t1;
private bool isIntersecting;
public Ray()
{
Origin = Vector2.Zero;
End = Vector2.Zero;
sprite = new Sprite(0.1f, 0.1f);
}
public Ray(Vector2 origin, Vector2 end) : this()
{
Origin = origin;
End = end;
}
public Ray(Vector2 origin, Vector2 direction, float length) : this()
{
Origin = origin;
SetDirection(direction, length);
}
public void SetDirection(Vector2 direction, float length)
{
End = Origin + (direction.Normalized() * length);
}
public void Draw()
{
float gradient = 0;
while (gradient <= 1)
{
sprite.position = Vector2.Lerp(Origin, End, gradient);
gradient += 0.01f;
if (isIntersecting && gradient >= t0 && gradient <= t1)
{
sprite.DrawSolidColor(0, 255, 0);
}
else
{
sprite.DrawSolidColor(255, 255, 0);
}
}
}
/* Liang - Barsky
* x = x0 + (x1 - x0) * m
* y = y0 + (y1 - y0) * m
*
* m == 0 -> x0, y0
* m == 1 -> x1, y1
*
* left <= x <= right
* top <= y <= bottom
*
* left <= x0 + (x1 - x0) * m <= right
* top <= y0 + (y1 - y0) * m <= bottom
*
* - (x1 - x0) * m <= x0 - left
* (x1 - x0) * m <= right - x0
*
* - (y1 - y0) * m <= y0 - top
* (y1 - y0) * m <= bottom - y0
*
* dx = (x1 - x0) // deltaX in code
* dy = (y1 - y0) // deltaY in code
*
* -dx * m <= x0 - left
* dx * m <= right - x
*
* -dy * m <= y0 - top
* dy *m <= bottom - y0
*
* mLeft <= (x0 - left) / (-dx)
* mRight <= (right -x0) / (dx)
* mTop <= (y0 - top) / (-dy)
* mBottom <= (bottom - y0) / (dy)
*
* p = -dx
* q = (x0 - left)
*
*
*/
public bool Intersects(Vector2 leftTop, Vector2 rightBottom)
{
float deltaX = (End.X - Origin.X);
float deltaY = (End.Y - Origin.Y);
t0 = 0;
t1 = 1;
isIntersecting = false;
for (int i = 0; i < 4; i++)
{
float p = 0;
float q = 0;
// mLeft <= (x0 - left) / (-dx)
if (i == 0)
{
p = -deltaX;
q = Origin.X - leftTop.X;
}
// mRight <= (right - x0) / (dx)
else if (i == 1)
{
p = deltaX;
q = rightBottom.X - Origin.X;
}
// mTop <= (y0 - top) / (-dy)
else if (i == 2)
{
p = -deltaY;
q = Origin.Y - leftTop.Y;
}
// mBottom <= (bottom - y0) / (dy)
else if (i == 3)
{
p = deltaY;
q = rightBottom.Y - Origin.Y;
}
if (p == 0 && q < 0) // fast exit if the line is parallel and out of the limit
return false;
float m = q / p;
if (p < 0)
{
if (m > t1) return false; // check if the gradient is over the line higher limit
else if (m > t0) t0 = m;
}
else if (p > 0)
{
if (m < t0) return false;// check if the gradient is below the line lower limit
else if (m < t1) t1 = m;
}
}
isIntersecting = true;
return true;
}
public bool Intersects(Vector2 leftTop, float width, float height)
{
return Intersects(leftTop, new Vector2(leftTop.X + width, leftTop.Y + height));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment