JavaScript 中的直线交点?

Line Line intersection in JavaScript?

我正在做一个ray caster,我需要检测射线是否与墙段相交,

我有每个顶点的坐标,有人知道这样做的方法吗?

我已经查过了,但我还没有找到任何可以帮助我的东西,

所以我在这里问。代码如下(使用wasd测试):

<!DOCTYPE html>
<html>
    <head>
        <title>Page Title</title>
    </head>
    <body>
 
    <canvas width="500px" height="500px" id="c"></canvas>   
    </body>
    <script>
        
        c = document.getElementById("c");
        w = c.width;
        h = c.height;
        ctx = c.getContext("2d");
        var tilesize = 50;
    var walls = [];
    var rays = [];
    rayangle = 1;
    lowrayangle = -1;
 
 
        var player = {
            x : 80,
            y: 80,
            size : 10,
            speed: 1,
            dir: 0,
      rot: 0,
      rotSpeed: 0.05,
      rotDir: 0,
        }
 
 
        var map = [
            [1,1,1,1,1,1,1,1,1,1,],
            [1,0,0,0,0,0,0,0,0,1,],
            [1,0,1,1,0,0,0,0,0,1,],
            [1,0,1,1,0,0,0,0,0,1,],
            [1,0,0,0,0,0,0,0,0,1,],
            [1,0,0,0,0,0,0,0,0,1,],
            [1,0,0,0,0,0,1,0,0,1,],
            [1,0,0,0,0,0,1,0,0,1,],
            [1,0,0,0,0,0,1,0,0,1,],
            [1,1,1,1,1,1,1,1,1,1,]
            ]
            
 
      for(y = 0;y < map.length;y++){
                    for(x = 0;x < map[y].length;x++){
 
                    ctx.fillStyle = ["white", "black"][map[y][x]];
                    ctx.fillRect(x * tilesize, y * tilesize, tilesize, tilesize);
 
                    if(map[y][x] == 1){
                      var wallSeg = {
                        coordX : x * tilesize,
                        coordY : y * tilesize,
                        sizeX : tilesize,
                        sizeY : 0,
                      }
                      var wallSeg2 = {
                        coordX : x * tilesize,
                        coordY : y * tilesize,
                        sizeX : 0,
                        sizeY : tilesize,
                      }
                      var wallSeg3 = {
                        coordX : x * tilesize,
                        coordY : (y * tilesize)+tilesize,
                        sizeX : tilesize,
                        sizeY : 0,
                      }
                      var wallSeg4 = {
                        coordX : (x * tilesize) + tilesize,
                        coordY : y * tilesize,
                        sizeX : 0,
                        sizeY : tilesize,
                      }
                      walls.push(wallSeg)
                      walls.push(wallSeg2)
                      walls.push(wallSeg3)
                      walls.push(wallSeg4)
 
                    }
                    }    
                }
        
 
            
 
            function keydown(event){
                switch(event.keyCode){
                    case 87:
                        player.dir = 1;
                    break;
                    case 83:
                        player.dir = -1;
                    break;
          case 68:
                        player.rotDir = -1;
                    break;
                    case 65:
                        player.rotDir = 1;
                    break;
                }
 
            }
            function keyup(event){
                switch(event.keyCode){
                    case 87:
                        player.dir = 0;
                    break;
                    case 83:
                        player.dir = 0;
                    break;
          case 68:
                        player.rotDir = 0;
                    break;
                    case 65:
                        player.rotDir = 0;
                    break;
                }
 
            }
        
            var gameloop = setInterval(function(){
                ctx.clearRect(0,0,w,h);
        rays = [];
                //move
        
 
        rotstep = player.rotSpeed * player.rotDir
                movestep = player.speed * player.dir;
        player.rot += rotstep;
        rayangle += rotstep;
        lowrayangle += rotstep;
        newY = player.y - Math.cos(player.rot) * movestep;
        newX = player.x - Math.sin(player.rot) * movestep;
 
        leftbY = (player.y - 10) - Math.cos(player.rot) * movestep;
        leftbX = (player.x - 10) - Math.sin(player.rot) * movestep;
        rightbY = (player.y + 10) - Math.cos(player.rot) * movestep;
        rightbX = (player.x + 10) - Math.sin(player.rot) * movestep;
                //borders 
                 var leftcol = Math.floor((leftbX)/tilesize)
         var leftrow = Math.floor((leftbY)/tilesize)
         var rightcol = Math.floor((rightbX)/tilesize)
         var rightrow = Math.floor((rightbY)/tilesize)
         if(map[rightcol][rightrow] == 0 && map[leftcol][leftrow] == 0 ){
            player.y = newY;
            player.x = newX;
         }
         
                //map
                for(y = 0;y < map.length;y++){
                    for(x = 0;x < map[y].length;x++){
 
                    ctx.fillStyle = ["white", "black"][map[y][x]];
                    ctx.fillRect(x * tilesize, y * tilesize, tilesize, tilesize);
 
                    }
                    }    
                
        
 
        //rays  
 
        for(i=lowrayangle;i<rayangle;i+= 0.1){
          var ray = {
            rayAngle : i,
            newY : player.y - Math.cos(i) * 1000,
            newX : player.x - Math.sin(i) * 1000,
            x : player.x,
            y : player.y
          }
          rays.push(ray)
        }
        for(i=0;i<rays.length;i++){
          ctx.beginPath();
          ctx.moveTo(rays[i].x,rays[i].y)
          ctx.lineTo(rays[i].newX,rays[i].newY)
          ctx.stroke();
        }
                //player
        markerY = player.y - Math.cos(player.rot) * 30;
        markerX = player.x - Math.sin(player.rot) * 30;
                ctx.fillStyle = "red";
                ctx.beginPath();
        ctx.ellipse(player.x, player.y, player.size, player.size, player.rot * (Math.PI/180), 0, 2 * Math.PI);
        ctx.fill();
        //marker
        ctx.beginPath();
        ctx.moveTo(player.x,player.y)
        ctx.lineTo(markerX,markerY)
        ctx.strokeStyle = "Black"
        ctx.stroke();
 
            },1000/30)
 
            document.addEventListener("keydown",function(event){
                keydown(event);
            })
      document.addEventListener("keyup",function(event){
                keyup(event);
            })
 
    </script>
</html>

for(i=lowrayangle;i<rayangle;i+= 0.1){
      var distantCheck = 1000;
      var detail = 5;
      var memoryX;
      var memoryY;

      var xLength;
      var yLength;
      for(var j =0;j<distantCheck;j+=detail){

        xLength = player.y - Math.cos(i) * j;
        yLength= player.x - Math.sin(i) * j;

        memoryY = xLength;
        memoryX = yLength;

        xLength = xLength -(xLength%tilesize); 
        yLength = yLength -(yLength%tilesize);


        if(map[yLength/tilesize][xLength/tilesize]==1){
          break;
        }
      }
      var ray = {
        rayAngle : i,
        newY : memoryY,
        newX : memoryX,
        x : player.x,
        y : player.y
      }
      rays.push(ray)
    }