diff --git a/.build b/.build new file mode 100644 index 0000000..62f9457 --- /dev/null +++ b/.build @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1172fa4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +bin +unoptimized assets +/*.keystore diff --git a/Raider Wings.hxproj b/Raider Wings.hxproj new file mode 100644 index 0000000..b2df5b3 --- /dev/null +++ b/Raider Wings.hxproj @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/application.xml b/application.xml new file mode 100644 index 0000000..9f26ed3 --- /dev/null +++ b/application.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/effects/bulletHit/bulletHit.png b/assets/effects/bulletHit/bulletHit.png new file mode 100644 index 0000000..b3aa363 Binary files /dev/null and b/assets/effects/bulletHit/bulletHit.png differ diff --git a/assets/effects/debries/debries1.png b/assets/effects/debries/debries1.png new file mode 100644 index 0000000..5d22949 Binary files /dev/null and b/assets/effects/debries/debries1.png differ diff --git a/assets/effects/debries/debries2.png b/assets/effects/debries/debries2.png new file mode 100644 index 0000000..a4ccfe9 Binary files /dev/null and b/assets/effects/debries/debries2.png differ diff --git a/assets/effects/debries/debries3.png b/assets/effects/debries/debries3.png new file mode 100644 index 0000000..15f2915 Binary files /dev/null and b/assets/effects/debries/debries3.png differ diff --git a/assets/effects/explosion1/1.png b/assets/effects/explosion1/1.png new file mode 100644 index 0000000..9be0ef5 Binary files /dev/null and b/assets/effects/explosion1/1.png differ diff --git a/assets/effects/explosion1/2.png b/assets/effects/explosion1/2.png new file mode 100644 index 0000000..5117873 Binary files /dev/null and b/assets/effects/explosion1/2.png differ diff --git a/assets/effects/explosion1/3.png b/assets/effects/explosion1/3.png new file mode 100644 index 0000000..40e9850 Binary files /dev/null and b/assets/effects/explosion1/3.png differ diff --git a/assets/effects/explosion1/4.png b/assets/effects/explosion1/4.png new file mode 100644 index 0000000..a6219aa Binary files /dev/null and b/assets/effects/explosion1/4.png differ diff --git a/assets/effects/explosion1/5.png b/assets/effects/explosion1/5.png new file mode 100644 index 0000000..9b64e9c Binary files /dev/null and b/assets/effects/explosion1/5.png differ diff --git a/assets/effects/projectiles/beam01.png b/assets/effects/projectiles/beam01.png new file mode 100644 index 0000000..076e305 Binary files /dev/null and b/assets/effects/projectiles/beam01.png differ diff --git a/assets/effects/projectiles/beam02.png b/assets/effects/projectiles/beam02.png new file mode 100644 index 0000000..7342da0 Binary files /dev/null and b/assets/effects/projectiles/beam02.png differ diff --git a/assets/effects/projectiles/enemyBalloonBullet.png b/assets/effects/projectiles/enemyBalloonBullet.png new file mode 100644 index 0000000..0535337 Binary files /dev/null and b/assets/effects/projectiles/enemyBalloonBullet.png differ diff --git a/assets/effects/projectiles/railgunTrail.png b/assets/effects/projectiles/railgunTrail.png new file mode 100644 index 0000000..fe75a3b Binary files /dev/null and b/assets/effects/projectiles/railgunTrail.png differ diff --git a/assets/effects/smoke/smoke01.png b/assets/effects/smoke/smoke01.png new file mode 100644 index 0000000..27f7771 Binary files /dev/null and b/assets/effects/smoke/smoke01.png differ diff --git a/assets/effects/smoke/smoke02.png b/assets/effects/smoke/smoke02.png new file mode 100644 index 0000000..1d8db49 Binary files /dev/null and b/assets/effects/smoke/smoke02.png differ diff --git a/assets/effects/smoke/smoke03.png b/assets/effects/smoke/smoke03.png new file mode 100644 index 0000000..1909520 Binary files /dev/null and b/assets/effects/smoke/smoke03.png differ diff --git a/assets/effects/smoke/smoke04.png b/assets/effects/smoke/smoke04.png new file mode 100644 index 0000000..10ac4e4 Binary files /dev/null and b/assets/effects/smoke/smoke04.png differ diff --git a/assets/effects/smoke/smoke05.png b/assets/effects/smoke/smoke05.png new file mode 100644 index 0000000..4632cc2 Binary files /dev/null and b/assets/effects/smoke/smoke05.png differ diff --git a/assets/fonts/04B_03.TTF b/assets/fonts/04B_03.TTF new file mode 100644 index 0000000..fe4328b Binary files /dev/null and b/assets/fonts/04B_03.TTF differ diff --git a/assets/fonts/04B_03.TTF.hash b/assets/fonts/04B_03.TTF.hash new file mode 100644 index 0000000..d87af26 --- /dev/null +++ b/assets/fonts/04B_03.TTF.hash @@ -0,0 +1 @@ +oy4:hashq:111oy6:ascentd768y4:dataad384d894.976d384d641.024d128d641.024d128d894.976d384d894.976d128d896d0d896d0d640d128d640d128d512d384d512d384d640d512d640d512d896d384d896d384d1024d128d1024d128d896hy6:_widthd640y4:xMaxd512y4:xMind0y4:yMaxd512y4:yMind0y7:_heightd512y7:leadingd0y7:descentd256y8:charCodei111y15:leftsideBearingd0y12:advanceWidthd640y8:commandsai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:223oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i223R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:110oR1d768R2ad384d1024d512d1024d512d640d384d640d384d1024d128d640d384d640d384d512d0d512d0d1024d128d1024d128d640hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i110R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2hg:222oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i222R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:109oR1d768R2ad0d512d0d1024d128d1024d128d640d256d640d256d1024d384d1024d384d640d512d640d512d512d0d512d512d1024d640d1024d640d640d512d640d512d1024hR3d768R4d640R5d0R6d512R7d0R8d512R9d0R10d256R11i109R12d0R13d768R14ai1i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:221oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i221R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:108oR1d768R2ad128d384d0d384d0d1024d128d1024d128d384hR3d256R4d128R5d0R6d640R7d0R8d640R9d0R10d256R11i108R12d0R13d256R14ai1i2i2i2i2hg:220oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i220R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:107oR1d768R2ad384d640d256d640d256d768d128d768d128d384d0d384d0d1024d128d1024d128d896d384d896d384d640d512d512d384d512d384d640d512d640d512d512d512d1024d512d896d384d896d384d1024d512d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i107R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:219oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i219R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:106oR1d768R2ad256d384d128d384d128d512d256d512d256d384d256d640d128d640d128d1152d256d1152d256d640d128d1152d0d1152d0d1280d128d1280d128d1152hR3d384R4d256R5d0R6d640R7d-256R8d640R9d0R10d256R11i106R12d0R13d384R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:218oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i218R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:105oR1d768R2ad128d384d0d384d0d512d128d512d128d384d128d640d0d640d0d1024d128d1024d128d640hR3d256R4d128R5d0R6d640R7d0R8d640R9d0R10d256R11i105R12d0R13d256R14ai1i2i2i2i2i1i2i2i2i2hg:217oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i217R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:104oR1d768R2ad128d512d128d384d0d384d0d1024d128d1024d128d640d384d640d384d512d128d512d384d1024d512d1024d512d640d384d640d384d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i104R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2hg:216oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i216R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:103oR1d768R2ad128d894.976d384d894.976d384d641.024d128d641.024d128d894.976d128d1152d384d1152d384d1024d128d1024d128d896d0d896d0d640d128d640d128d512d512d512d512d1152d384d1152d384d1280d128d1280d128d1152hR3d640R4d512R5d0R6d512R7d-256R8d512R9d0R10d256R11i103R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:215oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i215R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:102oR1d768R2ad384d384d256d384d256d512d384d512d384d384d128d512d128d640d0d640d0d768d128d768d128d1024d256d1024d256d768d384d768d384d640d256d640d256d512d128d512hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i102R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:214oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i214R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:101oR1d768R2ad256d766.976d256d641.024d128d641.024d128d766.976d256d766.976d128d1024d128d896d0d896d0d640d128d640d128d512d384d512d384d640d512d640d512d768d256d768d256d896d384d896d384d1024d128d1024hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i101R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:213oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i213R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:100oR1d768R2ad128d894.976d384d894.976d384d641.024d128d641.024d128d894.976d128d640d128d512d384d512d384d384d512d384d512d1024d128d1024d128d896d0d896d0d640d128d640hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i100R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2hg:212oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i212R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:99oR1d768R2ad384d640d384d512d128d512d128d640d384d640d128d640d0d640d0d896d128d896d128d640d384d1024d384d896d128d896d128d1024d384d1024hR3d512R4d384R5d0R6d512R7d0R8d512R9d0R10d256R11i99R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:211oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i211R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:98oR1d768R2ad384d640d512d640d512d896d384d896d384d1024d0d1024d0d384d128d384d128d512d384d512d384d640d128d894.976d384d894.976d384d641.024d128d641.024d128d894.976hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i98R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:210oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i210R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:97oR1d768R2ad128d894.976d384d894.976d384d641.024d128d641.024d128d894.976d128d640d128d512d512d512d512d1024d128d1024d128d896d0d896d0d640d128d640hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i97R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2hg:209oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i209R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:96oR1d768R2ad0d384d0d512d128d512d128d384d0d384d128d640d256d640d256d512d128d512d128d640hR3d384R4d256R5d0R6d640R7d384R8d640R9d0R10d256R11i96R12d0R13d384R14ai1i2i2i2i2i1i2i2i2i2hg:208oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i208R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:95oR1d768R2ad0d896d0d1024d512d1024d512d896d0d896hR3d640R4d512R5d0R6d128R7d0R8d128R9d0R10d256R11i95R12d0R13d640R14ai1i2i2i2i2hg:207oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i207R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:94oR1d768R2ad128d384d128d512d256d512d256d384d128d384d0d640d128d640d128d512d0d512d0d640d256d640d384d640d384d512d256d512d256d640hR3d512R4d384R5d0R6d640R7d384R8d640R9d0R10d256R11i94R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:206oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i206R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:93oR1d768R2ad256d1024d256d384d0d384d0d512d128d512d128d896d0d896d0d1024d256d1024hR3d384R4d256R5d0R6d640R7d0R8d640R9d0R10d256R11i93R12d0R13d384R14ai1i2i2i2i2i2i2i2i2hg:205oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i205R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:92oR1d768R2ad256d640d128d640d128d512d256d512d256d640d128d384d128d512d0d512d0d384d128d384d512d896d384d896d384d768d512d768d512d896d384d768d256d768d256d640d384d640d384d768d640d1024d512d1024d512d896d640d896d640d1024hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i92R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:204oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i204R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:91oR1d768R2ad0d384d0d1024d256d1024d256d896d128d896d128d512d256d512d256d384d0d384hR3d384R4d256R5d0R6d640R7d0R8d640R9d0R10d256R11i91R12d0R13d384R14ai1i2i2i2i2i2i2i2i2hg:203oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i203R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:90oR1d768R2ad384d384d0d384d0d512d256d512d256d640d384d640d384d384d256d640d128d640d128d768d256d768d256d640d384d1024d384d896d128d896d128d768d0d768d0d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i90R12d0R13d512R14ai1i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2hg:202oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i202R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:89oR1d768R2ad128d384d0d384d0d640d128d640d128d384d384d640d128d640d128d768d384d768d384d896d512d896d512d384d384d384d384d640d128d896d128d1024d384d1024d384d896d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i89R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i1i2i2i2i2hg:201oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i201R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:88oR1d768R2ad128d384d0d384d0d640d128d640d128d384d512d384d384d384d384d640d512d640d512d384d384d768d384d640d128d640d128d768d384d768d128d768d0d768d0d1024d128d1024d128d768d384d1024d512d1024d512d768d384d768d384d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i88R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:200oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i200R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:87oR1d768R2ad128d384d0d384d0d896d128d896d128d384d384d512d256d512d256d896d384d896d384d512d128d1024d256d1024d256d896d128d896d128d1024d384d1024d512d1024d512d896d384d896d384d1024d512d384d512d896d640d896d640d384d512d384hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i87R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:199oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i199R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:86oR1d768R2ad0d896d128d896d128d384d0d384d0d896d256d896d384d896d384d640d256d640d256d896d384d384d384d640d512d640d512d384d384d384d128d1024d256d1024d256d896d128d896d128d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i86R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:198oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i198R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:85oR1d768R2ad384d896d512d896d512d384d384d384d384d896d128d384d0d384d0d896d128d896d128d384d128d896d128d1024d384d1024d384d896d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i85R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:197oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i197R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:84oR1d768R2ad128d1024d256d1024d256d512d384d512d384d384d0d384d0d512d128d512d128d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i84R12d0R13d512R14ai1i2i2i2i2i2i2i2i2hg:196oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i196R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:83oR1d768R2ad0d640d128d640d128d512d0d512d0d640d128d384d128d512d512d512d512d384d128d384d384d768d384d640d128d640d128d768d384d768d512d896d512d768d384d768d384d896d512d896d0d896d0d1024d384d1024d384d896d0d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i83R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:195oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i195R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:82oR1d768R2ad512d1024d384d1024d384d896d128d896d128d1024d0d1024d0d384d384d384d384d510.976d128d510.976d128d766.976d384d766.976d384d512d512d512d512d768d384d768d384d896d512d896d512d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i82R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:194oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i194R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:81oR1d768R2ad384d894.976d384d513.024d128d513.024d128d894.976d384d894.976d128d896d0d896d0d512d128d512d128d384d384d384d384d512d512d512d512d896d384d896d384d1024d512d1024d512d1152d384d1152d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d-128R8d640R9d0R10d256R11i81R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:193oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i193R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:80oR1d768R2ad384d512d512d512d512d768d384d768d384d896d128d896d128d1024d0d1024d0d384d384d384d384d512d128d766.976d384d766.976d384d513.024d128d513.024d128d766.976hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i80R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:192oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i192R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:79oR1d768R2ad384d894.976d384d513.024d128d513.024d128d894.976d384d894.976d128d896d0d896d0d512d128d512d128d384d384d384d384d512d512d512d512d896d384d896d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i79R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:191oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i191R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:78oR1d768R2ad384d768d384d1024d512d1024d512d384d384d384d384d640d256d640d256d768d384d768d128d640d256d640d256d512d128d512d128d384d0d384d0d1024d128d1024d128d640hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i78R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i2i2i2i2hg:190oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i190R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:77oR1d768R2ad128d512d128d384d0d384d0d1024d128d1024d128d640d256d640d256d512d128d512d256d768d384d768d384d640d256d640d256d768d512d512d384d512d384d640d512d640d512d1024d640d1024d640d384d512d384d512d512hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i77R12d0R13d768R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2i2i2hg:189oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i189R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:76oR1d768R2ad384d1024d384d896d128d896d128d384d0d384d0d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i76R12d0R13d512R14ai1i2i2i2i2i2i2hg:188oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i188R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:75oR1d768R2ad128d384d0d384d0d1024d128d1024d128d768d256d768d256d640d128d640d128d384d384d512d512d512d512d384d384d384d384d512d256d640d384d640d384d512d256d512d256d640d384d896d384d768d256d768d256d896d384d896d512d1024d512d896d384d896d384d1024d512d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i75R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:187oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i187R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:74oR1d768R2ad256d384d256d512d384d512d384d896d512d896d512d384d256d384d0d768d0d896d128d896d128d768d0d768d128d896d128d1024d384d1024d384d896d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i74R12d0R13d640R14ai1i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:186oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i186R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:73oR1d768R2ad256d512d384d512d384d384d0d384d0d512d128d512d128d896d0d896d0d1024d384d1024d384d896d256d896d256d512hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i73R12d0R13d512R14ai1i2i2i2i2i2i2i2i2i2i2i2i2hg:185oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i185R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:72oR1d768R2ad384d640d128d640d128d384d0d384d0d1024d128d1024d128d768d384d768d384d1024d512d1024d512d384d384d384d384d640hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i72R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i2i2hg:184oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i184R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:71oR1d768R2ad512d512d512d384d128d384d128d512d512d512d128d512d0d512d0d896d128d896d128d512d512d1024d128d1024d128d896d384d896d384d768d256d768d256d640d512d640d512d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i71R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2i2i2hg:183oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i183R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:70oR1d768R2ad128d768d384d768d384d640d128d640d128d512d384d512d384d384d0d384d0d1024d128d1024d128d768hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i70R12d0R13d512R14ai1i2i2i2i2i2i2i2i2i2i2hg:182oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i182R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:69oR1d768R2ad384d1024d384d896d128d896d128d768d384d768d384d640d128d640d128d512d384d512d384d384d0d384d0d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i69R12d0R13d512R14ai1i2i2i2i2i2i2i2i2i2i2i2i2hg:181oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i181R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:68oR1d768R2ad384d894.976d384d513.024d128d513.024d128d894.976d384d894.976d384d1024d0d1024d0d384d384d384d384d512d512d512d512d896d384d896d384d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i68R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2hg:180oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i180R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:67oR1d768R2ad384d512d384d384d128d384d128d512d384d512d128d512d0d512d0d896d128d896d128d512d384d1024d384d896d128d896d128d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i67R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:179oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i179R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:66oR1d768R2ad128d638.976d384d638.976d384d513.024d128d513.024d128d638.976d384d769.024d128d769.024d128d894.976d384d894.976d384d769.024d512d896d384d896d384d1024d0d1024d0d384d384d384d384d512d512d512d512d640d384d640d384d768d512d768d512d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i66R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:178oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i178R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:65oR1d768R2ad128d512d128d384d384d384d384d512d512d512d512d1024d384d1024d384d896d128d896d128d1024d0d1024d0d512d128d512d384d768d384d513.024d128d513.024d128d768d384d768hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i65R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:177oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i177R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:64oR1d768R2ad512d894.976d512d768d384d768d384d894.976d512d894.976d512d513.024d128d513.024d128d894.976d256d894.976d256d640d512d640d512d513.024d640d512d640d896d512d896d512d1024d128d1024d128d896d0d896d0d512d128d512d128d384d512d384d512d512d640d512hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i64R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:176oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i176R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:63oR1d768R2ad0d384d0d512d384d512d384d384d0d384d384d640d512d640d512d512d384d512d384d640d128d640d128d768d384d768d384d640d128d640d128d1024d256d1024d256d896d128d896d128d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i63R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:175oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i175R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:62oR1d768R2ad0d384d0d512d128d512d128d384d0d384d128d512d128d640d256d640d256d512d128d512d128d896d256d896d256d768d128d768d128d896d256d768d384d768d384d640d256d640d256d768d0d1024d128d1024d128d896d0d896d0d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i62R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:174oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i174R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:61oR1d768R2ad0d512d0d640d384d640d384d512d0d512d0d768d0d896d384d896d384d768d0d768hR3d512R4d384R5d0R6d512R7d128R8d512R9d0R10d256R11i61R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:173oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i173R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:60oR1d768R2ad128d640d256d640d256d512d128d512d128d640d256d512d384d512d384d384d256d384d256d512d0d768d128d768d128d640d0d640d0d768d256d896d256d768d128d768d128d896d256d896d384d1024d384d896d256d896d256d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i60R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:172oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i172R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:59oR1d768R2ad128d512d0d512d0d640d128d640d128d512d128d768d0d768d0d1024d128d1024d128d768hR3d256R4d128R5d0R6d512R7d0R8d512R9d0R10d256R11i59R12d0R13d256R14ai1i2i2i2i2i1i2i2i2i2hg:171oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i171R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:58oR1d768R2ad0d640d128d640d128d512d0d512d0d640d0d896d128d896d128d768d0d768d0d896hR3d256R4d128R5d0R6d512R7d128R8d512R9d0R10d256R11i58R12d0R13d256R14ai1i2i2i2i2i1i2i2i2i2hg:170oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i170R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:57oR1d768R2ad128d513.024d128d638.976d384d638.976d384d513.024d128d513.024d128d896d384d896d384d768d128d768d128d640d0d640d0d512d128d512d128d384d384d384d384d512d512d512d512d896d384d896d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i57R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:169oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i169R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:56oR1d768R2ad384d638.976d384d513.024d128d513.024d128d638.976d384d638.976d384d894.976d384d769.024d128d769.024d128d894.976d384d894.976d128d896d0d896d0d768d128d768d128d640d0d640d0d512d128d512d128d384d384d384d384d512d512d512d512d640d384d640d384d768d512d768d512d896d384d896d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i56R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:168oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i168R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:55oR1d768R2ad0d384d0d512d384d512d384d640d512d640d512d384d0d384d128d1024d256d1024d256d768d128d768d128d1024d256d768d384d768d384d640d256d640d256d768hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i55R12d0R13d640R14ai1i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:167oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i167R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:54oR1d768R2ad384d894.976d384d769.024d128d769.024d128d894.976d384d894.976d128d896d0d896d0d512d128d512d128d384d384d384d384d512d128d512d128d640d384d640d384d768d512d768d512d896d384d896d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i54R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:166oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i166R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:53oR1d768R2ad128d640d128d512d512d512d512d384d0d384d0d768d384d768d384d640d128d640d512d768d384d768d384d896d512d896d512d768d384d1024d384d896d0d896d0d1024d384d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i53R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:165oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i165R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:52oR1d768R2ad128d641.024d128d768d256d768d256d641.024d128d641.024d384d384d384d768d512d768d512d896d384d896d384d1024d256d1024d256d896d0d896d0d640d128d640d128d512d256d512d256d384d384d384hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i52R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:164oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i164R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:51oR1d768R2ad0d384d0d512d384d512d384d384d0d384d384d640d512d640d512d512d384d512d384d640d128d640d128d768d384d768d384d640d128d640d512d896d512d768d384d768d384d896d512d896d0d896d0d1024d384d1024d384d896d0d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i51R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:163oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i163R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:50oR1d768R2ad0d384d0d512d384d512d384d384d0d384d384d640d512d640d512d512d384d512d384d640d128d640d128d768d384d768d384d640d128d640d0d1024d512d1024d512d896d128d896d128d768d0d768d0d1024hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i50R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2hg:162oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i162R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:49oR1d768R2ad128d1024d256d1024d256d384d0d384d0d512d128d512d128d1024hR3d384R4d256R5d0R6d640R7d0R8d640R9d0R10d256R11i49R12d0R13d384R14ai1i2i2i2i2i2i2hg:161oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i161R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:48oR1d768R2ad384d894.976d384d513.024d128d513.024d128d894.976d384d894.976d128d896d0d896d0d512d128d512d128d384d384d384d384d512d512d512d512d896d384d896d384d1024d128d1024d128d896hR3d640R4d512R5d0R6d640R7d0R8d640R9d0R10d256R11i48R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2hg:160oR1d768R2ahR3d512R4d0R5d0R6d0R7d0R8d0R9d0R10d256R11i160R12d0R13d512R14ahg:47oR1d768R2ad384d640d512d640d512d512d384d512d384d640d512d384d512d512d640d512d640d384d512d384d128d896d256d896d256d768d128d768d128d896d256d768d384d768d384d640d256d640d256d768d0d1024d128d1024d128d896d0d896d0d1024hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i47R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:159oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i159R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:46oR1d768R2ad0d1024d128d1024d128d896d0d896d0d1024hR3d256R4d128R5d0R6d128R7d0R8d128R9d0R10d256R11i46R12d0R13d256R14ai1i2i2i2i2hg:158oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i158R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:45oR1d768R2ad0d640d0d768d384d768d384d640d0d640hR3d512R4d384R5d0R6d384R7d256R8d384R9d0R10d256R11i45R12d0R13d512R14ai1i2i2i2i2hg:157oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i157R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:44oR1d768R2ad128d1024d256d1024d256d896d128d896d128d1024d0d1152d128d1152d128d1024d0d1024d0d1152hR3d384R4d256R5d0R6d128R7d-128R8d128R9d0R10d256R11i44R12d0R13d384R14ai1i2i2i2i2i1i2i2i2i2hg:156oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i156R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:43oR1d768R2ad128d896d256d896d256d768d384d768d384d640d256d640d256d512d128d512d128d640d0d640d0d768d128d768d128d896hR3d512R4d384R5d0R6d512R7d128R8d512R9d0R10d256R11i43R12d0R13d512R14ai1i2i2i2i2i2i2i2i2i2i2i2i2hg:155oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i155R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:42oR1d768R2ad128d512d128d384d0d384d0d512d128d512d256d640d256d512d128d512d128d640d256d640d384d512d384d384d256d384d256d512d384d512d128d768d128d640d0d640d0d768d128d768d384d768d384d640d256d640d256d768d384d768hR3d512R4d384R5d0R6d640R7d256R8d640R9d0R10d256R11i42R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:154oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i154R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:41oR1d768R2ad0d384d0d512d128d512d128d384d0d384d256d512d128d512d128d896d256d896d256d512d128d896d0d896d0d1024d128d1024d128d896hR3d384R4d256R5d0R6d640R7d0R8d640R9d0R10d256R11i41R12d0R13d384R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:153oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i153R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:40oR1d768R2ad256d384d128d384d128d512d256d512d256d384d128d512d0d512d0d896d128d896d128d512d256d1024d256d896d128d896d128d1024d256d1024hR3d384R4d256R5d0R6d640R7d0R8d640R9d0R10d256R11i40R12d0R13d384R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:152oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i152R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:39oR1d768R2ad128d384d0d384d0d640d128d640d128d384hR3d256R4d128R5d0R6d640R7d384R8d640R9d0R10d256R11i39R12d0R13d256R14ai1i2i2i2i2hg:151oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i151R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:38oR1d768R2ad384d769.024d128d769.024d128d894.976d384d894.976d384d769.024d640d1024d512d1024d512d896d384d896d384d1024d128d1024d128d896d0d896d0d768d128d768d128d640d0d640d0d512d128d512d128d384d384d384d384d512d128d512d128d640d384d640d384d768d512d768d512d640d640d640d640d768d512d768d512d896d640d896d640d1024hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i38R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2hg:150oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i150R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:37oR1d768R2ad128d384d0d384d0d512d128d512d128d384d512d384d384d384d384d640d512d640d512d384d128d1024d256d1024d256d768d128d768d128d1024d256d768d384d768d384d640d256d640d256d768d512d896d512d1024d640d1024d640d896d512d896hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i37R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:149oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i149R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:36oR1d768R2ad384d384d256d384d256d512d128d512d128d640d0d640d0d768d256d768d256d640d512d640d512d512d384d512d384d384d0d896d0d1024d256d1024d256d1152d384d1152d384d896d512d896d512d768d256d768d256d896d0d896hR3d640R4d512R5d0R6d640R7d-128R8d640R9d0R10d256R11i36R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2hg:148oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i148R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:35oR1d768R2ad640d640d640d512d512d512d512d384d384d384d384d512d256d512d256d384d128d384d128d512d0d512d0d640d128d640d128d768d0d768d0d896d128d896d128d1024d256d1024d256d896d384d896d384d1024d512d1024d512d896d640d896d640d768d512d768d512d640d640d640d384d768d256d768d256d640d384d640d384d768hR3d768R4d640R5d0R6d640R7d0R8d640R9d0R10d256R11i35R12d0R13d768R14ai1i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:147oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i147R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:34oR1d768R2ad0d640d128d640d128d384d0d384d0d640d256d640d384d640d384d384d256d384d256d640hR3d512R4d384R5d0R6d640R7d384R8d640R9d0R10d256R11i34R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:146oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i146R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:33oR1d768R2ad128d384d0d384d0d768d128d768d128d384d128d896d0d896d0d1024d128d1024d128d896hR3d256R4d128R5d0R6d640R7d0R8d640R9d0R10d256R11i33R12d0R13d256R14ai1i2i2i2i2i1i2i2i2i2hg:145oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i145R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:32oR1d768R2ahR3d512R4d0R5d0R6d0R7d0R8d0R9d0R10d256R11i32R12d0R13d512R14ahg:144oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i144R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:143oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i143R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:255oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i255R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:142oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i142R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:254oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i254R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:141oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i141R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:253oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i253R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:140oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i140R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:252oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i252R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:139oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i139R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:251oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i251R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:138oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i138R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:250oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i250R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:137oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i137R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:249oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i249R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:136oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i136R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:248oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i248R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:135oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i135R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:247oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i247R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:134oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i134R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:246oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i246R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:133oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i133R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:245oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i245R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:132oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i132R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:244oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i244R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:131oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i131R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:243oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i243R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:130oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i130R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:242oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i242R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:129oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i129R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:241oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i241R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:128oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i128R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:240oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i240R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:127oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i127R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:239oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i239R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:126oR1d768R2ad128d384d128d512d256d512d256d384d128d384d0d640d128d640d128d512d0d512d0d640d384d512d512d512d512d384d384d384d384d512d256d640d384d640d384d512d256d512d256d640hR3d640R4d512R5d0R6d640R7d384R8d640R9d0R10d256R11i126R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:238oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i238R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:125oR1d768R2ad256d384d0d384d0d512d128d512d128d640d256d640d256d384d128d896d0d896d0d1024d256d1024d256d768d128d768d128d896d256d768d384d768d384d640d256d640d256d768hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i125R12d0R13d512R14ai1i2i2i2i2i2i2i1i2i2i2i2i2i2i1i2i2i2i2hg:237oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i237R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:124oR1d768R2ad0d1024d128d1024d128d384d0d384d0d1024hR3d256R4d128R5d0R6d640R7d0R8d640R9d0R10d256R11i124R12d0R13d256R14ai1i2i2i2i2hg:236oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i236R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:123oR1d768R2ad128d384d128d640d256d640d256d512d384d512d384d384d128d384d0d768d128d768d128d640d0d640d0d768d128d1024d384d1024d384d896d256d896d256d768d128d768d128d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i123R12d0R13d512R14ai1i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2i2i2hg:235oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i235R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:122oR1d768R2ad0d512d0d640d256d640d256d768d384d768d384d640d512d640d512d512d0d512d128d896d0d896d0d1024d512d1024d512d896d256d896d256d768d128d768d128d896hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i122R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i2i2i2i2hg:234oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i234R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:121oR1d768R2ad128d512d0d512d0d896d128d896d128d512d384d1024d384d1152d512d1152d512d512d384d512d384d896d128d896d128d1024d384d1024d128d1152d128d1280d384d1280d384d1152d128d1152hR3d640R4d512R5d0R6d512R7d-256R8d512R9d0R10d256R11i121R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i1i2i2i2i2hg:233oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i233R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:120oR1d768R2ad0d512d0d640d128d640d128d512d0d512d384d512d256d512d256d640d384d640d384d512d256d640d128d640d128d896d256d896d256d640d128d896d0d896d0d1024d128d1024d128d896d384d1024d384d896d256d896d256d1024d384d1024hR3d512R4d384R5d0R6d512R7d0R8d512R9d0R10d256R11i120R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:232oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i232R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:119oR1d768R2ad128d512d0d512d0d768d128d768d128d512d512d768d640d768d640d512d512d512d512d768d384d512d256d512d256d768d384d768d384d512d128d1024d256d1024d256d768d128d768d128d1024d384d1024d512d1024d512d768d384d768d384d1024hR3d768R4d640R5d0R6d512R7d0R8d512R9d0R10d256R11i119R12d0R13d768R14ai1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:231oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i231R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:118oR1d768R2ad384d768d512d768d512d512d384d512d384d768d128d768d128d512d0d512d0d896d128d896d128d768d128d768d256d896d384d896d384d768d256d768d256d896d128d1024d256d1024d256d896d128d896d128d1024hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i118R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i1i2i2i2i2i1i2i2i2i2hg:230oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i230R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:117oR1d768R2ad384d896d128d896d128d1024d512d1024d512d512d384d512d384d896d128d512d0d512d0d896d128d896d128d512hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i117R12d0R13d640R14ai1i2i2i2i2i2i2i1i2i2i2i2hg:229oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i229R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:116oR1d768R2ad256d384d128d384d128d512d0d512d0d640d128d640d128d896d256d896d256d640d384d640d384d512d256d512d256d384d384d1024d384d896d256d896d256d1024d384d1024hR3d512R4d384R5d0R6d640R7d0R8d640R9d0R10d256R11i116R12d0R13d512R14ai1i2i2i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:228oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i228R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:115oR1d768R2ad128d512d128d640d0d640d0d768d256d768d256d640d512d640d512d512d128d512d0d896d0d1024d384d1024d384d896d512d896d512d768d256d768d256d896d0d896hR3d640R4d512R5d0R6d512R7d0R8d512R9d0R10d256R11i115R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i1i2i2i2i2i2i2i2i2hg:227oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i227R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:114oR1d768R2ad384d512d256d512d256d640d384d640d384d512d128d768d256d768d256d640d128d640d128d512d0d512d0d1024d128d1024d128d768hR3d512R4d384R5d0R6d512R7d0R8d512R9d0R10d256R11i114R12d0R13d512R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2hg:226oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i226R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:113oR1d768R2ad128d894.976d384d894.976d384d641.024d128d641.024d128d894.976d128d640d128d512d512d512d512d1280d384d1280d384d1024d128d1024d128d896d0d896d0d640d128d640hR3d640R4d512R5d0R6d512R7d-256R8d512R9d0R10d256R11i113R12d0R13d640R14ai1i2i2i2i2i1i2i2i2i2i2i2i2i2i2i2hg:225oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i225R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hg:112oR1d768R2ad384d640d512d640d512d896d384d896d384d1024d128d1024d128d1280d0d1280d0d512d384d512d384d640d128d894.976d384d894.976d384d641.024d128d641.024d128d894.976hR3d640R4d512R5d0R6d512R7d-256R8d512R9d0R10d256R11i112R12d0R13d640R14ai1i2i2i2i2i2i2i2i2i2i2i1i2i2i2i2hg:224oR1d768R2ad64.512d1024d64.512d256d448.512d256d448.512d1024d64.512d1024d128d959.488d384d959.488d384d319.487d128d319.487d128d959.488hR3d512R4d448.512R5d64.512R6d768R7d0R8d703.488R9d0R10d256R11i224R12d64.512R13d512R14ai1i2i2i2i2i1i2i2i2i2hghy8:fontNamey5:04b03g \ No newline at end of file diff --git a/assets/general/goButton.png b/assets/general/goButton.png new file mode 100644 index 0000000..38965e3 Binary files /dev/null and b/assets/general/goButton.png differ diff --git a/assets/general/sky.png b/assets/general/sky.png new file mode 100644 index 0000000..ecb68bb Binary files /dev/null and b/assets/general/sky.png differ diff --git a/assets/objects/enemies/foe02.png b/assets/objects/enemies/foe02.png new file mode 100644 index 0000000..5e8e4c7 Binary files /dev/null and b/assets/objects/enemies/foe02.png differ diff --git a/assets/objects/enemies/tesla1.png b/assets/objects/enemies/tesla1.png new file mode 100644 index 0000000..bb01e6f Binary files /dev/null and b/assets/objects/enemies/tesla1.png differ diff --git a/assets/objects/enemies/tesla2.png b/assets/objects/enemies/tesla2.png new file mode 100644 index 0000000..f01a390 Binary files /dev/null and b/assets/objects/enemies/tesla2.png differ diff --git a/assets/objects/enemies/tesla3.png b/assets/objects/enemies/tesla3.png new file mode 100644 index 0000000..c267db2 Binary files /dev/null and b/assets/objects/enemies/tesla3.png differ diff --git a/assets/objects/player/plane01.png b/assets/objects/player/plane01.png new file mode 100644 index 0000000..45ed6a8 Binary files /dev/null and b/assets/objects/player/plane01.png differ diff --git a/assets/openfl.svg b/assets/openfl.svg new file mode 100644 index 0000000..506f61d --- /dev/null +++ b/assets/openfl.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/assets/rw.png b/assets/rw.png new file mode 100644 index 0000000..a18113f Binary files /dev/null and b/assets/rw.png differ diff --git a/assets/rw.svg b/assets/rw.svg new file mode 100644 index 0000000..572cd90 --- /dev/null +++ b/assets/rw.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + diff --git a/assets/rw2.png b/assets/rw2.png new file mode 100644 index 0000000..57ec4ac Binary files /dev/null and b/assets/rw2.png differ diff --git a/assets/rw2.svg b/assets/rw2.svg new file mode 100644 index 0000000..79efc9f --- /dev/null +++ b/assets/rw2.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + diff --git a/assets/tiles/middle.png b/assets/tiles/middle.png new file mode 100644 index 0000000..f77cd13 Binary files /dev/null and b/assets/tiles/middle.png differ diff --git a/assets/tiles/middle2.png b/assets/tiles/middle2.png new file mode 100644 index 0000000..afa0472 Binary files /dev/null and b/assets/tiles/middle2.png differ diff --git a/assets/tiles/slopeDown.png b/assets/tiles/slopeDown.png new file mode 100644 index 0000000..79b06e9 Binary files /dev/null and b/assets/tiles/slopeDown.png differ diff --git a/assets/tiles/slopeUp.png b/assets/tiles/slopeUp.png new file mode 100644 index 0000000..172fe76 Binary files /dev/null and b/assets/tiles/slopeUp.png differ diff --git a/assets/tiles/top.png b/assets/tiles/top.png new file mode 100644 index 0000000..90f33b8 Binary files /dev/null and b/assets/tiles/top.png differ diff --git a/assets/tiles/top2.png b/assets/tiles/top2.png new file mode 100644 index 0000000..03d5969 Binary files /dev/null and b/assets/tiles/top2.png differ diff --git a/assets/tiles/tst1.png b/assets/tiles/tst1.png new file mode 100644 index 0000000..8ec737b Binary files /dev/null and b/assets/tiles/tst1.png differ diff --git a/assets/tiles/tst4.png b/assets/tiles/tst4.png new file mode 100644 index 0000000..9dfc54f Binary files /dev/null and b/assets/tiles/tst4.png differ diff --git a/assets/tiles/tstM.png b/assets/tiles/tstM.png new file mode 100644 index 0000000..47b7f79 Binary files /dev/null and b/assets/tiles/tstM.png differ diff --git a/assets/ui/gameOverText.png b/assets/ui/gameOverText.png new file mode 100644 index 0000000..a1cc9c9 Binary files /dev/null and b/assets/ui/gameOverText.png differ diff --git a/assets/ui/gameOverText.psd b/assets/ui/gameOverText.psd new file mode 100644 index 0000000..41f0112 Binary files /dev/null and b/assets/ui/gameOverText.psd differ diff --git a/assets/ui/joystickHead.png b/assets/ui/joystickHead.png new file mode 100644 index 0000000..e95d64b Binary files /dev/null and b/assets/ui/joystickHead.png differ diff --git a/assets/ui/joystickHead.psd b/assets/ui/joystickHead.psd new file mode 100644 index 0000000..1bc517e Binary files /dev/null and b/assets/ui/joystickHead.psd differ diff --git a/openfl-readme.txt b/openfl-readme.txt new file mode 100644 index 0000000..035191d --- /dev/null +++ b/openfl-readme.txt @@ -0,0 +1,68 @@ +About OpenFL + + OpenFL is the successor of NME, for Haxe 3+. + + Building a game or application with OpenFL is almost like writing for a single platform. However, + when you are ready to publish your application, you can choose between targets like iOS, webOS, + Android, Windows, Mac, Linux and Flash Player. + + Instead of using the lowest common denominator between platforms with a "universal" runtime, + OpenFL projects are compiled as SWF bytecode or C++ applications, using the Haxe language compiler + and the standard C++ compiler toolchain for each platform. + + Read more: + http://openfl.org/ + +Project configuration, libraries, classpaths + + OpenFL configuration is based on a XML file - it allows you very complex + configurations depending on the target platform. There is no GUI for it. + + DO NOT modify FlashDevelop project properties as they will automatically be synchronized with the + XML when you modify it. + +Development + + OpenFL is encouraging to develop using the Flash API (ie. flash.display.Sprite) as in ActionScript 3. + + Just code like you would code a Flash application, with the limitation that you can only use + the drawing API, bitmaps (see below) and TextFields. + + However test often all the platforms you plan to target! + + In OpenFL 3.x, SWFs and videos aren't supported yet. + +Assets + + Place all your images, sounds, fonts in /assets and access them in your code using the + global Assets class which abstracts assets management for all platforms: + + var img = new Bitmap(Assets.getBitmapData("assets/my-image.png")); + addChild(img); + + Tutorials: + https://github.com/openfl/openfl/wiki/Get-Started + +Debugging + + By default your project targets Flash so you'll be able to add breakpoints and debug your app + like any AS3 project. + HTML5 target can be debugged in the browser - some browsers, like Chrome, support "script maps" + which let you interactively debug .hx code directly instead of the generated JS. + There is however no interactive debugger yet for native targets. + +Changing target platform + + For OpenFL projects, an additional drop-down menu appears in the main toolbar where you can choose + a supported targets on Windows: flash, html5, windows, neko, android, webos, blackberry. + You can also manually enter a custom target not in the list. + + Attention, for native targets you'll need to install additional compilers & SDKs. The compiler + will tell you in the Output panel what command to execute for that. More information here: + https://github.com/openfl/openfl/wiki/Get-Started + +Tips: + - in C++ expect first compilation to be very long as it first compiles the whole OpenFL API, + - if a change is not taken in account, delete everything in /bin to start a fresh compilation, + - on mobile, Bitmap blitting is NOT performant, + - use spritesheets and Tilesheet.drawTiles for optimal rendering performance. diff --git a/src/FPS.hx b/src/FPS.hx new file mode 100644 index 0000000..e2d899b --- /dev/null +++ b/src/FPS.hx @@ -0,0 +1,38 @@ +import flash.events.Event; +import flash.Lib; +import flash.text.TextField; +import flash.text.TextFormat; + +class FPS extends TextField +{ + var times:Array; + + public function new(inX:Float=10.0, inY:Float=10.0, inCol:Int = 0x000000) + { + super(); + x = inX; + y = inY; + selectable = false; + embedFonts = true; + defaultTextFormat = new TextFormat(FontManager.mainFont.fontName, 16, 0, true); + text = "FPS:"; + textColor = inCol; + times = []; + addEventListener(Event.ENTER_FRAME, enterFrame); + } + + private function enterFrame(e:Event):Void + { + var now = Lib.getTimer () / 1000; + times.push(now); + while(times[0]; + static private var socketConnected:Bool; + + static public function connectTracer():Void + { + messageQueue = []; + + xmlSocket = new XMLSocket(); + xmlSocket.addEventListener(IOErrorEvent.IO_ERROR, onIOError); + xmlSocket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError); + xmlSocket.addEventListener(Event.CONNECT, onConnect); + try + { + xmlSocket.connect('localhost', 4442); + } + catch (e:Dynamic) + { + + } + } + + static public function disconnectTracer():Void + { + if (xmlSocket != null && xmlSocket.connected) + { + xmlSocket.close(); + } + } + + static private function onConnect(e:Event):Void + { + socketConnected = true; + add("Connected to socket"); + while (messageQueue.length > 0) { + xmlSocket.send(messageQueue.shift()); + } + } + + static private function onSecurityError(e:SecurityErrorEvent):Void + { + + } + + static private function onIOError(e:IOErrorEvent):Void + { + + } + + static public function add(string:String, type:String = "SYSTEM"):Void + { + var splitMessage:Array = string.split("\n"); + + if (xmlSocket == null) { + connectTracer(); + } + + var message:String = '!SOS'; + if (socketConnected) + { + try + { + xmlSocket.send(message); + } + catch (e:Dynamic) + { + + } + } + else + { + messageQueue.push(message); + } + + while (messageQueue.length > 1000) + { + messageQueue.shift(); + } + } + + static public function objectToString(target:Dynamic, ?depth:Int = 0):String + { + var tab:String = ' '; + for (i in 0...depth) + { + tab += ' '; + } + + var out : String = ''; + + /* + var item:Dynamic; + var dat:Dynamic; + var objectToDescribe:String; + var enter:String = '\n'; + for (item in target) + { + dat = target[item]; + if (typeof(dat) == 'object') + { + out += tab+'['+item+']' + enter; + objectToDescribe = objectToString(dat, depth+1); + out += (objectToDescribe != '' ? objectToDescribe : tab + '...') + enter; + out += tab+'[/'+item+']' + enter; + } + } + + var step:Int = 0; + for (item in target) { + dat = target[item]; + if (typeof(dat) != 'object') { + if (step) { out += enter; } + out += tab+''+item+' = '+dat; + step++; + } + } + */ + return out; + } + + static public function sosTrace(data:String, ?logLevel:String = TRACE):Void + { + + /* + for (var i:int = 0; i < arguments.length; i++) + { + argument = arguments[i]; + if (argument == null ) + { + string += null; + } + else if (typeof(argument) == 'object') + { + string += '\n'; + string += "[" + getQualifiedClassName(argument) + "]"; + string += '\n' + SOSLog.objectToString(argument) + '\n'; + string += "[/" + getQualifiedClassName(argument) + "]"; + } else + { + string += argument; + if (i < arguments.length - 1) { + string += ', '; + } + } + }*/ + SOSLog.add(data, logLevel); + } + #else + static public function sosTrace(data:String, ?logLevel:String = TRACE):Void + { + trace(data); + } + #end +} \ No newline at end of file diff --git a/src/ScreenPad.hx b/src/ScreenPad.hx new file mode 100644 index 0000000..b6a5829 --- /dev/null +++ b/src/ScreenPad.hx @@ -0,0 +1,88 @@ +package ; +import flash.display.Bitmap; +import flash.display.BitmapData; +import flash.display.Sprite; +import flash.events.Event; +import flash.events.MouseEvent; +import openfl.Assets; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class ScreenPad extends Sprite +{ + static public inline var WIDTH:Int = 128; + static public inline var HEIGHT:Int = 128; + static public inline var SIDE_PAD:Int = 16; + + public var xMagnitude:Float; + public var yMagnitude:Float; + private var headBitmap:Bitmap; + private var mouseDown:Bool; + private var headContainer:Sprite; + + public function new() + { + super(); + var backgroundBitmapData:BitmapData = new BitmapData(WIDTH,HEIGHT, true, 0); + var backgroundSource:Sprite = new Sprite(); + backgroundSource.graphics.lineStyle(2, 0, 0.6, true); + backgroundSource.graphics.beginFill(0, 0.2); + backgroundSource.graphics.drawRoundRect(1, 1, WIDTH-2, HEIGHT-2, WIDTH/4, HEIGHT/4); + backgroundSource.graphics.endFill(); + backgroundBitmapData.draw(backgroundSource); + addChild(new Bitmap(backgroundBitmapData)); + + headContainer = new Sprite(); + headContainer.x = WIDTH / 2; + headContainer.y = HEIGHT / 2; + addChild(headContainer); + + headBitmap = new Bitmap(Assets.getBitmapData("assets/ui/joystickHead.png")); + headBitmap.x = -headBitmap.width / 2; + headBitmap.y = -headBitmap.height/ 2; + headContainer.addChild(headBitmap); + + addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); + addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); + //TODO cleanup routine on removed from stage + } + + private function addedToStageHandler(e:Event):Void + { + removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); + stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler); + } + + private function mouseDownHandler(e:MouseEvent):Void + { + mouseDown = true; + } + + private function stage_mouseUpHandler(e:MouseEvent):Void + { + mouseDown = false; + } + + public function update(dTime:Float):Void + { + if (mouseDown) + { + headContainer.x = Math.min(Math.max(mouseX, SIDE_PAD), WIDTH - SIDE_PAD); + headContainer.y = Math.min(Math.max(mouseY, SIDE_PAD), HEIGHT - SIDE_PAD); + xMagnitude = (mouseX - WIDTH / 2) / ((WIDTH - SIDE_PAD * 2 - 2) / 2); + yMagnitude = (mouseY - HEIGHT/ 2) / ((HEIGHT- SIDE_PAD * 2 - 2) / 2); + } + else + { + headContainer.x += (WIDTH / 2 - headContainer.x) * dTime * 10; + headContainer.y += (HEIGHT / 2 - headContainer.y) * dTime * 10; + xMagnitude = 0; + yMagnitude = 0; + } + + } + +} \ No newline at end of file diff --git a/src/assets/EntityGraphicsAsset.hx b/src/assets/EntityGraphicsAsset.hx new file mode 100644 index 0000000..310f5cc --- /dev/null +++ b/src/assets/EntityGraphicsAsset.hx @@ -0,0 +1,93 @@ +package assets; +import flash.display.BitmapData; +import flash.geom.Point; +import flash.geom.Rectangle; +import haxe.ds.IntMap.IntMap; +import haxe.ds.StringMap.StringMap; +import haxe.ds.StringMap.StringMap; +import openfl.Assets; + +/** + * ... + * @author Dmitriy Barabanschikov + */ +class EntityGraphicsAsset +{ + public var assetID:String; + public var spriteSheet:BitmapData; + public var frameRectangles:Array; + public var tileSheetRectangles:Array; + public var tileSheetFrameID:Array; + public var sizeCorrection:Point; + public var assetFrameByName:StringMap; + + public function new(assetID:String) + { + this.assetID = assetID; + frameRectangles = new Array(); + tileSheetFrameID = new Array(); + tileSheetRectangles = new Array(); + assetFrameByName = new StringMap(); + } + + public function initializeFromAssetNames(namesArray:Array):EntityGraphicsAsset + { + var sourceAssets:Array = []; + var numAssets:Int = namesArray.length; + var maxWidth:Int = 0; + var maxHeight:Int = 0; + for (i in 0...numAssets) + { + //trace(namesArray[i]); + var asset:BitmapData = Assets.getBitmapData(namesArray[i]); + maxWidth = Std.int(Math.max(maxWidth, asset.width)); + maxHeight = Std.int(Math.max(maxHeight, asset.height)); + sourceAssets.push(asset); + assetFrameByName.set(namesArray[i], i); + } + + //TODO only for non-flash targets + #if (!flash) + maxWidth = Math.ceil(Std.int(Math.max(maxWidth, maxHeight))/2)*2; + maxHeight = maxWidth; + #end + + sizeCorrection = new Point(-maxWidth / 2, -maxHeight/2); + + frameRectangles = new Array(); + + #if flash + spriteSheet = new BitmapData(numAssets * maxWidth, numAssets*maxHeight, true, 0x0); + #else + spriteSheet = new BitmapData(numAssets * maxWidth, numAssets*maxHeight, true, 0x0); + #end + + for (i in 0...numAssets) + { + var destinationRectangle:Rectangle = new Rectangle(i * maxWidth, 0, maxWidth, maxHeight); + //trace(destinationRectangle); + frameRectangles.push(destinationRectangle); + var sourceWidth:Int = sourceAssets[i].width; + var sourceHeight:Int = sourceAssets[i].height; + spriteSheet.copyPixels(sourceAssets[i], new Rectangle(0, 0, sourceWidth, sourceHeight), new Point(destinationRectangle.x + Std.int((maxWidth - sourceWidth) / 2), destinationRectangle.y + Std.int((maxHeight - sourceHeight) / 2))); + } + + return this; + } + + public function getFrameByAssetName(assetName:String):Int + { + var assetFrame:Null = assetFrameByName.get(assetName); + if (assetFrame != null) + { + return assetFrame; + } + return 0; + } + + public function clear() + { + spriteSheet.dispose(); + } + +} \ No newline at end of file diff --git a/src/assets/GraphicsLibrary.hx b/src/assets/GraphicsLibrary.hx new file mode 100644 index 0000000..829f654 --- /dev/null +++ b/src/assets/GraphicsLibrary.hx @@ -0,0 +1,183 @@ +package assets; + +import flash.display.Bitmap; +import flash.display.BitmapData; +import openfl.display.Tilesheet; +import flash.geom.Matrix; +import flash.geom.Point; +import flash.geom.Rectangle; +import openfl.Assets; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class GraphicsLibrary +{ + private static var explosionAsset:EntityGraphicsAsset; + + private static var playerAsset:EntityGraphicsAsset; + + private static var tilesAsset:EntityGraphicsAsset; + + private static var bulletAsset:EntityGraphicsAsset; + + private static var enemyBulletAsset:EntityGraphicsAsset; + + private static var teslaFlyerAsset:EntityGraphicsAsset; + + static private var bulletHitAsset:EntityGraphicsAsset; + + static private var debriesAsset:EntityGraphicsAsset; + + static private var baloonAsset:EntityGraphicsAsset; + + static private var railgunTrailAsset:EntityGraphicsAsset; + + static private var smokeAsset:EntityGraphicsAsset; + + static public var tilesheet:Tilesheet; + + public function GraphicsLibrary() + { + + } + + public static function initialize():Void + { + explosionAsset = new EntityGraphicsAsset("explosion").initializeFromAssetNames(["assets/effects/explosion1/1.png", "assets/effects/explosion1/2.png", "assets/effects/explosion1/3.png", "assets/effects/explosion1/4.png", "assets/effects/explosion1/5.png"]); + playerAsset = new EntityGraphicsAsset("player").initializeFromAssetNames(["assets/objects/player/plane01.png"]); + tilesAsset = new EntityGraphicsAsset("tile").initializeFromAssetNames(["assets/tiles/top.png", "assets/tiles/middle.png", "assets/tiles/slopeUp.png", "assets/tiles/slopeDown.png", "assets/tiles/middle2.png", "assets/tiles/top2.png"]); + + bulletAsset = new EntityGraphicsAsset("bullet").initializeFromAssetNames(["assets/effects/projectiles/beam02.png"]); + enemyBulletAsset = new EntityGraphicsAsset("enemyBullet").initializeFromAssetNames(["assets/effects/projectiles/beam01.png","assets/effects/projectiles/enemyBalloonBullet.png"]); + bulletHitAsset = new EntityGraphicsAsset("bulletHit").initializeFromAssetNames(["assets/effects/bulletHit/bulletHit.png"]); + teslaFlyerAsset = new EntityGraphicsAsset("teslaFlyer").initializeFromAssetNames(["assets/objects/enemies/tesla1.png", "assets/objects/enemies/tesla2.png", "assets/objects/enemies/tesla3.png"]); + baloonAsset = new EntityGraphicsAsset("baloon").initializeFromAssetNames(["assets/objects/enemies/foe02.png"]); + smokeAsset = new EntityGraphicsAsset("smoke").initializeFromAssetNames(["assets/effects/smoke/smoke01.png", "assets/effects/smoke/smoke02.png", "assets/effects/smoke/smoke03.png", "assets/effects/smoke/smoke04.png", "assets/effects/smoke/smoke05.png"]); + debriesAsset = new EntityGraphicsAsset("debries").initializeFromAssetNames(["assets/effects/debries/debries1.png", "assets/effects/debries/debries2.png", "assets/effects/debries/debries3.png"]); + + #if (!android && !iphone) + railgunTrailAsset = new EntityGraphicsAsset("railgunTrail").initializeFromAssetNames(["assets/effects/projectiles/railgunTrail.png"]); + #end + + #if (android || iphone) + createTilesheet([explosionAsset, playerAsset, tilesAsset, bulletAsset, enemyBulletAsset, bulletHitAsset, teslaFlyerAsset, baloonAsset, smokeAsset, debriesAsset]); + #elseif cpp + createTilesheet([explosionAsset, playerAsset, tilesAsset, debriesAsset, bulletAsset, enemyBulletAsset, bulletHitAsset, teslaFlyerAsset, baloonAsset, railgunTrailAsset, smokeAsset]); + #end + } + + static private function createTilesheet(assetArray:Array):Void + { + var maxHeight:Float = 0; + var totalWidth:Float = 0; + var assetFrameID:Int = 0; + for (i in 0...assetArray.length) + { + var asset:EntityGraphicsAsset = assetArray[i]; + + for (j in 0...asset.frameRectangles.length) + { + asset.tileSheetFrameID.push(assetFrameID); + var tilesheetRect:Rectangle = asset.frameRectangles[j].clone(); + tilesheetRect.x += totalWidth; + asset.tileSheetRectangles.push(tilesheetRect); + assetFrameID++; + } + maxHeight = Math.max(maxHeight, asset.spriteSheet.height); + totalWidth += asset.spriteSheet.width; + } + + var bitmapData:BitmapData = new BitmapData(Std.int(totalWidth), Std.int(maxHeight), true, 0); + + var currentX:Int = 0; + for (i in 0...assetArray.length) + { + var asset:EntityGraphicsAsset = assetArray[i]; + bitmapData.copyPixels(asset.spriteSheet, new Rectangle(0, 0, asset.spriteSheet.width, asset.spriteSheet.height), new Point(currentX, 0)); + currentX += asset.spriteSheet.width; + asset.clear(); + } + + tilesheet = new Tilesheet(bitmapData); + for (i in 0...assetArray.length) + { + var asset:EntityGraphicsAsset = assetArray[i]; + for (j in 0...asset.tileSheetRectangles.length) + { + tilesheet.addTileRect(asset.tileSheetRectangles[j]); + } + } + } + + public static function getExplosion1():EntityGraphicsAsset + { + return explosionAsset; + } + + public static function getPlayerShip():EntityGraphicsAsset + { + return playerAsset; + + /*if (playerAsset != null) + { + return playerAsset; + } + + var bd:BitmapData = new BitmapData(120, 50, true, 0x00000000); + var playerBitmap:BitmapData = Assets.getBitmapData("assets/objects/player/plane01.png"); + bd.copyPixels(playerBitmap, new Rectangle(0, 0, 120, 50), new Point(0, 0)); + + playerAsset = new EntityGraphicsAsset(); + playerAsset.spriteSheet = bd; + playerAsset.frameRectangles = [new Rectangle(0, 0, 120, 50)]; + playerAsset.sizeCorrection = new Point( -60, -25); + return playerAsset;*/ + } + + public static function getTiles():EntityGraphicsAsset + { + return tilesAsset; + } + + public static function getDebries():EntityGraphicsAsset + { + return debriesAsset; + } + + public static function getBullet():EntityGraphicsAsset + { + return bulletAsset; + } + + public static function getEnemyBullet():EntityGraphicsAsset + { + return enemyBulletAsset; + } + + public static function getBulletHit():EntityGraphicsAsset + { + return bulletHitAsset; + } + + public static function getTeslaFlyer():EntityGraphicsAsset + { + return teslaFlyerAsset; + } + + public static function getBaloon():EntityGraphicsAsset + { + return baloonAsset; + } + + public static function getRailgunTrail():EntityGraphicsAsset + { + return railgunTrailAsset; + } + + static public function getSmoke() + { + return smokeAsset; + } + +} \ No newline at end of file diff --git a/src/com/sphaeraobscura/keyboard/KeyKeeper.hx b/src/com/sphaeraobscura/keyboard/KeyKeeper.hx new file mode 100644 index 0000000..6bd4662 --- /dev/null +++ b/src/com/sphaeraobscura/keyboard/KeyKeeper.hx @@ -0,0 +1,65 @@ +package com.sphaeraobscura.keyboard; +import flash.display.Stage; +import flash.events.Event; +import flash.events.EventDispatcher; +import flash.events.KeyboardEvent; + +/** + * ... + * @author Dimonte + */ +class KeyKeeper extends EventDispatcher +{ + private var _stage:Stage; + private var _keysPressed:Array; + + public function new(stage:Stage) + { + super(); + _stage = stage; + initKeeper(); + } + + private function initKeeper():Void + { + _keysPressed = new Array(); + _stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, false); + _stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler, false); + _stage.addEventListener(Event.DEACTIVATE, deactivateHandler, false); + } + + private function keyDownHandler(e:KeyboardEvent):Void + { + if (!_keysPressed[e.keyCode]) + { + dispatchEvent(new KeyKeeperEvent(KeyKeeperEvent.KEY_DOWN, e.keyCode)); + } + _keysPressed[e.keyCode] = true; + } + + private function keyUpHandler(e:KeyboardEvent):Void + { + if (_keysPressed[e.keyCode]) + { + dispatchEvent(new KeyKeeperEvent(KeyKeeperEvent.KEY_UP, e.keyCode)); + } + _keysPressed[e.keyCode] = false; + } + + private function deactivateHandler(e:Event):Void + { + for (i in 0..._keysPressed.length) + { + if (_keysPressed[i]) + { + dispatchEvent(new KeyKeeperEvent(KeyKeeperEvent.KEY_UP, i)); + } + _keysPressed[i] = false; + } + } + + public function isDown(keyCode:Int):Bool + { + return _keysPressed[keyCode]; + } +} \ No newline at end of file diff --git a/src/com/sphaeraobscura/keyboard/KeyKeeperEvent.hx b/src/com/sphaeraobscura/keyboard/KeyKeeperEvent.hx new file mode 100644 index 0000000..bdce3e8 --- /dev/null +++ b/src/com/sphaeraobscura/keyboard/KeyKeeperEvent.hx @@ -0,0 +1,28 @@ +package com.sphaeraobscura.keyboard; +import flash.events.Event; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class KeyKeeperEvent extends Event +{ + + static public inline var KEY_DOWN:String = "keyDown"; + static public inline var KEY_UP:String = "keyUp"; + + public var keyCode:Int; + + public function new(type:String, keyCode:Int, bubbles:Bool = false, cancelable:Bool = false) + { + this.keyCode = keyCode; + super(type, bubbles, cancelable); + } + + override public function clone():Event + { + return new KeyKeeperEvent(type, keyCode, bubbles, cancelable); + } + +} \ No newline at end of file diff --git a/src/dataStructures/DLL.hx b/src/dataStructures/DLL.hx new file mode 100644 index 0000000..132ee55 --- /dev/null +++ b/src/dataStructures/DLL.hx @@ -0,0 +1,74 @@ +package dataStructures; + + +/** + * ... + * @author Dimonte + */ +class DLL +{ + public var _head:DLLNode; + public var _tail:DLLNode; + + public function new() + { + } + + public function head():DLLNode + { + return _head; + } + + public function append(object:Dynamic):DLLNode + { + var dllNode:DLLNode = new DLLNode(); + dllNode.val = object; + if (_head == null) + { + _head = dllNode; + _tail = dllNode; + } else { + _tail.next = dllNode; + dllNode.previous = _tail; + _tail = dllNode; + } + return dllNode; + } + + public function remove(node:DLLNode):Void + { + if (node == _head) { + _head = _head.next; + } + if (node == _tail) { + _tail = _tail.previous; + } + if (node.next != null) + { + node.next.previous = node.previous; + } + if (node.previous != null) + { + node.previous.next = node.next; + } + } + + public function clear():Void + { + _tail = null; + _head = null; + } + + public function getLength():Int + { + var length:Int = 0; + var node:DLLNode = _head; + while (node != null) + { + length++; + node = node.next; + } + return length; + } + +} \ No newline at end of file diff --git a/src/dataStructures/DLLNode.hx b/src/dataStructures/DLLNode.hx new file mode 100644 index 0000000..74626cc --- /dev/null +++ b/src/dataStructures/DLLNode.hx @@ -0,0 +1,31 @@ +package dataStructures; + +/** + * ... + * @author Dimonte + */ +class DLLNode +{ + + public var next:DLLNode; + public var previous:DLLNode; + public var val:Dynamic; + + public function new() + { + + } + + public function remove():Void + { + if (next != null) + { + next.previous = previous; + } + if (previous != null) + { + previous.next = next; + } + } + +} \ No newline at end of file diff --git a/src/game/Bullet.hx b/src/game/Bullet.hx new file mode 100644 index 0000000..0743ac5 --- /dev/null +++ b/src/game/Bullet.hx @@ -0,0 +1,80 @@ +package game; + +import assets.GraphicsLibrary; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.shapes.BaseShape; +import game.GameEntity; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class Bullet extends GameEntity +{ + private var timePassedSinceLastUpdate:Float; + + public function new(world:GameWorld) + { + super(world); + + type = EntityType.PLAYER_BULLET; + + graphicsAsset = GraphicsLibrary.getBullet(); + + collisionCategory = CollisionCategory.PLAYER_BULLET; + collisionMask = CollisionCategory.TILE | CollisionCategory.ENEMY; + unguidedProjectile = true; + gridBound = true; + /* + var s:Polygon = new Polygon(); + s.setAsBox(1, 1); + /*/ + var s:CircleShape = new CircleShape(0,0,6); + //*/ + s.sensor = true; + addShape(s); + init(); + } + + override public function reset():Void + { + super.reset(); + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + cast(collidingBody, GameEntity).recieveDamage(12); + + var bh:GameEntity = world.getReusableEntityByType(EntityType.BULLET_HIT); + bh.reset(); + bh.x = x; + bh.y = y; + world.addParticle(bh); + + dead = true; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + timePassedSinceLastUpdate += dTime; + while (timePassedSinceLastUpdate > 0.035) + { + timePassedSinceLastUpdate-= 0.035; + speed.y *= 0.98; + } + + #if (!android && !iphone) + if (Math.random() < 6*dTime) + { + var trail:GameEntity = world.getReusableEntityByType(EntityType.RAILGUN_TRAIL); + trail.reset(); + trail.position = position.clone(); + trail.speed = speed.clone(); + world.addParticle(trail); + } + #end + } + +} \ No newline at end of file diff --git a/src/game/BulletHit.hx b/src/game/BulletHit.hx new file mode 100644 index 0000000..8b2c2ac --- /dev/null +++ b/src/game/BulletHit.hx @@ -0,0 +1,40 @@ +package game; +import assets.GraphicsLibrary; + +//import assets.GraphicsLibrary; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class BulletHit extends GameEntity +{ + private var counter:Float; + + public function new(world:GameWorld) + { + super(world); + counter = 0; + type = EntityType.BULLET_HIT; + graphicsAsset = GraphicsLibrary.getBulletHit(); + gridBound = true; + unguidedProjectile = true; + init(); + } + + override public function reset():Void + { + super.reset(); + counter = 0; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + counter+=dTime; + if (counter > 0.2) + { + dead = true; + } + } + +} \ No newline at end of file diff --git a/src/game/CollisionCategory.hx b/src/game/CollisionCategory.hx new file mode 100644 index 0000000..72aaf5d --- /dev/null +++ b/src/game/CollisionCategory.hx @@ -0,0 +1,19 @@ +package game; + +/** + * ... + * @author Dimonte + */ +class CollisionCategory +{ + public static inline var INHERIT:Int = 0x00000000; + + public static inline var PLAYER:Int = 0x00000001; + public static inline var TILE:Int = 0x00000002; + public static inline var LAND_OBJECT:Int = 0x00000004; + public static inline var ENEMY:Int = 0x00000008; + public static inline var PLAYER_BULLET:Int = 0x00000010; + public static inline var ENEMY_BULLET:Int = 0x00000020; + public static inline var PARTICLE:Int = 0x00000040; + static public inline var IGNORE:Int = 0x10000000; +} \ No newline at end of file diff --git a/src/game/Debries.hx b/src/game/Debries.hx new file mode 100644 index 0000000..17b190d --- /dev/null +++ b/src/game/Debries.hx @@ -0,0 +1,96 @@ +package game; + +//import assets.GraphicsLibrary; +import assets.GraphicsLibrary; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.shapes.BaseShape; +import game.GameEntity; +import sphaeraGravita.shapes.CircleShape; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class Debries extends GameEntity +{ + private var score:Int; + + public function new(world:GameWorld) + { + super(world); + + type = EntityType.DEBRIES; + + graphicsAsset = GraphicsLibrary.getDebries(); + + collisionCategory = CollisionCategory.PARTICLE; + + gridBound = true; + unguidedProjectile = true; + + bounceFactor = 0.5; + frictionFactor = 1; + + selectGraphicsAndScore(); + + var shape:CircleShape = new CircleShape(0, 0, 6); + shape.collisionMask = CollisionCategory.TILE; + addShape(shape); + + var sensorShape:CircleShape = new CircleShape(0, 0, 6); + sensorShape.sensor = true; + sensorShape.collisionMask = CollisionCategory.PLAYER; + addShape(sensorShape); + init(); + } + + override public function reset():Void + { + super.reset(); + collisionMask = CollisionCategory.TILE | CollisionCategory.PLAYER; + selectGraphicsAndScore(); + } + + override public function update(dTime:Float):Void + { + speed.y += 400*dTime; + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + super.reactToCollision(collidingBody, selfShape, otherShape); + + if (collidingBody.collisionCategory == CollisionCategory.PLAYER) + { + world.score += score; + dead = true; + return; + } + + speed.x *= 0.2; + if (speed.y <= 0) + { + speed.y = Math.min(speed.y, -5); + } + collisionMask = CollisionCategory.PLAYER; + } + + private function selectGraphicsAndScore():Void + { + if (Math.random() > 0.3) + { + frameRectNum = 2; + score = 100; + } + else if (Math.random() > 0.3) + { + frameRectNum = 0; + score = 75; + } + else + { + frameRectNum = 1; + score = 50; + } + } + +} \ No newline at end of file diff --git a/src/game/EnemyBullet.hx b/src/game/EnemyBullet.hx new file mode 100644 index 0000000..2e44eeb --- /dev/null +++ b/src/game/EnemyBullet.hx @@ -0,0 +1,55 @@ +package game; + +import assets.GraphicsLibrary; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.CircleShape; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class EnemyBullet extends GameEntity +{ + public var bulletDamage:Int; + + public function new(world:GameWorld) + { + bulletDamage = 20; + + super(world); + + type = EntityType.ENEMY_BULLET; + + graphicsAsset = GraphicsLibrary.getEnemyBullet(); + + collisionCategory = CollisionCategory.ENEMY_BULLET; + collisionMask = CollisionCategory.TILE | CollisionCategory.PLAYER; + unguidedProjectile = true; + gridBound = true; + /* + var s:Polygon = new Polygon(); + s.setAsBox(1, 1); + /*/ + var s:CircleShape = new CircleShape(0,0,6); + //*/ + s.sensor = true; + addShape(s); + init(); + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + cast(collidingBody, GameEntity).recieveDamage(bulletDamage); + var bh:GameEntity = world.getReusableEntityByType(EntityType.BULLET_HIT); + bh.x = x; + bh.y = y; + world.addParticle(bh); + dead = true; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + } + +} \ No newline at end of file diff --git a/src/game/EnemyShip.hx b/src/game/EnemyShip.hx new file mode 100644 index 0000000..d121f9f --- /dev/null +++ b/src/game/EnemyShip.hx @@ -0,0 +1,250 @@ +package game; + +import assets.GraphicsLibrary; +import game.behaviours.BaloonBehaviour; +import game.behaviours.BasicBehaviour; +import game.behaviours.IBehaviour; +import game.behaviours.KamikazeBaloonBehaviour; +import game.behaviours.TeslaBehaviourFrontalAssault; +import game.behaviours.TeslaBehaviourRam; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.shapes.BaseShape; +import game.GameEntity; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class EnemyShip extends GameEntity +{ + public static inline var TESLA:String = "tesla"; + public static inline var BALOON:String = "baloon"; + + public var shipType:String; + public var shotDown:Bool; + private var counter:Float; + public var behaviour:IBehaviour; + + private var smokeCounter:Float; + + public function new(world:GameWorld) + { + super(world); + + type = EntityType.ENEMY_SHIP; + + collisionCategory = CollisionCategory.ENEMY; + collisionMask = CollisionCategory.PLAYER_BULLET | CollisionCategory.PLAYER; + + shipType = Math.random() > 0.6 ? TESLA : BALOON; + + if (shipType == TESLA) + { + createAsTesla(); + } + else + { + createAsBalloon(); + } + + counter = 0; + smokeCounter = 0; + + init(); + } + + override public function reset():Void + { + super.reset(); + + clearShapes(); + rotation = 0; + speed.x = 0; + speed.y = 0; + counter = 0; + smokeCounter = 0; + + collisionCategory = CollisionCategory.ENEMY; + collisionMask = CollisionCategory.PLAYER_BULLET | CollisionCategory.PLAYER; + + shotDown = false; + unguidedProjectile = false; + + shipType = Math.random() > 0.6 ? TESLA : BALOON; + + if (shipType == TESLA) + { + createAsTesla(); + } + else + { + createAsBalloon(); + } + + init(); + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + cast(collidingBody, GameEntity).recieveDamage(5); + if (shotDown) + { + if (Type.getClass(collidingBody) == Tile) + { + die(); + } + } + } + + public function die():Void + { + dead = true; + var exp:GameEntity = world.getReusableEntityByType(EntityType.EXPLOSION); + exp.position = position.clone(); + world.addParticle(exp); + + var debriesChance:Float = shipType == TESLA ? 0.8 : 0.6; + var maxNumber:Int = shipType == TESLA ? 6 : 2; + var minNumber:Int = shipType == TESLA ? 3 : 1; + + + while (Math.random() < debriesChance || minNumber > 0) + { + var debries:GameEntity = world.getReusableEntityByType(EntityType.DEBRIES); + debries.position.x = x; + debries.position.y = y; + debries.speed.x = (Math.random() * 10 - 5)*30; + debries.speed.y = (-Math.random() * 5 - 5)*30; + world.addParticle(debries); + minNumber--; + if (--maxNumber < 1) + { + break; + } + } + + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + if (behaviour != null) + { + behaviour.update(dTime); + } + if (x < world.activeZoneStartMarker - 60) + { + dead = true; + } + + if (!dead && shotDown) + { + if (smokeCounter > 0.125) + { + var smokeParticle:GameEntity = world.getReusableEntityByType(EntityType.SMOKE); + smokeParticle.position.x = position.x + 5; + smokeParticle.position.y = position.y - 5; + world.addParticle(smokeParticle); + smokeCounter = 0; + } + else + { + smokeCounter+=dTime; + } + } + + } + + public function shootAtPlayer():Void + { + var player:GameEntity = world.player; + var dx:Int = Std.int(player.x - x); + dx = Std.int(dx* 0.9); + var dy:Int = Std.int(player.y - y); + var angle:Float = Math.atan2(dy, dx); + var bullet:GameEntity = world.getReusableEntityByType(EntityType.ENEMY_BULLET); + bullet.position.x = x; + bullet.position.y = y; + bullet.speed.x = 360*Math.cos(angle); + bullet.speed.y = 360*Math.sin(angle); + world.addEnemyBullet(bullet); + } + + public function shoot(angle:Float, speed:Float):Void + { + var bullet:GameEntity = world.getReusableEntityByType(EntityType.ENEMY_BULLET); + bullet.position.y = y; + bullet.speed.x = speed*Math.cos(angle); + bullet.speed.y = speed * Math.sin(angle); + if (shipType == TESLA) + { + bullet.frameRectNum = 0; + bullet.position.x = x - 26; + cast(bullet, EnemyBullet).bulletDamage = 15; + } + else + { + bullet.position.x = x; + bullet.frameRectNum = 1; + cast(bullet, EnemyBullet).bulletDamage = 30; + } + world.addEnemyBullet(bullet); + } + + override public function recieveDamage(damageAmount:Int):Void + { + super.recieveDamage(damageAmount); + if (Type.getClass(behaviour) == BasicBehaviour) + { + cast(behaviour, BasicBehaviour).respondToDamage(); + } + if (shipType == TESLA) + { + if (healthPoints < 0) + { + frameRectNum = 2; + } else if (healthPoints < 100) + { + frameRectNum = 1; + } + } + } + + private function createAsBalloon():Void + { + graphicsAsset = GraphicsLibrary.getBaloon(); + var circle:CircleShape= new CircleShape(-10,0,12); + circle.sensor = true; + addShape(circle); + healthPoints = 100; + speed.x = Std.int(Math.random() * -2 - 1) *10; + if (Math.random() > 0.5) + { + behaviour = new BaloonBehaviour(this); + } else + { + behaviour = new KamikazeBaloonBehaviour(this); + } + } + + private function createAsTesla():Void + { + graphicsAsset = GraphicsLibrary.getTeslaFlyer(); + var shape:Polygon = new Polygon(); + shape.sensor = true; + shape.setAsBox(50, 12); + addShape(shape); + healthPoints = 200; + if (Math.random() > 0.7) + { + speed.x = Std.int(Math.random() * -4 - 4)*40; + behaviour = new TeslaBehaviourRam(this); + } else + { + speed.x = Std.int(Math.random() * -6 - 1)*40; + behaviour = new TeslaBehaviourFrontalAssault(this); + } + } + +} \ No newline at end of file diff --git a/src/game/EntityType.hx b/src/game/EntityType.hx new file mode 100644 index 0000000..abc07d9 --- /dev/null +++ b/src/game/EntityType.hx @@ -0,0 +1,23 @@ +package game; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class EntityType +{ + + static public inline var PLAYER:String = "player"; + static public inline var TILE:String = "tile"; + static public inline var PLAYER_BULLET:String = "playerBullet"; + static public inline var ENEMY_BULLET:String = "enemyBullet"; + static public inline var BULLET_HIT:String = "bulletHit"; + static public inline var RAILGUN_TRAIL:String = "railgunTrail"; + static public inline var ENEMY_SHIP:String = "enemyShip"; + static public inline var DEBRIES:String = "debries"; + static public inline var EXPLOSION:String = "explosion"; + static public inline var SMOKE:String = "smoke"; + static public inline var UNKNOWN:String = "unknown"; + +} \ No newline at end of file diff --git a/src/game/Explosion.hx b/src/game/Explosion.hx new file mode 100644 index 0000000..31ef8e0 --- /dev/null +++ b/src/game/Explosion.hx @@ -0,0 +1,42 @@ +package game; + +//import assets.GraphicsLibrary; +import assets.GraphicsLibrary; +import sphaeraGravita.shapes.CircleShape; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class Explosion extends GameEntity +{ + private var counter:Float; + + public function new(world:GameWorld) + { + super(world); + type = EntityType.EXPLOSION; + graphicsAsset = GraphicsLibrary.getExplosion1(); + gridBound = true; + unguidedProjectile = true; + init(); + counter = 0; + } + + override public function reset():Void + { + super.reset(); + counter = 0; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + counter+=dTime; + frameRectNum = Std.int(counter*5*1.25); + if (counter >= 0.8) + { + dead = true; + } + } + +} \ No newline at end of file diff --git a/src/game/GameEntity.hx b/src/game/GameEntity.hx new file mode 100644 index 0000000..c8be2a3 --- /dev/null +++ b/src/game/GameEntity.hx @@ -0,0 +1,52 @@ +package game; + +import assets.EntityGraphicsAsset; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.shapes.BaseShape; +/** + * ... + * @author Dimonte + */ +class GameEntity extends PhysicalBody +{ + public var world:GameWorld; + public var healthPoints:Int; + public var unguidedProjectile:Bool; + public var graphicsAsset:EntityGraphicsAsset; + public var frameRectNum:Int; + public var type:String; + + public function new(world:GameWorld) + { + this.world = world; + type = EntityType.UNKNOWN; + super(); + } + + public function reset():Void + { + dead = false; + frameRectNum = 0; + } + + public function destroy():Void + { + dead = true; + } + + public function update(dTime:Float):Void + { + + } + + public function doDamage():Void + { + + } + + public function recieveDamage(damageAmount:Int):Void + { + healthPoints -= damageAmount; + } + +} \ No newline at end of file diff --git a/src/game/GameEvent.hx b/src/game/GameEvent.hx new file mode 100644 index 0000000..1a291c3 --- /dev/null +++ b/src/game/GameEvent.hx @@ -0,0 +1,23 @@ +package game; +import flash.events.Event; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class GameEvent extends Event +{ + static public inline var GAME_OVER:String = "gameOver"; + + public function new(type:String, bubbles:Bool = false, cancelable:Bool = false) + { + super(type, bubbles, cancelable); + } + + override public function clone():Event + { + return new GameEvent(type, bubbles, cancelable); + } + +} \ No newline at end of file diff --git a/src/game/GameStage.hx b/src/game/GameStage.hx new file mode 100644 index 0000000..2fec3b3 --- /dev/null +++ b/src/game/GameStage.hx @@ -0,0 +1,143 @@ +package game; + +import com.sphaeraobscura.keyboard.KeyKeeper; +import flash.events.EventDispatcher; +//import utils.logger.Logger; +/** + * ... + * @author ... + */ +class GameStage extends EventDispatcher +{ + /** + * Speed of moving through level in pixels/second. + */ + static private inline var ACTIVE_ZONE_SHIFT:Float= 60; + + public var gameWorld:GameWorld; + public var player:PlayerShip; + public var playerController:PlayerController; + private var loadedLevel:Level; + private var gameOver:Bool; + private var activeZoneWidth:Int; + private var activeZoneHeight:Int; + + + + public function new(activeZoneWidth:Int, activeZoneHeight:Int) + { + super(); + this.activeZoneWidth = activeZoneWidth; + this.activeZoneHeight = activeZoneHeight; + gameWorld = new GameWorld(activeZoneWidth, activeZoneHeight); + } + + public function initializeStage():Void + { + gameWorld.clear(); + player = new PlayerShip(gameWorld); + player.position.x = 60; + player.position.y = 100; + playerController = new PlayerController(player); + gameWorld.addActiveEntity(player); + gameWorld.player = player; + + loadLevel(new Level(activeZoneWidth, activeZoneHeight)); + + gameOver = false; + } + + public function loadLevel(level:Level):Void + { + loadedLevel = level; + //Logger.log("level.tiles.length : " + level.tiles.length); + + level.tiles.sort(sortEntityOnX); + + level.enemies.sort(sortEntityOnX); + } + + private function sortEntityOnX(a:LevelObjectTemplate, b:LevelObjectTemplate):Int + { + if (a.position.x < b.position.x) + { + return 1; + } + if (a.position.x > b.position.x) + { + return -1; + } + if (a.position.x == b.position.x) + { + return 0; + } + return 0; + } + + private function spawnTiles():Void + { + while (loadedLevel.tiles.length > 0) + { + var tileTemplate:LevelObjectTemplate = loadedLevel.tiles[loadedLevel.tiles.length-1]; + if (tileTemplate.position.x <= gameWorld.activeZoneStartMarker + activeZoneWidth + 60) + { + var tile:Tile = cast(gameWorld.getReusableEntityByType(EntityType.TILE), Tile); + tile.position = tileTemplate.position; + tile.createFromTemplate(cast(tileTemplate, TileTemplate).tileTemplate); + gameWorld.addTile(tile); + loadedLevel.tiles.pop(); + } else + { + break; + } + } + } + + private function spawnEnemies():Void + { + while (loadedLevel.enemies.length > 0) + { + var enemyTemplate:LevelObjectTemplate = loadedLevel.enemies[loadedLevel.enemies.length-1]; + if (enemyTemplate.position.x <= gameWorld.activeZoneStartMarker + activeZoneWidth + 60) + { + var enemy:GameEntity = gameWorld.getReusableEntityByType(EntityType.ENEMY_SHIP); + enemy.x = enemyTemplate.position.x; + enemy.y = enemyTemplate.position.y; + gameWorld.addEnemy(enemy); + loadedLevel.enemies.pop(); + } else + { + break; + } + } + } + + public function update(dTime:Float):Void + { + if (!player.dead) + { + + gameWorld.activeZoneStartMarker += ACTIVE_ZONE_SHIFT*dTime; + player.x += 60*dTime; + + playerController.update(dTime); + + spawnEnemies(); + + spawnTiles(); + } + else + { + if (!gameOver) + { + gameOver = true; + dispatchEvent(new GameEvent(GameEvent.GAME_OVER)); + } + } + + + + gameWorld.update(dTime); + } + +} \ No newline at end of file diff --git a/src/game/GameWorld.hx b/src/game/GameWorld.hx new file mode 100644 index 0000000..8e40d55 --- /dev/null +++ b/src/game/GameWorld.hx @@ -0,0 +1,365 @@ +package game; + +import dataStructures.DLL; +import dataStructures.DLLNode; +import flash.errors.Error; +import game.CollisionCategory; +import game.GameEntity; +import haxe.ds.GenericStack; +import haxe.ds.StringMap; +import sphaeraGravita.collision.CollisionEngine; +import sphaeraGravita.spacePartitioning.GridCell; +import sphaeraGravita.spacePartitioning.UniformGrid; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class GameWorld +{ + public var activeZoneStartMarker:Float; + + public var collisionEngine:CollisionEngine; + + public var grid:UniformGrid; + + public var player:PlayerShip; + public var players:DLL; + public var tiles:DLL; + //public var stationaryObjects:DLL; + public var particles:DLL; + public var enemies:DLL; + public var playerBullets:DLL; + public var enemyBullets:DLL; + + public var score:Int; + + private var reuseLists:StringMap>; + + private var activeZoneWidth:Int; + private var activeZoneHeight:Int; + + public function new(activeZoneWidth:Int, activeZoneHeight:Int) + { + this.activeZoneWidth = activeZoneWidth; + this.activeZoneHeight = activeZoneHeight; + + activeZoneStartMarker = 0; + reuseLists = new StringMap(); + collisionEngine = new CollisionEngine(); + players = new DLL(); + playerBullets = new DLL(); + enemyBullets = new DLL(); + tiles = new DLL(); + enemies = new DLL(); + particles = new DLL(); + grid = new UniformGrid(); + grid.initialize(Level.LEVEL_WIDTH, Math.ceil(activeZoneHeight/40), 4); + } + + public function clear():Void + { + player = null; + players.clear(); + tiles.clear(); + //stationaryObjects.clear(); + particles.clear(); + enemies.clear(); + playerBullets.clear(); + enemyBullets.clear(); + + grid.initialize(Level.LEVEL_WIDTH, Math.ceil(activeZoneHeight/40), 4); + score = 0; + activeZoneStartMarker = 0; + } + + private function initializeFixedEntities():Void + { + + } + + public function addActiveEntity(gameEntity:GameEntity):Void + { + players.append(gameEntity); + } + + public function addEnemy(enemy:GameEntity):Void + { + enemies.append(enemy); + } + + public function addPlayerBullet(gameEntity:GameEntity):Void + { + playerBullets.append(gameEntity); + } + + public function addEnemyBullet(gameEntity:GameEntity):Void + { + enemyBullets.append(gameEntity); + } + + public function addFixedEntiry(gameEntity:GameEntity):Void + { + tiles.append(gameEntity); + gameEntity.updateWorldCache(); + } + + public function addTile(tile:Tile):Void + { + tiles.append(tile); + tile.updateWorldCache(); + grid.placeTile(tile); + } + + public function addParticle(particle:GameEntity):Void + { + particle.updateWorldCache(); + grid.placeActiveObject(particle); + particles.append(particle); + } + + public function update(dTime:Float):Void + { + grid.clean(); + + //trace(playerBullets.length); + + updatePositionsInList(players, dTime); + if (player.worldAABB.lowerBound.x < activeZoneStartMarker) + { + player.position.x += activeZoneStartMarker - player.worldAABB.lowerBound.x; + player.updateWorldCache(); + } + + if (player.worldAABB.upperBound.x > activeZoneStartMarker+activeZoneWidth) + { + player.position.x += activeZoneStartMarker + activeZoneWidth - player.worldAABB.upperBound.x; + player.updateWorldCache(); + } + + if (player.worldAABB.lowerBound.y < 0) + { + player.position.y += 0 - player.worldAABB.lowerBound.y; + player.updateWorldCache(); + } + + if (player.worldAABB.upperBound.y > activeZoneHeight && player.healthPoints > 0) + { + player.position.y += activeZoneHeight - player.worldAABB.upperBound.y; + player.updateWorldCache(); + } + + updateTiles(); + + updatePositionsInList(playerBullets, dTime); + updatePositionsInList(enemyBullets, dTime); + updatePositionsInList(enemies, dTime); + updatePositionsInList(particles, dTime); + + collideObjectWithGrid(player); + collideListWithList(players, enemies); + collideListWithList(players, particles); + collideListWithGrid(enemies, grid); + collideListWithGrid(playerBullets, grid); + collideListWithGrid(enemyBullets, grid); + collideListWithGrid(particles, grid); + + updateLogicInList(players, dTime); + updateLogicInList(playerBullets, dTime); + updateLogicInList(enemies, dTime); + updateLogicInList(particles, dTime); + } + + private function updateTiles() + { + var activeBodyNode:DLLNode = tiles._head; + var activeBody:GameEntity; + while (activeBodyNode != null) + { + activeBody = cast(activeBodyNode.val, GameEntity); + if (activeBody.worldAABB.upperBound.x < activeZoneStartMarker) + { + tiles.remove(activeBodyNode); + placeEntityForReuse(activeBody); + } + + activeBodyNode = activeBodyNode.next; + } + } + + public function updatePositionsInList(list:DLL, dTime:Float):Void + { + var activeBodyNode:DLLNode = list._head; + var activeBody:GameEntity; + while (activeBodyNode != null) + { + activeBody = cast(activeBodyNode.val, GameEntity); + if (activeBody.dead) + { + list.remove(activeBodyNode); //TODO transfer to logic update? + placeEntityForReuse(activeBody); + } else { + activeBody.position.x += activeBody.speed.x*dTime; + activeBody.position.y += activeBody.speed.y*dTime; + activeBody.updateWorldCache(); + if (activeBody.gridBound) + { + grid.placeActiveObject(activeBody); + } + if (activeBody.unguidedProjectile) + { + if (!activeBody.inBounds(activeZoneStartMarker, 0, activeZoneWidth, activeZoneHeight)) + { + activeBody.dead = true; + } + } + } + + activeBodyNode = activeBodyNode.next; + } + } + + public function placeEntityForReuse(activeBody:GameEntity) + { + if (activeBody.type == EntityType.UNKNOWN) + { + throw new Error("Unknown type of reusable asset"); + return; + } + var reuseList:GenericStack = reuseLists.get(activeBody.type); + if (reuseList == null) + { + reuseList = new GenericStack(); + reuseLists.set(activeBody.type, reuseList); + } + reuseList.add(activeBody); + } + + public function getReusableEntityByType(type:String):GameEntity + { + var newEntity:GameEntity = null; + + var reuseList:GenericStack = reuseLists.get(type); + if (reuseList != null) + { + if (reuseList.head != null) + { + newEntity = reuseList.pop(); + newEntity.reset(); + return newEntity; + } + } + + switch (type) + { + case EntityType.BULLET_HIT: + newEntity = new BulletHit(this); + case EntityType.ENEMY_BULLET: + newEntity = new EnemyBullet(this); + case EntityType.PLAYER: + newEntity = new PlayerShip(this); + case EntityType.PLAYER_BULLET: + newEntity = new Bullet(this); + case EntityType.RAILGUN_TRAIL: + newEntity = new RailgunTrail(this); + case EntityType.ENEMY_SHIP: + newEntity = new EnemyShip(this); + case EntityType.DEBRIES: + newEntity = new Debries(this); + case EntityType.EXPLOSION: + newEntity = new Explosion(this); + case EntityType.TILE: + newEntity = new Tile(this); + case EntityType.SMOKE: + newEntity = new SmokeParticle(this); + default: + newEntity = new GameEntity(this); + } + + return newEntity; + } + + public function updateLogicInList(list:DLL, dTime:Float):Void + { + var activeBodyNode:DLLNode = list._head; + var activeBody:GameEntity; + while (activeBodyNode != null) + { + + activeBody = cast(activeBodyNode.val, GameEntity); + activeBodyNode = activeBodyNode.next; + activeBody.update(dTime); + + } + } + + public function collideListWithList(listOne:DLL, listTwo:DLL):Void + { + var listOneNode:DLLNode = listOne._head; + var listOneEntity:GameEntity; + while (listOneNode != null) + { + listOneEntity = cast(listOneNode.val, GameEntity); + var listTwoNode:DLLNode = listTwo._head; + var listTwoEntity:GameEntity; + while (listTwoNode != null) + { + listTwoEntity = cast(listTwoNode.val, GameEntity); + collisionEngine.collideBodies(listOneEntity, listTwoEntity); + listTwoNode = listTwoNode.next; + } + listOneNode = listOneNode.next; + } + } + + public function collideObjectWithGrid(object:GameEntity):Void + { + if (object.collisionCategory == CollisionCategory.IGNORE) + return; + + var coveredCells:Array; + if (object.gridBound) + { + coveredCells = object.overlappingCells; + } else + { + coveredCells = grid.getCellsBetweenPoints(object.worldAABB.lowerBound, object.worldAABB.upperBound); + } + var cellListNode:DLLNode; + var cellObject:GameEntity; + //trace("coveredCells.length: " + coveredCells.length); + for (i in 0...coveredCells.length) + { + cellListNode = coveredCells[i].fixedObjectList._head; + while (cellListNode != null) + { + cellObject = cast(cellListNode.val, GameEntity); + + if (cellObject != object) + collisionEngine.collideBodies(object, cellObject); + + cellListNode = cellListNode.next; + } + cellListNode = coveredCells[i].activeObjectList._head; + while (cellListNode != null) + { + cellObject = cast(cellListNode.val, GameEntity); + + if (cellObject != object) + collisionEngine.collideBodies(object, cellObject); + + cellListNode = cellListNode.next; + } + } + } + + public function collideListWithGrid(list:DLL, grid:UniformGrid):Void + { + var listNode:DLLNode = list._head; + while (listNode != null) + { + collideObjectWithGrid(cast(listNode.val, GameEntity)); + listNode = listNode.next; + } + } + +} \ No newline at end of file diff --git a/src/game/Level.hx b/src/game/Level.hx new file mode 100644 index 0000000..7f5ba81 --- /dev/null +++ b/src/game/Level.hx @@ -0,0 +1,288 @@ +package game; + +import game.TileTemplate; +import haxe.ds.IntMap.IntMap; + +/** + * ... + * @author Dimonte + */ +class Level +{ + + static public inline var LEVEL_WIDTH:Int = 600; + public var tiles:Array; + public var enemies:Array; + private var surroundingTiles:Array; + private var levelHeight:Int; + private var activeZoneWidth:Int; + private var activeZoneHeight:Int; + + static public var templatePriority:Array = + { + [TilePositionTemplate.middle, TilePositionTemplate.slopeUp, TilePositionTemplate.slopeDown, TilePositionTemplate.top ]; + + } + + public function new(activeZoneWidth:Int, activeZoneHeight:Int) + { + this.activeZoneWidth = activeZoneWidth; + this.activeZoneHeight = activeZoneHeight; + this.levelHeight = Math.ceil(activeZoneHeight/40); + surroundingTiles = new Array(); + tiles = new Array(); + enemies = new Array(); + var normalHeight:Int = 2; + var previousHeight:Int = normalHeight; + var height:Int = previousHeight; + var heightChangeSpeed:Int = 0; + var tileGrid:TileGrid = new TileGrid(LEVEL_WIDTH, levelHeight); + + var tileTemplate:TileTemplate; + for (i in 0...LEVEL_WIDTH) + { + var heightChangeSpeedChange:Int = Std.int(Math.random() * 2) + Std.int(Math.random() * 2) - 1; + if (height > normalHeight && heightChangeSpeed > 0) { + heightChangeSpeedChange += Math.round((normalHeight - height) / 1); + } + if (height < normalHeight && heightChangeSpeed < 0) { + heightChangeSpeedChange += Math.round((normalHeight - height) / 1); + } + heightChangeSpeed += heightChangeSpeedChange; + height += heightChangeSpeed; + + for (j in 0...height) + { + tileTemplate = new TileTemplate(); + tileTemplate.tileGridX = i; + tileTemplate.tileGridY = levelHeight - 1 - j; + tileTemplate.position.x = i * 40 + 20; + tileTemplate.position.y = Std.int(levelHeight - 1 - j) * 40 + 20; + tiles.push(tileTemplate); + tileGrid.addTileAt(i, levelHeight - 1 - j, tileTemplate); + } + previousHeight = height; + } + + for (i in 0...tiles.length) + { + tileTemplate = cast(tiles[i], TileTemplate); + findTemplateForTile(tileTemplate, tileGrid); + } + + for (i in 0...160) + { + + var diffMod:Float = (160 - i) / 160 - 0.4; + var minShips:Int = Std.int(i / 40) +1; + var shipsAdded:Int = 0; + + while (Math.random() > diffMod || shipsAdded < minShips) + { + diffMod += 0.05; + var enemyShipTemplate:LevelObjectTemplate = new LevelObjectTemplate(); + enemyShipTemplate.position.x = i * 90 + activeZoneWidth + Math.random()*90; + enemyShipTemplate.position.y = Math.random() * activeZoneHeight/2 + 40; + enemies.push(enemyShipTemplate); + shipsAdded++; + } + } + + tileGrid = null; + } + + private function findTemplateForTile(tileTemplate:TileTemplate, tileGrid:TileGrid):Void + { + //To match templates, reading in column/row + for (j in 0...3) + { + for (i in 0...3) + { + surroundingTiles[i+j*3] = tileGrid.isTileAt(i + tileTemplate.tileGridX - 1, j + tileTemplate.tileGridY - 1); + } + } + + var matchFound:Bool = false; + var tilePositionTemplate:TilePositionTemplate = null; + var positionTemplate:Array; + for (i in 0...templatePriority.length) + { + tilePositionTemplate = templatePriority[i]; + positionTemplate = tilePositionTemplate.template; + matchFound = true; + for (j in 0...positionTemplate.length) + { + if (positionTemplate[j] == -1) + { + continue; + } + if (positionTemplate[j] == 0) + { + if (surroundingTiles[j]) + { + matchFound = false; + break; + } + } + if (positionTemplate[j] == 1) + { + if (!surroundingTiles[j]) + { + matchFound = false; + break; + } + } + } + if (matchFound) + { + break; + } + } + + if (!matchFound) + { + tilePositionTemplate = TilePositionTemplate.top; + } + + tileTemplate.tileTemplate = tilePositionTemplate.code; + + } + +} + +class TileGrid +{ + private var standInTile:TileTemplate; + private var tileHash:IntMap>; + private var width:Int; + private var height:Int; + + public function new(width:Int, height:Int) + { + standInTile = new TileTemplate(); + this.width = width; + this.height = height; + tileHash = new IntMap(); + var tileColumnHash:IntMap; + for (i in 0...width) + { + tileColumnHash = new IntMap(); + tileHash.set(i, tileColumnHash); + } + } + + public function addTileAt(x:Int, y:Int, tileTemplate:TileTemplate):Void + { + tileHash.get(x).set(y, tileTemplate); + } + + public function getTileAt(x:Int, y:Int):Null + { + if (x < 0) + { + return null; + } + if (x >= width) + { + return null; + } + if (y < 0) + { + return null; + } + if (y >= height) + { + return standInTile; + } + return tileHash.get(x).get(y); + } + + public function isTileAt(x:Int, y:Int):Bool + { + if (x < 0) + { + return false; + } + if (x >= width) + { + return false; + } + if (y < 0) + { + return false; + } + if (y >= height) + { + return true; + } + return tileHash.get(x).get(y) != null; + } +} + +class TilePositionTemplate +{ + + static public var slopeUp:TilePositionTemplate = + { + var tilePosTemp:TilePositionTemplate = new TilePositionTemplate(); + tilePosTemp.template = + [ -1, 0, -1, + 0, 1, 1, + -1, 1, 1] + ; + + /*tilePosTemp.template = + [ -1, -1, -1, + -1, -1, -1, + -1, -1, -1] + ;*/ + + tilePosTemp.code = Tile.SLOPE_UP; + tilePosTemp; + } + + static public var slopeDown:TilePositionTemplate = + { + var tilePosTemp:TilePositionTemplate = new TilePositionTemplate(); + tilePosTemp.template = + [ -1, 0, -1, + 1, 1, 0, + 1, 1, -1] + ; + tilePosTemp.code = Tile.SLOPE_DOWN; + tilePosTemp; + } + + static public var middle:TilePositionTemplate = + { + var tilePosTemp:TilePositionTemplate = new TilePositionTemplate(); + tilePosTemp.template = + [ -1, 1, -1, + -1, 1, -1, + -1, 1, -1] + ; + tilePosTemp.code = Tile.MIDDLE; + tilePosTemp; + } + + static public var top:TilePositionTemplate = + { + var tilePosTemp:TilePositionTemplate = new TilePositionTemplate(); + tilePosTemp.template = + [ -1, 0, -1, + -1, 1, -1, + -1, 1, -1] + ; + tilePosTemp.code = Tile.TOP; + tilePosTemp; + } + + + public var template:Array; + public var code:String; + + public function new() + { + + } +} \ No newline at end of file diff --git a/src/game/LevelObjectTemplate.hx b/src/game/LevelObjectTemplate.hx new file mode 100644 index 0000000..3103f1b --- /dev/null +++ b/src/game/LevelObjectTemplate.hx @@ -0,0 +1,19 @@ +package game; +import sphaeraGravita.math.Vector2D; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class LevelObjectTemplate +{ + + public var position:Vector2D; + + public function new() + { + position = new Vector2D(); + } + +} \ No newline at end of file diff --git a/src/game/PlayerController.hx b/src/game/PlayerController.hx new file mode 100644 index 0000000..ecf9eca --- /dev/null +++ b/src/game/PlayerController.hx @@ -0,0 +1,87 @@ +package game; +import game.PlayerShip; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class PlayerController +{ + private var horizontalAccelerationMax:Float; + private var verticalAccelerationMax:Float; + + private var player:PlayerShip; + + private var horizontalAcceleration:Float; + private var verticalAcceleration:Float; + private var shootOnUpdate:Bool; + + public function new(player:PlayerShip) + { + this.player = player; + horizontalAccelerationMax = 3000; + verticalAccelerationMax = 3000; + horizontalAcceleration = 0; + verticalAcceleration = 0; + } + + public function accelerateRight(?magnitude:Float = 1.0):Void + { + horizontalAcceleration += magnitude; + } + + public function accelerateLeft(?magnitude:Float = 1.0):Void + { + horizontalAcceleration -= magnitude; + } + + public function accelrateDown(?magnitude:Float = 1.0):Void + { + verticalAcceleration += magnitude; + } + + public function accelrateUp(?magnitude:Float = 1.0):Void + { + verticalAcceleration -= magnitude; + } + + public function setHorizontalAcceleration(magnitude:Float):Void + { + horizontalAcceleration = magnitude; + } + + public function setVerticalAcceleration(magnitude:Float):Void + { + verticalAcceleration = magnitude; + } + + public function update(dTime:Float):Void + { + if (player == null) + { + return; + } + if (player.dead || player.healthPoints < 0) + { + return; + } + horizontalAcceleration = Math.max(Math.min(horizontalAcceleration, 1), -1); + verticalAcceleration = Math.max(Math.min(verticalAcceleration, 1), -1); + player.speed.x += horizontalAcceleration * horizontalAccelerationMax * dTime; + player.speed.y += verticalAcceleration * verticalAccelerationMax * dTime; + if (shootOnUpdate) + { + player.shoot(); + } + horizontalAcceleration = 0; + verticalAcceleration = 0; + shootOnUpdate = false; + } + + public function shoot():Void + { + shootOnUpdate = true; + } + +} \ No newline at end of file diff --git a/src/game/PlayerShip.hx b/src/game/PlayerShip.hx new file mode 100644 index 0000000..68c2c25 --- /dev/null +++ b/src/game/PlayerShip.hx @@ -0,0 +1,176 @@ +package game; +import assets.EntityGraphicsAsset; +import assets.GraphicsLibrary; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; + +/** + * ... + * @author Dmitriy Barabanschikov + */ +class PlayerShip extends GameEntity +{ + private var reload:Int; + private var bulletAngle:Float; + private var smokeCounter:Float; + private var timePassedSinceLastSpeedUpdate:Float; + private var reloadTime:Float; + + public function new(world:GameWorld) + { + super(world); + type = EntityType.PLAYER; + + reloadTime = 0.02; + bulletAngle = 0; + smokeCounter = 0; + timePassedSinceLastSpeedUpdate = 0; + + collisionCategory = CollisionCategory.PLAYER; + collisionMask = CollisionCategory.ENEMY | CollisionCategory.TILE | CollisionCategory.ENEMY_BULLET | CollisionCategory.PARTICLE; + graphicsAsset = GraphicsLibrary.getPlayerShip(); + + bounceFactor = 2; + + var poly:Polygon = new Polygon(); + poly.setPoly([new Vector2D( -55, 0), new Vector2D( -55, -10), new Vector2D(0, -15), new Vector2D(50, -10), new Vector2D(50, 10), new Vector2D(20, 22), new Vector2D(0, 22)]); + addShape(poly); + var circle:CircleShape = new CircleShape(20, 0, 11); + addShape(circle); + init(); + + healthPoints = 800; + } + + public function accelerateForward():Void + { + + } + + public function accelerateBackwards():Void + { + + } + + public function accelerateUp():Void + { + + } + + public function accelerateDown():Void + { + + } + + override public function update(dTime:Float):Void + { + + //healthPoints -= 10; + + if (healthPoints <= 0) + { + unguidedProjectile = true; + speed.y += 900*dTime; + } + + if (reloadTime > 0) + { + reloadTime-= dTime; + } + + timePassedSinceLastSpeedUpdate += dTime; + while (timePassedSinceLastSpeedUpdate > 0.02) + { + speed.multiply(0.8); + timePassedSinceLastSpeedUpdate -= 0.02; + } + + if (!dead && healthPoints <= 0) + { + if (smokeCounter >= 0.05) + { + var smokeParticle:GameEntity = world.getReusableEntityByType(EntityType.SMOKE); + smokeParticle.position.x = position.x - 20 + Math.random()*50; + smokeParticle.position.y = position.y - 10 + Math.random()*5; + world.addParticle(smokeParticle); + smokeCounter = 0; + } + else + { + smokeCounter+=dTime; + } + } + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + super.reactToCollision(collidingBody, selfShape, otherShape); + cast(collidingBody, GameEntity).recieveDamage(10); + if (Type.getClass(collidingBody) == Tile) + { + if (healthPoints <= 0 ) + { + dead = true; + var exp:GameEntity = world.getReusableEntityByType(EntityType.EXPLOSION); + exp.position = position.clone(); + world.addParticle(exp); + while (Math.random() > 0.6) + { + var debries:GameEntity = world.getReusableEntityByType(EntityType.DEBRIES); + debries.position.x = x; + debries.position.y = y; + debries.speed.x = Math.random() * 10 - 5; + debries.speed.y = -Math.random() * 10; + world.addParticle(debries); + } + } + } + } + + override public function recieveDamage(damageAmount:Int):Void + { + super.recieveDamage(damageAmount); + } + + public function shoot():Void + { + if (healthPoints <= 0) + { + return; + } + if (reloadTime > 0) + { + return; + } + reloadTime = 0.02; + if (reload > 0) + { + reload--; + } else + { + reload = 1; + } + + bulletAngle += Math.PI / 34; + + var i:Int = 4; + while (i-- > 0) + { + if (i % 2 == reload) + { + continue; + } + var bullet:GameEntity = world.getReusableEntityByType(EntityType.PLAYER_BULLET); + bullet.position.x = this.position.x + 30; + bullet.position.y = this.position.y; + bullet.speed.x = 450; + bullet.speed.y = Math.sin((bulletAngle + i)*(i + 1))*60; + world.addPlayerBullet(bullet); + } + + } + +} \ No newline at end of file diff --git a/src/game/RailgunTrail.hx b/src/game/RailgunTrail.hx new file mode 100644 index 0000000..09e98ce --- /dev/null +++ b/src/game/RailgunTrail.hx @@ -0,0 +1,50 @@ +package game; +import assets.GraphicsLibrary; + +//import assets.GraphicsLibrary; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class RailgunTrail extends GameEntity +{ + private var counter:Float; + private var timePassedSinceLastUpdate:Float; + + public function new(world:GameWorld) + { + super(world); + type = EntityType.RAILGUN_TRAIL; + collisionCategory = CollisionCategory.IGNORE; + counter = 0; + graphicsAsset = GraphicsLibrary.getRailgunTrail(); + gridBound = true; + unguidedProjectile = true; + timePassedSinceLastUpdate = 0; + init(); + } + + override public function reset():Void + { + super.reset(); + counter = 0; + timePassedSinceLastUpdate = 0; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + timePassedSinceLastUpdate += dTime; + while(timePassedSinceLastUpdate > 0.02) + { + speed.multiply(0.8); + timePassedSinceLastUpdate -= 0.02; + } + counter+=dTime; + if (counter > 0.4) + { + dead = true; + } + } + +} \ No newline at end of file diff --git a/src/game/SmokeParticle.hx b/src/game/SmokeParticle.hx new file mode 100644 index 0000000..3821ed7 --- /dev/null +++ b/src/game/SmokeParticle.hx @@ -0,0 +1,42 @@ +package game; +import assets.GraphicsLibrary; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class SmokeParticle extends GameEntity +{ + private var counter:Float; + + public function new(world:GameWorld) + { + super(world); + counter = 0; + type = EntityType.SMOKE; + graphicsAsset = GraphicsLibrary.getSmoke(); + gridBound = true; + unguidedProjectile = true; + speed.y = -1; + init(); + } + + override public function reset():Void + { + super.reset(); + counter = 0; + } + + override public function update(dTime:Float):Void + { + super.update(dTime); + counter+=dTime; + frameRectNum = Std.int(counter * 5); + if (counter >= 1) + { + dead = true; + } + } + +} \ No newline at end of file diff --git a/src/game/Tile.hx b/src/game/Tile.hx new file mode 100644 index 0000000..db8a1de --- /dev/null +++ b/src/game/Tile.hx @@ -0,0 +1,63 @@ +package game; + +import assets.GraphicsLibrary; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.Polygon; + +/** + * ... + * @author Dimonte + */ +class Tile extends GameEntity +{ + public static inline var MIDDLE:String = "middle"; + public static inline var TOP:String = "top"; + public static inline var SLOPE_UP:String = "slopeUp"; + public static inline var SLOPE_DOWN:String = "slopeDown"; + + public var template:String; + + public function new(world:GameWorld) + { + super(world); + type = EntityType.TILE; + collisionCategory = CollisionCategory.TILE; + graphicsAsset = GraphicsLibrary.getTiles(); + } + + public function createFromTemplate(template:String):Void + { + clearShapes(); + var shape:Polygon; + shape = new Polygon(); + this.template = template; + switch (template) + { + case MIDDLE: + shape.setAsBox(20, 20); + frameRectNum = Math.random() > 0.2 ? graphicsAsset.getFrameByAssetName("assets/tiles/middle.png") : graphicsAsset.getFrameByAssetName("assets/tiles/middle2.png"); + case SLOPE_UP: + shape.setPoly([new Vector2D( -20, 20), new Vector2D( 20, -20), new Vector2D( 20, 20)]); + frameRectNum = 2; + case SLOPE_DOWN: + shape.setPoly([new Vector2D( -20, -20), new Vector2D( 20, 20), new Vector2D( -20, 20)]); + frameRectNum = 3; + case TOP: + shape.setAsBox(20, 20); + frameRectNum = Math.random() > 0.2 ? graphicsAsset.getFrameByAssetName("assets/tiles/top2.png") : graphicsAsset.getFrameByAssetName("assets/tiles/top.png"); + default: + shape.setAsBox(20, 20); + } + addShape(shape); + init(); + } + + override public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + super.reactToCollision(collidingBody, selfShape, otherShape); + cast(collidingBody, GameEntity).recieveDamage(10); + } + +} \ No newline at end of file diff --git a/src/game/TileTemplate.hx b/src/game/TileTemplate.hx new file mode 100644 index 0000000..8477618 --- /dev/null +++ b/src/game/TileTemplate.hx @@ -0,0 +1,20 @@ +package game; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class TileTemplate extends LevelObjectTemplate +{ + public var tileGridX:Int; + public var tileGridY:Int; + + public var tileTemplate:String; + + public function new() + { + super(); + } + +} \ No newline at end of file diff --git a/src/game/behaviours/BaloonBehaviour.hx b/src/game/behaviours/BaloonBehaviour.hx new file mode 100644 index 0000000..ac32d88 --- /dev/null +++ b/src/game/behaviours/BaloonBehaviour.hx @@ -0,0 +1,70 @@ +package game.behaviours; + +import game.CollisionCategory; +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class BaloonBehaviour extends BasicBehaviour +{ + + public function new(subject:EnemyShip) + { + super(subject); + } + + override public function init(dTime:Float):Void + { + updateFunction = oscillateDown; + } + + private function oscillateDown(dTime:Float):Void + { + if (subject.speed.y < 50) + { + subject.speed.y += 30*dTime; + } else + { + updateFunction = oscillateUp; + } + } + + private function oscillateUp(dTime:Float):Void + { + if (subject.speed.y > -50) + { + subject.speed.y -= 30*dTime; + } else + { + updateFunction = oscillateDown; + } + } + + override public function checkCommonConditions():Void + { + if (subject.healthPoints <= 0 && !subject.shotDown) + { + subject.world.score += 1500; + subject.shotDown = true; + subject.unguidedProjectile = true; + subject.collisionCategory = CollisionCategory.PARTICLE; + subject.collisionMask = CollisionCategory.TILE; + updateFunction = goDownInFlames; + } + } + + private function goDownInFlames(dTime:Float):Void + { + if (subject.shotDown && subject.speed.y < 300) + { + subject.speed.y += 200*dTime; + } + } + + override public function respondToDamage():Void + { + super.respondToDamage(); + } + +} \ No newline at end of file diff --git a/src/game/behaviours/BasicBehaviour.hx b/src/game/behaviours/BasicBehaviour.hx new file mode 100644 index 0000000..31362ac --- /dev/null +++ b/src/game/behaviours/BasicBehaviour.hx @@ -0,0 +1,43 @@ +package game.behaviours; + +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class BasicBehaviour implements IBehaviour +{ + public var updateFunction: Float -> Void; + public var subject:EnemyShip; + + public function new(subject:EnemyShip) + { + this.subject = subject; + updateFunction = init; + } + + public function update(dTime:Float):Void + { + checkCommonConditions(); + if (updateFunction != null) + { + updateFunction(dTime); + } + } + + public function checkCommonConditions():Void + { + + } + + public function init(dTime:Float):Void + { + + } + + public function respondToDamage():Void + { + + } + +} \ No newline at end of file diff --git a/src/game/behaviours/IBehaviour.hx b/src/game/behaviours/IBehaviour.hx new file mode 100644 index 0000000..34a44e2 --- /dev/null +++ b/src/game/behaviours/IBehaviour.hx @@ -0,0 +1,10 @@ +package game.behaviours; + +/** + * ... + * @author Dmitriy Barabanschikov + */ +interface IBehaviour +{ + function update(dTime:Float):Void; +} \ No newline at end of file diff --git a/src/game/behaviours/KamikazeBaloonBehaviour.hx b/src/game/behaviours/KamikazeBaloonBehaviour.hx new file mode 100644 index 0000000..bd7e31c --- /dev/null +++ b/src/game/behaviours/KamikazeBaloonBehaviour.hx @@ -0,0 +1,57 @@ +package game.behaviours; + +import game.CollisionCategory; +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class KamikazeBaloonBehaviour extends BasicBehaviour +{ + private var counter:Float; + + public function new(subject:EnemyShip) + { + super(subject); + counter = 0; + } + + override public function init(dTime:Float):Void + { + counter = 4 + Std.int(Math.random() * 8); + updateFunction = waitToExplode; + } + + private function waitToExplode(dTime:Float):Void + { + counter -= dTime; + if (counter <= 0) + { + updateFunction = explode; + } + } + + private function explode(dTime:Float):Void + { + for (i in 0...12) + { + subject.shoot(i * Math.PI * 2 / 12, 150); + } + subject.die(); + updateFunction = null; + } + + override public function checkCommonConditions():Void + { + if (subject.healthPoints <= 0 && !subject.shotDown) + { + subject.world.score += 1500; + subject.shotDown = true; + subject.unguidedProjectile = true; + subject.collisionCategory = CollisionCategory.PARTICLE; + subject.collisionMask = CollisionCategory.TILE; + subject.die(); + } + } + +} \ No newline at end of file diff --git a/src/game/behaviours/TeslaBehaviourFrontalAssault.hx b/src/game/behaviours/TeslaBehaviourFrontalAssault.hx new file mode 100644 index 0000000..dce816d --- /dev/null +++ b/src/game/behaviours/TeslaBehaviourFrontalAssault.hx @@ -0,0 +1,41 @@ +package game.behaviours; + +import game.EnemyBullet; +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class TeslaBehaviourFrontalAssault implements IBehaviour +{ + private var subject:EnemyShip; + private var counter:Float; + private var shootCounter:Int; + + public function new(subject:EnemyShip) + { + this.subject = subject; + counter = 0; + shootCounter = 1; + } + + public function update(dTime:Float):Void + { + counter+=dTime; + if (counter > shootCounter*1.1) + { + subject.shootAtPlayer(); + shootCounter++; + } + if (counter > 3) + { + subject.behaviour = new TeslaBehaviourRetreat(subject); + } + + if (subject.healthPoints < 100) + { + subject.behaviour = new TeslaBehaviourRetreat(subject); + } + } + +} \ No newline at end of file diff --git a/src/game/behaviours/TeslaBehaviourGoDownInFlames.hx b/src/game/behaviours/TeslaBehaviourGoDownInFlames.hx new file mode 100644 index 0000000..d8453c0 --- /dev/null +++ b/src/game/behaviours/TeslaBehaviourGoDownInFlames.hx @@ -0,0 +1,29 @@ +package game.behaviours; + +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class TeslaBehaviourGoDownInFlames implements IBehaviour +{ + private var subject:EnemyShip; + + public function new(subject:EnemyShip) + { + this.subject = subject; + } + + public function update(dTime:Float):Void + { + if (subject.speed.y < 400) + { + subject.speed.y += 450*dTime; + } + if (subject.rotation > -Math.PI / 4) + { + subject.rotation -= Math.PI / 5*dTime; + } + } + +} \ No newline at end of file diff --git a/src/game/behaviours/TeslaBehaviourRam.hx b/src/game/behaviours/TeslaBehaviourRam.hx new file mode 100644 index 0000000..5430ffc --- /dev/null +++ b/src/game/behaviours/TeslaBehaviourRam.hx @@ -0,0 +1,50 @@ +package game.behaviours; + +import game.EnemyShip; +import game.PlayerShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class TeslaBehaviourRam implements IBehaviour +{ + private var subject:EnemyShip; + private var target:PlayerShip; + private var counter:Float; + private var shootCounter:Int; + + public function new(subject:EnemyShip) + { + this.subject = subject; + counter = 0; + } + + public function update(dTime:Float):Void + { + if (target == null) + { + target = subject.world.player; + } + + counter+=dTime; + if (counter > shootCounter) + { + subject.shoot(Math.PI, 400); + shootCounter++; + } + + if (target.y > subject.y + subject.speed.y / 5) + { + subject.speed.y += 180*dTime; + } else + { + subject.speed.y -= 180*dTime; + } + + if (subject.healthPoints < 100) + { + subject.behaviour = new TeslaBehaviourRetreat(subject); + } + } + +} \ No newline at end of file diff --git a/src/game/behaviours/TeslaBehaviourRetreat.hx b/src/game/behaviours/TeslaBehaviourRetreat.hx new file mode 100644 index 0000000..130a037 --- /dev/null +++ b/src/game/behaviours/TeslaBehaviourRetreat.hx @@ -0,0 +1,46 @@ +package game.behaviours; + +import game.CollisionCategory; +import game.EnemyShip; +/** + * ... + * @author Dmitriy Barabanschikov + */ +class TeslaBehaviourRetreat implements IBehaviour +{ + private var subject:EnemyShip; + private var counter:Float; + private var shootCounter:Int; + + public function new(subject:EnemyShip) + { + this.subject = subject; + counter = 0; + } + + public function update(dTime:Float):Void + { + counter+=dTime; + if (counter > shootCounter*2) + { + subject.shootAtPlayer(); + shootCounter++; + } + + if (subject.speed.y > -1200) + { + subject.speed.y -= 300*dTime; + subject.rotation += Math.PI / 10*dTime; + } + if (subject.healthPoints < 0) + { + subject.shotDown = true; + subject.unguidedProjectile = true; + subject.collisionCategory = CollisionCategory.PARTICLE; + subject.collisionMask = CollisionCategory.TILE; + subject.behaviour = new TeslaBehaviourGoDownInFlames(subject); + subject.world.score += 5000; + } + } + +} \ No newline at end of file diff --git a/src/game/ui/GameOverScreen.hx b/src/game/ui/GameOverScreen.hx new file mode 100644 index 0000000..83fd71b --- /dev/null +++ b/src/game/ui/GameOverScreen.hx @@ -0,0 +1,104 @@ +package game.ui; + +#if (!android && !iphone) + +#end +import flash.display.Bitmap; +import flash.display.BitmapData; +import flash.display.Sprite; +import flash.text.TextField; +import flash.text.TextFormat; +import flash.text.TextFormatAlign; +import game.GameWorld; +import motion.Actuate; +import openfl.Assets; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class GameOverScreen extends Sprite +{ + + + private var darkScreen:Bitmap; + private var gameOverText:Bitmap; + private var gameWorld:GameWorld; + private var scoreText:TextField; + private var restartText:String; + private var screenWidth:Float; + private var screenHeight:Float; + + public function new(gameWorld:GameWorld, screenWidth:Float, screenHeight:Float) + { + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + this.gameWorld = gameWorld; + super(); + + #if (android || iphone) + restartText = "Tap anywhere to restart"; + #else + restartText = "Click anywhere to restart"; + #end + + darkScreen = new Bitmap(new BitmapData(1, 1, true, 0xFF000000)); + darkScreen.scaleX = screenWidth; + darkScreen.scaleY = screenHeight; + darkScreen.alpha = 0; + addChild(darkScreen); + + gameOverText = new Bitmap(Assets.getBitmapData("assets/ui/gameOverText.png")); + gameOverText.x = (screenWidth - gameOverText.width) / 2; + gameOverText.y = Std.int(screenHeight/2 - 100); + gameOverText.alpha = 0; + addChild(gameOverText); + + scoreText = new TextField(); + scoreText.alpha = 0; + scoreText.embedFonts = true; + scoreText.selectable = false; + scoreText.width = screenWidth; + scoreText.y = gameOverText.y + 60; + addChild(scoreText); + + var scoreTF:TextFormat = scoreText.defaultTextFormat; + scoreTF.font = FontManager.mainFont.fontName; + scoreTF.bold = true; + scoreTF.size = 24; + scoreTF.align = TextFormatAlign.CENTER; + scoreTF.color = 0xFFFFFF; + scoreText.defaultTextFormat = scoreTF; + + + #if (android || iphone) + darkScreen.alpha = 0.6; + gameOverText.alpha = 1; + scoreText.alpha = 1; + #end + } + + public function show():Void + { + visible = true; + #if (!android && !iphone) + Actuate.tween(darkScreen, 8, { alpha: 0.6 } ); + Actuate.tween(gameOverText, 1, { alpha: 1 } ); + Actuate.tween(scoreText, 3, { alpha: 1 } ); + #end + scoreText.text = "SCORE: " + Std.string(gameWorld.score) + "\n\n" + restartText; + } + + public function hide():Void + { + visible = false; + #if (!android && !iphone) + Actuate.stop(darkScreen, "alpha", false, false); + Actuate.stop(gameOverText, "alpha", false, false); + darkScreen.alpha = 0; + gameOverText.alpha = 0; + #end + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/AABB.hx b/src/sphaeraGravita/collision/AABB.hx new file mode 100644 index 0000000..f187584 --- /dev/null +++ b/src/sphaeraGravita/collision/AABB.hx @@ -0,0 +1,94 @@ +package sphaeraGravita.collision; +import sphaeraGravita.math.Vector2D; + +/** + * ... + * @author Dimonte + */ +class AABB +{ + private var bottomRight:Vector2D; + private var topLeft:Vector2D; + private var topRight:Vector2D; + private var bottomLeft:Vector2D; + public var lowerBound:Vector2D; + public var upperBound:Vector2D; + + public function new() + { + lowerBound = new Vector2D(); + upperBound = new Vector2D(); + topLeft = new Vector2D(); + topRight = new Vector2D(); + bottomRight = new Vector2D(); + bottomLeft = new Vector2D(); + } + + public function getWidth():Float + { + return upperBound.x - lowerBound.x; + } + + public function getHeight():Float + { + return upperBound.y - lowerBound.y; + } + + public function containsPoint(point:Vector2D):Bool + { + if (point.x < lowerBound.x) + return false; + if (point.x > upperBound.x) + return false; + if (point.y < lowerBound.y) + return false; + if (point.y > upperBound.y) + return false; + return true; + } + + public function getTopLeftCorner():Vector2D + { + topLeft.x = lowerBound.x; + topLeft.y = lowerBound.y; + return topLeft; + } + + public function getTopRightCorner():Vector2D + { + topRight.x = upperBound.x; + topRight.y = lowerBound.y; + return topRight; + } + + public function getBottomLeftCorner():Vector2D + { + bottomLeft.x = lowerBound.x; + bottomLeft.y = upperBound.y; + return bottomLeft; + } + + public function getBottomRightCorner():Vector2D + { + + bottomRight.x = upperBound.x; + bottomRight.y = upperBound.y; + return bottomRight; + } + + static public function asMinMax(minX:Float, minY:Float, maxX:Float, maxY:Float):AABB + { + var aabb:AABB = new AABB(); + aabb.lowerBound.x = minX; + aabb.lowerBound.y = minY; + aabb.upperBound.x = maxX; + aabb.upperBound.y = maxY; + return aabb; + } + + public function toString():String + { + return "minX: " + lowerBound.x + ", minY: " + lowerBound.y + ", width: " + getWidth() + ", height: " + getHeight(); + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/CollidingEntity.hx b/src/sphaeraGravita/collision/CollidingEntity.hx new file mode 100644 index 0000000..1874ab3 --- /dev/null +++ b/src/sphaeraGravita/collision/CollidingEntity.hx @@ -0,0 +1,56 @@ +package sphaeraGravita.collision; +import game.CollisionCategory; + +/** + * ... + * @author Dmitriy Barabanschikov + */ +class CollidingEntity +{ + public var parent:CollidingEntity; + + public var collisionCategory(get, set):Int; + + var _collisionCategory:Int = CollisionCategory.INHERIT; + + public function get_collisionCategory():Int + { + if (_collisionCategory == CollisionCategory.INHERIT) + { + if (parent != null) + { + return parent.collisionCategory; + } + } + return _collisionCategory; + } + + public function set_collisionCategory(value:Int):Int + { + _collisionCategory = value; + return collisionCategory; + } + + public var collisionMask(get, set):Int; + + var _collisionMask:Int; + + public function get_collisionMask():Int + { + if (_collisionMask == CollisionCategory.INHERIT) + { + if (parent != null) + { + return parent.collisionMask; + } + } + return _collisionMask; + } + + public function set_collisionMask(value:Int):Int + { + _collisionMask = value; + return collisionMask; + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/CollisionEngine.hx b/src/sphaeraGravita/collision/CollisionEngine.hx new file mode 100644 index 0000000..fa93f73 --- /dev/null +++ b/src/sphaeraGravita/collision/CollisionEngine.hx @@ -0,0 +1,623 @@ +package sphaeraGravita.collision; + +import dataStructures.DLLNode; +import game.CollisionCategory; +import game.GameEntity; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; +import sphaeraGravita.shapes.ShapeType; + +/** + * ... + * @author Dimonte + */ +class CollisionEngine +{ + /** + * WARNING! Gets overwritten every time project<...> functions are called. + */ + private var projectionResult:ProjectionResult; + + private var intervalOne:Float; + private var intervalTwo:Float; + private var min:Float; + private var max:Float; + private var projectionPoint:Float; + private var verticeNum:Int; + private var i:Int; + + public function new() + { + projectionResult = new ProjectionResult(); + } + + public function collideBodies(entityOne:PhysicalBody, entityTwo:PhysicalBody):Void + { + + //trace("collideBodies > " + entityOne + " - " + entityTwo); + + if (entityOne.dead || entityTwo.dead) + { + return; + } + if(!matchCollisionCategories(entityOne, entityTwo)) + { + return; + } + if (!queryBoundsIntersection(entityOne, entityTwo)) + { + return; + } + //trace("full cd"); + var collisionResult:CollisionResult; + var bodyOneShape:BaseShape = entityOne.shapeList; + while (bodyOneShape != null) + { + var bodyTwoShape:BaseShape; + bodyTwoShape = entityTwo.shapeList; + while (bodyTwoShape != null) + { + if (bodyOneShape.collisionMask != 0 || bodyOneShape.collisionCategory != CollisionCategory.INHERIT || bodyTwoShape.collisionMask != 0 || bodyTwoShape.collisionCategory != CollisionCategory.INHERIT) + { + if (!matchCollisionCategories(bodyOneShape, bodyTwoShape)) + { + bodyTwoShape = bodyTwoShape.next; + continue; + } + } + + //trace("bodyTwoShape : " + bodyTwoShape); + if (bodyOneShape.sensor || bodyTwoShape.sensor) + { + //trace("huh?"); + if (queryShapes(bodyOneShape, bodyTwoShape)) + { + entityOne.reactToCollision(entityTwo, bodyOneShape, bodyTwoShape); + entityTwo.reactToCollision(entityOne, bodyTwoShape, bodyOneShape); + } + } + else + { + collisionResult = collideShapes(bodyOneShape, bodyTwoShape); + if (collisionResult != null) + { + if (collisionResult.collision) + { + collisionResult.calculateMTDVector(); + var bounceCoefficient:Float = entityOne.bounceFactor * entityTwo.bounceFactor; + entityOne.position.x += collisionResult.mtdVector.x * bounceCoefficient; + entityOne.position.y += collisionResult.mtdVector.y * bounceCoefficient; + var frictionCoefficient:Float = entityOne.frictionFactor * entityTwo.frictionFactor; + var firstReflectingComponent:Vector2D = Vector2D.project(entityOne.speed, collisionResult.mtdAxis).invert().multiply(bounceCoefficient); + var firstFrictionComponent:Vector2D = Vector2D.project(entityOne.speed, collisionResult.mtdAxis.getNormalRight()).multiply(frictionCoefficient); + var speedProjection:Vector2D = Vector2D.project(entityOne.speed, collisionResult.mtdAxis); + if (Vector2D.dotProduct(entityOne.speed, collisionResult.mtdVector) < 0) + { + entityOne.speed = (firstReflectingComponent.add(firstFrictionComponent)); + } + + //TODO entityTwo speed after collision + + entityOne.reactToCollision(entityTwo, bodyOneShape, bodyTwoShape); + entityTwo.reactToCollision(entityOne, bodyTwoShape, bodyOneShape); + } + } + } + bodyTwoShape = bodyTwoShape.next; + } + bodyOneShape = bodyOneShape.next; + } + } + + public function matchCollisionCategories(entityOne:CollidingEntity, entityTwo:CollidingEntity):Bool + { + //trace("matchCollisionCategories > " + entityOne + " - " + entityTwo); + + //trace("entityOne.collisionMask " + entityOne.collisionMask); + //trace("entityTwo.collisionCategory " + entityTwo.collisionCategory); + + if (entityOne.collisionMask != 0 && (entityOne.collisionMask & entityTwo.collisionCategory == 0)) + return false; + + //trace("entityTwo.collisionMask " + entityTwo.collisionMask); + //trace("entityOne.collisionCategory " + entityOne.collisionCategory); + + if (entityTwo.collisionMask != 0 && (entityTwo.collisionMask & entityOne.collisionCategory == 0)) + return false; + + return true; + } + + public function collideShapes(shapeOne:BaseShape, shapeTwo:BaseShape):CollisionResult + { + var shapeCollisionResult:CollisionResult = null; + var tempCollisionResult:CollisionResult = null; + if (shapeOne.type == ShapeType.POLYGON_SHAPE) + { + if (shapeTwo.type == ShapeType.POLYGON_SHAPE) + { + shapeCollisionResult = detectPolygons(cast(shapeOne,Polygon), cast(shapeTwo,Polygon)); + } + else if (shapeTwo.type == ShapeType.CIRCLE_SHAPE) + { + shapeCollisionResult = detectPolyCircle(cast(shapeTwo, CircleShape), cast(shapeOne, Polygon)); + if (shapeCollisionResult != null) + { + shapeCollisionResult.mtdAmount = -shapeCollisionResult.mtdAmount; + } + } + } + else if (shapeOne.type == ShapeType.CIRCLE_SHAPE) + { + if (shapeTwo.type == ShapeType.CIRCLE_SHAPE) + { + shapeCollisionResult = detectCircleCircle(cast(shapeOne,CircleShape), cast(shapeTwo,CircleShape)); + } + else if (shapeTwo.type == ShapeType.POLYGON_SHAPE) + { + shapeCollisionResult = detectPolyCircle(cast(shapeOne,CircleShape), cast(shapeTwo,Polygon)); + } + } + return shapeCollisionResult; + } + + public function queryShapes(shapeOne:BaseShape, shapeTwo:BaseShape):Bool + { + var tempCollisionResult:CollisionResult = null; + if (shapeOne.type == ShapeType.POLYGON_SHAPE) + { + if (shapeTwo.type == ShapeType.POLYGON_SHAPE) + { + tempCollisionResult = detectPolygons(cast(shapeOne,Polygon), cast(shapeTwo,Polygon)); + } + else if (shapeTwo.type == ShapeType.CIRCLE_SHAPE) + { + tempCollisionResult = detectPolyCircle(cast(shapeTwo,CircleShape), cast(shapeOne,Polygon)); + } + } + else if (shapeOne.type == ShapeType.CIRCLE_SHAPE) + { + if (shapeTwo.type == ShapeType.CIRCLE_SHAPE) + { + tempCollisionResult = detectCircleCircle(cast(shapeOne,CircleShape), cast(shapeTwo,CircleShape)); + } + else if (shapeTwo.type == ShapeType.POLYGON_SHAPE) + { + tempCollisionResult = detectPolyCircle(cast(shapeOne,CircleShape), cast(shapeTwo,Polygon)); + } + } + if (tempCollisionResult != null) + { + if (tempCollisionResult.collision) + { + return true; + } + } + return false; + } + + /** + * + * @param bodyOne + * @param bodyTwo + * @return collision result, mtd is for the FIRST body + */ + public function collide(bodyOne:PhysicalBody, bodyTwo:PhysicalBody):CollisionResult + { + var collisionResult:CollisionResult = new CollisionResult(); + collisionResult.mtdAmount = Math.POSITIVE_INFINITY; + var tempCollisionResult:CollisionResult = collisionResult; + var bodyOneShape:BaseShape; + var bodyTwoShape:BaseShape; + if (queryBoundsIntersection(bodyOne, bodyTwo)) + { + bodyOneShape = bodyOne.shapeList; + while (bodyOneShape != null) + { + bodyTwoShape = bodyTwo.shapeList; + while (bodyTwoShape != null) + { + if (bodyOneShape.type == ShapeType.POLYGON_SHAPE) + { + if (bodyTwoShape.type == ShapeType.POLYGON_SHAPE) + { + tempCollisionResult = detectPolygons(cast(bodyOneShape,Polygon), cast(bodyTwoShape,Polygon)); + } + else if (bodyTwoShape.type == ShapeType.CIRCLE_SHAPE) + { + tempCollisionResult = detectPolyCircle(cast(bodyTwoShape,CircleShape), cast(bodyOneShape,Polygon)); + tempCollisionResult.mtdAmount = -tempCollisionResult.mtdAmount; + } + } + else if (bodyOneShape.type == ShapeType.CIRCLE_SHAPE) + { + if (bodyTwoShape.type == ShapeType.CIRCLE_SHAPE) + { + tempCollisionResult = detectCircleCircle(cast(bodyOneShape,CircleShape), cast(bodyTwoShape,CircleShape)); + } + else if (bodyTwoShape.type == ShapeType.POLYGON_SHAPE) + { + tempCollisionResult = detectPolyCircle(cast(bodyOneShape, CircleShape), cast(bodyTwoShape,Polygon)); + } + } + if(tempCollisionResult.collision) + { + if (!collisionResult.collision) + { + collisionResult = tempCollisionResult; + collisionResult.calculateMTDVector(); + } else { + collisionResult.mtdVector.add(tempCollisionResult.calculateMTDVector()); + } + } + bodyTwoShape = bodyTwoShape.next; + } + bodyOneShape = bodyOneShape.next; + } + } + // TODO sensor shapes + // TODO immidiate vs delayed logic response + /*var bodyOneShapeOne:BaseShape = bodyOne.shapeList.head().val as BaseShape; + var bodyTwoShapeOne:BaseShape = bodyTwo.shapeList.head().val as BaseShape; + if ((bodyTwoShapeOne.type == ShapeType.AABB_SHAPE) && (bodyOneShapeOne.type == ShapeType.AABB_SHAPE)) + { + collisionResult = collideAABBToAABB(bodyOneShapeOne as AABB, bodyTwoShapeOne as AABB); + if (collisionResult.collision) + { + //trace("Collision! " + collisionResult.mtdVector.toString()); + bodyOne.position.x += collisionResult.mtdVector.x; + bodyOne.position.y += collisionResult.mtdVector.y; + var firstReflectingComponent:Vector2D = Vector2D.project(bodyOne.speed.clone().invert(), collisionResult.mtdAxis).multiply(0.9); + var firstFrictionComponent:Vector2D = Vector2D.project(bodyOne.speed, collisionResult.mtdAxis.getNormalRight()).multiply(0.8); + bodyOne.speed = (firstReflectingComponent.add(firstFrictionComponent)); + } + }*/ + return collisionResult; + } + + public function queryBoundsIntersection(bodyOne:PhysicalBody, bodyTwo:PhysicalBody):Bool + { + var bodyOneLowerBound:Vector2D = bodyOne.worldAABB.lowerBound; + var bodyOneUpperBound:Vector2D = bodyOne.worldAABB.upperBound; + var bodyTwoLowerBound:Vector2D = bodyTwo.worldAABB.lowerBound; + var bodyTwoUpperBound:Vector2D = bodyTwo.worldAABB.upperBound; + + if (bodyOneLowerBound.x >= bodyTwoUpperBound.x) + { + return false; + } + if (bodyOneLowerBound.y >= bodyTwoUpperBound.y) + { + return false; + } + if (bodyOneUpperBound.x <= bodyTwoLowerBound.x) + { + return false; + } + if (bodyOneUpperBound.y <= bodyTwoLowerBound.y) + { + return false; + } + return true; + } + + private function detectPolygons(firstPoly:Polygon, secondPoly:Polygon):Null + { + var resultMTD:Float = Math.POSITIVE_INFINITY; + var mtdAxis:Vector2D = null; + + var testAxisList:Array = new Array(); + + var firstPolyVertexNum:Int = firstPoly.getNumVertices(); + var secondPolyVertexNum:Int = secondPoly.getNumVertices(); + var totalVerges:Int = firstPolyVertexNum + secondPolyVertexNum; + var firstVerticeSet:Array = []; + var body:PhysicalBody = firstPoly.body; + for (i in 0...firstPoly.getNumVertices()) + { + firstVerticeSet[i] = body.localToWorld(firstPoly.vertices[i]); + testAxisList.push(firstPoly.normals[i].clone().applyXform(body.xform)); + } + + var firstMin:Float = 0; + var firstMax:Float = 0; + var secondMin:Float = 0; + var secondMax:Float = 0; + var intervalOneAbs:Float = 0; + var intervalTwoAbs:Float = 0; + var firstPolyProjection:ProjectionResult; + var secondPolyProjection:ProjectionResult; + + var secondVerticeSet:Array = []; + body = secondPoly.body; + for (i in 0...secondPoly.getNumVertices()) + { + secondVerticeSet[i] = secondPoly.body.localToWorld(secondPoly.vertices[i]); + testAxisList.push(secondPoly.normals[i].clone().applyXform(body.xform)); + } + for (i in 0...totalVerges) + { + var testAxis:Vector2D; + testAxis = testAxisList[i]; + + firstPolyProjection = projectVerticeSetOnAxis(firstVerticeSet, testAxis); + firstMin = firstPolyProjection.min; + firstMax = firstPolyProjection.max; + + secondPolyProjection = projectVerticeSetOnAxis(secondVerticeSet, testAxis); + secondMin = secondPolyProjection.min; + secondMax = secondPolyProjection.max; + + if (secondMin > firstMax) + { + return null; + } + if (firstMin > secondMax) + { + return null; + } + + intervalOne = secondMin - firstMax; + intervalTwo = secondMax - firstMin; + intervalOneAbs = intervalOne < 0 ? -intervalOne:intervalOne; + intervalTwoAbs = intervalTwo < 0 ? -intervalTwo:intervalTwo; + + // use faster math for ABSes or get rid of 'em + if (intervalTwoAbs < intervalOneAbs) + { + intervalOneAbs = intervalTwoAbs; + if (intervalTwo < 0) + { + testAxis = testAxis.clone().invert(); + } + } else { + if (intervalOne < 0) + { + testAxis = testAxis.clone().invert(); + } + } + + if (intervalOneAbs < resultMTD) + { + //trace(interval); + resultMTD = intervalOneAbs; + mtdAxis = testAxis.clone(); + } + } + + var result:CollisionResult = new CollisionResult(); + result.mtdAmount = resultMTD; + result.mtdAxis = mtdAxis; + result.collision = true; + + return result; + } + + public function detectPolyCircle(circle:CircleShape, poly:Polygon):Null + { + + + var resultMTD:Float = Math.POSITIVE_INFINITY; + var mtdAxis:Vector2D = null; + var collision:Bool = true; + + var circlePosition:Vector2D = circle.body.localToWorld(circle.position); + + var totalEdges:Int = poly.getNumVertices(); + + var polyVerticeSet:Array = []; + for (i in 0...totalEdges) + { + polyVerticeSet[i] = poly.body.localToWorld(poly.vertices[i]); + } + + var testAxis:Vector2D; + var circleProjection:ProjectionResult; + var secondPolyProjection:ProjectionResult; + var intervalOneAbs:Float; + var intervalTwoAbs:Float; + + var circleMin:Float = 0; + var circleMax:Float = 0; + var polyMin:Float = 0; + var polyMax:Float = 0; + var intervalOneAbs:Float = 0; + var intervalTwoAbs:Float = 0; + + for (i in 0...totalEdges) + { + //* + testAxis = poly.normals[i].clone().applyXform(poly.body.xform); + /*/ + testAxis = poly.normals[i].clone(); + //*/ + + circleProjection = projectCircleOnAxis(circle, testAxis); + circleMin = circleProjection.min; + circleMax = circleProjection.max; + + secondPolyProjection = projectVerticeSetOnAxis(polyVerticeSet, testAxis); + polyMin = secondPolyProjection.min; + polyMax = secondPolyProjection.max; + + if (polyMin > circleMax) + { + return null; + } + if (circleMin > polyMax) + { + return null; + } + intervalOne = polyMin - circleMax; + intervalTwo = polyMax - circleMin; + intervalOneAbs = intervalOne < 0 ? -intervalOne:intervalOne; + intervalTwoAbs = intervalTwo < 0 ? -intervalTwo:intervalTwo; + // use faster math for ABSes or get rid of 'em + if (intervalTwoAbs < intervalOneAbs) + { + intervalOneAbs = intervalTwoAbs; + if (intervalTwo < 0) + { + testAxis = testAxis.invert(); + } + } else { + if (intervalOne < 0) + { + testAxis = testAxis.invert(); + } + } + + if (intervalOneAbs < resultMTD) + { + resultMTD = intervalOneAbs; + mtdAxis = testAxis; + } + } + for (i in 0...totalEdges) + { + testAxis = circle.body.localToWorld(circle.position).subtract(poly.body.localToWorld(poly.vertices[i])).normalize(); + + circleProjection = projectCircleOnAxis(circle, testAxis); + circleMin = circleProjection.min; + circleMax = circleProjection.max; + secondPolyProjection = projectVerticeSetOnAxis(polyVerticeSet, testAxis); + polyMin = secondPolyProjection.min; + polyMax = secondPolyProjection.max; + + if (polyMin > circleMax) + { + return null; + } + if (circleMin > polyMax) + { + return null; + } + intervalOne = polyMin - circleMax; + intervalTwo = polyMax - circleMin; + intervalOneAbs = intervalOne < 0 ? -intervalOne:intervalOne; + intervalTwoAbs = intervalTwo < 0 ? -intervalTwo:intervalTwo; + // use faster math for ABSes or get rid of 'em + if (intervalTwoAbs < intervalOneAbs) + { + intervalOneAbs = intervalTwoAbs; + if (intervalTwo < 0) + { + testAxis = testAxis.invert(); + } + } else { + if (intervalOne < 0) + { + testAxis = testAxis.invert(); + } + } + + if (intervalOneAbs < resultMTD) + { + resultMTD = intervalOneAbs; + mtdAxis = testAxis; + } + } + + var result:CollisionResult = new CollisionResult(); + result.mtdAmount = resultMTD; + result.mtdAxis = mtdAxis; + result.collision = true; + + return result; + //*/ + } + + private function detectCircleCircle(circleOne:CircleShape, circleTwo:CircleShape):Null + { + var circleOneWorldPosition:Vector2D = circleOne.body.localToWorld(circleOne.position); + var circleTwoWorldPosition:Vector2D = circleTwo.body.localToWorld(circleTwo.position); + var distanceSquared:Float = Math.pow(circleTwoWorldPosition.x - circleOneWorldPosition.x, 2) + Math.pow(circleTwoWorldPosition.y - circleOneWorldPosition.y, 2); + var radiusesSquared:Float = (circleOne.radius + circleTwo.radius)*(circleOne.radius + circleTwo.radius); + if (distanceSquared >= radiusesSquared) + { + return null; + } + var result:CollisionResult = new CollisionResult(); + result.collision = true; + result.mtdAmount = Math.sqrt(radiusesSquared) - Math.sqrt(distanceSquared); + result.mtdAxis = circleOneWorldPosition.clone().subtract(circleTwoWorldPosition).normalize(); + return result; + } + + private function projectVerticeSetOnAxis(verticeSet:Array, axis:Vector2D):ProjectionResult + { + verticeNum = verticeSet.length; + min = Vector2D.dotProduct(verticeSet[0], axis); + max = Vector2D.dotProduct(verticeSet[0], axis); + for (i in 1...verticeNum) + { + projectionPoint = Vector2D.dotProduct(verticeSet[i], axis); + if (projectionPoint < min) + { + min = projectionPoint; + } + if (projectionPoint > max) + { + max = projectionPoint; + } + } + + projectionResult.min = min; + projectionResult.max = max; + + return projectionResult; + } + + private function projectPolygonOnAxis(polygon:Polygon, axis:Vector2D):ProjectionResult + { + var body:PhysicalBody = polygon.body; + var min:Float = Vector2D.dotProduct(body.localToWorld(polygon.vertices[0]), axis); + var max:Float = Vector2D.dotProduct(body.localToWorld(polygon.vertices[0]), axis); + var projectionPoint:Float; + for (i in 1...polygon.getNumVertices()) + { + projectionPoint = Vector2D.dotProduct(body.localToWorld(polygon.vertices[i]), axis); + if (projectionPoint < min) + min = projectionPoint; + if (projectionPoint > max) + max = projectionPoint; + } + + projectionResult.min = min; + projectionResult.max = max; + + return projectionResult; + } + + private function closestPointOnLineSegment(startPoint:Vector2D, segment:Vector2D, point:Vector2D):Vector2D + { + var closestPoint:Vector2D; + + var testDotProduct:Float = Vector2D.dotProduct(segment, point.clone().subtract(startPoint)); + var segmentLengthSquared:Float = segment.getLengthSquared(); + + if (testDotProduct <= 0) + { + closestPoint = startPoint.clone(); + } else if(testDotProduct >= segmentLengthSquared) { + closestPoint = startPoint.clone().add(segment); + } else { + var segmentPart:Float = testDotProduct / segmentLengthSquared; + closestPoint = startPoint.clone().add(segment.clone().multiply(segmentPart)); + } + + return closestPoint; + } + + private function projectCircleOnAxis(circle:CircleShape, axis:Vector2D):ProjectionResult + { + var center:Float = Vector2D.dotProduct(circle.body.localToWorld(circle.position), axis); + projectionResult.min = center - circle.radius; + projectionResult.max = center + circle.radius; + return projectionResult; + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/CollisionResult.hx b/src/sphaeraGravita/collision/CollisionResult.hx new file mode 100644 index 0000000..86328ef --- /dev/null +++ b/src/sphaeraGravita/collision/CollisionResult.hx @@ -0,0 +1,26 @@ +package sphaeraGravita.collision; + +import sphaeraGravita.math.Vector2D; +/** + * ... + * @author Dimonte + */ +class CollisionResult +{ + public var collision:Bool; + public var mtdAmount:Float; + public var mtdAxis:Vector2D; + public var mtdVector:Vector2D; + + public function new () + { + + } + + public function calculateMTDVector():Vector2D + { + mtdVector = mtdAxis.clone().multiply(mtdAmount); + return mtdVector; + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/PhysicalBody.hx b/src/sphaeraGravita/collision/PhysicalBody.hx new file mode 100644 index 0000000..9608dae --- /dev/null +++ b/src/sphaeraGravita/collision/PhysicalBody.hx @@ -0,0 +1,207 @@ +package sphaeraGravita.collision; + + +import dataStructures.DLL; +import dataStructures.DLLNode; +import sphaeraGravita.math.RotationMatrix; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.spacePartitioning.GridCell; +//import sphaeraGravita.shapes.BaseShape; + +/** + * ... + * @author Dimonte + */ +class PhysicalBody extends CollidingEntity +{ + + public var boundingAABB:AABB; + public var xformedBoundingAABB:AABB; + public var worldAABB:AABB; + public var shapeList:BaseShape; + public var colliding:Bool; + public var gridBound:Bool; + public var overlappingCells:Array; + public var fixed:Bool; + public var dead:Bool; + + public var position:Vector2D; + public var xform:RotationMatrix; + public var speed:Vector2D; + + public var bounceFactor:Float; + public var frictionFactor:Float; + + public var x(get,set):Float; + public var y(get,set):Float; + public var rotation(get,set):Float; + + public function new() + { + bounceFactor = 1; + frictionFactor = 1; + position = new Vector2D(); + speed = new Vector2D(); + xform = new RotationMatrix(); + } + + public function clearShapes():Void + { + shapeList = null; + } + + public function addShape(shape:BaseShape):Void + { + shape.parent = shape.body = this; + + if (shapeList != null) { + var shapeNode:BaseShape = shapeList; + while (shapeNode.next != null) { + shapeNode = shapeNode.next; + } + shapeNode.next = shape; + } else { + shapeList = shape; + } + } + + public function init():Void + { + var minX:Float = Math.POSITIVE_INFINITY; + var minY:Float = Math.POSITIVE_INFINITY; + var maxX:Float = Math.NEGATIVE_INFINITY; + var maxY:Float = Math.NEGATIVE_INFINITY; + + var shape:BaseShape = shapeList; + + // if there's no shapes inside, zeroes abound! + if (shape == null) + { + minX = minY = maxX = maxY = 0; + } + + while (shape != null) + { + minX = Math.min(minX, shape.getBoundingAABB().lowerBound.x); + minY = Math.min(minY, shape.getBoundingAABB().lowerBound.y); + maxX = Math.max(maxX, shape.getBoundingAABB().upperBound.x); + maxY = Math.max(maxY, shape.getBoundingAABB().upperBound.y); + shape = shape.next; + } + boundingAABB = AABB.asMinMax(minX, minY, maxX, maxY); + xformedBoundingAABB = AABB.asMinMax(minX, minY, maxX, maxY); + worldAABB = AABB.asMinMax(minX, minY, maxX, maxY); + } + + public function updateWorldCache():Void + { + if (worldAABB == null) + { + //trace(this); + return; + } + worldAABB.lowerBound.x = xformedBoundingAABB.lowerBound.x + position.x; + worldAABB.lowerBound.y = xformedBoundingAABB.lowerBound.y + position.y; + worldAABB.upperBound.x = xformedBoundingAABB.upperBound.x + position.x; + worldAABB.upperBound.y = xformedBoundingAABB.upperBound.y + position.y; + } + + private function recalculateXformedAABB():Void + { + var tl:Vector2D = boundingAABB.getTopLeftCorner().applyXform(xform); + var tr:Vector2D = boundingAABB.getTopRightCorner().applyXform(xform); + var bl:Vector2D = boundingAABB.getBottomLeftCorner().applyXform(xform); + var br:Vector2D = boundingAABB.getBottomRightCorner().applyXform(xform); + var minX:Float = Math.min(Math.min(tl.x, tr.x), Math.min(bl.x, br.x)); + var minY:Float = Math.min(Math.min(tl.y, tr.y), Math.min(bl.y, br.y)); + var maxX:Float = Math.max(Math.max(tl.x, tr.x), Math.max(bl.x, br.x)); + var maxY:Float = Math.max(Math.max(tl.y, tr.y), Math.max(bl.y, br.y)); + xformedBoundingAABB.lowerBound.x = minX; + xformedBoundingAABB.lowerBound.y = minY; + xformedBoundingAABB.upperBound.x = maxX; + xformedBoundingAABB.upperBound.y = maxY; + } + + public function set_x(value:Float):Float + { + position.x = value; + return position.x; + } + + public function get_x():Float + { + return position.x; + } + + public function get_y():Float + { + return position.y; + } + + public function set_y(value:Float):Float + { + position.y = value; + return position.y; + } + + /** + * Gets and sets rotation angle in radians + */ + public function get_rotation():Float + { + return xform.angle; + } + + public function set_rotation(value:Float):Float + { + xform.setAngle(value); + recalculateXformedAABB(); + return xform.angle; + } + + /** + * Does not modify localPoint + * @param localPoint point in local coordinates + * @return point in world coordinates + */ + public function localToWorld(localPoint:Vector2D, t:Bool = false):Vector2D + { + return localPoint.clone().applyXform(xform).add(position); + } + + /** + * Checks if body is in specified bounds + * @param x + * @param y + * @param width + * @param heigth + * @return + */ + public function inBounds(x:Float, y:Float, width:Float, heigth:Float):Bool + { + if (worldAABB.upperBound.x < x) + { + return false; + } + if (worldAABB.upperBound.y < y) + { + return false; + } + if (worldAABB.lowerBound.x > x + width) + { + return false; + } + if (worldAABB.lowerBound.y > y +heigth) + { + return false; + } + return true; + } + + public function reactToCollision(collidingBody:PhysicalBody, selfShape:BaseShape, otherShape:BaseShape):Void + { + + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/collision/ProjectionResult.hx b/src/sphaeraGravita/collision/ProjectionResult.hx new file mode 100644 index 0000000..3a06f30 --- /dev/null +++ b/src/sphaeraGravita/collision/ProjectionResult.hx @@ -0,0 +1,17 @@ +package sphaeraGravita.collision; + +/** + * ... + * @author Dimonte + */ +class ProjectionResult +{ + public var min:Float; + public var max:Float; + + public function new (min:Float = 0, max:Float = 0) + { + this.min = min; + this.max = max; + } +} \ No newline at end of file diff --git a/src/sphaeraGravita/math/RotationMatrix.hx b/src/sphaeraGravita/math/RotationMatrix.hx new file mode 100644 index 0000000..24e79d1 --- /dev/null +++ b/src/sphaeraGravita/math/RotationMatrix.hx @@ -0,0 +1,33 @@ +package sphaeraGravita.math; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class RotationMatrix +{ + + public var sin:Float; + public var cos:Float; + + /** + * Use this variable to read angle information ONLY! Use setAngle to set angle. + */ + public var angle:Float; + + public function new():Void + { + setAngle(0); + } + + public function setAngle(angle:Float):Void + { + this.angle = angle; + sin = Math.sin(angle); + cos = Math.cos(angle); + } + + + +} \ No newline at end of file diff --git a/src/sphaeraGravita/math/Vector2D.hx b/src/sphaeraGravita/math/Vector2D.hx new file mode 100644 index 0000000..cfc8a6b --- /dev/null +++ b/src/sphaeraGravita/math/Vector2D.hx @@ -0,0 +1,117 @@ +package sphaeraGravita.math; + + +/** + * ... + * @author Dimonte + */ +class Vector2D +{ + + public static function dotProduct(vector1:Vector2D, vector2:Vector2D):Float + { + return vector1.x * vector2.x + vector1.y * vector2.y; + } + + public static function project(vector:Vector2D, vectorToProjectOn:Vector2D):Vector2D + { + var vectorToProjectOnNormal:Vector2D = vectorToProjectOn.clone().normalize(); + var dp:Float = dotProduct(vector, vectorToProjectOnNormal); + return new Vector2D(dp * vectorToProjectOnNormal.x, dp * vectorToProjectOnNormal.y); + } + + public var x:Float; + public var y:Float; + + public function new(?x:Float=0, ?y:Float=0) + { + this.x = x; + this.y = y; + } + + public function getLength():Float + { + return Math.sqrt(x * x + y * y); + } + + public function getLengthSquared():Float + { + return (x * x + y * y); + } + + public function add(vector:Vector2D):Vector2D + { + x += vector.x; + y += vector.y; + return this; + } + + public function subtract(vector:Vector2D):Vector2D + { + x -= vector.x; + y -= vector.y; + return this; + } + + public function multiply(multiplier:Float):Vector2D + { + x *= multiplier; + y *= multiplier; + return this; + } + + public function getNormalLeft():Vector2D + { + return new Vector2D( y, -x ); + } + + public function getNormalRight():Vector2D + { + return new Vector2D( -y, x ); + } + + public function invert():Vector2D + { + x = -x; + y = -y; + return this; + } + + public function equals(vector:Vector2D):Bool + { + return (x == vector.x) && (y == vector.y); + } + + public function clone():Vector2D + { + return new Vector2D(x, y); + } + + public function normalize():Vector2D + { + var length:Float = this.getLength(); + if ( length == 0 ) + { + return this; + } else { + x /= length; + y /= length; + } + return this; + } + + public function applyXform(xform:RotationMatrix):Vector2D + { + var newX:Float = x * xform.cos - y * xform.sin; + var newY:Float = x * xform.sin + y * xform.cos; + x = newX; + y = newY; + return this; + } + + public function toString():String + { + return "(" + x + "," + y + ")"; + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/shapes/BaseShape.hx b/src/sphaeraGravita/shapes/BaseShape.hx new file mode 100644 index 0000000..c14decf --- /dev/null +++ b/src/sphaeraGravita/shapes/BaseShape.hx @@ -0,0 +1,33 @@ +package sphaeraGravita.shapes; + +import flash.errors.IllegalOperationError; +import game.CollisionCategory; +import sphaeraGravita.collision.AABB; +import sphaeraGravita.collision.CollidingEntity; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +/** + * ... + * @author Dimonte + */ +class BaseShape extends CollidingEntity +{ + public var body:PhysicalBody; + public var previous:BaseShape; + public var next:BaseShape; + public var sensor:Bool; + public var name:String; + public var type:String; + + public function new(type:String) + { + this.type = type; + } + + public function getBoundingAABB():AABB + { + throw new IllegalOperationError("Function must be overridden"); + return new AABB(); + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/shapes/CircleShape.hx b/src/sphaeraGravita/shapes/CircleShape.hx new file mode 100644 index 0000000..82a800d --- /dev/null +++ b/src/sphaeraGravita/shapes/CircleShape.hx @@ -0,0 +1,28 @@ +package sphaeraGravita.shapes; + +import sphaeraGravita.collision.AABB; +import sphaeraGravita.math.Vector2D; + +/** + * ... + * @author Dimonte + */ +class CircleShape extends BaseShape +{ + public var radius:Float; + public var position:Vector2D; + + public function new(x:Float, y:Float, radius:Float) + { + super(ShapeType.CIRCLE_SHAPE); + position = new Vector2D(x, y); + this.radius = radius; + } + + override public function getBoundingAABB():AABB + { + var boundingAABB:AABB = AABB.asMinMax(position.x - radius, position.y - radius, position.x + radius, position.y + radius); + return boundingAABB; + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/shapes/Polygon.hx b/src/sphaeraGravita/shapes/Polygon.hx new file mode 100644 index 0000000..0b40751 --- /dev/null +++ b/src/sphaeraGravita/shapes/Polygon.hx @@ -0,0 +1,95 @@ +package sphaeraGravita.shapes; + +import sphaeraGravita.collision.AABB; +import sphaeraGravita.math.Vector2D; +/** + * ... + * @author Dimonte + */ +class Polygon extends BaseShape +{ + public var vertices:Array; + public var normals:Array; + private var _worldVerticesCache:Array; + public var cacheUpdateRequired:Bool; + + public function new() + { + super(ShapeType.POLYGON_SHAPE); + vertices = new Array(); + normals = new Array(); + _worldVerticesCache = new Array(); + } + + public function setPoly(vertices:Array):Void + { + this.vertices = vertices; + initialize(); + } + + public function initialize():Void + { + normals.splice(0, normals.length); + for (i in 0...vertices.length - 1) + { + var edge:Vector2D = vertices[i + 1].clone().subtract(vertices[i]); + normals[i] = edge.getNormalLeft().normalize(); + //trace("vertex " + i, vertices[i]); + //_worldVerticesCache[i] = vertices[i].clone().add(position); + } + normals[vertices.length - 1] = vertices[0].clone().subtract(vertices[vertices.length - 1]).getNormalLeft().normalize(); + } + + public function getWorldVertex(vertexNum:Int):Vector2D + { + if (cacheUpdateRequired) + { + updateWorldVerticesCache(); + } + return _worldVerticesCache[vertexNum]; + } + + private function updateWorldVerticesCache():Void + { + for (i in 0...vertices.length) + { + _worldVerticesCache[i] = body.localToWorld(vertices[i]); + } + } + + public function getNumVertices():Int + { + return vertices.length; + } + + override public function getBoundingAABB():AABB + { + var minX:Float = Math.POSITIVE_INFINITY; + var minY:Float = Math.POSITIVE_INFINITY; + var maxX:Float = Math.NEGATIVE_INFINITY; + var maxY:Float = Math.NEGATIVE_INFINITY; + var vertice:Vector2D; + for (i in 0...vertices.length) + { + vertice = vertices[i]; + minX = Math.min(minX, vertice.x); + minY = Math.min(minY, vertice.y); + maxX = Math.max(maxX, vertice.x); + maxY = Math.max(maxY, vertice.y); + } + + var boundingAABB:AABB = AABB.asMinMax(minX, minY, maxX, maxY); + //trace(boundingAABB); + return boundingAABB; + } + + public function setAsBox(halfWidth:Float, halfHeight:Float):Void + { + vertices[0] = new Vector2D( -halfWidth, -halfHeight); + vertices[1] = new Vector2D( halfWidth, -halfHeight); + vertices[2] = new Vector2D( halfWidth, halfHeight); + vertices[3] = new Vector2D( -halfWidth, halfHeight); + initialize(); + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/shapes/ShapeType.hx b/src/sphaeraGravita/shapes/ShapeType.hx new file mode 100644 index 0000000..0b6be64 --- /dev/null +++ b/src/sphaeraGravita/shapes/ShapeType.hx @@ -0,0 +1,12 @@ +package sphaeraGravita.shapes; + +/** + * ... + * @author Dimonte + */ +class ShapeType +{ + public static inline var CIRCLE_SHAPE:String = "circleShape"; + public static inline var POLYGON_SHAPE:String = "polygonShape"; + +} \ No newline at end of file diff --git a/src/sphaeraGravita/spacePartitioning/GridCell.hx b/src/sphaeraGravita/spacePartitioning/GridCell.hx new file mode 100644 index 0000000..5940f89 --- /dev/null +++ b/src/sphaeraGravita/spacePartitioning/GridCell.hx @@ -0,0 +1,22 @@ +package sphaeraGravita.spacePartitioning; + +import dataStructures.DLL; +/** + * ... + * @author ... + */ +class GridCell +{ + public var x:Int; + public var y:Int; + public var activeObjectList:DLL; + public var fixedObjectList:DLL; + public var dirty:Bool; + + public function new() + { + activeObjectList = new DLL(); + fixedObjectList = new DLL(); + } + +} \ No newline at end of file diff --git a/src/sphaeraGravita/spacePartitioning/UniformGrid.hx b/src/sphaeraGravita/spacePartitioning/UniformGrid.hx new file mode 100644 index 0000000..532eb20 --- /dev/null +++ b/src/sphaeraGravita/spacePartitioning/UniformGrid.hx @@ -0,0 +1,165 @@ +package sphaeraGravita.spacePartitioning; + +import game.GameEntity; +import game.Tile; +import sphaeraGravita.math.Vector2D; +/** + * ... + * @author Dmitry Barabanschikov + */ +class UniformGrid +{ + public static inline var CELL_SIZE:Int = 40; //TODO change to 40, make literal + + public var cells:Array; + public var dummy:GridCell; + public var dirtyCells:Array; + public var height:Int; + public var width:Int; + public var padding:Int; + public var minX:Int; + public var maxX:Int; + public var paddedWidth:Int; + public var minY:Int; + public var maxY:Int; + public var paddedHeight:Int; + + private var correctedX:Int; + private var correctedY:Int; + + public function new() + { + dummy = new GridCell(); + cells = new Array(); + dirtyCells = new Array(); + } + + /** + * Initializes uniform grid + * @param width + * @param height + * @param padding + */ + public function initialize(width:Int, height:Int, padding:Int):Void + { + dummy = new GridCell(); + dirtyCells = []; + + this.width = width; + this.height = height; + this.padding = padding; + + minX = - padding; + maxX = width + padding; + paddedWidth = width + padding * 2; + minY = - padding; + maxY = height + padding; + paddedHeight = height + padding * 2; + + var totalNumberOfCells:Int = paddedWidth*paddedHeight; + + + for (i in 0...totalNumberOfCells) + { + if (cells[i] == null) + { + cells[i] = new GridCell(); + } + var cell:GridCell = cells[i]; + cell.activeObjectList.clear(); + cell.fixedObjectList.clear(); + cell.x = Std.int(i / paddedHeight) - padding; + cell.y = Std.int(i % paddedHeight) - padding; + } + + while (cells.length > totalNumberOfCells) + { + cells.pop(); + } + } + + /** + * Cleans all cells containing active objects + */ + public function clean():Void + { + for (i in 0...dirtyCells.length) + { + dirtyCells[i].activeObjectList.clear(); + dirtyCells[i].dirty = false; + } + while (dirtyCells.length > 0) + { + dirtyCells.pop(); + } + + dummy.activeObjectList.clear(); + } + + /** + * Returns cell at (x,y), if out of bounds, returns dummy cell (still usable) + * @param x + * @param y + */ + public function getCellAt(x:Int, y:Int):GridCell + { + if (x < minX) { return dummy; } + if (x >= maxX) { return dummy; } + if (y >= maxY) { return dummy; } + if (y < minY) { return dummy; } + correctedX = x + padding; + correctedY = y + padding; + return cells[correctedX * paddedHeight + correctedY]; + } + + public function placeTile(tile:Tile):Void + { + //getCellAt(Int(tile.position.x / CELL_SIZE), Int(tile.position.y / CELL_SIZE)).fixedObjectList.append(tile); + placeFixedObject(tile); + } + + public function placeFixedObject(object:GameEntity):Void + { + var overlappingCells:Array = getCellsBetweenPoints(object.worldAABB.lowerBound, object.worldAABB.upperBound); + object.overlappingCells = overlappingCells; + for (i in 0...overlappingCells.length) + { + overlappingCells[i].fixedObjectList.append(object); + } + } + + public function placeActiveObject(activeObject:GameEntity):Void + { + var overlappingCells:Array = getCellsBetweenPoints(activeObject.worldAABB.lowerBound, activeObject.worldAABB.upperBound); + activeObject.overlappingCells = overlappingCells; + for (i in 0...overlappingCells.length) + { + overlappingCells[i].activeObjectList.append(activeObject); + if (overlappingCells[i].dirty) + { + continue; + } else + { + dirtyCells.push(overlappingCells[i]); + } + } + } + + public function getCellsBetweenPoints(pointOne:Vector2D, pointTwo:Vector2D):Array + { + var startX:Int = Std.int(pointOne.x / CELL_SIZE); + var startY:Int = Std.int(pointOne.y / CELL_SIZE); + var endX:Int = Std.int(pointTwo.x / CELL_SIZE) + 1; + var endY:Int = Std.int(pointTwo.y / CELL_SIZE) + 1; + var cellArray:Array = []; + for (i in startX...endX) + { + for (j in startY...endY) + { + cellArray.push(getCellAt(i, j)); + } + } + return cellArray; + } + +} \ No newline at end of file diff --git a/src/view/PhysicalWorldView.hx b/src/view/PhysicalWorldView.hx new file mode 100644 index 0000000..4ad6f39 --- /dev/null +++ b/src/view/PhysicalWorldView.hx @@ -0,0 +1,156 @@ +package view; + +import assets.GraphicsLibrary; +import dataStructures.DLL; +import dataStructures.DLLNode; +import flash.display.Bitmap; +import flash.display.BitmapData; +import flash.geom.Matrix; +import flash.geom.Point; +import flash.geom.Rectangle; +import game.Bullet; +import game.BulletHit; +import game.Debries; +import game.EnemyShip; +import game.Explosion; +import game.GameEntity; +import game.GameStage; +import game.GameWorld; +import game.PlayerShip; +import game.Tile; +import openfl.Assets; +import sphaeraGravita.collision.AABB; +import sphaeraGravita.collision.CollisionResult; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; +import sphaeraGravita.shapes.ShapeType; +import sphaeraGravita.spacePartitioning.GridCell; +import sphaeraGravita.spacePartitioning.UniformGrid; +/** + * ... + * @author Dimonte + */ +class PhysicalWorldView extends WorldView +{ + public var debugDraw:Bool; + + private var _world:GameWorld; + private var _canvas:Bitmap; + private var _skyBD:BitmapData; + private var _worldDrawMarker:Int; + private var screenWidth:Int; + private var screenHeight:Int; + + public function new(gameStage:GameStage, screenWidth:Int, screenHeight:Int) + { + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + super(gameStage); + + _skyBD = Assets.getBitmapData("assets/general/sky.png"); + var skyBitmap:Bitmap = new Bitmap(_skyBD); + skyBitmap.scaleX = screenWidth / skyBitmap.width; + skyBitmap.scaleY = screenHeight / skyBitmap.height; + addChild(skyBitmap); + + _world = gameStage.gameWorld; + _canvas = new Bitmap(new BitmapData(screenWidth, screenHeight)); + + //_canvas.alpha = 0.5; + addChild(_canvas); + + createScoreDisplay(); + } + + override public function update():Void + { + super.update(); + + drawStuff(); + } + + public function drawStuff():Void + { + _worldDrawMarker = Std.int(_world.activeZoneStartMarker); + _canvas.bitmapData.lock(); + + _canvas.bitmapData.fillRect(new Rectangle(0, 0, screenWidth, screenHeight), 0x0); + + drawEntityList(_world.tiles); + drawEntityList(_world.playerBullets); + if (!_world.player.dead) + { + drawEntity(_world.player, true); + } + drawEntityList(_world.enemies); + drawEntityList(_world.particles); + drawEntityList(_world.enemyBullets); + + _canvas.bitmapData.fillRect(new Rectangle(0, 0, _world.player.healthPoints * (screenWidth/800), 10), 0xFFFF0000); + + _canvas.bitmapData.unlock(); + } + + private function drawEntityList(list:DLL):Void + { + var node:DLLNode = list._head; + var entity:GameEntity; + while (node != null) + { + entity = cast(node.val, GameEntity); + node = node.next; + if (entity.dead) + { + continue; + } + if (entity.worldAABB.upperBound.x - _worldDrawMarker < 0) + { + continue; + } + if (entity.worldAABB.lowerBound.x - _worldDrawMarker > screenWidth) + { + continue; + } + + drawEntity(entity); + + } + } + + private function drawEntity(ge:GameEntity, ?debug:Bool = false):Void + { + + if (ge == null) + { + //SOSLog.sosTrace( "ge : " + ge ); + return; + } + + if (ge.graphicsAsset == null) + { + //SOSLog.sosTrace( "ge.graphicsAsset : " + ge.graphicsAsset ); + return; + } + + var sr:Rectangle = ge.graphicsAsset.frameRectangles[ge.frameRectNum]; + var dp:Point = new Point(ge.x - _worldDrawMarker, ge.y).add(ge.graphicsAsset.sizeCorrection); + var source:BitmapData = ge.graphicsAsset.spriteSheet; + if (ge.rotation != 0) + { + var sourceClip:BitmapData = new BitmapData(Std.int(sr.width), Std.int(sr.height), true, 0x0); + sourceClip.copyPixels(source, sr, new Point(0,0)); + var m:Matrix = new Matrix(); + m.createBox(1, 1, ge.rotation, dp.x, dp.y); + _canvas.bitmapData.draw(sourceClip, m); + } else + { + _canvas.bitmapData.copyPixels(source, sr, dp, null, null, true); + } + + } + +} \ No newline at end of file diff --git a/src/view/TilesView.hx b/src/view/TilesView.hx new file mode 100644 index 0000000..7b91d05 --- /dev/null +++ b/src/view/TilesView.hx @@ -0,0 +1,151 @@ +package view; + +import assets.GraphicsLibrary; +import dataStructures.DLL; +import dataStructures.DLLNode; +import flash.display.Bitmap; +import flash.display.BitmapData; +import flash.display.Sprite; +import game.Bullet; +import game.BulletHit; +import game.Debries; +import game.EnemyShip; +import game.Explosion; +import game.GameEntity; +import game.GameStage; +import game.GameWorld; +import game.PlayerShip; +import game.Tile; +import openfl.Assets; +import sphaeraGravita.collision.AABB; +import sphaeraGravita.collision.CollisionResult; +import sphaeraGravita.collision.PhysicalBody; +import sphaeraGravita.math.Vector2D; +import sphaeraGravita.shapes.BaseShape; +import sphaeraGravita.shapes.CircleShape; +import sphaeraGravita.shapes.Polygon; +import sphaeraGravita.shapes.ShapeType; +import sphaeraGravita.spacePartitioning.GridCell; +import sphaeraGravita.spacePartitioning.UniformGrid; +/** + * ... + * @author Dimonte + */ +class TilesView extends WorldView +{ + public var debugDraw:Bool; + + private var _world:GameWorld; + private var _skyBD:BitmapData; + private var _worldDrawMarker:Int; + private var tilesCanvas:Sprite; + private var toDraw:Array; + private var healthBitmap:Bitmap; + private var screenWidth:Int; + private var screenHeight:Int; + + public function new(gameStage:GameStage, screenWidth:Int, screenHeight:Int) + { + super(gameStage); + + this.screenWidth = screenWidth; + this.screenHeight = screenHeight; + + _world = gameStage.gameWorld; + + _skyBD = Assets.getBitmapData("assets/general/sky.png"); + var skyBitmap:Bitmap = new Bitmap(_skyBD); + skyBitmap.scaleX = screenWidth / skyBitmap.width; + skyBitmap.scaleY = screenHeight / skyBitmap.height; + addChild(skyBitmap); + + tilesCanvas = new Sprite(); + addChild(tilesCanvas); + + healthBitmap = new Bitmap(new BitmapData(1, 1, false, 0xFFFF0000)); + healthBitmap.scaleY = 10; + addChild(healthBitmap); + + toDraw = new Array(); + + createScoreDisplay(); + } + + override public function update():Void + { + super.update(); + tilesCanvas.graphics.clear(); + drawStuff(); + } + + public function drawStuff():Void + { + _worldDrawMarker = Std.int(_world.activeZoneStartMarker); + + + var toDrawLength:Int = 0; + + toDrawLength = addEntityListTiles(_world.tiles, toDraw, toDrawLength); + toDrawLength = addEntityListTiles(_world.playerBullets, toDraw, toDrawLength); + if (!_world.player.dead) + { + toDrawLength = drawEntity(_world.player, toDraw, toDrawLength); + } + toDrawLength = addEntityListTiles(_world.enemies, toDraw, toDrawLength); + toDrawLength = addEntityListTiles(_world.particles, toDraw, toDrawLength); + toDrawLength = addEntityListTiles(_world.enemyBullets, toDraw, toDrawLength); + + while (toDraw.length > toDrawLength) + { + toDraw.pop(); + } + + + tilesCanvas.graphics.drawTiles(GraphicsLibrary.tilesheet, toDraw); + + //trace( "toDraw : " + toDraw ); + + if (healthBitmap.scaleX != _world.player.healthPoints * (screenWidth/800)) + { + healthBitmap.scaleX = _world.player.healthPoints * (screenWidth/800); + } + } + + private function addEntityListTiles(list:DLL, toDraw:Array, toDrawLength:Int):Int + { + var node:DLLNode = list._head; + var entity:GameEntity; + while (node != null) + { + entity = cast(node.val, GameEntity); + node = node.next; + if (entity.dead) + { + continue; + } + /*if (entity.worldAABB.upperBound.x - _worldDrawMarker < 0) + { + continue; + } + if (entity.worldAABB.lowerBound.x - _worldDrawMarker > 800) + { + continue; + }*/ + + toDrawLength = drawEntity(entity, toDraw, toDrawLength); + } + return toDrawLength; + } + + private function drawEntity(ge:GameEntity, drawList:Array, toDrawLength:Int):Int + { + drawList[toDrawLength] = Std.int(ge.x - _worldDrawMarker + ge.graphicsAsset.sizeCorrection.x); + toDrawLength++; + drawList[toDrawLength] = Std.int(ge.y + ge.graphicsAsset.sizeCorrection.y); + toDrawLength++; + drawList[toDrawLength] = ge.graphicsAsset.tileSheetFrameID[ge.frameRectNum]; + toDrawLength++; + return toDrawLength; + } + +} \ No newline at end of file diff --git a/src/view/WorldView.hx b/src/view/WorldView.hx new file mode 100644 index 0000000..5f97a64 --- /dev/null +++ b/src/view/WorldView.hx @@ -0,0 +1,50 @@ +package view; +import flash.display.Sprite; +import flash.text.TextField; +import flash.text.TextFieldAutoSize; +import flash.text.TextFormat; +import game.GameStage; + +/** + * ... + * @author Dmitriy Barabanschikov + */ + +class WorldView extends Sprite +{ + private var scoreTextField:TextField; + public var gameStage:GameStage; + + public function new(gameStage:GameStage) + { + super(); + this.gameStage = gameStage; + } + + public function update():Void + { + scoreTextField.text = "Score: " + gameStage.gameWorld.score; + } + + public function createScoreDisplay():Void + { + scoreTextField = new TextField(); + scoreTextField.embedFonts = true; + scoreTextField.y = 14; + scoreTextField.x = 8; + scoreTextField.autoSize = TextFieldAutoSize.LEFT; + scoreTextField.mouseEnabled = false; + + var scoreTextFormat:TextFormat = scoreTextField.defaultTextFormat; + + scoreTextFormat.font = FontManager.mainFont.fontName; + scoreTextFormat.size = 16; + scoreTextFormat.color = 0xFFFFFF; + scoreTextFormat.bold = true; + + scoreTextField.defaultTextFormat = scoreTextFormat; + + addChild(scoreTextField); + } + +} \ No newline at end of file