使用Interp绘制realX,realY等

时间:2017-01-23 20:32:07

标签: javascript html5-canvas

使用interp来改善绘图功能时遇到问题。由于某种原因,realX每3帧返回undefined。我正在使用this guide来实现此功能。最终目标是使碰撞系统工作,这样它就可以反映出投射盾牌上的子弹(基本上是子弹如何与画布边界相互作用。这是代码的一部分:

//INT
var canvas = document.getElementById('ctx'),
    cw = canvas.width,
    ch = canvas.height,
    cx = null,
    bX = canvas.getBoundingClientRect().left,
    bY = canvas.getBoundingClientRect().top,
    mX,
    mY,
    lastFrameTimeMs = 0,
    maxFPS = 60,
    fps = 60,
    timestep     		=    1000/fps,
    lastTime     		=    (new Date()).getTime(),
    currentTime = 0,
    delta = 0,
    framesThisSecond = 0,
    lastFpsUpdate = 0,
    running = false,
    started = false,
    frameID = 0;

var gametimeStart = Date.now(),
    frameCount = 0,
    score = 0,
    player,
    enemyList = {},
    boostList = {},
    bulletList = {},
    pulseList = {},
    shieldList = {};

//CREATE , create object
var Unit = function(){
  this.x;
  this.y;
  this.realX;
  this.realY;
  this.type = "unit";
  this.hp = 0;
  this.color;
  this.collision = function(arc){
    return this.x + this.r + arc.r > arc.x 
    && this.x < arc.x + this.r + arc.r
    && this.y + this.r + arc.r > arc.y 
    && this.y < arc.y + this.r + arc.r
  };
  this.position = function(delta){
    boundX = document.getElementById('ctx').getBoundingClientRect().left;
    boundY = document.getElementById('ctx').getBoundingClientRect().top;
    this.realX = this.x;
    this.realX = this.y;
    this.realR = this.r;
    this.x += this.spdX * delta / 1000;
    this.y += this.spdY * delta / 1000;
    if (this.x < this.r || this.x + this.r > cw){
      this.spdX = -this.spdX;
      if (Math.random() < 0.5) {
        this.spdY += 100;
      } else {
        this.spdY -= 100;
      }
    }
    if (this.y < this.r || this.y + this.r > ch){
      this.spdY = -this.spdY;
      if (Math.random() < 0.5) {
        this.spdX += 100;
      } else {
        this.spdX -= 100;
      }
    }
  };
  this.draw = function(interp){
    ctx.save();
    ctx.fillStyle = this.color;
    ctx.beginPath();
    //THIS DOESN'T WORK, the code is working perfectly without it
    this.x = (this.realX + (this.x - this.realX) * interp);
    this.y = (this.realY + (this.y - this.realY) * interp);
    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    ctx.arc(this.x,this.y,this.r,0,2*Math.PI,false);
    ctx.fill();
    ctx.restore();
  };
}
//Player
var Player = function(){
  //Coördinates
  this.x = 50;
  this.y = 50;
  this.r = 10;
  //Stats
  this.spdX = 30;
  this.spdY = 5;
  this.atkSpd = 1;
  this.hp = 100;
  //Other
  this.name;
  this.color = "green";
  this.type = "player";
  this.angle = 1;
  this.attack = function attack(enemy){
    enemy.hp -= 10;
  };
};
Player.prototype = new Unit();
//Boost
var Boost = function(){
  //Coördinates
  this.x = 300;
  this.y = 300;
  this.r = 5;
};
Boost.prototype = new Unit();
//Bullet
var Bullet = function(){
  //Coördinates
  this.x = player.x;
  this.y = player.y;
  this.r = 3;
  //Stats
  var angle = player.angle*90;
  this.spdX = Math.cos(angle/180*Math.PI)*200;
  this.spdY = Math.sin(angle/180*Math.PI)*200;
  //Other
  if (player.angle === 4)
    player.angle = 0;
  player.angle++;
};
Bullet.prototype = new Unit();

var player = new Player();
var boost = new Boost();
var bullet = new Bullet();

//UPDATE
update = function(delta){
  bullet.position(delta);
  if(player.collision(boost)){
    alert("collide");
  }
};
//DRAW
draw = function(interp){
  ctx.clearRect(0,0,cw,ch);
  fpsDisplay.textContent = Math.round(fps) + ' FPS';
  boost.draw(interp);
  bullet.draw(interp);
  player.draw(interp);
};
//LOAD	
if (!document.hidden) { console.log("viewed"); }
function panic() { delta = 0; }
function begin() {}
function end(fps) {
  if (fps < 25) {
    fpsDisplay.style.color = "red";
  }
  else if (fps > 30) {
    fpsDisplay.style.color = "black";
  }
}
function stop() {
  running = false;
  started = false;
  cancelAnimationFrame(frameID);
}
function start() {
  if (!started) {
    started = true;
    frameID = requestAnimationFrame(function(timestamp) {
      draw(1);
      running = true;
      lastFrameTimeMs = timestamp;
      lastFpsUpdate = timestamp;
      framesThisSecond = 0;
      frameID = requestAnimationFrame(mainLoop);
    });
  }
}
function mainLoop(timestamp) {  
  if (timestamp < lastFrameTimeMs + (1000 / maxFPS)) {
    frameID = requestAnimationFrame(mainLoop);
    return;
  }
  delta += timestamp - lastFrameTimeMs;
  lastFrameTimeMs = timestamp;
  begin(timestamp, delta);
  if (timestamp > lastFpsUpdate + 1000) {
    fps = 0.25 * framesThisSecond + 0.75 * fps;
    lastFpsUpdate = timestamp;
    framesThisSecond = 0;
  }
  framesThisSecond++;
  var numUpdateSteps = 0;
  while (delta >= timestep) {
    update(timestep);
    delta -= timestep;
    if (++numUpdateSteps >= 240) {
      panic();
      break;
    }
  }
  draw(delta / timestep);
  end(fps);
  frameID = requestAnimationFrame(mainLoop);
}
start();
if (typeof (canvas.getContext) !== undefined) {
  ctx = canvas.getContext('2d');
  ctx.font = '30px Arial';
}

//CONTROLLES
//Mouse Movement
document.onmousemove = function(mouse){
  var mouseX = mouse.clientX - bX;
  var mouseY = mouse.clientY - bY;

  if(mouseX < player.width/2)
    mouseX = player.width/2;
  if(mouseX > cw-player.width/2)
    mouseX = cw-player.width/2;
  if(mouseY < player.height/2)
    mouseY = player.height/2;
  if(mouseY > ch-player.height/2)
    mouseY = ch-player.height/2;

  player.x = mX = mouseX;
  player.y = mY = mouseY;
}
//Pauze Game
var pauze = function(){
  if(window.event.target.id === "pauze"){
    stop();
  }
  if(window.event.target.id === "ctx"){
    start();
  }
};
document.addEventListener("click", pauze);
html {
  height: 100%;
  box-sizing: border-box;
}
*,*:before,*:after {
  box-sizing: inherit;
}
body {
  position: relative;
  margin: 0;
  padding-bottom: 6rem;
  min-height: 100%;
  font-family: "Helvetica Neue", Arial, sans-serif;
}
main {
  margin: 0 auto;
  padding-top: 64px;
  max-width: 640px;
  width: 94%;
}
main h1 {
  margin-top: 0;
}
canvas {
  border: 1px solid #000;
}
<canvas id="ctx" width="500" height="500"></canvas>
<div id="fpsDisplay" style="font-size:50px; position:relative; margin: 0 auto;"></div>
<p id="status"></p>
<button id="pauze">Pauze</button>

1 个答案:

答案 0 :(得分:0)

声明,定义,使用。

问题是您使用的是未定义的变量。

您有3个对象,Player,Boost和Bullet,每个对象都将对象Unit分配给它们的原型。

您声明并定义单位

function Unit(){
    this.x;
    this.y;
    this.realX;
    this.realY;
    // blah blah

    this.draw = function(){
         // blah blah

    this.draw = function (interp) {
        ctx.save();
        ctx.fillStyle = this.color;
        ctx.beginPath();
        // this.realX and this.realY are undefined
        this.x = (this.realX + (this.x - this.realX) * interp);
        this.y = (this.realY + (this.y - this.realY) * interp);
        ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
        ctx.fill();
        ctx.restore();
    };

}

然后玩家

var Player = function () {
    //Coördinates
    this.x = 50;
    this.y = 50;
    this.r = 10;
    //Stats
    // etc....
};

然后在原型中添加一个单元。

Player.prototype = new Unit();

这为玩家提供单位属性xyrealXrealY realX和{{1}未定义。与另外两个对象Boost,Bullet

相同

任何具有相同名称的现有属性都保持原样并保留其值。不在Player中的任何属性都会从Unit获取它们,但是在单元中你只声明了属性realYrealX你还没有定义它们。

您需要在使用它们之前为它们提供值来定义属性。您可以在Unit

中执行此操作
realY

然后在播放器

function Unit(){
    this.x = 0; // default value I am guessing
    this.y = 0;
    this.realX = 10;
    this.realY = 10;

在使用变量之前,您必须定义它是什么或检查它是否已定义并采取适当的措施。

function Player(){
    this.x = 50; // these will keep the value they have
    this.y = 50;
    // realX and realY will have the defaults when you add to the prototype
    // Or you can define them here
    this.realX = 20;
    this.realY = 20;

顺便说一句,当你让它们一个接一个地出现而没有机会离开页面时,你应该摆脱它们非常烦人的警报。