⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 raycast.cpp

📁 quake 游戏原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

/*********************

Portions of this code taken from Programming Gurus book by Waite Group

Most written for super speed game on '040 by Joshua Glazer
Those portions are Copyright Joshua Glazer c1994

Lightening fast two-level Fixed Point Routines Copyright Joshua Glazer c1994

These routines may be used by one Matthew Howard, but 
credit must be given to Joshua Glazer c1994

**** Yea, well I wrote some nice asm routines for IBM so, you can give Matt Howard -1994
a little credit too! ****

I like writing Joshua Glazer c1994

Violaters of the Copyright law violated by violating this source-code
will be hunted down and castrated (or spayed) by Joshua Glazer c1994

This means you!

Actually, 'This' is a pronoun used to refer to a subject being talked about
which is closer to the speaker than some other object.

Oh Shut Up.

Copyright Joshua Glazer c1994
*********************/

#include "asm.h"
#include "ray.h"
#include "rayrend.h"
#include "raycl.h"
#include "rayvb.h"
#include "assert.h"
#include "globals.h"
#include "fixed.h"
#include <mem.h>
#include "mymem.h"
#include <math.h>
#include "asm.h"
#include "prevarr.h"
#include "voxinter.h"
#include "texconst.h"
#include "scrconf.h"
#include "ldattrib.h"
#include <stdio.h>
#include <stdlib.h>


#define BLACK_COLOR 240  
#define SS_NO_VISIBLE -1
#define SS_VISIBLE 0

#define LOW_WALL 0
#define HIGH_WALL 1
#define MID_WALL 2

#define CLIP
#define CHECK_HIGH_LOW_CLIP_OUT
#define CLIPVERT
#define DO_FLOORS

#define BAR_LENGTH 10
#define RED_COLOR 79

typedef struct WALL_MOVE_INFO {
   MYFIXED top_start, bottom_start;
   MYFIXED top_increment, bottom_increment;
   ptexture texture;
   short type;
   long v_height;
   vb_node * cur_bounds;
} wall_move_info;

typedef struct INTERSECT_STRUCT {
   long distance, xpos;
   MYFIXED increment;
} intersect_struct;

intersect_struct * intersects;

MYFIXED * floor_offsets_x;
MYFIXED * floor_offsets_y;
long v_angle_plus_90;
MYFIXED floor_trans_x, floor_trans_y;
short prev_win_top, prev_win_bottom,
prev_wall_top, prev_wall_bottom, proj_left, proj_right;

short floor_ray, floor_start, floor_end, cur_height_diff;
Byte * floor_texture;
Byte * cur_sky_texture;

sector * Cur_Sec;

long ssetup_count;

void Seg_Setup(wall_move_info & mid_walls);
void Get_Intersects(pvector2 base_v, angle_type angle_diff);
void Draw_Seg(seg * cur_seg);

/*
   Draw_Health
   Draws a bar for player's health
*/

void Draw_Health() {
long the_health=the_player->stats.current_health;
long start_pos=Get_Phys_Screen_Width()*(Get_Phys_Screen_Height()-BAR_LENGTH);
for (short cur_vert=0; cur_vert<BAR_LENGTH; cur_vert++) {
  memset(buff+start_pos+(cur_vert*Get_Phys_Screen_Width()), RED_COLOR, the_health);
}
}
/*
   Win_Bounds_Setup
   Just initializes bounding values before a draw to all 0's for top and
   WINDOW_HEIGHT for bottom
*/

inline void Win_Bounds_Setup()
{
   memset(win_tops, 0, WINDOW_WIDTH * sizeof(short));
   memsetshort(win_bottoms, WINDOW_HEIGHT, WINDOW_WIDTH);
}

/*
   Init_Floor_Values
   Initializes values used for floor drawing
   Notes: None
*/

