Advertisement
Drakim

Raycaster

May 15th, 2012
449
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import library.List;
  2. import library.display.Screen;
  3. import library.display.Pixmap;
  4. import library.display.Pixie;
  5. import library.display.Sprodel;
  6. import library.system.Controls;
  7. import library.display.Context;
  8.  
  9. import flash.display.BitmapData;
  10. import flash.geom.Rectangle;
  11. import flash.geom.Point;
  12. import flash.display.Bitmap;
  13. import flash.Vector;
  14.  
  15.  
  16. class Game implements library.system.Scene {
  17.   public var raycaster:Raycaster;
  18.   public function new() {}
  19.   public function startScene():Void {
  20.     raycaster = new Raycaster();
  21.     raycaster.x = 200;
  22.     raycaster.y = 200;
  23.     raycaster.z = 64;
  24.     raycaster.angle = 0;
  25.     raycaster.roll = 60;
  26.  
  27.   }
  28.   public function closeScene():Void {
  29.  
  30.   }
  31.   public function update():Void {
  32.  
  33.     if(Keyboard.keyDown[87]) {
  34.       raycaster.x += Math.cos( raycaster.angle ) * 6;
  35.       raycaster.y += Math.sin( raycaster.angle ) * 6;
  36.     }
  37.     if(Keyboard.keyDown[65]) {
  38.       raycaster.x += Math.cos( raycaster.angle-(Math.PI/2) ) * 6;
  39.       raycaster.y += Math.sin( raycaster.angle-(Math.PI/2) ) * 6;
  40.     }
  41.     if(Keyboard.keyDown[68]) {
  42.       raycaster.x += Math.cos( raycaster.angle+(Math.PI/2) ) * 6;
  43.       raycaster.y += Math.sin( raycaster.angle+(Math.PI/2) ) * 6;
  44.     }
  45.     if(Keyboard.keyDown[83]) {
  46.       raycaster.x += Math.cos( raycaster.angle+(Math.PI) ) * 6;
  47.       raycaster.y += Math.sin( raycaster.angle+(Math.PI) ) * 6;
  48.     }
  49.    
  50.     if(Keyboard.keyDown[81]) {
  51.       raycaster.angle -= 0.05;
  52.     }
  53.     if(Keyboard.keyDown[69]) {
  54.       raycaster.angle += 0.05;
  55.     }
  56.    
  57.    
  58.     if(Keyboard.keyDown[32]) {
  59.       raycaster.z++;
  60.     }
  61.   }
  62.   public function render():Void {
  63.     raycaster.render();
  64.   }
  65. }
  66.  
  67.  
  68. class Raycaster {
  69.   private var map: Array<Int>;
  70.  
  71.   //-- WORLD COORDINATES --//
  72.   public var x: Float;
  73.   public var y: Float;
  74.   public var z: Float;
  75.   public var angle: Float;
  76.   public var roll: Float;
  77.  
  78.   private var iceil: BitmapData;
  79.   private var ifloor: BitmapData;
  80.   private var iwall: BitmapData;
  81.   //-- PRE COMPUTE --//
  82.   public var fov: Float;
  83.   private var eyeDistance: Float;
  84.   private var subRayAngle: Float;
  85.   private var p_center: Float;
  86.  
  87.   private var sin: Array<Float>;
  88.   private var cos: Array<Float>;
  89.   private var tan: Array<Float>;
  90.  
  91.   private var myvector:Vector<UInt>;
  92.  
  93.   public function new() {
  94.     ifloor = new BitmapData( 64, 64, false, 0xffcc00 );
  95.     iceil  = new BitmapData( 64, 64, false, 0xff0000 );
  96.     iwall  = new BitmapData( 64, 96, false, 0xcccccc );
  97.     myvector = new Vector<UInt>(Core.width*Core.height,true);
  98.            
  99.     ifloor.copyPixels( Asset.pixmap.textures.bitmapdata, new Rectangle( 0, 0, 64, 64 ), new Point( 0, 0 ) );
  100.     iceil.copyPixels( Asset.pixmap.textures.bitmapdata, new Rectangle( 64, 0, 64, 64 ), new Point( 0, 0 ) );
  101.     iwall.copyPixels( Asset.pixmap.textures.bitmapdata, new Rectangle( 128, 0, 64, 96 ), new Point( 0, 0 ) );
  102.  
  103.  
  104.            
  105.     map = [
  106.       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  107.       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  108.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  109.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  110.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  111.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  112.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  113.       1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1,
  114.       1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,
  115.       1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,
  116.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  117.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  118.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  119.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  120.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  121.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  122.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  123.       1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,
  124.       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  125.       1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
  126.     ];
  127.    
  128.  
  129.  
  130.    
  131.    
  132.    
  133.            
  134.     angle = 0;
  135.     roll = 0;
  136.    
  137.     fov = 60 * Math.PI / 180;
  138.            
  139.     //-- fill lookup table
  140.     sin = new Array<Float>();
  141.     cos = new Array<Float>();
  142.     tan = new Array<Float>();
  143.  
  144.     var i:Int = 0;
  145.     while(i < 7200)  {
  146.       sin[i] = Math.sin( i / 3600 * Math.PI );
  147.       cos[i] = Math.cos( i / 3600 * Math.PI );
  148.       tan[i] = Math.tan( i / 3600 * Math.PI );
  149.       i++;
  150.     }
  151.    
  152.     init();
  153.   }
  154.    
  155.   public function init():Void {
  156.     eyeDistance = ( Core.width / 2 ) / Math.tan( fov / 2 );
  157.     subRayAngle = fov / Core.width;
  158.   }
  159.    
  160.   public function render():Void {
  161.     //-- LOCAL VARIABLES --//
  162.     var rx:Int = Std.int(x) >> 6;
  163.     var ry:Int = Std.int(y) >> 6;
  164.            
  165.     var tx:Int = rx;
  166.     var ty:Int = ry;
  167.    
  168.     var ax:Float;
  169.     var ay:Float;
  170.     var dx:Float;
  171.     var dy:Float;
  172.     var distance:Float = 0;
  173.    
  174.     var offset:Float = 0;
  175.     var nearest:Float;
  176.     var beta:Float;
  177.     var ht:Float;
  178.     var tn:Float;
  179.     var cs:Float;
  180.     var sn:Float;
  181.            
  182.     var distort:Float;
  183.     var cf:Float;
  184.     var ff:Float;
  185.     var c0:Int;
  186.     var c1:Int;
  187.     var dg:Int;
  188.            
  189.     var color:Int;
  190.            
  191.     //-- clamp angle for lookup tables
  192.     if( angle < 0 ) angle += Math.PI * 2;
  193.     if( angle > Math.PI * 2 ) angle -= Math.PI * 2;
  194.    
  195.     var a: Float = angle + fov * .5;
  196.     if( a > Math.PI * 2 ) a -= Math.PI * 2;
  197.            
  198.     var pixelColumn: Int = Core.width - 1;
  199.     var pixelRow: Int = 0;
  200.    
  201.     //-- PRECOMPUTE --//
  202.     p_center = Core.height / 2 - roll;
  203.     var oz: Float = 96 - z;
  204.            
  205.     var ang: Int = Std.int( angle * ( 3600 / Math.PI ) ) | 0;
  206.  
  207.     while( --pixelColumn > -1 ) {
  208.       nearest = Math.POSITIVE_INFINITY;
  209.       dg = Std.int( a * ( 3600 / Math.PI ) );
  210.                
  211.       tn = tan[ dg ];
  212.       sn = sin[ dg ];
  213.       cs = cos[ dg ];
  214.  
  215.       rx = tx;
  216.       ry = ty;
  217.                
  218.       if ( sn < 0 ) {
  219.         while( ry > -1 && rx > -1 && rx < 20 ) {
  220.           ay = ry << 6;
  221.           ax = x + ( ay - y ) / tn;
  222.           rx = Std.int(ax) >> 6;   
  223.           ry--;
  224.           if ( getmap( rx, ry ) != 0 ) {
  225.             dx = ax - x;
  226.             dy = ay - y;       
  227.             nearest = dx * dx + dy * dy;
  228.             offset = Std.int(ax) & 63;
  229.             break;
  230.           }
  231.         }
  232.       } else {
  233.         while( ry < 20 && rx > -1 && rx < 20) {
  234.           ++ry;
  235.           ay = ry << 6;
  236.           ax = x + ( ay - y ) / tn;
  237.           rx = Std.int(ax) >> 6;
  238.           if ( getmap( rx, ry ) != 0) {
  239.             dx = ax - x;
  240.             dy = ay - y;
  241.             nearest = dx * dx + dy * dy;
  242.             offset = 64 - Std.int(ax) & 63;
  243.             break;
  244.           }
  245.         }
  246.       }
  247.       rx = tx;
  248.       ry = ty;
  249.  
  250.       if ( cs < 0 ) {
  251.         while( rx > -1 && ry > -1 && ry < 20 ) {
  252.           ax = rx << 6;
  253.           ay = y + ( ax - x ) * tn;
  254.           ry = Std.int(ay) >> 6;
  255.           rx--;
  256.           if(getmap( rx, ry ) != 0) {
  257.             dx = ax - x;
  258.             dy = ay - y;
  259.             distance = dx * dx + dy * dy;
  260.             if(distance < nearest) {
  261.               nearest = distance;
  262.               offset = 64 - Std.int(ay) & 63;
  263.             }
  264.             break;
  265.           }
  266.         }
  267.       } else {
  268.         while( rx < 128 && ry > -1 && ry < 128 ) {
  269.           ++rx;
  270.           ax = rx << 6;
  271.           ay = y + ( ax - x ) * tn;
  272.           ry = Std.int(ay) >> 6;
  273.           if(getmap( rx, ry ) != 0) {
  274.             dx = ax - x;
  275.             dy = ay - y;
  276.             distance = dx * dx + dy * dy;
  277.             if ( distance < nearest ) {
  278.               nearest = distance;
  279.               offset = Std.int(ay) & 63;
  280.             }
  281.             break;
  282.           }
  283.         }
  284.       }
  285.  
  286.       if( dg < ang ) {
  287.         distort = eyeDistance / cos[ 7200 + dg - ang ];
  288.       } else {
  289.         distort = eyeDistance / cos[ dg - ang ];   
  290.       }
  291.       ht = distort / Math.sqrt( nearest );
  292.       cf = oz * distort;
  293.       ff =  z * distort;
  294.       c0 = Std.int( p_center - ht * oz );
  295.       c1 = Std.int( p_center + ht * z  );
  296.       pixelRow = Core.height;
  297.                
  298.                
  299.  
  300.                
  301.       while( --pixelRow > c1-1 ) {
  302.         if( pixelRow < 0 ) break;
  303.         //-- FLOOR TILES --//
  304.         distance = ff / ( pixelRow+1 - p_center );
  305.         color = iceil.getPixel( Std.int( x + cs * distance ) & 63, Std.int( y + sn * distance ) & 63 );
  306.         var dark:Int = 255-(Std.int(distance)>>2);
  307.         if(dark<0) {dark=0;}
  308.         myvector[pixelColumn+pixelRow*Core.width] = color+(dark<<24);
  309.       }
  310.  
  311.       pixelRow++;
  312.       while( --pixelRow > c0 ) {
  313.         if( pixelRow < 0 ) {break;}
  314.         //-- BLOCKS --//
  315.         color = iwall.getPixel( Std.int(offset), Std.int(( pixelRow - c0 ) / ht) );
  316.         var dark:Int = 255-(Std.int(distance)>>2);
  317.         if(dark<0) {dark=0;}
  318.         myvector[pixelColumn+pixelRow*Core.width] = color+(dark<<24);
  319.       }
  320.      
  321.       pixelRow++;
  322.       while( --pixelRow > -1 ) {
  323.         if( pixelRow < 0 ) break;
  324.         //-- CEILING --//
  325.         distance = cf / ( p_center - pixelRow );
  326.         color = iceil.getPixel( Std.int( x + cs * distance ) & 63, Std.int( y + sn * distance ) & 63 );
  327.         var dark:Int = 255-(Std.int(distance)>>2);
  328.         if(dark<0) {dark=0;}
  329.         myvector[pixelColumn+pixelRow*Core.width] = color+(dark<<24);
  330.       }
  331.      
  332.  
  333.       a -= subRayAngle;
  334.       if( a < 0) a += (Math.PI * 2)-0.001;
  335.     }
  336.  
  337.     Screen.buffer.bitmapdata.setVector(Screen.buffer.bitmapdata.rect,myvector);
  338.   }
  339.  
  340.   public inline function getmap(_x:Int,_y:Int):Int {
  341.     return if(_x>20||_y>20) {0;} else {map[_x+_y*20];}
  342.   }
  343.  
  344. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement