world-map/main.c

203 lines
5.8 KiB
C

#include <stdio.h>
#include <time.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include "draw.h"
#define PRESCALE 4
#define FORMAT SDL_PIXELFORMAT_RGB565
#define WHITE rgb565(255, 255, 255)
#define BLACK rgb565(0, 0, 0)
typedef struct {
int size;
float* points;
} Polygon;
typedef struct {
int size;
Polygon* polygons;
} Data;
Data data;
void load(char* filename) {
FILE* fp = fopen(filename, "r");
if (!fp) {
perror(filename);
exit(1);
}
if (1 != fscanf(fp, "%d", &data.size)) goto load_error;
data.polygons = malloc(sizeof(Polygon) * data.size);
for (int i = 0; i < data.size; i++) {
float tmp; // skip bbox
if (4 != fscanf(fp, "%f %f %f %f", &tmp, &tmp, &tmp, &tmp)) goto load_error;
if (1 != fscanf(fp, "%d", &data.polygons[i].size)) goto load_error;
data.polygons[i].size *= 2; // number of values is number of points * 2
data.polygons[i].points = malloc(sizeof(float) * data.polygons[i].size);
for (int j = 0; j < data.polygons[i].size; j++) {
if (1 != fscanf(fp, "%f", &data.polygons[i].points[j])) goto load_error;
}
}
return;
load_error:
perror(filename);
exit(1);
}
float center[2] = {WIDTH / 2, 0};
float zoom = 1;
void init() {
load("ne_10m_land.txt");
}
void deinit() {
}
void update(float dt) {
}
void redraw() {
clear_screen();
for (int i = 0; i < data.size; i++) {
float transformed[data.polygons[i].size];
for (int j = 0; j < data.polygons[i].size; j += 2) {
transformed[j] = data.polygons[i].points[j] * zoom * WIDTH / 360 + WIDTH / 2 + center[0] * zoom;
transformed[j + 1] = -data.polygons[i].points[j + 1] * zoom * HEIGHT / 180 + HEIGHT / 2 + center[1] * zoom;
}
//fill(data.polygons[i].size, transformed, WIDTH * zoom, rgb565((i * 128397) % 255, (i * 123551) % 255, (i * 1097123) % 255));
fill(data.polygons[i].size, transformed, WIDTH * zoom, rgb565(255, 255, 255));
}
}
//#define on_key(event)
//#define on_mouse(event, kind)
#define on_text(event)
int mouse_pressed = 0;
int mouse_start_x, mouse_start_y;
int center_start_x, center_start_y;
void on_key(SDL_Event event) {
switch (event.key.keysym.sym) {
case SDLK_1: zoom = 1; break;
case SDLK_2: zoom = 4; break;
case SDLK_3: zoom = 16; break;
case SDLK_4: zoom = 64; break;
case SDLK_5: zoom = 128; break;
}
}
void on_mouse(SDL_Event event, int kind) {
switch (kind) {
case 1:
mouse_pressed = 1;
mouse_start_x = event.motion.x;
mouse_start_y = event.motion.y;
center_start_x = center[0];
center_start_y = center[1];
break;
case 2:
mouse_pressed = 0;
break;
case 0:
if (mouse_pressed) {
center[0] = ((event.motion.x - mouse_start_x) / zoom + center_start_x);
center[1] = ((event.motion.y - mouse_start_y) / zoom + center_start_y);
}
break;
case 3:
zoom += event.wheel.preciseY / 8;
break;
}
}
int main(int argc, char** argv) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "Failed to init SDL\n");
return 1;
}
if(IMG_Init(IMG_INIT_PNG) < 0) {
fprintf(stderr, "Failed to init SDL_Image\n");
return 1;
}
init();
SDL_Window* window = SDL_CreateWindow("RPG", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 2 * WIDTH, 2 * HEIGHT, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE );
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
SDL_Texture* scaled = SDL_CreateTexture(renderer, FORMAT, SDL_TEXTUREACCESS_TARGET, PRESCALE * WIDTH, PRESCALE * HEIGHT);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest");
SDL_RenderSetLogicalSize(renderer, WIDTH, HEIGHT);
//SDL_RenderSetIntegerScale(renderer, 1);
//SDL_MaximizeWindow(window);
SDL_StartTextInput();
SDL_SetRenderTarget(renderer, scaled);
int fullscreen = 0;
SDL_Texture* screen_texture = SDL_CreateTexture(renderer, FORMAT, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT);
while (1) {
Uint64 frame_start = SDL_GetPerformanceCounter();
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) { deinit(); exit(0);
} else if(event.type == SDL_WINDOWEVENT) {
} else if (event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_RETURN && event.key.keysym.mod & KMOD_ALT) {
fullscreen = SDL_WINDOW_FULLSCREEN_DESKTOP - fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
} else if (event.key.keysym.sym == SDLK_q && event.key.keysym.mod & KMOD_CTRL) {
deinit(); exit(0);
} else on_key(event);
} else if (event.type == SDL_KEYUP) { on_key(event);
} else if (event.type == SDL_TEXTINPUT) { on_text(event);
} else if (event.type == SDL_MOUSEBUTTONDOWN) { on_mouse(event, 1);
} else if (event.type == SDL_MOUSEMOTION) { on_mouse(event, 0);
} else if (event.type == SDL_MOUSEBUTTONUP) { on_mouse(event, 2);
} else if (event.type == SDL_MOUSEWHEEL) { on_mouse(event, 3);
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_UpdateTexture(screen_texture, NULL, framebuffer, WIDTH * sizeof(Color));
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, scaled, NULL, NULL);
SDL_RenderPresent(renderer);
SDL_SetRenderTarget(renderer, scaled);
update(1.0f / 60);
redraw();
Uint64 frame_end = SDL_GetPerformanceCounter();
Uint64 duration = (frame_end - frame_start) * 1000 / SDL_GetPerformanceFrequency();
if (duration > 0) printf("%ld fps\n", 1000 / duration);
if(duration < 1000 / 60) SDL_Delay(1000 / 60 - duration);
}
deinit();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}