0

我的javascript代码有问题。我正在尝试创建一组移动的圆圈,其中每个圆圈都有自己的属性。到目前为止,我已经设法将所有需要的值输入到一个数组中,但我不知道如何正确使用它们在画布上绘图。

这是javascript:

var radius = 10;
var step = x = y = 0;
var r = g = b = 255;
var circleHolder = [];
var loop = setInterval(function(){update();}, 30);

function Circle(x, y, radius, r, g, b)
{
    this.x = x;
    this.y = y;
    this.radius = radius;
    this.r = r;
    this.g = g;
    this.b = b;
    circleHolder.push(this);
}

Circle.prototype.draw = function()
{
    Circle.prototype.ctx = document.getElementById("MyCanvas").getContext("2d");
    Circle.prototype.ctx.clearRect(0,0,720,720); // clear canvas
    Circle.prototype.ctx.beginPath();
    Circle.prototype.ctx.strokeStyle = "rgb("+ this.r +", "+ this.g +", "+ this.b +")";
    Circle.prototype.ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
    Circle.prototype.ctx.stroke();
}

Circle.prototype.update = function ()
{
    step += .02;
    step %= 2 * Math.PI;
    this.x = parseInt((Math.sin(step)) * 150) + 360;
    this.y = parseInt((Math.cos(step)) * 150) + 360;
    this.radius += 16;
    if (this.radius > 200)
    {
        for (i in circleHolder)
        {
            if (circleHolder[i]==this)
            {
                circleHolder.splice(i, 1);
            }
        }
    }
}

function update()
{
    var ci = new Circle(x, y, radius, r, g, b);
    for (i in circleHolder)
    {
        ci = circleHolder[i];
        ci.update();
        ci.draw();
    }
}

我很确定我的问题在于 update() {} 但我不知道如何正确地做到这一点。


编辑:好的,我已经完成了一些更改!检查这个小提琴!我在控制台中收到“ci not defined”错误,它有一个奇怪的错误:将“if(this.radius > 128)”更改为更高的整数,它会使圆圈旋转得更快,我不知道为什么。如果您愿意,可以尝试将其更改为 256,看看会发生什么。

for (var i=0; i < allCircles; i++)
        {
            ci = circleHolder[i]; <----- This is causing the error
            ci.update();
            ci.draw();
        }
4

2 回答 2

1

我不是 100% 清楚你要做什么,但我试图解决主要问题

一个问题是你的for循环......你不应该使用for in数组,而是这样做:

for (var i=0 ; i<circleHolder.length ; i++)
{
    ci = circleHolder[i];
    ci.update();
    ci.draw();
}

看到这个小提琴

此外,我将您的获取上下文和其他应该只发生一次的事情移到了构造函数中,而不是在更新函数中。

您还在每次绘制之前清除画布,因此它只会显示每帧最后绘制的圆圈。(如果您删除它,clearRect它看起来像是那些旧的螺旋计之一)。

您还用(255,255,255)(白色)绘制了圆圈,因此在更改颜色之前它不会显示。

编辑:

这段代码确实存在一些问题:

如果您打算拥有许多,则上下文不应在圆形类中。

您应该有一些对象,其中包含画布/上下文和所有圆圈的数组。

然后让该对象管理更新/绘图。

于 2012-09-27T18:37:13.357 回答
1

对于初学者来说,除非有其他事情发生,在这段代码之外:

for ... in ...在数组上使用,for-in 用于对象,当在数组上使用时,大多数浏览器将包含 and 之类的方法.splice.forEach而不仅仅是数字0...n索引。

function splice () {}.draw();结局不好。

另外,页面背景的颜色是什么?您将每个圆圈的 rgb 颜色设置为 100% 白色。你也在清理画布……这很可能意味着整个事情都是透明的。所以如果你有一个透明的画布、白色的圆圈和一个白色的背景,你很可能根本看不到任何东西,如果这甚至可以正常工作而不会吐出错误的话。

以一种让你跟随正在发生的事情的方式来移动你的逻辑可能更有意义。

如果你创建了一个圆形构造函数,除了创建一个新的圆形之外别无他法。

在您的更新中,创建一个圈子。
然后将其放入您的圈子集合中(而不是圈子构造函数中)。

在大型应用程序中,您通常会对所有对象调用 update 然后对所有对象调用 draw,而不是一次更新和绘制一个。例如,想象一个游戏,它在吸引你并让你移动之前不费心检查你是否被子弹击中。

所以在你的循环里面,你应该有一个update和一个draw。在 内update,创建您的圈子,将它们添加到列表中并更新它们的位置。在 内draw,画圆圈。

将来,这将为您带来诸如碰撞检测之类的好处,而无需每帧多次重绘所有内容。

此外,不要在将被多次调用的函数内部进行 DOM 访问(Circle.draw)。这将在未来摧毁你的帧率。

相反,向函数传递一个依赖项(画布)。

// inside of the main game's scope
var screen = document.getElementById(...).getContext("2d");


// inside of your new draw function, in the animation/game loop
var i = 0, allCircles = circleHolder.length, currentCircle;

for (; i < allCircles; i += 1) {
    currentCircle = circleHolder[i];
    currentCircle.draw(screen);
}
于 2012-09-27T18:49:59.233 回答