/* TODO: Find a bit better way, so it won't cancel the movement. */ void mapFixMovement (Map *map, double x, double y, double *xNew, double *yNew) { int mapX, mapY; assert (map != NULL); assert (xNew != NULL && yNew != NULL); mapX = x + *xNew; if (mapX < 0 || mapX >= map->width || mapGetField (map, mapX, y)) *xNew = 0; mapY = y + *yNew; if (mapY < 0 || mapY >= map->height || mapGetField (map, x, mapY)) *yNew = 0; }
String* mapGetString(int field, FIX::FieldMap& map) { QF_STACK_TRY StringField* stringField = new StringField(field); return mapGetField( stringField, map )->getValue(); QF_STACK_CATCH }
DateTime mapGetUtcTimeOnly(int field, FIX::FieldMap& map) { QF_STACK_TRY UtcTimeOnlyField* utcTimeOnlyField = new UtcTimeOnlyField(field); return mapGetField( utcTimeOnlyField, map )->getValue(); QF_STACK_CATCH }
double mapGetDouble(int field, FIX::FieldMap& map) { QF_STACK_TRY DoubleField* doubleField = new DoubleField(field); return mapGetField( doubleField, map )->getValue(); QF_STACK_CATCH }
int mapGetInt(int field, FIX::FieldMap& map) { QF_STACK_TRY IntField* intField = new IntField(field); return mapGetField( intField, map )->getValue(); QF_STACK_CATCH }
char mapGetChar(int field, FIX::FieldMap& map) { QF_STACK_TRY CharField* charField = new CharField(field); return mapGetField( charField, map )->getValue(); QF_STACK_CATCH }
bool mapGetBoolean(int field, FIX::FieldMap& map) { QF_STACK_TRY BooleanField* booleanField = new BooleanField(field); return mapGetField( booleanField, map )->getValue(); QF_STACK_CATCH }
static void envRenderEnvironment (Environment env, Camera *cam) { double xh, yh, xv, yv, xhInc, xvInc, yhInc, yvInc; double angle, angleInc, tan_angle; int col; angle = cam->angle + cam->fov / 2; angleInc = cam->fov / cam->screen->w; for (col = 0; col < cam->screen->w; col++) { /* Normalize the angle value. */ if (angle <= 0.) angle += 2 * M_PI; else if (angle > 2 * M_PI) angle -= 2 * M_PI; tan_angle = tan (angle); /* TODO: What's up with the almost-zero decrement? */ /* Find the first intersection with the horizontal grid. */ /* Facing up or down? */ if (angle < M_PI) { yh = floor (cam->y) - 10e-8; yhInc = -1; yvInc = -fabs (tan_angle); } else { yh = floor (cam->y) + 1; yhInc = 1; yvInc = fabs (tan_angle); } xh = cam->x + (cam->y - yh) / tan_angle; /* Find the first intersection with the vertical grid. */ /* To the left or to the right? */ if (angle > M_PI_2 && angle < M_PI_2 * 3) { xv = floor (cam->x) - 10e-8; xvInc = -1; xhInc = -1 / fabs (tan_angle); } else { xv = floor (cam->x) + 1; xvInc = 1; xhInc = 1 / fabs (tan_angle); } yv = cam->y + (cam->x - xv) * tan_angle; /* FIXME: It should not pretend there's a wall behind the border. */ /* There's a slight problem with looking back at the area with a map. * We should somehow detect whether the ray will EVER hit a wall. */ /* Stop when either there's a wall or we've reached the border. */ while (yh < env->map->height && yh >= 0 && xh < env->map->width && xh >= 0 && !mapGetField (env->map, xh, yh)) { xh += xhInc; yh += yhInc; } while (yv < env->map->height && yv >= 0 && xv < env->map->width && xv >= 0 && !mapGetField (env->map, xv, yv)) { xv += xvInc; yv += yvInc; } double distH, distV, dist, offset; int height, blockX, blockY, texId; /* Compute the distance to both intersections. */ /* See http://www.permadi.com/tutorial/raycast/rayc8.html for optim. */ distH = (xh - cam->x) * (xh - cam->x) + (yh - cam->y) * (yh - cam->y); distV = (xv - cam->x) * (xv - cam->x) + (yv - cam->y) * (yv - cam->y); /* Find the nearer intersection and texture offset. */ if (distH < distV) { dist = sqrt (distH); offset = fmod (xh, 1.0); blockX = xh; blockY = yh; } else { dist = sqrt (distV); offset = fmod (yv, 1.0); blockX = xv; blockY = yv; } /* The texture ID is one less than the number in the map array. */ if (blockX >= 0 && blockX < env->map->width && blockY >= 0 && blockY < env->map->height) texId = mapGetField (env->map, blockX, blockY) - 1; else texId = 0; assert (texId < env->textures_len); /* Remove distortion. */ /* TODO: Precompute into an array. */ dist *= cos (angle - cam->angle); /* Compute the projected wall height. */ height = cam->distance / dist; /* Draw the wall with a texture. */ int i, yy, wallYStart, wallYStop; int texXPrecomp; double texYPrecomp; Uint32 pixel; texXPrecomp = offset * env->textures[texId]->w; texYPrecomp = (double) env->textures[texId]->h / height; if (height > cam->screen->h) { wallYStart = (height - cam->screen->h) / 2; wallYStop = height - wallYStart - 1; } else { wallYStart = 0; wallYStop = height; } for (i = wallYStart; i < wallYStop; i++) { yy = (cam->screen->h - height) / 2 + i; pixel = sdluGetPixel32Unsafe (env->textures[texId], texXPrecomp, (int) (i * texYPrecomp)); /* Enhance the 3D effect a bit by darkening some walls. */ if (distH < distV) pixel = (pixel >> 1) & 0x7F7F7F7F & ~RGB_AMASK; sdluPutPixel (cam->screen, col, yy, SDL_MapRGB (cam->screen->format, RGB_GETR (pixel), RGB_GETG (pixel), RGB_GETB (pixel))); /* Set the Z-buffer. */ cam->zbuffer[yy * cam->screen->w + col] = dist; } /* Draw the floor. */ double fdist, dx, dy; double fdistPrecomp; int k = 0; fdistPrecomp = cam->distance * cam->z / cos (angle - cam->angle); for (i = (cam->screen->h + height) / 2; i < cam->screen->h; i++) { fdist = fdistPrecomp / (i - cam->screen->h / 2); dx = fabs (fmod (fdist * cos (angle) + cam->x, 1.0)); dy = fabs (fmod (fdist * sin (angle) - cam->y, 1.0)); /* XXX: Hard-coded texture ID. */ pixel = sdluGetPixel32Unsafe (env->textures[0], (int) (dx * env->textures[0]->w), (int) (dy * env->textures[0]->h)); sdluPutPixel (cam->screen, col, i, SDL_MapRGB (cam->screen->format, RGB_GETR (pixel), RGB_GETG (pixel), RGB_GETB (pixel))); /* Some relatively low-cost glass effect. */ if ((cam->renderFlags & GAME_FLAG_FLOOR_REFLECTION) && k++ < GAME_FLOOR_REFLECTION_HEIGHT) { Uint8 xr, xg, xb; SDL_GetRGB (sdluGetPixel (cam->screen, col, i - 2 * k), cam->screen->format, &xr, &xg, &xb); sdluPutPixelAlpha (cam->screen, col, i, RGB_BUILDCOLOR_A (xr, xg, xb, 128 - (int) ((double) k / GAME_FLOOR_REFLECTION_HEIGHT * 128))); } /* Set the Z-buffer. */ cam->zbuffer[i * cam->screen->w + col] = fdist * cos (angle - cam->angle); } /* Advance to the next ray. */ angle -= angleInc; } }