// NormFloat64 returns a normally distributed float64 in the range // [-math.MaxFloat64, +math.MaxFloat64] with // standard normal distribution (mean = 0, stddev = 1). // To produce a different normal distribution, callers can // adjust the output using: // // sample = NormFloat64() * desiredStdDev + desiredMean // real_t rstdnorm_zig(void) { for (;;) { int32_t j = gen_rand32(); // Possibly negative int32_t i = j & 0x7F; real_t x = (real_t)(j) * (real_t)(wn[i]); if (absInt32(j) < kn[i]) { // This case should be hit better than 99% of the time. return x; } if (i == 0) { // This extra work is only required for the base strip. for (;;) { x = -log(runif()) * (1.0 / rn); real_t y = -log(runif()); if (y+y >= x*x) { break; } } if (j > 0) { return rn + x; } return -rn - x; } if (fn[i]+runif()*(fn[i-1]-fn[i]) < exp(-.5*x*x)) { return x; } } errx(EXIT_FAILURE,"Unreachable: %s (%s:%d)",__func__,__FILE__,__LINE__); }
void render_hex(v2 hex_pos, uint32_t * pixels, HexShape hexes, v2 window_dimensions_in_pixels, uint32_t color) { // TODO: Sub-pixel rendering, instead of flooring v2 startPos = subV2(hex_pos, floorVf2(hexes.dimensions_in_pixels)); v2 endPos = addV2(hex_pos, floorVf2(hexes.dimensions_in_pixels)); if (startPos.x < 0) { startPos.x = 0; } else if (startPos.x > window_dimensions_in_pixels.x) { startPos.x = window_dimensions_in_pixels.x; } if (startPos.y < 0) { startPos.y = 0; } else if (startPos.y > window_dimensions_in_pixels.y) { startPos.y = window_dimensions_in_pixels.y; } v2 pos; for (pos.y = startPos.y; pos.y < endPos.y; pos.y++) { for (pos.x = startPos.x; pos.x < endPos.x; pos.x++) { v2 rel_to_hex_pos = subV2(pos, hex_pos); if (absInt32(rel_to_hex_pos.x) < hexes.radius_in_pixels * (hexes.dimensions_in_pixels.y - absInt32(rel_to_hex_pos.y) * .5f) / hexes.dimensions_in_pixels.y) { pixels[v2ToV1(pos, window_dimensions_in_pixels.x)] = color; } } } }
int main(int32_t argc, char * argv) { srand(time(NULL)); void * game_memory = malloc(MEM); void * game_memory_pos = game_memory; assert(game_memory != NULL); HexShape hexes; hexes.radius_in_pixels = 20; // NOTE: This is 'radius' dimensions hexes.dimensions_in_pixels = mulVf2ByScalar((vf2){1, sqrt(3) * .5f}, hexes.radius_in_pixels); v2 window_dimensions_in_pixels = floorVf2(mulV2ByVf2((v2){24, 18}, hexes.dimensions_in_pixels)); vHex camera_position_in_hexes = {2,3}; SDL_Init(SDL_INIT_VIDEO); SDL_Window * window = SDL_CreateWindow("A Hex Game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_dimensions_in_pixels.x, window_dimensions_in_pixels.y, 0); SDL_Renderer * renderer = SDL_CreateRenderer(window, -1, 0); SDL_Texture * texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, window_dimensions_in_pixels.x, window_dimensions_in_pixels.y); // The pixel buffer uint32_t * pixels = (uint32_t *)game_memory_pos; game_memory_pos += window_dimensions_in_pixels.x * window_dimensions_in_pixels.y * sizeof(uint32_t); assert(game_memory_pos < game_memory + MEM); printf("Starting\n"); // For average FPS measurement uint64_t last_measure = get_us(); uint32_t frame_count = 0; // For FPS timing uint64_t last_frame = get_us(); uint32_t delta_frame; bool32 quit = false; SDL_Event event; while (!quit) { uint64_t now = get_us(); // Measure FPS if (now >= (last_measure + 1000000)) { // If last measurement was more than 1 sec ago last_measure = now; printf("%f us/frame\n", 1000000.0f / (double)frame_count); frame_count = 0; } // Render if (now >= last_frame + (1000000/FPS)) { delta_frame = now - last_frame; last_frame = now; frame_count++; // Clear screen to white v2 pixelPointer; for (pixelPointer.y = 0; pixelPointer.y < window_dimensions_in_pixels.y; pixelPointer.y++) { for (pixelPointer.x = 0; pixelPointer.x < window_dimensions_in_pixels.x; pixelPointer.x++) { pixels[v2ToV1(pixelPointer, window_dimensions_in_pixels.x)] = 0x00FFFFFF; } } // Draw Hexagons int32_t radius = 2; vHex hex_pos; for (hex_pos.q = 1-radius; hex_pos.q < radius; hex_pos.q += 1) { for (hex_pos.r = 1-radius; hex_pos.r < radius; hex_pos.r += 1) { if (absInt32(hex_pos.q + hex_pos.r) < radius) { uint32_t color; if (hex_pos.q == 0 && hex_pos.r == 0) { color = 0x00FF0000; } else { color = 0; } v2 hex_pixel_pos = floorVf2(mulVf2ByVf2( hexes.dimensions_in_pixels, hexToCart(addHexes(hex_pos, camera_position_in_hexes), hexes.radius_in_pixels) )); render_hex(hex_pixel_pos, pixels, hexes, window_dimensions_in_pixels, color); } } } // Flip pixels v2 pos; for (pos.y = 0; pos.y < window_dimensions_in_pixels.y / 2; pos.y++) { for (pos.x = 0; pos.x < window_dimensions_in_pixels.x; pos.x++) { uint32_t top_pixel = pixels[pos.y * window_dimensions_in_pixels.x + pos.x]; pixels[v2ToV1(pos, window_dimensions_in_pixels.x)] = pixels[(window_dimensions_in_pixels.y - pos.y - 1) * window_dimensions_in_pixels.x + pos.x]; pixels[(window_dimensions_in_pixels.y - pos.y - 1) * window_dimensions_in_pixels.x + pos.x] = top_pixel; } } SDL_UpdateTexture(texture, NULL, pixels, window_dimensions_in_pixels.x * sizeof(uint32_t)); SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } // Get inputs SDL_PollEvent(&event); if (event.type == SDL_QUIT) { quit = true; } else if (event.type == SDL_KEYDOWN) { if (event.key.keysym.sym == 'w' && event.key.keysym.mod == KMOD_LCTRL) { quit = true; } } } error("Quitting"); SDL_DestroyTexture(texture); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); free(game_memory); printf("Finished\n"); return 0; }