js实现火车变轨小游戏代码

代码语言:html

所属分类:游戏

代码描述:js实现火车变轨小游戏代码

代码标签: 变轨 小游戏

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开


<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">
  

  
  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Coustard&amp;display=block'>
  
<style>
body {
  margin: 0;
  background-color: #252021;
  height: 100vh;
  display: -webkit-box;
  display: flex;
  -webkit-box-align: center;
          align-items: center;
  text-transform: uppercase;
  overflow: hidden;
}

.canvas-container {
  position: relative;
  width: 100vmin;
  height: 100vmin;
  display: block;
  text-align: center;
  margin: 0 auto;
}
.canvas-container a {
  display: none;
  position: absolute;
  right: 5%;
  top: 5%;
}
.canvas-container canvas {
  height: 100%;
}

.modal {
  position: absolute;
  width: 130px;
  height: 183px;
  font-size: 14px;
  background: url(https://s3-us-west-2.amazonaws.com/s.cdpn.io/21151/ticket.svg);
  background-repeat: no-repeat;
  background-size: contain;
  color: #019897;
  text-align: center;
  left: 50%;
  top: 50%;
  font-family: 'Coustard', serif;
  -webkit-transform: translateX(-50%) translateY(-50%);
          transform: translateX(-50%) translateY(-50%);
  padding: 20px;
  -webkit-transition: .2s all;
  transition: .2s all;
}

.modal__gameover,
.modal__win {
  display: none;
}
.modal__gameover .modal__title,
.modal__win .modal__title {
  padding: 40px 0 25px;
}

.modal__loading {
  display: none;
}

.game--active .canvas-container a {
  display: block;
}
.game--active .modal {
  pointer-events: none;
  opacity: 0;
  -webkit-transform: translateX(-50%) translateY(0);
          transform: translateX(-50%) translateY(0);
}

.game--over .modal__gameover {
  display: block;
}
.game--over .modal__main,
.game--over .modal__win {
  display: none;
}

.game--win .modal__win {
  display: block;
}
.game--win .modal__gameover,
.game--win .modal__main {
  display: none;
}

.game--loading .modal__main {
  display: none;
}
.game--loading .modal__loading {
  display: block;
}

.modal__title {
  padding: 10px 0 17px;
  margin: 0;
  color: #f38073;
  line-height: 1.1;
  font-weight: normal;
}

.modal__text {
  margin: 2.5em 0;
}

.modal__controls {
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
  margin: 17px 0 10px;
}

.btn {
  font-family: 'Coustard', serif;
  display: inline-block;
  line-height: 40px;
  background-color: #d8d1c6;
  padding: 0 20px;
  color: #252021;
  cursor: pointer;
  text-transform: none;
}
.btn:hover {
  background-color: #c3b9a8;
}

input[type=range] {
  -webkit-appearance: none;
  background-color: transparent;
}

input[type=range]::-webkit-slider-runnable-track {
  width: 129px;
  height: 6px;
  background-color: #01aead;
  border: none;
  border-radius: 3px;
}

input[type=range]::-moz-range-track {
  width: 129px;
  height: 6px;
  background-color: #01aead;
  border: none;
  border-radius: 3px;
}

input[type=range]::-ms-track {
  width: 129px;
  height: 6px;
  background-color: #01aead;
  border: none;
  border-radius: 3px;
  margin: 5px 0;
}

input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  border: none;
  height: 16px;
  width: 16px;
  border-radius: 50%;
  background-color: #f38073;
  margin-top: -5px;
}

input[type=range]::-moz-range-thumb {
  -webkit-appearance: none;
  border: none;
  height: 16px;
  width: 16px;
  border-radius: 50%;
  background-color: #f38073;
  margin-top: -5px;
}

input[type=range]::-ms-thumb {
  margin-top: 0;
}

/*input[type=range]::-ms-fill-lower {
  background: #2a6495;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
  background: #3071a9;
  border: 0.2px solid #010101;
  border-radius: 2.6px;
  box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
}*/
input[type=range]:focus {
  outline: none;
}

input[type=range]:focus::-webkit-slider-runnable-track {
  background-color: #016565;
}

input[type=range]:focus::-moz-range-track {
  background-color: #016565;
}
</style>




