Can someone help me fix my DDA collision algorithm in processing?

192 views Asked by At

I have been trying to make a DDA algorithm for a raycaster for a while now. For some reason I'm having a ton of trouble. The way my code works is that it puts a player into the map that spins at a constant rate. the green circle should be landing wherever the player is looking on the nearest wall. It seems to almost work when the line is more vertical than horizontal, but it still is a bit off. the moment it passes the y=x or y=-x line it goes crazy, seeming to shoot off into infinity. I suspect it has something to do with slope, but frankly I'm not really sure.

I have been following this video closely, but to no avail. I hope someone can spot the error in my code so I can continue with this project.

Here's a condensed version of my code:

int[][] map = {
    {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,1,1,1,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,1,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,1,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,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,1,0,0,0,0,0,0,0,0,0,0,0,1},
    {1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,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,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};

float fov;
Player p;
void setup() {
    size(800, 600);
    background(0);
    stroke(255);
    
    fov = PI/2;
    p = new Player(12.5, 12.5, -PI/4);
}

void draw() {
    background(0);
    p.map_();
    p.ddaTest4();
    p.dir += PI/512;
    p.dir %= TWO_PI;
}

class Player {
    float dir;
    PVector pos = new PVector();
    

    Player (float x, float y, float dir) {
        this.dir = dir;
        this.pos.x = x;
        this.pos.y = y;
    }

    // this draws the map array as rectangles
    void map_() {
        noStroke();
        float sf = height/map.length;
        for (int i = 0; i < map.length; i++) {
            for (int j = 0; j < map.length; j++) {
                
                if (map[j][i] != 0) {
                    stroke(0);
                    fill(255);
                    rect(i*sf, j*sf, height/sf, height/sf);
                } else {
                    stroke(255);
                    fill(0);
                    rect(i*sf, j*sf, height/sf, height/sf);
                }
            }
        }
    }

    void ddaTest4() {
        float sf = height/map.length;
        PVector rayDir = PVector.fromAngle(dir);
        PVector stepScale  = new PVector(sqrt(((rayDir.y/rayDir.x) * (rayDir.y/rayDir.x)) + 1), sqrt(((rayDir.x/rayDir.y) * (rayDir.x/rayDir.y)) + 1));

        PVector mapPos = new PVector((int)pos.x, (int)pos.y);
        PVector rayLength = new PVector();

        PVector step = new PVector(1, 1);

        if (rayDir.x < 0) {
            step.x = -1;
            rayLength.x = (pos.x - mapPos.x) * stepScale.x;
        } else {
            rayLength.x = ((mapPos.x + 1) - mapPos.x) * stepScale.x;
        }
        if (rayDir.y < 0) {
            step.y = -1;
            rayLength.x = (pos.y - mapPos.y) * stepScale.y;
        } else {
            rayLength.x = ((mapPos.y + 1) - mapPos.y) * stepScale.y;
        }

        boolean hit = false;
        float distance = 0;
        while(!hit) {
            if (rayLength.x < rayLength.y) {
                mapPos.x += step.x;
                distance = rayLength.x;
                rayLength.x += stepScale.x;
            } else {
                mapPos.y += step.y;
                distance = rayLength.y;
                rayLength.y += stepScale.y;
            }

            if (map[(int)mapPos.y][(int)mapPos.x] != 0) {
                hit = true;
            }
        }

        PVector hitPoint = PVector.add(pos, PVector.mult(rayDir, distance));
        fill(0, 255, 0);
        stroke(0, 255, 0);
        line(pos.x*sf, pos.y*sf, hitPoint.x*sf, hitPoint.y*sf);
        ellipse(hitPoint.x*sf, hitPoint.y*sf, 5, 5);
    }
    
}

PS: sorry if I have poorly phrased my question, I'm not really sure how else to put it.

0

There are 0 answers