Created
August 25, 2012 17:40
-
-
Save lasarus/3468331 to your computer and use it in GitHub Desktop.
ASCII Raycasting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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