</head>


  <body class="game game--loading">
  <div class="canvas-container"><a class="btn" onclick="finish()">Finished</a>
    <canvas width="1380" height="1380"></canvas>
  </div>
  <div class="modal">
    <div class="modal__content modal__main">
      <h2 class="modal__title">Train Puzzle</h2>
      <label>Difficulty
        <input type="range" min="1" max="100" value="25" oninput="setSpeed(this)"/>
      </label>
      <div class="modal__controls"><a class="btn" onclick="playLevel(false, false)">Play</a></div>
    </div>
    <div class="modal__content modal__loading">
      <h2 class="modal__title">Train Puzzle</h2>
      <div class="modal__text">Loading...</div>
    </div>
    <div class="modal__content modal__gameover">
      <h2 class="modal__title">Game Over</h2>
      <div class="modal__controls"><a class="btn" onclick="gotoMenu()">Try again</a></div>
    </div>
    <div class="modal__content modal__win">
      <h2 class="modal__title">Well done!</h2>
      <div class="modal__controls"><a class="btn" onclick="gotoMenu()">Thanks</a></div>
    </div>
  </div>

  
      <script>
const lerp = (norm, min, max) => {
  return (max - min) * norm + min;
}

const norm = (value, min, max) => {
  return (value - min) / (max - min);
}

const map = (value, sourceMin, sourceMax, destMin, destMax) => {
  return lerp(norm(value, sourceMin, sourceMax), destMin, destMax);
}

const TileTypes = Object.freeze({
  "upleft": 1,
  "upright": 2,
  "downleft": 3,
  "downright": 4,
  "horizontal": 5,
  "vertical": 6,
  "shadow": 7,
  "blocker": 9
});

const Directions = Object.freeze({
  "up": 1,
  "right": 2,
  "down": 3,
  "left": 4
});

class Line {
  constructor(startPos, endPos) {
    this.startPos = startPos;
    this.endPos = endPos;
  }
  
  isIntersecting(line) {
    let det = (this.endPos.x - this.startPos.x) * (line.endPos.y - line.startPos.y) - (line.endPos.x - line.startPos.x) * (this.endPos.y - this.startPos.y),
        gamma, lambda;
    
    if (det === 0) {
      return false;
    } else {
      lambda = ((line.endPos.y - line.startPos.y) * (line.endPos.x - this.startPos.x) + (line.startPos.x - line.endPos.x) * (line.endPos.y - this.startPos.y)) / det;
      gamma = ((this.startPos.y - this.endPos.y) * (line.endPos.x - this.startPos.x) + (this.endPos.x - this.startPos.x) * (line.endPos.y - this.startPos.y)) / det;
      return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1);
    }
  }
}

class PathPos {
  constructor(x, y, trail) {
    this.x = x;
    this.y = y;
    this.trail = [...trail];
    this.finishFound = false;
    this.tileType = "";
  }
  
  getAdjacent(l, prev) {
    let directions = [
      { x: 0, y: -1, dir: 'up' },
      { x: 0, y: 1, dir: 'down' },
      { x: -1, y: 0, dir: 'left' },
      { x: 1, y: 0, dir: 'right' }
    ], 
    adjPathPositions = [];
    
    if(Math.random() >= 0.5) {
      directions = directions.reverse();
    }
    
    for (var i = 0; i < directions.length; i++) {
      let dir = directions[i],
          newpos = { x: this.x + dir.x, y: this.y + dir.y },
          posKey = newpos.x + 'x' + newpos.y;
      
      if(newpos.x >= 0 && newpos.y >= 0 && newpos.x < 8 && newpos.y < 8) {
        if(l.level[newpos.y][newpos.x] !== 9 && !prev.includes(posKey)) {
          this.trail.push(this);
          prev.push(posKey);
          
          let newPathPos = new PathPos(newpos.x, newpos.y, this.trail);
          
          if(newpos.x === l.end.x && newpos.y === l.end.y) {
            newPathPos.finishFound = true;
          }
          
          adjPathPositions.push(newPathPos);
        }
      }
    };
    
    return adjPathPositions;
  }
}

