【问题标题】:Adding image to moving and colliding circles将图像添加到移动和碰撞的圆圈
【发布时间】:2013-09-03 02:28:36
【问题描述】:

我目前有一堆球(圆圈)在一个盒子里弹跳并相互碰撞。

现在它们是普通的绿色球。但我想为这个圈子使用一张图片。

我该怎么做?这是我的渲染函数。

  function render() {
  var ball;
  context.fillStyle = "#008800";
  for (var i = 0; i <balls.length; i++) {
     ball = balls[i];
     ball.x = ball.nextx;
     ball.y = ball.nexty;
     context.beginPath();
     context.arc(ball.x,ball.y,ball.radius,0,Math.PI*2,true);
     context.closePath();
     context.fill();
  }

有什么想法吗?可能吗?如果没有,有没有其他方法可以实现球与图像的弹跳和碰撞?

【问题讨论】:

    标签: javascript html canvas three.js


    【解决方案1】:

    您可以通过三种方式做到这一点:

    方法一——使用图案填充球

    定义要用作图案的图像:

    /// create a pattern
    var pattern = context.createPattern(img, 'repeat');
    

    现在您可以将图案用作填充样式而不是绿色:

    context.fillStyle = pattern;
    

    但是,由于图案总是在坐标的 origo(默认 0, 0)处绘制,因此您需要为每个移动进行平移。幸运的是没有那么多额外的代码:

    /// to move pattern where the ball is
    context.translate(x, y);
    
    context.beginPath();
    
    /// and we can utilize that for the ball as well so we draw at 0,0
    context.arc(0, 0, radius, 0, Math.PI * 2);
    context.closePath();
    
    context.fillStyle = pattern;
    context.fill();
    

    现在,根据您想要的移动方式,您周围的球可能需要也可能不需要每次都平移回来。

    Here's an online demo showing this approach.

    方法 2 - 使用路径裁剪来裁剪图像以适应球

    我们可以使用 drawImage 来代替图案来绘制图像。但是,问题在于这将绘制一个正方形,因此除非您创建一个球形图像,该图像适合您的球顶部且具有透明像素。

    因此,您可以使用裁剪来实现与使用模式方法相同的效果:

    这里只需要多几行:

    /// define the ball (we will use its path for clipping)
    context.beginPath();
    context.arc(x, y, radius, 0, Math.PI * 2);
    context.closePath();
    
    /// as we need to remove clip we need to save current satte
    context.save(); 
    
    /// uses current Path to clip the canvas
    context.clip();
    
    /// draw the ball which now will be clipped
    context.drawImage(img, x - radius, y - radius);
    
    /// remove clipping
    context.restore();
    

    Here's an online demo of this approach.

    方法 3 - 将球预剪辑为图像

    在 Photoshop 或一些类似程序中制作一个球,然后将其绘制为图像,而不是绘制然后填充的弧。

    您只需绘制球,而不是使用圆弧创建路径:

    drawImage(ballImage, x - radius, y -radius);
    

    如果您需要绘制不同尺寸,只需将调用扩展到:

    drawImage(ballImage, x - radius, y - radius, radius, radius);
    

    如果性能很关键,这是要走的路,因为它比其他两种方法性能更好,但不如它们灵活。

    如果您需要在灵活性和性能之间取得平衡,那么剪辑方法似乎是最佳选择(这可能因浏览器而异,因此请测试一下)。

    Here's an online demo with drawImage

    【讨论】:

    • 肯 - 哇!很抱歉回复晚了,但答案是什么!谢谢你。我会尝试让其中一个工作:)
    • @CheesePuffs 如果答案有用/解决了问题,请不要忘记投票/接受 :-)
    • 肯 - 我做到了!这非常有效。现在我有了我的图像。现在我只需要弄清楚如何旋转图像,我就完成了:)
    【解决方案2】:

    检查drawImage 函数。这允许您在画布上的坐标点绘制图像。它采用Image 实例作为它的第一个参数以及各种其他位置和裁剪值。引用上面链接的 MDN 页面:

    drawImage(image, dx, dy, dw, dh, sx, sy, sw, sh)

    图片 要绘制到上下文中的元素;该规范允许任何图像元素(即&lt;img&gt;&lt;canvas&gt;&lt;video&gt;)。某些浏览器,包括 Firefox,允许您使用任意元素。

    dx 目标画布中放置源图像左上角的 X 坐标。

    dy 目标画布中放置源图像左上角的 Y 坐标。

    dw 在目标画布中绘制图像的宽度。这允许缩放绘制的图像。如果不指定,则图像不 绘制时按比例缩放。

    dh 在目标画布中绘制图像的高度。这允许缩放绘制的图像。如果不指定,则图像不 绘制时按高度缩放。

    sx 要绘制到目标上下文中的源图像子矩形左上角的 X 坐标。

    sy要绘制到目标上下文中的源图像子矩形左上角的 Y 坐标。

    sw 要绘制到目标上下文中的源图像的子矩形的宽度。如果未指定,则整个矩形从 由 sx 和 sy 指定的坐标到右下角 图像被使用。如果指定负值,则图像为 绘制时水平翻转。

    sh 要绘制到目标上下文中的源图像的子矩形的高度。如果指定负值,则 绘制时图像垂直翻转。

    在您的情况下,您可以将路径绘制功能替换为drawImage

    var img = new Image;
    img.onload = function() {
        //You have to make sure the image is loaded first
        //Begin rendering!
        render();
    };
    
    img.src = "path/to/your/ball/img.png"
    
    function render() {
      var ball;
      context.fillStyle = "#008800";
      for (var i = 0; i <balls.length; i++) {
         ball = balls[i];
         ball.x = ball.nextx;
         ball.y = ball.nexty;
         context.drawImage(img, ball.x - (img.width/2), ball.y - (img.height/2)); //Make x, y the centerpoint
      }
    }
    

    【讨论】:

    • 阿德里安 - 谢谢你的回答!一定会试试这个!
    猜你喜欢
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多