Graal Forums

Graal Forums (https://forums.graalonline.com/forums/index.php)
-   Code Gallery (https://forums.graalonline.com/forums/forumdisplay.php?f=179)
-   -   Field of view using Bresenham's line algorithm. (https://forums.graalonline.com/forums/showthread.php?t=79032)

DrakilorP2P 03-15-2008 03:59 AM

Field of view using Bresenham's line algorithm.
 
This script is really just a big hack-up to get a sample field of view drawing set up. If you intend to use it somewhere, you probably want to heavily tweak it in order to render the scene in a sane manner.

It uses Bresenham's line algorithm to draw lines from the point of origin to the edges of the level, stopping if any walls are encountered. While this is a pretty fast operation, it's usually not a good idea to do it every 0.1 seconds. I suggest only updating when the integer position changes.

Since 64x64 tiles is pretty large for this algorithm, there will be artifacts over long distances, but since this isn't NetHack, I consider it good enough.

In these screenshots, the purple tile is the point of origin.
http://image2life.net/users/public/g10532fov3q13.png

The following iteration uses some penetration in order to display a few non-walkable tiles, which makes more sense since normal people can see walls.
http://image2life.net/users/public/c29984fov44g13.png
PHP Code:

//#CLIENTSIDE
function onCreated()
{
  
clearPlots();
  
settimer(1);
}

function 
onTimeout()
{
  
clearPlots();
  
  
originx int(mousex);
  
originy int(mousey);

  
//Only draw lines towards the edges of the level. This saves computation but produces artifacts at long distances.
  
for (x=0x<64x++) {
    
bresenham(originxoriginyx0true5);
  }
  for (
x=0x<64x++) {
    
bresenham(originxoriginyx64true5);
  }
  for (
y=0y<64y++) {
    
bresenham(originxoriginy0ytrue5);
  }
  for (
y=0y<64y++) {
    
bresenham(originxoriginy64ytrue5);
  }

  
//Drawing lines towards all tiles is a slow process but produces a lot less artifacts.
  /*for (x=0; x<64; x++) {
    for (y=0; y<64; y++) {
      bresenham(originx, originy, x, y, true);
    }
  }*/
  
  
settimer(1);
}

// A variant of Bresenham's line algorithm. It's pretty fast, especially if you only use integers which GScript doesn't seem to support.
// If stopAtWall is true, the line drawing will terminate when a wall tile is encountered.
// In this case, penetration specifies how many walls a line will be able to pass before terminating.
// bresenham(0, 0, 64, 64, true, 4) will draw a line between (0, 0) and (64, 64) but will stop after passing four blocking tiles.
function bresenham(x0y0x1y1stopAtWallpenetration)
{
  
x0 int(x0); y0 int(y0); x1 int(x1); y1 int(y1);
  
dx abs(x1 x0) << 1;
  
dy abs(y1 y0) << 1;
  
  if (
x1 x0ix 1;
  else 
ix = -1;
  if (
y1 y0iy 1;
  else 
iy = -1;
  
  if (
stopAtWall && onwall(x0y0)) penetration--;
  if (
stopAtWall && penetration 0) return;
  
plot(x0y0);
  
  if (
dx >= dy) {
    
error dy - (dx >> 1);
    
    while (
x0 != x1) {
      if (
error >= 0) {
        if (
error != || (ix 0)) {
          
y0 += iy;
          
error -= dx;
        }
      }
      
      
x0 += ix;
      
error += dy;
      
      if (
stopAtWall && onwall(x0y0)) penetration--;
      if (
stopAtWall && penetration 0) return;
      
plot(x0y0);
    }
  }
  else {
    
error dx - (dy >> 1);
    
    while (
y0 != y1) {
      if (
error >= 0) {
        if (
error != || iy 0) {
          
x0 += ix;
          
error -= dy;
        }
      }
        
      
y0 += iy;
      
error += dx;
      
      if (
stopAtWall && onwall(x0y0)) penetration--;
      if (
stopAtWall && penetration 0) return;     
      
plot(x0y0);
    }
  }
}

function 
plot(xy)
{
  
index 100 300;
  
showpoly(index, {xyx+1yx+1y+1xy+1});
  
changeimgcolors(index0.250.250.250.01);
  
changeimgmode(index3);
  
changeimgvis(index3);
}

// 300 + 64 + 64 * 100 = 6664
function clearPlots()
{
  
hideimgs(3006664);


Note that there is faster ways to do this, especially for large areas such as a Graal level. If you're serious about field of view, do some research and find something that better suits your specific purposes.

If all you want is the implementation of Bresenham's line algorithm, here's a cleaned up version. Please define the plot(x, y) function so that it draws wherever you want it to.
PHP Code:

function cleanBresenham(x0y0x1y1)
{
  
// Things can screw up if we don't use integers.
  
x0 int(x0); y0 int(y0); x1 int(x1); y1 int(y1);
  
  
dx abs(x1 x0) << 1;
  
dy abs(y1 y0) << 1;
  
  if (
x1 x0ix 1;
  else 
ix = -1;
  if (
y1 y0iy 1;
  else 
iy = -1;
  
  
plot(x0y0);
  
  if (
dx >= dy) {
    
error dy - (dx >> 1);
    
    while (
x0 != x1) {
      if (
error >= 0) {
        if (
error != || (ix 0)) {
          
y0 += iy;
          
error -= dx;
        }
      }
      
      
x0 += ix;
      
error += dy;
      
      
plot(x0y0);
    }
  }
  else {
    
error dx - (dy >> 1);
    
    while (
y0 != y1) {
      if (
error >= 0) {
        if (
error != || iy 0) {
          
x0 += ix;
          
error -= dy;
        }
      }
        
      
y0 += iy;
      
error += dx;
          
      
plot(x0y0);
    }
  }



xXziroXx 03-19-2008 12:52 PM

Very nicely done, rep++ :)

coreys 03-19-2008 03:10 PM

That's very impressive.
Whenever I make baddies I just check if a target is in the direction the baddy is facing to do field of view. xP
Now I feel like a chump.

Chompy 03-19-2008 03:24 PM

Quote:

Originally Posted by coreys (Post 1380780)
Whenever I make baddies I just check if a target is in the direction the baddy is facing to do field of view. xP
Now I feel like a chump.

They aren't for checking distances tho :p

it's to draw pretty lights

But, the only thing I mislike in those scripts is that you edit variables with the same name as the function params :( Only that, other then that they are very nice :p

DrakilorP2P 03-19-2008 06:29 PM

Quote:

Originally Posted by Chompy (Post 1380783)
They aren't for checking distances tho :p

it's to draw pretty lights

But, the only thing I mislike in those scripts is that you edit variables with the same name as the function params :( Only that, other then that they are very nice :p

Only small adjustments are required in order to check if a particular baddy have a clear line of sight to the intended target.
PHP Code:

function lineOfSight(x0y0x1y1)
{
  
// Things can screw up if we don't use integers.
  
x0 int(x0); y0 int(y0); x1 int(x1); y1 int(y1);
  
  
dx abs(x1 x0) << 1;
  
dy abs(y1 y0) << 1;
  
  if (
x1 x0ix 1;
  else 
ix = -1;
  if (
y1 y0iy 1;
  else 
iy = -1;
  
  if (
onwall(x0y0)) return false;
  
  if (
dx >= dy) {
    
error dy - (dx >> 1);
    
    while (
x0 != x1) {
      if (
error >= 0) {
        if (
error != || (ix 0)) {
          
y0 += iy;
          
error -= dx;
        }
      }
      
      
x0 += ix;
      
error += dy;
      
      if (
onwall(x0y0)) return false;
    }
  }
  else {
    
error dx - (dy >> 1);
    
    while (
y0 != y1) {
      if (
error >= 0) {
        if (
error != || iy 0) {
          
x0 += ix;
          
error -= dy;
        }
      }
      
      
y0 += iy;
      
error += dx;
      
      if (
onwall(x0y0)) return false;
    }
  }
  
  
// Success
  
return true;


If you want distance with that, add a counter or employ trigonometry in a separate function.

Tigairius 03-19-2008 07:03 PM

Wow, nice.

cbk1994 03-19-2008 10:06 PM

Amazing.

Inverness 03-19-2008 10:33 PM

Excellent.

smirt362 03-20-2008 12:59 AM

Well that is just plain nifty.

xAzerothx 03-20-2008 01:07 AM

Is it bad if I don't understand what its used for?

Chompy 03-20-2008 02:36 PM

Quote:

Originally Posted by xAzerothx (Post 1380931)
Is it bad if I don't understand what its used for?

no, it's good, but maybe bad for you since you don't know how to use it? :p

Anyways, the fun thing with this is if you add some sleep()'s inside the loops you can see how they act/work (Ie, going one line at a time and which direction they go in etc.) :)

Dan 03-22-2008 08:07 PM

Nice. I like your tip Chompy hehe.

Galdor 03-22-2008 08:56 PM

wow thats kinda cool =)


All times are GMT +2. The time now is 01:20 PM.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2026, vBulletin Solutions Inc.
Copyright (C) 1998-2019 Toonslab All Rights Reserved.