const levelFactory = {
  newLevel: (difficulty, debug) => {
    let l = null, 
      path = [],
      minLength = 9; //difficulty > 50 ? 8 : 6;
    
    while(path.length < minLength) {
      l = levelFactory.generateLevel(difficulty);
      path = levelFactory.findPath(l);
    }
    
    levelFactory.addTrailToMap(l.level, path, l.end);

    for(let i = 0; i < l.level.length; i++) {
      for(let j = 0; j < l.level[i].length; j++) {
        if(l.level[i][j] === 0) {
          l.level[i][j] = levelFactory.randomNumber(1, 6);
        }
      }
    }

    // Remove frame
    for (let i = 0; i <= 7; i++) {
      if(l.level[i][0] === 9) {
        l.level[i][0] = 0;
      }

      if(l.level[0][i] === 9) {
        l.level[0][i] = 0;
      }

      if(l.level[i][7] === 9) {
        l.level[i][7] = 0;
      }

      if(l.level[7][i] === 9) {
        l.level[7][i] = 0;
      }
    }
    
    if(debug) {
      levelFactory.drawLevel(l, path);
    }
    
    return l;
  },
  drawLevel: (l, path) => {
    let c = document.getElementById("canvas");
    let ctx = c.getContext("2d");
    let colors = {
      "c1": "coral",
      "c2": "green",
      "c3": "aqua",
      "c4": "sienna",
      "c5": "maroon",
      "c6": "ivory",
      "c9": "pink" // blocker
    }

    ctx.clearRect(0, 0, c.width, c.height);

    for(let i = 0; i < l.level.length; i++) {
      for(let j = 0; j < l.level[i].length; j++) {
        let tileType = l.level[i][j];

        if(tileType !== 0) {
          levelFactory.drawSquare(ctx, j, i, colors['c' + tileType]);
        }
      }
    }
    
    /*for(let i = 0; i < path.length; i++) {
      levelFactory.drawSquare(ctx, path[i].x, path[i].y, 'rgba(0,255,0,0.1)');
    };*/
  },
  generateLevel: difficulty => {
    const l = {
        level: [
            [9, 9, 9, 9, 9, 9, 9, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 0, 0, 0, 0, 0, 0, 9],
            [9, 9, 9, 9, 9, 9, 9, 9],
        ],
        start: Math.random() >= 0.5 ? { x: levelFactory.randomNumber(1, 6), y: 0 } : { x: 0, y: levelFactory.randomNumber(1, 6) },
        end: Math.random() >= 0.5 ? { x: levelFactory.randomNumber(1, 6), y: 7 } : { x: 7, y: levelFactory.randomNumber(1, 6) },
        spare: levelFactory.randomNumber(1, 6)
      };
    
    let minBlockers = Math.floor(levelFactory.randomNumber(1, 100) / 10); // difficulty / 10
    
    l.level[l.start.y][l.start.x] = (l.start.x == 0) ? 6 : 5;
    l.level[l.end.y][l.end.x] = (l.end.x == 7) ? 6 : 5;  

    // Add blockers
    for (let i = 0; i < levelFactory.randomNumber(minBlockers, 10); i++) {
      let x = levelFactory.randomNumber(1, 6),
          y = levelFactory.randomNumber(1, 6);
      l.level[y][x] = 9;

      if(Math.random() > 0.5) {
        l.level[y][x + 1] = 9;
      }

      if(Math.random() > 0.5) {
        l.level[y + 1][x] = 9;
      }
    }

    return l;
  }, 
  randomNumber: (min, max) => {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  },
  findPath: l => {
    let pos = new PathPos(l.start.x, l.start.y, []),
        prev = [];

    let t = levelFactory.recursiveAdjacentPositions([pos], l, prev);
    
    return t;
  },
  addTrailToMap: (level, path, endPos) => {
    let dir = "";
    
    for(let i = 0; i < path.length; i++) {
      let trailTile = path[i],
          nextPos = {};

      if(path[i + 1]) {
        nextPos = {
          x: path[i + 1].x,
          y: path[i + 1].y
        }
      } else {
        nextPos = endPos;
      }
      
      let change = levelFactory.getNextTilePosition(trailTile, nextPos);
      
      if(trailTile.y === 0) {
        level[trailTile.y][trailTile.x] = 6; // vertical
        dir = 'down';
      } else if(trailTile.x === 0) {
        level[trailTile.y][trailTile.x] = 5; // horizontal
        dir = 'right';
      }
      
      if(change) {
        if(dir === 'down') {
          if(change === 'left') {
            level[trailTile.y][trailTile.x] = 3;
            dir = 'left';
          } else if (change === 'right') {
            level[trailTile.y][trailTile.x] = 4;
            dir = 'right';
          } else {
            level[trailTile.y][trailTile.x] = 5;
          }
        } else if(dir === 'up') {
          if(change === 'left') {
            level[trailTile.y][trailTile.x] = 1;
            dir = 'left';
          } else if (change === 'right') {
            level[trailTile.y][trailTile.x] = 2;
            dir = 'right';
          } else {
            level[trailTile.y][trailTile.x] = 5;
          }
        } else if(dir === 'right') {
          if(change === 'up') {
            level[trailTile.y][trailTile.x] = 3;
            dir = 'up';
          } else if (change === 'down') {
            level[trailTile.y][trailTile.x] = 1;
            dir = 'down';
          } else {
            level[trailTile.y][trailTile.x] = 6;
          }
        } else if(dir === 'left') {
          if(change === 'up') {
            level[trailTile.y][trailTile.x] = 4;
            dir = 'up';
          } else if (change === 'down') {
            level[trailTile.y][trailTile.x] = 2;
            dir = 'down';
          } else {
            level[trailTile.y][trailTile.x] = 6;
          }
        }
      }
    }
  },
  getNextTilePosition: (trailTile, nextPos) => {
    if(!nextPos) return;
    
    let change = {
      x: nextPos.x - trailTile.x,
      y: nextPos.y - trailTile.y
    }
    
    if(change.x === -1)
      return 'left';
    if(change.x === 1)
      return 'right';
    if(change.y === -1)
      return 'up';
    if(change.y === 1)
      return 'down';
  },
  recursiveAdjacentPositions: (positions, l, prev) => {
    let manyPos = [];

    for (let i = 0; i < positions.length; i++) {
      let pos = positions[i],
          adjacentPositions = pos.getAdjacent(l, prev);

      manyPos = manyPos.concat(adjacentPositions);

      for (let j = 0; j < adjacentPositions.length; j++) {
        let p = adjacentPositions[j];

        if(p.finishFound) {
          return p.trail;
        }
      }
    }

    if(manyPos.length) {
      let res = levelFactory.recursiveAdjacentPositions(manyPos, l, prev);

      if(res.length)
        return res;
    }

    return [];
  },
  drawSquare: (ctx, x, y, color) => {
    ctx.beginPath();
    ctx.fillStyle = color;
    ctx.rect(40 * x, 40 * y, 40, 40);
    ctx.fill();
  }
}

