Roguelike视场角问题
我正在从事一个大学计算机科学项目,我需要一些有关视场算法的帮助。我大部分时间都在工作,但在某些情况下,算法会穿透墙壁并突出显示玩家不应该看到的墙壁。
void cMap::los(int x0, int y0, int radius)
{ //Does line of sight from any particular tile
for(int x = 0; x < m_Height; x++) {
for(int y = 0; y < m_Width; y++) {
getTile(x,y)->setVisible(false);
}
}
double xdif = 0;
double ydif = 0;
bool visible = false;
float dist = 0;
for (int x = MAX(x0 - radius,0); x < MIN(x0 + radius, m_Height); x++) { //Loops through x values within view radius
for (int y = MAX(y0 - radius,0); y < MIN(y0 + radius, m_Width); y++) { //Loops through y values within view radius
xdif = pow( (double) x - x0, 2);
ydif = pow( (double) y - y0, 2);
dist = (float) sqrt(xdif + ydif); //Gets the distance between the two points
if (dist <= radius) { //If the tile is within view distance,
visible = line(x0, y0, x, y); //check if it can be seen.
if (visible) { //If it can be seen,
getTile(x,y)->setVisible(true); //Mark that tile as viewable
}
}
}
}
}
bool cMap::line(int x0,int y0,int x1,int y1)
{
bool steep = abs(y1-y0) > abs(x1-x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0,x1);
swap(y0,y1);
}
int deltax = x1-x0;
int deltay = abs(y1-y0);
int error = deltax/2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if ( steep && getTile(y,x)->isBlocked()) {
getTile(y,x)->setVisible(true);
getTile(y,x)->setDiscovered(true);
return false;
} else if (!steep && getTile(x,y)->isBlocked()) {
getTile(x,y)->setVisible(true);
getTile(x,y)->setDiscovered(true);
return false;
}
error -= deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
return true;
}
如果有人可以帮助我使第一个被阻挡的瓷砖可见,但停止其余的,我将不胜感激。
谢谢, 曼德林87
I am working on a college compsci project and I would like some help with a field of view algorithm. I works mostly, but in some situations the algorithm sees through walls and hilights walls the player should not be able to see.
void cMap::los(int x0, int y0, int radius)
{ //Does line of sight from any particular tile
for(int x = 0; x < m_Height; x++) {
for(int y = 0; y < m_Width; y++) {
getTile(x,y)->setVisible(false);
}
}
double xdif = 0;
double ydif = 0;
bool visible = false;
float dist = 0;
for (int x = MAX(x0 - radius,0); x < MIN(x0 + radius, m_Height); x++) { //Loops through x values within view radius
for (int y = MAX(y0 - radius,0); y < MIN(y0 + radius, m_Width); y++) { //Loops through y values within view radius
xdif = pow( (double) x - x0, 2);
ydif = pow( (double) y - y0, 2);
dist = (float) sqrt(xdif + ydif); //Gets the distance between the two points
if (dist <= radius) { //If the tile is within view distance,
visible = line(x0, y0, x, y); //check if it can be seen.
if (visible) { //If it can be seen,
getTile(x,y)->setVisible(true); //Mark that tile as viewable
}
}
}
}
}
bool cMap::line(int x0,int y0,int x1,int y1)
{
bool steep = abs(y1-y0) > abs(x1-x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0,x1);
swap(y0,y1);
}
int deltax = x1-x0;
int deltay = abs(y1-y0);
int error = deltax/2;
int ystep;
int y = y0;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (int x = x0; x < x1; x++) {
if ( steep && getTile(y,x)->isBlocked()) {
getTile(y,x)->setVisible(true);
getTile(y,x)->setDiscovered(true);
return false;
} else if (!steep && getTile(x,y)->isBlocked()) {
getTile(x,y)->setVisible(true);
getTile(x,y)->setDiscovered(true);
return false;
}
error -= deltay;
if (error < 0) {
y = y + ystep;
error = error + deltax;
}
}
return true;
}
If anyone could help me make the first blocked tiles visible but stops the rest, I would appreciate it.
thanks,
Manderin87
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您似乎正在尝试创建光线投射算法。我想你已经了解布雷森纳姆的线路是如何工作的,所以我就开门见山吧。
您无需检查潜在视场中每个单元的可见性,只需从 FOV 中心向潜在 FOV 区域(您循环穿过的正方形)周边的每个单元发射 Bresenham 线即可。在 Bresenham 生产线的每一步,您都会检查细胞状态。每条光线的伪代码如下所示:
请记住,光线投射会产生大量伪影,在计算视野后,您可能还需要进行后处理。
一些有用的资源:
You seem to be attempting to create a raycasting algorithm. I assume you have knowledge of how Bresenham's lines work, so I'll cut to the chase.
Instead of checking the visibility of each cell in the potential field of view, you only need to launch Bresenham lines from the FOV centre towards each cell at the very perimetre of the potential FOV area (the square you loop through). At each step of the Bresenham line, you check the cell status. The pseudocode for each ray would go like this:
Please remember that raycasting produces tons of artifacts and you might also need postprocessing after you have calculated your field of view.
Some useful resources: