fixs et raycast

This commit is contained in:
attilavs2 2024-10-22 12:27:16 +02:00
parent 82ab21aed4
commit fab0cfb277
12 changed files with 205 additions and 39 deletions

View file

@ -21,6 +21,7 @@ set(SOURCES
#sources du moteur #sources du moteur
eng/moteur.c eng/moteur.c
eng/map.c eng/map.c
eng/utils.c
eng/sprites.c eng/sprites.c
eng/game.c eng/game.c
) )
@ -35,7 +36,7 @@ fxconv_declare_assets(${ASSETS} WITH_METADATA)
add_executable(Copy3DEngine ${SOURCES} ${ASSETS}) add_executable(Copy3DEngine ${SOURCES} ${ASSETS})
target_compile_options(Copy3DEngine PRIVATE -Wall -Wextra -Ofast) target_compile_options(Copy3DEngine PRIVATE -Wall -Wextra -Ofast)
target_include_directories(Copy3DEngine PRIVATE "include/C3D/") target_include_directories(Copy3DEngine PRIVATE "include/")
target_compile_definitions(Copy3DEngine PRIVATE NAMEOFGAME="${NAMEOFGAME}" AUTHOR="${AUTHOR}") target_compile_definitions(Copy3DEngine PRIVATE NAMEOFGAME="${NAMEOFGAME}" AUTHOR="${AUTHOR}")
target_link_libraries(Copy3DEngine Gint::Gint) target_link_libraries(Copy3DEngine Gint::Gint)
target_link_libraries(Copy3DEngine LibProf::LibProf) target_link_libraries(Copy3DEngine LibProf::LibProf)

View file

@ -5,12 +5,13 @@
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include "fixed.h" #include "C3D/fixed.h"
#include "map.h" #include "C3D/map.h"
#include "game.h" #include "C3D/game.h"
#include "utils.h" #include "C3D/utils.h"
#include "moteur.h" #include "C3D/moteur.h"
#include "sprites.h" #include "C3D/sprites.h"
#include "C3D/config.h"
int lhook_c = 0; int lhook_c = 0;
RcLogicFunc *logic_hooks[HINDEX_S]; RcLogicFunc *logic_hooks[HINDEX_S];
@ -46,3 +47,4 @@ void do_logic(RcGame *game, int delta){
} }
} }
} }

View file

@ -2,8 +2,8 @@
#include <stdint.h> #include <stdint.h>
#include "map.h" #include "C3D/map.h"
#include "moteur.h" #include "C3D/moteur.h"
uint8_t __attribute__((section(".rodata"))) map_test[map_w][map_h] = { uint8_t __attribute__((section(".rodata"))) map_test[map_w][map_h] = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3},

View file

