【问题标题】:Comparing x/y of two positions on a canvas比较画布上两个位置的 x/y
【发布时间】:2015-02-18 02:15:17
【问题描述】:

我正在使用画布来可视化我的一个小游戏。 基本上我有两个代表太空船的对象,每个对象都有一个“位置”数组,其中保存着飞船当前的 x/y。 根据这些数组,我在画布上绘制图像(totalw/h 为 300/300 fyi)。

现在,对于困难的部分。 我想在该画布上绘制动画(枪声)。基本上是从ship1 x/y 到ship2 x/y。

对于动画函数本身,我传递了一个包含 3 个数组的效果对象,shooter.location[x, y], target.location[x, y] 和第三个数组,其中包含当前 EFFECT 在 [x , y]。

this.animateEffects = function(effects){

    var shooter = effects.shooter;
    var target = effects.target;
    var current = effects.current;

    var canvas = document.getElementById("effects");
    var context = canvas.getContext("2d");
        context.clearRect(0, 0, canvas.width, canvas.height);
        context.beginPath();
        context.fillStyle = "red";
        context.arc(current[0], current[1], 5, 0, 2*Math.PI);
        effects.current[0]++
        effects.current[1]++
        context.fill();

        if (current == target){
            console.log("ding");
            this.end()
        }
}

我的“问题”是,如果可能的话,我正在寻找一种聪明的方法来确定(对于每一帧) effects[x, y] 是否应该去 ++ 或 -- 或两者的组合,具体取决于在“移动”的船只所在的位置(当时,拍摄开始)。

感谢任何建议或提示。

【问题讨论】:

  • 如果我没记错的话,你想让effects跟随移动的船吗?
  • 没有。船只在着火点处是静止的。玩家 A 移动,玩家 B 移动。玩家 A 舰船向玩家 B 舰船开火,反之亦然。
  • 嗯,好的。然后你应该将目标船在开火时刻的位置保存在一个变量中(var shootLocation)。然后检查效果的位置到shootLocationif(effect.x > shootLocation.x){// --}else{//++}
  • 这不行。我试过了。问题是,子弹不会直接穿过目标,但它会做一个轴直到它对齐,然后它会做另一个轴。
  • 你应该将xy添加到同一帧中,这样如果它们不对齐就会产生对角线轨迹。

标签: javascript arrays html canvas


【解决方案1】:

您可以使用线性插值从射手向目标发射子弹。

  1. 计算射手和目标的原始 X 和 Y 位置的差异。

    // save the starting position of the bullet (== shooter's original position)
    // (these original X & Y are needed in the linear interpolation formula)
    bulletOriginalX=shooter.x;
    bulletOriginalY=shooter.y;
    
    // calc the delta-X & delta-Y of the shooter & target positions
    // (these deltas are needed in the linear interpolation formula)
    dx=target.x-shooter.x;
    dy=target.y-shooter.y;
    
  2. 使用插值公式将子弹移向目标

    // where percent == the percent you want the bullet to be between 
    // it's starting & ending positions
    // (between starting shooter & starting target positions)
    currentBulletX=bulletOriginalX+dx*percent;
    currentBulletY=bulletOriginalY+dy*percent;
    

这是一个例子:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

shooter={x:50,y:50};
target={x:100,y:100};
effect={x:50,y:50,dx:0,dy:0,pct:0,speedPct:0.25};

draw();
fire();

$('#test').click(function(){
  moveEffect();
  draw();
});

function fire(){
  effect.x=shooter.x;
  effect.y=shooter.y;
  effect.dx=target.x-shooter.x;
  effect.dy=target.y-shooter.y;
  effect.pct=0;
}

function moveEffect(){
  effect.pct+=effect.speedPct;
}

function draw(){
  ctx.clearRect(0,0,cw,ch);

  ctx.beginPath();
  ctx.arc(shooter.x,shooter.y,15,0,Math.PI*2);
  ctx.closePath();
  ctx.strokeStyle='green';
  ctx.stroke();

  ctx.beginPath();
  ctx.arc(target.x,target.y,15,0,Math.PI*2);
  ctx.closePath();
  ctx.strokeStyle='red';
  ctx.stroke();

  if(effect.pct>1){return;}

  var x=effect.x+effect.dx*effect.pct;
  var y=effect.y+effect.dy*effect.pct;

  ctx.beginPath();
  ctx.arc(x,y,3,0,Math.PI*2);
  ctx.closePath();
  ctx.fillStyle='black';
  ctx.fill();

}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button id=test>Animate 1 frame</button>
<br><canvas id="canvas" width=300 height=300></canvas>

【讨论】:

  • 稍作改动后,这就像使用 setInterval 的魔法一样。我非常感谢顶部的 cmets。
猜你喜欢
  • 1970-01-01
  • 2018-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-20
  • 2012-11-30
  • 2022-09-30
相关资源
最近更新 更多