2016-05-17 56 views
3

我已经查看了相关的所有问题,但似乎无法找到所需的东西。我对画布非常新,所以为了练习一些练习,我开始写一个非常小的平台游戏引擎。到目前为止,我已经有了一个方块可以在屏幕上跳跃,但是我的下一步是给这个小方块一个武器。有很多关于如何制造投射物的教程,但没有关于如何制作近战武器(如剑)的教程。所以这就是我想要实现的。在按下按键时在画布上旋转绘制的矩形

这里是立方先生

enter image description here

立方先生需要的武器。我可以添加此我更新功能:

// Draw player 
ctx.fillStyle = player.fill 
ctx.fillRect(player.x, player.y, player.width, player.height); 

// Draw weapon 
ctx.fillStyle = "green"; 
ctx.fillRect(player.x + 20, player.y - 20, 8, 30); 

这让我我想要的外观

enter image description here

所以我得出的武器到像这样的画布,使用x,y值作为玩家x,y值,因此它始终与Cube先生相关。当然,这些会在某些时候换成适当的图形,但这实际上将作为一个看不见的盒子。我的问题是这样的:

如何创建一个旋转此绘制的矩形的函数(如挥动一把剑)。这真让我困惑。什么我想要实现的图像是在这里:

enter image description here

这是我的JavaScript迄今

// Platform game prototyping engine 

// Globals 

player_created = 0; 
environment = 0; 
debug_on = false; 

// Request frames 

(function() { 
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame; 
    window.requestAnimationFrame = requestAnimationFrame; 
})(); 

/** 
    * New Game 
    * @desc Creates canvas and context then sets the height and width 
    * @param [string] canvas - Canvas ID in your HTML 
    * @param [integer] width - Canvas width 
    * @param [integer] height - Canvas height 
    * @param [string] bg - Canvas background color 
*/ 

function new_game(canvas,width,height){ 
    game = document.getElementById(canvas); 
    ctx = game.getContext("2d"); 
    game.width = width; 
    game.height = height; 

} 

/** 
    * New Player 
    * @desc Creates a single player on the canvas 
    * @param [integer] x - Player x position on canvas 
    * @param [integer] y - Player y position on canvas 
    * @param [integer] width - Player width 
    * @param [integer] height - Player height 
    * @param [integer] speed - Player movement speed 
    * @param [integer] jumpVel - Player jump amount 
    * @param [string] fill - Player fill color 
*/ 

function new_player(x,y,width,height,speed,jumpVel,fill){ 
    player = { 
     x: x, 
     y: y, 
     width: width, 
     height: height, 
     fill: fill, 
     speed:speed, 
     velX:0, 
     velY:0, 
     jumpVel:jumpVel, 
     jumping: false 
    } 
    keys = []; 

    ctx.fillStyle = player.fill; 
    ctx.fillRect(player.x, player.y, player.width, player.height); 
    ctx.fill(); 
    player_created = 1; 
} 

/** 
    * New Environment 
    * @desc Creates the game environment 
    * @param [integer] friction - Sets the environment platfrom friction 
    * @param [integer] gravity - Sets the environemnt gravity 
*/ 

function new_environment(friction,gravity){ 
    environment = { 
     friction: friction, 
     gravity: gravity 
    } 
    document.body.addEventListener("keydown", function(e) { 
     keys[e.keyCode] = true; 
    }); 
    document.body.addEventListener("keyup", function(e) { 
     keys[e.keyCode] = false; 
    }); 
} 

function debug(){ 
    ctx.font = "11px Verdana"; 
    ctx.fillStyle = "white"; 
    ctx.fillText('Velocity X: ' + player.velX,20,30); 
    ctx.fillText('Velocity Y: ' + player.velY,20,50); 
    ctx.fill(); 
} 

function update(){ 
    ctx.clearRect(0,0,game.width,game.height); 
    if(player_created == 1){ 

     // Draw player 
     ctx.fillStyle = player.fill 
     ctx.fillRect(player.x, player.y, player.width, player.height); 

     // Draw weapon 
     ctx.fillStyle = "green"; 
     ctx.fillRect(player.x + 20, player.y - 20, 8, 30); 

     if(environment == 0){ 
      console.log('%c No environment has been created! ', 'background: #222; color: #bada55'); 
     } 
     if (keys[38]) { 
      // up arrow or space 
      if(!player.jumping){ 
       player.jumping = true; 
       player.velY = -player.jumpVel; 
      } 
     } 
     if (keys[39]) { 
      player.velX =+ player.speed;   
     }  
     if (keys[37]) {     
      player.velX =- player.speed; 
     } 

     player.y += player.velY; 
     player.x += player.velX; 
     player.velY += environment.gravity; 
     player.velX *= environment.friction; 

     if (player.x >= game.width-player.width) { 
      player.x = game.width-player.width; 
     } else if (player.x <= 0) {   
      player.x = 0;  
     } 

     if(player.y >= game.height - player.height){ 
      player.y = game.height - player.height; 
      player.jumping = false; 
     } 
    } 
    if(debug_on == true){ 
     debug() 
    } 
    requestAnimationFrame(update); 
} 

window.addEventListener("load", function(){ 
    update(); 
}); 

new_game('game',600,600) 
new_player(250,250,20,20,4,20,'red') 
new_environment(.9,1) 

真人版可以在这里找到

http://codepen.io/jcoulterdesign/pen/d6308fc86305d70c875c30f9452aa4d6?editors=1010

谢谢提前!

回答

2

在绘制矩形之前使用ctx.rotate()函数,然后恢复旋转。

后96 if(player_created == 1){行添加以下代码在您的示例开始:

ctx.save(); // save current rotation and coordinates 
ctx.translate(player.x + player.width, player.y); // set canvas draw start to new rect coordinates 
ctx.rotate(Math.PI/4); // 45 degrees for example 
ctx.fillStyle = 'green'; 
ctx.fillRect(0, -25, 10, 30); // 10 by 30 rect, shifted 25 y up 
ctx.restore(); // restore to old rotation and coordinates 
ctx.fillStyle = 'red'; 
+0

这是伟大的。所以,如果我把它钩到按键上,我可以随着时间改变旋转值。换句话说,它将动画旋转而不是捕捉它? –

+1

是的,对于动画,您将不得不将当前旋转存储在变量中,并根据按钮按下的时间增加/减少变量。 您已经使用requestAnimationFrame,因此您可以在更新函数的第一个参数中查找自启动动画以来所经过的时间。将函数update(){'更新为'function update(thisLoop){'和console.log(thisLoop)来检查时间戳。为避免第一次运行时未定义变量thisLoop,请将动画开始(示例中的第138行)更改为:'requestAnimationFrame(update);' – M4tini

+1

好回答upvote。就性能而言:'save&restore'将保存并恢复所有的上下文属性(不仅仅是translate和rotate转换)。只撤销翻译,旋转更有效。通过以相反的顺序调用原始转换以负值执行此操作:'ctx.rotate(-Math.PI/4); ctx.translate(-player.x-player.width,-player.y)'。或者用'ctx.setTransform(1,0,0,1,0,0)';-)重置所有转换为“未转换” – markE