0%æÑц†‘yGeõázíÃ̆Êe~9Ô¹¼Ò„«h`†À…~§ˆVxdöö¿ 0ÿÿÿÿÿÿÿÿ2Tv˜ºÜþïÍ«‰gE#2Tv˜ºÜþ2Tv˜ºÜþ@™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™À?™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™ ™™™™ 0333™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™033333™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™ ™™ 333333™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™ ™™03333333™™™fff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ 33333333™™ fffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ 33333333™™`ffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™0333333333 fffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™0333333333`ffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™0333333333`ffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™0333333333fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™0333333333fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™ ™0333333333fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™™™ ™0333333333fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ 33333333 fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ ™™™™™™ 33333333 fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ PUUU™™™™™@DDD03333333 fffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™PUUUU™™™DDDD333333™™`ffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ UUUUUUDDDDDD033333`ffffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™™™™™PUUUUUUU™@DDDDDD0333ˆˆˆfffffff™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ UUUUUUUU DDDDDDDDˆˆˆˆˆ`ffffff™™™™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™™ ffff™™™™ UUUUUUUU DDDDDDDD™ ˆˆˆˆˆˆfffff™™™ ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™™ `fffffff™™™PUUUUUUUUU@DDDDDDDDD€ˆˆˆˆˆˆˆfff™™™™ ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™ `fffffffff™™PUUUUUUUUU@DDDDDDDDDˆˆˆˆˆˆˆˆ™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™™`fffffffffff™PUUUUUUUUU@DDDDDDDDDˆˆˆˆˆˆˆˆ™™ ™™™™™™™ ™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™ ffffffffffff™PUUUUUUUUU@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ™™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™™`fffffffffffffPUUUUUUUUU@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ™™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™ ffffffffffffffPUUUUUUUUU@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™™`fffffffffffffffPUUUUUUUUU@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™ ffffffffffffffffUUUUUUUU DDDDDDDD€ˆˆˆˆˆˆˆˆˆ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™ ffffffffffffffffUUUUUUUU DDDDDDDD€ˆˆˆˆˆˆˆˆˆ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™`fffffffffffffffffPUUUUUUU™@DDDDDDD€ˆˆˆˆˆˆˆˆˆ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™™`fffffffffffffffffUUUUUU™™ DDDDDD™ ˆˆˆˆˆˆˆˆ™ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™™™™™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffffPUUUUU™™™@DDDDD™ ˆˆˆˆˆˆˆˆ™ ™™™™™™™™™ €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™ ™™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffff PUUU™™™™ @DDD™™™€ˆˆˆˆˆˆˆ™™™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™ €ˆˆˆ™™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffff™ ™™™™ ™™ ˆˆˆˆˆˆ™™™™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™€ˆˆˆˆˆ™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffff™www™™™™DDD™™€ˆˆˆˆˆ™™™ ™™™™™™™ ™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™ ˆˆˆˆˆˆ™™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffff wwwww™™™ DDDDD™™ €ˆˆˆ™™™™™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™€ˆˆˆˆˆˆˆ™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffffpwwwwww™™@DDDDDD™™ ™™™™ ™™™™™ ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆ™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffffwwwwwww™ DDDDDDD™™™333™™™™™™™ ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆ™™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffffpwwwwwwww@DDDDDDDD™ 33333™™™™™™™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`fffffffffffffffffffpwwwwwwww@DDDDDDDD™0333333™™™ªªª ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™™™™™™™™™ÀÌÌÌÌ™™™™™™™™™™`ffffffffffffffffffwwwwwwwwwDDDDDDDDD 3333333™™ ªªªªª ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™ÀÌÌÌÌ™™™™™™™™™™`ffffffffffffffffffwwwwwwwwwDDDDDDDDD033333333™ ªªªªªª™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™@DDDDDDÀÌÌÌÌ™™™™™™™™™™`ffffffffffffffffffwwwwwwwwwDDDDDDDDD033333333 ªªªªªªª ™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™@DDDDDDÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffffwwwwwwwwwDDDDDDDDD333333333 ªªªªªªªª€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™@DDDDDDÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffffwwwwwwwwwDDDDDDDDD333333333 ªªªªªªªª€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆ™@DDDDDDÀÌÌÌÌ™™™™™™™™™™ ffffffffffffffffffwwwwwwwwwDDDDDDDDD333333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆ™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™`fffffffffffffffffwwwwwwwwwDDDDDDDDD333333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆ™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™`fffffffffffffffffpwwwwwwww@DDDDDDDD333333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™€ˆˆˆˆˆˆˆ™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™ ffffffffffffffff™pwwwwwwww@DDDDDDDD333333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™ ˆˆˆˆˆˆ™™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™ ffffffffffffffff™ wwwwwww™ DDDDDDD 333333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™€ˆˆˆˆˆ™™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™™`fffffffffffffff™™pwwwwww™™@DDDDDD™033333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™ €ˆˆˆ™™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™™ ffffffffffffff™™™ wwwww DDDDD033333333ªªªªªªªªª €ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™ ww™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™™™`fffffffffffff™www033DDD@DD3333333™ ªªªªªªªª€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™ wwwww™@DDDDDDÀÌÌÌÌ™™™™™™™™™™™™™ ffffffffffffˆˆˆ™03333™@DDDD0333333™ ªªªªªªªª€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™™pwwwwww@DDDDDDÀÌÌÌÌ™™™™™™™™™™™™™™`ffffffffffˆˆˆˆˆ™™™0333333™™@DDDDD33333™™ ªªªªªªª ™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™ wwwwwwwÀÌÌÌÌ™™™™™™™™™™™™™™ `fffffffff€ˆˆˆˆˆˆ™ 3333333™ DDDDDDD333™ ªªªªªª™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™pwwwwwwwwÀÌÌÌÌ™™™™™™™™™™™™™™™ `fffffffˆˆˆˆˆˆˆ™033333333@DDDDDDDD ªªª ªªªªª ™™€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ™™™pwwwwwwww°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™ ffff€ˆˆˆˆˆˆˆˆ033333333@DDDDDDDD™ ªªªªªªªª ™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™€ˆˆˆˆˆˆˆˆ333333333DDDDDDDDD ªªªªªª ™PUUU™™™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDD ªªªªªªª™™PUUUUU™™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDDªªªªªªªª ™ UUUUUU™™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDDªªªªªªªª ™PUUUUUUU™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDDªªªªªªªªªUUUUUUUU™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDDªªªªªªªªªUUUUUUUU™™™™™™™™™™™™™™™™™™™ wwwwwwwww»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ333333333DDDDDDDDDªªªªªªªªªPUUUUUUUUU™™™™™™™™™™™™™™™™™™™pwwwwwwww°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆˆˆ033333333@DDDDDDDD ªªªªªªªªªPUUUUUUUUU™™™™™™™™™™™™™™™™™™™pwwwwwwww°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™€ˆˆˆˆˆˆˆˆ033333333@DDDDDDDD ªªªªªªªªªPUUUUUUUUU™™™™™™™™™™™™™™™™™™™ wwwwwww°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™€ˆˆˆˆˆˆˆˆ 3333333™ DDDDDDD ªªªªªªªªªPUUUUUUUUU™™™™™™™™™™™™™™™™™™™™pwwwwww°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™ ˆˆˆˆˆˆˆ™™0333333™™@DDDDDD ªªªªªªªªªPUUUUUUUUU™™™™™™™™™™™™™™™™™™™™ wwwww™°»»»»»»ÀÌÌÌÌ™™™™™™™™™™™™™™™™™™™™™™™™™€ˆˆˆˆˆˆ™™ 33333™™™ DDDDD™ ªªªªªªªª PUUUUUUUUU™™™™™™™™™ ™™™™™™™™www™ÀÌÌÌÌ™™™ ™™™™™™™™™™™™ˆˆˆˆˆ™333™DDD™ ªªªªªªªª PUUUUUUUUU™™™™™ €ˆˆˆ™™™™™ ™™™™™™ÀÌÌÌÌ™™ PUUU™™™™ˆˆˆ™™™™ÌÌ̈ˆˆwww™DDD™™™ ªªªªªªª UUUUUUUU@DDD™™™™€ˆˆˆˆˆ™™™ €ˆˆˆ™™™™ÌÌÌ ™™ÀÌÌÌÌ™™PUUUUU™™ ˆˆˆˆˆ™™™ ÌÌÌÌÌ wwwww™™™ DDDDD™™™™™™ ªªªªªª ™ UUUUUUUUDDDDD™™ ˆˆˆˆˆˆ™™™€ˆˆˆˆˆ™™ ÌÌÌÌÌ ™™ÀÌÌÌÌ™ UUUUUU™™€ˆˆˆˆˆˆ™™ÀÌÌÌÌÌÌ™™pwwwwww™™@DDDDDD™™™™™™ ªªªªª™™PUUUUUUU@DDDDD™™€ˆˆˆˆˆˆˆ™ ˆˆˆˆˆˆ™™ÀÌÌÌÌÌÌ™ÀÌÌÌÌ™PUUUUUUU ˆˆˆˆˆˆˆ™ ÌÌÌÌÌÌÌ ™ wwwwwww™ DDDDDDD™™™™™™  ªªª™™™ UUUUUUDDDDDDD ˆˆˆˆˆˆˆˆ™€ˆˆˆˆˆˆˆ ÌÌÌÌÌÌÌ ™ÀÌÌÌÌ UUUUUUUU€ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌpwwwwwwww@DDDDDDDDPUUUUU@DDDDDDD ˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌÀÌÌÌÌ UUUUUUUU€ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌpwwwwwwww@DDDDDDDDDDDDDD0333333 PUUUDDDDDDDD€ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™ @DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDD€ˆˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌPUUUUUUUUU€ˆˆˆˆˆˆˆˆÌÌÌÌÌÌÌÌÌ wwwwwwwwwDDDDDDDDDDDDDDD0333333™™™™™@DDDDDDDDDˆˆˆˆˆˆˆˆ€ˆˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌ ÀÌÌÌÌ UUUUUUUU€ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌpwwwwwwww@DDDDDDDDDDDDDD0333333™™™™™ DDDDDDDD ˆˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌÀÌÌÌÌ UUUUUUUU€ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌpwwwwwwww@DDDDDDDDDDDDDD0333333™™™™™ DDDDDDDD™€ˆˆˆˆˆˆˆ ˆˆˆˆˆˆˆˆÀÌÌÌÌÌÌÌÌÀÌÌÌÌ™PUUUUUUU ˆˆˆˆˆˆˆ™ ÌÌÌÌÌÌÌ ™ wwwwwww™ DDDDDDD DDDDDD0333333™™™™™™@DDDDDDD™ ˆˆˆˆˆˆ™™€ˆˆˆˆˆˆˆ ÌÌÌÌÌÌÌ ™ÀÌÌÌÌ™ UUUUUU™™€ˆˆˆˆˆˆ™™ÀÌÌÌÌÌÌ™™pwwwwww™™@DDDDDD DDDDDD0333333™™™™™™ DDDDDD™™™€ˆˆˆˆˆ™™ ˆˆˆˆˆˆ™™ÀÌÌÌÌÌÌ™ÀÌÌÌÌ™™PUUUUU™™ ˆˆˆˆˆ™™™ ÌÌÌÌÌ ™™™ wwwww™™™ DDDDD™ DDDDDD0333333™™™™™™™@DDDDD™™™ €ˆˆˆ™™™™€ˆˆˆˆˆ™™ ÌÌÌÌÌ ™™ÀÌÌÌÌ™™ PUUU™™™™ˆˆˆ™™™™ÌÌÌ ™™™™www™™™™DDD™ ™™™™™™™ @DDD™™™™™ ™™™™™ €ˆˆˆ™™™™ÌÌÌ ™™ÀÌÌÌÌÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUÀÌÌÌÌÉ7-- title: Unoptimised Physics -- author: TylerDurden -- desc: I can't, for the love of God, optimize this -- license: MIT License (change this to your license of choice) -- version: 1.0 -- script: lua ---------------------- -- 2D Vector library vector={}vector.__index=vector;setmetatable(vector,{__call=function(a,...)return a.new(...)end})function vector.new(b,c)local self=setmetatable({},vector)self.x=b or 0;self.y=c or 0;return self end;function vector:__tostring()return string.format("(%s,%s)->%s",self.x,self.y,self:mag())end;function vector.isvector(d)return getmetatable(d)==vector end;function vector.lerp(e,f,g)local function h(i,j,k)return(1-k)*i+k*j end;return vector(h(e.x,f.x,g),h(e.y,f.y,g))end;function vector.fromAngle(l)return vector(math.cos(l),-math.sin(l))end;function vector.random()return vector.fromAngle(math.random()*math.pi*2)end;function vector:set(b,c)self.x=b;self.y=c end;function vector:__add(d)assert(vector.isvector(d),'Wrong type, expected a vector')return vector(self.x+d.x,self.y+d.y)end;function vector:__sub(d)assert(vector.isvector(d),'Wrong type, expected a vector')return vector(self.x-d.x,self.y-d.y)end;function vector:__mul(d)if type(d)=='number'then return vector(self.x*d,self.y*d)end;assert(vector.isvector(d),'Wrong type, expected a vector or a number')return vector(self.x*d.x,self.y*d.y)end;function vector:__div(d)assert(type(d)=='number','Wrong type, expected a number')return vector(self.x/d,self.y/d)end;function vector:__eq(d)assert(vector.isvector(d),'Wrong type, expected a vector')return self.x==d.x and self.y==d.y end;function vector:__unm()return vector(-self.x,-self.y)end;function vector:dist(d)assert(vector.isvector(d),'Wrong type, expected a vector')local m=self.x-d.x;local n=self.y-d.y;return math.sqrt(m*m+n*n)end;function vector:normal()return vector(-self.y,self.x)end;function vector:dot(d)assert(vector.isvector(d),'Wrong type, expected a vector')return self.x*d.x+self.y*d.y end;function vector.cross(e,f)return e.x*f.y-e.y*f.x end;function vector:replace(d)assert(vector.isvector(d),'Wrong type, expected a vector')self.x=d.x;self.y=d.y end;function vector:clone()return vector(self.x,self.y)end;function vector:mag(o)if o then assert(type(o)=='number','Wrong type, expected a number')return self:normalize()*o else return math.sqrt(self.x*self.x+self.y*self.y)end end;function vector:magSq()return self.x*self.x+self.y*self.y end;function vector:normalize()local p=self:mag()local q=self:clone()if p~=0 then q=q/p end;return q end;function vector:limit(r)assert(type(r),'Wrong type, expected a number')local p=self:mag()local d=self:clone()if p>r*r then d=d:mag(r)end;return d end;function vector:clamp(s,r)assert(vector.isvector(s)and vector.isvector(r),'Wrong type, expected a number')local b=math.min(math.max(self.x,s.x),r.x)local c=math.min(math.max(self.y,s.y),r.y)return vector(b,c)end;function vector:heading()local l=math.atan2(self.y,-self.x)return math.pi-l end;function vector:head(l)local o=self:mag()local d=vector.fromAngle(l)d=d:mag(o)return d end;function vector:rotate(l)local t=math.sin(l)local a=math.cos(l)local d=vector(a*self.x+t*self.y,-(t*self.x)+a*self.y)return d end;function vector:rotateAround(u,l)local v=vector(math.cos(-l),math.sin(-l))local w=self-u;local d=vector(w.x*v.x-w.y*v.y,w.x*v.y+w.y*v.x)return d+u end;function vector.project(d,x)local y=vector()y.x=(d.x*x.x+d.y*x.y)/(x.x*x.x+x.y*x.y)*x.x;y.y=(d.x*x.x+d.y*x.y)/(x.x*x.x+x.y*x.y)*x.y;return y end;function vector:array()return{self.x,self.y}end;function vector:unpack(d)return self.x,self.y end ---------------------- ---------------------- -- Input Helper input={keycodes={a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9,j=10,k=11,l=12,m=13,n=14,o=15,p=16,q=17,r=18,s=19,t=20,u=21,v=22,w=23,x=24,y=25,z=26,[0]=27,[1]=28,[2]=29,[3]=30,[4]=31,[5]=32,[6]=33,[7]=34,[8]=35,[9]=36,minus=37,equals=38,leftbracket=39,grave=44,rightbracket=40,backslash=41,semicolon=42,apostrophe=43,comma=45,period=46,slash=47,space=48,tab=49,['return']=50,backspace=51,delete=52,insert=53,pageup=54,pagedown=55,home=56,['end']=57,up=58,down=59,left=60,right=61,capslock=62,ctrl=63,shift=64,alt=65,mouse1='mouse1',mouse2='mouse2',mouse3='mouse3',scrollup='scrollup',scrolldown='scrolldown'},last_presses={},presses={},x=0,y=0,binds={}}function input:bind(a,b)local c=self.keycodes[b]self.binds[c]=self.binds[c]or{}table.insert(self.binds[c],a)end;function input:update()self.last_presses=self.presses;self.presses={}for d=0,3 do local e=peek(0xff88+d)if e>0 then self.presses[e]=true end end;local f,g,h,i,j,k,l=mouse()self.x=f;self.y=g;self.presses['mouse1']=h;self.presses['mouse2']=i;self.presses['mouse3']=j;self.presses['scrollup']=l>0;self.presses['scrolldown']=l<0;for m,k in pairs(self.presses)do if self.binds[m]then for k,n in pairs(self.binds[m])do self.presses[n]=self.presses[m]end end end end;function input:clicked(b)return(self.presses[self.keycodes[b]]or self.presses[b])and not(self.last_presses[self.keycodes[b]]or self.last_presses[b])end;function input:down(b)return self.presses[self.keycodes[b]]or self.presses[b]end;function input:released(b)return not(self.presses[self.keycodes[b]]or self.presses[b])and(self.last_presses[self.keycodes[b]]or self.last_presses[b])end ---------------------- Phy={ shape={}, CIRCLE="circle", RECT="rectangle", DYNAMIC="dynamic", STATIC="static", } function Phy.Grid(cs) local grid={ cellSize=cs, cells={} } function grid:hash(p) local x,y=math.floor(p.x/self.cellSize),math.floor(p.y/self.cellSize) return x..','..y,x,y end function grid:add(o) local bb=o:getBounds() local _,cx1,cy1=self:hash({x=bb.x1,y=bb.y1}) local _,cx2,cy2=self:hash({x=bb.x2,y=bb.y2}) for x=cx1,cx2 do for y=cy1,cy2 do local cell,cx,cy=x..','..y,x,y if not self.cells[cell] then self.cells[cell]={ bodies={}, x=cx,y=cy, count=0, } end self.cells[cell].bodies[o]=true self.cells[cell].count=self.cells[cell].count+1 end end end function grid:remove(o) local bb=o:getBounds() local _,cx1,cy1=self:hash({x=bb.x1,y=bb.y1}) local _,cx2,cy2=self:hash({x=bb.x2,y=bb.y2}) for x=cx1,cx2 do for y=cy1,cy2 do local cell,cx,cy=x..','..y,x,y if self.cells[cell] then if self.cells[cell].bodies[o] then self.cells[cell].bodies[o]=nil self.cells[cell].count=self.cells[cell].count-1 end if self.cells[cell].count==0 then self.cells[cell]=nil end end end end end function grid:getNear(o) local bb=o:getBounds() local _,cx1,cy1=self:hash({x=bb.x1,y=bb.y1}) local _,cx2,cy2=self:hash({x=bb.x2,y=bb.y2}) objects={} for x=cx1,cx2 do for y=cy1,cy2 do local cell,cx,cy=x..','..y,x,y if self.cells[cell] then for k,v in pairs(self.cells[cell].bodies) do if k~=o then objects[k]=true end end end end end return objects end function grid:debug() for i,cell in pairs(self.cells) do rectb(cell.x*self.cellSize,cell.y*self.cellSize,self.cellSize,self.cellSize,0) print(cell.x..','..cell.y,cell.x*self.cellSize+3,cell.y*self.cellSize+3,1,1,1,1) print(cell.count,cell.x*self.cellSize+3,cell.y*self.cellSize+13,1,1,1,1) end end return grid end function Phy.shape.circle(r) local c={ type=Phy.CIRCLE, radius=r, } function c:getBounds(pos) return { x1=pos.x-self.radius, y1=pos.y-self.radius, x2=pos.x+self.radius, y2=pos.y+self.radius, w=self.radius*2,h=self.radius*2, } end return c end function Phy.shape.rectangle(w,h) local r={ type=Phy.RECT, width=w, height=h, } function r:getBounds(pos) return { x1=pos.x-self.width/2, y1=pos.y-self.height/2, x2=pos.x+self.width/2, y2=pos.y+self.height/2, w=self.width,h=self.height, } end return r end function Phy.Body(shape,x,y) local body={ pos=vector(x,y), vel=vector(), acc=vector(), mass=1, rest=.3, type=Phy.DYNAMIC, shape=shape, color=math.random(1,12) } function body:getBounds() return self.shape:getBounds(self.pos) end function body:getInvMass() return 1/self.mass end function body:applyForce(f) self.acc=self.acc+f/self.mass end function body:applyImpulse(i) self.vel=self.vel+i end function body:move(w,p) if p.x==0 and p.y==0 then return end --w.grid:remove(self) self.pos=self.pos+p --w.grid:add(self) end function body:step(w,dt) self.acc=self.acc*dt self.vel=self.vel+self.acc self:move(w,self.vel) self.acc=vector() end return body end function Phy.World(g,cs) local world={ bodies={}, gravity=vector(0,g or 0), grid=Phy.Grid(cs or 50), } function world:reset() world.bodies={} end function world:add(b) table.insert(self.bodies,b) --self.grid:add(b) return #self.bodies end function world:getBody(i) return self.bodies[i] end function world:step(dt,ss) for z=1,ss do for i=#self.bodies,1,-1 do local b1=self:getBody(i) b1:applyForce(self.gravity*b1.mass) --local near=self.grid:getNear(b1) for j=i-1,1,-1 do --for b2,_ in pairs(near) do local b2=self:getBody(j) local coll=Phy.check(b1,b2) Phy.solve(world,coll) end if b1.type==Phy.DYNAMIC then b1:step(self,dt/ss) end end end end function world:debug(db) for i,b in pairs(self.bodies) do local pos,shape=b.pos,b.shape if shape.type==Phy.CIRCLE then circ(pos.x,pos.y,shape.radius,b.color) circb(pos.x,pos.y,shape.radius,0) end if shape.type==Phy.RECT then rect(pos.x-shape.width/2,pos.y-shape.height/2,shape.width,shape.height,b.color) rectb(pos.x-shape.width/2,pos.y-shape.height/2,shape.width,shape.height,0) end if db then local bb=b:getBounds() rectb(bb.x1,bb.y1,bb.w,bb.h,0) end end end function world:Circle(x,y,r) local i=self:add(Phy.Body(Phy.shape.circle(r),x,y)) return self.bodies[i] end function world:Rectangle(x,y,w,h) local i=self:add(Phy.Body(Phy.shape.rectangle(w,h),x,y)) return self.bodies[i] end return world end function Phy.check(b1,b2) local shape1,shape2=b1.shape.type,b2.shape.type if shape1==Phy.CIRCLE and shape2==Phy.CIRCLE then return Phy.checkCircles(b1,b2) end if shape1==Phy.RECT and shape2==Phy.RECT then return Phy.checkRects(b1,b2) end if shape1==Phy.CIRCLE and shape2==Phy.RECT then return Phy.checkCircleRect(b1,b2) end if shape1==Phy.RECT and shape2==Phy.CIRCLE then return Phy.checkCircleRect(b2,b1) end return {objects={b1,b2},hasCollided=false} end function Phy.solve(w,c) if c.hasCollided then local b1,b2=c.objects[1],c.objects[2] local relVel=b1.vel-b2.vel local rest=math.min(b1.rest,b2.rest) local impulse=-(1+rest)*relVel:dot(c.normal)/(b1:getInvMass()+b2:getInvMass()) local dir=vector() if b1.type==Phy.DYNAMIC and b2.type==Phy.DYNAMIC then dir=c.normal*c.penetration/2 elseif b1.type==Phy.STATIC or b2.type==Phy.STATIC then dir=c.normal*c.penetration end if b1.type==Phy.DYNAMIC then b1:applyImpulse(c.normal*(impulse/b1.mass)) b1:move(w,-dir) end if b2.type==Phy.DYNAMIC then b2:applyImpulse(-c.normal*(impulse/b2.mass)) b2:move(w,dir) end end end function Phy.checkCircles(c1,c2) local r1,r2=c1.shape.radius,c2.shape.radius local diff=c2.pos-c1.pos local total=r1+r2 if diff:magSq()oy then if diff.y>0 then return { objects={r1,r2}, contactPoint=vector(r1.pos.x,r1.pos.y+h1/2+h2/2), normal=vector(0,1), penetration=oy, hasCollided=true, } else return { objects={r1,r2}, contactPoint=vector(r1.pos.x,r1.pos.y-h1/2+-h2/2), normal=vector(0,-1), penetration=oy, hasCollided=true, } end else if diff.x>0 then return { objects={r1,r2}, contactPoint=vector(r1.pos.x+w1/2+w2/2,r1.pos.y), normal=vector(1,0), penetration=ox, hasCollided=true, } else return { objects={r1,r2}, contactPoint=vector(r1.pos.x-w1/2-w2/2,r1.pos.y), normal=vector(-1,0), penetration=ox, hasCollided=true, } end end end return { objects={r1,r2}, hasCollided=false, } end function Phy.checkCircleRect(c,r) local rshape=r.shape local cshape=c.shape local cx=math.max(r.pos.x-rshape.width/2,math.min(c.pos.x,r.pos.x+rshape.width/2)) local cy=math.max(r.pos.y-rshape.height/2,math.min(c.pos.y,r.pos.y+rshape.height/2)) local closest=vector(cx,cy) local diff=c.pos-closest if diff:magSq()