From cf631e23e1d0e29edac2e13446bdd42235c111fc Mon Sep 17 00:00:00 2001 From: kartofen Date: Sat, 15 Apr 2023 18:27:29 +0300 Subject: collision and depth shading --- src/sector.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 16 deletions(-) (limited to 'src/sector.c') 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; -- cgit v1.2.3