如何获取在画布上移动的图像的X和Y坐标

时间:2017-03-11 19:57:07

标签: javascript image canvas coordinates

当我在画布周围移动player.hero的图像时,我想要一个包含英雄当前x和y pos的变量。所以我可以让僵尸图像朝着英雄的当前位置移动。谢谢,如果到目前为止我的代码很糟糕,请提出修改意见。

(function() {

    var canvas, context, width, height, speed = 8;    
    var interval_id;
    var zombies = [];
    var bullets = [];

    var moveLeft = false;
    var moveRight = false;
    var moveUp = false;
    var moveDown = false;

    var player = {
        x : 0,
        y : 0,
        width : 35,
        height : 60,
        hero : new Image(),
    };

    for (var i = 0; i < 10; i += 1){
        var zombie = {
            x : 10,
            y : 10,
            undead : new Image(),
            targetToGox : 0,
            targetToGoy : 0,
         };
         zombies.push(zombie);
    }
    var mouse = {
        x : 0,
        y : 0,
    }

    document.addEventListener('DOMContentLoaded', init, false);

    function init() {    
        canvas = document.querySelector('canvas');
        context = canvas.getContext('2d');
        width = canvas.width;
        height = canvas.height;
        player.x = width / 2 - 18;
        player.y = height / 2 - 30;
        player.hero.src = 'hero.png';
        zombie.undead.src = 'zombie.png';
        //context.drawImage(player.hero, player.x, player.y);  
        window.addEventListener("keydown", activate,false);
        window.addEventListener("keyup",deactivate,false);
        //window.addEventListener("mouseover", drawImagePointingAt, false);
        interval_player = window.setInterval(drawPlayer, 33);
    }

    function drawPlayer() {
        context.clearRect(0 ,0 ,width, height);
        context.drawImage(player.hero,player.x, player.y);
        //******** need zombie to go to position of player.hero******///
        context.drawImage(zombie.undead (somthing for x and y coordinats of player.hero);
        // stops player moveing beyond the bounds of the canvas
        if (player.x + player.width >= width) {
            moveRight = false
        }
        if (player.y + player.height >= height) {
            moveDown = false
        }
        if (player.x  <= 0) {
            moveLeft = false
        }
        if (player.y <= 0) {
            moveUp = false
        }     
        if (moveRight) {
            player.x  += speed;
        }
        if (moveUp) {
            player.y -= speed;
        }
        if (moveDown) {
            player.y += speed;
        }
        if (moveLeft){
            player.x -= speed;
        }

    function activate(event) {
        var keyCode = event.keyCode;
            if (keyCode === 87){
                moveUp = true;
            }
            else if (keyCode === 68){
                moveRight = true;
            }
            else if (keyCode === 83){
                moveDown = true;
            }
            else if (keyCode === 65){
                moveLeft = true;
            }

    }
    function deactivate(event) {
        var keyCode = event.keyCode;
            if (keyCode === 87){
                moveUp = false;}
            else if (keyCode === 68){
                moveRight = false;}
            else if (keyCode === 83){
                moveDown = false;}
            else if (keyCode === 65){
                moveLeft = false;}
    }
    function getRandomNumber(min, max) {
        return Math.round(Math.random() * (max - min)) + min;
    }
    function stop() {
        clearInterval(interval_player);

    }
})();

2 个答案:

答案 0 :(得分:2)

这是一个很长的文本墙,关于为什么我认为重新构建代码而不是“...获取我在屏幕上移动的图像的X和Y坐标”会更好“< / em>的。

这篇文章的结尾包含一个脚本,试图展示你如何做到这一点。

您询问了代码的质量。对于新程序员来说,你的代码可怕,但随着你的代码库变大,你陷入一些经典的陷阱会很痛苦。

这方面的一个例子可能是保持玩家在按键之后应该移动的每个可能方向的变量(在单独的函数中被操纵和使用)。问题在于,当您决定更改此系统的任何方面时,它将崩溃。

相反,考虑让一个对象代表玩家,它包含了自己的内部逻辑,通过改变它自己的坐标来“移动”。

我无法强调这个想法 - 优秀的黑客总是给自己一个工作空间。你不应该(例如)让Player 直接操纵游戏绘图程序。这是一个普遍存在的概念,软件工程中实际上存在着这个组织原则的不同方面的词汇(像'Encapsulation'或'Loose coupling'或'{{ 3}}“)。 非常重要。

这引出了另一个观点:全局变量。

这是一个更难的,因为它是一个所有程序员最终制造自己伪君子的人,如果他们过于批评它(特别是如果他们做低级别的工作)。尽管如此,最好整合你所拥有的全局变量,并且可能创建充当“外部世界”接口的函数。

在你的游戏中,这意味着像moveLeft一样移动到“游戏循环”中,只需检查所有“对象”坐标,清除屏幕和屏幕。适当地绘制这些对象。

这里的另一个重要想法是“重复”功能应该共享一个方法。在您的情况下,这将导致PlayerZombie成为一些更抽象类别的实例,我将其命名为GameObject。这允许您为GameObject编写一次所有主要函数,并在PlayerZombie内“继承”其功能(有许多Law of Demeter,{{3} },如何在没有原型或继承的情况下完成此任务)

考虑到所有这一切,我试着花20分钟鞭打一些可以带给你工作的东西。如果这与你的目标完全无关,至少你可以在你的腰带下进行另一轮可能毫无意义的互联网教育。

我的代码的“继承”是以一种非常简单的Javascript风格完成的,即使有不少于十几种“新的和改进的”方法来共享JS中的代码之间的实现细节,每种方式都有很多种。他们深入坚持原型或面向对象编程的原则。

我不能希望报道邮票,jSL,甚至Javascript现在臭名昭着other,所以我建议你阅读这些内容并将它们自己用于盈利,但是现在我坚持使用基础知识

const ZOMBIE_COUNT = 10

function GameState() {
    this.player  = null;
    this.enemies = []
}
var Game = new GameState() // our global game state

// An abstract 'game object' or character
function GameObject({x, y, image}) {
    this.x = x
    this.y = y
    this.image = image
}
GameObject.prototype.draw = function() {
    Game.ctx.fillStyle = this.color
    Game.ctx.fillRect(this.x, this.y, 10, 10)
}
GameObject.prototype.moveLeft =  function(n) { if(this.x > 0) this.x -= n }
GameObject.prototype.moveRight = function(n) { if(this.x < Game.width) this.x += n }
GameObject.prototype.moveDown =  function(n) { if(this.y < Game.height) this.y += n}
GameObject.prototype.moveUp =    function(n) { if(this.y > 0) this.y -= n }

function Player({x, y, width}) {
    GameObject.call(this, {x, y}) // setup x, y & image
    this.color = 'red'
}
Player.prototype = Object.create(GameObject.prototype, {})

function Zombie({x, y, target}) {
    GameObject.call(this, {x, y}) // setup x, y & image
    this.target = target // target contains the player
    this.color = 'blue'
}
Zombie.prototype = Object.create(GameObject.prototype, {})
Zombie.prototype.moveToPlayer = function() {
    let {x, y} = Game.player
    // very basic 'movement' logic
    if (this.x < x) {
        this.moveRight(1/4)
    } else if (this.x > x) {
        this.moveLeft(1/4)
    }

    if (this.y > y) {
        this.moveUp(1/4)
    } else if (this.y < y) {
        this.moveDown(1/4)
    }
}


function init() {
    var canvas = document.getElementById('canvas')
    if (canvas.getContext) {
        var ctx = canvas.getContext('2d')
    } else {
        console.log("No canvas")
        return -1
    }

    let {width, height} = canvas

    // Setup our game object
    Game.width = width
    Game.height = height
    Game.ctx = ctx
    // Create our player in the middle
    Game.player = new Player({x: width / 2, y: height / 2})

    // Create our enemies
    for(let i = 0; i < ZOMBIE_COUNT; i++) {
        Game.enemies.push(new Zombie({x: Math.random() * width  | 0, // truncate our value
                                      y: Math.random() * height | 0}))
    }

    game_loop()
}

function game_loop() {
    window.requestAnimationFrame(game_loop)
    Game.ctx.fillStyle = 'white'
    Game.ctx.fillRect(0, 0, Game.width, Game.height);
    Game.player.draw()

    Game.enemies.map(enemy => {
        enemy.moveToPlayer()
        enemy.draw()
    })
}

function process_key(ev) {
    let speed = 3
    let key = ev.keyCode
    if (key === 68)
        Game.player.moveRight(speed)
    if (key === 87)
        Game.player.moveUp(speed)
    if (key === 65)
        Game.player.moveLeft(speed)
    if (key === 83)
        Game.player.moveDown(speed)
}

window.addEventListener('keydown', process_key, false);

init()
canvas { border: 3px solid #333; }
<canvas id="canvas" width="400" height="400"></canvas>

答案 1 :(得分:1)

我认为你的意思是这条线?

//******** need zombie to go to position of player.hero******///
context.drawImage(zombie.undead (somthing for x and y coordinats of player.hero);

我会将代码更改为:

function init() {    
  ...
  interval_player = window.setInterval(updateGame, 33);
}

function updateGame() {
    context.clearRect(0 ,0 ,width, height);
    updatePlayer();
    for (let zombie of zombies) {
       updateZombie(zombie);
}

function updatePlayer() {
    // stops player moveing beyond the bounds of the canvas
    if (player.x + player.width >= width) {
        moveRight = false
    }
    if (player.y + player.height >= height) {
        moveDown = false
    }
    if (player.x  <= 0) {
        moveLeft = false
    }
    if (player.y <= 0) {
        moveUp = false
    }     
    if (moveRight) {
        player.x  += speed;
    }
    if (moveUp) {
        player.y -= speed;
    }
    if (moveDown) {
        player.y += speed;
    }
    if (moveLeft){
        player.x -= speed;
    }
    context.drawImage(player.x, player.y);
}

function updateZombie(zombie) {
  // Move zombie closer to player
  if (zombie.x > player.x)
     zombie.x -= zombieSpeed;
  else if (zombie.x < player.x)
     zombie.x += zombie.Speed;

  if (zombie.y > player.y)
     zombie.y -= zombieSpeed;
  else if (zombie.y < player.y)
     zombie.y += zombie.Speed;

  context.drawImage(zombie.undead, zombie.x, zombie.y);
}

这一行:

zombie.undead.src = 'zombie.png';

只会更改最后创建的僵尸。你真的需要移动它:

for (var i = 0; i < 10; i += 1) {
    var zombie = {
        x : 10,
        y : 10,
        undead : new Image(),
        targetToGox : 0,
        targetToGoy : 0,
     };
     zombie.undead.src = 'zombie.png'; 
     zombies.push(zombie);
}