/apps/examples/circle-raster: simple code for grid-centered circle rasterization
This commit is contained in:
		
							
								
								
									
										16
									
								
								apps/examples/circle-raster/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								apps/examples/circle-raster/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| cmake_minimum_required(VERSION 3.21) | ||||
|  | ||||
| project(circle-raster LANGUAGES C) | ||||
|  | ||||
| if(NOT CMAKE_BUILD_TYPE) | ||||
|         set(CMAKE_BUILD_TYPE Debug) | ||||
| endif() | ||||
|  | ||||
| add_subdirectory($ENV{TWNROOT} $ENV{TWNROOT}/build) | ||||
|  | ||||
| set(SOURCE_FILES | ||||
|         game.c | ||||
|         state.h | ||||
| ) | ||||
|  | ||||
| use_townengine(${PROJECT_NAME} "${SOURCE_FILES}" ${CMAKE_CURRENT_SOURCE_DIR}) | ||||
							
								
								
									
										26
									
								
								apps/examples/circle-raster/data/twn.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								apps/examples/circle-raster/data/twn.toml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| # This file contains everything about the engine and your game that can be | ||||
| # configured before it runs. | ||||
| # | ||||
| # Optional settings are commented out, with their default values shown. | ||||
| # Invalid values in these settings will be ignored. | ||||
|  | ||||
| # Data about your game as an application | ||||
| [about] | ||||
| title = "Template" | ||||
| developer = "You" | ||||
| app_id = "template" | ||||
| dev_id = "you" | ||||
|  | ||||
| # Game runtime details | ||||
| [game] | ||||
| resolution = [ 640, 480 ] | ||||
| #debug = true | ||||
|  | ||||
| # Engine tweaks. You probably don't need to change these | ||||
| [engine] | ||||
| #ticks_per_second = 60 # minimum of 8 | ||||
| #keybind_slots = 3 # minimum of 1 | ||||
| #texture_atlas_size = 2048 # minimum of 32 | ||||
| #font_texture_size = 2048 # minimum of 1024 | ||||
| #font_oversampling = 4 # minimum of 0 | ||||
| #font_filtering = "linear" # possible values: "nearest", "linear" | ||||
							
								
								
									
										54
									
								
								apps/examples/circle-raster/game.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								apps/examples/circle-raster/game.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| #include "twn_game_api.h" | ||||
| #include "state.h" | ||||
|  | ||||
| #include <malloc.h> | ||||
| #include <math.h> | ||||
|  | ||||
|  | ||||
| /* Emits `x` and `y` for every intersecting cell */ | ||||
| /* We snap position to the nearest corner, which means there's no aliasing */ | ||||
| /* It works great for integer radii */ | ||||
| #define m_iter_circle_pixels(p_center_x, p_center_y, p_radius) \ | ||||
|     for (float y = (p_center_y + ceilf(p_radius)) - 1; y > (p_center_y - ceilf(p_radius)) - 1; --y) \ | ||||
|         for (float x = p_center_x - ceilf(sqrtf(p_radius * p_radius - (y - p_center_y + (y <= p_center_y)) * (y - p_center_y + (y <= p_center_y)))); x < p_center_x + ceilf(sqrtf(p_radius * p_radius - (y - p_center_y + (y <= p_center_y)) * (y - p_center_y + (y <= p_center_y)))); ++x) | ||||
|  | ||||
|  | ||||
| void game_tick(void) { | ||||
|     if (ctx.initialization_needed) { | ||||
|         if (!ctx.udata) { | ||||
|             ctx.udata = ccalloc(1, sizeof (struct state)); | ||||
|             struct state *state = ctx.udata; | ||||
|             state->r = 10; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     struct state *state = ctx.udata; | ||||
|  | ||||
|     Vec2 const mouse_snap = {floorf(ctx.mouse_position.x / 8) * 8, floorf(ctx.mouse_position.y / 8) * 8}; | ||||
|  | ||||
|     input_action("up", CONTROL_LEFT_MOUSE); | ||||
|     input_action("down", CONTROL_RIGHT_MOUSE); | ||||
|  | ||||
|     if (input_action_just_pressed("up")) | ||||
|         state->r += 1; | ||||
|     if (input_action_just_pressed("down")) | ||||
|         state->r -= 1; | ||||
|  | ||||
|     float const rs = state->r * state->r; | ||||
|     float const cr = ceilf(state->r); | ||||
|     for (float iy = cr - 1; iy > -cr - 1; --iy) { | ||||
|         float const dx = ceilf(sqrtf(rs - (iy + (iy <= 0)) * (iy + (iy <= 0)))); | ||||
|         for (float ix = -dx; ix < dx; ++ix) { | ||||
|             draw_box((Rect){mouse_snap.x + ix * 8, mouse_snap.y + iy * 8, 8, 8}, 1, (Color){255, 0, 0, 125}); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     draw_circle(mouse_snap, state->r * 8, (Color){125, 125, 125, 125}); | ||||
| } | ||||
|  | ||||
|  | ||||
| void game_end(void) { | ||||
|     /* do your deinitialization here */ | ||||
|     struct state *state = ctx.udata; | ||||
|     free(state); | ||||
| } | ||||
							
								
								
									
										11
									
								
								apps/examples/circle-raster/state.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								apps/examples/circle-raster/state.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #ifndef STATE_H | ||||
| #define STATE_H | ||||
|  | ||||
| #include "twn_game_api.h" | ||||
|  | ||||
| struct state { | ||||
|     float r; | ||||
| }; | ||||
|  | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user