Jibble

Author Topic: [C++] Raycasting - Drawing the Rear of a Cube? [SOLVED]  (Read 1177 times)

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    • I can help with backgrounds
    • I can help with characters
    • I can help with scripting
    • Scavenger worked on one or more games that won an AGS Award!
    •  
    • Scavenger worked on one or more games that was nominated for an AGS Award!
I'm trying to write a raycaster for AGS (that can be controlled from within AGS using sprites as maps and stuff), and it's going pretty well. I currently have a very very simple raycaster working, based on this tutorial, and I've added light levels and stuff to it, and am currently working on transparent walls. Unfortunately, I've run into a problem I can't solve myself, and I'm not sure where else to turn to. I know I'm asking a lot of non-AGSScript questions, but I really can't do this in AGSScript without it requiring a futuristic supercomputer.

My problem is that I can't seem to get the back face of a cube to render properly. This is what I got so far:


The cube has the pillar texture on all four faces, so in reality, it's got to look something like this, with the pillar texture visible at the back as well. But my attempts, well, they're not going well. I end up with an infinite line of "other walls", instead of just the one I wanted. You can see that the opposite wall of the cube just goes on forever when you look into it. I'm not even sure how it's doing that. And the adjacent wall isn't drawn at all, to be expected, but I'm not sure how to do that either.



My method is:
1) Cast ray
2) Continue until it hits a wall.
2) Start drawing that wall, using the ZBuffer to mask out anything already drawn in front of it.
3) If the wall has any transparent pixels, flag the thing to draw deeper.
4) On the next pass, draw the back face by flipping the ray direction and manually stepping to the next intersection.
5) Goto 2 afterwards to draw the wall behind it.

I'm sure I'm doing this wrong, but I'm not sure how to fix it, I don't understand the code well enough to do anything constructive with it. Is there anything I can do to stop this? Is there a better way to be doing this?

