From 464bda0b44abc4b375fb59ce0fcf8ddf2fc0d755 Mon Sep 17 00:00:00 2001 From: Mitch Weaver <20451170+MitchWeaver@users.noreply.github.com> Date: Sun, 26 Nov 2017 03:00:36 +0100 Subject: [PATCH] initial commit --- .gitignore | 3 + README.md | 11 + dev/Forlorn Hope - Plot.odt.lrz | Bin 0 -> 15338 bytes dev/PyxelEdit/Player.pyxel | Bin 0 -> 1796 bytes dev/PyxelEdit/defaultGun.pyxel | Bin 0 -> 929 bytes dev/unused art/GameBoy Color Pallete.png | Bin 0 -> 122 bytes dev/unused art/butterfly.png | Bin 0 -> 129 bytes dev/unused art/flowers.png | Bin 0 -> 117 bytes res/Forlorn-Hope.jpg | Bin 0 -> 25133 bytes res/backgrounds/.getxfer.7000.61.mega | 0 res/backgrounds/background.png | Bin 0 -> 371 bytes res/backgrounds/foreground.png | Bin 0 -> 512 bytes res/backgrounds/midground.png | Bin 0 -> 140 bytes res/backgrounds/scenery-demo.png | Bin 0 -> 1197 bytes res/data/map.png | Bin 0 -> 551 bytes res/sounds/effects/jump_sound.mp3 | Bin 0 -> 8821 bytes res/sounds/effects/splat.mp3 | Bin 0 -> 17389 bytes res/sounds/effects/tir.mp3 | Bin 0 -> 6330 bytes res/spritesheets/hud/asdf.png | Bin 0 -> 154 bytes res/spritesheets/hud/test.png | Bin 0 -> 160 bytes res/spritesheets/mobs/scraveller.png | Bin 0 -> 132 bytes res/spritesheets/player/Player1.png | Bin 0 -> 532 bytes res/spritesheets/player/Player2.png | Bin 0 -> 602 bytes res/spritesheets/player/Player3.png | Bin 0 -> 604 bytes res/spritesheets/player/Player4.png | Bin 0 -> 602 bytes res/spritesheets/player/Player5.png | Bin 0 -> 955 bytes res/spritesheets/player/default_gun.png | Bin 0 -> 151 bytes res/spritesheets/tiles/tile.png | Bin 0 -> 89 bytes src/core/Console.java | 16 + src/core/Main.java | 62 ++++ src/core/input/KeyInput.java | 34 ++ src/core/input/MouseInput.java | 38 +++ src/jython/Jython.java | 40 +++ src/jython/forlorn_hope_jython_imports.py | 31 ++ src/mobs/MobDamages.java | 8 + src/mobs/MobHealths.java | 9 + src/mobs/MobSpeeds.java | 7 + src/mobs/scraveller/Scraveller.java | 108 +++++++ src/mobs/scraveller/scraveller_ai.py | 42 +++ src/player/Player.java | 62 ++++ src/player/PlayerRenderer.java | 177 +++++++++++ src/player/gun/PlayerBulletDamages.java | 8 + src/player/gun/PlayerGun.java | 28 ++ src/player/gun/bullets/DefaultBullet.java | 76 +++++ src/player/gun/bullets/PlayerBullet.java | 21 ++ src/player/gun/player_gun.py | 136 ++++++++ src/player/player_animations.py | 60 ++++ src/tiles/Tile.java | 31 ++ src/ui/HUD.java | 3 + src/ui/inventory/Inventory.java | 48 +++ src/ui/inventory/InventorySlot.java | 35 ++ src/ui/inventory/ItemIDs.java | 17 + src/worldgen/TestMapCreator.java | 59 ++++ src/worldgen/WorldGenerator.java | 36 +++ textures/textures/Texture.java | 7 + textures/textures/TextureLoader.java | 25 ++ .../textures/mobs/ScravellerTextures.java | 27 ++ .../textures/player/PlayerGunTextures.java | 34 ++ textures/textures/player/PlayerTextures.java | 299 ++++++++++++++++++ textures/textures/tiles/TileTextures.java | 19 ++ 60 files changed, 1617 insertions(+) create mode 100755 dev/Forlorn Hope - Plot.odt.lrz create mode 100755 dev/PyxelEdit/Player.pyxel create mode 100755 dev/PyxelEdit/defaultGun.pyxel create mode 100755 dev/unused art/GameBoy Color Pallete.png create mode 100755 dev/unused art/butterfly.png create mode 100755 dev/unused art/flowers.png create mode 100755 res/Forlorn-Hope.jpg create mode 100755 res/backgrounds/.getxfer.7000.61.mega create mode 100755 res/backgrounds/background.png create mode 100755 res/backgrounds/foreground.png create mode 100755 res/backgrounds/midground.png create mode 100755 res/backgrounds/scenery-demo.png create mode 100755 res/data/map.png create mode 100755 res/sounds/effects/jump_sound.mp3 create mode 100755 res/sounds/effects/splat.mp3 create mode 100755 res/sounds/effects/tir.mp3 create mode 100755 res/spritesheets/hud/asdf.png create mode 100755 res/spritesheets/hud/test.png create mode 100755 res/spritesheets/mobs/scraveller.png create mode 100755 res/spritesheets/player/Player1.png create mode 100755 res/spritesheets/player/Player2.png create mode 100755 res/spritesheets/player/Player3.png create mode 100755 res/spritesheets/player/Player4.png create mode 100755 res/spritesheets/player/Player5.png create mode 100755 res/spritesheets/player/default_gun.png create mode 100755 res/spritesheets/tiles/tile.png create mode 100755 src/core/Console.java create mode 100755 src/core/Main.java create mode 100755 src/core/input/KeyInput.java create mode 100755 src/core/input/MouseInput.java create mode 100755 src/jython/Jython.java create mode 100755 src/jython/forlorn_hope_jython_imports.py create mode 100755 src/mobs/MobDamages.java create mode 100755 src/mobs/MobHealths.java create mode 100755 src/mobs/MobSpeeds.java create mode 100755 src/mobs/scraveller/Scraveller.java create mode 100755 src/mobs/scraveller/scraveller_ai.py create mode 100755 src/player/Player.java create mode 100755 src/player/PlayerRenderer.java create mode 100755 src/player/gun/PlayerBulletDamages.java create mode 100755 src/player/gun/PlayerGun.java create mode 100755 src/player/gun/bullets/DefaultBullet.java create mode 100755 src/player/gun/bullets/PlayerBullet.java create mode 100755 src/player/gun/player_gun.py create mode 100755 src/player/player_animations.py create mode 100755 src/tiles/Tile.java create mode 100755 src/ui/HUD.java create mode 100755 src/ui/inventory/Inventory.java create mode 100755 src/ui/inventory/InventorySlot.java create mode 100755 src/ui/inventory/ItemIDs.java create mode 100755 src/worldgen/TestMapCreator.java create mode 100755 src/worldgen/WorldGenerator.java create mode 100755 textures/textures/Texture.java create mode 100755 textures/textures/TextureLoader.java create mode 100755 textures/textures/mobs/ScravellerTextures.java create mode 100755 textures/textures/player/PlayerGunTextures.java create mode 100755 textures/textures/player/PlayerTextures.java create mode 100755 textures/textures/tiles/TileTextures.java diff --git a/.gitignore b/.gitignore index 6143e53..5cf39ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +bin +/bin/ + # Compiled class file *.class diff --git a/README.md b/README.md index b6276db..94afc03 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,13 @@ # Forlorn-Hope old abandoned game of mine, using my sjgs engine +------------------------------------- + +*Discontinued*: 2016 + +Might be useful if anyone wanted to see an example of the engine. + +Other than that, this is just a place to store it for nostalgia. + +-------------------- + +If you want to try it, simple `java -jar` the jar in /build diff --git a/dev/Forlorn Hope - Plot.odt.lrz b/dev/Forlorn Hope - Plot.odt.lrz new file mode 100755 index 0000000000000000000000000000000000000000..c311b0468934da4d7dd62426dac4a2575b7097cf GIT binary patch literal 15338 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%0Aso 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 U@6Lt2K*Jb3UHx3vIVCg!07CLGCIA2c literal 0 HcmV?d00001 diff --git a/dev/unused art/butterfly.png b/dev/unused art/butterfly.png new file mode 100755 index 0000000000000000000000000000000000000000..2c37e62042fcefb896baf539ce55e7305a880f38 GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^>>$j+1|*LJgFVdQ&MBb@0Di|RC;$Ke literal 0 HcmV?d00001 diff --git a/dev/unused art/flowers.png b/dev/unused art/flowers.png new file mode 100755 index 0000000000000000000000000000000000000000..0adb7c4019a377a180957fd34ab8fd8690de0623 GIT binary patch literal 117 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XK2JY5_^DsCmec>Vf!KdgTe~DWM4f{L3eD literal 0 HcmV?d00001 diff --git a/res/Forlorn-Hope.jpg b/res/Forlorn-Hope.jpg new file mode 100755 index 0000000000000000000000000000000000000000..66f1117e55af7e2b8c3ac52334d95f0ec63df66f GIT binary patch literal 25133 zcmeHv2{={lyZ4exDXAoxi;y8QXYNfxrpz;yVVh;1X+j7|=4?e~@|rXEhRB$)43T*z zvlPy=*4{M!-+%8p-*>+Aoy+dJR<-tC&w7S?_}%yYd!CJV8y}#9mo7?Pgm7?hpex`H zw9y5LLVI@a#@oGX4;~)g-o1P9_a7nHzi;1u(!)fAM<~gtsVK=PD2|_GWjId5LQ6q$ zikFe)3_BMW7c~Q)&{+;aR!%MsxDlMad-v|&xBnOc!7+{#6el?T@n_=&bZ8Hb0WJwH z4h^*95DxAkoQ(>I0>XiCAzaYitq<<5-8egT;_U(7iXMb;cHr*Zvt!RrJZQ&`9k>vL za|qlxOr+np>&Q`dE}OVaVk?ppobm>-Py2V{ac9x|arK(*%_p=Rbc*MdtZxl~Mo7VA zz@M!bfJQ(YyTDhc4}se_xI019&~9Ah7vQTyCk_*_%kRuQ@&^saE(NP6e>I)I`SI#T zC$t~@WXB=gLy!oR9>Xz=)^B$?m?r(X17G{;OFNF!6VLI{O4<*rs>9smSrv1iKOix0 zNQ`c7YiPd8A3*^Bgq+uJY}hvDF{|;gOuJ46Gm-X;{yZMzpz-H%AM0Gh{KMy$qoQ5? z;z&fRT5PUPd%Zav_nYr|oNJR4E}I}~d?s4jtG<8LDVkw)U!+s8U05c5#aovS!M|#p z$lO(K#v+r?#IK8(DW4DNFEaFkaqQPXgfS4 zpy_kMzI%M1s(|F3aebcPy{*+|J#2{)&F(iq|9I8GbjvuD1lLg{1|`m<(ABg>c1!N- zv9OzCy{An`EmQAZNPg~8fNL!nxH{+&=Zrq1J={qCvky#8^7e|0Fuh=x1CC;i zUseb?Y;0{~5@(W!F9D0n3@obc+=*fp?Bh9KEx0c}#wl88tzu#smq6}tO? z-fc3T+2RlF7fN%nlkpc}&qv8H_Icdt0dQ~lFM)d#ylYAP5bF~5Z&~eYx3G>N1Y^g^ zIyc=9y;iGKWaG7yJ~1wgm%8q&UMChzDq@s}y`8w^s{1NhAGoxae*%{#M?+p|fOP|+ zTQ2n2W9;zhuue5^%jJY|A0Ezr=R97 zNNrBPQ)A;zImvo|bpu*jmkub6v*f>^LnM^B`HI^nw>YG1v^i9jh59ekEHoaUrxyLKa*i0iY5_ztyn?&ygE zZ6S}=RV80Bub?X_&2N;e+xo*;(XO5WeDW;&_VXNNkT^tRuzoD4`N*6gnSj_IaSJ7s zTFSilC8Al)BzKlfCZ(Wrd%t+Lw=CJVUljjPd0Rr!WK|#4G1gcmJNa5)ZV7rRiL2s)D?ulGXmnNQd^DY(Xg}rBCo)cAq-*<&g6l!-O+!(- zbQbwaszsxS*b4^TN$F+ng@x{~{S|87WG#gHC;3&L8dQIn%0YU+UM>D*=E*&&hP%WT zD-R55uNx>)ht;w(HWToQAL&eN8`74}qH;Q@aZ#g*f0cq*=h@bYIlHy+XT9JqCiCLs3I zRsYlHQW+ndv=f)pO{XLlX^xR?Qu31_;8!v>qHn74rwQp zG`I9}LvpH1bCevF<%QOBT=)x#<3pHii4U9TORGKcGE0>RePW=daZ=1y;)!@2{)4eJ6*V!dsT&ZT?Xq)vTg#HPDV?zPqTp-U_C7TbN**bK1AFr?ctmrC zg75`Z=AAp1c5zEPdDd}#K56`#u=>94 zd4l?%4b_v=`aFRkbnPLP-hfg`4FV|i3u0IS+DQbEgtaRgUmMnXp(Du}^U(>FPm!Z-&5YI}fsrwZQ0cNFW&aaw*qzrSu?V8w<1zq|FU zv?l&|0x_Azq6jPL?5oj19o@A}V*r> z#`9bL=Zx;ZVPztA8Tz!HGGVez@2>SVh}u6H&@fQqxfU(Jg!;*GH;Pe3wNE6E<+_lx zoCq`N%1#wv&w%A7qIkZFaPk!os)6N~rh~n=yvyxp+oAPUuVKY&JMzh)b)HT@)AOo* z_o%`ooIuO}UN--UW%{qRP8`Xg^du>{G~b4mG1QDROF$sP`De9r9N~z1#qoT=K55Ws zU!;!>$XXu00J4^@wXq{x_Qnt>hGjz1&p@cY>_)%4bQN;(AVkSrL#!RS2TsM8h?~HU zy@~zJBx<6H`9IEYzEQBs;=8|mCI=JJS|p$Cps02UW+S#rSA#wUy!bZjyvyKXvZ%bG zA!6h0?Zr{VA!M-DMLBTvM;LT;P(G?uap!9vHDN5~uUvQ@-&tmFi!x=95faRvrO4&B zDz9f2p_s7cKGH*ZZBq>lJWTwInYlH!+zXF+`nj)oAJDW0^?_joN?;2(zdOo+P*C zcycTIIS^fqFz9SyVisBDDSc2%v?yX66Y>OYZ!7M$fA*zz*PAOPbgm5J?oDINeIklW zXv@m>#f6#PmZhHCyD+x`C3W|%#^kuO=4Zr}B~F#>-q)=9(mipC3Te&gi?*e%xQASq z^L~=28F$v?I)yOptrYf@2CT>AEgWORG~j$`MXq%%Zq}~EjdD%IJl#$~;E$;j z^M9-qDn^$!PoVNcqUmJg)oD^Hi+t|aWlb4}bbyW|VLBr1>fXRcCn%cjmB=S9BqW{r z=*PF>&f2=U6)rCdakcYQMON$(eB%x1-+kxZ2G}T1!ch?J`zK!et8JJ0Q%3VL*V?U4=T1MTF|M)NL++hZM7G8=( z*}s|F(K9-j#ldt&ynn)ZRbbV9Yq49JL_ghpHimBkPYn+#JT>EYr%1#ss)jocWmDLCo+hs^_M&cW_gB)`jN1a8#7{}zw8SgR>&KH%JF+tP|g}P|Z z%4>9TI`R@<%qgnfN2 zRipnJhhwSSa^>O&oB@|}pqXRX8qD9O+Y;NZ|8^>`@acfQ&57x&Mvki%W0Y~v3NOiszP=vPu?DbmnaMr}YBnK5D|xY!#`HXWE8 z|FM>2E;h_m&4txB0O-qD42i0{UdY>W3udg5z*>aAaC=t@g-d&M))Vu7&_zTmqSxfi zXTG%wEj#i0M^`@!tfISmzqJVodxnqX9%d*}i^1xQdCCTKhP#t*0oEB{A%V^`MW<~* zil;F~Qj|a_JjmQawOfih+wZkh0Q#8K?EvR6f!atR+7wmA*7uqP5&LU-B099A{r{CI zxmlcZy=F$waU_(}>>N(pjj!ts{)KlYJ}F3Oyy9a^htJXWA-9S%E)uS9mM-L7RbHkI zujy^p=odkeJV4Vprkp;XjB@6g!?~CJn*IgU`L!LqSg%Bd<|Az?r@Ljm48lyMlfVc@ z=WnT(;s1_-67}vMlePbBTi7u*gpyQDR*`_04OT%71AC7Jvr`^txZj_Uk?IR&8!l&U z|8q%Oo)VrSLU>9fl72QVKA{2p!7hAyQi?3Ds@*qlVQm9ufgD9hG~c$o|69Ay^sfvV z%fejCz^NX-fv_9U)jzQliRUN1?)_BcRm5kdPxfAGHsTvlFx&EpMao|)Q}%#|G@31V zZPv{Za_o77Z3BXK5O8A0pe^@vW9D*pF&LcHE;r4jp!RHqx#ru5&&oOsjw%m}n( zus$eUZ2Re$o@X?x2el&0&^Uw_JqAJ7eugNuAKb(#9}2)xA_7iIad>>yzYicd|B!rD zJuKRNXM$2Tey1{6{P>|TQ<({%Xcw}bvS!IS8?_aajaDO5k51Exan$A}h^criT*Elw zmPT!0mq%A4VY|$Paal>gE~C|F?HqX9qYDIYYhs2QOCq|b42%#(D z*?MG`++W~~T4QGNz#CY8`!QOECUaq@>FmyUUY~U|!N=@n>a_TA-`G~BP=`26`oNCL z!Nj`_94b~fpwX}EfHZ?s$7pg=&N&kg(T2sU$^JP7azE-SQm17#}oqst6ScNj=f*f^hck=dA}(M6fZ+#FD$1LmCG5P)YJ@FKKK`K;-VcG zd!WbcA!&Md?UBwUN1y(rT>SXx(XQ&<9E~TVAY2m&TDaUgu5msR_V9lq9-cU6ja(OF zf&Rh`bv|oi^U#t~I&)SNYnB!+uU|1OJRccW&Z1lIrJa6tvM^RaeLb-uP>et}{wZS$ zKrK=GVbmfIqn3s*+NYoU*Sjtcmkxf9f?EE9VG#P+-}!2GB@tkE?bZINL~34B-+y{>kZz>V09@fF8V^v6K62l)m`Wfp64vAhEiff@RF+XCM5n|Lt!Pc``;g zo8aEYD$>arwwUpa2c*^!7JX8t)wBT()~;2%IWBxDo1)V7Su=tJGp<0m#KH#kg0It- zPN;$M)sZ5&Xr=iUQw<6XVg=NOM8G)!nGw09K9doI2Z8V|;4}%p+#3?EdHM;qYs5a! zmb090Kb+%Q155yoY(O}0sc$G13kX`{$OxvMQe?!Ic`_u{BUE1pE+wNL_WFKWffkF8 zZ%Pz|Q3|Y4N1qjXDs1FDuw>=L*eJp>=*8rBIYqt4zxW2OwPas<9<+A5Nb6|O3U9&3DLhUln z%oVt&o1UmivBOiPebB8UPt+E|y30r=moq7y-GR?FPZUBp;{R!%T>wy1N6s^_p$ihbv0}<1io8@MEq@++gGq5stSx~QzL?7`VoD)2W)8g?HsCRYA$NOc)qSF);t#{ z^=74Ut@&s;mu+0zP#efrEsi!is_4r$1|R(}cp5#7#w7%Mnw@L>4V2p{T5u zZ^c6zs-4aeo4oJD9F9PQ<%HNm3p1#uhD>#)!FS7&EaE=6C; z5`zQA6L7%D3mQ>*xeO2kf+nu7r-p^pr_GoUdK}Y8} zPSfMBzdVy39^_Ut_;zUnx>c*ODDdcw!bIoA&+j9}pg#2|k0b+UcgXLZloay%=&l_{YZ%`=;xRM?Ybs3b{QP}7;0V3`Vk1FDS{ z7gttZNiXtYug^@)O+A&;XxjF?FL1^CRn3(3$Qs)kWpSC6Csu#XB2lX7D2?Wi4wefE zNiVXG)N;lg|H((&BLhA7J$!v-em|E>%8*#sns4W(pT;(0^&tBmgm>|V4ZffRdXc_u z11ei5Esz{a_AfoS!%g?|2J`{BN0dQ4H8ch>Apapi?oU*JJNr+~(zvunsjhE8D>nPR zV6?nUbgWiHHr#jviah@H=Y3~6-v+xCy9v%p7%7`u$XV^3@}VM@b3Qn}0rhS`1OqYo zf(u}lzI!X#L}fsa&V5Wr`YII2h&45XyZL7YoK9foC%F?gGh}H(R-exnKb)m{hk$^4 zR~o*Z8O)q0BKl8ObXqIaa86-*kw=`Eor>rH;rbKIk#4 z30*y4{Ye7WpTRtf?WO>tgX^DqNT&`~eOAhTjUtS>L8$p+OTeHhyd3X(LM`N-_c5_V z=o6*oIEwkX2Dv>9zUVrpynNc}q zY02D(_olPa!Sdz+9&CO79@o}+Bw5TIkyOdGAIWU6vi8I?cY?b_d8HQVVToToSCEH@i= zcQmDj^8Ac?5Ji+jqhTvkK)ahu<0G*Zi&mz{o&`%(#9|INw|&W5iiNBV=oP1xl7^>3 z!-DzX?qL1d5|&rU;FHlrFYT>k63obCf?q9U^UHlhwML!nfd zXs~+B<-*`UW@tm$C&f-PQ53QkYA6t%-`Uvgy9vT0>9X-N3MfiD>Of`TZW%$Rr=n($ z|KvR1qU8{}A%5-aaL>e5_{=DZXF2wSqRy-zF$%JKU%LUdMYLp)_9e$XTsvil3=0{d zF%q93tjpSh;4)Kc=|K)M0Gz|RrFGy`ayVSb;Lu8+%O)s3b<<@_#;e=gF6?^`gDs?7 zLXdKoq-ZPLAy+=gW)GL3#zf9(wbVtWmE2XKFY0+cOpx*r0(SQ-qRRfd8h3U~IJ&zJ?D`PnrzYma<1(H8J`g z)i>nK+4&|bn5!52AGf!+yQar87hZE0v*zURObdh;E@dy&-52opfcmNt>i1}| z$-~Z5|2T1+*({QvJg2voV(_DnVwsDY)fIuL^6zX862hrtHaw|oT_DJPH12W341=`+R4ZaYwK^dM6RgBaFch)yPlsW;tvw(pPZhMz zm4rS+XbCV=>ONA~db)-KD@_)xG&3#?;e2wma)34*lFAKO(8b*ogWAUmsf44V2yJ<8 zgiw4617JM+o#!=FPqo4nOt-Sc5XKUOFBAbLbTptS7g^ZtN{vQH(+C&%SJHDpvASg$ z(1wA-KM6bhPe<*32^&t)U3;-hADK*?3W<*?E^oXMS(n|%kzLM9>iQUQHdMZQ37#6O zw2!^o<|xqwON>l8mQ?tdp20fqwp%A1m4!x~ z`tQF15eRyq*%nS5B&?y;u zPN)zEhnNAu3u}M|0OCl`t00a(fR zffo_($F;8QOJ4@hQ-S=7=k;&F*rpkMU$hdik9<^y|FW0b4bm+L39qc|isGNBg) zW@^dQv_%QrjA@n91}3XOD+gxw(_OQiFg7i@qKu2Lsa zI%G{~CTRi!6ZV}-OIMY13#hH?Hr+KB=8M`#YQut;VKk=TsLv&lm(TWG6q}YL+CRUr zU@RGS92#8M6xwr=G~Y0`Z)X3@|3RqR$UYf=OM)%%h1@`#^I1vSbAUe$1Fi=EaMccL zA3?U(Ae)8G^@!E|OciKo>f?`~fS(Ss&x}CxIc@>MaAeyLj0-N9-uaO`gth#?CX?@; zy#z5I$4(lK5Y_@6miUG>{@85fC!$0H24zseJB}hy_li^zXo>U(86C2Ni2J4F_lb0l z(I;CSJ@+f(&2^fT_P zuy?mjqbh|+E^m zKZI1yK|7quqUDgplMS4BiVgwk>w`Pgi#z?}9R}8{ZzaHK>Px=bsmmxaI9v6K0*^iJ zNn#w!OY@@ohZ9--(1AdyG$iyyWg%rN&b%;h0^KtZrPevHnz-Q#tswT-!z9R#hhk&1 ztHfeS$}BS%dt_jfAb04V(_Gz1^_Ct}UDI&tEKy2sH`jg@l%1VbP}n`Uy7Om2+}(bq zuz(=#FFR|&wPJMXFjWf@e;n_uBT+rh&mlWZ)k*rB8_KT!CpO_xV%>Fu0@m&5Y*_-v zGUEAiK@b=G&7x6F6zgg~}Q|`;4b=-Dz7F++R9oSE(muO&w zuCOKMEy&C+L3mA=EXCm!cy6>FaS2|A#GkZd1gry*8PYDPa<7bV=)kk%VB|PRu7=_~ zrjVnhwk{xtYOgbVrxE!>Ep>+;%iIGqh#(0(ggdJI%V2;pFzDMHB5kjxHFj6aua!yE zF%64|R5#N!HQ1doshc63`jCk7PZEI}F5iD)ISD~#!Pt=Ym37U<%vZfTH$!Tikpj)3 zvGCUw)*n6`Ro%akmo)$#Bkky=NYH^GBy@vzmQp-ouf46M`oONw{yN051jhE=C#*d9 z#Pz*4_UQ7>!^{zD-`?k$I^vM%I-t7kC7*>0i)EvX2`?)=8K*0 zTPO^LA;|b|rXN%8z+ms!U(->1Lqm^>i_d|29nvUa?9UX-uottXUNw|kj!74a5@Y#+ z`l`1%s|#rJErcv}7D>q>4P!2t*-R#`gLCmhcg|EBfjYjf6??g0{Kp030sTSfm@S0E z=FPC*`omk|!DvVAM?l?fAP?ib{_Azpys3xLhuypF9jX{XwV4dtw2%f*ULS&CSx`r&M?4Q(k2x)B5*@}FbAyN z#0vB78o>JV0+g;CeS!htG^JSPAcEsSzK24}H7U|V&t9><&Z156Oko<@Gl_jS<}Yh? z3U2GH*A!==sKSAJRWBd{h~h#z$m~EErT~XgVlk+&CKlhB@#1lE%H;_C2ptHx0#X8) zn(AMOavYTUF^!BZ$i5Q%WN0%8QDO(|cJw!Q$D(;l|M~vde`GUpk+kaBAN51-^niaU z5k$z@3eOM4BZ|mCp8TZ%Xt&ON%!Ca!;27u$(rdkCz+=E=I8As2Iy8#;W*=L5liC-l z*jQAyI-TYQH0}K$AO@yK=U!U{1S(EIv?TYZTp?F#wha-cwHUS~V(I40kw{y*XMpCs zS7w^q<+v(*za`S^UP@Y9`uLn))U_^+EZ?-L@$PFm4#OGu#`tAOKIHRHjxx^JrK+3; zSqe3Al)Wum&ZM0J4u8(xx zYilcIp3%MQvA^4$tT{WkNY&OR)-=!lrfQGtⅇ-UxsI8h}7f0?3mC9qVTJ?Zi~8{ z#@c?UW0{(l&6HA@-Cr-d#`4@T;0;6$HRss!hB?=*oa{nno1BEJiaLVN_@s*kAFm1r ze@Xs0MXatppcya~%_!S865cB!e>GONA;)t=moX^l4pR8JI8X;)%1N=0` z3$`Mm`(AORZi1%m!U6%(im!r*|2rH023;n8cQfJFicZ9(A3|^`!Nl=W7`yL5#s^<8 z!YAY%fJ7eU0U2R#Y)2r9=o|2N!8g>kxUKSPp<_fSE$awJ2Emob_1ey9b%H{bcmnWTKtW9I=E_y@^T0-^?NWqcUv!)pD#tCwwlZ+txF_9`N35Wn^$+*%3e)|>$Ol{Z?@~9jZHmeF})aZ z=yksFWT&S*u-U>^qrLsTa?8}>&9=gnv8l`%Y~03&8Zr&i)jgF#30>G~jJ8iieko?3 z_&iTZ*@}tB%1BdLWogVbRe&%vs32KYVStbg=6BKg8_*$OL>|_XI%Nnsd?1h$Z*6mo zE{c$s&c5DI4T^B9$FhyJS3YYsEph?A*{Tx4$Yl~xUr%6Jc2%F_DcOKTz`iL@*y8{! zZf*k##9f(gfHxV@(RQe74IQN))qWq>0n_h;s_qbswp4w(3IMZ}cmJes+EUq*p%{UI zuAJJnj5Yd6HE0orHhW!h8f5o5UT;}<9fbBQfLcGInxer7RzJjchh5GQ0B|{{J$MOv z4BnwbmiHlJ#CjrXc_0y~Z(jP>r7zsk?4Ndi7*U zui0-U;Pv1FO_dE1C_Z5eGuR|OT#UKWjQqYs&{B%MyJ8A87WGX*Ct#StR783bfeD_) zBA#R?wH*N9Su~V^!#otrTv&M?npCpp+xkR#!tWF>M&Pl(RJWI>AnD=*OfD<9L4({{ z@%@=$cGv<3QaGW^OF90vSaQZ(>0HTHoOz`)>6@y_U%B!WVVF9J4JeOfJvT8P3RS3n zvTJ&4>kw_}@AM6RZ#Yj1ZP!-hBMi#{3%7vn)}>Xhnwk9} zly2{bQ}G)zjnmZ^LDil?uab8Db_J?7_9Ju2wUfb?nt*u~o#wn8vKXnV`6MZ!Akz(S z%fMC;&TLW>p}jC+a^mQ;VL3;=m%S>=CculY&)*+Kue^}5#*k_>9a24VbYMdQF@rvg>(rG1=Y7T0!g zN|n212lz0cHo30pC$t4B?TZuIQkp#?5u4z86sZO}w{+y<$K?j<%#VCCm7HGavsS*g z*abid!1XD!tjXB3*FK}zfmk!sIT z8@7#iW|W)+6nNog{F$oNVGIGbIX28>t)mH0a~7GlGA9v(F?a*Dptd=)mU!t~!CPYe zX>q%dsu?T|*(jD_mko#-pX8e{&`%BAse1Ws8{E0_JC?W9^0rAVKSDa$fZ%%-x?X5v z8B1r6#bG)r*1E@BQE;sb(YXZ&cBdlsRl~oYB8mi;z4QuvIvZPfzR^?4x?gH(!w<2T zuIP$FokZdEkcUA8m#){;`Q-GOi%U)sg~1D9QXtmwj0`izrBlN6e^O{aYuQZ)?ndR%3pB zEbrr8%tlyZ^y5S7Si(Hdjh&U)V|h2}%}~7g9xO3>2lHkY;SCi2!?CtEj-)@qK6yiI zbK7JmM0AAsdluA=kQ^+7{qmkPEE$^o+>Rdub4VfY4)#eL;!R4p5hQ&Xd;Tu=);WBY zH`pzh=V-E&u*dpBdw)DA80S*wLClkTi!X!|A=3~?R#gzw6Mcw|mWirW}5l z7aBc5hxr|s$Yq61%B&qR7K{qwK@uf;ItnM5J}rFx^pDttX14#{4nhiV7=`DuZDl`j zP2=Lr+f^w`9jzRvu)pjG6k4Kv5;aTC9%bY#xbvidVcKd_7M6|%4i1Q)NMP4q a=YIBl#tQ4;rDuSF$>8bg=d#Wzp$P!L=zn7X literal 0 HcmV?d00001 diff --git a/res/backgrounds/foreground.png b/res/backgrounds/foreground.png new file mode 100755 index 0000000000000000000000000000000000000000..90907c6718719f2e8eb3d7bcdf727f574e2846b4 GIT binary patch literal 512 zcmeAS@N?(olHy`uVBq!ia0vp^DImW;uunK>+PLbKW0N7*N1w| z?$a1%C;Yc&`q(zX!C2OOXW9PGxAv>3Z=39M<#w*(dinSB)9=@RGZx(+{ns}1?+v{r zSq9qd$vso5r9&=GJaur#C)+}&vND$`BHSxGCTUK7JHMP3MVfks_;+Lzd+=Pn^y;h|P6ghf$ty5nTSYp#VLC?r-?WQm;&zUXJWv{}g z?_Ih3(>14{vJEXQvYG-yVQ++99}iR9oqqnZ_!lnC*p@9_ecHSVDmq?j@-w&WVS3VH z9^#cXrDxa9iY<=)0-JtI1-?Fg&9gs>lk@Cf&+tf2&fTV#N&cI5^GJS;6I7>rGXa$_%&Cf1W_`%Wz|gRf8^mX*v14ZVA`9fd1#?k}39MTG1=Rn! R8C(O2d%F6$taD0e0s#4JAe8_B literal 0 HcmV?d00001 diff --git a/res/backgrounds/scenery-demo.png b/res/backgrounds/scenery-demo.png new file mode 100755 index 0000000000000000000000000000000000000000..332d65fd78beb0a7e2e15a882a222ffa22944971 GIT binary patch literal 1197 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 Bo238% literal 0 HcmV?d00001 diff --git a/res/sounds/effects/splat.mp3 b/res/sounds/effects/splat.mp3 new file mode 100755 index 0000000000000000000000000000000000000000..8a6d44a2807ad181cf616c1f0007681cc6c365b1 GIT binary patch literal 17389 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 f#iM`F`iED=L-FBI81Z2E{`R|eTi68 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 literal 0 HcmV?d00001 diff --git a/res/spritesheets/hud/asdf.png b/res/spritesheets/hud/asdf.png new file mode 100755 index 0000000000000000000000000000000000000000..ab103130e9d1cd659134a62dfda820d95f4e72e6 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^3xJrNgAGXbUvsMlQi+}}jv*Ddk|!7#{IKtG|LBm& zCb02c$6*aMCi@>BnEaHJ10?byXR#hr*tWD)O`^X`SWMoxAw|t0W#dH_(^(Acdst+S zE)Mq2C<0|l2P zadL1)2uMdC=)8ZDJ%){IRfi_+2T+9rH4<9qUeKp4uXeEQEtDnm{ Hr-UW|=i@Xe literal 0 HcmV?d00001 diff --git a/res/spritesheets/mobs/scraveller.png b/res/spritesheets/mobs/scraveller.png new file mode 100755 index 0000000000000000000000000000000000000000..4d7b827c392d9b9685a89b592e945edeed27e7a8 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^AT|pJ8<5;?vF;*Nw@FFaW_5`%A*|0Pm zVDFHJRuoI?=XIF4T8Dyyrhaa@0JA@qB7Swrb2tsB;Y3S%91~rKprzG>M}KrU(o0T^ z2}Zvs{4lg+O)&bN@Wauv2QMu@@U!8&413@4u$b_?<0000lizC2>Gk>e z{ku&Imc%lV%ZsyVQs`Vt1e>2VU(7+Dr4{-|Fx-)lPD@T%L@@a+=0mLXQT@ZxK?ahW zF<{D7)+FS|Sf%p%^OqL=lFzWe6tvF{Bf_6tsl0P5V`(+GRA*+hNZoJQnVCKsLtRT} zti~L7^x)A2cfnn78^uE{xM%ZQ=A&k5E59-mV)6qbm|}xwX)C`n0<`(9#fF-tEnLhB zVDbYInfqy$X86@wT`_#@7c*5@8i|0b z@oW3gj$nvI3$bV+7Oi7hbRQv;j~!#?e^|q!|7{T92BKw-#hzgei{=`{78{^A;A<#& z7=|g9;6vi&<0}4MI>w?o23e{x%msZyqaYXov1lO{tz%g<$Dp}lLsM{oz2~m`V(EXl zCQHk8-%Jz)F{6-EuE$IXm-NA&!!_Qzbkb@imX^6|K^QhQ0SwuoWYcO^aFHcl8!h*V zu0_yNE5ee$v^g%9oEQ;I{v7iu!3;UEBAEOZ^G(k%gO)jXsd>TAnr{+p{l-Hh!t#v= oV}3Sx9NIS?9WA@yF1Y>J0XK~Q? zawF-C8>U=kO+tR$t5n`_{?cMx@)-`7g7(>AM1+$om3L}o%&i8O8q91Kss5IonHi%o z)U|ZRYRqv*4<21`7u*H6Q9RUwdp5siK5CY>@+&hTCO;s8DK==9w(=_@K%3uMY^Yh< z!o{orCO;67=})sX!>`uris9q1n5n|jNX*7TJFal!HLM&RxvS^M$Q^kg+-~fA1T@S_5 z|8Px~mg}LJCdl7$0000JG~Q znMgWg!j!A5Nyv}6O63jLFD=F;pW$#TXrCQMM7X$8d8c;9+-`8G!OUTi>TfxjnK2qe zT}$s+jXCbXO31-NN6~W}Um~VQ98MMs7OU)nrtobIv)^9vCA}rr{ oFy?22$Dw`W(b2LC?tluRsaA1 literal 0 HcmV?d00001 diff --git a/res/spritesheets/player/Player5.png b/res/spritesheets/player/Player5.png new file mode 100755 index 0000000000000000000000000000000000000000..5023184bc2b91cf0aaf381a29be628d9b0c9f8a2 GIT binary patch literal 955 zcmV;s14R6ZP)Nw1l1=+I6-hx+3E%e(hW?rNLd2M;dI z?|t{a-@Ux|{jRTzK!gs$1?M03%USG~vq&Wqq1;gLZ{+4e;rD|}@K&u4qxaG*5{?ML z|M|;NpuAQL#YeGc9(aCd6D){_dXACZEY&;vK~)5opOYK_^_h88BfMIA>K#NN5^X&< zOM~$ds+a~udTy5TdV$8rhN(XmBLdN2e57HlDnEx;w7g!R{#cC0 z$A%m7c3Z_C4#bguaB}^9;~B0^-^S(MOTL+Xvb+TS<0b$gwUmIq_yOp3$KATW3jBS_ z#hoI?Z}dp{Re7z*%unEOAPxZ7GY{PS&I~LhXKY!PWz-s1F%8P=1!*7acX_=K7_ZmN zXfzvKf*TD`^=3ixar>wwR4VwqHI?La5va3`N4p~u-0p}3hi&e;{LPF<*-Hb>`B%<> zIQ$#AId-w(=cQXN9=HOy{G9l$S|75TB@Fc(Bg(H*jxX%7}4^2LAs4O z$Lfp~VqJo($aMpYB@vIaz=Si6)sNL zR~5m|vAo-!tY5npt<3xc9>09yxfnR1WY#_UaH_H5P7wg`>*yj9Q==$-D@o&1$pqFu z73=>STic#O>QN1A+fye2UQe#;GrcXf>b<>M1E`2-hCk@!*aSD@oH!yl{H-Kk2G^qHdt|@?mxvYl4ORKM zysEH0;k%R5_3OzyHccpxy<0@u{BiQ1$hJSj+Qv#v`(p9_To0 d83}H8`~ibZ8vbde`G)`i002ovPDHLkV1o7M)2RRe literal 0 HcmV?d00001 diff --git a/res/spritesheets/player/default_gun.png b/res/spritesheets/player/default_gun.png new file mode 100755 index 0000000000000000000000000000000000000000..d6dcdd0ebea78e96bd77339ced5c987863027558 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^=0MEK!3HEBW|lkvQY^(zo*^7SP{WbZ0p$C6x;Tbd z^d|o}|KY#=+K*qwgER8j&CVEv$awLk?fI8<>i_HVYX%^|a_ddH0?Re|!XpBQm-5e! ua;p09Qr(TeYu`heVwLJX8Jhq`CI*w~OD1~q?QsE`%;4$j=d#Wzp$P!-U@>I? literal 0 HcmV?d00001 diff --git a/res/spritesheets/tiles/tile.png b/res/spritesheets/tiles/tile.png new file mode 100755 index 0000000000000000000000000000000000000000..fd18a526b201f9bbb79589586695adbdfebd13f4 GIT binary patch literal 89 zcmeAS@N?(olHy`uVBq!ia0vp^Y#_`5A|IT2?*XI~JY5_^DsCmO(DV7#&uiSk;mz$U l(xb!}?74>}Z1ILfhPCUxQdy?l%m=Dv@O1TaS?83{1OSb(7w!N6 literal 0 HcmV?d00001 diff --git a/src/core/Console.java b/src/core/Console.java new file mode 100755 index 0000000..327782f --- /dev/null +++ b/src/core/Console.java @@ -0,0 +1,16 @@ +package core; + +import sjgs.core.DeveloperConsole; +import sjgs.core.Engine; + +public class Console extends DeveloperConsole { + + public Console(final Engine engine) { super(engine); } + + @Override + protected void commands(final String action, final String item, final String value) { + + } + + +} diff --git a/src/core/Main.java b/src/core/Main.java new file mode 100755 index 0000000..8eecdeb --- /dev/null +++ b/src/core/Main.java @@ -0,0 +1,62 @@ +package core; + +import static sjgs.utils.Utils.pythagoras; +import java.awt.Graphics2D; +import core.input.KeyInput; +import core.input.MouseInput; +import jython.Jython; +import player.Player; +import sjgs.core.Camera; +import sjgs.core.DeveloperConsole; +import sjgs.core.Engine; +import sjgs.core.Handler; +import sjgs.physics.Physics; +import textures.TextureLoader; +import worldgen.WorldGenerator; + +public final class Main extends Engine { + + public Main(int WIDTH, int HEIGHT, String title) { + super(WIDTH, HEIGHT, title); + } + + public static final int TILE_SIZE = 6; + public static final float TILE_DIAGONAL = pythagoras(TILE_SIZE, TILE_SIZE); + public static final double SCALE_FACTOR = 8d; + public static final float GRAVITY = 0.25f, TERIMNAL_VELOCITY = 2f, FRICTION = 0.1175f; + + public static Main engine; + public static Camera camera; + public static Player player; + + public static void main(final String[] args) { + engine = new Main(1280, 720, "Forlorn Hope"); + } + + @Override + protected void init() { + new Jython().init(); + camera = new Camera(this); + new MouseInput(this); + Physics.init(GRAVITY, TERIMNAL_VELOCITY, FRICTION); + setScaleFactor(SCALE_FACTOR); + new Console(this); + TextureLoader.getTextures(); + WorldGenerator.generateWorld(); + } + + @Override + protected void render(final Graphics2D g2d) { + WorldGenerator.currentBackground.render(g2d, camera, getScaleFactor()); + Handler.render(g2d, camera, getScaleFactor()); + } + + @Override + protected void tick() { + if(DeveloperConsole.CONSOLE_OPEN) return; + camera.tick(player.getCenter(), getScaleFactor()); + Handler.tick(camera, getScaleFactor()); + KeyInput.tick(player); + } + +} diff --git a/src/core/input/KeyInput.java b/src/core/input/KeyInput.java new file mode 100755 index 0000000..d97f4ba --- /dev/null +++ b/src/core/input/KeyInput.java @@ -0,0 +1,34 @@ +package core.input; + +import static sjgs.utils.Utils.exit; +import player.Player; +import player.gun.PlayerGun; +import sjgs.core.input.Keyboard; +import sjgs.enums.Facing; +import worldgen.WorldGenerator; + +public class KeyInput implements Keyboard { + + public static void tick(final Player player) { + + if(Keyboard.D()) { if(!player.getProne()) player.setVelX(Player.WALKING_SPEED); player.setFacing(Facing.RIGHT); } + else if(Keyboard.A()) { if(!player.getProne()) player.setVelX(-Player.WALKING_SPEED); player.setFacing(Facing.LEFT); } + + if(Keyboard.S()) { + player.setProne(true); + player.setLookingUp(false); + } else player.setProne(false); + + if(Keyboard.W()) { player.setLookingUp(true); player.setProne(false); } + else player.setLookingUp(false); + + if(Keyboard.SPACE() && !player.getJumping() && !player.getFalling() && player.getVelY() >= 0) { player.jump(); } + + if(Keyboard.F()) PlayerGun.shoot(player); + + if(Keyboard.R()) WorldGenerator.generateWorld(); + if(Keyboard.Q()) exit(); + + } + +} diff --git a/src/core/input/MouseInput.java b/src/core/input/MouseInput.java new file mode 100755 index 0000000..e4fcec1 --- /dev/null +++ b/src/core/input/MouseInput.java @@ -0,0 +1,38 @@ +package core.input; + +import java.awt.event.MouseEvent; +import java.awt.event.MouseWheelEvent; +import core.Main; +import player.gun.PlayerGun; +import sjgs.core.Engine; +import sjgs.core.input.Mouse; + +public class MouseInput extends Mouse { + + private final Engine engine; + + public MouseInput(final Engine engine) { super(engine); this.engine = engine; } + + @Override + public void mouseClicked(final MouseEvent e) { + Main.player.setHealth(Main.player.getHealth() - 1); + } + + @Override + public void mouseMoved(final MouseEvent e) {} + + @Override + public void mousePressed(final MouseEvent e) { + if(e.getButton() == 1) PlayerGun.shoot(Main.player); + } + + @Override + public void mouseReleased(final MouseEvent e) {} + + @Override + public void mouseWheelMoved(final MouseWheelEvent e) { + // engine.setScaleFactor(engine.getScaleFactor() + -e.getPreciseWheelRotation() / 5f); + // engine.setScaleFactor(clamp(engine.getScaleFactor(), 0.1f, 15f)); + } + +} diff --git a/src/jython/Jython.java b/src/jython/Jython.java new file mode 100755 index 0000000..63f6f28 --- /dev/null +++ b/src/jython/Jython.java @@ -0,0 +1,40 @@ +package jython; + +import static sjgs.core.jython.Jython.pi; +import static sjgs.utils.Utils.readTextFileAsString; +import mobs.scraveller.Scraveller; +import player.Player; +import player.gun.PlayerGun; + +public class Jython { + + public void init() { + imports(); + loadMethodsIntoInterpretor(); + createPyFuncs(); + } + + // IMPORTS ALL NECESSARY JAVA CLASSES FOR INTERP + private static void imports() { + pi.exec(readTextFileAsString("/jython/forlorn_hope_jython_imports.py")); + } + + // RUNS THE MODULES THROUGH THE INTERP TO LOAD THE NAMES OF FUNCS + private static void loadMethodsIntoInterpretor() { + // Player scripts + pi.exec(readTextFileAsString("/player/gun/player_gun.py")); + pi.exec(readTextFileAsString("/player/player_animations.py")); + // MOB AI + pi.exec(readTextFileAsString("/mobs/scraveller/scraveller_ai.py")); + } + + private static void createPyFuncs() { + // PlayerScripts + PlayerGun.initPyFuncs(); + Player.createPyFuncs(); + // MOBS + Scraveller.createPyFuncs(); + } + + +} diff --git a/src/jython/forlorn_hope_jython_imports.py b/src/jython/forlorn_hope_jython_imports.py new file mode 100755 index 0000000..0388305 --- /dev/null +++ b/src/jython/forlorn_hope_jython_imports.py @@ -0,0 +1,31 @@ +from core.input import MouseInput +from core import Main + +from ui.inventory.ItemIDs import * + +from player import Player +from player.gun.PlayerBulletDamages import * +from textures.player import PlayerTextures + +from player.gun.bullets import PlayerBullet +from player.gun.bullets import DefaultBullet +from player.gun import PlayerGun + +from tiles import Tile + +from worldgen import WorldGenerator + +### MOBS +import mobs.MobDamages +import mobs.MobHealths +import mobs.MobSpeeds +from mobs.MobDamages import * +from mobs.MobHealths import * +from mobs.MobSpeeds import * + +from mobs.scraveller import Scraveller + + +## IMPORT JMP3 +from jmp3 import MP3Player +from jmp3 import AdvancedMP3Player diff --git a/src/mobs/MobDamages.java b/src/mobs/MobDamages.java new file mode 100755 index 0000000..2008a18 --- /dev/null +++ b/src/mobs/MobDamages.java @@ -0,0 +1,8 @@ +package mobs; + +public interface MobDamages { + + public static final float SCRAVELLER_DAMAGE = 5; + + +} diff --git a/src/mobs/MobHealths.java b/src/mobs/MobHealths.java new file mode 100755 index 0000000..0f28458 --- /dev/null +++ b/src/mobs/MobHealths.java @@ -0,0 +1,9 @@ +package mobs; + +public interface MobHealths { + + + public static final int SCRAVELLER_HEALTH = 6; + + +} diff --git a/src/mobs/MobSpeeds.java b/src/mobs/MobSpeeds.java new file mode 100755 index 0000000..52100ff --- /dev/null +++ b/src/mobs/MobSpeeds.java @@ -0,0 +1,7 @@ +package mobs; + +public interface MobSpeeds { + + public static final float SCRAVELLER_SPEED = 0.175f; + +} diff --git a/src/mobs/scraveller/Scraveller.java b/src/mobs/scraveller/Scraveller.java new file mode 100755 index 0000000..8e7d488 --- /dev/null +++ b/src/mobs/scraveller/Scraveller.java @@ -0,0 +1,108 @@ +package mobs.scraveller; + +import static sjgs.core.jython.Jython.pi; +import static sjgs.utils.pyutils.PyUtils.java2py; +import java.awt.Graphics2D; +import org.python.core.PyBoolean; +import org.python.core.PyFloat; +import org.python.core.PyFunction; +import org.python.core.PyObject; +import core.Main; +import jmp3.MP3Player; +import mobs.MobDamages; +import mobs.MobHealths; +import mobs.MobSpeeds; +import sjgs.base_objects.Bullet; +import sjgs.base_objects.Mob; +import sjgs.graphics.Animation; +import sjgs.utils.data_structures.Stack; +import sjgs.utils.data_structures.shapes.Rectangle; +import textures.mobs.ScravellerTextures; + +public class Scraveller extends Mob { + + /******* SOUNDS ************************************/ + public static final String deathSound = "/splat.mp3", walkSound = "???"; + /***************************************************/ + + private static PyFloat speed = new PyFloat(MobSpeeds.SCRAVELLER_SPEED); + + public static final int WIDTH = 4, HEIGHT = 4; + public Rectangle territory; + private final PyObject _territory; + public int pointsIndex; + public boolean clockWise; + + /** @hitBullets: all the bullets that have already hit the mob as to not + * calc damage on them every tick if they are in the stack */ + public final Stack hitBullets; + + public Scraveller(final Rectangle territory, final boolean clockWise) { + super(territory.pos.x, territory.pos.y - HEIGHT, WIDTH, HEIGHT); + self = java2py(this); + move = ScravellerTextures.move.clone(); + moveFlipped = ScravellerTextures.moveFlipped.clone(); + rotatedRight = ScravellerTextures.rotatedRight; + rotatedLeft = ScravellerTextures.rotatedLeft; + this.territory = territory; + this.clockWise = clockWise; + health = MobHealths.SCRAVELLER_HEALTH; + damage = MobDamages.SCRAVELLER_DAMAGE; + hitBullets = new Stack(); + _territory = java2py(territory); + } + + @Override + protected void init() { } + + @Override + public void tick() { + ai.__call__(self, _territory, speed, new PyBoolean(clockWise)); + scravellerCollision.__call__(self); + updatePosition(); + runAnimations.__call__(self); + checkIfAlive(); + } + + @Override + public void render(final Graphics2D g2d) { + final float vx = getVelX(); + final float vy = getVelY(); + if(clockWise) { + if(vx < 0) moveFlipped.drawAnimation(g2d, getBounds()); + else if(vx > 0) move.drawAnimation(g2d, getBounds()); + else if(vy > 0) rotatedRight.drawAnimation(g2d, getBounds()); + else if(vy < 0) rotatedLeft.drawAnimation(g2d, getBounds()); + } else { + if(vx < 0) move.drawAnimation(g2d, getBounds()); + else if(vx > 0) moveFlipped.drawAnimation(g2d, getBounds()); + else if(vy > 0) rotatedLeft.drawAnimation(g2d, getBounds()); + else if(vy < 0) rotatedRight.drawAnimation(g2d, getBounds()); + } + // g2d.setColor(red); + // territory.draw(g2d); + } + + @Override + protected void destroy() { + hitBullets.clear(); + removeFromHandler(); + final float distance = getCenter().distance(Main.player.getCenter()); + final float gain = -(distance / Main.TILE_DIAGONAL)*3; + if (gain > -65) MP3Player.play(deathSound); + } + + // --------------------------------- ANIMATIONS ------------------------------------------------------------------------------------------------- // + public final Animation move, moveFlipped, rotatedRight, rotatedLeft; + // ------------------------------------ PYTHON -------------------------------------------------------------------------------------------------- // + private static PyFunction ai, runAnimations, scravellerCollision; private final PyObject self; + public static void createPyFuncs() { + ai = pi.get("mob_travel_around_rectangle_ai", PyFunction.class); + runAnimations = pi.get("scraveller_run_animations", PyFunction.class); + scravellerCollision = pi.get("scraveller_collision", PyFunction.class); + } + + public void reverseDirection() { clockWise = !clockWise; } + public void setClockwise(final boolean clockWise) { this.clockWise = clockWise; } + +} diff --git a/src/mobs/scraveller/scraveller_ai.py b/src/mobs/scraveller/scraveller_ai.py new file mode 100755 index 0000000..c99faf7 --- /dev/null +++ b/src/mobs/scraveller/scraveller_ai.py @@ -0,0 +1,42 @@ +def scraveller_collision(s): + response = s.getCollidedObjects() + + bullets = response.collided_bullets; + + for b in bullets: + if not s.hitBullets.contains(b): + s.hitBullets.add(b) + + # IF IS A PLAYER BULLET + if isinstance(b, PlayerBullet): + # IF IS THE DEFAULT BULLET + if isinstance(b, DefaultBullet): + s.setHealth(s.getHealth() - DEFAULT_GUN_DAMAGE) + + players = response.collided_players; + + + bullets.clear() + players.clear() + response.discard() + +#def scraveller_walk_sound(s): + #d = s.getCenter().distance(Main.player.getCenter()) + #gain = -(d / Main.TILE_DIAGONAL)*3 + #if gain < -60: return + #SoundPlayer.play(s.walkSound, gain) + +def scraveller_run_animations(s): + vx = s.getVelX() + vy = s.getVelY() + if s.clockWise: + if vx < 0: s.moveFlipped.runAnimation() + elif vx > 0: s.move.runAnimation() + elif vy > 0: s.rotatedRight.runAnimation() + elif vy < 0: s.rotatedLeft.runAnimation() + else: + if vx < 0: s.move.runAnimation() + elif vx > 0: s.moveFlipped.runAnimation() + elif vy > 0: s.rotatedLeft.runAnimation() + elif vy < 0: s.rotatedRight.runAnimation() + \ No newline at end of file diff --git a/src/player/Player.java b/src/player/Player.java new file mode 100755 index 0000000..edf2c5b --- /dev/null +++ b/src/player/Player.java @@ -0,0 +1,62 @@ +package player; + +import static sjgs.core.jython.Jython.pi; +import static sjgs.utils.pyutils.PyUtils.java2py; +import java.awt.Graphics2D; +import org.python.core.PyFunction; +import org.python.core.PyObject; +import core.Main; +import jmp3.MP3Player; +import sjgs.base_objects.PlayerBase; +import sjgs.physics.structs.CollisionResponse; + +public class Player extends PlayerBase { + + public static final float WALKING_SPEED = Main.TILE_SIZE/6, JUMPING_SPEED = -Main.TILE_SIZE/2; + public static final float WIDTH = Main.TILE_SIZE, HEIGHT = Main.TILE_SIZE; + + private boolean prone, lookingUp; + private final PyObject self; + private final int playerMaxHealth; + + public Player(final float x, final float y) { + super(x, y, WIDTH, HEIGHT); + self = java2py(this); + playerMaxHealth = 7; + setHealth(playerMaxHealth); + } + + @Override + protected void init() {} + + @Override + public void tick() { + final CollisionResponse response = applyPhysics(); + response.discard(); + manageJumping(); + runAnimations.__call__(self); + } + + @Override + public void render(final Graphics2D g2d) { PlayerRenderer.render(this, g2d); } + + @Override + protected void destroy() { removeFromHandler(); } + + // ------------------------- GETTERS AND SETTERS ------------------------------------------------------------------------------// + public boolean getProne() { return prone; } + public boolean getLookingUp() { return lookingUp; } + public void setProne(final boolean prone) { this.prone = prone; } + public void setLookingUp(final boolean lookingUp) { this.lookingUp = lookingUp; } + public PyObject getSelf() { return self; } + // ------------------------ END GETTERS AND SETTERS ---------------------------------------------------------------------------// + + public void jump() { + setVelY(Player.JUMPING_SPEED); setJumping(true); + MP3Player.play("/jump_sound.mp3"); + } + public float getPlayerMaxHealth() { return playerMaxHealth; } + + private static PyFunction runAnimations; + public static void createPyFuncs() { runAnimations = pi.get("run_player_animations", PyFunction.class); } +} diff --git a/src/player/PlayerRenderer.java b/src/player/PlayerRenderer.java new file mode 100755 index 0000000..5cbd5a0 --- /dev/null +++ b/src/player/PlayerRenderer.java @@ -0,0 +1,177 @@ +package player; + +import static textures.player.PlayerTextures.*; +import java.awt.Graphics2D; + +class PlayerRenderer { + + private static final float _white = 0.70f, + _gray = 0.50f, + _pale_green = 0.30f, + _green = 0.10f; + + private final static int offset = 2; // NOTE YOU DO NEED THIS! + + static void render(final Player player, final Graphics2D g2d) { + + final boolean right = player.facingRight(); + final boolean lookingUp = player.getLookingUp(); + final boolean jumping = player.getJumping(); + final boolean falling = player.getFalling(); + final boolean prone = player.getProne(); + final boolean stopped = player.stopped(); + final boolean white = player.getHealth() >= player.getPlayerMaxHealth() * _white; + final boolean gray = player.getHealth() >= player.getPlayerMaxHealth() * _gray; + final boolean pale_green = player.getHealth() >= player.getPlayerMaxHealth() * _pale_green; + final boolean green = player.getHealth() >= player.getPlayerMaxHealth() * _green; + final int x = (int)player.getX(); + final int y = (int)player.getY(); + + + + if(white) { + if(prone) { + if(falling || jumping) g2d.drawImage(right ? playerLookingDownRight : playerLookingDownLeft, x - offset, y - offset, null); + else g2d.drawImage(right ? playerProneRight : playerProneLeft, x - offset, y - offset, null); + } else if(!lookingUp) { + if(falling) g2d.drawImage(right ? playerFallingRight : playerFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? playerJumpingRight : playerJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) playerIdleRight.drawAnimation(g2d, x - offset, y - offset); + else playerIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) playerWalkRight.drawAnimation(g2d, x - offset, y - offset); + else playerWalkLeft.drawAnimation(g2d, x - offset, y - offset); + } + } else { + if(falling) g2d.drawImage(right ? playerLookingUpFallingRight : playerLookingUpFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? playerLookingUpJumpingRight : playerLookingUpJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) playerLookingUpIdleRight.drawAnimation(g2d, x - offset, y - offset); + else playerLookingUpIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) playerLookingUpRunningRight.drawAnimation(g2d, x - offset, y - offset); + else playerLookingUpRunningLeft.drawAnimation(g2d, x - offset, y - offset); + } + } + } + + + + else if(gray) { + if(prone) { + if(falling || jumping) g2d.drawImage(right ? GRAYplayerLookingDownRight : GRAYplayerLookingDownLeft, x - offset, y - offset, null); + else g2d.drawImage(right ? GRAYplayerProneRight : GRAYplayerProneLeft, x - offset, y - offset, null); + } else if(!lookingUp) { + if(falling) g2d.drawImage(right ? GRAYplayerFallingRight : GRAYplayerFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? GRAYplayerJumpingRight : GRAYplayerJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) GRAYplayerIdleRight.drawAnimation(g2d, x - offset, y - offset); + else GRAYplayerIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) GRAYplayerWalkRight.drawAnimation(g2d, x - offset, y - offset); + else GRAYplayerWalkLeft.drawAnimation(g2d, x - offset, y - offset); + } + } else { + if(falling) g2d.drawImage(right ? GRAYplayerLookingUpFallingRight : GRAYplayerLookingUpFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? GRAYplayerLookingUpJumpingRight : GRAYplayerLookingUpJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) GRAYplayerLookingUpIdleRight.drawAnimation(g2d, x - offset, y - offset); + else GRAYplayerLookingUpIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) GRAYplayerLookingUpRunningRight.drawAnimation(g2d, x - offset, y - offset); + else GRAYplayerLookingUpRunningLeft.drawAnimation(g2d, x - offset, y - offset); + } + } + } + + + + else if(pale_green) { + if(prone) { + if(falling || jumping) g2d.drawImage(right ? PALE_GREENplayerLookingDownRight : PALE_GREENplayerLookingDownLeft, x - offset, y - offset, null); + else g2d.drawImage(right ? PALE_GREENplayerProneRight : PALE_GREENplayerProneLeft, x - offset, y - offset, null); + } else if(!lookingUp) { + if(falling) g2d.drawImage(right ? PALE_GREENplayerFallingRight : PALE_GREENplayerFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? PALE_GREENplayerJumpingRight : PALE_GREENplayerJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) PALE_GREENplayerIdleRight.drawAnimation(g2d, x - offset, y - offset); + else PALE_GREENplayerIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) PALE_GREENplayerWalkRight.drawAnimation(g2d, x - offset, y - offset); + else PALE_GREENplayerWalkLeft.drawAnimation(g2d, x - offset, y - offset); + } + } else { + if(falling) g2d.drawImage(right ? PALE_GREENplayerLookingUpFallingRight : PALE_GREENplayerLookingUpFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? PALE_GREENplayerLookingUpJumpingRight : PALE_GREENplayerLookingUpJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) PALE_GREENplayerLookingUpIdleRight.drawAnimation(g2d, x - offset, y - offset); + else PALE_GREENplayerLookingUpIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) PALE_GREENplayerLookingUpRunningRight.drawAnimation(g2d, x - offset, y - offset); + else PALE_GREENplayerLookingUpRunningLeft.drawAnimation(g2d, x - offset, y - offset); + } + } + } + + + + else if(green) { + if(prone) { + if(falling || jumping) g2d.drawImage(right ? GREENplayerLookingDownRight : GREENplayerLookingDownLeft, x - offset, y - offset, null); + else g2d.drawImage(right ? GREENplayerProneRight : GREENplayerProneLeft, x - offset, y - offset, null); + } else if(!lookingUp) { + if(falling) g2d.drawImage(right ? GREENplayerFallingRight : GREENplayerFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? GREENplayerJumpingRight : GREENplayerJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) GREENplayerIdleRight.drawAnimation(g2d, x - offset, y - offset); + else GREENplayerIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) GREENplayerWalkRight.drawAnimation(g2d, x - offset, y - offset); + else GREENplayerWalkLeft.drawAnimation(g2d, x - offset, y - offset); + } + } else { + if(falling) g2d.drawImage(right ? GREENplayerLookingUpFallingRight : GREENplayerLookingUpFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? GREENplayerLookingUpJumpingRight : GREENplayerLookingUpJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) GREENplayerLookingUpIdleRight.drawAnimation(g2d, x - offset, y - offset); + else GREENplayerLookingUpIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) GREENplayerLookingUpRunningRight.drawAnimation(g2d, x - offset, y - offset); + else GREENplayerLookingUpRunningLeft.drawAnimation(g2d, x - offset, y - offset); + } + } + } + + + + // BROWN --- below 10% health + else { + if(prone) { + if(falling || jumping) g2d.drawImage(right ? BROWNplayerLookingDownRight : BROWNplayerLookingDownLeft, x - offset, y - offset, null); + else g2d.drawImage(right ? BROWNplayerProneRight : BROWNplayerProneLeft, x - offset, y - offset, null); + } else if(!lookingUp) { + if(falling) g2d.drawImage(right ? BROWNplayerFallingRight : BROWNplayerFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? BROWNplayerJumpingRight : BROWNplayerJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) BROWNplayerIdleRight.drawAnimation(g2d, x - offset, y - offset); + else BROWNplayerIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) BROWNplayerWalkRight.drawAnimation(g2d, x - offset, y - offset); + else BROWNplayerWalkLeft.drawAnimation(g2d, x - offset, y - offset); + } + } else { + if(falling) g2d.drawImage(right ? BROWNplayerLookingUpFallingRight : BROWNplayerLookingUpFallingLeft, x - offset, y - offset, null); + else if(jumping) g2d.drawImage(right ? BROWNplayerLookingUpJumpingRight : BROWNplayerLookingUpJumpingLeft, x - offset, y - offset, null); + else if(stopped) { + if(right) BROWNplayerLookingUpIdleRight.drawAnimation(g2d, x - offset, y - offset); + else BROWNplayerLookingUpIdleLeft.drawAnimation(g2d, x - offset, y - offset); + } else { + if(right) BROWNplayerLookingUpRunningRight.drawAnimation(g2d, x - offset, y - offset); + else BROWNplayerLookingUpRunningLeft.drawAnimation(g2d, x - offset, y - offset); + } + } + } + } + +} diff --git a/src/player/gun/PlayerBulletDamages.java b/src/player/gun/PlayerBulletDamages.java new file mode 100755 index 0000000..44c7eb3 --- /dev/null +++ b/src/player/gun/PlayerBulletDamages.java @@ -0,0 +1,8 @@ +package player.gun; + +public interface PlayerBulletDamages { + + + public static float DEFAULT_GUN_DAMAGE = 3; + +} diff --git a/src/player/gun/PlayerGun.java b/src/player/gun/PlayerGun.java new file mode 100755 index 0000000..ed8bb93 --- /dev/null +++ b/src/player/gun/PlayerGun.java @@ -0,0 +1,28 @@ +package player.gun; + +import static sjgs.core.jython.Jython.pi; +import org.python.core.PyFunction; +import player.Player; + +public class PlayerGun { + + private static long then; + + public static void shoot(final Player player) { + + if(System.currentTimeMillis() - then > 175) { + shoot.__call__(player.getSelf()); + then = System.currentTimeMillis(); + } + + /* uncomment for interactive scripting */ + // pi.exec(readTextFileAsString("/player/gun/player_gun.py")); + // initPyFuncs(); + } + + private static PyFunction shoot; + public static void initPyFuncs() { + shoot = pi.get("player_shoot", PyFunction.class); + } + +} diff --git a/src/player/gun/bullets/DefaultBullet.java b/src/player/gun/bullets/DefaultBullet.java new file mode 100755 index 0000000..e211b6c --- /dev/null +++ b/src/player/gun/bullets/DefaultBullet.java @@ -0,0 +1,76 @@ +package player.gun.bullets; + +import static sjgs.utils.Utils.isPositive; +import java.awt.Graphics2D; +import core.Main; +import sjgs.enums.Facing; +import sjgs.graphics.Animation; +import sjgs.physics.structs.CollisionResponse; +import sjgs.utils.data_structures.vectors.Point2f; +import textures.player.PlayerGunTextures; + +public class DefaultBullet extends PlayerBullet { + + public static final String sound = "/tir.mp3"; + + private static final int w = 8, h = 1, health_timer = 18; + private final Animation animation; + private final Point2f p; + private final Facing facing; + + /** @constructor: velX / velY are the player's velocity at initial shot */ + public DefaultBullet(final Point2f p, final Facing facing, final float velX, final float velY) { + // note the +2 and +1, leave them! + super(p.x + 2, p.y + 1, facing == Facing.RIGHT || facing == Facing.LEFT ? w : h, facing == Facing.RIGHT || facing == Facing.LEFT ? h : w, velX, velY, 0, health_timer); + this.p = p; this.facing = facing; + switch(facing) { + case RIGHT: animation = PlayerGunTextures.default_gun_right.clone(); break; + case LEFT: animation = PlayerGunTextures.default_gun_left.clone(); break; + case ABOVE: animation = PlayerGunTextures.default_gun_up.clone(); break; + default: animation = PlayerGunTextures.default_gun_down.clone(); break; // (down) + } + } + + @Override + protected void init() {} + + @Override + public void tick() { + final CollisionResponse response = getCollidedObjects(); + + // do collision stuff here + + response.discard(); + + animation.playAnimationOnce(); + + if(isMoving()) { + // if player changed directions since last shot, set the bullet velocity to zero + final float pvx = Main.player.getVelX(), pvy = Main.player.getVelY(), vx = getVelX(), vy = getVelY(); + if(pvx == 0 || isPositive(vx) ^ isPositive(pvx)) setVelX(0); + if(pvy == 0 || isPositive(vy) ^ isPositive(pvy)) setVelY(0); + // update animation position + p.x += getVelX(); + p.y += getVelY(); + } + + // NOTE YOU DO NEED THIS, it updates the bounds pos when running to match animation + updatePosition(); + + if(timer.tick()) destroy(); + } + + @Override + public void render(final Graphics2D g2d) { + if(animation != null) animation.drawAnimation(g2d, p); + + // g2d.setColor(Color.blue); + // getFullBounds().draw(g2d); + } + + @Override + protected void destroy() { + removeFromHandler(); + } + +} diff --git a/src/player/gun/bullets/PlayerBullet.java b/src/player/gun/bullets/PlayerBullet.java new file mode 100755 index 0000000..f37a9cc --- /dev/null +++ b/src/player/gun/bullets/PlayerBullet.java @@ -0,0 +1,21 @@ +package player.gun.bullets; + +import java.awt.Graphics2D; +import sjgs.base_objects.Bullet; + +public abstract class PlayerBullet extends Bullet { + + public PlayerBullet(final float x, final float y, final float w, final float h, final float velX, final float velY, final int elasticity, final int health_timer) { + super(x, y, w, h, velX, velY, elasticity, health_timer); + } + + @Override + protected abstract void init(); + @Override + public abstract void tick(); + @Override + public abstract void render(Graphics2D g2d); + @Override + protected abstract void destroy(); + +} diff --git a/src/player/gun/player_gun.py b/src/player/gun/player_gun.py new file mode 100755 index 0000000..f5302a8 --- /dev/null +++ b/src/player/gun/player_gun.py @@ -0,0 +1,136 @@ +# DIFFERENT BULLETS: +DEFAULT_GUN = 1 + +import textures.player.PlayerTextures as PlayerTextures + +# creates the bullet for gun to shoot +def player_shoot(player): + p = getPlayerGunPositionPoint(player) + dir = getPlayerBulletDirection(player) + b = whichPlayerBullet(player) + + # create the bullet + if b == DEFAULT_GUN: + down_multiplier = 1/3 + if dir == Facing.BELOW or dir == Facing.ABOVE: DefaultBullet(p, dir, 0, player.getVelY() * down_multiplier) + elif (dir == Facing.RIGHT or dir == Facing.LEFT) or dir == Facing.ABOVE and player.getVelX() != 0: DefaultBullet(p, dir, player.getVelX(), 0) + else: DefaultBullet(p, dir, 0, 0) + + # play shooting sound + playerBulletSound(b) + +# gets the position of the gun barrel location +# NOTE: use (int) as graphics cannot be floating points! +def getPlayerGunPositionPoint(player): + x = 0 + y = 0 + + # get variables for clarity + right = player.getFacing() == Facing.RIGHT + left = not right + jumping = player.getJumping() + falling = player.getFalling() + up = player.getLookingUp() + down = player.getProne() and (player.getFalling() or player.getJumping()) + moving = player.getVelX() != 0 or player.getVelY() != 0 + prone = player.getProne() and not (player.getFalling() or player.getJumping()) and not moving + + cx = int(player.getCenterX()) + cy = int(player.getCenterY()) + + idle = not falling and not jumping and not up and not down and not prone and not moving + idleUp = not falling and not jumping and up and not down and not prone and not moving + running = not falling and not jumping and not up and not down and not prone and moving + runningUp = not falling and not jumping and up and not down and not prone and moving + jumping = (jumping or falling) and not up + jumpingUp = (jumping or falling or player.getVelY() < 0) and up + +############ IF FACING RIGHT ############################################################################ + if right: + if idle: + x = cx + 4 + y = cy - 2 + if PlayerTextures.playerIdleRight.currentFrame == PlayerTextures.playerIdleRight.size() - 1: y += 1 + elif idleUp: + x = cx - 1 + y = cy - 14 + if PlayerTextures.playerLookingUpIdleRight.currentFrame == PlayerTextures.playerLookingUpIdleRight.size() - 1: y += 1 + elif running: + x = cx + 4 + y = cy - 2 + if PlayerTextures.playerWalkRight.currentFrame % 2 == 0: y -= 1 + if PlayerTextures.playerWalkRight.currentFrame == 1: x += 1 + if PlayerTextures.playerWalkRight.currentFrame == 3: x -= 1 + elif runningUp: + x = cx + y = cy - 14 + if PlayerTextures.playerLookingUpRunningRight.currentFrame % 2 == 0: y -= 1 + if PlayerTextures.playerLookingUpRunningRight.currentFrame == 1: x += 1 + if PlayerTextures.playerLookingUpRunningRight.currentFrame == 3: x -= 1 + elif prone: + x = cx + 5 + y = cy + elif down: + x = cx - 2 + y = cy + 5 + elif jumping: + x = cx + 4 + y = cy - 1 + elif jumpingUp: + x = cx - 1 + y = cy - 9 +################## IF FACING LEFT ####################################################################### + else: + if idle: + x = cx - 13 + y = cy - 2 + if PlayerTextures.playerIdleLeft.currentFrame == PlayerTextures.playerIdleLeft.size() - 1: y += 1 + elif idleUp: + x = cx - 2 + y = cy - 14 + if PlayerTextures.playerLookingUpIdleLeft.currentFrame == PlayerTextures.playerLookingUpIdleLeft.size() - 1: y += 1 + elif running: + x = cx - 13 + y = cy - 2 + if PlayerTextures.playerWalkLeft.currentFrame % 2 == 0: y -= 1 + if PlayerTextures.playerWalkLeft.currentFrame == 1: x -= 1 + if PlayerTextures.playerWalkLeft.currentFrame == 3: x += 1 + elif runningUp: + x = cx - 2 + y = cy - 14 + if PlayerTextures.playerLookingUpRunningLeft.currentFrame % 2 == 0: y -= 1 + if PlayerTextures.playerLookingUpRunningLeft.currentFrame == 1: x -= 1 + if PlayerTextures.playerLookingUpRunningLeft.currentFrame == 3: x += 1 + elif prone: + x = cx - 14 + y = cy + elif down: + x = cx - 1 + y = cy + 7 + elif jumping: + x = cx - 12 + y = cy - 1 + elif jumpingUp: + x = cx - 2 + y = cy - 9 +################################################################################################################## + return Point2f(x, y) + +def playerBulletSound(b): + if b == DEFAULT_GUN: MP3Player.play(DefaultBullet.sound) + +def getPlayerBulletDirection(player): + right = player.getFacing() == Facing.RIGHT + left = not right + prone = player.getProne() and not (player.getFalling() or player.getJumping()) + up = player.getLookingUp() + down = player.getProne() and (player.getFalling() or player.getJumping()) + + if right and not down and not up: return Facing.RIGHT + elif left and not down and not up: return Facing.LEFT + elif down: return Facing.BELOW + elif up: return Facing.ABOVE + +# determines which kind of bullet to shoot +def whichPlayerBullet(player): + return DEFAULT_GUN \ No newline at end of file diff --git a/src/player/player_animations.py b/src/player/player_animations.py new file mode 100755 index 0000000..902e060 --- /dev/null +++ b/src/player/player_animations.py @@ -0,0 +1,60 @@ +### NOTE we run them all here as its the easiest way to get them sync'd up, and +# with my animation implementation its only incrementing an int, so its not resource intensive. + +def run_player_animations(p): + # IF RUNNING NORMALLY + if not p.getProne() and not p.getFalling() and not p.getLookingUp() and not p.stopped(): + if p.facingRight(): + PlayerTextures.playerWalkRight.runAnimation() + PlayerTextures.GRAYplayerWalkRight.runAnimation() + PlayerTextures.PALE_GREENplayerWalkRight.runAnimation() + PlayerTextures.GREENplayerWalkRight.runAnimation() + PlayerTextures.BROWNplayerWalkRight.runAnimation() + else: + PlayerTextures.playerWalkLeft.runAnimation() + PlayerTextures.GRAYplayerWalkLeft.runAnimation() + PlayerTextures.PALE_GREENplayerWalkLeft.runAnimation() + PlayerTextures.GREENplayerWalkLeft.runAnimation() + PlayerTextures.BROWNplayerWalkLeft.runAnimation() + # IF RUNNING LOOKING UP + elif not p.getProne() and not p.getFalling() and not p.stopped(): + if p.facingRight(): + PlayerTextures.playerLookingUpRunningRight.runAnimation() + PlayerTextures.GRAYplayerLookingUpRunningRight.runAnimation() + PlayerTextures.PALE_GREENplayerLookingUpRunningRight.runAnimation() + PlayerTextures.GREENplayerLookingUpRunningRight.runAnimation() + PlayerTextures.BROWNplayerLookingUpRunningRight.runAnimation() + else: + PlayerTextures.playerLookingUpRunningLeft.runAnimation() + PlayerTextures.GRAYplayerLookingUpRunningLeft.runAnimation() + PlayerTextures.PALE_GREENplayerLookingUpRunningLeft.runAnimation() + PlayerTextures.GREENplayerLookingUpRunningLeft.runAnimation() + PlayerTextures.BROWNplayerLookingUpRunningLeft.runAnimation() + # IF IDLE NORMAL + elif not p.getProne() and not p.getFalling() and not p.getLookingUp(): + if p.facingRight(): + PlayerTextures.playerIdleRight.runAnimation() + PlayerTextures.GRAYplayerIdleRight.runAnimation() + PlayerTextures.PALE_GREENplayerIdleRight.runAnimation() + PlayerTextures.GREENplayerIdleRight.runAnimation() + PlayerTextures.BROWNplayerIdleRight.runAnimation() + else: + PlayerTextures.playerIdleLeft.runAnimation() + PlayerTextures.GRAYplayerIdleLeft.runAnimation() + PlayerTextures.PALE_GREENplayerIdleLeft.runAnimation() + PlayerTextures.GREENplayerIdleLeft.runAnimation() + PlayerTextures.BROWNplayerIdleLeft.runAnimation() + # IF IDLE LOOKING UP + elif not p.getProne() and not p.getFalling() and p.stopped() and p.getLookingUp(): + if p.facingRight(): + PlayerTextures.playerLookingUpIdleRight.runAnimation() + PlayerTextures.GRAYplayerLookingUpIdleRight.runAnimation() + PlayerTextures.PALE_GREENplayerLookingUpIdleRight.runAnimation() + PlayerTextures.GREENplayerLookingUpIdleRight.runAnimation() + PlayerTextures.BROWNplayerLookingUpIdleRight.runAnimation() + else: + PlayerTextures.playerLookingUpIdleLeft.runAnimation() + PlayerTextures.GRAYplayerLookingUpIdleLeft.runAnimation() + PlayerTextures.PALE_GREENplayerLookingUpIdleLeft.runAnimation() + PlayerTextures.GREENplayerLookingUpIdleLeft.runAnimation() + PlayerTextures.BROWNplayerLookingUpIdleLeft.runAnimation() \ No newline at end of file diff --git a/src/tiles/Tile.java b/src/tiles/Tile.java new file mode 100755 index 0000000..0954881 --- /dev/null +++ b/src/tiles/Tile.java @@ -0,0 +1,31 @@ +package tiles; + +import java.awt.Graphics2D; +import sjgs.base_objects.BaseTile; +import textures.tiles.TileTextures; + +public class Tile extends BaseTile { + + public Tile(final int x, final int y, final int w, final int h, final float startingHeightPercentage, final float endingHeightPercentage) { + super(x, y, w, h, startingHeightPercentage, endingHeightPercentage); + } + + // no args = not angled + public Tile(final int x, final int y, final int w, final int h) { super(x, y, w, h, 0, 0); } + + @Override + public void init() {} + + @Override + public void tick() {} + + @Override + public void render(final Graphics2D g2d) { + g2d.drawImage(TileTextures.tile1, (int)getX(), (int)getY(), null); // NOTE YOU NEED THE +2!!! + } + + + @Override + public void destroy() { removeFromHandler(); } + +} diff --git a/src/ui/HUD.java b/src/ui/HUD.java new file mode 100755 index 0000000..83e8499 --- /dev/null +++ b/src/ui/HUD.java @@ -0,0 +1,3 @@ +package ui; + +public class HUD {} diff --git a/src/ui/inventory/Inventory.java b/src/ui/inventory/Inventory.java new file mode 100755 index 0000000..80c4d5a --- /dev/null +++ b/src/ui/inventory/Inventory.java @@ -0,0 +1,48 @@ +package ui.inventory; + +import java.awt.Graphics2D; +import sjgs.graphics.ui.InventorySystem; +import sjgs.graphics.ui.InventorySystemSlot; + +public class Inventory extends InventorySystem { + + public Inventory(final float x, final float y, final float width, final float height) { + super(x, y, width, height); + } + + @Override + public void init() { + + } + + + @Override + public void onLeftClick() { + baseOnLeftClick(); + } + + @Override + public int getStackableAmount(final int itemId) { return 0; } + + @Override + public boolean isStackable(final int itemId) { return false; } + + @Override + public void render(final Graphics2D g2d) { + for(final InventorySystemSlot slot : getSlots()) slot.render(g2d); + } + + @Override + public void tick() { + for(final InventorySystemSlot slot : getSlots()) slot.tick(); + } + + @Override + public void swapSlots(final InventorySystemSlot a, final InventorySystemSlot b) { + baseSwapSlots(a, b); + } + + @Override + public void destroy() {} + +} diff --git a/src/ui/inventory/InventorySlot.java b/src/ui/inventory/InventorySlot.java new file mode 100755 index 0000000..81a3b8b --- /dev/null +++ b/src/ui/inventory/InventorySlot.java @@ -0,0 +1,35 @@ +package ui.inventory; + +import java.awt.Graphics2D; +import sjgs.graphics.ui.InventorySystemSlot; + +public class InventorySlot extends InventorySystemSlot { + + + public InventorySlot(final float x, final float y, final float w, final float h, final int slotNumber) { + super(x, y, w, h, slotNumber); + } + + @Override + public void init() { + + } + + @Override + public void render(final Graphics2D g2d) { + + } + + @Override + public void reset() { + baseReset(); + } + + @Override + public void tick() { + + } + + + +} diff --git a/src/ui/inventory/ItemIDs.java b/src/ui/inventory/ItemIDs.java new file mode 100755 index 0000000..f4dbc2e --- /dev/null +++ b/src/ui/inventory/ItemIDs.java @@ -0,0 +1,17 @@ +package ui.inventory; + +public interface ItemIDs { + + + public static final int UPGRADED_DEFAULT_GUN = 1, + DOUBLE_JUMP = 2, + NIGHT_VISION = 3, + DASH_BOOSTER = 4, + LAVA_SUIT = 5, + WATER_SUIT = 6, + MAP = 7, + DEFAULT_GUN = 8; + + + +} diff --git a/src/worldgen/TestMapCreator.java b/src/worldgen/TestMapCreator.java new file mode 100755 index 0000000..b08d441 --- /dev/null +++ b/src/worldgen/TestMapCreator.java @@ -0,0 +1,59 @@ +package worldgen; + +import static sjgs.utils.Utils.COIN_FLIP; +import static sjgs.utils.Utils.loadImage; +import static sjgs.utils.Utils.unpackBlue; +import static sjgs.utils.Utils.unpackGreen; +import static sjgs.utils.Utils.unpackRed; +import java.awt.image.BufferedImage; +import core.Main; +import mobs.scraveller.Scraveller; +import sjgs.utils.data_structures.shapes.Rectangle; +import sjgs.utils.data_structures.vectors.Point2f; +import sjgs.utils.multithreading.Runner; +import tiles.Tile; + +public class TestMapCreator { + + public static void createTestMap() { + + final int TILE_SIZE = Main.TILE_SIZE; + + final BufferedImage map = loadImage("/map.png"); + Main.camera.setLimitsWithRect(0, 0, map.getWidth()*6, map.getHeight()*6); + + for (int i = 0; i < map.getHeight(); i++) { + for (int j = 0; j < map.getWidth(); j++) { + final int col = i, row = j; + new Runner(() -> { + + final int pixel = map.getRGB(col, row); + final int r = unpackRed(pixel); + final int g = unpackGreen(pixel); + final int b = unpackBlue(pixel); + + if(r == 64 && g == 64 && b == 64) new Tile(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); + else if(r == 0 && g == 0 && b == 255) Main.player.setLocation(col * TILE_SIZE, row * TILE_SIZE); + else if(r == 255 && g == 0 && b == 0) { + new Tile(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); + new Scraveller( new Rectangle( new Point2f(col * TILE_SIZE, row * TILE_SIZE), 2*TILE_SIZE, TILE_SIZE ), COIN_FLIP() ); + } + else if(r == 255 && g == 255 && b == 255) { + new Tile(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); + new Scraveller( new Rectangle( new Point2f(col * TILE_SIZE, row * TILE_SIZE), 3*TILE_SIZE, TILE_SIZE ), COIN_FLIP() ); + } + else if(r == 255 && g == 200 && b == 0) { + new Tile(col * TILE_SIZE, row * TILE_SIZE, TILE_SIZE, TILE_SIZE); + new Scraveller( new Rectangle( new Point2f(col * TILE_SIZE, row * TILE_SIZE), TILE_SIZE, TILE_SIZE ), COIN_FLIP() ); + } + + + } ).run(); + + } + } + } + + + +} diff --git a/src/worldgen/WorldGenerator.java b/src/worldgen/WorldGenerator.java new file mode 100755 index 0000000..e9428cb --- /dev/null +++ b/src/worldgen/WorldGenerator.java @@ -0,0 +1,36 @@ +package worldgen; + +import static sjgs.utils.Utils.loadImage; +import core.Main; +import player.Player; +import sjgs.core.Handler; +import sjgs.graphics.backgrounds.Background; +import sjgs.graphics.backgrounds.ParallaxBackground; + +public class WorldGenerator { + + public static ParallaxBackground currentBackground; + + public static void generateWorld() { + Handler.clearAll(); + Main.player = new Player(0, 0); + TestMapCreator.createTestMap(); + + final int startX = 0, startY = 0; + + final Background background = new Background(loadImage("/background.png"), startX, startY, 100, 0, true); + final Background midground = new Background(loadImage("/midground.png"), startX, startY, 50, 100, true); + final Background foreground = new Background(loadImage("/foreground.png"), startX, startY, 80, 0, true); + + + + + currentBackground = new ParallaxBackground(background, midground, foreground); + + + +// currentBackground = new ParallaxBackground(midground); + } + + +} diff --git a/textures/textures/Texture.java b/textures/textures/Texture.java new file mode 100755 index 0000000..17a79e5 --- /dev/null +++ b/textures/textures/Texture.java @@ -0,0 +1,7 @@ +package textures; + +public interface Texture { + + abstract void getTextures(); + +} diff --git a/textures/textures/TextureLoader.java b/textures/textures/TextureLoader.java new file mode 100755 index 0000000..5047581 --- /dev/null +++ b/textures/textures/TextureLoader.java @@ -0,0 +1,25 @@ +package textures; + +import sjgs.utils.multithreading.Runner; +import textures.mobs.ScravellerTextures; +import textures.player.PlayerGunTextures; +import textures.player.PlayerTextures; +import textures.tiles.TileTextures; + +public final class TextureLoader { + + + public static void getTextures() { + // PLAYER STUFF + new Runner(() -> new PlayerTextures().getTextures() ).run(); + new Runner(() -> new PlayerGunTextures().getTextures() ).run(); + + new Runner(() -> new TileTextures().getTextures() ).run(); + //MOBS + new Runner(() -> new ScravellerTextures().getTextures() ).run(); + } + + + + +} diff --git a/textures/textures/mobs/ScravellerTextures.java b/textures/textures/mobs/ScravellerTextures.java new file mode 100755 index 0000000..df03105 --- /dev/null +++ b/textures/textures/mobs/ScravellerTextures.java @@ -0,0 +1,27 @@ +package textures.mobs; + +import static sjgs.utils.Utils.grabSprite; +import static sjgs.utils.Utils.loadImage; +import java.awt.image.BufferedImage; +import sjgs.graphics.Animation; +import textures.Texture; + +public class ScravellerTextures implements Texture { + + public static Animation move, moveFlipped, rotatedRight, rotatedLeft; + + @Override + public void getTextures() { + final int MOVE_SPEED = 15; + final int width = 5, height = 4; + final BufferedImage ss = loadImage("/scraveller.png"); + + move = new Animation(MOVE_SPEED, + grabSprite(ss, 0, 0, width, height), + grabSprite(ss, 1, 0, width, height) + ); + moveFlipped = move.getInverted(); + rotatedRight = move.getRotatedRight(); + rotatedLeft = move.getRotatedLeft(); + } +} diff --git a/textures/textures/player/PlayerGunTextures.java b/textures/textures/player/PlayerGunTextures.java new file mode 100755 index 0000000..c344fa8 --- /dev/null +++ b/textures/textures/player/PlayerGunTextures.java @@ -0,0 +1,34 @@ +package textures.player; + +import static sjgs.utils.Utils.grabSprite; +import static sjgs.utils.Utils.loadImage; +import java.awt.image.BufferedImage; +import sjgs.graphics.Animation; +import textures.Texture; + +public class PlayerGunTextures implements Texture { + + public static Animation default_gun_right, default_gun_left, default_gun_up, default_gun_down; + + @Override + public void getTextures() { + final int default_gun_speed = 2; + final BufferedImage default_gun_ss = loadImage("/default_gun.png"); + final int default_gun_width = 11, default_gun_height = 5; + + default_gun_right = new Animation(default_gun_speed, + grabSprite(default_gun_ss, 0, 0, default_gun_width, default_gun_height), + grabSprite(default_gun_ss, 1, 0, default_gun_width, default_gun_height), + grabSprite(default_gun_ss, 2, 0, default_gun_width, default_gun_height), + grabSprite(default_gun_ss, 3, 0, default_gun_width, default_gun_height), + grabSprite(default_gun_ss, 4, 0, default_gun_width, default_gun_height)); + default_gun_left = default_gun_right.getReverse(); + default_gun_up = default_gun_right.getRotatedLeft(); + default_gun_down = default_gun_right.getRotatedRight(); + } + + + + + +} diff --git a/textures/textures/player/PlayerTextures.java b/textures/textures/player/PlayerTextures.java new file mode 100755 index 0000000..6f3d688 --- /dev/null +++ b/textures/textures/player/PlayerTextures.java @@ -0,0 +1,299 @@ +package textures.player; + +import static sjgs.utils.Utils.grabSprite; +import static sjgs.utils.Utils.loadImage; +import static sjgs.utils.Utils.reverseImage; +import java.awt.image.BufferedImage; +import sjgs.graphics.Animation; +import textures.Texture; + +public class PlayerTextures implements Texture { + + + // ------------------- WHITE EYE ----------------------------------------------------------------- // + public static Animation playerWalkRight, playerWalkLeft, playerIdleLeft, playerIdleRight, + playerLookingUpRunningRight, playerLookingUpRunningLeft, playerLookingUpIdleRight, + playerLookingUpIdleLeft; + public static BufferedImage playerJumpingRight, playerJumpingLeft, playerFallingRight, playerFallingLeft, + playerLookingDownRight, playerLookingDownLeft, playerProneRight, playerProneLeft, playerLookingUpJumpingRight, + playerLookingUpJumpingLeft, playerLookingUpFallingRight, playerLookingUpFallingLeft; + // ------------------ END WHITE EYE -------------------------------------------------------------- // + + // ------------------- GRAY EYE ----------------------------------------------------------------- // + public static Animation GRAYplayerWalkRight, GRAYplayerWalkLeft, GRAYplayerIdleLeft, GRAYplayerIdleRight, + GRAYplayerLookingUpRunningRight, GRAYplayerLookingUpRunningLeft, GRAYplayerLookingUpIdleRight, GRAYplayerLookingUpIdleLeft; + public static BufferedImage GRAYplayerJumpingRight, GRAYplayerJumpingLeft, GRAYplayerFallingRight, GRAYplayerFallingLeft, + GRAYplayerLookingDownRight, GRAYplayerLookingDownLeft, GRAYplayerProneRight, GRAYplayerProneLeft, + GRAYplayerLookingUpJumpingRight, GRAYplayerLookingUpJumpingLeft, GRAYplayerLookingUpFallingRight, + GRAYplayerLookingUpFallingLeft; + // ------------------ END GRAY EYE -------------------------------------------------------------- // + // ------------------- PALE GREEN EYE ----------------------------------------------------------------- // + public static Animation PALE_GREENplayerWalkRight, PALE_GREENplayerWalkLeft, PALE_GREENplayerIdleLeft, PALE_GREENplayerIdleRight, + PALE_GREENplayerLookingUpRunningRight, PALE_GREENplayerLookingUpRunningLeft, PALE_GREENplayerLookingUpIdleRight, PALE_GREENplayerLookingUpIdleLeft; + public static BufferedImage PALE_GREENplayerJumpingRight, PALE_GREENplayerJumpingLeft, PALE_GREENplayerFallingRight, PALE_GREENplayerFallingLeft, + PALE_GREENplayerLookingDownRight, PALE_GREENplayerLookingDownLeft, PALE_GREENplayerProneRight, PALE_GREENplayerProneLeft, + PALE_GREENplayerLookingUpJumpingRight, PALE_GREENplayerLookingUpJumpingLeft, PALE_GREENplayerLookingUpFallingRight, + PALE_GREENplayerLookingUpFallingLeft; + // ------------------ END PALE GREEN EYE -------------------------------------------------------------- // + // ------------------- GREEN EYE ----------------------------------------------------------------- // + public static Animation GREENplayerWalkRight, GREENplayerWalkLeft, GREENplayerIdleLeft, GREENplayerIdleRight, + GREENplayerLookingUpRunningRight, GREENplayerLookingUpRunningLeft, GREENplayerLookingUpIdleRight, GREENplayerLookingUpIdleLeft; + public static BufferedImage GREENplayerJumpingRight, GREENplayerJumpingLeft, GREENplayerFallingRight, GREENplayerFallingLeft, + GREENplayerLookingDownRight, GREENplayerLookingDownLeft, GREENplayerProneRight, GREENplayerProneLeft, + GREENplayerLookingUpJumpingRight, GREENplayerLookingUpJumpingLeft, GREENplayerLookingUpFallingRight, + GREENplayerLookingUpFallingLeft; + // ------------------ END GREEN EYE -------------------------------------------------------------- // + // ------------------- BROWN EYE ----------------------------------------------------------------- // + public static Animation BROWNplayerWalkRight, BROWNplayerWalkLeft, BROWNplayerIdleLeft, BROWNplayerIdleRight, + BROWNplayerLookingUpRunningRight, BROWNplayerLookingUpRunningLeft, BROWNplayerLookingUpIdleRight, BROWNplayerLookingUpIdleLeft; + public static BufferedImage BROWNplayerJumpingRight, BROWNplayerJumpingLeft, BROWNplayerFallingRight, BROWNplayerFallingLeft, + BROWNplayerLookingDownRight, BROWNplayerLookingDownLeft, BROWNplayerProneRight, BROWNplayerProneLeft, + BROWNplayerLookingUpJumpingRight, BROWNplayerLookingUpJumpingLeft, BROWNplayerLookingUpFallingRight, + BROWNplayerLookingUpFallingLeft; + // ------------------ END BROWN EYE -------------------------------------------------------------- // + + + @Override + public void getTextures() { + // WHITE EYE + final int w = 12, h = 12; + final int RUNNING_SPEED = 8, IDLE_SPEED = 20; + BufferedImage ss = loadImage("/Player1.png"); + playerWalkRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 0, w, h), + grabSprite(ss, 1, 0, w, h), + grabSprite(ss, 2, 0, w, h), + grabSprite(ss, 3, 0, w, h) + ); + playerWalkLeft = playerWalkRight.getReverse(); + + playerIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 1, w, h), + grabSprite(ss, 1, 1, w, h) + ); + playerIdleLeft = playerIdleRight.getReverse(); + + playerJumpingRight = grabSprite(ss, 2, 1, w, h); + playerJumpingLeft = reverseImage(playerJumpingRight); + + playerFallingRight = grabSprite(ss, 3, 1, w, h); + playerFallingLeft = reverseImage(playerFallingRight); + + playerLookingUpJumpingRight = grabSprite(ss, 4, 0, w, h); + playerLookingUpJumpingLeft = reverseImage(playerLookingUpJumpingRight); + + playerLookingUpFallingRight = grabSprite(ss, 4, 1, w, h); + playerLookingUpFallingLeft = reverseImage(playerLookingUpFallingRight); + + playerLookingUpIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 2, w, h), + grabSprite(ss, 1, 2, w, h) + ); + playerLookingUpIdleLeft = playerLookingUpIdleRight.getReverse(); + + playerProneRight = grabSprite(ss, 2, 2, w, h); + playerProneLeft = reverseImage(playerProneRight); + + playerLookingDownRight = grabSprite(ss, 3, 2, w, h); + playerLookingDownLeft = reverseImage(playerLookingDownRight); + + playerLookingUpRunningRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 3, w, h), + grabSprite(ss, 1, 3, w, h), + grabSprite(ss, 2, 3, w, h), + grabSprite(ss, 3, 3, w, h) + ); + playerLookingUpRunningLeft = playerLookingUpRunningRight.getReverse(); + + + // GRAY EYE + ss = loadImage("/Player2.png"); + GRAYplayerWalkRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 0, w, h), + grabSprite(ss, 1, 0, w, h), + grabSprite(ss, 2, 0, w, h), + grabSprite(ss, 3, 0, w, h) + ); + GRAYplayerWalkLeft = GRAYplayerWalkRight.getReverse(); + + GRAYplayerIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 1, w, h), + grabSprite(ss, 1, 1, w, h) + ); + GRAYplayerIdleLeft = GRAYplayerIdleRight.getReverse(); + + GRAYplayerJumpingRight = grabSprite(ss, 2, 1, w, h); + GRAYplayerJumpingLeft = reverseImage(GRAYplayerJumpingRight); + + GRAYplayerFallingRight = grabSprite(ss, 3, 1, w, h); + GRAYplayerFallingLeft = reverseImage(GRAYplayerFallingRight); + + GRAYplayerLookingUpJumpingRight = grabSprite(ss, 4, 0, w, h); + GRAYplayerLookingUpJumpingLeft = reverseImage(GRAYplayerLookingUpJumpingRight); + + GRAYplayerLookingUpFallingRight = grabSprite(ss, 4, 1, w, h); + GRAYplayerLookingUpFallingLeft = reverseImage(GRAYplayerLookingUpFallingRight); + + GRAYplayerLookingUpIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 2, w, h), + grabSprite(ss, 1, 2, w, h) + ); + GRAYplayerLookingUpIdleLeft = GRAYplayerLookingUpIdleRight.getReverse(); + + GRAYplayerProneRight = grabSprite(ss, 2, 2, w, h); + GRAYplayerProneLeft = reverseImage(GRAYplayerProneRight); + + GRAYplayerLookingDownRight = grabSprite(ss, 3, 2, w, h); + GRAYplayerLookingDownLeft = reverseImage(GRAYplayerLookingDownRight); + + GRAYplayerLookingUpRunningRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 3, w, h), + grabSprite(ss, 1, 3, w, h), + grabSprite(ss, 2, 3, w, h), + grabSprite(ss, 3, 3, w, h) + ); + GRAYplayerLookingUpRunningLeft = playerLookingUpRunningRight.getReverse(); + // PALE GREEN EYE + ss = loadImage("/Player3.png"); + PALE_GREENplayerWalkRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 0, w, h), + grabSprite(ss, 1, 0, w, h), + grabSprite(ss, 2, 0, w, h), + grabSprite(ss, 3, 0, w, h) + ); + PALE_GREENplayerWalkLeft = PALE_GREENplayerWalkRight.getReverse(); + + PALE_GREENplayerIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 1, w, h), + grabSprite(ss, 1, 1, w, h) + ); + PALE_GREENplayerIdleLeft = PALE_GREENplayerIdleRight.getReverse(); + + PALE_GREENplayerJumpingRight = grabSprite(ss, 2, 1, w, h); + PALE_GREENplayerJumpingLeft = reverseImage(PALE_GREENplayerJumpingRight); + + PALE_GREENplayerFallingRight = grabSprite(ss, 3, 1, w, h); + PALE_GREENplayerFallingLeft = reverseImage(PALE_GREENplayerFallingRight); + + PALE_GREENplayerLookingUpJumpingRight = grabSprite(ss, 4, 0, w, h); + PALE_GREENplayerLookingUpJumpingLeft = reverseImage(PALE_GREENplayerLookingUpJumpingRight); + + PALE_GREENplayerLookingUpFallingRight = grabSprite(ss, 4, 1, w, h); + PALE_GREENplayerLookingUpFallingLeft = reverseImage(PALE_GREENplayerLookingUpFallingRight); + + PALE_GREENplayerLookingUpIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 2, w, h), + grabSprite(ss, 1, 2, w, h) + ); + PALE_GREENplayerLookingUpIdleLeft = PALE_GREENplayerLookingUpIdleRight.getReverse(); + + PALE_GREENplayerProneRight = grabSprite(ss, 2, 2, w, h); + PALE_GREENplayerProneLeft = reverseImage(PALE_GREENplayerProneRight); + + PALE_GREENplayerLookingDownRight = grabSprite(ss, 3, 2, w, h); + PALE_GREENplayerLookingDownLeft = reverseImage(PALE_GREENplayerLookingDownRight); + + PALE_GREENplayerLookingUpRunningRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 3, w, h), + grabSprite(ss, 1, 3, w, h), + grabSprite(ss, 2, 3, w, h), + grabSprite(ss, 3, 3, w, h) + ); + PALE_GREENplayerLookingUpRunningLeft = PALE_GREENplayerLookingUpRunningRight.getReverse(); + // GREEN EYE + ss = loadImage("/Player4.png"); + GREENplayerWalkRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 0, w, h), + grabSprite(ss, 1, 0, w, h), + grabSprite(ss, 2, 0, w, h), + grabSprite(ss, 3, 0, w, h) + ); + GREENplayerWalkLeft = GREENplayerWalkRight.getReverse(); + + GREENplayerIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 1, w, h), + grabSprite(ss, 1, 1, w, h) + ); + GREENplayerIdleLeft = GREENplayerIdleRight.getReverse(); + + GREENplayerJumpingRight = grabSprite(ss, 2, 1, w, h); + GREENplayerJumpingLeft = reverseImage(GREENplayerJumpingRight); + + GREENplayerFallingRight = grabSprite(ss, 3, 1, w, h); + GREENplayerFallingLeft = reverseImage(GREENplayerFallingRight); + + GREENplayerLookingUpJumpingRight = grabSprite(ss, 4, 0, w, h); + GREENplayerLookingUpJumpingLeft = reverseImage(GREENplayerLookingUpJumpingRight); + + GREENplayerLookingUpFallingRight = grabSprite(ss, 4, 1, w, h); + GREENplayerLookingUpFallingLeft = reverseImage(GREENplayerLookingUpFallingRight); + + GREENplayerLookingUpIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 2, w, h), + grabSprite(ss, 1, 2, w, h) + ); + GREENplayerLookingUpIdleLeft = GREENplayerLookingUpIdleRight.getReverse(); + + GREENplayerProneRight = grabSprite(ss, 2, 2, w, h); + GREENplayerProneLeft = reverseImage(GREENplayerProneRight); + + GREENplayerLookingDownRight = grabSprite(ss, 3, 2, w, h); + GREENplayerLookingDownLeft = reverseImage(GREENplayerLookingDownRight); + + GREENplayerLookingUpRunningRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 3, w, h), + grabSprite(ss, 1, 3, w, h), + grabSprite(ss, 2, 3, w, h), + grabSprite(ss, 3, 3, w, h) + ); + GREENplayerLookingUpRunningLeft = GREENplayerLookingUpRunningRight.getReverse(); + // BROWN EYE + ss = loadImage("/Player5.png"); + BROWNplayerWalkRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 0, w, h), + grabSprite(ss, 1, 0, w, h), + grabSprite(ss, 2, 0, w, h), + grabSprite(ss, 3, 0, w, h) + ); + BROWNplayerWalkLeft = BROWNplayerWalkRight.getReverse(); + + BROWNplayerIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 1, w, h), + grabSprite(ss, 1, 1, w, h) + ); + BROWNplayerIdleLeft = BROWNplayerIdleRight.getReverse(); + + BROWNplayerJumpingRight = grabSprite(ss, 2, 1, w, h); + BROWNplayerJumpingLeft = reverseImage(BROWNplayerJumpingRight); + + BROWNplayerFallingRight = grabSprite(ss, 3, 1, w, h); + BROWNplayerFallingLeft = reverseImage(BROWNplayerFallingRight); + + BROWNplayerLookingUpJumpingRight = grabSprite(ss, 4, 0, w, h); + BROWNplayerLookingUpJumpingLeft = reverseImage(BROWNplayerLookingUpJumpingRight); + + BROWNplayerLookingUpFallingRight = grabSprite(ss, 4, 1, w, h); + BROWNplayerLookingUpFallingLeft = reverseImage(BROWNplayerLookingUpFallingRight); + + BROWNplayerLookingUpIdleRight = new Animation(IDLE_SPEED, + grabSprite(ss, 0, 2, w, h), + grabSprite(ss, 1, 2, w, h) + ); + BROWNplayerLookingUpIdleLeft = BROWNplayerLookingUpIdleRight.getReverse(); + + BROWNplayerProneRight = grabSprite(ss, 2, 2, w, h); + BROWNplayerProneLeft = reverseImage(BROWNplayerProneRight); + + BROWNplayerLookingDownRight = grabSprite(ss, 3, 2, w, h); + BROWNplayerLookingDownLeft = reverseImage(BROWNplayerLookingDownRight); + + BROWNplayerLookingUpRunningRight = new Animation(RUNNING_SPEED, + grabSprite(ss, 0, 3, w, h), + grabSprite(ss, 1, 3, w, h), + grabSprite(ss, 2, 3, w, h), + grabSprite(ss, 3, 3, w, h) + ); + BROWNplayerLookingUpRunningLeft = BROWNplayerLookingUpRunningRight.getReverse(); + } + +} diff --git a/textures/textures/tiles/TileTextures.java b/textures/textures/tiles/TileTextures.java new file mode 100755 index 0000000..b62b61d --- /dev/null +++ b/textures/textures/tiles/TileTextures.java @@ -0,0 +1,19 @@ +package textures.tiles; + +import static sjgs.utils.Utils.grabSprite; +import static sjgs.utils.Utils.loadImage; +import java.awt.image.BufferedImage; +import textures.Texture; + +public class TileTextures implements Texture { + + public static BufferedImage tile1; + + @Override + public void getTextures() { + final BufferedImage image = loadImage("/tile.png"); + final int width = 6, height = 6; + tile1 = grabSprite(image, 0, 0, width, height); + } + +}