inline void Init_Floor_Values()
{

   // might as well calculate an angle that is used all the time for drawing floors

   v_angle_plus_90=Get_Angle_Difference(render_view_angle, ANGLE_90);

   floor_trans_x=fixedmult(x_inv_trans, rcos_table[v_angle_plus_90]);
   floor_trans_y=fixedmult(x_inv_trans, rsin_table[v_angle_plus_90]);

   long floor_adder_x=floor_trans_x >> X_TRANS_SHIFT;
   long floor_adder_y=floor_trans_y >> X_TRANS_SHIFT;

   long floor_sum_x=floor_adder_x * (-WINDOW_MIDDLEW);
   long floor_sum_y=floor_adder_y * (-WINDOW_MIDDLEW);

   for (short cur_ray=0; cur_ray < (WINDOW_WIDTH); cur_ray++) {
      floor_offsets_x[cur_ray]=floor_sum_x;
      floor_offsets_y[cur_ray]=floor_sum_y;

      floor_sum_x+=floor_adder_x;
      floor_sum_y+=floor_adder_y;
      }

}

/*
   Start_Tex
   Marks starts of texture lines on rows from "start" up to but not including "end at x position "ray"
   Notes: Assumes floor_texture already points to the floor texture to draw
*/
                       
inline void Start_Tex() {
   short row;

   for (row=floor_start; row<floor_end; row++) {
      tex_mark_table[row]=floor_ray;
      }

}


/*
   Finish_Tex
   Draws the previously marked floor textures on rows from "start" up to but no including "end"
   Ends lines at "ray"
   Notes: Assumes floor_texture already points to the floor texture to draw
*/

inline void Finish_Tex() {

 
   short row, start_ray;
   long tempLight;
   MYFIXED distance_fixed;
   floor_run_info * cur_floor_run;

   for (row=floor_start; row<floor_end; row++) {

      start_ray=tex_mark_table[row];

      if (floor_ray<=start_ray)
         continue;

      if (floor_run_count>=MAX_FLOOR_RUNS)
         break;

      cur_floor_run=floor_runs+floor_run_count;
      floor_run_count++;

      // Set row to draw on

      cur_floor_run->screen_y=row;

      // Get starting x and width of texture

      cur_floor_run->scale=(short)(floor_ray-start_ray);

      cur_floor_run->screen_x=start_ray;

      // Get distance to floor

      distance_fixed=cur_height_diff *distance_table[row];
      Assert(distance_fixed < 0, "Negative floor row distance");

      // Get map starting positions

      cur_floor_run->map_x=fixedmult(rcos_table[render_view_angle] + 
        floor_offsets_x[start_ray], distance_fixed)+(render_x);
      cur_floor_run->map_y=fixedmult(rsin_table[render_view_angle] +
        floor_offsets_y[start_ray], distance_fixed)+(render_y);

      // Get increments by multiplying the increment along the  actual line by sin & cos of line angle

      cur_floor_run->x_inc=fixedmult(distance_fixed,
         floor_trans_x) >> X_TRANS_SHIFT;
      cur_floor_run->y_inc=fixedmult(distance_fixed,
         floor_trans_y) >> X_TRANS_SHIFT;

      // do light calculation
      // In getting the light value, we take into account that distance_fixed
      // is a fixed point number and add to the right shift the fixed point conversion
      // number

      tempLight=(SecLight(Cur_Sec)-
         (distance_fixed >> (SHIFT+SecLTSpeed(Cur_Sec))) );
      if (tempLight<0) tempLight=0;
      if (tempLight>MAX_LIGHT) tempLight=MAX_LIGHT;

      Assert(((tempLight <0) || (tempLight >MAX_LIGHT)), "Bad Lighting Value");
      cur_floor_run->light=pal_table[tempLight];

       cur_floor_run->texture=floor_texture;

   } /* endfor */
}


/*
  Draw_Sky_Column
  Draws one column of the sky texture from "top" down to but not including "bottom"
  Notes: This is a hack. Code is cryptic. Should be improved upon. For example, it should
  not require that sky texture be length of screen. Requires a theoretical
  understanding of screen rays intersecting a circle on the horizon that I don't have
*/

