9. 實現類似星球大戰遊戲風格的漂移

9.Catch My Drift: a post about implementing asteroids-style drifting

This post is about implementing drifting movement (a la asteroids), and draws together several previous posts.

這篇帖子討論如何實現飄移(以星球大戰爲例),並把前面帖子的內容綜合一下。

There are various simple movement schemes that you can implement in games. We’ve used one in our previous posts:moving at a fixed speed (with steering). Another is what I will call asteroids-style movement: you have a persistent velocity (or “drift”), and you can apply thrust in a particular direction to change the velocity. It’s hard to describe it simply in text, so the best way to get an idea of what I’m talking about is togo have a play with the scenario.

在遊戲中你可以實現各種各樣簡單的運動設計。在前面的帖子中我們使用了一種:以固定的速度移動(結合轉向)。另一種是我將稱爲星球大戰類型的運動:擁有持續的速率(或“漂移”),同時能夠在某個特定的方向運用推力來改變速率。這很難用文字簡單地進行描述,因此要了解我說的什麼意思最好去玩一下相關的遊戲劇本

In this post, we will implement drifting. To do this, we must create a variable to hold the current speed in the X direction, and the current speed in the Y direction. Each frame we add the current speeds onto the current position.

在這篇帖子裏,我們將實現飄移。爲了達到目的,我們必須創建一個變量來保存當前x方向和y方向的速度值。每一幀我們把當前的速度值加到當前的座標上去。

The key aspect of implementing drift-style movement is that when we press a key to move, instead of adding some amount to the currentposition, we add some amount (known as acceleration) to the currentspeed, which in turn will be added to the current position in each of the future frames. We’ve already seen this technique inthe previous post on falling, so we can form a rough skeleton of our code:

實現類似飄移運動的關鍵部分是,當按下某個鍵來移動時,我們並不是增加當前座標值,而是增加速度值(加速度),相應地在每個下一幀將其累加到當前座標上。我們在之前討論下落的帖子裏已經瞭解了這個技術,因此我們可以形成如下代碼框架:

    private double speedX;
    private double speedY;

    public void act() 
    {
        doTurn();

        doMove();
    }

    private void doMove()
    {
        if (Greenfoot.isKeyDown("up"))
        {
            setImage("rocket.png");
            
            speedX = speedX + ???;
            speedY = speedY + ???;
        }
        else
        {
            setImage("rocket_nothrust.png");
        }

        setLocation(getX() + (int)speedX, getY() + (int)speedY);
    }

(We’ll additionally use the doTurn method from our turning example, and alsothe world-wrapping code from our world-wrapping example.)

(我們將額外地使用在轉向示例中提到的doTurn方法,以及在世界捲動示例中提到的座標捲動代碼。)

So we have persistent variables for speedX and speedY, declared as members of our Spaceship class. We add these speeds to our position each frame, on the last line of the code above. We also have some code to change the image of the rocket when we are accelerating/drifting. The bit that still needs filling in is how to adjust the speed each frame.

於是我們擁有了持久的變量speedX 和speedY,並把它們定義爲Spaceship 類的成員變量。每一幀我們把這些速度值累加到座標上,如上述代碼的最後一行所示。我們也通過一些代碼來改變火箭加速/飄移時的圖像。現在有待完成的是如何在每一幀中去調準速度值。

We want to add an appropriate acceleration to our speed, based on which direction we’re facing. We want to accelerate a certain amount in the direction we are pointing. This is exactly the same principle asan earlier post, where we wanted to move a certain amount in the direction we are pointing. The only difference is that instead of moving, we add to our speed:
我們希望在當前所處的方向上給速度增加一個加速度值。我們希望在當前方向增加一個固定值。這和
之前帖子討論的原理是一致的。唯一的區別在於我們增加的是速度值,而不是移動距離:

            double radians = Math.toRadians(getRotation());
            double moveSpeed = 0.1;

            double accX = Math.cos(radians) * moveSpeed;
            double accY = Math.sin(radians) * moveSpeed;

            speedX = speedX + accX;
            speedY = speedY + accY;

You can have a play with the finished scenario, or view its full source code in Greenfoot. You may notice that its speed can increase to unlimited amounts — we will fix that in a forthcoming post.

你可以玩一下完成後的遊戲劇本,或者在Greenfoot中查看完整代碼。你可能會注意到其速度值可以無限增加——我們將會在接下來的帖子中進行修正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章