簡體   English   中英

同時運行 class 的多個實例 javascript

[英]run multiple instances of a class simultaneously javascript

您可能只需要查看障礙.js

我有一個 class 在 canvas 上繪制一個正方形並為其添加碰撞檢測。

當我創建一個實例時,它可以完美運行,

new Obstacle(100, 100, 100, 100).init()

但如果我創建 2 它只適用於我創建的第二個

new Obstacle(100, 100, 100, 100).init()
new Obstacle(400, 100, 100, 100).init()

有誰知道讓這段代碼在兩個實例上都工作的方法?

 // utility.js //define variables let Keys = { W: false, A: false, S: false, D: false } let Allow = { W: true, A: true, S: true, D: true } let Character = { X: 0, Y: 0, H: parseInt(window.getComputedStyle(character).getPropertyValue("height")), W: parseInt(window.getComputedStyle(character).getPropertyValue("width")), } //function to update the position of `character` every milisecond setInterval(function() { document.getElementById("character").style.left = Character.X + "px" document.getElementById("character").style.top = Character.Y + "px" }, 1) //waits for event `keyDOWN` to happen, if it happens it sets `Keys.` + the key to TRUE so it START animating document.addEventListener("keydown", (event) => { if (event.key === "w") Keys.W = true if (event.key === "a") Keys.A = true if (event.key === "s") Keys.S = true if (event.key === "d") Keys.D = true }) //waits for event `keyUP` to happen, if it happens it sets `Keys.` + the key to FALSE so it STOPS animating document.addEventListener("keyup", (event) => { if (event.key === "w") Keys.W = false if (event.key === "a") Keys.A = false if (event.key === "s") Keys.S = false if (event.key === "d") Keys.D = false }) //function that makes `character` move by adding to its X and Y value setInterval(function() { if (Keys.W && Allow.W) { if (Character.Y > 0) { Character.Y -= 1 } } if (Keys.A && Allow.A) { if (Character.X > 0) { Character.X -= 1 } } if (Keys.S && Allow.S) { if (Character.Y < 500 - Character.H) { Character.Y += 1 } } if (Keys.D && Allow.D) { if (Character.X < 800 - Character.W) { Character.X += 1 } } }, 1) // obstacle.js //define variables let canvas = document.getElementById("ObstacleHolder") let ctx = canvas.getContext("2d") //resize the canvas canvas.width = 800 canvas.height = 500 class Obstacle { constructor(x, y, height, width, src = null) { this.H = height this.W = width this.X = x this.Y = y this.src = src } //function to draw the obstacle on the canvas & apply colision detection init() { //array for the coordinates let ObstaclePositions = [this.X - Character.W, this.Y - Character.H, (this.X + this.W), (this.Y + this.H)] //draw the obstacle on the canvas ctx.beginPath() ctx.rect(this.X, this.Y, this.W, this.H) ctx.fillStyle = "Red" ctx.fill() //colision detection setInterval(function() { //colision detection X if (Character.Y > ObstaclePositions[1] && Character.Y < ObstaclePositions[3] && Character.X > ObstaclePositions[0] - 1 && Character.X < ObstaclePositions[2] - 1) { Allow.D = false Allow.A = true Allow.S = true Allow.W = true } else { Allow.D = true } if (Character.Y > ObstaclePositions[1] && Character.Y < ObstaclePositions[3] && Character.X > ObstaclePositions[0] + 1 && Character.X < ObstaclePositions[2] + 1) { Allow.A = false Allow.D = true Allow.S = true Allow.W = true } else { Allow.A = true } //colision detection Y if (Character.Y > ObstaclePositions[1] - 1 && Character.Y < ObstaclePositions[3] - 1 && Character.X > ObstaclePositions[0] && Character.X < ObstaclePositions[2]) { Allow.S = false Allow.D = true Allow.A = true Allow.W = true } else { Allow.S = true } if (Character.Y > ObstaclePositions[1] + 1 && Character.Y < ObstaclePositions[3] + 1 && Character.X > ObstaclePositions[0] && Character.X < ObstaclePositions[2]) { Allow.W = false Allow.A = true Allow.D = true Allow.S = true } else { Allow.W = true } }, 1) } } new Obstacle(100, 100, 100, 100).init() new Obstacle(400, 100, 100, 100).init()
 * { padding: 0; margin: 0; font-family: "Dosis", "Source Sans Pro", "Helvetica Neue", Arial, sans-serif; -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } #canvas { height: 500px; width: 800px; border: 1px solid black; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); } #character { height: 50px; width: 50px; background-color: rgb(0, 204, 255); position: absolute; top: 0px; left: 0px; } #ObstacleHolder { background-color: rgba(100, 100, 158, 0.288); position: absolute; }
 <,DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width. initial-scale=1.0"> <title>Prototype</title> </head> <body> <div id="canvas"> <canvas id="ObstacleHolder"></canvas> <div id="character"></div> </div> </body> </html> <.-- import css file --> <link rel="stylesheet" href="style.css"> <!-- import javascript files --> <script src="utility.js"></script> <script src="obstacle.js"></script>

