2 Replies Latest reply on Jul 8, 2010 6:45 PM by Bruce_Jawn

    how do i pass a variable in flex

    RadioactiveLizard Level 1

      i've been looking all over google for how to pass a variable yet

      i've come up empty handed

      i have a C code and as3

       

      i've never been able to get a C program to compile on my own, this is from a tutorial im trying to understand about raycasting

      from what i can gather i think that the variables are passed threw this

       

      #######raycaster.c##########
      AS3_Val loop( void* self, AS3_Val args )
      {
          AS3_ArrayValue(args,"IntType,IntType,IntType,IntType",&K_UP,&K_DOWN,&K_LEFT,&K_RIGHT);
          CastRay();
          int opos,j,i,jpos;
          for(j=0; j < resY; j++ ){
              jpos = resX*j;
              for(i=0; i < resX; i++ ){
                  opos = (jpos+i);
                  tBuffer[opos] = buffer[i][j];
              }//end of for
          }//end of for
          return 0;
      }//end of loop

      however not one of the values inside of AS3_ArrayValue is to be found on the Main.as

      this is the only function that comunicates with the C code, but i could be wrong

      ####Main.as######
              private function enterFrame(event:Event):void {
                  alcRCLib.loop(upKey,downKey,leftKey,rightKey);
                  alchemyMemory.position=alcScreenBufferPointer;
                  screenBitmapData.setPixels(screenBitmapData.rect,alchemyMemory);
                 
                  }

       

      the reason i want to do this, other than to know how, because that would be useful above all else, i've already written a as3 that comunicates with php

      to get a array of images  for a topdown game, and i wouldn't know how to load these variables to C from a HTTP request but if i can get flash to tell c what they are then every thing worked out

       

       

       

       

       

       

       

       

       

       

      heres both codes in full

       

      #####Main.as####

      /**
      *Alchemy Ray Caster
      *April 6, 2010
      *Bruce Jawn
      *http://bruce-lab.blogspot.com
       
      *Copyright (c) <2010> <Bruce Jawn>
      *This software is released under the MIT License
      *<http://www.opensource.org/licenses/mit-license.php>
      **/
      package {

       

      //    import cmodule.Ray_Caster._worldMap;
      //    import cmodule.Ray_Caster._worldMap;
          import cmodule.Ray_Caster.CLibInit;
      //    import cmodule.Ray_Caster.TextFieldI;
          import flash.display.*;
          import flash.text.*;
          import flash.events.*;
          import flash.geom.*;
          import flash.text.engine.TextBlock;
          import flash.text.engine.TextLine;
          import flash.text.TextField;
          import flash.utils.*;
          import flash.ui.*;

       

          [SWF(width="840", height="880")]
          public class Main extends Sprite {

       

              [Embed(source="../wolftex/barrel.png")]
              public static var barrelClass:Class;

       

              [Embed(source="../wolftex/bluestone.png")]
              public static var bluestoneClass:Class;

       

              [Embed(source="../wolftex/colorstone.png")]
              public static var colorstoneClass:Class;

       

              [Embed(source="../wolftex/eagle.png")]
              public static var eagleClass:Class;

       

              [Embed(source="../wolftex/greenlight.png")]
              public static var greenlightClass:Class;

       

              [Embed(source="../wolftex/greystone.png")]
              public static var greystoneClass:Class;

       

              [Embed(source="../wolftex/mossy.png")]
              public static var mossyClass:Class;

       

              [Embed(source="../wolftex/pillar.png")]
              public static var pillarClass:Class;

       

              [Embed(source="../wolftex/purplestone.png")]
              public static var purplestoneClass:Class;

       

              [Embed(source="../wolftex/redbrick.png")]
              public static var redbrickClass:Class;

       

              [Embed(source="../wolftex/wood.png")]
              public static var woodClass:Class;

       

              //Array to hold all the textures
              private var texs:Array=[];
              private var worldMap:Array = [];
              //private var worldMap[1]:Array=[];
              private static const SCREEN_WIDTH:int=640;
              private static const SCREEN_HEIGHT:int=480;
              private var screenBitmapData:BitmapData;
              private var screenBitmap:Bitmap;

       

              private var alchemyMemory:ByteArray;
              private var alcRCLib:Object;
              private var cLibInit:CLibInit;
              private var alcScreenBufferPointer:uint;
              private var alcTexPointer:uint;

       

              private var upKey:int=0;
              private var downKey:int=0;
              private var leftKey:int=0;
              private var rightKey:int=0;
              private var a:flash.text.TextField;
              public function Main() {
                  stage.frameRate=60;
                  stage.align=StageAlign.TOP_LEFT;
                  stage.scaleMode=StageScaleMode.NO_SCALE;
                  stage.fullScreenSourceRect=new Rectangle(0,0,SCREEN_WIDTH,SCREEN_HEIGHT);
                  init();
                 
                  }//end of function Main

       

              private function init():void {
                  initBitmaps();
                  initAlchemy();
                  initRendering();
              }//end of function init

       

              private function initBitmaps():void {
                  texs.push(prepareBitmapData(new eagleClass().bitmapData  ));
                  texs.push(prepareBitmapData(new redbrickClass().bitmapData  ));
                  texs.push(prepareBitmapData(new purplestoneClass().bitmapData  ));
                  texs.push(prepareBitmapData(new greystoneClass().bitmapData  ));
                  texs.push(prepareBitmapData(new bluestoneClass().bitmapData  ));
                  texs.push(prepareBitmapData(new mossyClass().bitmapData  ));
                  texs.push(prepareBitmapData(new woodClass().bitmapData  ));
                  texs.push(prepareBitmapData(new colorstoneClass().bitmapData  ));
                  texs.push(prepareBitmapData(new barrelClass().bitmapData  ));
                  texs.push(prepareBitmapData(new pillarClass().bitmapData  ));
                  texs.push(prepareBitmapData(new greenlightClass().bitmapData  ));

       

                  screenBitmapData=new BitmapData(SCREEN_WIDTH,SCREEN_HEIGHT,false,0);
                  screenBitmap=new Bitmap(screenBitmapData);
                  addChild(screenBitmap);
         
                  worldMap[1] = (1,2,3,4);
                  worldMap[2] = (1,2,3,4);
                  worldMap[3] = (1,2,3,4);
                  worldMap[4] = (1,2,3,4);
                  worldMap[5] = (1,2,3,4);
                  worldMap[6] = (1,2,3,4);
                  worldMap[7] = (1,2,3,4);
                 
                 
                 
                 
                 
                 
                 
                 
                 
                 
                  }//end of function initBitmaps

       

              //Prepare the bitmap once to take into account the lower-endianess of the alchemy code.
              private function prepareBitmapData(sourceMap:BitmapData):BitmapData {
                  var outBitmapData:BitmapData=sourceMap.clone();
                  outBitmapData=new BitmapData(outBitmapData.width,outBitmapData.height,true,0xFF000000);
                  outBitmapData.copyChannel(sourceMap,outBitmapData.rect,outBitmapData.rect.topLeft,BitmapD ataChannel.ALPHA,BitmapDataChannel.BLUE);
                  outBitmapData.copyChannel(sourceMap,outBitmapData.rect,outBitmapData.rect.topLeft,BitmapD ataChannel.RED,BitmapDataChannel.GREEN);
                  outBitmapData.copyChannel(sourceMap,outBitmapData.rect,outBitmapData.rect.topLeft,BitmapD ataChannel.GREEN,BitmapDataChannel.RED);
                  outBitmapData.copyChannel(sourceMap,outBitmapData.rect,outBitmapData.rect.topLeft,BitmapD ataChannel.BLUE,BitmapDataChannel.ALPHA);
                  return outBitmapData;
              }//end of function prepareBitmapData

       

              private function initAlchemy():void {
                  cLibInit=new CLibInit  ;
                  alcRCLib=cLibInit.init();

       

                  //Retrieve the "Alchemy Memory".
                  var ns:Namespace=new Namespace("cmodule.Ray_Caster");
                  alchemyMemory=ns::gstate.ds;

       

                  //Allocate the buffers in Alchemy.
                  alcScreenBufferPointer=alcRCLib.initializeScreenBuffer(SCREEN_WIDTH,SCREEN_HEIGHT);//Setu p a screenbuffer of size x,y;

       

                  //Copy the textures to alchemy memory.
                  for (var i:int=0; i<11; i++) {
                      var ba:ByteArray=texs[i].getPixels(texs[i].rect);
                      alcTexPointer=alcRCLib.initializeTexBuffer(i);
                      alchemyMemory.position=alcTexPointer;
                      alchemyMemory.writeBytes(ba,0,ba.length);
                  }//end of for
              }//end of function initAlchemy

       

              private function initRendering():void {
                  stage.addEventListener(KeyboardEvent.KEY_DOWN,key_pressed);
                  stage.addEventListener(KeyboardEvent.KEY_UP,key_released);
                  addEventListener(Event.ENTER_FRAME,enterFrame);
              }//end of function initRendering

       

              private function enterFrame(event:Event):void {
                  alcRCLib.loop(upKey,downKey,leftKey,rightKey);
                  alchemyMemory.position=alcScreenBufferPointer;
                  screenBitmapData.setPixels(screenBitmapData.rect,alchemyMemory);
                 
                  }//end of function enterFrame

       

              private function key_pressed(e:KeyboardEvent):void {
                 
                  switch (e.keyCode) {
                      case Keyboard.UP :
                          upKey=1;
                          break;
                      case Keyboard.DOWN :
                          downKey=1;
                          break;
                      case Keyboard.LEFT :
                          leftKey=1;
                          break;
                      case Keyboard.RIGHT :
                          rightKey=1;
                          break;
                  }//end of switch
             
                  }//end of function key_pressed

       

              private function key_released(e:KeyboardEvent):void {
                  switch (e.keyCode) {
                      case Keyboard.UP :
                          upKey=0;
                          break;
                      case Keyboard.DOWN :
                          downKey=0;
                          break;
                      case Keyboard.LEFT :
                          leftKey=0;
                          break;
                      case Keyboard.RIGHT :
                          rightKey=0;
                          break;               
                          }//end of switch
                  }//end of function key_released

       

                 
                  }//end of class
      }//end of package

       

       

       

       

      ###raycaster####

      //Raycasting Engine from Lode's Computer Graphics Tutorial
      //http://www.student.kuleuven.be/~m0216922/CG/raycasting.html
      //Modified for Alchemy by Bruce Jawn
      //http://bruce-lab.blogspot.com
      #include "AS3.h"
      #include <math.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      //============================================================
      //============================================================
      enum bool {false=0,true=!false};

       

      #define screenWidth 1640
      #define screenHeight 1480
      #define texWidth 64
      #define texHeight 64
      #define mapWidth 24
      #define mapHeight 24

       

      //1D Screen Buffer
      int* tBuffer;
      int resX = 0;
      int resY = 0;
      //2D Screen Buffer
      int buffer[screenWidth][screenHeight];
      //1D Zbuffer
      double ZBuffer[screenWidth];
      //============================================================
      //============================================================
      //textures
      int texture[11][texWidth*texHeight];

       

      #define numSprites 19
      //arrays used to sort the sprites
      int spriteOrder[numSprites];
      double spriteDistance[numSprites];

       

      struct SSprite
      {
        double x;
        double y;
        int texture;
      };

       

      struct SSprite sprite[numSprites]=
      {
        //green light in front of playerstart
        {20.5, 11.5, 10},
        //green lights in every room
        {18.5,4.5, 10},
        {10.0,4.5, 10},
        {10.0,12.5,10},
        {3.5, 6.5, 10},
        {3.5, 20.5,10},
        {3.5, 14.5,10},
        {14.5,20.5,10},
       
        //row of pillars in front of wall: fisheye test
        {18.5, 10.5, 9},
        {18.5, 11.5, 9},
        {18.5, 12.5, 9},
       
        //some barrels around the map
        {21.5, 1.5, 8},
        {15.5, 1.5, 8},
        {16.0, 1.8, 8},
        {16.2, 1.2, 8},
        {3.5,  2.5, 8},
        {9.5, 15.5, 8},
        {10.0, 15.1,8},
        {10.5, 15.8,8},
      };
      //============================================================
      //============================================================
      //map
      int worldMap[mapWidth][mapHeight] =
      {
        {8,8,8,8,8,8,8,8,8,8,8,4,4,6,4,4,6,4,6,4,4,4,6,4},
        {8,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,4},
        {8,0,3,3,0,0,0,0,0,8,8,4,0,0,0,0,0,0,0,0,0,0,0,6},
        {8,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6},
        {8,0,3,3,0,0,0,0,0,8,8,4,0,0,0,0,0,0,0,0,0,0,0,4},
        {8,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,6,6,0,6,4,6},
        {8,8,8,8,0,8,8,8,8,8,8,4,4,4,4,4,4,6,0,0,0,0,0,6},
        {7,7,7,7,0,7,7,7,7,0,8,0,8,0,8,0,8,4,0,4,0,6,0,6},
        {7,7,0,0,0,0,0,0,7,8,0,8,0,8,0,8,8,6,0,0,0,0,0,6},
        {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,4},
        {7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,6,0,6,0,6},
        {7,7,0,0,0,0,0,0,7,8,0,8,0,8,0,8,8,6,4,6,0,6,6,6},
        {7,7,7,7,0,7,7,7,7,8,8,4,0,6,8,4,8,3,3,3,0,3,3,3},
        {2,2,2,2,0,2,2,2,2,4,6,4,0,0,6,0,6,3,0,0,0,0,0,3},
        {2,2,0,0,0,0,0,2,2,4,0,0,0,0,0,0,4,3,0,0,0,0,0,3},
        {2,0,0,0,0,0,0,0,2,4,0,0,0,0,0,0,4,3,0,0,0,0,0,3},
        {1,0,0,0,0,0,0,0,1,4,4,4,4,4,6,0,6,3,3,0,0,0,3,3},
        {2,0,0,0,0,0,0,0,2,2,2,1,2,2,2,6,6,0,0,5,0,5,0,5},
        {2,2,0,0,0,0,0,2,2,2,0,0,0,2,2,0,5,0,5,0,0,0,5,5},
        {2,0,0,0,0,0,0,0,2,0,0,0,0,0,2,5,0,5,0,5,0,5,0,5},
        {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5},
        {2,0,0,0,0,0,0,0,2,0,0,0,0,0,2,5,0,5,0,5,0,5,0,5},
        {2,2,0,0,0,0,0,2,2,2,0,0,0,2,2,0,5,0,5,0,0,0,5,5},
        {2,2,2,2,1,2,2,2,2,2,2,1,2,2,2,5,5,5,5,5,5,5,5,5}

       

        };
      //============================================================
      //============================================================
      double posX = 22.0, posY = 11.5; //x and y start position
      double dirX = -1.0, dirY = 0.0; //initial direction vector
      double planeX = 0.0, planeY = 0.66; //the 2d raycaster version of camera plane
      int K_LEFT=0;
      int K_RIGHT=0;
      int K_UP=0;
      int K_DOWN=0;
      //speed modifiers
      double moveSpeed =  .30; //the constant value is in squares/second
      double rotSpeed =   .20; //the constant value is in radians/second
      //============================================================
      //============================================================
      AS3_Val initializeScreenBuffer(void* self, AS3_Val args)
      {
          AS3_ArrayValue(args, "IntType, IntType", &resX, &resY);
          tBuffer = malloc( resX * resY * sizeof(int) );
          return AS3_Ptr( tBuffer );
      }//end of initializeScreenBuffer

       

      //used to load some textures & sprite textures
      AS3_Val initializeTexBuffer(void* self, AS3_Val args)
      {
          int index;
          AS3_ArrayValue(args, "IntType", &index);
          return AS3_Ptr( texture[index] );
      }//end of initializeTexBuffer

       

      //start the main loop
      AS3_Val loop( void* self, AS3_Val args )
      {
          AS3_ArrayValue(args,"IntType,IntType,IntType,IntType",&K_UP,&K_DOWN,&K_LEFT,&K_RIGHT);
          CastRay();
          int opos,j,i,jpos;
          for(j=0; j < resY; j++ ){
              jpos = resX*j;
              for(i=0; i < resX; i++ ){
                  opos = (jpos+i);
                  tBuffer[opos] = buffer[i][j];
              }//end of for
          }//end of for
          return 0;
      }//end of loop

      int main()
      {
          AS3_Val initializeScreenBufferMethod = AS3_Function( NULL,initializeScreenBuffer );
          AS3_Val loopMethod = AS3_Function( NULL,loop );
          AS3_Val initializeTexBufferMethod = AS3_Function( NULL,initializeTexBuffer );
          AS3_Val result = AS3_Object("initializeScreenBuffer:AS3ValType,loop:AS3ValType,initializeTexBuffer:AS3ValT ype"
                                      ,initializeScreenBufferMethod,loopMethod,initializeTexBufferMethod);
          AS3_Release( initializeScreenBufferMethod );
          AS3_Release( loopMethod );
          AS3_Release( initializeTexBufferMethod );
          AS3_LibInit( result );
         
          return 0;
      }//end of main
      //================================================================
      //================================================================
      void CastRay()
      {
          printf ("Hello World!\n");
          int x;
          int y;
          int w=screenWidth;
          int h=screenHeight;
          for( x = 0; x < screenWidth; x++) for( y = 0; y < screenHeight; y++) {buffer[x][y] = 0;} //clear the buffer instead of cls()
          for(x = 0; x < w; x++)
          {
            //calculate ray position and direction
            double cameraX = 2 * x / (double)(w) - 1; //x-coordinate in camera space    
            double rayPosX = posX;
            double rayPosY = posY;
            double rayDirX = dirX + planeX * cameraX;
            double rayDirY = dirY + planeY * cameraX;
          
            //which box of the map we're in 
            int mapX = (int)(rayPosX);
            int mapY = (int)(rayPosY);
            
            //length of ray from current position to next x or y-side
            double sideDistX;
            double sideDistY;
            
            //length of ray from one x or y-side to next x or y-side
            double deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
            double deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
            double perpWallDist;
            
            //what direction to step in x or y-direction (either +1 or -1)
            int stepX;
            int stepY;
                 
            int hit = 0; //was there a wall hit?
            int side; //was a NS or a EW wall hit?

       

            //calculate step and initial sideDist
            if (rayDirX < 0)
            {
              stepX = -1;
              sideDistX = (rayPosX - mapX) * deltaDistX;
            }//end of if (rayDirX < 0)
            else
            {
              stepX = 1;
              sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
            }//end of else
            if (rayDirY < 0)
            {
              stepY = -1;
              sideDistY = (rayPosY - mapY) * deltaDistY;
            }//end of if (rayDirY < 0)
            else
            {
              stepY = 1;
              sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
            }//end of else
            //perform DDA
            while (hit == 0)
            {
              //jump to next map square, OR in x-direction, OR in y-direction
              if (sideDistX < sideDistY)
              {
                sideDistX += deltaDistX;
                mapX += stepX;
                side = 0;
              }//end of if (sideDistX < sideDistY)
              else
              {
                sideDistY += deltaDistY;
                mapY += stepY;
                side = 1;
              }//end of else
              //Check if ray has hit a wall      
              if (worldMap[mapX][mapY] > 0) hit = 1;
            }//end of while (hit == 0)
           
            //Calculate distance of perpendicular ray (oblique distance will give fisheye effect!)   
            if (side == 0) perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
            else       perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
           
            //Calculate height of line to draw on screen      
            int lineHeight = abs((int)(h / perpWallDist));
           
            //calculate lowest and highest pixel to fill in current stripe
            int drawStart = -lineHeight / 2 + h / 2;
            if(drawStart < 0) drawStart = 0;
            int drawEnd = lineHeight / 2 + h / 2;
            if(drawEnd >= h) drawEnd = h - 1;
            //texturing calculations
            int texNum = worldMap[mapX][mapY] - 1; //1 subtracted from it so that texture 0 can be used!
           
            //calculate value of wallX
            double wallX; //where exactly the wall was hit
            if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX;
            else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY;
            wallX -= floor((wallX));
            
            //x coordinate on the texture
            int texX = (int)(wallX * (double)(texWidth));
            if(side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
            if(side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
            int y;
            for(y = drawStart; y < drawEnd; y++)
            {
              int d = y * 256 - h * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
              int texY = ((d * texHeight) / lineHeight) / 256;
              int color = texture[texNum][texWidth * texY + texX];
              //make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
              if(side == 1) color = (color >> 1) & 8355711;
              buffer[x][y] = color;
            }//end of for(y = drawStart; y < drawEnd; y++)
           
            //SET THE ZBUFFER FOR THE SPRITE CASTING
            ZBuffer[x] = perpWallDist; //perpendicular distance is used
           
            //FLOOR CASTING
            double floorXWall, floorYWall; //x, y position of the floor texel at the bottom of the wall

       

            //4 different wall directions possible
            if(side == 0 && rayDirX > 0)
            {
              floorXWall = mapX;
              floorYWall = mapY + wallX;
            }//end of if(side == 0 && rayDirX > 0)
            else if(side == 0 && rayDirX < 0)
            {
              floorXWall = mapX + 1.0;
              floorYWall = mapY + wallX;
            }//end of else if(side == 0 && rayDirX < 0)
            else if(side == 1 && rayDirY > 0)
            {
              floorXWall = mapX + wallX;
              floorYWall = mapY;
            }//end of else if(side == 1 && rayDirY > 0)
            else
            {
              floorXWall = mapX + wallX;
              floorYWall = mapY + 1.0;
            }//end of else
           
            double distWall, distPlayer, currentDist;

       

            distWall = perpWallDist;
            distPlayer = 0.0;
            if (drawEnd < 0) drawEnd = h; //becomes < 0 when the integer overflows
            //draw the floor from drawEnd to the bottom of the screen
            for(y = drawEnd + 1; y < h; y++)
            {
              currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead

       

              double weight = (currentDist - distPlayer) / (distWall - distPlayer);
              
              double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
              double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
             
              int floorTexX, floorTexY;
              floorTexX = (int)(currentFloorX * texWidth) % texWidth;
              floorTexY = (int)(currentFloorY * texHeight) % texHeight;
             
              //floor
              buffer[x][y] = (texture[3][texWidth * floorTexY + floorTexX] >> 1) & 8355711;
              //ceiling (symmetrical!)
              buffer[x][h - y] = texture[6][texWidth * floorTexY + floorTexX];
            }//end of for(y = drawEnd + 1; y < h; y++)
          }//end of for(x = 0; x < w; x++)
         
          //SPRITE CASTING
          //sort sprites from far to close
          int i;
          for(i = 0; i < numSprites; i++)
          {
            spriteOrder[i] = i;
            spriteDistance[i] = ((posX - sprite[i].x) * (posX - sprite[i].x) + (posY - sprite[i].y) * (posY - sprite[i].y)); //sqrt not taken, unneeded
          }//end of for(i = 0; i < numSprites; i++)
          combSort(spriteOrder, spriteDistance, numSprites);
          
          //after sorting the sprites, do the projection and draw them
          for(i = 0; i < numSprites; i++)
          {
            //translate sprite position to relative to camera
            double spriteX = sprite[spriteOrder[i]].x - posX;
            double spriteY = sprite[spriteOrder[i]].y - posY;
              
            //transform sprite with the inverse camera matrix
            // [ planeX   dirX ] -1                                       [ dirY      -dirX ]
            // [               ]       =  1/(planeX*dirY-dirX*planeY) *   [                 ]
            // [ planeY   dirY ]                                          [ -planeY  planeX ]
           
            double invDet = 1.0 / (planeX * dirY - dirX * planeY); //required for correct matrix multiplication
           
            double transformX = invDet * (dirY * spriteX - dirX * spriteY);
            double transformY = invDet * (-planeY * spriteX + planeX * spriteY); //this is actually the depth inside the screen, that what Z is in 3D      
                 
            int spriteScreenX = (int)((w / 2) * (1 + transformX / transformY));
           
            //parameters for scaling and moving the sprites
            #define uDiv 1
            #define vDiv 1
            #define vMove 0.0
            int vMoveScreen = (int)(vMove / transformY);
           
            //calculate height of the sprite on screen
            int spriteHeight = abs((int)(h / (transformY))) / vDiv; //using "transformY" instead of the real distance prevents fisheye
            //calculate lowest and highest pixel to fill in current stripe
            int drawStartY = -spriteHeight / 2 + h / 2 + vMoveScreen;
            if(drawStartY < 0) drawStartY = 0;
            int drawEndY = spriteHeight / 2 + h / 2 + vMoveScreen;
            if(drawEndY >= h) drawEndY = h - 1;
           
            //calculate width of the sprite
            int spriteWidth = abs( (int) (h / (transformY))) / uDiv;
            int drawStartX = -spriteWidth / 2 + spriteScreenX;
            if(drawStartX < 0) drawStartX = 0;
            int drawEndX = spriteWidth / 2 + spriteScreenX;
            if(drawEndX >= w) drawEndX = w - 1;
           
            //loop through every vertical stripe of the sprite on screen
            int stripe;
            for(stripe = drawStartX; stripe < drawEndX; stripe++)
            {
              int texX = (int)(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texWidth / spriteWidth) / 256;
              //the conditions in the if are:
              //1) it's in front of camera plane so you don't see things behind you
              //2) it's on the screen (left)
              //3) it's on the screen (right)
              //4) ZBuffer, with perpendicular distance
              int y;
              if(transformY > 0 && stripe > 0 && stripe < w && transformY < ZBuffer[stripe])
              for(y = drawStartY; y < drawEndY; y++) //for every pixel of the current stripe
              {
                int d = (y-vMoveScreen) * 256 - h * 128 + spriteHeight * 128; //256 and 128 factors to avoid floats
                int texY = ((d * texHeight) / spriteHeight) / 256;
                unsigned int color = texture[sprite[spriteOrder[i]].texture][texWidth * texY + texX]; //get current color from the texture//??????????????????
                if((color & 0x00FFFFFF) != 0) buffer[stripe][y] = color; //paint pixel if it isn't black, black is the invisible color
              }//end of for(y = drawStartY; y < drawEndY; y++)
            }//end of for(stripe = drawStartX; stripe < drawEndX; stripe++)
          }//end of for(i = 0; i < numSprites; i++)
        
         
          //readKeys
          //move forward if no wall in front of you
          if (K_UP)
          {
            if(worldMap[(int)(posX + dirX * moveSpeed)][(int)(posY)] == false) posX += dirX * moveSpeed;
            if(worldMap[(int)(posX)][(int)(posY + dirY * moveSpeed)] == false) posY += dirY * moveSpeed;
          }//end of if (K_UP)
          //move backwards if no wall behind you
          if (K_DOWN)
          {
            if(worldMap[(int)(posX - dirX * moveSpeed)][(int)(posY)] == false) posX -= dirX * moveSpeed;
            if(worldMap[(int)(posX)][(int)(posY - dirY * moveSpeed)] == false) posY -= dirY * moveSpeed;
          }//end of if (K_DOWN)
          //rotate to the right
          if (K_RIGHT)
          {
            //both camera direction and camera plane must be rotated
            double oldDirX = dirX;
            dirX = dirX * cos(-rotSpeed) - dirY * sin(-rotSpeed);
            dirY = oldDirX * sin(-rotSpeed) + dirY * cos(-rotSpeed);
            double oldPlaneX = planeX;
            planeX = planeX * cos(-rotSpeed) - planeY * sin(-rotSpeed);
            planeY = oldPlaneX * sin(-rotSpeed) + planeY * cos(-rotSpeed);
          }//end of if (K_RIGHT)
          //rotate to the left
          if (K_LEFT)
          {
            //both camera direction and camera plane must be rotated
            double oldDirX = dirX;
            dirX = dirX * cos(rotSpeed) - dirY * sin(rotSpeed);
            dirY = oldDirX * sin(rotSpeed) + dirY * cos(rotSpeed);
            double oldPlaneX = planeX;
            planeX = planeX * cos(rotSpeed) - planeY * sin(rotSpeed);
            planeY = oldPlaneX * sin(rotSpeed) + planeY * cos(rotSpeed);
          }//end of if (K_LEFT)

       


      }//end of CastRay

       

      //sort algorithm
      void combSort(int* order, double* dist, int amount)
      {
        int gap = amount;
        enum bool swapped = false;
        while(gap > 1 || swapped)
        {
          //shrink factor 1.3
          gap = (gap * 10) / 13;
          if(gap == 9 || gap == 10) gap = 11;
          if (gap < 1) gap = 1;
          swapped = false;
          int i;
          for (i = 0; i < amount - gap; i++)
          {
            int j = i + gap;
            if (dist[i] < dist[j])
            {
              double disttemp=dist[i];
              dist[i]=dist[j];
              dist[j]=disttemp;
              int ordertemp=order[i];
              order[i]=order[j];
              order[j]=ordertemp;
              swapped = true;
            }//end of if (dist[i] < dist[j])
          }//end of for (i = 0; i < amount - gap; i++)
        }//end of while(gap > 1 || swapped)
      }//end of combSort

      the sorce file can be found here http://bruce-lab.blogspot.com/2010/04/alchemy-ray-casting-engine-source-code.html