21.视线:在网格中计算可见性

21.Lines of Sight: Calculating visibility on a grid

Last post, we developed a game where your robotic opponents all come towards you and you must fire at them to stop them. It was made somewhat easier by the fact that you can see all your opponents all the time, which allowed you to plan what to do quite easily. What would be better is if only the enemies (and parts of the arena) that you can see would be shown.

在上一篇帖子里,我们设计了一个游戏,在其中你的机器人对手都冲着你过来而你必须朝它们射击来阻止它们。

这做得有一点简单,因为你始终可以看见所有的对手,这使得你可以非常容易地计划行动。要是你所能看见的敌人(场景中的一部分)才会被显示出来,这是不是更好一些呢?

So how can we show only the enemies and walls that you can see? Well, we can only see any given square if we have direct line of sight into them, uninterrupted by other obstacles. So line of sight is just another special case of usingour line drawing algorithm!

那么我们怎样仅仅显示你所能看见的敌人和墙壁呢?我们仅仅能够看到一些特定的方格,如果视线能够达到它们而不被其他障碍物所阻隔。因而视线正好是使用我们的直线绘制算法的另一个特例。

One way to implement visibility would be to attempt to trace a line from our location to each square in the arena — if we get there without going through walls then we can see that particular square, otherwise we cannot. That would work fine, but it would get quite time consuming as the arena grows larger. If the arena was 50 by 50, that’s 2500 lines to trace!

视线可视化的一种办法或许是试图追踪场从当前位置到达场景中每个方格的线段——如果没有被墙壁阻挡的话那么我们可以看到那些特定的方格,否则就不能。那样可能运行良好,但是随着场景增大这可能会带来大量的时间消耗。如果场景是50乘以50大小的,那么一次要追踪2500条线段!

A more efficient way to do it is to instead trace a small number of lines heading out from the player at regular (angular) intervals:

更加有效的办法是在玩家行进时根据给定的(弧度的)间隔追踪一小部分线段:

So you trace each line and see what squares you cross. You can see all the empty squares you pass through, and the first square with an obstacle in. With enough lines, this will show all the squares that you can see. Tracing lines at regular intervals uses our old friends sine and cosine, in the same way as last post:

于是我们追踪每条线段并且看看穿过了哪些方格。你可以看到线段穿过的所有空的方格,以及障碍物的第一个方格。在线段充足的情况下,这将显示你能看到的所有方格。追踪给定间隔的线段时使用了我们的老朋友sin和cos函数,并采用上篇帖子中的相同方式:

        for (int angle = 0; angle < 360; angle += 5)
        {
            double dirX = Math.cos(Math.toRadians(angle));
            double dirY = Math.sin(Math.toRadians(angle));
            v.followLine(getPlayer().getX(), getPlayer().getY(), dirX, dirY);
        }

Everything is made invisible by default, and only made visible if a line-of-sight hits it. Where we used to see everything:

缺省时任何东西都是不可见的,只有当一条视线触及它时才变得可见。下图是我们曾经可以看到所有东西时的情形:

We now trace lines of sight outwards:

现在我们向外追踪视线:

And only show what has been hit:

同时仅仅显示视线触及的部分:

That now makes our game more difficult. You can have a play with the finished version to see how this pans out in practice.

现在我们的游戏变得更加有难度。你可以玩一下完成后的版本去看看实际中是怎样实现的。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值