显示屏幕外项目的SVG视图框

时间:2016-12-14 20:28:36

标签: javascript html css html5 svg

我正在使用图片的svg标签在HTML5中制作游戏,以提供多分辨率显示。大部分游戏都是完整的,但在测试中我遇到了一个主要的错误,它涉及到SVG对象可见,尽管在非原生分辨率的视图框之外。我不确定这是我的代码中的缺陷,还是浏览器本身(Google Chrome 54.0.2840.99 m(64位)和57.0.2950.0(官方构建)金丝雀(64位))。我不得不使用谷歌浏览器,因为我在项目中使用WebSQL(它不是在许多主流浏览器中)。

该项目是一个自上而下的滚动迷宫游戏,阴影是通过光线投影填充的多边形从形状顶点绘制的。只有当它们“附着”的一个或多个顶点在屏幕上时才会绘制阴影。问题在于,当我降低分辨率(我的默认值为1366 x 768)时,它们不会像通常那样绘制到屏幕的顶部/底部。bad SVG它应该是这样的。{{3} }

以下是我的代码的主要缩减版本。我假设如果有错误,在我的代码中,它将在shadowrays()函数内。通常,程序将以全屏模式(F11)运行,以确保它与窗口大小相同。要移动屏幕,请使用w,a,s和d键

window.setInterval(function() {
  if (draw) {
    if (keystate[controls[2]]) {
      xvelocity -= 2;
    }
    if (keystate[controls[3]]) {
      xvelocity += 2;
    }
    xvelocity = xvelocity * 0.93;
    xscroll += xvelocity;
    svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
    centerplayer();
    if (checkcollision()) {
      xscroll -= xvelocity;
      xvelocity = xvelocity * -0.8;
    }
    if (keystate[controls[0]]) {
      yvelocity += 2;
    }
    if (keystate[controls[1]]) {
      yvelocity -= 2;
    }
    yvelocity = yvelocity * 0.93;
    yscroll -= yvelocity;
    svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
    centerplayer();
    if (checkcollision()) {
      yscroll += yvelocity;
      yvelocity = yvelocity * -0.8;
    }
    shadowrays();
  }
}, 16.666666666666667);
var keystate = {};
window.addEventListener("keydown", function(e) {
  if (!(((e.keycode || e.which) > 111) && ((e.keyCode || e.which) < 124))) {
    keystate[e.keycode || e.which] = true;
  }
}, true);
window.addEventListener("keyup", function(e) {
  keystate[e.keycode || e.which] = false;
}, true);

function shadowrays() {
  var kill = document.getElementsByClassName("shadowray");
  while (kill[0]) {
    kill[0].parentNode.removeChild(kill[0]);
  }
  var len = level.length,
    shape = {},
    points = [],
    poly = [],
    p1x, p2x, p1y, p2y, p3x, p3y, p4x, p4y, p5x, p5y, p6x, p6y, cx = player.cx.animVal.value,
    cy = player.cy.animVal.value,
    m, i, n;
  for (i = 1; i < len; i += 1) {
    shape = level[i];
    points = [shape.x, shape.y, shape.x, shape.y + shape.height, shape.x + shape.width, shape.y + shape.height, shape.x + shape.width, shape.y];
    for (n = 0; n < 4; n += 1) {
      p1x = points[(n * 2) % 8];
      p2x = points[(n * 2 + 2) % 8];
      p1y = points[(n * 2 + 1) % 8];
      p2y = points[(n * 2 + 3) % 8];
      if ((((Math.abs(p1x - cx) <= dimensions.width / 2) || (Math.abs(p2x - cx) <= dimensions.width / 2)) && ((Math.abs(p1y - cy) <= dimensions.height / 2) || (Math.abs(p2y - cy) <= dimensions.height / 2))) && shape.id != "enclosure") {
        m = (p1y - cy) / (p1x - cx);
        p6y = m * (cx + dimensions.width / 2 * (Math.abs(p1x - cx) / (p1x - cx))) - m * cx + cy;
        if (Math.abs(p6y - cy) <= dimensions.height / 2) {
          p6x = (p6y - cy) / m + cx;
          p5x = p6x;
          p5y = cy + dimensions.height / 2 * (Math.abs(p6y - cy) / (p6y - cy));
        } else {
          p6y = cy + dimensions.height / 2 * (Math.abs(p6y - cy) / (p6y - cy));
          p6x = (p6y - cy) / m + cx;
          p5x = cx + dimensions.width / 2 * (Math.abs(p6x - cx) / (p6x - cx));
          p5y = p6y;
        }
        m = (p2y - cy) / (p2x - cx);
        p3y = m * (cx + dimensions.width / 2 * (Math.abs(p2x - cx) / (p2x - cx))) - m * cx + cy;
        if (Math.abs(p3y - cy) <= dimensions.height / 2) {
          p3x = (p3y - cy) / m + cx;
          p4x = p3x;
          p4y = cy + dimensions.height / 2 * (Math.abs(p3y - cy) / (p3y - cy));
        } else {
          p3y = cy + dimensions.height / 2 * (Math.abs(p3y - cy) / (p3y - cy));
          p3x = (p3y - cy) / m + cx;
          p4x = Number(cx) + Number(dimensions.width) / 2 * (Math.abs(p3x - cx) / (p3x - cx));
          p4y = p3y;
        }
        poly = [];
        poly.push(p1x + ',' + p1y, p2x + ',' + p2y, p3x + ',' + p3y, p4x + ',' + p4y, p5x + ',' + p5y, p6x + ',' + p6y);
        createpolygon(poly, "", ("s" + i + n), "shadowray");
      }
    }
  }
}

function createpolygon(points, filter, id, classt) {
  var polygon = document.createElementNS(svgns, "polygon"),
    data_points = "",
    max = points.length,
    z;
  polygon.setAttributeNS(null, "id", "p" + id);
  for (z = 0; z < max; z += 1) {
    data_points += points[z] + " ";
  }
  polygon.setAttributeNS(null, "points", data_points);
  if (filter !== "") {
    polygon.setAttributeNS(null, "filter", filter);
  }
  polygon.setAttributeNS(null, "class", classt);
  svg.appendChild(polygon);
}

function centerplayer() {
  player.setAttributeNS(null, "cx", (xscroll + dimensions.width / 2));
  player.setAttributeNS(null, "cy", (yscroll + dimensions.height / 2));
  var hitbox = document.getElementById("rhb");
  hitbox.setAttributeNS(null, "width", player.r.animVal.value * 2);
  hitbox.setAttributeNS(null, "height", player.r.animVal.value * 2);
  //            var hitboxbbox = hitbox.getBBox();
  hitbox.setAttributeNS(null, "transform", ("translate(" + (xscroll + dimensions.width / 2 - player.r.animVal.value) + ", " + (yscroll + dimensions.height / 2 - player.r.animVal.value) + ")"));
}

function draw(lvl) {
  var objects = lvl.length,
    i;
  xscroll = Number(lvl[0].xspawn);
  yscroll = Number(lvl[0].yspawn);
  xvelocity = 0;
  yvelocity = 0;
  for (i = 1; i < objects; i += 1) {
    var object = lvl[i];
    if (object.type == "rect") {
      createrectangle(object.x, object.y, object.width, object.height, "", object.id, object.class);
    } else if (object.type == "circle") {
      createcircle(object.x, object.y, object.r, "", object.id, object.class);
    } else if (object.type == "polygon") {
      createpolygon(object.points, "", object.id, object.class);
    }
  }
  createcircle("7680", "4320", "50", "", "player", "st1");
  createrectangle("0", "0", "100", "100", "", "hb", "st2");
  createrectangle(lvl[0].xexit - 50, lvl[0].yexit - 50, "100", "100", "", "exit", "exit");
  drawn = true;
}

function createcircle(posx, posy, radius, filter, id, classt) {
  var circle = document.createElementNS(svgns, "circle");
  circle.setAttributeNS(null, "id", "c" + id);
  circle.setAttributeNS(null, "cx", posx);
  circle.setAttributeNS(null, "cy", posy);
  circle.setAttributeNS(null, "r", radius);
  if (filter !== "") {
    circle.setAttributeNS(null, "filter", filter);
  }
  circle.setAttributeNS(null, "class", classt);
  svg.appendChild(circle);
}

