tunnel-runner

Pseudo 3D tunnel effect.
git clone git://git.amin.space/tunnel-runner.git
Log | Files | Refs | README | LICENSE

commit 4f38cc4e2d3f503fa747747e42c2ed23dc221149
parent 668ba541f2f33381bf94ba49fde05ef8545c8fa5
Author: amin <dev@aminmesbah.com>
Date:   Sun, 13 Nov 2016 21:35:40 +0000

Enable looking around and changing texture color.

FossilOrigin-Name: 43442c8f385290f7fbaa058f625d333753feb18157d7d5f00af9b7d9b126ea57
Diffstat:
M.gitignore | 2+-
MMakefile | 4++--
Dsdl_tunnel_flyer.cpp | 434-------------------------------------------------------------------------------
Asdl_tunnel_runner.cpp | 509+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 512 insertions(+), 437 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -1 +1 @@ -tunnel-flyer +tunnel-runner diff --git a/Makefile b/Makefile @@ -1,7 +1,7 @@ build: - g++ -std=c++11 -Wall -Wextra -g sdl_tunnel_flyer.cpp -o tunnel-flyer `sdl2-config --cflags --libs` + g++ -std=c++11 -Wall -Wextra -g sdl_tunnel_runner.cpp -o tunnel-runner `sdl2-config --cflags --libs` run: - ./tunnel-flyer + ./tunnel-runner test: build run diff --git a/sdl_tunnel_flyer.cpp b/sdl_tunnel_flyer.cpp @@ -1,434 +0,0 @@ -#include <cmath> -#include <SDL.h> -#include <stdio.h> -#include <stdint.h> -#include <sys/mman.h> - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -#define internal static -#define local_persist static -#define global_variable static - -typedef int8_t int8; -typedef int16_t int16; -typedef int32_t int32; -typedef int64_t int64; - -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -#define BYTES_PER_PIXEL 4 -#define MAX_CONTROLLERS 4 -#define MOVEMENT_SPEED 5 - - -struct SDLOffscreenBuffer -{ - // NOTE(amin): pixels are always 32-bits wide. Memory order: BB GG RR XX. - SDL_Texture *texture; - void *memory; - int width; - int height; - int pitch; -}; - - -struct SDLWindowDimension -{ - int width; - int height; -}; - - -global_variable SDLOffscreenBuffer global_back_buffer; -global_variable SDL_GameController *controller_handles[MAX_CONTROLLERS]; -global_variable SDL_Haptic *rumble_handles[MAX_CONTROLLERS]; - - -internal void -render_mosaic(SDLOffscreenBuffer buffer, int x_offset, int y_offset, char color_choice) -{ - uint8 *row = (uint8 *)buffer.memory; - - for (int y = 0; y < buffer.height; ++y) - { - uint32 *pixel = (uint32 *)row; - - for (int x = 0; x < buffer.width; ++x) - { - uint8 x_factor = (x + x_offset); - uint8 y_factor = (y + y_offset); - uint8 color_value (x_factor * x_factor * y_factor * y_factor); - uint32 red = color_value << 16; - uint32 green = color_value << 8; - uint32 blue = color_value; - - switch(color_choice) - { - case 'g': - { - *pixel++ = green; - } break; - case 'r': - { - *pixel++ = red; - } break; - case 'b': - { - *pixel++ = blue; - } break; - case 'y': - { - *pixel++ = red | green; - } break; - default: - { - *pixel++ = red | green | blue; - } break; - } - } - - row += buffer.pitch; - } -} - - -SDLWindowDimension -sdl_get_window_dimension(SDL_Window *window) -{ - SDLWindowDimension result; - SDL_GetWindowSize(window, &result.width, &result.height); - return(result); -} - - -internal void -sdl_resize_texture(SDLOffscreenBuffer *buffer, SDL_Renderer *renderer, int width, int height) -{ - if (buffer->memory) - { - munmap(buffer->memory, buffer->width * buffer->height * BYTES_PER_PIXEL); - } - - if (buffer->texture) - { - SDL_DestroyTexture(buffer->texture); - } - - buffer->texture = SDL_CreateTexture( - renderer, - SDL_PIXELFORMAT_ARGB8888, - SDL_TEXTUREACCESS_STREAMING, - width, height); - - buffer->width = width; - buffer->height = height; - buffer->pitch = width * BYTES_PER_PIXEL; - - buffer->memory = mmap( - 0, - width * height * BYTES_PER_PIXEL, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, - -1, 0); -} - - -internal void -sdl_update_window(SDL_Window *window, SDL_Renderer *renderer, SDLOffscreenBuffer buffer) -{ - if (SDL_UpdateTexture(buffer.texture, 0, buffer.memory, buffer.pitch)) - { - // TODO(amin): Handle this error - } - - SDL_RenderCopy(renderer, buffer.texture, 0, 0); - SDL_RenderPresent(renderer); -} - - -bool -handle_event(SDL_Event *event) -{ - bool should_quit = false; - - switch(event->type) - { - case SDL_QUIT: - { - printf("SDL_QUIT\n"); - should_quit = true; - } break; - - case SDL_WINDOWEVENT: - { - switch(event->window.event) - { - case SDL_WINDOWEVENT_SIZE_CHANGED: - { - SDL_Window *window = SDL_GetWindowFromID(event->window.windowID); - SDL_Renderer *renderer = SDL_GetRenderer(window); - printf("SDL_WINDOWEVENT_SIZE_CHANGED (%d, %d)\n", event->window.data1, event->window.data2); - // TODO(amin): Why does this segfault? - //sdl_resize_texture(&global_back_buffer, renderer, event->window.data1, event->window.data2); - } break; - - case SDL_WINDOWEVENT_FOCUS_GAINED: - { - printf("SDL_WINDOWEVENT_FOCUS_GAINED\n"); - } break; - - case SDL_WINDOWEVENT_EXPOSED: - { - SDL_Window *window = SDL_GetWindowFromID(event->window.windowID); - SDL_Renderer *renderer = SDL_GetRenderer(window); - sdl_update_window(window, renderer, global_back_buffer); - } break; - } - } break; - } - return(should_quit); -} - - -internal void -sdl_open_game_controllers() -{ - int num_joysticks = SDL_NumJoysticks(); - for (int controller_index = 0; controller_index < num_joysticks; ++controller_index) - { - if (!SDL_IsGameController(controller_index)) - { - continue; - } - - if (controller_index >= MAX_CONTROLLERS) - { - break; - } - - controller_handles[controller_index] = SDL_GameControllerOpen(controller_index); - rumble_handles[controller_index] = SDL_HapticOpen(controller_index); - - if (rumble_handles[controller_index] && SDL_HapticRumbleInit(rumble_handles[controller_index]) != 0) - { - SDL_HapticClose(rumble_handles[controller_index]); - rumble_handles[controller_index] = 0; - } - } -} - - -internal void -sdl_close_game_controllers() -{ - for (int controller_index = 0; controller_index < MAX_CONTROLLERS; ++controller_index) - { - if (controller_handles[controller_index]) - { - SDL_GameControllerClose(controller_handles[controller_index]); - } - } -} - - -int main(void) -{ - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) != 0) - { - // TODO(amin): log SDL_Init error - } - - sdl_open_game_controllers(); - - SDL_Window *window = SDL_CreateWindow( - "Tunnel Flyer", - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - 640, - 480, - SDL_WINDOW_RESIZABLE); - - if (window) - { - SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); - - if (renderer) - { - bool running = true; - SDLWindowDimension dimension = sdl_get_window_dimension(window); - sdl_resize_texture(&global_back_buffer, renderer, dimension.width, dimension.height); - - int tex_width = 256; - int tex_height = 256; - int screen_width = dimension.width; - int screen_height = dimension.height; - - uint32 texture[tex_width][tex_height]; - int distance_table[screen_height][screen_width]; - int angle_table[screen_height][screen_width]; - - // Make XOR texture - for (int y = 0; y < tex_height; ++y) - { - for (int x = 0; x < tex_width; ++x) - { - texture[y][x] = (x * 256 / tex_width) ^ (y * 256 / tex_height); - } - } - - // Make distance and angle transformation tables - for (int y = 0; y < screen_height; ++y) - { - for (int x = 0; x < screen_width; ++x) - { - float ratio = 32.0; - int distance = (int)(ratio * tex_height / sqrt( - (x - screen_width / 2.0) * (x - screen_width / 2.0) + (y - screen_height / 2.0) * (y - screen_height / 2.0)) - ) % tex_height; - int angle = (unsigned int)(0.5 * tex_width * atan2(y - screen_height / 2.0, x - screen_width / 2.0) / 3.1416); - distance_table[y][x] = distance; - angle_table[y][x] = angle; - } - } - - int rotation_offset = 0; - int translation_offset = 0; - char color_choice = '\0'; - - while (running) - { - SDL_Event event; - - while (SDL_PollEvent(&event)) - { - if (handle_event(&event)) - { - running = false; - } - } - - SDL_PumpEvents(); - const uint8 *keystate = SDL_GetKeyboardState(0); - - if (keystate[SDL_SCANCODE_A]) - { - rotation_offset -= MOVEMENT_SPEED; - } - if (keystate[SDL_SCANCODE_D]) - { - rotation_offset += MOVEMENT_SPEED; - } - if (keystate[SDL_SCANCODE_W]) - { - translation_offset += MOVEMENT_SPEED; - } - if (keystate[SDL_SCANCODE_S]) - { - translation_offset -= MOVEMENT_SPEED; - } - if (keystate[SDL_SCANCODE_LEFT]) - { - rotation_offset --; - } - if (keystate[SDL_SCANCODE_RIGHT]) - { - rotation_offset ++; - } - if (keystate[SDL_SCANCODE_UP]) - { - translation_offset ++; - } - if (keystate[SDL_SCANCODE_DOWN]) - { - translation_offset --; - } - - - for (int controller_index = 0; controller_index < MAX_CONTROLLERS; ++controller_index) - { - if (SDL_GameControllerGetAttached(controller_handles[controller_index])) - { - bool start = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_START); - bool back = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_BACK); - bool a_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_A); - bool b_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_B); - bool x_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_X); - bool y_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_Y); - - int16 stick_leftx = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_LEFTX); - int16 stick_lefty = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_LEFTY); - - if (start) - { - SDL_HapticRumblePlay(rumble_handles[controller_index], 0.5f, 2000); - } - else - { - SDL_HapticRumbleStop(rumble_handles[controller_index]); - } - - if (back) - { - running = false; - } - - // NOTE(amin): Buttons select colors. - if (a_button) - { - color_choice = 'g'; - } - if (b_button) - { - color_choice = 'r'; - } - if (x_button) - { - color_choice = 'b'; - } - if (y_button) - { - color_choice = 'y'; - } - - rotation_offset += stick_leftx / 5000; - translation_offset -= stick_lefty / 5000; - } - } - - // Transform texture and draw to buffer - uint8 *row = (uint8 *)global_back_buffer.memory; - for (int y = 0; y < global_back_buffer.height; ++y) - { - uint32 *pixel = (uint32 *)row; - for (int x = 0; x < global_back_buffer.width; ++x) - { - int color = texture[(unsigned int)(distance_table[y][x] + translation_offset) % tex_width] - [(unsigned int)(angle_table[y][x] + rotation_offset) % tex_height]; - *pixel++ = color; - } - row += global_back_buffer.pitch; - } - //render_mosaic(global_back_buffer, rotation_offset, translation_offset, color_choice); - sdl_update_window(window, renderer, global_back_buffer); - } - } - else - { - // TODO(amin): log SDL_Renderer error - } - } - else - { - // TODO(amin): log SDL_Window error - } - - sdl_close_game_controllers(); - SDL_Quit(); - return(0); -} diff --git a/sdl_tunnel_runner.cpp b/sdl_tunnel_runner.cpp @@ -0,0 +1,509 @@ +#include <cmath> +#include <SDL.h> +#include <stdio.h> +#include <stdint.h> +#include <sys/mman.h> + +#ifndef MAP_ANONYMOUS +#define MAP_ANONYMOUS MAP_ANON +#endif + +#define internal static +#define local_persist static +#define global_variable static + +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; + +// TODO(amin): Make screen size adjustable +#define SCREEN_WIDTH 640 +#define SCREEN_HEIGHT 480 +#define BYTES_PER_PIXEL 4 +#define MAX_CONTROLLERS 4 +#define MOVEMENT_SPEED 5 +#define CONTROLLER_STICK_MAX 32770 +#define CONTROLLER_STICK_MIN -32770 + + +struct SDLOffscreenBuffer +{ + // NOTE(amin): pixels are always 32-bits wide. Memory order: BB GG RR XX. + SDL_Texture *texture; + void *memory; + int width; + int height; + int pitch; +}; + + +struct SDLWindowDimension +{ + int width; + int height; +}; + + +global_variable SDLOffscreenBuffer global_back_buffer; +global_variable SDL_GameController *controller_handles[MAX_CONTROLLERS]; +global_variable SDL_Haptic *rumble_handles[MAX_CONTROLLERS]; + + +internal void +render_mosaic(SDLOffscreenBuffer buffer, int x_offset, int y_offset, char color_choice) +{ + uint8 *row = (uint8 *)buffer.memory; + + for (int y = 0; y < buffer.height; ++y) + { + uint32 *pixel = (uint32 *)row; + + for (int x = 0; x < buffer.width; ++x) + { + uint8 x_factor = (x + x_offset); + uint8 y_factor = (y + y_offset); + uint8 color_value (x_factor * x_factor * y_factor * y_factor); + uint32 red = color_value << 16; + uint32 green = color_value << 8; + uint32 blue = color_value; + + switch(color_choice) + { + case 'g': + { + *pixel++ = green; + } break; + case 'r': + { + *pixel++ = red; + } break; + case 'b': + { + *pixel++ = blue; + } break; + case 'y': + { + *pixel++ = red | green; + } break; + case 'm': + { + *pixel++ = red | blue; + } break; + case 'c': + { + *pixel++ = blue | green; + } break; + default: + { + *pixel++ = red | green | blue; + } break; + } + } + + row += buffer.pitch; + } +} + + +SDLWindowDimension +sdl_get_window_dimension(SDL_Window *window) +{ + SDLWindowDimension result; + SDL_GetWindowSize(window, &result.width, &result.height); + return(result); +} + + +internal void +sdl_resize_texture(SDLOffscreenBuffer *buffer, SDL_Renderer *renderer, int width, int height) +{ + if (buffer->memory) + { + munmap(buffer->memory, buffer->width * buffer->height * BYTES_PER_PIXEL); + } + + if (buffer->texture) + { + SDL_DestroyTexture(buffer->texture); + } + + buffer->texture = SDL_CreateTexture( + renderer, + SDL_PIXELFORMAT_ARGB8888, + SDL_TEXTUREACCESS_STREAMING, + width, height); + + buffer->width = width; + buffer->height = height; + buffer->pitch = width * BYTES_PER_PIXEL; + + buffer->memory = mmap( + 0, + width * height * BYTES_PER_PIXEL, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, + -1, 0); +} + + +internal void +sdl_update_window(SDL_Window *window, SDL_Renderer *renderer, SDLOffscreenBuffer buffer) +{ + if (SDL_UpdateTexture(buffer.texture, 0, buffer.memory, buffer.pitch)) + { + // TODO(amin): Handle this error + } + + SDL_RenderCopy(renderer, buffer.texture, 0, 0); + SDL_RenderPresent(renderer); +} + + +bool +handle_event(SDL_Event *event) +{ + bool should_quit = false; + + switch(event->type) + { + case SDL_QUIT: + { + printf("SDL_QUIT\n"); + should_quit = true; + } break; + + case SDL_WINDOWEVENT: + { + switch(event->window.event) + { + case SDL_WINDOWEVENT_SIZE_CHANGED: + { + SDL_Window *window = SDL_GetWindowFromID(event->window.windowID); + SDL_Renderer *renderer = SDL_GetRenderer(window); + printf("SDL_WINDOWEVENT_SIZE_CHANGED (%d, %d)\n", event->window.data1, event->window.data2); + // TODO(amin): Why does this segfault? + //sdl_resize_texture(&global_back_buffer, renderer, event->window.data1, event->window.data2); + } break; + + case SDL_WINDOWEVENT_FOCUS_GAINED: + { + printf("SDL_WINDOWEVENT_FOCUS_GAINED\n"); + } break; + + case SDL_WINDOWEVENT_EXPOSED: + { + SDL_Window *window = SDL_GetWindowFromID(event->window.windowID); + SDL_Renderer *renderer = SDL_GetRenderer(window); + //sdl_update_window(window, renderer, global_back_buffer); + } break; + } + } break; + } + return(should_quit); +} + + +internal void +sdl_open_game_controllers() +{ + int num_joysticks = SDL_NumJoysticks(); + for (int controller_index = 0; controller_index < num_joysticks; ++controller_index) + { + if (!SDL_IsGameController(controller_index)) + { + continue; + } + + if (controller_index >= MAX_CONTROLLERS) + { + break; + } + + controller_handles[controller_index] = SDL_GameControllerOpen(controller_index); + rumble_handles[controller_index] = SDL_HapticOpen(controller_index); + + if (rumble_handles[controller_index] && SDL_HapticRumbleInit(rumble_handles[controller_index]) != 0) + { + SDL_HapticClose(rumble_handles[controller_index]); + rumble_handles[controller_index] = 0; + } + } +} + + +internal void +sdl_close_game_controllers() +{ + for (int controller_index = 0; controller_index < MAX_CONTROLLERS; ++controller_index) + { + if (controller_handles[controller_index]) + { + SDL_GameControllerClose(controller_handles[controller_index]); + } + } +} + + +int main(void) +{ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) != 0) + { + // TODO(amin): log SDL_Init error + } + + sdl_open_game_controllers(); + + SDL_Window *window = SDL_CreateWindow( + "Tunnel Flyer", + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + SCREEN_WIDTH, + SCREEN_HEIGHT, + 0); + + if (window) + { + SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0); + + if (renderer) + { + bool running = true; + SDLWindowDimension dimension = sdl_get_window_dimension(window); + sdl_resize_texture(&global_back_buffer, renderer, dimension.width, dimension.height); + + int tex_width = 256; + int tex_height = 256; + + uint32 texture[tex_width][tex_height]; + global_variable int distance_table[2 * SCREEN_HEIGHT][2 * SCREEN_WIDTH]; + global_variable int angle_table[2 * SCREEN_HEIGHT][2 * SCREEN_WIDTH]; + + // Make XOR texture + for (int y = 0; y < tex_height; ++y) + { + for (int x = 0; x < tex_width; ++x) + { + texture[y][x] = (x * 256 / tex_width) ^ (y * 256 / tex_height); + } + } + + // Make distance and angle transformation tables + for (int y = 0; y < 2 * SCREEN_HEIGHT; ++y) + { + for (int x = 0; x < 2 * SCREEN_WIDTH; ++x) + { + float ratio = 32.0; + int distance = int(ratio * tex_height / sqrt( + float((x - SCREEN_WIDTH) * (x - SCREEN_WIDTH) + (y - SCREEN_HEIGHT) * (y - SCREEN_HEIGHT)) + )) % tex_height; + int angle = (unsigned int)(0.5 * tex_width * atan2(float(y - SCREEN_HEIGHT), float(x - SCREEN_WIDTH)) / 3.1416); + distance_table[y][x] = distance; + angle_table[y][x] = angle; + } + } + + int rotation_offset = 0; + int translation_offset = 0; + int look_shift_x = SCREEN_WIDTH / 2; + int look_shift_y = SCREEN_HEIGHT / 2; + char color_choice = '\0'; + + while (running) + { + SDL_Event event; + + while (SDL_PollEvent(&event)) + { + if (handle_event(&event)) + { + running = false; + } + } + + SDL_PumpEvents(); + const uint8 *keystate = SDL_GetKeyboardState(0); + + if (keystate[SDL_SCANCODE_A]) + { + rotation_offset -= MOVEMENT_SPEED; + } + if (keystate[SDL_SCANCODE_D]) + { + rotation_offset += MOVEMENT_SPEED; + } + if (keystate[SDL_SCANCODE_W]) + { + translation_offset += MOVEMENT_SPEED; + } + if (keystate[SDL_SCANCODE_S]) + { + translation_offset -= MOVEMENT_SPEED; + } + if (keystate[SDL_SCANCODE_LEFT]) + { + rotation_offset --; + } + if (keystate[SDL_SCANCODE_RIGHT]) + { + rotation_offset ++; + } + if (keystate[SDL_SCANCODE_UP]) + { + translation_offset ++; + } + if (keystate[SDL_SCANCODE_DOWN]) + { + translation_offset --; + } + + + for (int controller_index = 0; controller_index < MAX_CONTROLLERS; ++controller_index) + { + if (SDL_GameControllerGetAttached(controller_handles[controller_index])) + { + bool start = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_START); + bool back = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_BACK); + bool a_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_A); + bool b_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_B); + bool x_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_X); + bool y_button = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_Y); + bool left_shoulder = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_LEFTSHOULDER); + bool right_shoulder = SDL_GameControllerGetButton(controller_handles[controller_index], SDL_CONTROLLER_BUTTON_RIGHTSHOULDER); + + int16 stick_leftx = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_LEFTX); + int16 stick_lefty = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_LEFTY); + int16 stick_rightx = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_RIGHTX); + int16 stick_righty = SDL_GameControllerGetAxis(controller_handles[controller_index], SDL_CONTROLLER_AXIS_RIGHTY); + + if (start) + { + SDL_HapticRumblePlay(rumble_handles[controller_index], 0.5f, 2000); + color_choice = '\0'; + } + else + { + SDL_HapticRumbleStop(rumble_handles[controller_index]); + } + + if (back) + { + running = false; + } + + // NOTE(amin): Buttons select colors. + if (a_button) + { + color_choice = 'g'; + } + if (b_button) + { + color_choice = 'r'; + } + if (x_button) + { + color_choice = 'b'; + } + if (y_button) + { + color_choice = 'y'; + } + if (left_shoulder) + { + color_choice = 'm'; + } + if (right_shoulder) + { + color_choice = 'c'; + } + + rotation_offset += stick_leftx / 5000; + translation_offset -= stick_lefty / 5000; + + int dampened_x_max = SCREEN_WIDTH / 2; + int dampened_x_min = -(SCREEN_WIDTH / 2); + int dampened_y_max = SCREEN_HEIGHT / 2; + int dampened_y_min = -(SCREEN_HEIGHT / 2); + + int dampened_x = (stick_rightx - CONTROLLER_STICK_MIN) * (dampened_x_max - dampened_x_min) / (CONTROLLER_STICK_MAX - CONTROLLER_STICK_MIN) + dampened_x_min; + int dampened_y = (stick_righty - CONTROLLER_STICK_MIN) * (dampened_y_max - dampened_y_min) / (CONTROLLER_STICK_MAX - CONTROLLER_STICK_MIN) + dampened_y_min; + + look_shift_x = SCREEN_WIDTH / 2 + dampened_x; + look_shift_y = SCREEN_HEIGHT / 2 + dampened_y; + //printf("screen_width / 2: %d\t damp_x: %d\t raw_x: %d\n", screen_width / 2, dampened_x, stick_rightx); + //printf("screen_height / 2: %d\t damp_y: %d\t raw_y: %d\n", screen_height / 2, dampened_y, stick_righty); + } + } + + // Transform texture and draw to buffer + uint8 *row = (uint8 *)global_back_buffer.memory; + for (int y = 0; y < global_back_buffer.height; ++y) + { + uint32 *pixel = (uint32 *)row; + for (int x = 0; x < global_back_buffer.width; ++x) + { + int color = texture[(unsigned int)(distance_table[y + look_shift_y][x + look_shift_x] + translation_offset) % tex_width] + [(unsigned int)(angle_table[y + look_shift_y][x + look_shift_x] + rotation_offset) % tex_height]; + + uint32 red = color << 16; + uint32 green = color << 8; + uint32 blue = color; + + // TODO(amin): Make a color choice enum + switch(color_choice) + { + case 'g': + { + *pixel++ = green; + } break; + case 'r': + { + *pixel++ = red; + } break; + case 'b': + { + *pixel++ = blue; + } break; + case 'y': + { + *pixel++ = red | green; + } break; + case 'm': + { + *pixel++ = red | blue; + } break; + case 'c': + { + *pixel++ = blue | green; + } break; + default: + { + *pixel++ = red | green | blue; + } break; + } + } + row += global_back_buffer.pitch; + } + //render_mosaic(global_back_buffer, rotation_offset, translation_offset, color_choice); + sdl_update_window(window, renderer, global_back_buffer); + } + } + else + { + // TODO(amin): log SDL_Renderer error + } + } + else + { + // TODO(amin): log SDL_Window error + } + + sdl_close_game_controllers(); + SDL_Quit(); + return(0); +}