?? raycast.cpp
字號:
/*********************
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 + -