function createrectangle(posx, posy, width, height, filter, id, classt) {
  var rectangle = document.createElementNS(svgns, "rect");
  rectangle.setAttributeNS(null, "id", "r" + id);
  rectangle.setAttributeNS(null, "x", posx);
  rectangle.setAttributeNS(null, "y", posy);
  rectangle.setAttributeNS(null, "width", width);
  rectangle.setAttributeNS(null, "height", height);
  if (filter !== "") {
    rectangle.setAttributeNS(null, "filter", filter);
  }
  rectangle.setAttributeNS(null, "class", classt);
  svg.appendChild(rectangle);
}

var svg = document.getElementById("canvas"), //the svg element
  dimensions = {
    width: 1920,
    height: 1080
  }, //view dimensions
  svgns = "http://www.w3.org/2000/svg", //the SVG name space address
  player, //player is used later in game
  level, xvelocity, yvelocity, xscroll, yscroll, //current level, speeds and positions
  controls = ["87", "83", "65", "68", "32"],
  drawn = false;

function checkcollision() {
  var r = player.r.animVal.value,
    frame = document.getElementById("renclosure").getBBox(),
    i;
  if ((player.cx.animVal.value < r) || (player.cy.animVal.value < r) || (player.cx.animVal.value > frame.width - r) || (player.cy.animVal.value > frame.height - r)) {
    return true;
  }
  var collisions = [],
    len, r0 = document.getElementById("rhb").getBoundingClientRect(),
    r1 = svg.createSVGRect();
  r1.x = r0.left;
  r1.y = r0.top;
  r1.width = r0.width;
  r1.height = r0.height;
  var collisions_node = svg.getIntersectionList(r1, null);
  len = collisions_node.length;
  for (i = 0; i < len; i += 1) {
    collisions.push(collisions_node[i]);
  }
  for (i = len - 1; i >= 0; i -= 1) {
    if (collisions[i].id == "renclosure" || collisions[i].id == "cplayer" || collisions[i].id == "rpain" || collisions[i].id == "rhb" || collisions[i].className.animVal == "shadowray") {

      collisions.splice(i, 1);
    } else if (collisions[i].id == "rexit") { //winner
      //DO STUFF
    }
  }
  if (collisions.length > 0) {
    return true;
  } else {
    return false;
  }
}

level = [{
  "id": "l0",
  "name": "pretty", //level name
  "description": "oooooo shadows", //desciption
  "xspawn": 0, //where the player starts
  "yspawn": 0,
  "xexit": 2200, //where the exit it
  "yexit": 2200,
  "bits": 50 //umber of qbits in the level
}, {
  id: "enclosure", //shape id
  type: "rect", //shape type
  x: 0, //top left x
  y: 0, //top left y
  class: "obstacle_box", //class for style
  width: 5760, //width
  height: 2160 //height
}, {
  id: "1",
  type: "rect",
  x: 150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "2",
  type: "rect",
  x: 350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "3",
  type: "rect",
  x: 550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "4",
  type: "rect",
  x: 750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "5",
  type: "rect",
  x: 950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "6",
  type: "rect",
  x: 1150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "7",
  type: "rect",
  x: 1350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "8",
  type: "rect",
  x: 1550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "9",
  type: "rect",
  x: 1750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "10",
  type: "rect",
  x: 1950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "11",
  type: "rect",
  x: 2150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "12",
  type: "rect",
  x: 2350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "13",
  type: "rect",
  x: 2550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "14",
  type: "rect",
  x: 2750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "15",
  type: "rect",
  x: 2950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "16",
  type: "rect",
  x: 3150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "17",
  type: "rect",
  x: 3350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "18",
  type: "rect",
  x: 3550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "19",
  type: "rect",
  x: 3750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "20",
  type: "rect",
  x: 3950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}];

