Graal Forums  

Go Back   Graal Forums > Development Forums > NPC Scripting > Code Gallery
FAQ Members List Calendar Today's Posts

 
 
Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
  #1  
Old 03-15-2008, 03:59 AM
DrakilorP2P DrakilorP2P is offline
Registered User
DrakilorP2P's Avatar
Join Date: Apr 2006
Posts: 755
DrakilorP2P is just really niceDrakilorP2P is just really nice
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.


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.

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);
    }
  }


Last edited by DrakilorP2P; 03-15-2008 at 12:57 PM.. Reason: Improving language
Reply With Quote
 


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 03:07 PM.


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