I'v been trying and studying a hell of a lot for making my 2D raycasting, I'v been visiting KahnAcademy for Trigonometry-lessons as well as reading various topics ( each with a completely different method of achieving it. )

Currently I'm just trying to get the ray-casting and movement to work, so far so good, almost.I'm not entirely sure of how to do the casting, but I got something almost working, though it's a bit off. Here is how it looks so far:

The blue/magenta arrow is the direction the player will travel ( current angle ) and the white rays are supposed to be the ray-casting, as you can see it's off by quite a bit and I can't understand why.

1. Why do you multiply by -d and not just d ( distance ) when calculating with sin and cos?2. Does this technique look right considering it's supposed to transition into fake 3D using 2D raycasting ( Given that the final ray distance is determined on where it hit a wall ).

Kind regardsMoonkis

EDIT:

Realized that the offset was due to me accidentally subtracting the subsequent ray angle when calculating the offset using players FOVChanged it from this:

It seems to work as intended now, checked using 90, 180, 270 and 360 FOV angles. ( 180 and 90 was the ones I based it on working, they looked as intended, also added some wrapping when calculated angles for the rx and ry:

Whether you multiply by d or -d and whether you use cosine for x or for y depends on the conventions you are using. I would stick to trigonometric conventions as much as possible, where angle 0 points in the positive x direction, and angles go up counterclockwise.

I don't think you need nearly as much trigonometry as you are using. The pixel columns on your screen don't cover a constant angle: The center column covers a larger angle than the column on the far right. Imagine you have a very large screen compared to the distance you are sitting from it and it will be obvious.

The way I think about this, the player is looking in some direction (cos(player.rot),sin(player.rot)), which I'll call (x,y) for short. Now you can compute an equally-spaced sequence of points from (x,y)-K*(y,-x) to (x,y)+K*(y,-x) and launch rays in those directions. K is a constant that you can compute as tan(FOV/2).

By the way, as part of my crusade against angles, you can store the direction in which the player is looking as (x,y) directly, instead of an angle. And I even prefer to specify K directly instead of FOV. But start by getting your code working.

You didn't post all your code, so I don't know if this is biting anywhere, but you should really use the intended type for every variable. That variable should be a double instead of an int. Getting the type wrong could result in expressions like player.fov/w being truncated, if player.fov and w happen to be integers.

Whether you multiply by d or -d and whether you use cosine for x or for y depends on the conventions you are using. I would stick to trigonometric conventions as much as possible, where angle 0 points in the positive x direction, and angles go up counterclockwise.

Well I just based on what angles I got from 0, 90, 180 and 270, isn't this the trigonometric conventions?

I don't think you need nearly as much trigonometry as you are using. The pixel columns on your screen don't cover a constant angle: The center column covers a larger angle than the column on the far right. Imagine you have a very large screen compared to the distance you are sitting from it and it will be obvious.

This dosn't tell me much :/

The way I think about this, the player is looking in some direction (cos(player.rot),sin(player.rot)), which I'll call (x,y) for short. Now you can compute an equally-spaced sequence of points from (x,y)-K*(y,-x) to (x,y)+K*(y,-x) and launch rays in those directions. K is a constant that you can compute as tan(FOV/2).

I have no clue why that works. Or how it works, Or in what context to use it.

By the way, as part of my crusade against angles, you can store the direction in which the player is looking as (x,y) directly, instead of an angle. And I even prefer to specify K directly instead of FOV. But start by getting your code working.

I get that your against angles by now, but your crusade is not really helping me understand it, sorry. It just confuses me more :/Sorry.

Well, the way you are increasing the angle in the code you posted, seems to indicate that each column on the screen covers an equal angle from the eye, which is not true unless you have a cylindrical screen and you sit at the axis of the cylinder (which would be totally cool ;) ). If your screen is closer to a flat surface, you should do something like what I describe.

We seem to have trouble communicating, but I can think of a way to move forward: Come up with a specific example (player is here, looking in this direction, FOV is 45 degrees... whatever). Then I can walk you through what the code should do and why.

My distaste for angles is not capricious. I actually started writing graphics programs with angles everywhere, and over the years I have learned to think in terms of vectors instead, which made my code cleaner, faster and easier to get right. I hope my crusade will actually help you. But we'll see.

I edited my original post, I got the ray-casting aligning but I'm more than interested in getting a lesson and answers on my question, once I get into the part where my rays are supposed to render a fake 3D image I can't afford to have it done wrong in the beginning.

Okey so here is an example:

Object A is facing straight up ( towards the top of the screen ) and is currently at (400, 300) where the screen size is 800x600. Object A's FOV is 60 Degrees and needs the rays to identify whether there are objects in his line of sight.

Is this enough of information?
Also please when using tan and sin just quickly mention what it does and what it's for so I can have a context of it.

You seem to be using the coordinates of the screen directly, with (0,0) being the top-left corner. Notice that in those coordinates, an increase in y goes down, while the convention used in Math is that an increase in y goes up. This explains why you need to negate the sin(...) part. The sign of the cos(...) part should be positive, but your particular test is symmetric, so you haven't noticed the problem yet.

I will use traditional Math convention for everything. I will also assume the player is at (0,0) to simplify things. If your player is facing straight up, I guess player.rot = 90 degrees. You can draw an arrow of length 1 from the origin pointing in that direction, it will have coordinates (0,1). In general the coordinates are (cos(player.rot), sin(player.rot)). The length of 1 is arbitrary. If it helps you visualize it better, you can think of it as an arrow of length 100, which would have coordinates (0,100). In the end that factor of 100 won't matter. From now on, let this vector be (x,y).

Now I am going to draw a segment that represents the screen (I assume we are viewing the whole thing from the top of the scene). It will be a segment that is perpendicular to (0,1). You can find a direction that is perpendicular to (a,b) by computing (-b,a) (that's a rotation of 90 degrees counterclockwise). In our case, we'll get (-1,0). The segment I will draw will have (0,1) as the center and the left end will be at a point (0,1)+K*(-1,0). Reminder: That notation means (0+K*(-1),1+K*0) = (-K,1). The other end will be (0,1)-K*(-1,0), which is (K,1). I don't know what K is yet, but it will depend on FOV somehow.

So let's compute K. If you have been making a drawing of this (which you should), you can look at the triangle formed by the origin (0,0), the center of my "screen segment" (0,1) and the far right end of my screen segment (K,1). This triangle is rectangle at (0,1), and I am interested in the angle at the origin, which should be FOV/2 = 30 degrees. The tangent of that angle can be computed as "opposite side / adjacent side", which is K/1. That tells me that K/1 = tan(30 degrees) = 0.57735, and that's how I compute K.

I don't have a complete program to play with, so there might be mistakes in that code. If it doesn't work and it's not trivial to fix, I'll try to post a complete program, but this will probably need to wait until tonight.

If you have been making a drawing of this (which you should), you can look at the triangle formed by the origin (0,0), the center of my "screen segment" (0,1) and the far right end of my screen segment (K,1).

How can I do that? I have no idea where the point(K,1) is? Since we haven't computed it.

Here is what I drew up until that point:EDIT 2: I'm not sure if we are using cartesian-coordinate system or normal math one?

What exactly is distance_to_screen? and also your using player like a struct then telling me player is a vector representing the origin of the player?

EDIT:

On a second note maybe one thing should be clarified as well:1. "The pixel columns on your screen don't cover a constant angle" - I'm not 100% sure I get that statement, maybe a picture ( when you have time of course! ) along with words could help straighten that out.

PS. I'm so sorry for getting this slow, and that you take a lot of time explaining it to me.

If you have been making a drawing of this (which you should), you can look at the triangle formed by the origin (0,0), the center of my "screen segment" (0,1) and the far right end of my screen segment (K,1).

How can I do that? I have no idea where the point(K,1) is? Since we haven't computed it.

Dude, in the next sentence after what you quote I tell you myself that we don't know what K is yet, and than I have a paragraph devoted to describing how to compute K. You need to work on your reading comprehension.

I'm guessing 200.0f is the distance to draw the rays, 400.0f is the center of the map, and so is 300.0f?

float const degrees = std::atan(1.0f)/45.0f;

What exactly are the values used here? What does 1 and 45 represent?

float K = std::tan(30.0f*degrees);

What exactly is 30 representing in the code? Is it the same 30? for all the 30's in the code?

sf::Vector2f left(-heading.y, heading.x);

Why is the y and x inverted?

sf::Vector2f step = -(2.0f * K / width) * left ;

I have no idea what this is.

sf::Vector2f ray_end = left_edge + step * (i+0.5f);

What exactly is end here and what is the number 0.5 coming from.

Also in the drawing exercise before what coordination system are we using? Polar or Cartesian? I'd love to be able to draw It sucessfully since that might just be the key to being able to visualise it manually.

I'm guessing 200.0f is the distance to draw the rays, 400.0f is the center of the map, and so is 300.0f?

400.0f and 300.0f are indeed the center of the screen. I am using coordinates like I would in Math everywhere in the program and this is the function that translates them into screen coordinates. 200.0f is a scale factor, so the window covers the interval (-2, 2) horizontally and (-1.5, +1.5) vertically.

float const degrees = std::atan(1.0f)/45.0f;

What exactly are the values used here? What does 1 and 45 represent?

The angle whose tan is 1 is 45 degrees, so by multiplying a number of degrees by this number, you turn it into radians.

float K = std::tan(30.0f*degrees);

What exactly is 30 representing in the code? Is it the same 30? for all the 30's in the code?

30.0f if half the FOV of 60 degrees.

sf::Vector2f left(-heading.y, heading.x);

Why is the y and x inverted?

I think I covered this one already: This is just a 90-degree rotation of the heading vector.

sf::Vector2f step = -(2.0f * K / width) * left ;

I have no idea what this is.

That's how much I need to advance for each pixel.

sf::Vector2f ray_end = left_edge + step * (i+0.5f);

What exactly is end here and what is the number 0.5 coming from.

I think of the ray as an arrow, with a beginning (the player's position) and an end. The 0.5 is there so the ray aims to the center of the pixel, instead of the left side.

Also in the drawing exercise before what coordination system are we using? Polar or Cartesian? I'd love to be able to draw It sucessfully since that might just be the key to being able to visualise it manually.

I have only used Cartesian coordinates everywhere. Maybe I'll try to make a picture, but it's a bit of a pain.