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.

现在射击点与你射击的目标有一点不同,这意味着(特别在一定范围内),你很可能会漏射。你可以去玩一下完整的游戏剧本

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值