Rafraichissement raycast(), commentaires et ffloor en macro

This commit is contained in:
attilavs2 2024-01-06 18:54:57 +01:00
parent 8b825add63
commit d69a379121
7 changed files with 85 additions and 153 deletions

Binary file not shown.

View File

@ -10,6 +10,9 @@
typedef int32_t fixed_t;
/* Standard arithmetic. */
//GCC complained when in inline functions
#define ffloor(f) ((f) >> 16)
static inline fixed_t fmul(fixed_t left, fixed_t right)
{
/* Generally optimized by the compiler to use dmuls.l and xtrct */
@ -41,11 +44,6 @@ static inline fixed_t fdec(fixed_t f)
return f & 0xffff;
}
static inline int ffloor(fixed_t f)
{
return f >> 16;
}
static inline int fceil(fixed_t f)
{
return (f + 0xffff) >> 16;

View File

@ -103,14 +103,14 @@ void rc_pollevent(){
SDL_PumpEvents();
}
//All the following is to redo
uint8_t rc_keydown(enum keys key){
return 1;
}
//To reimplement
uint8_t rc_getkey(enum keys key) {
dupdate();

View File

@ -150,7 +150,7 @@ void move(Game *game, uint32_t keys) {
if (player->dir.x < -0xFFFF) player->dir.x = -0xFFFF;
if (player->dir.y < -0xFFFF) player->dir.y = -0xFFFF;
}
/*
void draw_background(int back_id){ //a refaire
}
@ -161,7 +161,7 @@ void logic(){
void draw_f(image_t *vram){ //a refaire
}
}*/
inline void dstripe(image_t *stripe, image_t *vram, int x, int linePos, int lineHeight, int ymin, int ymax){
uint16_t *strpdat = stripe->data;
@ -177,24 +177,26 @@ inline void dstripe(image_t *stripe, image_t *vram, int x, int linePos, int line
if(ymax-ymin < lineHeight){
texSample = ffloor((ymax-ymin) * texScale);
texSampleY = ffloor((linePos - ymin) * texScale);
texSampleY = ffloor((linePos - ymin) * texScale) < 0 ? 0:ffloor((linePos - ymin) * texScale);
}
if(keydown(KEY_F5)){
dclear(C_WHITE);
dprint(1,1,C_BLACK, "x : %d linePos : %d texSampleY : %d", x, linePos, texSampleY);
dupdate(); getkey();
}
dclear(C_WHITE);
dprint(1,1,C_BLACK, "x : %d linePos : %d lineHeight : %d ymin : %d ymax : %d", x, linePos, lineHeight, ymin, ymax);
dupdate(); getkey();
if(lineHeight < tsize){
cpixel = fix(texSampleY);
for(cy = ymin; cy < ymax && cpixel < texSampleY+texSample; cy++){
if(cy < 0 || cy >= viewport_h) break;
//vramdat[screen_w*cy + x] = strpdat[ffloor(cpixel*2)];
//vramdat[screen_w*cy + x+1] = strpdat[ffloor(cpixel*2)+1];
vramdat[screen_w*cy + x] = strpdat[ffloor(cpixel*2)];
vramdat[screen_w*cy + x+1] = strpdat[ffloor(cpixel*2)+1];
cpixel += texScale;
}
} else {
//This part doesn't seem to work
for(cpixel = texSampleY; cpixel < texSampleY+texSample && cy < ymax; cpixel++){
for(i = 0; i < ffloor(texScale); i++){
//vramdat[screen_w*cy + x] = strpdat[ffloor(cpixel*2)];
vramdat[screen_w*cy + x] = strpdat[ffloor(cpixel*2)];
vramdat[screen_w*cy + x+1] = strpdat[ffloor(cpixel*2)+1];
cy++;
}
@ -381,14 +383,14 @@ void draw_walls(Game *game, image_t *vram){
if(ymin >= ymax) continue;
gint_dvline(ymin, ymax, x, perpWallDist >> 16);
//gint_dvline(ymin, ymax, x, perpWallDist >> 16);
//gint_dvline(ymin, ymax, x+1, perpWallDist>>16);
//image_t tex_stripe;
image_t tex_stripe;
//image_sub(tex_index[tex], texX, 0, 2, tsize, &tex_stripe);
image_sub(tex_index[tex], texX, 0, 2, tsize, &tex_stripe);
//dstripe(&tex_stripe, vram, x, linePos, lineHeight, ymin, ymax);
dstripe(&tex_stripe, vram, x, linePos, lineHeight, ymin, ymax);
//prof_leave(img_drw);
//prof_enter(rayscat);

View File

@ -5,15 +5,6 @@
#ifndef moteur_h
#define moteur_h
static inline uint8_t has_collision(uint8_t tile){
switch(tile){
case 0: return 0;
case 254: return 0;
case 255: return 0;
default: return 1;
}
}
void draw_background(int back_id);
void logic();
void draw_f(image_t *vram);

View File

@ -129,141 +129,73 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Function using the same raycast logic returning distance (and without the same comments)
// Returns -1 if it didn't hit anything, -2 if incorrect type input
// Type 0 = Mobs & Walls; Type 1 = Mobs; Type 2 = Walls
// A refactoriser
inline int sml_v3d(Vector3d *a){
if(a->x < a->y){
if(a->x < a->z) return 0;
//if x<y && z<x then z<x<y
return 2;
}
if(a->y < a->z){
return 1;
}
//if y<x && z<y then z<y<x
return 2;
}
fixed_t raycast(ShooterMap *ShooterLevel, fixed_t posX, fixed_t posY, fixed_t rayDirX, fixed_t rayDirY, fixed_t dist, char type){
// 3D raycast function based on Permadi's'
// Returns -1 if it didn't hit anything within dist, else distance to hit
fixed_t sideDistX;
fixed_t sideDistY;
fixed_t deltaDistX;
fixed_t deltaDistY;
fixed_t wallDist;
fixed_t raycast(ShooterMap *ShooterLevel, Vector3d pos, Vector3d rayDir, fixed_t dist){
char side;
int mapX;
int mapY;
int stepX;
int stepY;
Vector3d sideDist;
Vector3d deltaDist;
Vector3d map;
Vector3d step;
int hit = 0;
int *sideDistp = (int*)&sideDist;
int *deltaDistp = (int*)&deltaDist;
int *rayDirp = (int*)&deltaDist;
int *mapp = (int*)&map;
int *stepp = (int*)&step;
int *posp = (int*)&pos;
int side;
mapX = f2int(posX);
mapY = f2int(posY);
map.x = f2int(pos.x);
map.y = f2int(pos.y);
map.z = f2int(pos.z);
deltaDistX = abs(fdiv(0xFFFF, rayDirX));
deltaDistY = abs(fdiv(0xFFFF, rayDirY));
deltaDist.x = abs(fdiv(0xFFFF, rayDir.x));
deltaDist.y = abs(fdiv(0xFFFF, rayDir.y));
deltaDist.z = abs(fdiv(0xFFFF, rayDir.z));
if (rayDirX <= 0) {
stepX = -1;
sideDistX = fmul(posX - fix(mapX), deltaDistX);
}
else {
stepX = 1;
sideDistX = fmul( fix(mapX + 1) - posX, deltaDistX);
}
if (rayDirY <= 0) {
stepY = -1;
sideDistY = fmul(posY - fix(mapY), deltaDistY);
}
else {
stepY = 1;
sideDistY = fmul( fix(mapY + 1) - posY, deltaDistY);
for(int i = 0; i < 3; i++){
if(rayDirp[i] < 0){
stepp[i] = -1;
sideDistp[i] = fmul(posp[i] - fix(mapp[i]), deltaDistp[i]);
} else {
stepp[i] = 1;
sideDistp[i] = fmul(fix(mapp[i] + 1) - posp[i], deltaDistp[i]);
}
}
//perform DDA
switch(type){
//Walls and mobs raycast
case 0 : {
while(1) {
//Check if the ray is out of range/bounds
if (sideDistX >= dist || sideDistY >= dist || mapX < 0 || mapY < 0) {
hit = 0;
break;
}
//Otherwise check if ray has hit a wall/mob
else if (ShooterLevel->wall[mapX][mapY] != 0 || 0 != 0) {
hit = 1;
break;
}
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
}
while(1) {
//Check if the ray is out of range/bounds
if (sideDist.x > dist || sideDist.y > dist || sideDist.z > dist|| map.x < 0 || map.y < 0 || map.z < 0) {
hit = 0;
break;
}
//Mobs only
case 1 : {
while(1) {
//Check if the ray is out of range/bounds
if (sideDistX >= dist || sideDistY >= dist || mapX < 0 || mapY < 0) {
hit = 0;
break;
}
//Otherwise check if ray has hit a wall
else if (ShooterLevel->wall[mapX][mapY] != 0) {
hit = 1;
break;
}
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
}
break;
}
//Walls only
case 2 : {
while(1) {
//Check if the ray is out of range/bounds
if (sideDistX >= dist || sideDistY >= dist || mapX < 0 || mapY < 0) {
hit = 0;
break;
}
//Otherwise check if ray has hit a mob
else if (0 != 0) {
hit = 1;
break;
}
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
}
break;
}
default : {
return -2;
//Otherwise check if ray has hit a wall
else if (has_collision(ShooterLevel->wall[map.z][map.x][map.y])) {
hit = 1;
break;
}
side = sml_v3d(&sideDist);
sideDistp[side] += deltaDistp[side];
mapp[side] += stepp[side];
}
if (hit == 0) wallDist = -1;
else if (side == 0) wallDist = (sideDistX - deltaDistX);
else wallDist = (sideDistY - deltaDistY);
return wallDist;
if (hit == 0) return -1;
return sideDistp[side] - deltaDistp[side];
}

View File

@ -8,6 +8,15 @@
#define sq(x) (x*x)
#define fsq(x) (fmul(x,x))
static inline uint8_t has_collision(uint8_t tile){
switch(tile){
case 0: return 0;
case 254: return 0;
case 255: return 0;
default: return 1;
}
}
//Provient de
//https://stackoverflow.com/questions/31117497/fastest-integer-square-root-in-the-least-amount-of-instructions
//, njuffa
@ -93,7 +102,7 @@ static inline Vector2d fix2DNorml(Vector2d a) {
int cmpfunc(const void *, const void *);
fixed_t raycast(ShooterMap*, fixed_t, fixed_t, fixed_t, fixed_t, fixed_t, char);
fixed_t raycast(ShooterMap *ShooterLevel, Vector3d pos, Vector3d rayDir, fixed_t dist);
#ifdef FXCG50