inline void Draw_Sky_Column()
{

   // Was the programmer such an idiot that he tried to draw column of length 0?
   if (floor_start>=floor_end)
      return;

   if (wall_run_count>=MAX_WALL_RUNS) {
      return;
   } /* endif */
   wall_run_info * cur_wall_run=wall_runs+wall_run_count;
   wall_run_count++;

   // Setup the render constants, pretty standard
   cur_wall_run->bound_val=SKY_HEIGHT-1;
   cur_wall_run->texture=cur_sky_texture;
   cur_wall_run->ray=floor_ray;
   cur_wall_run->top=floor_start;
   cur_wall_run->scale=floor_end-floor_start;
   cur_wall_run->clip=floor_start << SLIVER_SHIFT;
   cur_wall_run->light=pal_table[MAX_LIGHT];
   cur_wall_run->increment=SLIVER_ONE;
   cur_wall_run->width_shift=SKY_SHIFT;

   // Do a whole lot of stupid calculations to get the column in the texture to draw

   long temp_column;

   long temp_ray=floor_ray*HORIZ_VIEW_RANGE/WINDOW_WIDTH;
   long tempAngle;
   if (temp_ray<(HORIZ_VIEW_RANGE>>1))
      tempAngle=temp_ray;
   else tempAngle=Get_Angle_Difference(HORIZ_VIEW_RANGE, temp_ray);
   MYFIXED tempdiv=fixeddiv(tan_table[tempAngle],
        tan_table[HORIZ_VIEW_RANGE>>1]);
   tempdiv=convtoLONG((HORIZ_VIEW_RANGE>>1)*tempdiv);
   if (temp_ray>=(HORIZ_VIEW_RANGE>>1))
      tempdiv=HORIZ_VIEW_RANGE-tempdiv;
   // div by 2 to stretch out backround a little
   temp_column=(((HORIZ_VIEW_RANGE>>1)-tempdiv)+(render_view_angle));
  
   if (temp_column<0) {
      cur_wall_run->column=SKY_WIDTH-((-temp_column) % SKY_WIDTH);
   } else {
      cur_wall_run->column=temp_column % SKY_WIDTH;
   } /* endif */

}

/*
   Close_Textures
   Finishes up whatever textures were running in a given visible section
   Notes: Uses proj_right and the "prev" globals
*/

inline void Close_Textures(short closing_ray)
{

long floor_height_diff=render_z-Cur_Sec->floor_height;
long ceil_height_diff=Cur_Sec->ceil_height-render_z;

floor_ray=closing_ray;

floor_texture=Get_Floor_Texture(Cur_Sec->ceil_tex);
floor_start=prev_win_top; floor_end=prev_wall_top;

if ( ceil_height_diff>0 && floor_texture!=cur_sky_texture ) {
   Finish_Tex();
} /* endif */

floor_texture=Get_Floor_Texture(Cur_Sec->floor_tex);
floor_start=prev_wall_bottom; floor_end=prev_win_bottom;

if ( floor_height_diff>0 && floor_texture!=cur_sky_texture ) {
   Finish_Tex();
} /* endif */

}

/*
   SegVisible
   Decides if a seg is (a) visible and (b) facing you
*/

inline BOOL SegVisible(seg * cur_seg)
{
long x1, x2, y1, y2;
pvector2 v1, v2;
v1=Vector_List+cur_seg->v[0];
v2=Vector_List+cur_seg->v[1];
x1=v1->x;
x2=v2->x;
y1=v1->y;
y2=v2->y;
if ( fixedmult((x1-x2),(render_y-(y2<<SHIFT))) >= fixedmult((y1-y2),(render_x-(x2<<SHIFT))) ) {
   return TRUE;
} else {
   return FALSE;
} /* endif */
}

/////////////////////////////////////////////////////////////////////////////

/*
   Ray_Caster
   The all powerful function that renders the screen
   Notes: Well, it isn't really all powerful. After all, it's just a routine,
   not some sort of diety. It dosen't even do that much, just calls other routines
*/

void Ray_Caster(long x, long y, long z, long view_angle)
{

ssetup_count=0;

// setup rendering constants
render_x=x; render_y=y; render_z=z; render_view_angle=view_angle;

// setup constants for floor drawing

Init_Floor_Values();

// save the current frame of the sky animation 
// (we will say that sky texture cannot change while rendering)

cur_sky_texture=sky_texture->images[sky_texture->cur_image];

// Initialize the clipping structures

Win_Bounds_Setup();
VB_InitList();

// Set starting wall & floor run count to 0

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -