如果你看到这则信息,这表示下载可汗学院的外部资源时遇到困难.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

主要内容

交互场景

现在我们会做精美的动画情景,我们要保证可以处理另外那种非静态的场景:对用户的互动进行反应。例如,我们要绘制小黄鸭生宝宝的情景(当然,这是在他的摇滚明星阶段以后)-- 但我们还要让用户点击而给小黄鸭更多宝宝。因为我们这世界上总可以用更多黄鸭宝宝,对吧?
以下是这个情景作为独立的程序会是什么样子的。程序绘制情景静态的部分,然后在 mouseClicked(鼠标点击事件) 中,它在鼠标点击的位置绘制黄鸭宝宝的图像,把它们放在该处原已有的任何东西上面。
我们会怎样将这个整合到我们多场景的程序中呢?好吧,我们会先把所有静态绘制的代码都放进一个绘制场景的函数 drawScene5() 并为 mouseClicked 加上换场景的逻辑:
var drawScene5 = function() {
    currentScene = 5;
    background(173, 239, 255);
    fill(7, 14, 145);
    textSize(39);
    text("Winston has babies!", 10, 47);
    ...
};

mouseClicked = function() {
    if (currentScene === 1) {
        drawScene2();
    } else if (currentScene === 2) {
        drawScene3();
    } else if (currentScene === 3) {
        drawScene4();
    }  else if (currentScene === 4) {
        drawScene5();
    } else if (currentScene === 5) {
        drawScene1();
    }
};
如下所示:
但我们如何整合 mouseClicked 的功能呢?我们已经在代码中定义了 mouseClicked,我们不能再次定义它。在 Javascript 中,最后的函数定义 “赢”,它会覆盖之前的任何定义。也就是说,我们要在现有的 mouseClicked 中找个好地方来放那行画宝宝的代码。让我们谈谈几种选择:
1. 我们可以把这行放在函数的上面:
mouseClicked = function() {
    image(getImage("creatures/BabyWinston"), mouseX-20, mouseY-20);
    ...
};
这样,每次用户点击鼠标它都会被调用,即使不是绘制宝宝的场景 (如果黄鸭宝宝有了宝宝就怪了)。这样是不对的。
2. 我们可以把这行放在 currentScene === 4 的 if 语句中:
mouseClicked = function() {
    if (currentScene === 1) {
        drawScene2();
    } else if (currentScene === 2) {
        drawScene3();
    } else if (currentScene === 3) {
        drawScene4();
    }  else if (currentScene === 4) {
        drawScene5();
        image(getImage("creatures/BabyWinston"), mouseX-20, mouseY-20);
    } else if (currentScene === 5) {
        drawScene1();
    }
};
归根到底,我们就在哪儿调用 drawScene5(),而宝宝应该在哪被加到第 5 个场景。但想想:这就意味着我们 每次 画这个场景时都会多画一个宝宝。这也意味着我们永远不再画 更多 宝宝了,因为 currentScene 会被改成 5,而 if 语句中的代码不再会被执行。
3. 我们可以把这行放在 currentScene === 5 的 if 语句中:
mouseClicked = function() {
    if (currentScene === 1) {
        drawScene2();
    } else if (currentScene === 2) {
        drawScene3();
    } else if (currentScene === 3) {
        drawScene4();
    }  else if (currentScene === 4) {
        drawScene5();
    } else if (currentScene === 5) {
        image(getImage("creatures/BabyWinston"), mouseX-20, mouseY-20);
        drawScene1();
    }
};
也就是说,我们直到初次绘制这个场景后的第一次点击前都不会画宝宝。但是,正如你在之后这一行可见,宝宝会立刻被第 1 个场景代替。
在此我们发现了整合宝宝点击场景这个主意的致命缺点:我们在用完全相同的互动 -- 屏幕上任何位置的鼠标点击 -- 来切换场景并且进行场景内的互动。现在我们真的有了个难题,我们要考虑更彻底的方法来整合这个场景。
4. 我们可以在最后停止重画场景 1,并在此时告诉用户重启。 当然,那会有效,但是前提是我们的点击控制的场景必须是最后一个。那如果我们想要一个早一些的点击控制的场景呢?这个方法就会失败。
5. 我们可以用另外一种互动 - 例如 mouseDragged。  那会有效,因为拖动鼠标不会引起点击的事件发生。我们还要确认 currentScene === 5,以保证拖动在其它场景中不会画宝宝。
mouseDragged = function() {
    if (currentScene === 5) {
        image(getImage("creatures/BabyWinston"), mouseX-20, mouseY-20);
    }
};
下面来试试,确保你在最后一个场景拖动:
这样,这似乎有效,但我有点担心小黄鸭最后会有多少宝宝。总而言之,这不是理想的方法,因为这意味着我们必须避免设计对点击鼠标有反应的场景。我们不想有这样的限制,一定还有更好的方法。
如果我们把点击鼠标根据位置区别,使一个位置的点击表示切换场景,而其它位置的点击为场景内的互动,会怎么样?如你所知,就像一个按钮!其实,大部分多场景的程序都是这样处理这个问题的,我们接下来会谈这个问题。

想加入讨论吗?

尚无帖子。
你会英语吗?单击此处查看更多可汗学院英文版的讨论.