const puzzleSpritesFactory = quality => { 
  class Rectangle {
    constructor(center, radius, rotation) {
      this.radius = radius;
      this.center = center;
      this.rotation = rotation;
      this.rotate(rotation);
    }
    
    rotate(r) {
      this.rotation = r;
      
      this.p1 = this.getPoint(this.center, r + 30, this.radius);
      this.p2 = this.getPoint(this.center, r + 150, this.radius);
      this.p3 = this.getPoint(this.center, r + 210, this.radius);
      this.p4 = this.getPoint(this.center, r + 330, this.radius);
    }
    
    translate(distance) {
      let r = new Rectangle(this.center, this.radius, this.rotation);
      
      r.p1.y += distance;
      r.p2.y += distance;
      r.p3.y += distance;
      r.p4.y += distance;
      
      return r;
    }

    localTranslate(distance) {
      this.p1.y += distance;
      this.p2.y += distance;
      this.p3.y += distance;
      this.p4.y += distance;
      
      return this;
    }
    
    push(distance) {
      var newCenter = this.getPoint(this.center, this.rotation, distance);
      return new Rectangle(newCenter, this.radius, this.rotation);
    }
    
    intersect(rectangle, inverted) {
      let r = new Rectangle(this.center, this.radius, this.rotation);
      
      if(inverted) {
        r.p1 = { x: this.p1.x, y: this.p1.y };
        r.p2 = { x: rectangle.p2.x, y: rectangle.p2.y };
        r.p3 = { x: rectangle.p3.x, y: rectangle.p3.y };
        r.p4 = { x: this.p4.x, y: this.p4.y };
      } else {
        r.p1 = { x: rectangle.p1.x, y: rectangle.p1.y };
        r.p2 = { x: this.p2.x, y: this.p2.y };
        r.p3 = { x: this.p3.x, y: this.p3.y };
        r.p4 = { x: rectangle.p4.x, y: rectangle.p4.y };
      }
      
      return r;
    }
    
    connect(ctx, colors, rectangle, drawHiddenSides) {
      let drawOrder,
          sides = {
            1: {
              p1: this.p1,
              p2: rectangle.p1,
              p3: rectangle.p4,
              p4: this.p4
            },
            2: {
              p1: this.p2,
              p2: rectangle.p2,
              p3: rectangle.p1,
              p4: this.p1
            },
            3: {
              p1: this.p2,
              p2: rectangle.p2,
              p3: rectangle.p3,
              p4: this.p3
            },
            4: {
              p1: this.p3,
              p2: rectangle.p3,
              p3: rectangle.p4,
              p4: this.p4
            }
          }
      
      if(this.rotation <= 90) {
        drawOrder = [4, 3, 2, 1];
      } else if (this.rotation <= 180) {
        drawOrder = [2, 3, 1, 4];
      } else if (this.rotation <= 270) {
        drawOrder = [2, 1, 3, 4];
      } else if (this.rotation <= 360) {
        drawOrder = [4, 1, 3, 2];
      }
      
      for (let i = (drawHiddenSides ? 1 : 3); i <= 4; i++) {
        this.drawSide(ctx, sides[drawOrder[i - 1]], colors['side' + drawOrder[i - 1]]);
      }
    }
    
    drawSide(ctx, side, color) {
      ctx.fillStyle = color;
      ctx.strokeStyle = color;
      ctx.lineWidth = 1;
      ctx.beginPath();
      ctx.moveTo(side.p1.x, side.p1.y);
      ctx.lineTo(side.p2.x, side.p2.y);
      ctx.lineTo(side.p3.x, side.p3.y);
      ctx.lineTo(side.p4.x, side.p4.y);
      ctx.closePath();
      ctx.fill();
      ctx.stroke();
    }
    
    getPoint(center, rotation, radius) {
      let radian = (rotation / 180) * Math.PI;
  
      return {
        x: center.x + radius * Math.cos(radian),
        y: center.y + Math.floor(radius / 1.6) * Math.sin(radian) // 1.3
      };
    }
    
    draw(ctx, color) {
      this.drawSide(ctx, this, color);
      return this;
    }
  }

  const drawSlice = (ctx, b, startSlant, colors, rotation, translate, height, slant) => {
    let g2 = b.push(0),
        g1 = b.push(startSlant),
        ground = g1.intersect(g2, true),
        ground2 = g1.intersect(g2, true),
        base = ground.localTranslate(translate),
        top = ground2.localTranslate(translate - height),
        topPushed = ground.push(slant).translate(translate - height),
        t = top.intersect(topPushed);
    
    base.connect(ctx, colors, t, slant !== 0);
    
    return t;
  }
  
  const getCanvas = (width, height) => {
    let c = document.createElement('canvas');
    c.width = width;
    c.height = height;
    return c;
  }
  
  const getCreateSpritePromise = (rotation, colors, isLocomotive) => {
    offscreen = getCanvas(600, 600),
    ctx = offscreen.getContext('2d'),
    ground = new Rectangle({x: 300, y: 420}, 210, rotation),
    base = new Rectangle({x: 300, y: 420}, 220, rotation);
    
    if(!isLocomotive) {
      ground.connect(ctx, colors.baseColors, base.translate(-40), false);
      base.translate(-40).connect(ctx, colors.baseColors, base.translate(-50), false);
      base.translate(-50).connect(ctx, colors.colorLine, base.translate(-70), false);
      base.translate(-70).connect(ctx, colors.baseColors, base.translate(-90), false);
      base.translate(-90).connect(ctx, colors.windowColors, base.translate(-160), false);
      base.translate(-160).connect(ctx, colors.baseColors, base.translate(-200).draw(ctx, '#fff'), false);
    } else {
      ground.connect(ctx, colors.baseColors, base.translate(-40), false);
      base.translate(-40).connect(ctx, colors.baseColors, base.translate(-50), false);
      
      drawSlice(ctx, base, 0, colors.colorLine2, rotation, -50, 20, -10),
      drawSlice(ctx, base, -10, colors.baseColors, rotation, -70, 20, -20),
      drawSlice(ctx, base, -30, colors.windowColors, rotation, -90, 70, -70);
      drawSlice(ctx, base, -100, colors.baseColors2, rotation, -160, 20, -70);
      drawSlice(ctx, base, -170, colors.baseColors3, rotation, -180, 20, -100).draw(ctx, '#FFF');
    }

    return createImageBitmap(offscreen);
  }
  
  let colors = {
    baseColors: { side1: '#d9dbdb', side2: '#fff', side3: '#d9dbdb', side4: '#fff' },
    baseColors2: { side1: '#e2e2e2', side2: '#fff', side3: '#d9dbdb', side4: '#fff' },
    baseColors3: { side1: '#f7f7f7', side2: '#fff', side3: '#d9dbdb', side4: '#fff' },
    colorLine: { side1: '#d9dbdb', side2: '#f38073', side3: '#d9dbdb', side4: '#f38073' },
    colorLine2: { side1: '#f38073', side2: '#f38073', side3: '#d9dbdb', side4: '#f38073' },
    windowColors: { side1: '#323332', side2: '#323332', side3: '#323332', side4: '#323332' }
  },
  locPromises = [],
  carPromises = [];
  
  for (let rotation = 0; rotation <= 360; rotation += quality) { 
    carPromises.push(getCreateSpritePromise(rotation, colors, false));
    locPromises.push(getCreateSpritePromise(rotation, colors, true));
  }

  return { locPromises, carPromises };
}

