javascript - 当按下左键或右键时仅在 Canvas 中旋转特定图像

标签 javascript html canvas

我是 Canvas 新手,正在开发一款汽车直线移动的游戏,现在我想旋转汽车的图像,仅在按下左键时逆时针旋转,按下右键时顺时针旋转。

目前我正在尝试

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");



var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
    heroReady = true;
};
heroImage.src = "images/car.png";
  if (37 in keysDown) { // Player holding left
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.save();
    ctx.translate(canvas.width,canvas.height);
    ctx.rotate(90*Math.PI/180);
    ctx.drawImage(heroImage,hero.x,hero.y);    
}

但这会旋转整个屏幕。我只想旋转英雄图像而不是屏幕。任何帮助都会受到赞赏。 我的源代码:working pen

最佳答案

获取按键输入并旋转路径以及 Canvas 上没有的内容。

/** SimpleUpdate.js begin **/
// short cut vars 
var ctx = canvas.getContext("2d");
var w = canvas.width;
var h = canvas.height;
ctx.font = "18px arial";
var cw = w / 2;  // center 
var ch = h / 2;
var focused = false;
var rotated = false;
var angle = 0;

// Handle all key input
const keys = {  // key input object
    ArrowLeft : false,  // only add key names you want to listen to
    ArrowRight : false,
    keyEvent (event) {
        if (keys[event.code] !== undefined) {  // are we interested in this key
            keys[event.code] = event.type === "keydown";
            rotated = true; // to turn off help
        }
    }
}
// add key listeners
document.addEventListener("keydown", keys.keyEvent)
document.addEventListener("keyup", keys.keyEvent)

// check if focus click
canvas.addEventListener("click",()=>focused = true);

// main update function
function update (timer) {
    ctx.setTransform(1, 0, 0, 1, 0, 0);  // reset transform
    ctx.clearRect(0,0,w,h);      
    
    // draw outside box
    ctx.fillStyle = "red"
    ctx.fillRect(50, 50, w - 100, h - 100);
    
    // rotate if input
    angle += keys.ArrowLeft ? -0.1 : 0;
    angle += keys.ArrowRight ? 0.1 : 0;
    
    // set orgin to center of canvas
    ctx.setTransform(1, 0, 0, 1, cw, ch);
    
    // rotate
    ctx.rotate(angle);
    
    // draw rotated box
    ctx.fillStyle = "Black"
    ctx.fillRect(-50, -50, 100, 100);
    
    // set transform to center
    ctx.setTransform(1, 0, 0, 1, cw, ch);
    // rotate
    ctx.rotate(angle);
    // move to corner
    ctx.translate(50,50);
    // rotate once more, Doubles the rotation
    ctx.rotate(angle);
    
    ctx.fillStyle = "yellow"
    ctx.fillRect(-20, -20,40, 40);

    ctx.setTransform(1, 0, 0, 1, 0, 0);  // restore default
    
    // draw center box
    ctx.fillStyle = "white"
    ctx.fillRect(cw - 25, ch - 25, 50, 50);
    
    if(!focused){
        ctx.lineWidth = 3;
        ctx.strokeText("Click on canvas to get focus.",10,20);
        ctx.fillText("Click on canvas to get focus.",10,20);
    }else if(!rotated){
        ctx.lineWidth = 3;
        ctx.strokeText("Left right arrow to rotate.",10,20);
        ctx.fillText("Left right arrow to rotate.",10,20);
    }

    requestAnimationFrame(update);

}
requestAnimationFrame(update);


/** SimpleUpdate.js end **/
<canvas id = canvas></canvas>

查看下面的笔是一个会有所帮助的功能。

以下函数将在 Canvas 上绘制缩放和旋转的 Sprite

// draws a image as sprite at x,y scaled and rotated around its center 
// image, the image to draw
// x,y position of the center of the image 
// scale the scale, 1 no scale, < 1 smaller, > 1 larger
// angle in radians
function drawSprite(image, x, y, scale = 1,angle = 0){
    ctx.setTransform(scale, 0, 0, scale, x, y); // set scale and center of sprite
    ctx.rotate(angle);
    ctx.drawImage(image,- image.width / 2, - image.height / 2);
    ctx.setTransform(1,0,0,1,0,0); // restore default transform
                                   // if you call this function many times
                                   // and dont do any other rendering between
                                   // move the restore default line
                                   // outside this function and after all the
                                   // sprites are drawn. 
}

