Lightning cosmetic on unlearned blueprint in radar

main
parent 8727b0f3f6
commit 170de8f748

@ -0,0 +1,4 @@
@Cosmetic - places where cosmetics could be added
@Robust - things to do to increase robustness of program
@BeforeShip - important things to handle before seriously shipping
no checkin - without the space between no and checkin, should never appear in commits, use a pre commit hook for this

@ -18,15 +18,15 @@
// Intensive profiling means profiling a lot of little tiny stuff. Not always enabled because tanks performance
#define INTENSIVE_PROFILING
// #define DEBUG_RENDERING
// #define DEBUG_WORLD
#define UNLOCK_ALL
#define DEBUG_WORLD
// #define UNLOCK_ALL
#define TIME_BETWEEN_WORLD_SAVE 1000000.0f
// #define TIME_BETWEEN_WORLD_SAVE 1.0f
// #define INFINITE_RESOURCES
#define DEBUG_TOOLS
#define CHIPMUNK_INTEGRITY_CHECK
// #define FAT_THRUSTERS
// #define NO_GRAVITY
#define NO_GRAVITY
// #define NO_SUNS
#else

Binary file not shown.

@ -352,7 +352,15 @@ static int sort_bodies_callback(const void *a, const void *b)
{
double a_dist = cpvdist(cpBodyGetPosition((cpBody *)a), from_point);
double b_dist = cpvdist(cpBodyGetPosition((cpBody *)b), from_point);
return (int)(a_dist - b_dist);
if (a_dist - b_dist < 0.0)
{
return -1;
}
else
{
return 1;
}
// return (int)(a_dist - b_dist);
}
LauncherTarget missile_launcher_target(GameState *gs, Entity *launcher)
@ -757,6 +765,14 @@ bool merge_box_is_merged(GameState *gs, Entity *merge_box)
return false;
}
}
bool could_learn_from_scanner(Player *for_player, Entity *box)
{
flight_assert(box->is_box);
flight_assert(box->box_type == BoxScanner);
return (for_player->box_unlocks | box->blueprints_learned) != for_player->box_unlocks;
}
bool box_interactible(GameState *gs, Player *for_player, Entity *box)
{
flight_assert(box->is_box);
@ -771,10 +787,6 @@ bool box_interactible(GameState *gs, Player *for_player, Entity *box)
{
return merge_box_is_merged(gs, box);
}
else if (box->box_type == BoxScanner)
{
return (for_player->box_unlocks | box->blueprints_learned) != for_player->box_unlocks;
}
else
{
return false;
@ -1286,6 +1298,7 @@ SerMaybeFailure ser_var(SerState *ser, char *var_pointer, size_t var_size, const
enum GameVersion
{
VInitial,
VNoGold,
VMax, // this minus one will be the version used
};
@ -1495,7 +1508,12 @@ SerMaybeFailure ser_entity(SerState *ser, GameState *gs, Entity *e)
SER_MAYBE_RETURN(ser_entityid(ser, &e->currently_inside_of_box));
SER_VAR(&e->squad_invited_to);
SER_MAYBE_RETURN(ser_f(ser, &e->goldness));
if (ser->version < VNoGold)
{
double goldness;
SER_VAR_NAME(&goldness, "&e->goldness");
}
}
SER_VAR(&e->is_explosion);
@ -2397,19 +2415,35 @@ void create_initial_world(GameState *gs)
create_bomb_station(gs, cpvadd(SUN_POS(3), cpv(0.0, 300.0)), BoxMerge);
#undef SUN_POS
#else
#if 0 // present the stations
Log("Creating debug world\n");
// pos, mass, radius
create_bomb_station(gs, (cpVect){-5.0, 0.0}, BoxExplosive);
create_bomb_station(gs, (cpVect){0.0, 5.0}, BoxGyroscope);
create_hard_shell_station(gs, (cpVect){-5.0, 5.0}, BoxCloaking);
#endif
#if 1 // scanner box
bool indestructible = false;
enum CompassRotation rot = Right;
{
Entity *grid = new_entity(gs);
grid_create(gs, grid);
entity_set_pos(grid, cpv(1.5, 0.0));
BOX_AT_TYPE(grid, cpv(0.0, 0.0), BoxExplosive);
BOX_AT_TYPE(grid, cpv(-BOX_SIZE, 0.0), BoxScanner);
BOX_AT_TYPE(grid, cpv(-BOX_SIZE, BOX_SIZE), BoxSolarPanel);
BOX_AT_TYPE(grid, cpv(-BOX_SIZE, BOX_SIZE * 2.0), BoxSolarPanel);
entity_ensure_in_orbit(gs, grid);
}
#endif
#if 0 // merge box
bool indestructible = false;
double theta = deg2rad(65.0);
cpVect from = (cpVect){BOX_SIZE * 4.0, -1};
enum CompassRotation rot = Right;
{
Entity *grid = new_entity(gs);
@ -2437,7 +2471,9 @@ void create_initial_world(GameState *gs)
cpBodySetVelocity(grid->body, (cpvspin((cpVect){-0.4, 0.0}, theta)));
entity_ensure_in_orbit(gs, grid);
}
#endif
#endif // grid tests
#endif // debug world
}
void exit_seat(GameState *gs, Entity *seat_in, Entity *p)
@ -2644,6 +2680,20 @@ void process(struct GameState *gs, double dt)
}
#endif
// general player logic
{
circle_query(gs->space, entity_pos(p), SCANNER_RADIUS);
QUEUE_ITER(&query_result, QueryResult, res)
{
Entity *maybe_scanner = cp_shape_entity(res->shape);
if (maybe_scanner->box_type == BoxScanner && could_learn_from_scanner(player, maybe_scanner))
{
player->box_unlocks |= maybe_scanner->blueprints_learned;
// @Cosmetic here
}
}
}
// process movement
{
// no cheating by making movement bigger than length 1

@ -0,0 +1,144 @@
@module lightning
@vs vs
in vec4 coord;
out vec2 texUV;
void main() {
gl_Position = vec4(coord.xy, 0.0, 1.0);
texUV = coord.zw;
}
@end
@fs fs
uniform uniforms {
float iTime;
};
in vec2 texUV;
out vec4 fragColor;
vec4 permute(vec4 t) {
return t * (t * 34.0 + 133.0);
}
// Gradient set is a normalized expanded rhombic dodecahedron
vec3 grad(float hash) {
// Random vertex of a cube, +/- 1 each
vec3 cube = mod(floor(hash / vec3(1.0, 2.0, 4.0)), 2.0) * 2.0 - 1.0;
// Random edge of the three edges connected to that vertex
// Also a cuboctahedral vertex
// And corresponds to the face of its dual, the rhombic dodecahedron
vec3 cuboct = cube;
int selected_edge =int(hash / 16.0) ;
if(selected_edge == 0)
cuboct.x = 0.0;
if(selected_edge == 1)
cuboct.y = 0.0;
if(selected_edge == 2)
cuboct.z = 0.0;
// In a funky way, pick one of the four points on the rhombic face
float type = mod(floor(hash / 8.0), 2.0);
vec3 rhomb = (1.0 - type) * cube + type * (cuboct + cross(cube, cuboct));
// Expand it so that the new edges are the same length
// as the existing ones
vec3 grad = cuboct * 1.22474487139 + rhomb;
// To make all gradients the same length, we only need to shorten the
// second type of vector. We also put in the whole noise scale constant.
// The compiler should reduce it into the existing floats. I think.
grad *= (1.0 - 0.042942436724648037 * type) * 3.5946317686139184;
return grad;
}
// BCC lattice split up into 2 cube lattices
vec4 bccNoiseDerivativesPart(vec3 X) {
vec3 b = floor(X);
vec4 i4 = vec4(X - b, 2.5);
// Pick between each pair of oppposite corners in the cube.
vec3 v1 = b + floor(dot(i4, vec4(.25)));
vec3 v2 = b + vec3(1, 0, 0) + vec3(-1, 1, 1) * floor(dot(i4, vec4(-.25, .25, .25, .35)));
vec3 v3 = b + vec3(0, 1, 0) + vec3(1, -1, 1) * floor(dot(i4, vec4(.25, -.25, .25, .35)));
vec3 v4 = b + vec3(0, 0, 1) + vec3(1, 1, -1) * floor(dot(i4, vec4(.25, .25, -.25, .35)));
// Gradient hashes for the four vertices in this half-lattice.
vec4 hashes = permute(mod(vec4(v1.x, v2.x, v3.x, v4.x), 289.0));
hashes = permute(mod(hashes + vec4(v1.y, v2.y, v3.y, v4.y), 289.0));
hashes = mod(permute(mod(hashes + vec4(v1.z, v2.z, v3.z, v4.z), 289.0)), 48.0);
// Gradient extrapolations & kernel function
vec3 d1 = X - v1; vec3 d2 = X - v2; vec3 d3 = X - v3; vec3 d4 = X - v4;
vec4 a = max(0.75 - vec4(dot(d1, d1), dot(d2, d2), dot(d3, d3), dot(d4, d4)), 0.0);
vec4 aa = a * a; vec4 aaaa = aa * aa;
vec3 g1 = grad(hashes.x); vec3 g2 = grad(hashes.y);
vec3 g3 = grad(hashes.z); vec3 g4 = grad(hashes.w);
vec4 extrapolations = vec4(dot(d1, g1), dot(d2, g2), dot(d3, g3), dot(d4, g4));
// Derivatives of the noise
vec3 derivative = -8.0 * mat4x3(d1, d2, d3, d4) * (aa * a * extrapolations)
+ mat4x3(g1, g2, g3, g4) * aaaa;
// Return it all as a vec4
return vec4(derivative, dot(aaaa, extrapolations));
}
// Gives X and Y a triangular alignment, and lets Z move up the main diagonal.
// Might be good for terrain, or a time varying X/Y plane. Z repeats.
vec4 bccNoiseDerivatives_XYBeforeZ(vec3 X) {
// Not a skew transform.
mat3 orthonormalMap = mat3(
0.788675134594813, -0.211324865405187, -0.577350269189626,
-0.211324865405187, 0.788675134594813, -0.577350269189626,
0.577350269189626, 0.577350269189626, 0.577350269189626);
X = orthonormalMap * X;
vec4 result = bccNoiseDerivativesPart(X) + bccNoiseDerivativesPart(X + 144.5);
return vec4(result.xyz * orthonormalMap, result.w);
}
void main()
{
vec2 uv = texUV;
vec2 p = uv;
uv = uv * 2. -1.;
float tickle = 0.001*1000*iTime;
vec3 offset = vec3(cos(tickle), sin(tickle), 0.0);
vec3 p3 = vec3(p, 0.0) + offset;
vec3 noise_input = vec3(p3*25.0+12.0);
//float intensity = noise(noise_input);
float intensity = 0.0;
intensity += bccNoiseDerivatives_XYBeforeZ(noise_input).w*0.4;
intensity += bccNoiseDerivatives_XYBeforeZ(noise_input*0.55).w*0.7;
intensity += bccNoiseDerivatives_XYBeforeZ(noise_input*0.44).w*0.8;
float t = clamp((uv.x * -uv.x * 0.16) + 0.15, 0., 1.);
//fragColor.rgb = vec3(t);
float dist = length(uv);
float y = abs(dist - 0.5 - intensity * 0.1);
float g = pow(y, 0.2);
vec3 col = vec3(1.50, 1.48, 1.78);
col = col * -g + col;
col = col * col;
col = col * col;
fragColor.rgb = col;
fragColor.a = (col.r + col.g + col.b)/3.0;
}
@end
@program program vs fs

@ -38,8 +38,10 @@
// shaders
#include "goodpixel.gen.h"
#include "hueshift.gen.h"
#include "lightning.gen.h"
static sg_pipeline hueshift_pipeline;
static sg_pipeline goodpixel_pipeline;
static sg_pipeline lightning_pipeline;
static struct GameState gs = {0};
static int my_player_index = -1;
@ -59,6 +61,7 @@ static cpVect mouse_pos = {0};
static bool fullscreened = false;
static bool picking_new_boxtype = false;
static double exec_time = 0.0; // cosmetic bouncing, network stats
static float iTime = 0.0; // fmodded to 1000, shader trick http://the-witness.net/news/2022/02/a-shader-trick/
// for network statistics, printed to logs with F3
static uint64_t total_bytes_sent = 0;
static uint64_t total_bytes_received = 0;
@ -618,6 +621,21 @@ static void init(void)
quit_with_popup("Couldn't make a shader! Uhhh ooooohhhhhh!!!", "Shader error BONED");
}
}
{
sgp_pipeline_desc pip_desc = {
.shader = *lightning_program_shader_desc(sg_query_backend()),
.blend_mode = SGP_BLENDMODE_BLEND,
};
lightning_pipeline = sgp_make_pipeline(&pip_desc);
sg_resource_state errstate = sg_query_pipeline_state(lightning_pipeline);
if (errstate != SG_RESOURCESTATE_VALID)
{
Log("Failed to make lightning pipeline\n");
quit_with_popup("Couldn't make a shader! Uhhh ooooohhhhhh!!!", "Shader error BONED");
}
}
}
// images loading
@ -734,6 +752,7 @@ static void draw_texture_centered(cpVect center, double size)
{
draw_texture_rectangle_centered(center, (cpVect){size, size});
}
static void draw_flipped_texture_rectangle_centered(cpVect center, cpVect width_height)
{
transform_scope()
@ -1469,6 +1488,7 @@ static void frame(void)
double width = (float)sapp_width(), height = (float)sapp_height();
double dt = sapp_frame_duration();
exec_time += dt;
iTime = (float)fmod(exec_time, 1000.0);
// pressed input management
{
@ -2116,6 +2136,20 @@ static void frame(void)
if (b->box_type == BoxScanner)
{
if (myplayer() != NULL && could_learn_from_scanner(myplayer(), b))
{
set_color(WHITE);
pipeline_scope(lightning_pipeline)
{
sgp_set_image(0, (sg_image){0});
lightning_uniforms_t uniform = {
.iTime = iTime,
};
sgp_set_uniform(&uniform, sizeof(uniform));
draw_color_rect_centered(entity_pos(b), BOX_SIZE*2.0);
sgp_reset_image(0);
}
}
sgp_set_image(0, image_scanner_head);
transform_scope()
{
@ -2301,21 +2335,25 @@ static void frame(void)
{
if (e != myentity() && has_point(centered_at(entity_pos(e), cpvmult(PLAYER_SIZE, player_scaling)), world_mouse_pos))
hovering_this_player = get_id(&gs, e);
if (get_entity(&gs, e->currently_inside_of_box) == NULL)
transform_scope()
{
rotate_at(entity_rotation(e), entity_pos(e).x, entity_pos(e).y);
set_color_values(1.0, 1.0, 1.0, 1.0);
pipeline_scope(hueshift_pipeline)
// the body
{
if (get_entity(&gs, e->currently_inside_of_box) == NULL)
transform_scope()
{
setup_hueshift(e->owning_squad);
sgp_set_image(0, image_player);
draw_texture_rectangle_centered(
entity_pos(e), cpvmult(PLAYER_SIZE, player_scaling));
sgp_reset_image(0);
rotate_at(entity_rotation(e), entity_pos(e).x, entity_pos(e).y);
set_color_values(1.0, 1.0, 1.0, 1.0);
pipeline_scope(hueshift_pipeline)
{
setup_hueshift(e->owning_squad);
sgp_set_image(0, image_player);
draw_texture_rectangle_centered(
entity_pos(e), cpvmult(PLAYER_SIZE, player_scaling));
sgp_reset_image(0);
}
}
}
}
}
// draw explosion

@ -5,4 +5,5 @@ IF %ERRORLEVEL% NEQ 0 ECHO ERROR download sokol-shdc from https://github.com/flo
@REM example of how to compile shaders: sokol-shdc.exe --input triangle.glsl --output triangle.gen.h --slang glsl330:hlsl5:metal_macos
sokol-shdc.exe --format sokol --input hueshift.glsl --output hueshift.gen.h --slang glsl330:hlsl5:metal_macos
sokol-shdc.exe --format sokol --input lightning.glsl --output lightning.gen.h --slang glsl330:hlsl5:metal_macos
sokol-shdc.exe --format sokol --input goodpixel.glsl --output goodpixel.gen.h --slang glsl330:hlsl5:metal_macos

@ -278,8 +278,7 @@ typedef struct Entity
enum Squad owning_squad; // also controls what the player can see, because of cloaking!
EntityID currently_inside_of_box;
enum Squad squad_invited_to; // if squad none, then no squad invite
double goldness; // how much the player is a winner
// explosion
bool is_explosion;
cpVect explosion_pos;
@ -496,6 +495,7 @@ EntityID get_id(struct GameState *gs, Entity *e);
cpVect entity_pos(Entity *e);
bool box_interactible(GameState *gs, Player *for_player, Entity *box);
void entity_set_rotation(Entity *e, double rot);
bool could_learn_from_scanner(Player *for_player, Entity *box);
void entity_set_pos(Entity *e, cpVect pos);
double entity_rotation(Entity *e);
void entity_ensure_in_orbit(GameState *gs, Entity *e);

Loading…
Cancel
Save