const state = {
  canvas: null,
  ctx: null,
  map: null,
  mousePos: null,
  hoveredTile: null,
  autoplay: true,
  paused: false,
  train: {
    tile: null,
    prevTiles: [],
    dir: null,
    speed: 0.25
  },
  timing: {
    delta: 0,
    last: 0
  },
  colors: {
    "rail": "#7d94a3",
    "railShadow": "#314858",
    "road": "#01aead",
    "blocker": "#f38073",
    "locked": "#019897",
    "bg": "#252021",
    "yellow": "#fdb601"
  },
  graphics: {
    // put sprites here
  },
  isTouchDevice: false
}

const drawTrain = (ctx, cartInfo) => {
  let sprite = state.graphics[cartInfo.isLocomotive ? 'locSprites' : 'carSprites'][cartInfo.rotation];

  if(sprite) {
    ctx.drawImage(sprite, cartInfo.x, cartInfo.y, 150, 150);
  }
}

class Tile {
  constructor(x, y, type) {
    this.x = x;
    this.y = y;
    this.type = type;
    this.width = 224;
    this.height = 144;
    this.progress = 0;
    this.locked = false;
    this.hidden = false;
    this.setDir = null;
    this.pixelPos = {
      x: 578 + (this.x * 112) - (this.y * 112),
      y: 124 + (this.y * 72) + (this.x * 72)
    }
  }
  