为您提供更多信息。

你的代码到处都是,弄清楚发生了什么的唯一方法就是从头开始重写它。

以下内容符合我认为您希望笔执行的操作。不是我挤压宽度以适合片段窗口。

代码来自 OP pen并进行修改以提供我认为OP想要的内容。

// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 1024;
canvas.height = 1024;
document.body.appendChild(canvas);
var monstersCaught = 0;
var lastFrameTime;
var frameTime = 0;  // in seconds used to control hero speed

// The main game loop
function main (time) {
    if(lastFrameTime !== undefined){
        frameTime = (time - lastFrameTime) / 1000;  // in seconds
    }
    lastFrameTime = time
    updateObjects();
	  render();
	  requestAnimationFrame(main);
};

// this is called when all the images have loaded
function start(){
    monstersCaught = 0;
    resetObjs();
    requestAnimationFrame(main);
}
function displayStatus(message){
    ctx.setTransform(1,0,0,1,0,0); // set default transform
    ctx.clearRect(0,0,canvas.width,canvas.height);
  	ctx.fillStyle = "black";
	  ctx.font = "24px Helvetica";
	  ctx.textAlign = "center";
	  ctx.textBaseline = "center";
	  ctx.fillText(message,canvas.width / 2 ,canvas.height / 2);
}
// reset objects
function resetObjs () {
    monsters.array.forEach(monster => monster.reset());
    heros.array.forEach(hero => hero.reset());
}

// Update game objects
function updateObjects (modifier) {

    monsters.array.forEach(monster => monster.update());
    heros.array.forEach(hero => hero.update());
}

function drawObjects (modifier) {
    monsters.array.forEach(monster => monster.draw());
    heros.array.forEach(hero => hero.draw());
    
}

// Draw everything
function render () {
    ctx.setTransform(1,0,0,1,0,0); // set default transform
    ctx.drawImage(images.background, 0, 0);    
    drawObjects();

	// Score
    ctx.setTransform(1,0,0,1,0,0); // set default transform
  	ctx.fillStyle = "rgb(250, 250, 250)";
	  ctx.font = "24px Helvetica";
	  ctx.textAlign = "left";
	  ctx.textBaseline = "top";
	  ctx.fillText("Points: " + monstersCaught, 32, 32);
}

// hold all the images in one object.
const images = {  // double underscore __ is to prevent adding images that replace these functions
    __status : {
        count : 0,
        ready : false,
        error : false,
    },
    __onready : null,
    __createImage(name,src){
        var image = new Image();
        image.src = src;
        images.__status.count += 1;
        image.onerror = function(){
            images.__status.error = true;
            displayStatus("Error loading image : '"+ name + "'");
        }
        image.onload = function(){
            images.__status.count -= 1;
            if(images.__status.count === 0){
                images.__status.ready = true;
                images.__onready();
            }
            if(!images.__status.error){
                displayStatus("Images remaing : "+ images.__status.count);
            }
        }
        images[name] = image;
        return image;
    }
}

// Handle all key input
const keys = {  // key input object
    ArrowLeft : false,  // only add key names you want to listen to
    ArrowRight : false,
    ArrowDown : false,
    ArrowUp : false,
    keyEvent (event) {
        if (keys[event.code] !== undefined) {  // are we interested in this key
            keys[event.code] = event.type === "keydown";
            event.preventDefault();
        }
    }
}

// default setting for objects
const objectDefault = {
    x : 0, y : 0,
    dir : 0,  // the image rotation
    isTouching(obj){  // returns true if object is touching box x,y,w,h
        return !(this.x > obj.x +obj.w || this.y > obj.y +obj.h || this.x + this.w < obj.x || this.y + this.h < obj.y);
    },
    draw(){
        ctx.setTransform(1,0,0,1,this.x + this.w / 2, this.y + this.h / 2);
        ctx.rotate(this.dir); 
        ctx.drawImage(this.image, - this.image.width / 2, - this.image.height / 2);
    },
    reset(){},
    update(){},
}

// default setting for monster object
const monsterDefault = {
    w : 32, // width 
    h : 32, // height
    reset(){
        this.x = this.w + (Math.random() * (canvas.width - this.w * 2));        
        this.y = this.h + (Math.random() * (canvas.height - this.h * 2));        
    },
}

// default settings for hero
const heroDefault = {
    w : 32, // width 
    h : 32, // height
    speed : 256,
    spawnPos : 1.5,
    reset(){
        this.x = canvas.width /  this.spawnPos;
        this.y = canvas.height / this.spawnPos;        
    }, 
    update(){
        if (keys.ArrowUp) { // Player holding up
            this.y -= this.speed * frameTime;
            this.dir = Math.PI * 0; // set direction
        }
        if (keys.ArrowDown) { // Player holding down
            this.y += this.speed * frameTime;
            this.dir = Math.PI * 1; // set direction
	      }
	      if (keys.ArrowLeft) { // Player holding left
            this.x -= this.speed * frameTime;
            this.dir = Math.PI * 1.5; // set direction
        }
        if (keys.ArrowRight) { // Player holding right
            this.x += this.speed * frameTime;
            this.dir = Math.PI * 0.5; // set direction
        }        
        if(Math.sign(this.speed) === -1){ // filp directio of second car
            this.dir += Math.PI; // set direction
        }
        
        monsters.array.forEach(monster => {
            if(monster.isTouching(this)){
                monster.reset();
                monstersCaught += 1;
            }
        });
        if (this.x >= canvas.width || this.y >= canvas.height || this. y < 0 || this.x < 0) {
            this.reset();
        } 
    }
}

// objects to hold monsters and heros
const monsters = { // dont call a monster "array"
    array : [],  // copy of monsters as array    
};

const heros = { // dont call a monster "array"
    array : [], // copy of heros as array
};

// add monster 
function createMonster(name, settings = {}){
    monsters[name] = {...objectDefault, ...monsterDefault, ...settings, name};
    monsters[name].reset();
    monsters.array.push(monsters[name]);
    return monsters[name];
}

// add hero to heros object
function createHero(name, settings){
    heros[name] = {...objectDefault, ...heroDefault, ...settings, name};
    heros[name].reset();
    heros.array.push(heros[name]);
    return heros[name];
}

// set function to call when all images have loaded
images.__onready = start;

// load all the images
images.__createImage("background", "http://res.cloudinary.com/dfhppjli0/image/upload/v1491958481/road_lrjihy.jpg");
images.__createImage("hero", "http://res.cloudinary.com/dfhppjli0/image/upload/c_scale,w_32/v1491958999/car_p1k2hw.png");
images.__createImage("monster", "http://res.cloudinary.com/dfhppjli0/image/upload/v1491959220/m_n1rbem.png");

// create all objects
createHero("hero", {image : images.hero, spawnPos : 1.5});
createHero("hero3", {image : images.hero, spawnPos : 2, speed : -256});
createMonster("monster", {image : images.monster});
createMonster("monster3", {image : images.monster});
createMonster("monster9", {image : images.monster});
createMonster("monster12", {image : images.monster});

// add key listeners
document.addEventListener("keydown", keys.keyEvent);
document.addEventListener("keyup", keys.keyEvent);
canvas {
   width : 100%;
   height : 100%;
}

关于javascript - 当按下左键或右键时仅在 Canvas 中旋转特定图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43358913/

相关文章:

javascript - 我可以同时热模块重新加载服务器(.NET Core)和客户端(Angular)吗?

javascript - 如何从 JS 浏览器客户端使不可流式传输的 mp4 流式传输?

javascript - 如何在 MVC 中的模型 View 中重置字段编辑器

javascript - HTML Canvas 内容拉伸(stretch)到底部/右侧

Javascript WebWorker - 异步/等待

javascript - youtube 视频没有响应

html - 如何让包裹的 div 水平填充窗口?

html - 垂直对齐从不响应

javascript - 将多个 Canvas 保存为一张图像(制作像 PicFrame 一样的网站)

javascript - 在Javascript中通过ID获取元素的效率如何?