Posted By: EvilSOB
Lightning-Strike Generator. - 07/31/09 04:18
Heres another little something Ive put together, a LIGHTING BOLT generator.
Ever needed a genuinely random, 3D lightning-strike from point A to boint B?
With variable thickness, color, and complexity? And with a cool glowing after-image? (retina-burn)
Ever wanted that "beautiful" bolt to be repeatable at a later time?
Now you can with a single function call.
Comes as a complete DEMO main.c with no necessary additional files. Plenty of included documentation.
Once again, any suggestions, questions, or instructional issues, just let me know...
[EDIT] NOW BUGFIXED FOR A7 Ver 7.82.2 !!
For historical purposes, here is Version 2.0. Its the same as 2.1, just doesnt allow control over the color of the after-image 'flare'.
Also historical purposes, here is Ye-Olde Version 1.0. Much simpler code.
Its basically the same as 2.0, but doesnt allow ANY control over the after-image 'flare'.
Ever needed a genuinely random, 3D lightning-strike from point A to boint B?
With variable thickness, color, and complexity? And with a cool glowing after-image? (retina-burn)
Ever wanted that "beautiful" bolt to be repeatable at a later time?
Now you can with a single function call.
Comes as a complete DEMO main.c with no necessary additional files. Plenty of included documentation.
Once again, any suggestions, questions, or instructional issues, just let me know...
[EDIT] NOW BUGFIXED FOR A7 Ver 7.82.2 !!
Code:
#include <acknex.h> #include <default.c> // // ////////////////////////////////////////////////////////////////////////////////////////// // 3D-LIGHTNING-BOLT-SPAWN 2.1 // // --------------------------- // // // // Author : EvilSOB // // Date : 31-07-2009 // // Updated : 06-04-2010 (7.82.2 bugfix) // // // ////////////////////////////////////////////////////////////////////////////////////////// //LB_spawn(VECTOR*Start,VECTOR*Finish,Div,Branch,Depth,Size,COLOR*Core,COLOR*Flare,FlareTime,Seed)// //--------------------------------------------------------------------------------------// // Parameters:: // // Start = Start Vector of Lightning Bolt (sky) // // Finish = Target Vector of Lightning Bolt (ground) // // Div = Number of primary "segments" in central bolt (suggest 5->20)// // Branch = 0.0->1.0 chance to "branch" at primary segment point.(suggest 0.4) // // Depth = depth of complexity to calculate into branches. (suggest 4) // // Size = diameter in quants of "core" bolt. (suggest 8) // // Core = color of lightning "bolt" (suggest 255,128,128)// // Flare = color of lightning-bolt 'afterimage' (suggest 128, 0, 0)// // FlareTime= duration in seconds of 'afterimage' (suggest 1.5) // // Seed = random number seed (for forcing duplicates) (suggest 0) // // // // NOTES : "Flare" = NULL or nullvector will suppress the "afterimage" generation. // // "Seed" = Zero is random, set to "any" number will generate duplicate stikes// // "Div" = !Be cautious with Divisions above 20, it can be a real FPS eater! // // "Depth" = !Be cautious with the depth above 3, it can be a real FPS eater! // // // ////////////////////////////////////////////////////////////////////////////////////////// // Example:: // // LB_spawn(me.x, you.x, 15, 0.4, 4, 8, vector(255,128,128), vector(180,0,0), 0); // // // ////////////////////////////////////////////////////////////////////////////////////////// // // // void LB_segment_fade(PARTICLE* p) { p.lifespan = p.alpha -= time_step*p.skill_x; } // void LB_segment_core(PARTICLE* p) { vec_set(p.blue, you.skill3); set(p, BEAM|BRIGHT|TRANSLUCENT|UNLIT|CAST); p.alpha = 100; p.size = you.skill2; p.skill_x = 20; p.event = LB_segment_fade; } // void LB_segment_flare(PARTICLE* p) { vec_set(p.blue, you.skill6); set(p, BEAM|BRIGHT|TRANSLUCENT|UNLIT|CAST); p.alpha = 20; p.size = you.skill2*2; p.skill_x = 1.28/you.skill7; p.event = LB_segment_fade; } // void LB_divide(VECTOR* A, VECTOR* B, long Div, float noise, VECTOR** Points) { VECTOR *points = (VECTOR*)malloc(sizeof(VECTOR)*Div); if(!Points) free(*Points); *Points = points; var idx; for(idx=0; idx<Div; idx++) { vec_lerp(points[idx], A, B, (float)idx/(Div-1)); if((idx>0)&&(idx<(Div-1))) { points[idx].x += random(noise*2)-noise; points[idx].y += random(noise*2)-noise; points[idx].z += random(noise)-noise/2; } } } // // void LB_spawn(VECTOR* Start, VECTOR* Finish, long Div, float Branch, long Depth, long Size, COLOR* Core, COLOR* Flare, float FlareTime, var Seed) { if(Div<3) return; if(!Seed) Seed = timer(); VECTOR A, B, C, D, tmpV, corec, flarec, *fine=0, *crude=0; vec_zero(flarec); vec_set(A, Start); vec_set(B, Finish); vec_set(corec, Core); if(Flare) vec_set(flarec, Flare); wait(1); long i, cnt, seg_size = vec_dist(A,B)/Div; random_seed(Seed); LB_divide(A, B, Div, vec_dist(A,B)/(Div+1), crude); me = ent_create(NULL, NULL, NULL); me.skill2 = Size; vec_set(me.skill3, corec); vec_set(me.skill6, flarec); me.skill7 = FlareTime; for(i=1; i<Div; i++) { LB_divide(crude[i-1],crude[i],Div/2,vec_dist(crude[i-1],crude[i])/Div/2+1,fine); for(cnt=1; cnt<(Div/2); cnt++) { vec_set(tmpV, fine[cnt]); vec_sub(tmpV, fine[cnt-1]); if(vec_length(tmpV)) vec_scale(tmpV, vec_length(tmpV)/vec_length(tmpV)); if(vec_length(flarec)) effect(LB_segment_flare, 1, fine[cnt-1], tmpV); effect(LB_segment_core, 1, fine[cnt-1], tmpV); } if((Depth>1)&&(random(1)<Branch)&&(i<(Div-1))) { vec_diff(C, crude[i], crude[i-1]); vec_diff(D, crude[i], crude[i+1]); vec_lerp(tmpV, D, C, random(1)+0.35); vec_normalize(tmpV, random(seg_size*(Div-i))*0.6); vec_add(tmpV,crude[i]); LB_spawn(crude[i], tmpV, Div*0.6, Branch, Depth-1, Size*0.6, corec, flarec, FlareTime, Seed+random(15)); } } wait(1); ent_remove(me); free(crude); free(fine); } // // ////////////////////////////////////////////////////////////////////////////////////////// // // ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // Remaining code is for DEMO purposes only. // ////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////// // // VECTOR FromPoint, ToPoint; var strike() { LB_spawn(FromPoint, ToPoint, 20, 0.7, 7, 8, vector(255,128,128), vector(180,0,0), 1.5, 00); } var arcing() { var last_key = key_lastpressed; while(key_pressed(last_key)) { LB_spawn(FromPoint, ToPoint, 13, 0.6, 3, 13, vector(255,128,128), vector(128,0,0), 1, 0); wait(-0.07); } } // // function main() { max_entities = 10000; level_load(NULL); wait(2); diag("\n\n\n"); vec_set(sky_color, vector(1,1,1)); vec_set(camera.x, vector(-700,0,255)); // vec_set(FromPoint, vector(0,0,500)); vec_set(ToPoint, vector(0,100,0)); on_space = strike; on_enter = arcing; // // strike(); while(1) { draw_text(_str("Hit SPACEBAR for Lightning Strike!"), 10, 10, NULL); draw_text(_str("Hold ENTER for an Elecrical Arc!"), 10, 30, NULL); draw_point3d(FromPoint, vector(255,200,200), 100, 10); draw_point3d(ToPoint, vector(255,200,200), 100, 10); wait(1); } // sys_exit(""); }
For historical purposes, here is Version 2.0. Its the same as 2.1, just doesnt allow control over the color of the after-image 'flare'.
Click to reveal..
Also historical purposes, here is Ye-Olde Version 1.0. Much simpler code.
Its basically the same as 2.0, but doesnt allow ANY control over the after-image 'flare'.
Click to reveal..