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

本文介绍了一种游戏中的视野算法,利用直线绘制技术实现角色可见范围内的敌人及障碍物的显示,以此提升游戏的真实感和挑战性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

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

请用MATLAB构建一个二维元胞自动机模型。要求如下: - 网格大小设置为50×50,每个元胞代表0.4m×0.4m的区域。 - 元胞状态包含:{空,行人,障碍物,出口},分别用数值0、1、2、3表示。 - 采用Moore邻居定义(8邻域)。 - 时间步长Δt = 0.5秒。 - 生成可视化函数,用不同颜色来区分不同的元胞状态。请在上述基础元胞自动机模型代码中添加以下规则: - 视觉感知范围:动态半径R_vision = 能见度 / 0.4(以网格为单位)。 - 听觉感知范围:固定半径R_audio = 3(以网格为单位)。 - 优先级规则: - 当出口处于视觉范围内时,行人向最近的出口移动。 - 当仅能通过听觉感知到出口时,行人沿声源方向移动。 - 若没有感知到出口,行人执行随机游走。 请在已有代码基础上添加烟雾扩散导致的能见度衰减规则: - 能见度初始值设定为10米,按照指数规律衰减,公式为visibility(t) = 10 * exp(-0.12 * t)。 - 当能见度低于0.8米时,触发应急照明系统,使能见度维持在≥0.5米。 - 在可视化部分用灰度值来表示能见度(0 - 1映射到黑 - 白)。 请在代码中添加结伴行人组的交互规则: - 组内成员之间保持1 - 3个网格的间距(对应0.4 - 1.2米)。 - 组领导者的决策权重是成员的2倍。 - 当成员超出领导者的感知范围时,触发重组行为: - 有50%的概率返回寻找组。 - 有50%的概率独立行动。 请编写MATLAB代码来实现参数优化: - 运用NSGA - II算法对出口布局进行优化。 - 目标函数为最小化疏散时间和最大化出口利用率。 - 约束条件为相邻出口间距≥8米,标识可见性>0.6。
最新发布
03-31
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值