diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-04-15 18:27:29 +0300 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-04-15 18:27:29 +0300 |
commit | cf631e23e1d0e29edac2e13446bdd42235c111fc (patch) | |
tree | 141f85599c7bd47b3fcb0a3088a5ce117d6e18fd | |
parent | 02ec17653ee5399eac67871dfd5fb193bb9dce2f (diff) |
collision and depth shading
-rwxr-xr-x | build.sh | 4 | ||||
-rw-r--r-- | src/common.h | 6 | ||||
-rw-r--r-- | src/main.c | 42 | ||||
-rw-r--r-- | src/player.c | 15 | ||||
-rw-r--r-- | src/player.h | 4 | ||||
-rw-r--r-- | src/sector.c | 71 | ||||
-rw-r--r-- | src/sector.h | 4 | ||||
-rw-r--r-- | src/shell.html | 3 |
8 files changed, 108 insertions, 41 deletions
@@ -63,7 +63,9 @@ if { [[ $WEB -eq 0 ]]; } 2> /dev/null; then $VALGRND $BIN/$NAME fi else - emcc -o $BIN/portal-engine.html $SRC/*.c \ + mkdir -p $BIN/web + + emcc -o $BIN/web/portal-engine.html $SRC/*.c \ $PROD_FLAGS $LIB_FLAGS \ -s USE_SDL=2 -s ASYNCIFY \ --shell-file $SRC/shell.html \ diff --git a/src/common.h b/src/common.h index 4d0df29..faaecb6 100644 --- a/src/common.h +++ b/src/common.h @@ -36,8 +36,14 @@ struct xyz { #define COLOR_GREEN 0x00FF00 #define COLOR_BLUE 0x0000FF #define COLOR_LIGHTWHITE 0xF5F5F5 + #define color(col) (((col)>>16) & 0xFF), (((col)>>8) & 0xFF), ((col) & 0xFF) +#define scale_color(col, z) \ + (((((col >> 16) & 0xFF) - clamp(z, 0, 255)) << 16) | \ + ((((col >> 8) & 0xFF) - clamp(z, 0, 255)) << 8) | \ + ((col & 0xFF) - clamp(z, 0, 255))) + // macro wrapper for the sdl logging system #include <SDL2/SDL.h> #define LOG_APPLICATION SDL_LOG_CATEGORY_APPLICATION @@ -11,6 +11,8 @@ SDL_Surface *surface = NULL; #define CLEAR_SCREEN(c) for(int i = 0; i < SW-1; i++) vline(i, 0, SH-1, c); +void print_message(void); + void vline(int x, int y1, int y2, uint32_t col) { y1 = clamp(y1, 0, SH-1); @@ -31,6 +33,8 @@ int main(void) SDL_LogSetAllPriority(SDL_LOG_PRIORITY_ERROR); #endif + print_message(); + // ----------------- START SDL ----------------- // int ret = 1; SDL_Window *window = NULL; @@ -61,19 +65,22 @@ int main(void) if(map_load(&map, "files/map_clear.txt")) return 1; + bool keys[6] = {0}; bool quit = false; - bool wasd[4] = {0}; while(!quit) { SDL_Event event; while(SDL_PollEvent(&event)) { // ----------------- EVENTS ----------------- // - #define KEY_SWITCH(b) \ - switch(event.key.keysym.sym) { \ - case 'w': wasd[0] = b; break; \ - case 'a': wasd[1] = b; break; \ - case 's': wasd[2] = b; break; \ - case 'd': wasd[3] = b; break; } + #define KEY_SWITCH(b) \ + switch(event.key.keysym.sym) { \ + case 'w': keys[0] = b; break; \ + case 'a': keys[1] = b; break; \ + case 's': keys[2] = b; break; \ + case 'd': keys[3] = b; break; \ + case ' ': keys[4] = b; break; \ + case SDLK_LSHIFT: \ + case SDLK_RSHIFT: keys[5] = b; break; } switch(event.type) { case SDL_QUIT: @@ -85,9 +92,7 @@ int main(void) case SDL_KEYUP: KEY_SWITCH(false); break; - default: - // log_debug(LOG_APPLICATION, "event: %d", event.type); - break; + default: break; } // ------------------------------------------ // } @@ -96,9 +101,8 @@ int main(void) int x,y; SDL_GetRelativeMouseState(&x,&y); - player_input(&map.player, wasd, x, y); - map_player_sector(&map); - // map_detect_collision(&map); + player_input(&map.player, keys, x, y); + map_detect_collision(&map); player_update(&map.player); CLEAR_SCREEN(COLOR_LIGHTWHITE); @@ -117,3 +121,15 @@ exit: SDL_Quit(); return ret; } + +void print_message(void) +{ + puts("--------------- Instructions ---------------"); + puts("Use WASD to move"); + puts("Use the mouse to look"); + puts("Use SPACE to jump"); + puts("Use SHIFT to duck"); + puts(""); + puts("There is collision, but it is very buggy"); + puts("--------------------------------------------"); +} diff --git a/src/player.c b/src/player.c index 2231b9e..6ea618b 100644 --- a/src/player.c +++ b/src/player.c @@ -3,7 +3,9 @@ #define DEFAULT_STAND_HEIGHT 6.0f #define DEFAULT_DUCK_HEIGHT 2.5f + #define DEFAULT_HEAD_MARGIN 1.0f +#define DEFAULT_KNEE_HEIGHT 2.0f void player_default(player_t *player) { @@ -17,8 +19,7 @@ void player_default(player_t *player) player->duck_height = DEFAULT_DUCK_HEIGHT; player->head_margin = DEFAULT_HEAD_MARGIN; - player->ground = false; player->falling = true; - player->moving = false; player->ducking = false; + player->ducking = false; } void player_input(player_t *player, bool *input, int rmouse_x, int rmouse_y) { @@ -30,8 +31,12 @@ void player_input(player_t *player, bool *input, int rmouse_x, int rmouse_y) if(input[2]) { move_vec[0] -= player->anglecos*0.2f; move_vec[1] -= player->anglesin*0.2f; } if(input[1]) { move_vec[0] += player->anglesin*0.2f; move_vec[1] -= player->anglecos*0.2f; } if(input[3]) { move_vec[0] -= player->anglesin*0.2f; move_vec[1] += player->anglecos*0.2f; } - player->moving = input[0] || input[1] || input[2] || input[3]; - float acceleration = player->moving ? 0.4f : 0.2f; + if(input[4]) { if(player->velocity.z == 0.0f) player->velocity.z += 0.5f; } + + player->ducking = input[5]; + + bool pressing = input[0] || input[1] || input[2] || input[3] || input[4]; + float acceleration = pressing ? 0.4f : 0.2f; player->velocity.x = player->velocity.x * (1-acceleration) + move_vec[0] * acceleration; player->velocity.y = player->velocity.y * (1-acceleration) + move_vec[1] * acceleration; @@ -44,5 +49,5 @@ void player_update(player_t *player) { player->pos.x += player->velocity.x; player->pos.y += player->velocity.y; - player->pos.z = player->stand_height; // temp + player->pos.z += player->velocity.z; } diff --git a/src/player.h b/src/player.h index c627bcf..3e957e9 100644 --- a/src/player.h +++ b/src/player.h @@ -8,8 +8,8 @@ typedef struct player { struct xyz pos, velocity; // vectors for the player float angle, anglesin, anglecos; // angle, and its sine and cosine size_t sector; // the sector that the player is in - float stand_height, duck_height, head_margin; // eyeheights; minimum margin between current height and celling - bool ground, falling, moving, ducking; + float stand_height, duck_height, head_margin, knee_height; // eyeheights; minimum margin between current height and celling; maximum height objects the player can walk over + bool moving, ducking; } player_t; void player_default(player_t *player); diff --git a/src/sector.c b/src/sector.c index c315382..f43ab86 100644 --- a/src/sector.c +++ b/src/sector.c @@ -14,6 +14,7 @@ void vline(int x, int y1, int y2, uint32_t col); +// !! drawing is dogshit !! int map_draw(map_t *map, int SW, int SH) { int sect_rendered[map->nsects]; @@ -85,7 +86,7 @@ int map_draw(map_t *map, int SW, int SH) int beginx = max(x1, now.sx1), endx = min(x2, now.sx2); for(int x = beginx; x <= endx; ++x) { - // int z = ((x - x1) * (tz2-tz1) / (x2-x1) + tz1) * 8; + int z = ((x - x1) * (tz2-tz1) / (x2-x1) + tz1) * 8; /* Acquire the Y coordinates for our ceiling & floor for this X coordinate. Clamp them. */ int ya = (x - x1) * (y2a-y1a) / (x2-x1) + y1a, cya = clamp(ya, ytop[x],ybottom[x]); // top int yb = (x - x1) * (y2b-y1b) / (x2-x1) + y1b, cyb = clamp(yb, ytop[x],ybottom[x]); // bottom @@ -94,26 +95,27 @@ int map_draw(map_t *map, int SW, int SH) // after (over) the walls int old_ytop = ytop[x], old_ybottom = ybottom[x]; - // TODO: add depth shading + // depth-shaded white color + uint wall_col = scale_color(COLOR_WHITE, (2*z/3)); + if(neighbor == (size_t)-1) { // no neighbor - // vline(x, cya, cyb, x==x1||x==x2 ? : ); - vline(x, cya, cyb, COLOR_WHITE); + vline(x, cya, cyb, wall_col); } else { // yes neighbor int nyb = (x - x1) * (ny2b-ny1b) / (x2-x1) + ny1b, cnyb = clamp(nyb, ytop[x],ybottom[x]); int nya = (x - x1) * (ny2a-ny1a) / (x2-x1) + ny1a, cnya = clamp(nya, ytop[x],ybottom[x]); - vline(x, cya, cnya-1, COLOR_WHITE); // upper wall + vline(x, cya, cnya-1, wall_col); // upper wall // vline(x, cnya, cnyb, COLOR_RED); // portal - vline(x, cnyb+1, cyb, COLOR_WHITE); // lower wall + vline(x, cnyb+1, cyb, wall_col); // lower wall ytop[x] = clamp(max(cya, cnya), ytop[x], SH-1); // Shrink the remaining window below these ceilings ybottom[x] = clamp(min(cyb, cnyb), 0, ybottom[x]); // Shrink the remaining window above these floors } /* Render ceiling: everything above this sector's ceiling height. */ - vline(x, old_ytop, cya-1, COLOR_GREEN); + vline(x, old_ytop, cya-1, scale_color(COLOR_GREEN, 0)); /* Render floor: everything below this sector's floor height. */ - vline(x, cyb+1, old_ybottom, COLOR_BLUE); + vline(x, cyb+1, old_ybottom, scale_color(COLOR_BLUE, 0)); } if((neighbor != (size_t)-1) && (endx >= beginx) && ((tail+1)%MAX_QUEUE != head)) { @@ -128,28 +130,65 @@ int map_draw(map_t *map, int SW, int SH) return 0; } -void map_player_sector(map_t *map) +// !! collision is dogshit !! +void map_detect_collision(map_t *map) { - struct sector *sect = &map->sectors[map->player.sector]; - float px = map->player.pos.x, py = map->player.pos.y; - float dx = map->player.velocity.x, dy = map->player.velocity.y; + player_t *player = &map->player; + struct sector *sect = &map->sectors[player->sector]; + float eyeheight = player->ducking ? player->duck_height : player->stand_height; + + player->velocity.z -= 0.05f; + float nextz = player->pos.z + player->velocity.z; + if(nextz < eyeheight + sect->floor) // falling inside the floor + { + player->pos.z = sect->floor + eyeheight; + player->velocity.z = 0.0f; + } + if(nextz + player->head_margin > sect->ceil) // falling up to the celling + { + player->pos.z = sect->ceil - player->head_margin; + player->velocity.z = 0.0f; + } + + float px = player->pos.x, py = player->pos.y; + float dx = player->velocity.x, dy = player->velocity.y; #define vert(x) map->vertices[x] + + // wether the player is intersecting a sector edge for(unsigned i = 0; i < sect->nverts; i++) { size_t s1 = sect->vertices[i]; size_t s0 = sect->vertices[i+1]; - if(sect->neighbors[i] != (size_t)-1 - && intersectbox(px,py, px+dx,py+dy, vert(s0).x, vert(s0).y, vert(s1).x, vert(s1).y) - && pointside(px+dx, py+dy, vert(s0).x, vert(s0).y, vert(s1).x, vert(s1).y) < 0) + if(!(intersectbox(px,py, px+dx,py+dy, vert(s0).x, vert(s0).y, vert(s1).x, vert(s1).y)) + || !(pointside(px+dx, py+dy, vert(s0).x, vert(s0).y, vert(s1).x, vert(s1).y) < 0)) + continue; + + float hole_low = 0.0f, hole_high = 0.0f; + if(sect->neighbors[i] != (size_t)-1) { + hole_high = min(sect->ceil, map->sectors[sect->neighbors[i]].ceil); + hole_low = map->sectors[sect->neighbors[i]].floor; + } + + // slide along the wall + if(sect->neighbors[i] == (size_t)-1 + || hole_high < player->pos.z + player->head_margin + || hole_low - player->pos.z > player->knee_height) { + // formula from wikipedia + float xd = vert(s1).x - vert(s0).x, yd = vert(s1).y - vert(s0).y; + player->velocity.x = xd * (dx*xd + yd*dy) / (xd*xd + yd*yd); + player->velocity.y = yd * (dx*xd + yd*dy) / (xd*xd + yd*yd); + } else { map->player.sector = sect->neighbors[i]; - break; } + + break; } } + int map_load(map_t *map, char *filename) { int ret = 1; diff --git a/src/sector.h b/src/sector.h index 438184b..b77c2c7 100644 --- a/src/sector.h +++ b/src/sector.h @@ -20,13 +20,13 @@ typedef struct { } map_t; int map_draw(map_t *map, int SW, int SH); // SW and SH should be uint -void map_player_sector(map_t *map); +void map_detect_collision(map_t *map); int map_load(map_t *map, char *filename); void map_unload(map_t *map); -void map_print(map_t *map); int map_save(map_t *map, char *filename); +void map_print(map_t *map); #endif diff --git a/src/shell.html b/src/shell.html index 03321c7..aee9bd6 100644 --- a/src/shell.html +++ b/src/shell.html @@ -3,7 +3,7 @@ <head> <meta charset="utf-8"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - <title>Pendulum</title> + <title>Portal Engine</title> <style> .el { margin: 5px; } div.el { float: left; } @@ -80,4 +80,3 @@ {{{ SCRIPT }}} </body> </html> -d |