My code for drawing walls is:
Code: C
  1.  while (hit == 0 && deeper == true)
  2. {
  3.         if (opposite)
  4.         {
  5.                 rayDirX = rayDirX * (-1);
  6.                 rayDirY = rayDirY * (-1);
  7.                 stepX = stepX * (-1);
  8.                 stepY = stepY * (-1);
  9.         }
  10.         else if (sideDistX < sideDistY) //jump to next map square, OR in x-direction, OR in y-direction
  11.         {
  12.           sideDistX += deltaDistX;
  13.           mapX += stepX;
  14.           side = 0;
  15.         }
  16.         else
  17.         {
  18.           sideDistY += deltaDistY;
  19.           mapY += stepY;
  20.           side = 1;
  21.         }
  22.         //Check if ray has hit a wall      
  23.         if (worldMap[mapX][mapY] > 0)
  24.                 {
  25.                         hit = 1; //Set this to true so that by default, it's impossible to hang the engine.
  26.                         deeper = false; //Set this to false so that we don't go deeper than we need to.
  27.  
  28.                         //Calculate distance of perpendicular ray (oblique distance will give fisheye effect!)    
  29.                         if (side == 0) perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
  30.                         else       perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
  31.      
  32.                          //Calculate height of line to draw on screen      
  33.                  int lineHeight = abs(int(h / perpWallDist));
  34.                  
  35.                  //calculate lowest and highest pixel to fill in current stripe
  36.                  drawStart = -lineHeight / 2 + h /2;
  37.                  if(drawStart < 0) drawStart = 0;
  38.                  drawEnd = lineHeight / 2 + h / 2;
  39.                  if(drawEnd >= h) drawEnd = h - 1;
  40.                  //texturing calculations
  41.                  int texNum = worldMap[mapX][mapY] - 1; //1 subtracted from it so that texture 0 can be used!
  42.                  
  43.                  //calculate value of wallX
  44.                  if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX;
  45.                  else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY;
  46.                  wallX -= floor((wallX));
  47.                  
  48.                  //x coordinate on the texture
  49.                          int wall_light=0;
  50.                  int texX = int(wallX * double(texWidth));
  51.                  if(side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
  52.                  if(side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
  53.                  if (rayDirX > 0 && side == 0) wall_light = 255 / (8-lightMap [(int)mapX-1][(int)mapY]);
  54.                  if (rayDirX < 0 && side == 0) wall_light = 255 / (8-lightMap [(int)mapX+1][(int)mapY]);
  55.                  if (rayDirY > 0 && side == 1) wall_light = 255 / (8-lightMap [(int)mapX][(int)mapY-1]);
  56.                  if (rayDirY < 0 && side == 1) wall_light = 255 / (8-lightMap [(int)mapX][(int)mapY+1]);
  57.                  for(int y = drawStart; y < drawEnd; y++)
  58.                         {
  59.                                 if (ZBuffer[x][y] > perpWallDist || ZBuffer[x][y] == 0) //We can draw.
  60.                                 {
  61.                                     int d = y * 256 - h * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
  62.                                     int texY = ((d * texHeight) / lineHeight) / 256;
  63.                                     int color = texture[texNum][texWidth * texY + texX];
  64.                                     if (color > 0)
  65.                                         {
  66.                                             color = MixColorAlpha (color,GetColor565(0,0,10),wall_light);
  67.                                             buffer[y][x] = color;
  68.                                             //SET THE ZBUFFER FOR THE SPRITE CASTING
  69.                                             ZBuffer[x][y] = perpWallDist; //perpendicular distance is used
  70.                                         }
  71.                                         else
  72.                                         {
  73.                                             //We found transparency, we have to draw deeper.
  74.                                             deeper = true;
  75.                                             hit = 0;
  76.                                         }
  77.                                 }
  78.                         }
  79.                          if (opposite)
  80.                          {
  81.                                  opposite = false;
  82.                                  rayDirX = rayDirX * (-1);
  83.                                  rayDirY = rayDirY * (-1);
  84.                                  stepX = stepX * (-1);
  85.                                  stepY = stepY * (-1);
  86.                          }
  87.                          else if (!opposite && deeper && (prevmapX != mapX && prevmapY != mapY))
  88.                          {
  89.                                  opposite = true;
  90.                                  prevmapX = mapX;
  91.                                  prevmapY = mapY;
  92.                          }
  93.                         //End of wall drawing functions.
  94.                         }
  95.                 //End of loop.
  96. }


Full code is here in case I've missed anything out.

Thank you in advance, and sorry for filling the technical forum.
« Last Edit: 30 Dec 2015, 11:05 by Scavenger »

Mandle

  • NO PIXEL LEFT BEHIND!!!
    • Mandle worked on one or more games that won an AGS Award!
    •  
    • Mandle worked on one or more games that was nominated for an AGS Award!
Re: [C++] Raycasting - Drawing the Rear of a Cube?
« Reply #1 on: 29 Dec 2015, 15:08 »
Ye gods man!!!

DOOM type game in AGS?!

AWESOME!!!!

Re: [C++] Raycasting - Drawing the Rear of a Cube?
« Reply #2 on: 29 Dec 2015, 21:47 »
I'd check for the texture being partly transparent (using a flag, or texture IDs in a certain range), and if so, keep the ray going until it hits a standard wall, storing walls (texture ID, texture coord, size) in between in a list. After rendering the far wall, go back and render the other pixel columns in reverse order.

I'll also offer an alternative solution that would require a slightly different engine, but this method of showing a column is kinda weird anyway, isn't it?

My solution is to use lines in a 2D space for the walls (those can relatively easily be generated from an ascii map). Objects like the column are then implemented just like walls, only that they will constantly rotate so the "wall" always runs perpendicular to the player's line of sight.
That way the column appears as scaled 2D sprite but the existing 2.5D engine can be used to render it, proper clipping and all (afaik that's how Wolfenstein showed objects and enemies). One could even implement proper lighting by setting a cylinder flag for the object and using the texture coordinate to alter the lighting calculation.
Fail at Floaty Rog' now!  still having to deal with what games are going through

Scavenger

  • Cavefish
  • In Four Glorious Colours!
    • I can help with animation
    • I can help with backgrounds
    • I can help with characters
    • I can help with scripting
    • Scavenger worked on one or more games that won an AGS Award!
    •  
    • Scavenger worked on one or more games that was nominated for an AGS Award!
Re: [C++] Raycasting - Drawing the Rear of a Cube?
« Reply #3 on: 30 Dec 2015, 02:29 »
Khris : I've already implemented objects like that, but this is for fences, doors, and other wall types that the  player needs to see through. I'm just using the column texture because it's already on the texture map.

My biggest problem thus far is trying to get the ray caster to hit the back walls of a cube at all, I'm not sure how to do it. The method I tried just renders it to the front wall texture and that's definitely not what I need. How do I get the ray to hit the rear face at all?

EDIT: It's been solved, I needed to flip the signs on a lot of the math in case of drawing the opposite wall, and offset the floorcasting by one unit to compensate:



This'll be useful for all of my fence, door, and mysterious shaft of light needs!

Though now I have a new problem: Drawing the back face without first drawing the front face, like so:



The wall only gets drawn if the front face is drawn first (which triggers the Opposite flag), but I'm not sure how to make it so that the opposite wall is drawn when it's visible, rather than when the ray passes right through the block. You can see that the left block there makes the opposite side of the right block visible, but it doesn't draw the back face. What IS good is that fully solid blocks are drawn as well as the transparent blocks, with no z-fighting.

Code: C
  1. void Raycast_Render (int slot)
  2. {
  3.         long w=0,h=0;
  4.         BITMAP *screen = engine->GetSpriteGraphic (slot);
  5.         engine->GetBitmapDimensions (screen,&w,&h,NULL);
  6.         unsigned char** buffer = engine->GetRawBitmapSurface (screen);
  7.         for (int x = 0;x<w;x++)
  8.         {
  9.                 for (int y=0;y<h;y++)
  10.                 {
  11.                         ZBuffer[x][y] = 0;
  12.                 }
  13.         }
  14.   //start the main loop
  15.     for(int x = 0; x < w; x++)
  16.     {
  17.       //calculate ray position and direction
  18.       double cameraX = 2 * x / double(w) - 1; //x-coordinate in camera space    
  19.       double rayPosX = posX;
  20.       double rayPosY = posY;
  21.       double rayDirX = dirX + planeX * cameraX;
  22.       double rayDirY = dirY + planeY * cameraX;
  23.      
  24.       //which box of the map we're in  
  25.       int mapX = int(rayPosX);
  26.       int mapY = int(rayPosY);
  27.        
  28.       //length of ray from current position to next x or y-side
  29.       double sideDistX;
  30.       double sideDistY;
  31.        
  32.       //length of ray from one x or y-side to next x or y-side
  33.       double deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
  34.       double deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
  35.       double perpWallDist;
  36.        
  37.       //what direction to step in x or y-direction (either +1 or -1)
  38.       int stepX;
  39.       int stepY;
  40.       int prevmapX=0;
  41.           int prevmapY=0;
  42.       int hit = 0; //was there a wall hit?
  43.       int side; //was a NS or a EW wall hit?
  44.          
  45.       //calculate step and initial sideDist
  46.       if (rayDirX < 0)
  47.       {
  48.         stepX = -1;
  49.         sideDistX = (rayPosX - mapX) * deltaDistX;
  50.       }
  51.       else
  52.       {
  53.         stepX = 1;
  54.         sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX;
  55.       }
  56.       if (rayDirY < 0)
  57.       {
  58.         stepY = -1;
  59.         sideDistY = (rayPosY - mapY) * deltaDistY;
  60.       }
  61.       else
  62.       {
  63.         stepY = 1;
  64.         sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY;
  65.       }
  66.       //perform DDA
  67.           bool deeper = true;
  68.           bool opposite = false;
  69.           bool oppositedrawn = false;
  70.           double wallX; //where exactly the wall was hit
  71.           int drawStart;
  72.           int drawEnd;
  73.       while (hit == 0 && deeper == true)
  74.           {
  75.                 if (opposite)
  76.                 {
  77.                           rayDirX = rayDirX * (-1);
  78.                           rayDirY = rayDirY * (-1);
  79.                           stepX = stepX * (-1);
  80.                           stepY = stepY * (-1);
  81.                           if (sideDistX < sideDistY) side = 0;
  82.                           else side = 1;
  83.                 }
  84.                 else if (sideDistX < sideDistY) //jump to next map square, OR in x-direction, OR in y-direction
  85.         {
  86.           sideDistX += deltaDistX;
  87.           mapX += stepX;
  88.           side = 0;
  89.         }
  90.         else
  91.         {
  92.           sideDistY += deltaDistY;
  93.           mapY += stepY;
  94.           side = 1;
  95.         }
  96.         //Check if ray has hit a wall      
  97.         if (worldMap[mapX][mapY] > 0)
  98.                 {
  99.                         hit = 1; //Set this to true so that by default, it's impossible to hang the engine.
  100.                         deeper = false; //Set this to false so that we don't go deeper than we need to.
  101.  
  102.                         //Calculate distance of perpendicular ray (oblique distance will give fisheye effect!)    
  103.                         if (side == 0) perpWallDist = fabs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX);
  104.                         else       perpWallDist = fabs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY);
  105.                          //Calculate height of line to draw on screen      
  106.                  int lineHeight = abs(int(h / perpWallDist));
  107.                  
  108.                  //calculate lowest and highest pixel to fill in current stripe
  109.                  drawStart = -lineHeight / 2 + h /2;
  110.                  if(drawStart < 0) drawStart = 0;
  111.                  drawEnd = lineHeight / 2 + h / 2;
  112.                  if(drawEnd >= h) drawEnd = h - 1;
  113.                  //texturing calculations
  114.                  int texNum = worldMap[mapX][mapY] - 1; //1 subtracted from it so that texture 0 can be used!
  115.                  if (!opposite)
  116.                          {       
  117.                  //calculate value of wallX
  118.                  if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX;
  119.                  else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY;
  120.                          }
  121.                          else
  122.                          {
  123.                                 if (side == 1) wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / -rayDirY) * -rayDirX;
  124.                         else       wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / -rayDirX) * -rayDirY;
  125.                          }
  126.                  wallX -= floor((wallX));
  127.                  
  128.                  //x coordinate on the texture
  129.                          int wall_light=0;
  130.                  int texX = int(wallX * double(texWidth));
  131.                  if(side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
  132.                  if(side == 1 && rayDirY < 0) texX = texWidth - texX - 1;
  133.                          if (!opposite)
  134.                          {
  135.                          if (rayDirX > 0 && side == 0) wall_light = 255 / (8-lightMap [(int)mapX-1][(int)mapY]);
  136.                          if (rayDirX < 0 && side == 0) wall_light = 255 / (8-lightMap [(int)mapX+1][(int)mapY]);
  137.                          if (rayDirY > 0 && side == 1) wall_light = 255 / (8-lightMap [(int)mapX][(int)mapY-1]);
  138.                          if (rayDirY < 0 && side == 1) wall_light = 255 / (8-lightMap [(int)mapX][(int)mapY+1]);
  139.                          }
  140.                          else if (opposite) wall_light = 255 / (8-lightMap [(int)mapX][(int)mapY]);
  141.                  for(int y = drawStart; y < drawEnd; y++)
  142.                         {
  143.                                         if (ZBuffer[x][y] > perpWallDist || ZBuffer[x][y] == 0) //We can draw.
  144.                                         {
  145.                                 int d = y * 256 - h * 128 + lineHeight * 128; //256 and 128 factors to avoid floats
  146.                                 int texY = ((d * texHeight) / lineHeight) / 256;
  147.                                 int color = texture[texNum][texWidth * texY + texX];
  148.                                 if (color > 0)
  149.                                                 {
  150.                                                         color = MixColorAlpha (color,GetColor565(0,0,10),wall_light);
  151.                                                         buffer[y][x] = color;
  152.                                                         //SET THE ZBUFFER FOR THE SPRITE CASTING
  153.                                                         ZBuffer[x][y] = perpWallDist; //perpendicular distance is used
  154.                                                 }
  155.                                         else
  156.                                                 {
  157.                                                         //We found transparency, we have to draw deeper.
  158.                                                         deeper = true;
  159.                                                         hit = 0;
  160.                                                 }
  161.                                         }
  162.                         }
  163.                          if (opposite)
  164.                          {
  165.                                  oppositedrawn = true;
  166.                                  if (deeper) opposite = false;
  167.                                  rayDirX = rayDirX * (-1);
  168.                                  rayDirY = rayDirY * (-1);
  169.                                  stepX = stepX * (-1);
  170.                                  stepY = stepY * (-1);
  171.                          }
  172.                          else if (!opposite && deeper && (prevmapX != mapX && prevmapY != mapY))
  173.                          {
  174.                                  opposite = true;
  175.                                  prevmapX = mapX;
  176.                                  prevmapY = mapY;
  177.                          }
  178.                         //End of wall drawing functions.
  179.                         }
  180.                 //End of loop.
  181.                 }
  182.      
  183.       //FLOOR CASTING
  184.       double floorXWall, floorYWall; //x, y position of the floor texel at the bottom of the wall
  185.       //4 different wall directions possible
  186.       if(side == 0 && rayDirX > 0)
  187.       {
  188.         floorXWall = mapX;
  189.         floorYWall = mapY + wallX;
  190.                 if (opposite) floorXWall = floorXWall + 1.0;
  191.       }
  192.       else if(side == 0 && rayDirX < 0)
  193.       {
  194.         floorXWall = mapX + 1.0;
  195.         floorYWall = mapY + wallX;
  196.                 if (opposite) floorXWall = floorXWall - 1.0;
  197.       }
  198.       else if(side == 1 && rayDirY > 0)
  199.       {
  200.         floorXWall = mapX + wallX;
  201.         floorYWall = mapY;
  202.                 if (opposite) floorYWall = floorYWall + 1.0;
  203.       }
  204.       else
  205.       {
  206.         floorXWall = mapX + wallX;
  207.         floorYWall = mapY + 1.0;
  208.                 if (opposite) floorYWall = floorYWall - 1.0;
  209.       }
  210.      
  211.       double distWall, distPlayer, currentDist;
  212.  
  213.       distWall = perpWallDist;
  214.       distPlayer = 0.0;
  215.       if (drawEnd < 0) drawEnd = h; //becomes < 0 when the integer overflows
  216.       //draw the floor from drawEnd to the bottom of the screen
  217.       for(int y = drawEnd; y < h; y++)
  218.       {
  219.         currentDist = h / (2.0 * y - h); //you could make a small lookup table for this instead
  220.                 if (currentDist < ZBuffer[x][y] || ZBuffer[x][y] == 0)
  221.                 {
  222.                         double weight = (currentDist - distPlayer) / (distWall - distPlayer);
  223.          
  224.                         double currentFloorX = weight * floorXWall + (1.0 - weight) * posX;
  225.                         double currentFloorY = weight * floorYWall + (1.0 - weight) * posY;
  226.        
  227.                         int floorTexX, floorTexY;
  228.                         int lighting = 255 / (8-lightMap [(int)currentFloorX][(int)currentFloorY]);
  229.                         floorTexX = int(currentFloorX * texWidth) % texWidth;
  230.                         floorTexY = int(currentFloorY * texHeight) % texHeight;
  231.        
  232.                         //floor
  233.                         buffer[y][x] = MixColorAlpha(texture[3][texWidth * floorTexY + floorTexX],GetColor565(0,0,10),lighting);
  234.                         //ceiling (symmetrical!)
  235.                         buffer[h-y][x] = MixColorAlpha(texture[6][texWidth * floorTexY + floorTexX],GetColor565(0,0,10),lighting);
  236.                         //SET THE ZBUFFER FOR THE SPRITE CASTING
  237.                         ZBuffer[x][y] = currentDist; //perpendicular distance is used
  238.                         ZBuffer[x][h-y] = currentDist; //perpendicular distance is used
  239.                 }
  240.       }
  241.     }
  242.    
  243.        
  244.  
  245.     //SPRITE CASTING
  246.     //sort sprites from far to close
  247.  
  248.     for(int i = 0; i < numSprites; i++)
  249.     {
  250.       spriteOrder[i] = i;
  251.       spriteDistance[i] = ((posX - sprite[i].x) * (posX - sprite[i].x) + (posY - sprite[i].y) * (posY - sprite[i].y)); //sqrt not taken, unneeded
  252.     }
  253.     combSort(spriteOrder, spriteDistance, numSprites);
  254.      
  255.     //after sorting the sprites, do the projection and draw them
  256.     for(int i = 0; i < numSprites; i++)
  257.     {
  258.       //translate sprite position to relative to camera
  259.       double spriteX = sprite[spriteOrder[i]].x - posX;
  260.       double spriteY = sprite[spriteOrder[i]].y - posY;
  261.          
  262.       //transform sprite with the inverse camera matrix
  263.       // [ planeX   dirX ] -1                                       [ dirY      -dirX ]
  264.       // [               ]       =  1/(planeX*dirY-dirX*planeY) *   [                 ]
  265.       // [ planeY   dirY ]                                          [ -planeY  planeX ]
  266.      
  267.       double invDet = 1.0 / (planeX * dirY - dirX * planeY); //required for correct matrix multiplication
  268.      
  269.       double transformX = invDet * (dirY * spriteX - dirX * spriteY);
  270.       double transformY = invDet * (-planeY * spriteX + planeX * spriteY); //this is actually the depth inside the screen, that what Z is in 3D      
  271.            
  272.       int spriteScreenX = int((w / 2) * (1 + transformX / transformY));
  273.      
  274.       //parameters for scaling and moving the sprites
  275.       #define uDiv 1
  276.       #define vDiv 1
  277.       #define vMove 0.0
  278.       int vMoveScreen = int(vMove / transformY);
  279.      
  280.       //calculate height of the sprite on screen
  281.       int spriteHeight = abs(int(h / (transformY))) / vDiv; //using "transformY" instead of the real distance prevents fisheye
  282.       //calculate lowest and highest pixel to fill in current stripe
  283.       int drawStartY = -spriteHeight / 2 + h / 2 + vMoveScreen;
  284.       if(drawStartY < 0) drawStartY = 0;
  285.       int drawEndY = spriteHeight / 2 + h / 2 + vMoveScreen;
  286.       if(drawEndY >= h) drawEndY = h - 1;
  287.      
  288.       //calculate width of the sprite
  289.       int spriteWidth = abs( int (h / (transformY))) / uDiv;
  290.       int drawStartX = -spriteWidth / 2 + spriteScreenX;
  291.       if(drawStartX < 0) drawStartX = 0;
  292.       int drawEndX = spriteWidth / 2 + spriteScreenX;
  293.       if(drawEndX >= w) drawEndX = w - 1;
  294.       int spr_light = 255 / (8-lightMap [(int)sprite[spriteOrder[i]].x][(int)sprite[spriteOrder[i]].y]);
  295.       //loop through every vertical stripe of the sprite on screen
  296.       for(int stripe = drawStartX; stripe < drawEndX; stripe++)
  297.       {
  298.         int texX = int(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texWidth / spriteWidth) / 256;
  299.         //the conditions in the if are:
  300.         //1) it's in front of camera plane so you don't see things behind you
  301.         //2) it's on the screen (left)
  302.         //3) it's on the screen (right)
  303.         //4) ZBuffer, with perpendicular distance
  304.         if(transformY > 0 && stripe > 0 && stripe < w)
  305.         for(int y = drawStartY; y < drawEndY; y++) //for every pixel of the current stripe
  306.         {
  307.                   if (transformY < ZBuffer[stripe][y])
  308.                   {
  309.                         int d = (y-vMoveScreen) * 256 - h * 128 + spriteHeight * 128; //256 and 128 factors to avoid floats
  310.                         int texY = ((d * texHeight) / spriteHeight) / 256;
  311.                         unsigned char color = texture[sprite[spriteOrder[i]].texture][texWidth * texY + texX]; //get current color from the texture
  312.                         if (color !=0)
  313.                         {
  314.                                   color = MixColorAlpha (color,GetColor565(0,0,10),spr_light);
  315.                                   buffer[y][stripe] = color; //paint pixel if it isn't black, black is the invisible color
  316.                   }
  317.                   }
  318.         }
  319.       }
  320.          
  321.     }
  322.         engine->ReleaseBitmapSurface (screen);
  323.         engine->NotifySpriteUpdated (slot);
  324. }

EDIT (again): Solved that. I should have this engine ready really soon!

« Last Edit: 30 Dec 2015, 11:06 by Scavenger »