//-------------------------------------------------------------------------- // Add supplemental (non-static/non-land) items into the obstruction matrix; // this is very cheap in comparison to the cost of processing land and statics //-------------------------------------------------------------------------- public void ProcessMatrixItems( Point3D beholder, VisibilityMatrix v ) { // double start = DateTime.Now.Ticks / 10000000.0; // for(int i=0; i<100000; i++) // { int eyelevel = beholder.Z + 12; foreach ( Item item in m_map.GetItemsInRange( new Point3D( beholder.X, beholder.Y, 0 ), 15 )) { // cutpoint optimization; if the cell is in shadow, don't bother with // any more tests; such a test would be irrelevant: if( !v.IsVisible( beholder, item.Location.X, item.Location.Y )) { int xOffset = item.Location.X - beholder.X; int yOffset = item.Location.Y - beholder.Y; // this check solves the diagonal problem mentioned in the // previous function comments; we don't "cut" for the diagonals. if( Math.Abs( xOffset - yOffset ) <= 1) continue; } if( ItemBlocksVis( item, eyelevel, beholder ) ) v.ProcessObstructionAt( beholder, item.Location.X, item.Location.Y ); } //} // double stop = DateTime.Now.Ticks / 10000000.0; // double elapsed = stop - start; // Console.WriteLine( "ProcessMatrixItems: " + elapsed ); }
//-------------------------------------------------------------------------- // Create the base matrix; this is the "cacheable" portion of the matrix, // the stuff like land and statics that never really change. //-------------------------------------------------------------------------- public VisibilityMatrix CreateBaseMatrix( Point3D beholder ) { VisibilityMatrix v = new VisibilityMatrix( 15 ); // VisibilityMatrix v = null; // for performance testing--leave in // double start = DateTime.Now.Ticks / 10000000.0; // for(int i=0; i<500; i++) // { int eyelevel = beholder.Z + 12; // v = new VisibilityMatrix( 15 ); //---------------------------------------------------------------------- // This is a spiral search pattern from center; the reason we do this // is that starting from the center allows us to benefit from // not having to load up data relating tiles and so forth further out // if x,y cursor is in the shadow of a prior obstruction... //---------------------------------------------------------------------- int locX = beholder.X; int locY = beholder.Y; for( int j = 0; j < m_SpiralPattern.Length; j++) { int xOffset = m_SpiralPattern[j][0]; int yOffset = m_SpiralPattern[j][1]; int x = locX + xOffset; int y = locY + yOffset; //------------------------------------------------------------------ // the spiral pattern could make us walk off the edge of the // map; break out of that here: //------------------------------------------------------------------ if( x < 0 || x > m_map.Width || y < 0 || y > m_map.Height ) goto cutpoint; //------------------------------------------------------------------ // Here we optimize by skipping the pulling up of tiles in the // event we are in a shadow; it turns out that in certain diagonal // 'L' cases (corners), this doesn't work perfectly, hence the check // for matching abs. x/y offsets ... we don't cut point those. //------------------------------------------------------------------ if ( !v.IsVisible( beholder, x, y ) && Math.Abs( xOffset - yOffset ) <= 1 ) goto cutpoint; //------------------------------------------------------------------ // Now process statics: //------------------------------------------------------------------ StaticTile[] staticTiles = m_map.Tiles.GetStaticTiles( x, y, true ); foreach (StaticTile staticTile in staticTiles) { if( TileBlocksVis( staticTile, eyelevel, x, y, beholder ) ) { v.ProcessObstructionAt( beholder, x, y ); goto cutpoint; // further obstructions irrelevant } } //------------------------------------------------------------------ // Now process land: //------------------------------------------------------------------ LandTile landTile = m_map.Tiles.GetLandTile( x, y ); if( LandBlocksVis( landTile, x, y, eyelevel+5, beholder ) ) { v.ProcessObstructionAt( beholder, x, y ); goto cutpoint; // further obstructions irrelevant } //------------------------------------------------------------------ // Now process "invalid" tiles (the black areas in dungeons): //------------------------------------------------------------------ if( IsVizBlockingInvalidLand( landTile, staticTiles, x, y ) ) { v.ProcessObstructionAt( beholder, x, y ); goto cutpoint; // further obstructions irrelevant } //------------------------------------------------------------------ // Items left deliberately out here (that's a follow up stage) //------------------------------------------------------------------ //------------------------------------------------------------------ cutpoint:; // sorry about the evil goto; please leave this alone for now // think of it this way; this is like a destionation for "continue", // where code can be if needed. //------------------------------------------------------------------ } //} // double stop = DateTime.Now.Ticks / 10000000.0; // double elapsed = stop - start; // Console.WriteLine( "CreateBaseMatrixInternalTime: " + elapsed ); return v; }