我正在寻找一个解决方案,但是找不到任何好的东西并且写得很简单,我希望你能帮我解决这个问题。
我只想实现: - - - onClick完美地点击指定速度的[x,y]坐标(存储在变量中,例如速度;),
我在这里看到了类似的问题,但是我无法理解它们,如果您知道解决方案,请以最简单的方式编写。提前谢谢。
var ctx = document.getElementById('canvas').getContext('2d');
var cHeight = 500;
var cWidth = 500;
ctx.font = '30px Arial';
var enemyList = {};
var player = {
x: 50,
y: 50,
spdX: 1,
spdY: 1,
name: 'P',
hp: 10
};
getDistanceBetweenEntity = function(entity1, entity2) {
var vx = entity1.x - entity2.x;
var vy = entity1.y - entity2.y;
return Math.sqrt(vx*vx+vy*vy);
}
testCollisionEntity = function(entity1, entity2) {
var distance = getDistanceBetweenEntity(entity1, entity2);
return distance < 30;
}
enemy = function(id, x, y, spdX, spdY) {
var enemy = {
x: x,
spdX: spdX,
y: y,
spdY: spdY,
name: 'E',
id: id
}
enemyList[id] = enemy;
}
updateEntity = function(entity){
updateEntityPosition(entity);
drawEntity(entity);
}
updateEntityPosition = function(entity) {
entity.x += entity.spdX;
entity.y += entity.spdY;
if (entity.x < 0 || entity.x > cWidth) {
entity.spdX = -entity.spdX;
}
if (entity.y < 0 || entity.y > cHeight) {
entity.spdY = -entity.spdY;
}
}
drawEntity = function(entity) {
ctx.fillText(entity.name, entity.x, entity.y);
}
update = function() {
ctx.clearRect(0, 0, cWidth, cHeight);
for(var key in enemyList) {
updateEntity(enemyList[key]);
var isColliding = testCollisionEntity(player, enemyList[key]);
if(isColliding) {
// console.log("Colliding!");
}
}
drawEntity(player);
}
enemy('E1', 150, 350, 10, 15);
enemy('E2', 250, 350, 10, -15);
enemy('E3', 250, 150, 10, -8);
setInterval(update, 1000/30);
document.onclick = function(mouse) {
var mouseX = mouse.clientX;
var mouseY = mouse.clientY;
while ( mouseX !== player.x && mouseY !== player.y ) {
if ( mouseX <= player.x ) {
player.x -= player.spdX;
} else if ( mouseX >= player.x ) {
player.x += player.spdX;
}
if ( mouseY <= player.y ) {
player.y -= player.spdY;
} else if ( mouseY >= player.y ) {
player.y += player.spdY;
}
}
}
&#13;
/*
I just wanted to achieve:
- onClick go to clicked [x, y] with SPECIFIED speed which will be stored in variable eg. var speed;
*/
&#13;
<canvas id="canvas" width="500" height="500" style="margin: 0 auto; border: 1px solid black;"></canvas>
&#13;
答案 0 :(得分:0)
为游戏添加两个属性,即当前目标x,y。如果没有目标
,则为nullconst player = {
x: 50,
y: 50,
name: 'P',
hp: 10,
targetX : null, // null for no target
targetY : null,
以每帧像素(60Fps)为单位添加速度值,因此每秒10像素为10/60
speed : 10 / 60,
添加一个功能,如果有目标集
,将移动玩家 update(){
if(this.targetX !== null){
获取目标的x,y距离,然后获得线性距离。如果距离小于速度,那么你就在那里设置位置并使目标为空
var xd = this.targetX - this.x;
var yd = this.targetY - this.y;
var distToTarget = Math.sqrt(xd*xd+yd*yd);
if(distToTarget<= this.speed){
this.x = this.targetX;
this.y = this.targetY;
this.targetX = this.targetY = null;
}else {
如果不存在,则将x,y距离除以线性距离,得到一个单位长的向量。
xd /= distToTarget;
yd /= distToTarget;
向量xd,yd的长度是1个像素。我们可以将它乘以速度并获得在x和y中移动的像素数以此速度移动
xd *= this.speed;
yd *= this.speed;
更新播放器位置和功能结束并关闭对象播放器
this.x += xd;
this.y += yd;
}
}
}
你可以为敌人做同样的事情,因为他们在追逐玩家你可以使用相同的功能,但你只需将目标设置为玩家。让它们哑一点可能是值得的,所以只设置每隔这么多帧的目标,或者使用随机赔率测试。 (见代码)
最好使用requestAnimationFrame
而不是setInterval
制作动画。
我在下面重写了你的代码。
var ctx = document.getElementById('canvas').getContext('2d');
var cHeight = 500;
var cWidth = 500;
ctx.font = '30px Arial';
// As you are sharing some functionality I put the shared functions in a separate object
var sharedBehaviour = {
x: 50,
y: 50,
targetX: null, // null for no target
targetY: null,
speed: 100 / 60,
update() {
if (this.targetX !== null) {
var xd = this.targetX - this.x;
var yd = this.targetY - this.y;
var distToTarget = Math.sqrt(xd * xd + yd * yd);
if (distToTarget <= this.speed) {
this.x = this.targetX;
this.y = this.targetY;
this.targetX = this.targetY = null;
} else {
xd /= distToTarget;
yd /= distToTarget;
xd *= this.speed;
yd *= this.speed;
this.x += xd;
this.y += yd;
}
}
},
draw() {
ctx.fillText(this.name, this.x, this.y);
}
}
var enemyList = [];
// to create the player with the shared properties you use Object.assign
var player = Object.assign({}, sharedBehaviour, { // add the unique properties last
x: 50, // you can overwrite shared properties
y: 50,
name: 'P',
hp: 10
});
// function to create an enemy with the shard properties
// use the for function functionName( rather than functionName = function
// It is safer and has other benefits as well
// you had enemy = function(id, x, y, spdX, spdY) {
function createEnemy(id, x, y, speed) {
enemyList.push(Object.assign({}, sharedBehaviour, {
x,
y,
speed,
id, // You can use shorthand properties rather than x:x,y:y
name: id,
setTarget() { // will set the player as a target with a random so its not to hard
this.targetX = player.x + (Math.random() - 0.5) * 100;
this.targetY = player.y + (Math.random() - 0.5) * 100;;
},
isOnPlayer() {
var xd = player.x - this.x;
var yd = player.y - this.y;
return Math.sqrt(xd * xd + yd * yd) < 30;
}
}));
}
function update() {
ctx.clearRect(0, 0, cWidth, cHeight);
enemyList.forEach(enemy => {
if (Math.random() < (1 / 300)) { // 1 in 500 chance to look for player about once every 5 seconds
enemy.setTarget();
}
enemy.update();
if (enemy.isOnPlayer()) {
// do what you need to do here
player.hp -= 0.1;
enemy.x = Math.random() * canvas.width;
enemy.y = Math.random() * canvas.height;
enemy.targetX = null;
}
})
player.update();
// best to update all then draw all
enemyList.forEach(enemy => {
enemy.draw()
});
player.draw();
requestAnimationFrame(update);
}
requestAnimationFrame(update);
createEnemy('E1', 150, 350, 60 / 60);
createEnemy('E2', 250, 350, 60 / 60);
createEnemy('E3', 250, 150, 60 / 60);
document.onclick = function(mouse) {
player.targetX = mouse.clientX;
player.targetY = mouse.clientY;
}
<canvas id="canvas" width="500" height="500" style="margin: 0 auto; border: 1px solid black;"></canvas>