  draw(ctx) {
    let tileId = 'tile-' + this.type + (this.locked ? "-locked" : "");
    
    if(!state.graphics[tileId]) {
        this.getTile(this.type, this.locked).then(sprite => {
          state.graphics[tileId] = sprite;
        });

        // Cache locked tiles
        if(!state.graphics[tileId + "-locked"]) {
          this.getTile(this.type, true).then(sprite => {
            state.graphics[tileId + "-locked"] = sprite;
          });
        }
    }
    
    if(state.graphics[tileId]) {
      ctx.drawImage(state.graphics[tileId], this.pixelPos.x, this.pixelPos.y);
    }
  }
  
  getCorners(rotateCount) {
    let corners = [
      { x: 112, y: 0 },
      { x: 224, y: 72 },
      { x: 112, y: 144 },
      { x: 0, y: 72 }
    ];
    
    for (let i = 0; i < rotateCount; i++) {
      corners.push(corners.shift());
    }
    
    return { 
      c1: corners[0],
      c2: corners[1],
      c3: corners[2],
      c4: corners[3]
    };
  }
  
  getTile(type, isLocked) {
    let offscreen = getCanvas(224, 144),
        ctx = offscreen.getContext('2d'),
        fillStyle = '#e17f51';
    
    if(isLocked) {
        fillStyle = state.colors.locked;
    } else {
      switch (this.type) {
          case TileTypes.shadow:
            fillStyle = 'rgba(0, 0, 0, .2)';
            break;
          case TileTypes.blocker:
            fillStyle = state.colors.blocker;
            break;
          case TileTypes.upleft:
          case TileTypes.upright:
          case TileTypes.downleft:
          case TileTypes.downright:
            fillStyle = state.colors.road;
            break;
          case TileTypes.horizontal:
       .........完整代码请登录后点击上方下载按钮下载查看

网友评论0