@ -12,12 +12,11 @@
#include <gint/gray.h> #include <gint/gray.h>
#include <libprof.h> #include <libprof.h>
#include "fixed.h" #include "C3D/fixed.h"
#include "C3D/moteur.h"
#include "moteur.h" #include "C3D/map.h"
#include "map.h" #include "C3D/game.h"
#include "game.h" #include "C3D/config.h"
#include "config.h"
// moteur.c : // moteur.c :
// ici se trouvent tout ce qui concerne les graphismes, mouvement et collisions // ici se trouvent tout ce qui concerne les graphismes, mouvement et collisions
@ -28,8 +27,8 @@ fixed_t zbuf[viewport_w];
void move(RcGame *game) { void move(RcGame *game) {
extern int frame_time; extern int frame_time;
fixed_t moveSpeed = fmul(fix(frame_time), 0x148); //frame_time * fix(carrés/seconde/1000) là carrés/seconde = 5 fixed_t moveSpeed = fmul(fix(frame_time)/1000, 0x148); //frame_time * fix(carrés/seconde/1000) là carrés/seconde = 5
fixed_t rotSpeed = fmul(fix(frame_time), 0x83); //frame_time * fix(radians/seconde/1000) là radians/seconde = 2 fixed_t rotSpeed = fmul(fix(frame_time)/1000, 0x83); //frame_time * fix(radians/seconde/1000) là radians/seconde = 2
fixed_t c_rotSpeed = fix(cos(f2float(rotSpeed))); fixed_t c_rotSpeed = fix(cos(f2float(rotSpeed)));
fixed_t s_rotSpeed = fix(sin(f2float(rotSpeed))); fixed_t s_rotSpeed = fix(sin(f2float(rotSpeed)));

View file

@ -2,15 +2,17 @@
#include <gint/display.h> #include <gint/display.h>
#include <gint/keyboard.h> #include <gint/keyboard.h>
#include <gint/gray.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "fixed.h" #include "C3D/fixed.h"
#include "game.h" #include "C3D/game.h"
#include "sprites.h" #include "C3D/sprites.h"
#include "moteur.h" #include "C3D/moteur.h"
#include "config.h" #include "C3D/map.h"
#include "utils.h" #include "C3D/config.h"
#include "C3D/utils.h"
extern fixed_t zbuf[viewport_w]; extern fixed_t zbuf[viewport_w];
@ -32,7 +34,7 @@ void remove_sprite(GUNUSED Sprite *sprite){
//TODO //TODO
} }
//Lodev's sprite projection, translated //Lodev's sprite projection, translated to use my functions and fixed point
void project_sprite(bopti_image_t *tex_index[], Sprite *sprite, RcActor *player){ void project_sprite(bopti_image_t *tex_index[], Sprite *sprite, RcActor *player){
@ -59,8 +61,6 @@ void project_sprite(bopti_image_t *tex_index[], Sprite *sprite, RcActor *player)
sprite_pos_y = 0; sprite_pos_y = 0;
int sprite_pos_x = -sprite_h / 2 + screen_x; int sprite_pos_x = -sprite_h / 2 + screen_x;
if(sprite_pos_x < 0)
sprite_pos_x = 0;
int sprite_end_x = sprite_h / 2 + screen_x; int sprite_end_x = sprite_h / 2 + screen_x;
if(sprite_end_x > viewport_w) if(sprite_end_x > viewport_w)
sprite_end_x = viewport_w; sprite_end_x = viewport_w;
@ -81,10 +81,10 @@ void project_sprite(bopti_image_t *tex_index[], Sprite *sprite, RcActor *player)
continue; continue;
if(x > viewport_w) if(x > viewport_w)
break; break;
int tex_x = ffloor((x-sprite_pos_x) * fdiv(fix(TSIZE), fix(sprite_w))); int tex_x = ffloor(fixabs(x-sprite_pos_x) * fdiv(fix(TSIZE), fix(sprite_w)));
tex_x %= TSIZE; tex_x %= TSIZE;
draw_stripe(tex_index[4], 0, sprite_pos_y, sprite_size, tex_x, x); draw_stripe(tex_index[sprite->tex], 0, sprite_pos_y, sprite_size, tex_x, x);
} }
} }
@ -120,3 +120,138 @@ void draw_sprites(bopti_image_t *tex_index[], RcActor *player){
project_sprite(tex_index, spr, player); project_sprite(tex_index, spr, player);
} }
} }
//Returns distance (-1 if no hit), hit is set to the hit sprite
//or NULL if no hit (can be passed NULL)
fixed_t raycast(RcGame *game, RcActor *origin, Sprite **hit){
fixed_t posX = origin->pos.x;
fixed_t posY = origin->pos.y;
fixed_t dirX = origin->dir.x;
fixed_t dirY = origin->dir.y;
fixed_t planeX = origin->plane.x;
fixed_t planeY = origin->plane.y;
uint8_t *map_test = game->current_map->dat;
fixed_t cameraX;
fixed_t rayDirX;
fixed_t rayDirY;
fixed_t sideDistX;//length of ray from current position to next x or y-side
fixed_t sideDistY;
fixed_t deltaDistX;
fixed_t deltaDistY;
fixed_t perpWallDist;
int x = viewport_w/2;
int mapX;
int mapY;
int stepX; //what direction to step in x or y-direction (either +1 or -1)
int stepY;
int side = 0; //was a NS or a EW wall hit?
//int v_offset = 0;
fixed_t h_offset = 0;
//calculate ray position and direction
cameraX = fdiv(fix(x*2), fix(viewport_w)) - 0xFFFF + h_offset; //x-coordinate in camera space
rayDirX = dirX + fmul(planeX, cameraX);
rayDirY = dirY + fmul(planeY, cameraX);
//which box of the map we're in
mapX = ffloor(posX);
mapY = ffloor(posY);
// length of ray from one x or y-side to next x or y-side
// these are derived as:
// deltaDistX = sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX))
// deltaDistY = sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY))
// which can be simplified to abs(|rayDir| / rayDirX) and abs(|rayDir| / rayDirY)
// where |rayDir| is the length of the vector (rayDirX, rayDirY). Its length,
// unlike (dirX, dirY) is not 1, however this does not matter, only the
// ratio between deltaDistX and deltaDistY matters, due to the way the DDA
// stepping further below works. So the values can be computed as below.
// Division through zero is prevented, even though technically that's not
// needed in C++ with IEEE 754 floating point values.
//Fcalva : It is with fp32s !
rayDirX = rayDirX == 0 ? 1 : rayDirX;
rayDirY = rayDirY == 0 ? 1 : rayDirY;
deltaDistX = abs(fdiv(0xFFFF, rayDirX));
deltaDistY = abs(fdiv(0xFFFF, rayDirY));
if(deltaDistX > max_dist) deltaDistX = max_dist;
if(deltaDistY > max_dist) deltaDistY = max_dist;
//calculate step and initial sideDist
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 = 0;
sideDistY = 0;
}
else if (rayDirY < 0) {
stepY = -1;
sideDistY = fmul(posY - fix(mapY), deltaDistY);
}
else {
stepY = 1;
sideDistY = fmul( fix(mapY + 1) - posY, deltaDistY);
}
int coll = 0;
//perform DDA
while(true) {
//Check if the ray is out of range/bounds
if (sideDistX >= max_dist || sideDistY >= max_dist || mapX < 0 || mapY < 0 || mapY >= map_w || mapX >= map_h) {
coll = 0;
break;
}
//Otherwise check if ray has hit a wall
if (map_test[mapX*map_w+mapY] > 0) {
coll = 0;
break;
}
for(int i = 0; i < spritec; i++){
Sprite *act = sprite_index[i];
if(ffloor(act->pos.x) == mapX && ffloor(act->pos.y) == mapY){
if(hit) *hit = act;
coll = 1;
goto outerbreak;
}
}
//jump to next map square, either in x-direction, or in y-direction
if (sideDistX < sideDistY) {
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else {
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
continue;
outerbreak: break;
}
//Calculate distance projected on camera direction. This is the shortest distance from the point where the wall is
//hit to the camera plane. Euclidean to center camera point would give fisheye effect!
//This can be computed as (mapX - posX + (1 - stepX) / 2) / rayDirX for side == 0, or same formula with Y
//for size == 1, but can be simplified to the code below thanks to how sideDist and deltaDist are computed:
//because they were left scaled to |rayDir|. sideDist is the entire length of the ray above after the multiple
//steps, but we subtract deltaDist once because one step more into the wall was taken above.
if(coll){
if (side == 0)
perpWallDist = (sideDistX - deltaDistX);
else
perpWallDist = (sideDistY - deltaDistY);
}
else {
perpWallDist = -1;
}
return perpWallDist;
}

4
eng/utils.c Normal file
View file

@ -0,0 +1,4 @@
#include <stdint.h>
#include "C3D/fixed.h"
#include "C3D/game.h"

View file

@ -26,7 +26,8 @@
#define SINDEX_S 64 #define SINDEX_S 64
//Game logic hooks //Game logic hooks
#define HINDEX_S 16 #define HINDEX_S 16
//Game entities
#define EINDEX_S 32
//===== Paramètres de debug ===== //===== Paramètres de debug =====

View file

@ -89,7 +89,7 @@ static inline fixed_t fease(fixed_t x)
} }
static inline fixed_t fixabs(fixed_t x){ static inline fixed_t fixabs(fixed_t x){
return x & 0x7FFFFFFF; return x > 0 ? x:-x;
} }
static inline fixed_t fV2d_dotp(V2d u, V2d v){ static inline fixed_t fV2d_dotp(V2d u, V2d v){

View file

@ -7,6 +7,7 @@
typedef struct { typedef struct {
V2d pos; V2d pos;
Rect coll;
int tex; int tex;
} Sprite; } Sprite;
@ -21,9 +22,13 @@ typedef struct {
} RcMap; } RcMap;
//Extension of Sprite, keep all first items common
typedef struct { typedef struct {
V2d pos; V2d pos;
Rect coll;
int tex;
V2d dir; V2d dir;
V2d plane; V2d plane;

View file

@ -17,3 +17,6 @@ void clear_sprites();
void draw_sprites(bopti_image_t *tex_index[], RcActor *player); void draw_sprites(bopti_image_t *tex_index[], RcActor *player);
//Returns distance (-1 if no hit), hit is set to the hit sprite
//or NULL if no hit (can be passed NULL)
fixed_t raycast(RcGame *game, RcActor *origin, Sprite **hit);

View file

@ -4,6 +4,18 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "fixed.h"
#define min(x, xmin) (x > xmin ? xmin:x) #define min(x, xmin) (x > xmin ? xmin:x)
typedef struct {
int x0,x1;
int y0,y1;
} Rect;
static bool rect_rect_coll(Rect *a, Rect *b){
bool r = a->x0 >= b->x0 && a->x1 <= b->x1;
r = r && a->y0 >= b->y0;
}

View file

@ -11,13 +11,13 @@
#include <gint/gdb.h> #include <gint/gdb.h>
#include <libprof.h> #include <libprof.h>
#include "fixed.h" #include "C3D/fixed.h"
#include "game.h" #include "C3D/game.h"
#include "sprites.h" #include "C3D/sprites.h"
#include "moteur.h" #include "C3D/moteur.h"
#include "map.h" #include "C3D/map.h"
#include "config.h" #include "C3D/config.h"
//====== Copy3DEngine ===== //====== Copy3DEngine =====
// Git du moteur : https://git.planet-casio.com/Fcalva/Copy3DEngine // Git du moteur : https://git.planet-casio.com/Fcalva/Copy3DEngine
@ -79,6 +79,10 @@ void keys_get(){
frame_time_timer--; frame_time_timer--;
if (keydown(KEY_EXIT)) game.flags.exit = 1; if (keydown(KEY_EXIT)) game.flags.exit = 1;
if(keydown(KEY_F2)){
dprint(0,0,3,"%d",raycast(&game, &game.player, NULL));
}
#ifdef debug #ifdef debug
//if (keydown(KEY_TAN)) end_screen(); //if (keydown(KEY_TAN)) end_screen();
#endif #endif
@ -154,7 +158,7 @@ int main(){
keys_get(); keys_get();
do_logic(&game, frame_time*1000); do_logic(&game, frame_time);
draw_walls( draw_walls(
#if debug #if debug
@ -165,7 +169,7 @@ int main(){
draw_sprites(tex_index, &game.player); draw_sprites(tex_index, &game.player);
if (disp_frame_time == 1) dprint( 0, 0, C_BLACK, "%d ms", frame_time); if (disp_frame_time == 1) dprint( 0, 0, C_BLACK, "%d ms", frame_time/1000);
#if debug #if debug
dprint( 1, 27, C_BLACK, "pX %d", game.player.pos.x); dprint( 1, 27, C_BLACK, "pX %d", game.player.pos.x);
@ -178,7 +182,7 @@ int main(){
dupdate(); dupdate();
prof_leave(frame); prof_leave(frame);
frame_time = (int)prof_time(frame)/1000; frame_time = (int)prof_time(frame);
first_frame = 0; first_frame = 0;
} }