創建你的TickManager (這個,基於EventEmitter ):

class TickManager extends EventEmitter {
  timer = false;
  running = false;

  constructor(...props) {
    super(...props);
    this.onStop = this.stop.bind(this);
    this.on('stop', this.onStop);
  }

  destroy(...props) {
    this.off('stop', this.onStop);
    super.destroy(...props);
  }

  start() {
    if(!this.running) {
      this.running = true;
      this.tick();
    }
  }

  stop() {
    cancelAnimationFrame(this.timer);
    this.running = false;
  }

  tick() {
    this.timer = false;
    this.emit( 'beforetick' );
    this.emit( 'tick' );
    this.emit( 'aftertick' );
    if(this.running) {
      this.timer = requestAnimationFrame(this.tick.bind(this));
    }
  }
}

const tickManager = new TickManager();

在您的播放器中使用它:

tickManager.on('beforetick', function() {
  Allow = {
    W: true,
    A: true,
    S: true,
    D: true
  };

  // Allow obstacles to disallow directions
  tickManager.emit('afterplayertick');
});

// Update the position of `character` after all calculations have been done
tickManager.on('aftertick', function() {
  document.getElementById("character").style.left = Character.X + "px"
  document.getElementById("character").style.top = Character.Y + "px"
});

// Makes `character` move by adding to its X and Y value, if allowed by obstacles
tickManager.on('tick', function() {
  if (Keys.W && Allow.W) {
    if (Character.Y > 0) {
      Character.Y -= 1
    }
  }
  if (Keys.A && Allow.A) {
    if (Character.X > 0) {
      Character.X -= 1
    }
  }
  if (Keys.S && Allow.S) {
    if (Character.Y < 500 - Character.H) {
      Character.Y += 1
    }
  }
  if (Keys.D && Allow.D) {
    if (Character.X < 800 - Character.W) {
      Character.X += 1
    }
  }
});

在你的障礙中使用它:

class Obstacle {
  // ...
  init() {
    // ...
    // Colision detection
    tickManager.on('afterplayertick', function() {
      //colision detection X
      if (Character.Y > ObstaclePositions[1] &&
          Character.Y < ObstaclePositions[3] &&
          Character.X > ObstaclePositions[0] - 1 &&
          Character.X < ObstaclePositions[2] - 1) {
        Allow.D = false
      }
      if (Character.Y > ObstaclePositions[1] &&
          Character.Y < ObstaclePositions[3] &&
          Character.X > ObstaclePositions[0] + 1 &&
          Character.X < ObstaclePositions[2] + 1) {
        Allow.A = false
      }
      if (Character.Y > ObstaclePositions[1] - 1 &&
          Character.Y < ObstaclePositions[3] - 1 &&
          Character.X > ObstaclePositions[0] &&
          Character.X < ObstaclePositions[2]) {
        Allow.S = false
      }
      if (Character.Y > ObstaclePositions[1] + 1 &&
          Character.Y < ObstaclePositions[3] + 1 &&
          Character.X > ObstaclePositions[0] &&
          Character.X < ObstaclePositions[2]) {
        Allow.W = false
      }
    });
  }
}

最后,啟動分時管理器:

tickManager.start();

事件發射器

您可以使用來自EventEmitter事件 package的 EventEmitter 或自己做(從本文復制):

class EventEmitter {
  listeners = [];
  emit(eventName, data) {
    this.listeners
      .filter(({ name }) => name === eventName)
      .forEach(
        ({ callback }) => setTimeout(
          callback.apply(this, [this, ...data]), 0
        );
      )
  }
  on(name, callback) {
    if (
      typeof callback === 'function'
      && typeof name === 'string'
    ) {
      this.listeners.push({ name, callback });
    }
  }
  off(eventName, callback) {
    this.listeners = this.listeners.filter(
      listener => !(listener.name === eventName &&
        listener.callback === callback)
    );
  }
  destroy() {
    this.listeners.length = 0;
  }
}

你可以對這段代碼做很多其他的改進:

  • 創建一個Player class(這樣您就可以擁有多個播放器。)。 向其中添加KeysAllowCharacter和 DOM 元素。
  • 將刻度管理器作為參數傳遞給玩家和障礙物創建者,這樣您就可以停止使用相同的上下文並可以開始import模塊來拆分和組織您的代碼。
  • 在這個例子中,玩家發出一個事件。 將玩家作為參數傳遞給其偵聽器,因此障礙偵聽器可以控制與每個玩家的碰撞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM