20.機器人逃犯:在網格中射擊

20.Robotic Outlaws: Shooting on a grid

Recently, we’ve seen how to find your way around a grid, and how to draw a line between two points, choosing which pixels to illuminate. Now we’ll move on to game which will use both these techniques: creating a game where you must fend off some robots. In this game, a bunch of robots have gone haywire and are trying to squash you! As the player, you must fired at the robots to deactivate them, before they can reach you.

最近我們已經瞭解瞭如何在網格中尋找路徑,以及如何在兩點之間繪製一條線。現在我們將使用這兩種技巧來繼續改進遊戲:創建一個遊戲,在其中你必須躲開一些機器人。在這個遊戲中,有一幫發瘋的機器人來追殺你!作爲遊戲者,你必須在機器人追上你之前向它們射擊來阻止它們。

Our robot game is to going to feature a grid. Each square can be empty, have a wall, be occupied by a robot or by the player. We need to implement two main aspects of our game: moving, and shooting.

我們的機器人遊戲打算採用網格形式。每一個方格可以爲空,擁有一堵牆,被機器人或玩家佔據。我們需要實現遊戲的兩個主要方面:移動,以及射擊。

Moving

移動

Our game will have the player character, and several robot opponents. These robot opponents will have very simple logic: they will move towards the player each turn. We’ve already seen how to do pathfinding, so we can re-use this code to know which way the robots should move so that they head towards the player.

我們的遊戲將擁有一個玩家角色,以及一些機器人對手。這些機器人對手將獲得非常簡答的邏輯:在每回閤中它們將會朝玩家移動。我們已經瞭解瞭如何去尋找路徑,於是我們可以重新使用這些代碼來了解機器人應該移動的路線從而讓機器人朝着玩家移動。

Shooting

射擊

We want the main player to be able to shoot at the robots, anywhere on the grid, and decide whether the shot will hit, or whether there is an obstacle in the way.

我們希望主角玩家能夠射擊機器人,而不論其處在網格的哪個位置,同時決定射擊是否命中,或者軌跡上是否有障礙物。

So we have a source and target as two squares on the grid, and we need to work out which squares a straight-shot will pass through… this is identical tothe problem of drawing a line between two points that we saw last post! We can use our code from the previous post, with a few trivial adjustments:

  • Instead of drawing pixels at each location on the line, we will check for obstacles.
  • When we find an obstacle, we will stop (because our shot has hit something) rather than going to the end of the line.

因此在網格中我們擁有一個源和目標作爲兩個方格,同時我們需要算出直線射擊時可以穿過哪些方格……這等同於我們在上篇帖子中瞭解的在兩點之間繪製線段的問題!我們可以使用上一篇帖子裏的代碼,並做一些小小的修改:

  • 我們將在線段的每個位置處檢測障礙物,而不是繪製像素
  • 當我們發現一個障礙物,我們將停下來(因爲擊中了東西)而不是定位到線段的終點

Shaky Hands

搖晃的手柄

At the moment, our planned game is a bit too easy: the player can aim and shoot perfectly, which means the robots don’t stand a chance. We can fix this by allowing the shot to vary a bit in its trajectory.

此刻我們設計的遊戲有一點太簡單了:玩家可以完美地瞄準和射擊,這意味着機器人毫無機會。我們可以改進一下,讓射擊的軌道改變一小點點。

How can we vary the shot? Well, usually it’s a matter of shooting a few degrees to either side of the intended angle. To be able to vary the line of the shot by a few degrees, we can use our prior knowledge of polar coordinates. We can convert the line into polar coordinates, then randomly alter the angle a little bit, then turn it back and trace the path of the shot.

我們怎樣改變軌道呢?通常來說大約在預期角度的兩邊偏離一些度數進行射擊。爲了能夠將射擊時的直線軌跡改變一些度數,我們可以使用之前關於極座標的知識。我們可以將直線轉換爲極座標,接着隨機地改變一點角度,然後轉換回來並追蹤射擊的軌跡。

First, we’ll use a slight variant of our polar conversion methods froma while back:

首先,我們把之前的極座標轉換方法進行一些細微的修改:

    private static double calculateDirection(double x, double y)
    {
        return Math.toDegrees(Math.atan2(y, x));
    }
       
    private static double calculateX(double dir)
    {
        return Math.cos(Math.toRadians(dir));
    }
    
    private static double calculateY(double dir)
    {
        return Math.sin(Math.toRadians(dir));
    }

The change from last time is that we don’t need the magnitude aspect.As we’ve already seen, it doesn’t matter what we scale the direction vector of a line by, so we can just ignore the magnitude aspect. We use these functions to convert the shooting direction into an angle, vary the angle by -20 to +20 degrees, then convert it back to a vector for exploring the line:

對於之前所做的改動是我們不再需要長度部分。由於我們已經瞭解了,線段的方向向量的長度並不是問題,因此我們便忽略長度因素。我們使用這些方法去將射擊方向轉換爲一個角度值,並在-20和+20度之間對其修改,然後將其轉回爲一個向量來探測該線段:

        double idealAngle = calculateDirection(x - getX(), y - getY());
        double actualAngle = idealAngle + (Greenfoot.getRandomNumber(40) - 20);
        
        p.followLine(getX(), getY(), calculateX(actualAngle), calculateY(actualAngle));

Now the shots vary a bit from where you shoot, meaning that (especially at range), you are likely to miss. You can go andplay the complete scenario.

現在射擊點與你射擊的目標有一點不同,這意味着(特別在一定範圍內),你很可能會漏射。你可以去玩一下完整的遊戲劇本

發佈了0 篇原創文章 · 獲贊 1 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章