This one page piece of code entirely governs your typical game "spinning collectable animating thing that flies off the screen often before you can shoot it" thing. It launches various felix threads, for animating, checking shots and plotting the gravity parabola. Originally I used a boolean that I passed to the various threads asking them to exit, but it was too easy to forget to check and honour the request, leaving hanging fthreads. I decided instead to try to take advantage of the garbage collector/sync channel property that makes fthreads go away when there's no-one there to pick up their messages. It's still not quite right - I currently write either a type of event or an event that works in lieu of the sleeps I used to use, however not all my sleep events seem to arrive (hence the NOTHING and NOTHING2 hacks you see). And if it were working there would be the problem that to implement the old sleep you need to know how man fthreads were out there to know how many sleeps to await before actually sleeping in the main fthread. My driver itself cheats in this respect, using an schannel with some c code that reschedules every fthread hanging on an schannel, as though you executed a "read n times, discarding result". Um. So in conclusion, I think I'm close to a nice clean robust design for this kind of thing, but not quite. Any suggestions?
RF p.s. I typedefef the schannel[event_type] thing, but that doesn't seem to create the associated constructor (mk_mynewname()), I can use the new name but I still have to remember the original type, saying var blah = mk_schannel[event_type]();... Is there some other name I can do or do I just have to remember or define a new ctor along with the typedef? proc new_ammo2 { var amr: shoot_spr_rec; var ammo = shoot_spr(amr); // don't know how to invoke constructor of a typedef... have to remember // actual type: var chan = mk_schannel[ammo_evt] (); //var chan = mk_ammo_chan(); // error set_field(ammo, FOREGROUND); // set field before appending append_shoot_spr ammo ; make_shootable ammo; var running = true; var r0: dpoint; var v0: dpoint; lt_launch_params(r0, v0); val animate = { while{ running } { var an = mk_animplay(ammo, AMMO_ANIM); run_anim(an, ammo); set_pos(an, ammo, 0); }; print "anim exits\n"; }; spawn_fthread{ animate; }; spawn_fthread{ launch_arc(ammo, r0, v0, chan); print "arc exits\n"; }; spawn_fthread{ wait_shot(ammo, chan); }; keepgoing:> snooze 1; var &et : ammo_evt <- read chan; match et with | OFFSCREEN => { print "OFFSCREEN\n"; } | SHOT => { print "SHOT\n"; } | NOTHING2 => { print "read NOTH2\n"; goto keepgoing; } | NOTHING => { print "read NOTH\n"; goto keepgoing; } endmatch; running = false; // make anim exit remove_shoot_spr ammo; print "FINISHED\n"; } union ammo_evt = | OFFSCREEN // went offscreen | SHOT // got shot | NOTHING2 | NOTHING // to implement idling? ; typedef ammo_chan = schannel[ammo_evt]; proc launch_arc[typez](spr: typez, r0: dpoint, v0: dpoint, chan: ammo_chan) { var t = 0; var T: double; forever { T = double_of(t)/TPS; t++; var pt = fall_equ(r0, v0, T); set_spr_pos(spr, pt); write(chan, NOTHING); // in lieu of snooze fun offscreen(): bool => (pt.y > SCRN_HIGH+30 and (v0.y - GRAV_ACC*T) > 0.0); if(offscreen()) goto fin; }; fin:> write(chan, OFFSCREEN); } proc wait_shot(sp: shoot_spr, chan: ammo_chan) { while{ not (get_shot sp) } { write(chan, NOTHING2); }; write(chan, SHOT); } ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language