diff options
| -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 | 
