Skip to content

Instantly share code, notes, and snippets.

@lasarus
Created August 25, 2012 17:40
Show Gist options
  • Save lasarus/3468331 to your computer and use it in GitHub Desktop.
Save lasarus/3468331 to your computer and use it in GitHub Desktop.
ASCII Raycasting
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <math.h>
int quit = 0;
/*int screen_width = 640, screen_height = 480, screen_bpp = 32;*/
int screen_width = 1280, screen_height = 720, screen_bpp = 32;
int char_width = 8, char_height = 12;
int text_width = 80;
int text_height = 40;
SDL_Surface * screen = NULL;
SDL_Surface * characters = NULL;
SDL_Surface * world_map = NULL;
SDL_Event event;
#define PI 3.1415926535897932384626
#define MAX(x, y) (x > y) ? x : y
void apply_surface(int x, int y, SDL_Surface * source, SDL_Surface * destination, SDL_Rect * clip)
{
SDL_Rect offset;
offset.x = x;
offset.y = y;
SDL_BlitSurface(source, clip, destination, &offset);
}
Uint32 getpixel(SDL_Surface * surface, int x, int y)
{
Uint32 * pixels = (Uint32 *)surface->pixels;
return pixels[(y * surface->w) + x];
}
void draw_char(SDL_Rect r, Uint32 color, int x, int y)
{
int i, j;
Uint32 * pixels = (Uint32 *)screen->pixels;
for(i = 0; i < char_height; i++)
{
for(j = 0; j < char_width; j++)
{
Uint32 pixel = getpixel(characters, r.x + j, r.y + i);
if(pixel == 0xFFFFFF)
pixels[((y + i) * screen->w) + (x + j)] = color;
}
}
}
void draw_text(unsigned char * text)
{
SDL_Rect r2 = {0, 0, 8, 12};
int i, j;
for(i = 0; i < text_height; i++)
{
for(j = 0; j < text_width; j++)
{
r2.x = (text[i * text_width + j] % 16) * char_width;
r2.y = (text[i * text_width + j] / 16) * char_height;
/*SDL_FillRect(screen, &r, 0xFF << (text[i * text_width + j] * 8));*/
/*apply_surface(r.x, r.y, characters, screen, &r2);*/
draw_char(r2, (text[i * text_width + j] == 247) ? 0xFF : ((text[i * text_width + j] == '#') ? 0xFF00: 0xFFFFFF), j * char_width, i * char_height);
}
}
}
/* ----------------------- IMPORTANT PART ------------------ */
double camera_x, camera_y, camera_rot;
int raycast(int x, int y)
{
int rt = 0;
double lx = 1, ly = 0, lz = 0, ll;
double cx = 8 - camera_x, cy = camera_y, cz = 0;
double r = 4;
double lc, cc;
double br, d, lat;
int mx, my;
double step = 0.1 / (text_width / 2.);
ly = (x - (text_width / 2.)) * step;
lz = (y - (text_width / 2.)) * step;
ll = sqrt(lx * lx + ly * ly + lz * lz);
lx /= ll;
ly /= ll;
lz /= ll;
lc = (cx * lx) + (cy * ly) + (cz * lz);
cc = (cx * cx) + (cy * cy) + (cz * cz);
br = (lc * lc) - cc + (r * r);
if(br < 0)
return 0;
d = lc - sqrt(br);
mx = (int)((atan2((lx * d) - cx, (ly * d) - cy) + camera_rot) * (180 / PI)) % 360;
lat = ((lz * d) - cz) / r;
if(lat >= 1) lat = 0.99999;
if(lat <= -1) lat = -0.99999;
my = 180 - (int)(acos(lat) * (180 / PI));
if(mx < 0)
mx += 360;
/*printf("my:%i\t-\t%f %f %f %f\n", my, acos(((lz * d) - cz) / r), ((lz * d) - cz), r, ((lz * d) - cz) / r);*/
rt = (getpixel(world_map, mx * world_map->w / 360, my * world_map->h / 180) != 0x007F00) ? 1 : 0;
return rt + 1;
}
/* ---------- END OF IMPORTANT PART ---------- */
SDL_Surface * load_image(char * filename)
{
SDL_Surface * loadedImage = NULL;
SDL_Surface * optimizedImage = NULL;
loadedImage = IMG_Load(filename);
if(loadedImage != NULL)
{
optimizedImage = SDL_DisplayFormat(loadedImage);
SDL_FreeSurface(loadedImage);
}
return optimizedImage;
}
int init()
{
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
return 1;
screen = SDL_SetVideoMode(screen_width, screen_height, screen_bpp, SDL_SWSURFACE);
if(screen == NULL)
return 1;
text_width = screen_width / char_width;
text_height = screen_height / char_height;
return 0;
}
int main(int argc, char ** argv)
{
Uint32 lastt, newt;
int i;
unsigned char * text = NULL;
if(init())
return 1;
text = malloc(text_height * text_width);
characters = load_image("characters.bmp");
SDL_SetColorKey(characters, SDL_SRCCOLORKEY, 0xFF00FF);
world_map = load_image("wmap2.png");
for(i = 0; i < text_height * text_width; i++)
text[i] = (i % (strlen("Hello, World!") + 1))["Hello, World!"];
lastt = SDL_GetTicks();
while(!quit)
{
Uint32 delta;
Uint8 * keystate = NULL;
if(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT)
quit = 1;
}
newt = SDL_GetTicks();
delta = newt - lastt;
keystate = SDL_GetKeyState(NULL);
if(keystate[SDLK_w])
camera_x += 0.04 * delta;
else if(keystate[SDLK_s])
camera_x -= 0.04 * delta;
if(keystate[SDLK_a])
camera_y += 0.01 * delta;
else if(keystate[SDLK_d])
camera_y -= 0.01 * delta;
if(keystate[SDLK_q])
camera_rot += 0.001 * delta;
else if(keystate[SDLK_e])
camera_rot -= 0.001 * delta;
SDL_FillRect(screen, NULL, 0);
memset(text, 0, text_height * text_width);
for(i = 0; i < text_height * text_width; i++)
{
switch(raycast(i % text_width, i / text_height))
{
case 0:
text[i] = ' ';
break;
case 1:
text[i] = '#';
break;
case 2:
text[i] = (char)(247);
break;
}
}
draw_text(text);
if(SDL_Flip(screen))
return 1;
lastt = newt;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment