summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkartofen <mladenovnasko0@gmail.com>2023-04-15 18:27:29 +0300
committerkartofen <mladenovnasko0@gmail.com>2023-04-15 18:27:29 +0300
commitcf631e23e1d0e29edac2e13446bdd42235c111fc (patch)
tree141f85599c7bd47b3fcb0a3088a5ce117d6e18fd
parent02ec17653ee5399eac67871dfd5fb193bb9dce2f (diff)
collision and depth shading
-rwxr-xr-xbuild.sh4
-rw-r--r--src/common.h6
-rw-r--r--src/main.c42
-rw-r--r--src/player.c15
-rw-r--r--src/player.h4
-rw-r--r--src/sector.c71
-rw-r--r--src/sector.h4
-rw-r--r--src/shell.html3
8 files changed, 108 insertions, 41 deletions
diff --git a/build.sh b/build.sh
index 9a37dce..7c140b7 100755
--- a/build.sh
+++ b/build.sh
@@ -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
diff --git a/src/main.c b/src/main.c
index 432d26f..f2d6944 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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