draw(level);
player = document.getElementById("cplayer");
svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
centerplayer();
shadowrays();
html,
body {
  /*default font for all elements*/
  font-family: Calibri;
  /*ensures page is flush*/
  margin: 0px;
  width: 100%;
  height: 100%;
  /*default position of text*/
  text-align: center;
  /*gets rid of scrollbars*/
  overflow: hidden;
  /*cursor is always the normal pointer*/
  cursor: default;
}
#canvas {
  /*makes it flush with the page*/
  height: 100%;
  width: 100%;
  padding: 0;
  /*black background*/
  background-color: #000;
  /*more flushing*/
  position: fixed;
  left: 0px;
  top: 0px;
  border: none;
}
#border {
  height: 100%;
  width: 100%;
  padding: 0;
  /*black background*/
  background: none;
  /*more flushing*/
  position: fixed;
  left: 0px;
  top: 0px;
  border: 1px solid #000;
}
/*currently the player*/

.st1 {
  /*it's black and no outline*/
  fill: black;
  stroke: none;
}
/*the main black bits of the levels that are collidable*/

.obstacle_box {
  /*black fill*/
  fill: #000;
  /*black outline*/
  stroke: #000;
  stroke-width: 1;
  /*prevents corner curling*/
  stroke-miterlimit: 10;
}
/*the hitbox thingy*/

.st2 {
  /*no fill but darkish outline*/
  fill: none;
  stroke: #999;
  stroke-width: 1;
  stroke-miterlimit: 10;
}
/*the exit*/

.exit {
  /*greenish fill*/
  fill: #0C3;
  /*greener outline*/
  stroke: #00FF40;
  stroke-width: 5;
  /*makes the line ends round*/
  stroke-linecap: round;
  /*makes them dashed*/
  stroke-dasharray: 10, 10;
  /*animates in a loop the outline*/
  animation: exit 0.5s linear infinite;
}
/*outline effect for the exit*/

@keyframes exit {
  0% {
    /*outline breaks offset*/
    stroke-dashoffset: 0
  }
  100% {
    stroke-dashoffset: 20
  }
}
.shadowray {
  /*black*/
  fill: #000;
  /*black*/
  stroke: #000;
  stroke-width: 1;
  stroke-miterlimit: 10;
  /*visible*/
  opacity: 1;
}
/*the edge of the level*/

#renclosure {
  /*the background you actually see*/
  fill: #EEE;
}
<svg id="canvas" viewBox="0 0 1920 1080">
  <!--for adding SVG filters to-->
  <defs id="filters"></defs>
</svg>
<div id="border"></div>

1 个答案:

答案 0 :(得分:1)

原来有一个非常简单的解决方案,我所要做的就是在preserveAspectRatio="none"标签中添加svg,这样可以拉伸所有窗口。

&#13;
&#13;
window.setInterval(function() {
  if (draw) {
    if (keystate[controls[2]]) {
      xvelocity -= 2;
    }
    if (keystate[controls[3]]) {
      xvelocity += 2;
    }
    xvelocity = xvelocity * 0.93;
    xscroll += xvelocity;
    svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
    centerplayer();
    if (checkcollision()) {
      xscroll -= xvelocity;
      xvelocity = xvelocity * -0.8;
    }
    if (keystate[controls[0]]) {
      yvelocity += 2;
    }
    if (keystate[controls[1]]) {
      yvelocity -= 2;
    }
    yvelocity = yvelocity * 0.93;
    yscroll -= yvelocity;
    svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
    centerplayer();
    if (checkcollision()) {
      yscroll += yvelocity;
      yvelocity = yvelocity * -0.8;
    }
    shadowrays();
  }
}, 16.666666666666667);
var keystate = {};
window.addEventListener("keydown", function(e) {
  if (!(((e.keycode || e.which) > 111) && ((e.keyCode || e.which) < 124))) {
    keystate[e.keycode || e.which] = true;
  }
}, true);
window.addEventListener("keyup", function(e) {
  keystate[e.keycode || e.which] = false;
}, true);

function shadowrays() {
  var kill = document.getElementsByClassName("shadowray");
  while (kill[0]) {
    kill[0].parentNode.removeChild(kill[0]);
  }
  var len = level.length,
    shape = {},
    points = [],
    poly = [],
    p1x, p2x, p1y, p2y, p3x, p3y, p4x, p4y, p5x, p5y, p6x, p6y, cx = player.cx.animVal.value,
    cy = player.cy.animVal.value,
    m, i, n;
  for (i = 1; i < len; i += 1) {
    shape = level[i];
    points = [shape.x, shape.y, shape.x, shape.y + shape.height, shape.x + shape.width, shape.y + shape.height, shape.x + shape.width, shape.y];
    for (n = 0; n < 4; n += 1) {
      p1x = points[(n * 2) % 8];
      p2x = points[(n * 2 + 2) % 8];
      p1y = points[(n * 2 + 1) % 8];
      p2y = points[(n * 2 + 3) % 8];
      if ((((Math.abs(p1x - cx) <= dimensions.width / 2) || (Math.abs(p2x - cx) <= dimensions.width / 2)) && ((Math.abs(p1y - cy) <= dimensions.height / 2) || (Math.abs(p2y - cy) <= dimensions.height / 2))) && shape.id != "enclosure") {
        m = (p1y - cy) / (p1x - cx);
        p6y = m * (cx + dimensions.width / 2 * (Math.abs(p1x - cx) / (p1x - cx))) - m * cx + cy;
        if (Math.abs(p6y - cy) <= dimensions.height / 2) {
          p6x = (p6y - cy) / m + cx;
          p5x = p6x;
          p5y = cy + dimensions.height / 2 * (Math.abs(p6y - cy) / (p6y - cy));
        } else {
          p6y = cy + dimensions.height / 2 * (Math.abs(p6y - cy) / (p6y - cy));
          p6x = (p6y - cy) / m + cx;
          p5x = cx + dimensions.width / 2 * (Math.abs(p6x - cx) / (p6x - cx));
          p5y = p6y;
        }
        m = (p2y - cy) / (p2x - cx);
        p3y = m * (cx + dimensions.width / 2 * (Math.abs(p2x - cx) / (p2x - cx))) - m * cx + cy;
        if (Math.abs(p3y - cy) <= dimensions.height / 2) {
          p3x = (p3y - cy) / m + cx;
          p4x = p3x;
          p4y = cy + dimensions.height / 2 * (Math.abs(p3y - cy) / (p3y - cy));
        } else {
          p3y = cy + dimensions.height / 2 * (Math.abs(p3y - cy) / (p3y - cy));
          p3x = (p3y - cy) / m + cx;
          p4x = Number(cx) + Number(dimensions.width) / 2 * (Math.abs(p3x - cx) / (p3x - cx));
          p4y = p3y;
        }
        poly = [];
        poly.push(p1x + ',' + p1y, p2x + ',' + p2y, p3x + ',' + p3y, p4x + ',' + p4y, p5x + ',' + p5y, p6x + ',' + p6y);
        createpolygon(poly, "", ("s" + i + n), "shadowray");
      }
    }
  }
}

function createpolygon(points, filter, id, classt) {
  var polygon = document.createElementNS(svgns, "polygon"),
    data_points = "",
    max = points.length,
    z;
  polygon.setAttributeNS(null, "id", "p" + id);
  for (z = 0; z < max; z += 1) {
    data_points += points[z] + " ";
  }
  polygon.setAttributeNS(null, "points", data_points);
  if (filter !== "") {
    polygon.setAttributeNS(null, "filter", filter);
  }
  polygon.setAttributeNS(null, "class", classt);
  svg.appendChild(polygon);
}

function centerplayer() {
  player.setAttributeNS(null, "cx", (xscroll + dimensions.width / 2));
  player.setAttributeNS(null, "cy", (yscroll + dimensions.height / 2));
  var hitbox = document.getElementById("rhb");
  hitbox.setAttributeNS(null, "width", player.r.animVal.value * 2);
  hitbox.setAttributeNS(null, "height", player.r.animVal.value * 2);
  //            var hitboxbbox = hitbox.getBBox();
  hitbox.setAttributeNS(null, "transform", ("translate(" + (xscroll + dimensions.width / 2 - player.r.animVal.value) + ", " + (yscroll + dimensions.height / 2 - player.r.animVal.value) + ")"));
}

function draw(lvl) {
  var objects = lvl.length,
    i;
  xscroll = Number(lvl[0].xspawn);
  yscroll = Number(lvl[0].yspawn);
  xvelocity = 0;
  yvelocity = 0;
  for (i = 1; i < objects; i += 1) {
    var object = lvl[i];
    if (object.type == "rect") {
      createrectangle(object.x, object.y, object.width, object.height, "", object.id, object.class);
    } else if (object.type == "circle") {
      createcircle(object.x, object.y, object.r, "", object.id, object.class);
    } else if (object.type == "polygon") {
      createpolygon(object.points, "", object.id, object.class);
    }
  }
  createcircle("7680", "4320", "50", "", "player", "st1");
  createrectangle("0", "0", "100", "100", "", "hb", "st2");
  createrectangle(lvl[0].xexit - 50, lvl[0].yexit - 50, "100", "100", "", "exit", "exit");
  drawn = true;
}

function createcircle(posx, posy, radius, filter, id, classt) {
  var circle = document.createElementNS(svgns, "circle");
  circle.setAttributeNS(null, "id", "c" + id);
  circle.setAttributeNS(null, "cx", posx);
  circle.setAttributeNS(null, "cy", posy);
  circle.setAttributeNS(null, "r", radius);
  if (filter !== "") {
    circle.setAttributeNS(null, "filter", filter);
  }
  circle.setAttributeNS(null, "class", classt);
  svg.appendChild(circle);
}

function createrectangle(posx, posy, width, height, filter, id, classt) {
  var rectangle = document.createElementNS(svgns, "rect");
  rectangle.setAttributeNS(null, "id", "r" + id);
  rectangle.setAttributeNS(null, "x", posx);
  rectangle.setAttributeNS(null, "y", posy);
  rectangle.setAttributeNS(null, "width", width);
  rectangle.setAttributeNS(null, "height", height);
  if (filter !== "") {
    rectangle.setAttributeNS(null, "filter", filter);
  }
  rectangle.setAttributeNS(null, "class", classt);
  svg.appendChild(rectangle);
}

var svg = document.getElementById("canvas"), //the svg element
  dimensions = {
    width: 1920,
    height: 1080
  }, //view dimensions
  svgns = "http://www.w3.org/2000/svg", //the SVG name space address
  player, //player is used later in game
  level, xvelocity, yvelocity, xscroll, yscroll, //current level, speeds and positions
  controls = ["87", "83", "65", "68", "32"],
  drawn = false;

function checkcollision() {
  var r = player.r.animVal.value,
    frame = document.getElementById("renclosure").getBBox(),
    i;
  if ((player.cx.animVal.value < r) || (player.cy.animVal.value < r) || (player.cx.animVal.value > frame.width - r) || (player.cy.animVal.value > frame.height - r)) {
    return true;
  }
  var collisions = [],
    len, r0 = document.getElementById("rhb").getBoundingClientRect(),
    r1 = svg.createSVGRect();
  r1.x = r0.left;
  r1.y = r0.top;
  r1.width = r0.width;
  r1.height = r0.height;
  var collisions_node = svg.getIntersectionList(r1, null);
  len = collisions_node.length;
  for (i = 0; i < len; i += 1) {
    collisions.push(collisions_node[i]);
  }
  for (i = len - 1; i >= 0; i -= 1) {
    if (collisions[i].id == "renclosure" || collisions[i].id == "cplayer" || collisions[i].id == "rpain" || collisions[i].id == "rhb" || collisions[i].className.animVal == "shadowray") {

      collisions.splice(i, 1);
    } else if (collisions[i].id == "rexit") { //winner
      //DO STUFF
    }
  }
  if (collisions.length > 0) {
    return true;
  } else {
    return false;
  }
}

level = [{
  "id": "l0",
  "name": "pretty", //level name
  "description": "oooooo shadows", //desciption
  "xspawn": 0, //where the player starts
  "yspawn": 0,
  "xexit": 2200, //where the exit it
  "yexit": 2200,
  "bits": 50 //umber of qbits in the level
}, {
  id: "enclosure", //shape id
  type: "rect", //shape type
  x: 0, //top left x
  y: 0, //top left y
  class: "obstacle_box", //class for style
  width: 5760, //width
  height: 2160 //height
}, {
  id: "1",
  type: "rect",
  x: 150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "2",
  type: "rect",
  x: 350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "3",
  type: "rect",
  x: 550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "4",
  type: "rect",
  x: 750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "5",
  type: "rect",
  x: 950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "6",
  type: "rect",
  x: 1150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "7",
  type: "rect",
  x: 1350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "8",
  type: "rect",
  x: 1550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "9",
  type: "rect",
  x: 1750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "10",
  type: "rect",
  x: 1950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "11",
  type: "rect",
  x: 2150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "12",
  type: "rect",
  x: 2350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "13",
  type: "rect",
  x: 2550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "14",
  type: "rect",
  x: 2750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "15",
  type: "rect",
  x: 2950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "16",
  type: "rect",
  x: 3150,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "17",
  type: "rect",
  x: 3350,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "18",
  type: "rect",
  x: 3550,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "19",
  type: "rect",
  x: 3750,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}, {
  id: "20",
  type: "rect",
  x: 3950,
  y: 200,
  class: "obstacle_box",
  width: 100,
  height: 100
}];

draw(level);
player = document.getElementById("cplayer");
svg.setAttribute("viewBox", (xscroll + " " + yscroll + " " + dimensions.width + " " + dimensions.height));
centerplayer();
shadowrays();
&#13;
html,
body {
  /*default font for all elements*/
  font-family: Calibri;
  /*ensures page is flush*/
  margin: 0px;
  width: 100%;
  height: 100%;
  /*default position of text*/
  text-align: center;
  /*gets rid of scrollbars*/
  overflow: hidden;
  /*cursor is always the normal pointer*/
  cursor: default;
}
#canvas {
  /*makes it flush with the page*/
  height: 100%;
  width: 100%;
  padding: 0;
  /*black background*/
  background-color: #000;
  /*more flushing*/
  position: fixed;
  left: 0px;
  top: 0px;
  border: none;
}
#border {
  height: 100%;
  width: 100%;
  padding: 0;
  /*black background*/
  background: none;
  /*more flushing*/
  position: fixed;
  left: 0px;
  top: 0px;
  border: 1px solid #000;
}
/*currently the player*/

.st1 {
  /*it's black and no outline*/
  fill: black;
  stroke: none;
}
/*the main black bits of the levels that are collidable*/

.obstacle_box {
  /*black fill*/
  fill: #000;
  /*black outline*/
  stroke: #000;
  stroke-width: 1;
  /*prevents corner curling*/
  stroke-miterlimit: 10;
}
/*the hitbox thingy*/

.st2 {
  /*no fill but darkish outline*/
  fill: none;
  stroke: #999;
  stroke-width: 1;
  stroke-miterlimit: 10;
}
/*the exit*/

.exit {
  /*greenish fill*/
  fill: #0C3;
  /*greener outline*/
  stroke: #00FF40;
  stroke-width: 5;
  /*makes the line ends round*/
  stroke-linecap: round;
  /*makes them dashed*/
  stroke-dasharray: 10, 10;
  /*animates in a loop the outline*/
  animation: exit 0.5s linear infinite;
}
/*outline effect for the exit*/

@keyframes exit {
  0% {
    /*outline breaks offset*/
    stroke-dashoffset: 0
  }
  100% {
    stroke-dashoffset: 20
  }
}
.shadowray {
  /*black*/
  fill: #000;
  /*black*/
  stroke: #000;
  stroke-width: 1;
  stroke-miterlimit: 10;
  /*visible*/
  opacity: 1;
}
/*the edge of the level*/

#renclosure {
  /*the background you actually see*/
  fill: #EEE;
}
&#13;
<svg id="canvas" viewBox="0 0 1920 1080" preserveAspectRatio="none">
  <!--for adding SVG filters to-->
  <defs id="filters"></defs>
</svg>
<div id="border"></div>
&#13;
&#13;
&#13;