diff --git a/.gitignore b/.gitignore index 0d20b64..5a39d93 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -*.pyc +.venv/ +.vscode/* +!.vscode/launch.json + +__pycache__ diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..8fab27f --- /dev/null +++ b/.pylintrc @@ -0,0 +1,5 @@ +[MASTER] +disable= + C0114, + C0115, + C0116, \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..171a6a9 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.12.1 diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..ab001ac --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. + // Pointez pour afficher la description des attributs existants. + // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python : fichier actif", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index f2d90cb..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "python.linting.enabled": true -} \ No newline at end of file diff --git a/Pipfile b/Pipfile deleted file mode 100644 index dd5b0d3..0000000 --- a/Pipfile +++ /dev/null @@ -1,16 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -pygame = "*" -screeninfo = "*" -pyaudio = "*" - -[dev-packages] -pylint = "*" -black = "*" - -[requires] -python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index 970114f..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,347 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "5ebed2aca2bde0457b0ed1d59cd639095b8dda9bf9e65f49b7586672825f05f6" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.8" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "pyaudio": { - "hashes": [ - "sha256:0f9debc6e47b6a5a4fe9da9d213d4bfe5e8096e68f0612f1b9097e3253eeea4d", - "sha256:19f654bd516154a655d9569d12d2a86ab5dfd58d039c0e4c6d1a26ec4ca02d89", - "sha256:1c29930cf2e392d8b21a4c6253efe39d7400e37d61a7991756d3b00a46bf18ce", - "sha256:2f4206c6a8d2eeb2d1f054c69e3741c8634cfafe7887be4950a2f7d273700f8a", - "sha256:55ddf5db72bc537bba5f5dbca3ab9f0222ee5b842bda83978eab0b7b8f60fb9e", - "sha256:5678725eb828742ea3febf381b1bd0bb94ba76c35e5e0daeab84e4c50f9f5d47", - "sha256:71fc1688732fced907ae707d609cc3eead9fa05baf703bf08885f71a8fd9c658", - "sha256:880aff391a73ff5e94bae73e32d3b8e27e988a93afec2dd9c74dcd92c305f8cc", - "sha256:d89f065adc0058df90ec59aa6b35c1c036f17bb4323fb68b4267c12924e9553e", - "sha256:dafe891903402694a0fc87663bdb9b89e7fa66872446c5ef0c9d71ac4780cf1d", - "sha256:ffa235c220992e417e5a462f6d73ffb1be54b683005a1c6b185139580f59e234" - ], - "index": "pypi", - "version": "==0.2.12" - }, - "pygame": { - "hashes": [ - "sha256:0427c103f741234336e5606d2fad86f5403c1a3d1dc55c309fbff3c984f0c9ae", - "sha256:07ca9f683075aea9bd977af9f09a720ebf747343d3ea8103e4f1735283b02330", - "sha256:0e06ae8e1c830f1b9c36a2bc6bb11de840232e95b78e2c349c6ed803a303be19", - "sha256:0e97d38308c441942577fea7fcd1326308bc56d6be6c024218e94d075d322e0f", - "sha256:119dee20c372c85dc47b717119534d15a60c64ceab8b0eb09278866d10486afe", - "sha256:1219a963941bd53aa754e8449364c142004fe706c33a9c22ff2a76521a82d078", - "sha256:1fddec8829e96424800c806582d73a5173b7d48946cccf7d035839ca09850db8", - "sha256:20676da24e3e3e6b9fc4eecc7ba09d77ef46c3a83a028763ba1d222476c2e3fb", - "sha256:2405414d8c572668e04739875661e030a0c588e197fa95463fe301c3d0a0510b", - "sha256:24254c4244f0d9bdc904f5d3f38e86757ca4c6aa0e44a6d55ef5e016bc7274d6", - "sha256:24b4f7f30fa2b3d092b60be6fcc725fb91d569fc87a9bcc91614ee8b0c005726", - "sha256:3bb0674aa789848ddc264bfc60c54965bf3bb659c141de4f600e379acc9b944c", - "sha256:3c8d6637ff75351e581327efefa9d04eeb0f257b533392b6cc6b15ceca4f7c5e", - "sha256:40e4d8d65985bb467d9c5a1305fb53fd6820c61d764979600becab973339676f", - "sha256:4aa3ae32320cc704d63e185864e44f6265c2a6e52c9384afe152cc3d51b3a2ef", - "sha256:50d9a21edd551669862c27c9272747401b20b1939abaacb842c08ea1cdd1c04d", - "sha256:5c7600bf307de1ca1dca0cc7840e34604d5b0b0a5a5dad345c3fa62b054b886d", - "sha256:5d0c14152d0ca8ef5fbcc5ed9981462bdf59a9ae85a291e62d8a8d0b7e5cbe43", - "sha256:5e88b0d4338b94960686f59396f23f7f684fed4859fcc3b9f40286d72c1c61af", - "sha256:5ebbefb8b576572c8fc97a3321d37dc2b4afea6b6e3877a67f7158d8c2c4cefe", - "sha256:636f51f56615d67459b11918206bb4da30cd7d7042027bf997c218ccd6c77902", - "sha256:660c80c0b2e80f1f801715583b759fb4c7bc0c11eb3b534e89c9fc4bfbc38acd", - "sha256:6ecda8dd4583982bb65f9c682f244a5e94524dcf628379766227e9ed97201a49", - "sha256:754c2906f2ef47173a14493e1de116b2a56a2c8e1764f1202ba844d080248a5b", - "sha256:7889dce887ec83c9a0bef8d9eb3669d8863fdaf37c45bacec707d8ad90b24a38", - "sha256:7fdb93b4282962c9a2ebf1af994ee698be823dd913218ed97a5f2fb372b10b66", - "sha256:8e87716114e97322fb177e223d889a4be369a0f73212f4f8507fe0cd43253b23", - "sha256:93c4cbfc942dd00410eaa9e84252129f9f9993f37f683006d7b49ab245342254", - "sha256:9649419254d3282dae41f23837de4108b17bc62187c3acd8af2ae3801b765cbd", - "sha256:97a74ba186deee68318a52637012ef6abf5be6282c659e1d1ba6ad08cf35ec85", - "sha256:9d6452419e01a0f848aed0597f69fd10a4c2a7750c15d1b0607f86090a39dcf3", - "sha256:9d7b021b8dde5d528363e474bc18bd6f79a9666eef89fb4859bcb8f0a536c9de", - "sha256:a0ccf8e3dce7ca67d523a6020b7e3dbf4b26797a9a8db5cc4c7b5ef20fb64701", - "sha256:a56a811d8821f7b9a594e3d0e0dd8bd39b25e3eea8963d5963263b90fd2ea5c2", - "sha256:c5ea87da5fe4b6164c3854f3b0c9146811dbad0dd7fa74297683dfacc485ae1c", - "sha256:c99b95e62cdda29c2e60235d7763447c168a6a877403e6f9ca5b2e2bb297c2ce", - "sha256:c9ce7f3d8af14d7e04eb7eb41c5e5313c43508c252bb2b9eb53e51fc87ada9fd", - "sha256:ca5ef1315fa67c241a657ab077be44f230c05740c95f0b46409457dceefdc7e5", - "sha256:d2d3c50ee9847b743db6cd7b1bb17a94c2c2abc16679d70f5e745cabdf19e655", - "sha256:d6d0eca28f886f0477cd0721ac688189155a587f2bb8eae740e52ca56c3ad23c", - "sha256:dad6bf3fdd3752d7519422f3732be779b98fe7c87d32c3efe2fdffdcbeebb6ca", - "sha256:db2f40d5a75fd9cdda473c58b0d8b294da6e0179f00bb3b1fc2f7f29cac09bea", - "sha256:dc4444d61d48c5546df5137cdf81554887ddb6e2ef1be7f51eb77ea3b6bdd56f", - "sha256:dcc285ee1f1d0e2672cc52f880fd3f564b1505de710e817f692fbf64a72ca657", - "sha256:dd528dbb91eca16f7522c975d0f9e94b95f6b5024c82c3247dc0383d242d33c6", - "sha256:e09044e9e1aa8512d6a9c7ce5f94b881824bcfc401105f3c24f546dfc3bb4aa5", - "sha256:e18c9466131378421d00fc40b637425229238d506a073d9c537b230b355a25d6", - "sha256:e1bb25986db77a48f632469c6bc61baf7508ce945aa6161c02180d4ee5ac5b8d", - "sha256:e4b4cd440d50a9f8551b8989e856aab175593af07eb825cad22fd2f8f6f2ffce", - "sha256:e627300a66a90651fb39e41601d447b1fdbbfffca3f08ef0278d6cc0436b2160", - "sha256:e7a8e18677e0064b7a422f6653a622652d932826a27e50f279d55a8b122a1a83", - "sha256:e8632f6b2ddb90f6f3950744bd65d5ef15af615e3034057fa30ff836f48a7179", - "sha256:ea36f4f93524554a35cac2359df63b50af6556ed866830aa1f07f0d8580280ea", - "sha256:f149e182d0eeef15d8a9b4c9dad1b87dc6eba3a99bd3c44a777a3a2b053a3dca", - "sha256:fc2e5db54491e8f27785fc5204c96f540d3557dcf5b0a9a857b6594d6b32561b", - "sha256:fc30e834f65b893d1b4c230070183bf98e6b70c41c1511687e8436a33d5ce49d", - "sha256:fcc9586e17875c0cdf8764597955f9daa979098fd4f80be07ed68276ac225480", - "sha256:ff961c3280d6ee5f4163f4772f963d7a4dbe42e36c6dd54b79ad436c1f046e5d" - ], - "index": "pypi", - "version": "==2.1.2" - }, - "screeninfo": { - "hashes": [ - "sha256:9501bf8b8458c7d1be4cb0ac9abddddfa80b932fb3f65bfcb54f5586434b1dc5", - "sha256:dac455fbed79e82c481d59a00962f543e5a9bf3c2cc9f0e48e2714eb8d3cec23" - ], - "index": "pypi", - "version": "==0.8" - } - }, - "develop": { - "astroid": { - "hashes": [ - "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b", - "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946" - ], - "markers": "python_full_version >= '3.6.2'", - "version": "==2.11.7" - }, - "black": { - "hashes": [ - "sha256:2818cf72dfd5d289e48f37ccfa08b460bf469e67fb7c4abb07edc2e9f16fb63f", - "sha256:41622020d7120e01d377f74249e677039d20e6344ff5851de8a10f11f513bf93", - "sha256:4acf672def7eb1725f41f38bf6bf425c8237248bb0804faa3965c036f7672d11", - "sha256:4be5bb28e090456adfc1255e03967fb67ca846a03be7aadf6249096100ee32d0", - "sha256:4f1373a7808a8f135b774039f61d59e4be7eb56b2513d3d2f02a8b9365b8a8a9", - "sha256:56f52cfbd3dabe2798d76dbdd299faa046a901041faf2cf33288bc4e6dae57b5", - "sha256:65b76c275e4c1c5ce6e9870911384bff5ca31ab63d19c76811cb1fb162678213", - "sha256:65c02e4ea2ae09d16314d30912a58ada9a5c4fdfedf9512d23326128ac08ac3d", - "sha256:6905238a754ceb7788a73f02b45637d820b2f5478b20fec82ea865e4f5d4d9f7", - "sha256:79dcf34b33e38ed1b17434693763301d7ccbd1c5860674a8f871bd15139e7837", - "sha256:7bb041dca0d784697af4646d3b62ba4a6b028276ae878e53f6b4f74ddd6db99f", - "sha256:7d5e026f8da0322b5662fa7a8e752b3fa2dac1c1cbc213c3d7ff9bdd0ab12395", - "sha256:9f50ea1132e2189d8dff0115ab75b65590a3e97de1e143795adb4ce317934995", - "sha256:a0c9c4a0771afc6919578cec71ce82a3e31e054904e7197deacbc9382671c41f", - "sha256:aadf7a02d947936ee418777e0247ea114f78aff0d0959461057cae8a04f20597", - "sha256:b5991d523eee14756f3c8d5df5231550ae8993e2286b8014e2fdea7156ed0959", - "sha256:bf21b7b230718a5f08bd32d5e4f1db7fc8788345c8aea1d155fc17852b3410f5", - "sha256:c45f8dff244b3c431b36e3224b6be4a127c6aca780853574c00faf99258041eb", - "sha256:c7ed6668cbbfcd231fa0dc1b137d3e40c04c7f786e626b405c62bcd5db5857e4", - "sha256:d7de8d330763c66663661a1ffd432274a2f92f07feeddd89ffd085b5744f85e7", - "sha256:e19cb1c6365fd6dc38a6eae2dcb691d7d83935c10215aef8e6c38edee3f77abd", - "sha256:e2af80566f43c85f5797365077fb64a393861a3730bd110971ab7a0c94e873e7" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.3.0" - }, - "click": { - "hashes": [ - "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", - "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" - ], - "markers": "python_version >= '3.7'", - "version": "==8.1.7" - }, - "dill": { - "hashes": [ - "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0", - "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==0.3.6" - }, - "isort": { - "hashes": [ - "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6", - "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==5.11.4" - }, - "lazy-object-proxy": { - "hashes": [ - "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada", - "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d", - "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7", - "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe", - "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd", - "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c", - "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858", - "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288", - "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec", - "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f", - "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891", - "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c", - "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25", - "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156", - "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8", - "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f", - "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e", - "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0", - "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==1.8.0" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "mypy-extensions": { - "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" - }, - "packaging": { - "hashes": [ - "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002", - "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124" - ], - "markers": "python_version >= '3.8'", - "version": "==24.1" - }, - "pathspec": { - "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" - ], - "markers": "python_version >= '3.8'", - "version": "==0.12.1" - }, - "platformdirs": { - "hashes": [ - "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee", - "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3" - ], - "markers": "python_version >= '3.8'", - "version": "==4.2.2" - }, - "pylint": { - "hashes": [ - "sha256:487ce2192eee48211269a0e976421f334cf94de1806ca9d0a99449adcdf0285e", - "sha256:fabe30000de7d07636d2e82c9a518ad5ad7908590fe135ace169b44839c15f90" - ], - "index": "pypi", - "version": "==2.14.5" - }, - "setuptools": { - "hashes": [ - "sha256:d0b9a8433464d5800cbe05094acf5c6d52a91bfac9b52bcfc4d41382be5d5d31", - "sha256:e197a19aa8ec9722928f2206f8de752def0e4c9fc6953527360d1c36d94ddb2f" - ], - "index": "pypi", - "version": "==65.5.1" - }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "markers": "python_version < '3.11'", - "version": "==2.0.1" - }, - "tomlkit": { - "hashes": [ - "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b", - "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73" - ], - "markers": "python_version >= '3.6'", - "version": "==0.11.6" - }, - "typing-extensions": { - "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" - ], - "markers": "python_version < '3.11'", - "version": "==4.12.2" - }, - "wrapt": { - "hashes": [ - "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3", - "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b", - "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4", - "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2", - "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656", - "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3", - "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff", - "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310", - "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a", - "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57", - "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069", - "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383", - "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe", - "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87", - "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d", - "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b", - "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907", - "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f", - "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0", - "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28", - "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1", - "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853", - "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc", - "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3", - "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3", - "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164", - "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1", - "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c", - "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1", - "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7", - "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1", - "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320", - "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed", - "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1", - "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248", - "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c", - "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456", - "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77", - "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef", - "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1", - "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7", - "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86", - "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4", - "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d", - "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d", - "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8", - "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5", - "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471", - "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00", - "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68", - "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3", - "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d", - "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735", - "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d", - "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569", - "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7", - "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59", - "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5", - "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb", - "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b", - "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f", - "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462", - "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015", - "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.14.1" - } - } -} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..789f036 --- /dev/null +++ b/poetry.lock @@ -0,0 +1,361 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "astroid" +version = "3.2.2" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "astroid-3.2.2-py3-none-any.whl", hash = "sha256:e8a0083b4bb28fcffb6207a3bfc9e5d0a68be951dd7e336d5dcf639c682388c0"}, + {file = "astroid-3.2.2.tar.gz", hash = "sha256:8ead48e31b92b2e217b6c9733a21afafe479d52d6e164dd25fb1a770c7c3cf94"}, +] + +[[package]] +name = "black" +version = "23.12.1" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.12.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e0aaf6041986767a5e0ce663c7a2f0e9eaf21e6ff87a5f95cbf3675bfd4c41d2"}, + {file = "black-23.12.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c88b3711d12905b74206227109272673edce0cb29f27e1385f33b0163c414bba"}, + {file = "black-23.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a920b569dc6b3472513ba6ddea21f440d4b4c699494d2e972a1753cdc25df7b0"}, + {file = "black-23.12.1-cp310-cp310-win_amd64.whl", hash = "sha256:3fa4be75ef2a6b96ea8d92b1587dd8cb3a35c7e3d51f0738ced0781c3aa3a5a3"}, + {file = "black-23.12.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8d4df77958a622f9b5a4c96edb4b8c0034f8434032ab11077ec6c56ae9f384ba"}, + {file = "black-23.12.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:602cfb1196dc692424c70b6507593a2b29aac0547c1be9a1d1365f0d964c353b"}, + {file = "black-23.12.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c4352800f14be5b4864016882cdba10755bd50805c95f728011bcb47a4afd59"}, + {file = "black-23.12.1-cp311-cp311-win_amd64.whl", hash = "sha256:0808494f2b2df923ffc5723ed3c7b096bd76341f6213989759287611e9837d50"}, + {file = "black-23.12.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:25e57fd232a6d6ff3f4478a6fd0580838e47c93c83eaf1ccc92d4faf27112c4e"}, + {file = "black-23.12.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2d9e13db441c509a3763a7a3d9a49ccc1b4e974a47be4e08ade2a228876500ec"}, + {file = "black-23.12.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1bd9c210f8b109b1762ec9fd36592fdd528485aadb3f5849b2740ef17e674e"}, + {file = "black-23.12.1-cp312-cp312-win_amd64.whl", hash = "sha256:ae76c22bde5cbb6bfd211ec343ded2163bba7883c7bc77f6b756a1049436fbb9"}, + {file = "black-23.12.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1fa88a0f74e50e4487477bc0bb900c6781dbddfdfa32691e780bf854c3b4a47f"}, + {file = "black-23.12.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a4d6a9668e45ad99d2f8ec70d5c8c04ef4f32f648ef39048d010b0689832ec6d"}, + {file = "black-23.12.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b18fb2ae6c4bb63eebe5be6bd869ba2f14fd0259bda7d18a46b764d8fb86298a"}, + {file = "black-23.12.1-cp38-cp38-win_amd64.whl", hash = "sha256:c04b6d9d20e9c13f43eee8ea87d44156b8505ca8a3c878773f68b4e4812a421e"}, + {file = "black-23.12.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e1b38b3135fd4c025c28c55ddfc236b05af657828a8a6abe5deec419a0b7055"}, + {file = "black-23.12.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4f0031eaa7b921db76decd73636ef3a12c942ed367d8c3841a0739412b260a54"}, + {file = "black-23.12.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:97e56155c6b737854e60a9ab1c598ff2533d57e7506d97af5481141671abf3ea"}, + {file = "black-23.12.1-cp39-cp39-win_amd64.whl", hash = "sha256:dd15245c8b68fe2b6bd0f32c1556509d11bb33aec9b5d0866dd8e2ed3dba09c2"}, + {file = "black-23.12.1-py3-none-any.whl", hash = "sha256:78baad24af0f033958cad29731e27363183e140962595def56423e626f4bee3e"}, + {file = "black-23.12.1.tar.gz", hash = "sha256:4ce3ef14ebe8d9509188014d96af1c456a910d5b5cbf434a09fef7e024b3d0d5"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)", "aiohttp (>=3.7.4,!=3.9.0)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.3.8" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.3.8-py3-none-any.whl", hash = "sha256:c36ca9ffb54365bdd2f8eb3eff7d2a21237f8452b57ace88b1ac615b7e815bd7"}, + {file = "dill-0.3.8.tar.gz", hash = "sha256:3ebe3c479ad625c4553aca177444d89b486b1d84982eeacded644afc0cf797ca"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "numpy" +version = "2.0.0" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:04494f6ec467ccb5369d1808570ae55f6ed9b5809d7f035059000a37b8d7e86f"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2635dbd200c2d6faf2ef9a0d04f0ecc6b13b3cad54f7c67c61155138835515d2"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:0a43f0974d501842866cc83471bdb0116ba0dffdbaac33ec05e6afed5b615238"}, + {file = "numpy-2.0.0-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:8d83bb187fb647643bd56e1ae43f273c7f4dbcdf94550d7938cfc32566756514"}, + {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79e843d186c8fb1b102bef3e2bc35ef81160ffef3194646a7fdd6a73c6b97196"}, + {file = "numpy-2.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d7696c615765091cc5093f76fd1fa069870304beaccfd58b5dcc69e55ef49c1"}, + {file = "numpy-2.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b4c76e3d4c56f145d41b7b6751255feefae92edbc9a61e1758a98204200f30fc"}, + {file = "numpy-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:acd3a644e4807e73b4e1867b769fbf1ce8c5d80e7caaef0d90dcdc640dfc9787"}, + {file = "numpy-2.0.0-cp310-cp310-win32.whl", hash = "sha256:cee6cc0584f71adefe2c908856ccc98702baf95ff80092e4ca46061538a2ba98"}, + {file = "numpy-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:ed08d2703b5972ec736451b818c2eb9da80d66c3e84aed1deeb0c345fefe461b"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad0c86f3455fbd0de6c31a3056eb822fc939f81b1618f10ff3406971893b62a5"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e7f387600d424f91576af20518334df3d97bc76a300a755f9a8d6e4f5cadd289"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:34f003cb88b1ba38cb9a9a4a3161c1604973d7f9d5552c38bc2f04f829536609"}, + {file = "numpy-2.0.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:b6f6a8f45d0313db07d6d1d37bd0b112f887e1369758a5419c0370ba915b3871"}, + {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f64641b42b2429f56ee08b4f427a4d2daf916ec59686061de751a55aafa22e4"}, + {file = "numpy-2.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a7039a136017eaa92c1848152827e1424701532ca8e8967fe480fe1569dae581"}, + {file = "numpy-2.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46e161722e0f619749d1cd892167039015b2c2817296104487cd03ed4a955995"}, + {file = "numpy-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0e50842b2295ba8414c8c1d9d957083d5dfe9e16828b37de883f51fc53c4016f"}, + {file = "numpy-2.0.0-cp311-cp311-win32.whl", hash = "sha256:2ce46fd0b8a0c947ae047d222f7136fc4d55538741373107574271bc00e20e8f"}, + {file = "numpy-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd6acc766814ea6443628f4e6751d0da6593dae29c08c0b2606164db026970c"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:354f373279768fa5a584bac997de6a6c9bc535c482592d7a813bb0c09be6c76f"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d2f62e55a4cd9c58c1d9a1c9edaedcd857a73cb6fda875bf79093f9d9086f85"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:1e72728e7501a450288fc8e1f9ebc73d90cfd4671ebbd631f3e7857c39bd16f2"}, + {file = "numpy-2.0.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:84554fc53daa8f6abf8e8a66e076aff6ece62de68523d9f665f32d2fc50fd66e"}, + {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c73aafd1afca80afecb22718f8700b40ac7cab927b8abab3c3e337d70e10e5a2"}, + {file = "numpy-2.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49d9f7d256fbc804391a7f72d4a617302b1afac1112fac19b6c6cec63fe7fe8a"}, + {file = "numpy-2.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0ec84b9ba0654f3b962802edc91424331f423dcf5d5f926676e0150789cb3d95"}, + {file = "numpy-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:feff59f27338135776f6d4e2ec7aeeac5d5f7a08a83e80869121ef8164b74af9"}, + {file = "numpy-2.0.0-cp312-cp312-win32.whl", hash = "sha256:c5a59996dc61835133b56a32ebe4ef3740ea5bc19b3983ac60cc32be5a665d54"}, + {file = "numpy-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:a356364941fb0593bb899a1076b92dfa2029f6f5b8ba88a14fd0984aaf76d0df"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e61155fae27570692ad1d327e81c6cf27d535a5d7ef97648a17d922224b216de"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4554eb96f0fd263041baf16cf0881b3f5dafae7a59b1049acb9540c4d57bc8cb"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_14_0_arm64.whl", hash = "sha256:903703372d46bce88b6920a0cd86c3ad82dae2dbef157b5fc01b70ea1cfc430f"}, + {file = "numpy-2.0.0-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:3e8e01233d57639b2e30966c63d36fcea099d17c53bf424d77f088b0f4babd86"}, + {file = "numpy-2.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1cde1753efe513705a0c6d28f5884e22bdc30438bf0085c5c486cdaff40cd67a"}, + {file = "numpy-2.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:821eedb7165ead9eebdb569986968b541f9908979c2da8a4967ecac4439bae3d"}, + {file = "numpy-2.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a1712c015831da583b21c5bfe15e8684137097969c6d22e8316ba66b5baabe4"}, + {file = "numpy-2.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9c27f0946a3536403efb0e1c28def1ae6730a72cd0d5878db38824855e3afc44"}, + {file = "numpy-2.0.0-cp39-cp39-win32.whl", hash = "sha256:63b92c512d9dbcc37f9d81b123dec99fdb318ba38c8059afc78086fe73820275"}, + {file = "numpy-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:3f6bed7f840d44c08ebdb73b1825282b801799e325bcbdfa6bc5c370e5aecc65"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9416a5c2e92ace094e9f0082c5fd473502c91651fb896bc17690d6fc475128d6"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:17067d097ed036636fa79f6a869ac26df7db1ba22039d962422506640314933a"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ecb5b0582cd125f67a629072fed6f83562d9dd04d7e03256c9829bdec027ad"}, + {file = "numpy-2.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:cef04d068f5fb0518a77857953193b6bb94809a806bd0a14983a8f12ada060c9"}, + {file = "numpy-2.0.0.tar.gz", hash = "sha256:cf5d1c9e6837f8af9f92b6bd3e86d513cdc11f60fd62185cc49ec7d1aba34864"}, +] + +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"}, + {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"}, +] + +[[package]] +name = "pillow" +version = "10.3.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pillow-10.3.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:90b9e29824800e90c84e4022dd5cc16eb2d9605ee13f05d47641eb183cd73d45"}, + {file = "pillow-10.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a2c405445c79c3f5a124573a051062300936b0281fee57637e706453e452746c"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78618cdbccaa74d3f88d0ad6cb8ac3007f1a6fa5c6f19af64b55ca170bfa1edf"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261ddb7ca91fcf71757979534fb4c128448b5b4c55cb6152d280312062f69599"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ce49c67f4ea0609933d01c0731b34b8695a7a748d6c8d186f95e7d085d2fe475"}, + {file = "pillow-10.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b14f16f94cbc61215115b9b1236f9c18403c15dd3c52cf629072afa9d54c1cbf"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d33891be6df59d93df4d846640f0e46f1a807339f09e79a8040bc887bdcd7ed3"}, + {file = "pillow-10.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b50811d664d392f02f7761621303eba9d1b056fb1868c8cdf4231279645c25f5"}, + {file = "pillow-10.3.0-cp310-cp310-win32.whl", hash = "sha256:ca2870d5d10d8726a27396d3ca4cf7976cec0f3cb706debe88e3a5bd4610f7d2"}, + {file = "pillow-10.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:f0d0591a0aeaefdaf9a5e545e7485f89910c977087e7de2b6c388aec32011e9f"}, + {file = "pillow-10.3.0-cp310-cp310-win_arm64.whl", hash = "sha256:ccce24b7ad89adb5a1e34a6ba96ac2530046763912806ad4c247356a8f33a67b"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:5f77cf66e96ae734717d341c145c5949c63180842a545c47a0ce7ae52ca83795"}, + {file = "pillow-10.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e4b878386c4bf293578b48fc570b84ecfe477d3b77ba39a6e87150af77f40c57"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdcbb4068117dfd9ce0138d068ac512843c52295ed996ae6dd1faf537b6dbc27"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9797a6c8fe16f25749b371c02e2ade0efb51155e767a971c61734b1bf6293994"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:9e91179a242bbc99be65e139e30690e081fe6cb91a8e77faf4c409653de39451"}, + {file = "pillow-10.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1b87bd9d81d179bd8ab871603bd80d8645729939f90b71e62914e816a76fc6bd"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81d09caa7b27ef4e61cb7d8fbf1714f5aec1c6b6c5270ee53504981e6e9121ad"}, + {file = "pillow-10.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:048ad577748b9fa4a99a0548c64f2cb8d672d5bf2e643a739ac8faff1164238c"}, + {file = "pillow-10.3.0-cp311-cp311-win32.whl", hash = "sha256:7161ec49ef0800947dc5570f86568a7bb36fa97dd09e9827dc02b718c5643f09"}, + {file = "pillow-10.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:8eb0908e954d093b02a543dc963984d6e99ad2b5e36503d8a0aaf040505f747d"}, + {file = "pillow-10.3.0-cp311-cp311-win_arm64.whl", hash = "sha256:4e6f7d1c414191c1199f8996d3f2282b9ebea0945693fb67392c75a3a320941f"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:e46f38133e5a060d46bd630faa4d9fa0202377495df1f068a8299fd78c84de84"}, + {file = "pillow-10.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:50b8eae8f7334ec826d6eeffaeeb00e36b5e24aa0b9df322c247539714c6df19"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d3bea1c75f8c53ee4d505c3e67d8c158ad4df0d83170605b50b64025917f338"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19aeb96d43902f0a783946a0a87dbdad5c84c936025b8419da0a0cd7724356b1"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74d28c17412d9caa1066f7a31df8403ec23d5268ba46cd0ad2c50fb82ae40462"}, + {file = "pillow-10.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:ff61bfd9253c3915e6d41c651d5f962da23eda633cf02262990094a18a55371a"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d886f5d353333b4771d21267c7ecc75b710f1a73d72d03ca06df49b09015a9ef"}, + {file = "pillow-10.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b5ec25d8b17217d635f8935dbc1b9aa5907962fae29dff220f2659487891cd3"}, + {file = "pillow-10.3.0-cp312-cp312-win32.whl", hash = "sha256:51243f1ed5161b9945011a7360e997729776f6e5d7005ba0c6879267d4c5139d"}, + {file = "pillow-10.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:412444afb8c4c7a6cc11a47dade32982439925537e483be7c0ae0cf96c4f6a0b"}, + {file = "pillow-10.3.0-cp312-cp312-win_arm64.whl", hash = "sha256:798232c92e7665fe82ac085f9d8e8ca98826f8e27859d9a96b41d519ecd2e49a"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:4eaa22f0d22b1a7e93ff0a596d57fdede2e550aecffb5a1ef1106aaece48e96b"}, + {file = "pillow-10.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cd5e14fbf22a87321b24c88669aad3a51ec052eb145315b3da3b7e3cc105b9a2"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1530e8f3a4b965eb6a7785cf17a426c779333eb62c9a7d1bbcf3ffd5bf77a4aa"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d512aafa1d32efa014fa041d38868fda85028e3f930a96f85d49c7d8ddc0383"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:339894035d0ede518b16073bdc2feef4c991ee991a29774b33e515f1d308e08d"}, + {file = "pillow-10.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:aa7e402ce11f0885305bfb6afb3434b3cd8f53b563ac065452d9d5654c7b86fd"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0ea2a783a2bdf2a561808fe4a7a12e9aa3799b701ba305de596bc48b8bdfce9d"}, + {file = "pillow-10.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c78e1b00a87ce43bb37642c0812315b411e856a905d58d597750eb79802aaaa3"}, + {file = "pillow-10.3.0-cp38-cp38-win32.whl", hash = "sha256:72d622d262e463dfb7595202d229f5f3ab4b852289a1cd09650362db23b9eb0b"}, + {file = "pillow-10.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:2034f6759a722da3a3dbd91a81148cf884e91d1b747992ca288ab88c1de15999"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2ed854e716a89b1afcedea551cd85f2eb2a807613752ab997b9974aaa0d56936"}, + {file = "pillow-10.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:dc1a390a82755a8c26c9964d457d4c9cbec5405896cba94cf51f36ea0d855002"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4203efca580f0dd6f882ca211f923168548f7ba334c189e9eab1178ab840bf60"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3102045a10945173d38336f6e71a8dc71bcaeed55c3123ad4af82c52807b9375"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:6fb1b30043271ec92dc65f6d9f0b7a830c210b8a96423074b15c7bc999975f57"}, + {file = "pillow-10.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:1dfc94946bc60ea375cc39cff0b8da6c7e5f8fcdc1d946beb8da5c216156ddd8"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b09b86b27a064c9624d0a6c54da01c1beaf5b6cadfa609cf63789b1d08a797b9"}, + {file = "pillow-10.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d3b2348a78bc939b4fed6552abfd2e7988e0f81443ef3911a4b8498ca084f6eb"}, + {file = "pillow-10.3.0-cp39-cp39-win32.whl", hash = "sha256:45ebc7b45406febf07fef35d856f0293a92e7417ae7933207e90bf9090b70572"}, + {file = "pillow-10.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:0ba26351b137ca4e0db0342d5d00d2e355eb29372c05afd544ebf47c0956ffeb"}, + {file = "pillow-10.3.0-cp39-cp39-win_arm64.whl", hash = "sha256:50fd3f6b26e3441ae07b7c979309638b72abc1a25da31a81a7fbd9495713ef4f"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:6b02471b72526ab8a18c39cb7967b72d194ec53c1fd0a70b050565a0f366d355"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8ab74c06ffdab957d7670c2a5a6e1a70181cd10b727cd788c4dd9005b6a8acd9"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:048eeade4c33fdf7e08da40ef402e748df113fd0b4584e32c4af74fe78baaeb2"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e2ec1e921fd07c7cda7962bad283acc2f2a9ccc1b971ee4b216b75fad6f0463"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c8e73e99da7db1b4cad7f8d682cf6abad7844da39834c288fbfa394a47bbced"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:16563993329b79513f59142a6b02055e10514c1a8e86dca8b48a893e33cf91e3"}, + {file = "pillow-10.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:dd78700f5788ae180b5ee8902c6aea5a5726bac7c364b202b4b3e3ba2d293170"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aff76a55a8aa8364d25400a210a65ff59d0168e0b4285ba6bf2bd83cf675ba32"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b7bc2176354defba3edc2b9a777744462da2f8e921fbaf61e52acb95bafa9828"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:793b4e24db2e8742ca6423d3fde8396db336698c55cd34b660663ee9e45ed37f"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93480005693d247f8346bc8ee28c72a2191bdf1f6b5db469c096c0c867ac015"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:c83341b89884e2b2e55886e8fbbf37c3fa5efd6c8907124aeb72f285ae5696e5"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1a1d1915db1a4fdb2754b9de292642a39a7fb28f1736699527bb649484fb966a"}, + {file = "pillow-10.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a0eaa93d054751ee9964afa21c06247779b90440ca41d184aeb5d410f20ff591"}, + {file = "pillow-10.3.0.tar.gz", hash = "sha256:9d2455fbf44c914840c793e89aa82d0e1763a14253a000743719ae5946814b2d"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +fpx = ["olefile"] +mic = ["olefile"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +typing = ["typing-extensions"] +xmp = ["defusedxml"] + +[[package]] +name = "platformdirs" +version = "4.2.2" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] +type = ["mypy (>=1.8)"] + +[[package]] +name = "pyglet" +version = "2.0.15" +description = "pyglet is a cross-platform games and multimedia package." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyglet-2.0.15-py3-none-any.whl", hash = "sha256:9e4cc16efc308106fd3a9ff8f04e7a6f4f6a807c6ac8a331375efbbac8be85af"}, + {file = "pyglet-2.0.15.tar.gz", hash = "sha256:42085567cece0c7f1c14e36eef799938cbf528cfbb0150c484b984f3ff1aa771"}, +] + +[[package]] +name = "pylint" +version = "3.2.2" +description = "python code static checker" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "pylint-3.2.2-py3-none-any.whl", hash = "sha256:3f8788ab20bb8383e06dd2233e50f8e08949cfd9574804564803441a4946eab4"}, + {file = "pylint-3.2.2.tar.gz", hash = "sha256:d068ca1dfd735fb92a07d33cb8f288adc0f6bc1287a139ca2425366f7cbe38f8"}, +] + +[package.dependencies] +astroid = ">=3.2.2,<=3.3.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""} +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "tomlkit" +version = "0.12.5" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, + {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.12" +content-hash = "8f3885fb79331675ca3bcf580fe01aa8387fa0058e5940721e6b4e5adeb236f8" diff --git a/src/audio/__init__.py b/pyoro/__init__.py similarity index 100% rename from src/audio/__init__.py rename to pyoro/__init__.py diff --git a/pyoro/activity/__init__.py b/pyoro/activity/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/activity/activities/__init__.py b/pyoro/activity/activities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/activity/activities/activity.py b/pyoro/activity/activities/activity.py new file mode 100644 index 0000000..6706244 --- /dev/null +++ b/pyoro/activity/activities/activity.py @@ -0,0 +1,27 @@ +from pyglet import event, clock + +from pyoro.views.view import View + + +class Activity(event.EventDispatcher): + def __init__(self) -> None: + self.running = False + + self.view: View | None = None + + self.register_event_type("on_start") # type: ignore + self.register_event_type("on_stop") # type: ignore + + def start(self): + self.running = True + + def update_view(_dt: float) -> None: + if self.view: + self.view.refresh() + + clock.schedule(update_view) # type: ignore + self.dispatch_event("on_start") # type: ignore + + def stop(self): + self.running = False + self.dispatch_event("on_stop") # type: ignore diff --git a/pyoro/activity/activities/game_activity.py b/pyoro/activity/activities/game_activity.py new file mode 100644 index 0000000..b5cd6c2 --- /dev/null +++ b/pyoro/activity/activities/game_activity.py @@ -0,0 +1,21 @@ +import logging + +from pyoro.activity.activities.activity import Activity +from pyoro.game.controllers.user_controller import UserController +from pyoro.game.game_engine import GameEngine +from pyoro.game.game_state import GameMode +from pyoro.views.game_view import GameView + + +class GameActivity(Activity): + def __init__(self, game_mode: GameMode): + super().__init__() + + self.controller = UserController() + self.game_engine = GameEngine(game_mode, self.controller) + self.view = GameView(self.game_engine) + + def start(self) -> None: + logging.info("Starting") + self.game_engine.run() + return super().start() diff --git a/pyoro/activity/activities/main_menu_activity.py b/pyoro/activity/activities/main_menu_activity.py new file mode 100644 index 0000000..0d10930 --- /dev/null +++ b/pyoro/activity/activities/main_menu_activity.py @@ -0,0 +1,37 @@ +import logging + +from pyoro.activity.activities.activity import Activity +from pyoro.activity.activities.game_activity import GameActivity +from pyoro.activity.activities.settings_activity import SettingsActivity +from pyoro.activity.activity_manager import ActivityManager +from pyoro.game.game_engine import GameEngine +from pyoro.game.game_state import GameMode +from pyoro.views.main_menu_view import MainMenuView + + +class MainMenuActivity(Activity): + def __init__(self): + super().__init__() + self.game_engine = GameEngine(GameMode.TONGUE) + self.view = MainMenuView( + self.game_engine, self.on_play, self.on_show_settings, self.on_quit + ) + + def start(self) -> None: + logging.info("Starting") + self.game_engine.run() + return super().start() + + def on_play(self, mode: GameMode) -> None: + activity_manager = ActivityManager() + activity_manager.push_activity(GameActivity(mode)) + self.stop() + + def on_show_settings(self) -> None: + activity_manager = ActivityManager() + activity_manager.push_activity(SettingsActivity()) + self.stop() + + def on_quit(self) -> None: + activity_manager = ActivityManager() + activity_manager.stop() diff --git a/pyoro/activity/activities/settings_activity.py b/pyoro/activity/activities/settings_activity.py new file mode 100644 index 0000000..04a935a --- /dev/null +++ b/pyoro/activity/activities/settings_activity.py @@ -0,0 +1,7 @@ +import logging +from pyoro.activity.activities.activity import Activity + + +class SettingsActivity(Activity): + def start(self): + logging.info("Starting") diff --git a/pyoro/activity/activity_manager.py b/pyoro/activity/activity_manager.py new file mode 100644 index 0000000..a757673 --- /dev/null +++ b/pyoro/activity/activity_manager.py @@ -0,0 +1,52 @@ +import logging +import pyglet + +from pyoro.activity.activities.activity import Activity +from pyoro.graphics.window import Window +from pyoro.utils.singleton import singleton + + +@singleton +class ActivityManager: + def __init__(self): + self._activities: list[Activity] = [] + self._current_activity: Activity | None = None + + window = Window() + window.push_handlers(on_close=self.stop) # type: ignore + + def push_activity(self, activity: Activity) -> None: + logging.debug( + f"New activity of type {activity.__class__.__name__} added to the stack" + ) + self._activities.append(activity) + + def on_activity_stop(self) -> None: + logging.info("Current activity stopped. Starting next activity") + + self._current_activity.pop_handlers() # type: ignore + + if self._activities: + self.set_current_activity(self._activities.pop(0)) + else: + logging.info("No activity left on stack") + self.stop() + + def set_current_activity(self, activity: Activity) -> None: + self._current_activity = activity + self._current_activity.push_handlers(on_stop=self.on_activity_stop) # type: ignore + self._current_activity.start() + + def start(self) -> None: + logging.info("Starting") + + if not self._activities: + logging.warn("No activity to start") + return self.stop() + self.set_current_activity(self._activities.pop(0)) + + pyglet.app.run() + + def stop(self) -> None: + logging.info("Stopping") + pyglet.app.exit() diff --git a/pyoro/banks/__init__.py b/pyoro/banks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/banks/animation_bank.py b/pyoro/banks/animation_bank.py new file mode 100644 index 0000000..16db979 --- /dev/null +++ b/pyoro/banks/animation_bank.py @@ -0,0 +1,70 @@ +import logging +import pyglet +from pyoro.banks.bank import Bank +from pyoro.banks.image_bank import ImageBank +from pyoro.utils.singleton import singleton + +ANIMATION_IDS: dict[str, tuple[tuple[str, float], ...]] = { + "bean_green": ( + ("bean_green_left", 0.4), + ("bean_green_middle", 0.4), + ("bean_green_right", 0.4), + ("bean_green_middle", 0.4), + ), + "bean_pink": ( + ("bean_pink_left", 0.4), + ("bean_pink_middle", 0.4), + ("bean_pink_right", 0.4), + ("bean_pink_middle", 0.4), + ), + "explosion": ( + ("explosion_0", 0.4), + ("explosion_1", 0.4), + ("explosion_2", 0.4), + ), + "score_300": ( + ("score_300_0", 0.05), + ("score_300_1", 0.05), + ("score_300_2", 0.05), + ("score_300_3", 0.05), + ("score_300_4", 0.05), + ("score_300_5", 0.05), + ), + "score_1000": ( + ("score_1000_0", 0.05), + ("score_1000_1", 0.05), + ("score_1000_2", 0.05), + ("score_1000_3", 0.05), + ("score_1000_4", 0.05), + ("score_1000_5", 0.05), + ), +} + + +@singleton +class AnimationBank(Bank[pyglet.image.Animation]): + def __init__(self): + logging.info("Initializing") + + image_bank = ImageBank() + self.fallback = pyglet.image.Animation( + [pyglet.image.AnimationFrame(image_bank.get_fallback(), 1)] + ) + super().__init__() + + def load(self): + logging.info("Generating animations") + + image_bank = ImageBank() + + for key, value in ANIMATION_IDS.items(): + self.data[key] = pyglet.image.Animation( + [ + pyglet.image.AnimationFrame( + image_bank.get(image_id), frame_duration + ) + for (image_id, frame_duration) in value + ] + ) + + return super().load() diff --git a/pyoro/banks/bank.py b/pyoro/banks/bank.py new file mode 100644 index 0000000..5602e51 --- /dev/null +++ b/pyoro/banks/bank.py @@ -0,0 +1,25 @@ +import typing + +T = typing.TypeVar("T") + + +class Bank(typing.Generic[T]): + def __init__(self): + self.data: dict[str, T] = {} + self.fallback: T | None = None + + def load(self) -> None: + pass + + def get(self, key: str) -> T: + if key not in self.data: + raise KeyError(f"Key '{key}' not found in bank '{self.__class__.__name__}'") + return self.data[key] + + def __getitem__(self, key: str): + return self.get(key) + + def get_fallback(self) -> T: + if not self.fallback: + raise NotImplementedError() + return self.fallback diff --git a/pyoro/banks/image_bank.py b/pyoro/banks/image_bank.py new file mode 100644 index 0000000..583782f --- /dev/null +++ b/pyoro/banks/image_bank.py @@ -0,0 +1,137 @@ +import logging +import pyglet + +from pyoro.banks.bank import Bank +from pyoro.utils.singleton import singleton + +IMAGE_IDS = { + # Angels + "angel_normal": "angels/angel_normal.png", + "angel_fly": "angels/angel_fly.png", + # Backgrounds 1 + "background_1_0": "backgrounds_1/background_1_0.png", + "background_1_1": "backgrounds_1/background_1_1.png", + "background_1_2": "backgrounds_1/background_1_2.png", + "background_1_3": "backgrounds_1/background_1_3.png", + "background_1_4": "backgrounds_1/background_1_4.png", + "background_1_5": "backgrounds_1/background_1_5.png", + "background_1_6": "backgrounds_1/background_1_6.png", + "background_1_7": "backgrounds_1/background_1_7.png", + "background_1_8": "backgrounds_1/background_1_8.png", + "background_1_9": "backgrounds_1/background_1_9.png", + "background_1_10": "backgrounds_1/background_1_10.png", + "background_1_11": "backgrounds_1/background_1_11.png", + "background_1_12": "backgrounds_1/background_1_12.png", + "background_1_13": "backgrounds_1/background_1_13.png", + "background_1_14": "backgrounds_1/background_1_14.png", + "background_1_15": "backgrounds_1/background_1_15.png", + "background_1_16": "backgrounds_1/background_1_16.png", + "background_1_17": "backgrounds_1/background_1_17.png", + "background_1_18": "backgrounds_1/background_1_18.png", + "background_1_19": "backgrounds_1/background_1_19.png", + "background_1_20": "backgrounds_1/background_1_20.png", + # Backgrounds 2 + "background_2_1": "backgrounds_2/background_2_1.png", + "background_2_2": "backgrounds_2/background_2_2.png", + "background_2_3": "backgrounds_2/background_2_3.png", + "background_2_4": "backgrounds_2/background_2_4.png", + "background_2_5": "backgrounds_2/background_2_5.png", + "background_2_6": "backgrounds_2/background_2_6.png", + "background_2_7": "backgrounds_2/background_2_7.png", + "background_2_8": "backgrounds_2/background_2_8.png", + "background_2_9": "backgrounds_2/background_2_9.png", + "background_2_10": "backgrounds_2/background_2_10.png", + "background_2_11": "backgrounds_2/background_2_11.png", + "background_2_12": "backgrounds_2/background_2_12.png", + "background_2_13": "backgrounds_2/background_2_13.png", + "background_2_14": "backgrounds_2/background_2_14.png", + "background_2_15": "backgrounds_2/background_2_15.png", + "background_2_16": "backgrounds_2/background_2_16.png", + "background_2_17": "backgrounds_2/background_2_17.png", + "background_2_18": "backgrounds_2/background_2_18.png", + "background_2_19": "backgrounds_2/background_2_19.png", + "background_2_20": "backgrounds_2/background_2_20.png", + # Green Beans + "bean_green_left": "beans_green/bean_green_left.png", + "bean_green_middle": "beans_green/bean_green_middle.png", + "bean_green_right": "beans_green/bean_green_right.png", + # GUI + "gui_button_background": "gui/button/base.png", + "gui_button_background_hovered": "gui/button/hovered.png", + "gui_button_background_pressed": "gui/button/pressed.png", + "gui_button_play_seed": "gui/button_play_seed/base.png", + "gui_button_play_seed_hovered": "gui/button_play_seed/hovered.png", + "gui_button_play_seed_pressed": "gui/button_play_seed/pressed.png", + "gui_button_play_tongue": "gui/button_play_tongue/base.png", + "gui_button_play_tongue_hovered": "gui/button_play_tongue/hovered.png", + "gui_button_play_tongue_pressed": "gui/button_play_tongue/pressed.png", + "gui_title": "gui/title.png", + # Pink Beans + "bean_pink_left": "beans_pink/bean_pink_left.png", + "bean_pink_middle": "beans_pink/bean_pink_middle.png", + "bean_pink_right": "beans_pink/bean_pink_right.png", + # Cases + "case": "cases/case.png", + # Explosions + "explosion_0": "explosions/explosion_0.png", + "explosion_1": "explosions/explosion_1.png", + "explosion_2": "explosions/explosion_2.png", + # Pyoro + "pyoro_normal": "pyoros/pyoro_normal.png", + "pyoro_dead": "pyoros/pyoro_dead.png", + "pyoro_tongue": "pyoros/pyoro_tongue.png", + "pyoro_eat": "pyoros/pyoro_eat.png", + "pyoro_jump": "pyoros/pyoro_jump.png", + # Pyoro 2 + "pyoro_2_normal": "pyoros_2/pyoro_2_normal.png", + "pyoro_2_dead": "pyoros_2/pyoro_2_dead.png", + "pyoro_2_shoot_1": "pyoros_2/pyoro_2_shoot_1.png", + "pyoro_2_shoot_2": "pyoros_2/pyoro_2_shoot_2.png", + "pyoro_2_shoot_3": "pyoros_2/pyoro_2_shoot_3.png", + "pyoro_2_shoot_4": "pyoros_2/pyoro_2_shoot_4.png", + "pyoro_2_jump": "pyoros_2/pyoro_2_jump.png", + # Scores + "score_10": "scores/score_10.png", + "score_50": "scores/score_50.png", + "score_100": "scores/score_100.png", + "score_300_0": "scores/score_300_0.png", + "score_300_1": "scores/score_300_1.png", + "score_300_2": "scores/score_300_2.png", + "score_300_3": "scores/score_300_3.png", + "score_300_4": "scores/score_300_4.png", + "score_300_5": "scores/score_300_5.png", + "score_1000_0": "scores/score_1000_0.png", + "score_1000_1": "scores/score_1000_1.png", + "score_1000_2": "scores/score_1000_2.png", + "score_1000_3": "scores/score_1000_3.png", + "score_1000_4": "scores/score_1000_4.png", + "score_1000_5": "scores/score_1000_5.png", + # Tongue + "tongue": "tongues/tongue.png", + "tongue_piece": "tongues/tongue_piece.png", +} + + +@singleton +class ImageBank(Bank[pyglet.image.ImageData]): + def __init__(self): + logging.info("Initializing") + super().__init__() + + self.fallback = pyglet.image.create( # type: ignore + 32, 32, pyglet.image.SolidColorImagePattern(color=(0, 0, 0, 255)) + ) + + def load(self) -> None: + logging.info("Loading images") + loader = pyglet.resource.Loader("../res/images") + + for key, value in IMAGE_IDS.items(): + try: + self.data[key] = loader.image(value) # type: ignore + except pyglet.resource.ResourceNotFoundException: + logging.warn( + f"Image '{value}' not found. Using a fake transparent image instead" + ) + self.data[key] = pyglet.image.create(32, 32, pyglet.image.SolidColorImagePattern(color=(0, 0, 0, 255))) # type: ignore + return super().load() diff --git a/pyoro/configuration.py b/pyoro/configuration.py new file mode 100644 index 0000000..6bf866a --- /dev/null +++ b/pyoro/configuration.py @@ -0,0 +1,29 @@ +import logging +import typing + +from pyoro.utils.singleton import singleton + +DEFAULT_CONFIG: typing.Final = { + "window_width": 640, + "window_height": 576, + "speed_factor": 0.02, + "zoom": 32, +} + + +@singleton +class Configuration: + __slots__ = ("window_width", "window_height", "speed_factor", "zoom") + + def __init__(self): + logging.info("Initializing") + self.window_width = int(DEFAULT_CONFIG["window_width"]) + self.window_height = int(DEFAULT_CONFIG["window_height"]) + self.speed_factor = float(DEFAULT_CONFIG["speed_factor"]) + self.zoom = float(DEFAULT_CONFIG["zoom"]) + + def load(self): + logging.info("Loading configuration") + + def save(self): + pass diff --git a/pyoro/entity/__init__.py b/pyoro/entity/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/entity/entities/__init__.py b/pyoro/entity/entities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/entity/entities/angel.py b/pyoro/entity/entities/angel.py new file mode 100644 index 0000000..611e09e --- /dev/null +++ b/pyoro/entity/entities/angel.py @@ -0,0 +1,17 @@ +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.game_state import GameState + + +class Angel(Entity): + SPEED = 10 + ARMS_LENGTH = 1.5 + + def __init__(self, pos: tuple[float, float]): + super().__init__(EntityKind.ANGEL, pos) + self.vel = (0, -self.SPEED) + + def update(self, deltatime: float, game_state: GameState) -> None: + super().update(deltatime, game_state) + if self.pos[1] <= self.ARMS_LENGTH + 0.5: + self.vel = (0, self.SPEED) diff --git a/pyoro/entity/entities/beans/__init__.py b/pyoro/entity/entities/beans/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/entity/entities/beans/bean.py b/pyoro/entity/entities/beans/bean.py new file mode 100644 index 0000000..9dc99ba --- /dev/null +++ b/pyoro/entity/entities/beans/bean.py @@ -0,0 +1,22 @@ +import random +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entity_kind import EntityKind + + +class Bean(Entity): + SIZE = (1.5, 1.5) + HITBOX = (0.25, 0.25, 1, 1) + FALL_SPEED_RANGE = (0.7, 1.2) + SCHEDULE_REPARTITION = (1, 1) + + def __init__(self, kind: EntityKind, pos: tuple[float, float]): + super().__init__(kind, pos) + + self.vel = ( + 0, + -( + random.random() * (self.FALL_SPEED_RANGE[1] - self.FALL_SPEED_RANGE[0]) + + self.FALL_SPEED_RANGE[0] + ), + ) + self.dangerous = True diff --git a/pyoro/entity/entities/beans/bean_green.py b/pyoro/entity/entities/beans/bean_green.py new file mode 100644 index 0000000..8df2740 --- /dev/null +++ b/pyoro/entity/entities/beans/bean_green.py @@ -0,0 +1,9 @@ +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entity_kind import EntityKind + + +class BeanGreen(Bean): + SCHEDULE_REPARTITION = (4, 0.5) + + def __init__(self, pos: tuple[float, float]): + super().__init__(EntityKind.BEAN_GREEN, pos) diff --git a/pyoro/entity/entities/beans/bean_pink.py b/pyoro/entity/entities/beans/bean_pink.py new file mode 100644 index 0000000..e96c581 --- /dev/null +++ b/pyoro/entity/entities/beans/bean_pink.py @@ -0,0 +1,16 @@ +import typing + +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entity_kind import EntityKind + + +class BeanPink(Bean): + SCHEDULE_REPARTITION = (10, 3) + + def __init__( + self, + pos: tuple[float, float], + spawn_angel_func: typing.Callable[[], None] | None = None, + ): + super().__init__(EntityKind.BEAN_PINK, pos) + self.spawn_angel_func = spawn_angel_func diff --git a/pyoro/entity/entities/case.py b/pyoro/entity/entities/case.py new file mode 100644 index 0000000..02ed1a9 --- /dev/null +++ b/pyoro/entity/entities/case.py @@ -0,0 +1,9 @@ +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entity_kind import EntityKind + + +class Case(Entity): + FALL_SPEED = 25 + + def __init__(self, pos: tuple[float, float]): + super().__init__(EntityKind.CASE, pos) diff --git a/pyoro/entity/entities/entity.py b/pyoro/entity/entities/entity.py new file mode 100644 index 0000000..5e314d2 --- /dev/null +++ b/pyoro/entity/entities/entity.py @@ -0,0 +1,44 @@ +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.game_state import GameState + + +class Entity: + SIZE = (1, 1) + HITBOX = (0, 0, 1, 1) + + def __init__(self, kind: EntityKind, pos: tuple[float, float]): + self.kind = kind + self.pos: tuple[float, float] = pos + self.vel: tuple[float, float] = (0, 0) + self.direction: EntityDirection = EntityDirection.RIGHT + + def is_colliding(self, other: "Entity") -> bool: + self_x0 = self.pos[0] + self.HITBOX[0] + self_x1 = self.pos[0] + self.HITBOX[0] + self.HITBOX[2] + self_y0 = self.pos[1] + self.HITBOX[1] + self_y1 = self.pos[1] + self.HITBOX[1] + self.HITBOX[3] + + other_x0 = other.pos[0] + other.HITBOX[0] + other_x1 = other.pos[0] + other.HITBOX[0] + other.HITBOX[2] + other_y0 = other.pos[1] + other.HITBOX[1] + other_y1 = other.pos[1] + other.HITBOX[1] + other.HITBOX[3] + + return ( + self_x0 < other_x1 + and self_x1 > other_x0 + and self_y0 < other_y1 + and self_y1 > other_y0 + ) + + def get_id(self) -> int: + return hash(self) + + def update(self, deltatime: float, game_state: GameState) -> None: + self.pos = ( + self.pos[0] + self.vel[0] * deltatime, + self.pos[1] + self.vel[1] * deltatime, + ) + + def kill(self): + del self diff --git a/pyoro/entity/entities/explosion.py b/pyoro/entity/entities/explosion.py new file mode 100644 index 0000000..7469563 --- /dev/null +++ b/pyoro/entity/entities/explosion.py @@ -0,0 +1,12 @@ +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entity_kind import EntityKind + + +class Explosion(Entity): + SIZE = (1.5, 1.5) + HITBOX = (0, 0, 0, 0) + POS_OFFSET = (0, -0.4) + DURATION = 1.2 + + def __init__(self, pos: tuple[float, float]): + super().__init__(EntityKind.EXPLOSION, pos) diff --git a/pyoro/entity/entities/pyoros/__init__.py b/pyoro/entity/entities/pyoros/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/entity/entities/pyoros/pyoro.py b/pyoro/entity/entities/pyoros/pyoro.py new file mode 100644 index 0000000..3f69869 --- /dev/null +++ b/pyoro/entity/entities/pyoros/pyoro.py @@ -0,0 +1,54 @@ +import pyglet +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_state import PyoroState +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_state import GameState + + +class Pyoro(Entity): + SIZE = (2, 2) + HITBOX = (0, 0, 2, 2) + SPEED = 16 + FALLING_SPEED = 3 + JUMP_ANIMATION_INTERVAL = 0.04 + + def __init__( + self, kind: EntityKind, pos: tuple[float, float], controller: Controller + ): + super().__init__(kind, pos) + self.vel = (0, 0) + self.state: PyoroState = PyoroState.NORMAL + self.score = 0 + + controller.push_handlers(on_move_start=self.start_move, on_move_end=lambda _: self.stop_move()) # type: ignore + + pyglet.clock.schedule_interval(lambda _: self.jump(), self.JUMP_ANIMATION_INTERVAL) # type: ignore + + def update(self, deltatime: float, game_state: GameState) -> None: + super().update(deltatime, game_state) + + if self.pos[0] < 0: + self.pos = (0, self.pos[1]) + if self.pos[0] + self.SIZE[0] > game_state.size[0]: + self.pos = (game_state.size[0] - self.SIZE[0], self.pos[1]) + + def start_move(self, direction: EntityDirection) -> None: + self.direction = direction + self.vel = (self.SPEED * self.direction.value, 0) + + def stop_move(self) -> None: + self.vel = (0, 0) + self.state = PyoroState.NORMAL + + def jump(self) -> None: + if self.vel[0] != 0: + if self.state == PyoroState.JUMPING: + self.state = PyoroState.NORMAL + elif self.state == PyoroState.NORMAL: + self.state = PyoroState.JUMPING + + def die(self) -> None: + self.state = PyoroState.DYING + self.vel = (0, -self.FALLING_SPEED) diff --git a/pyoro/entity/entities/pyoros/pyoro_seed.py b/pyoro/entity/entities/pyoros/pyoro_seed.py new file mode 100644 index 0000000..a592cb8 --- /dev/null +++ b/pyoro/entity/entities/pyoros/pyoro_seed.py @@ -0,0 +1,11 @@ +from pyoro.entity.entities.pyoros.pyoro import Pyoro +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.controllers.controller import Controller + + +class PyoroSeed(Pyoro): + def __init__(self, pos: tuple[float, float], controller: Controller): + super().__init__(EntityKind.PYORO_2, pos, controller) + + def shoot(self): + pass diff --git a/pyoro/entity/entities/pyoros/pyoro_state.py b/pyoro/entity/entities/pyoros/pyoro_state.py new file mode 100644 index 0000000..e5327eb --- /dev/null +++ b/pyoro/entity/entities/pyoros/pyoro_state.py @@ -0,0 +1,10 @@ +import enum + + +class PyoroState(enum.Enum): + NORMAL = 0 + JUMPING = 1 + EATING = 2 + TONGING = 3 + DYING = 4 + SHOOTING = 5 diff --git a/pyoro/entity/entities/pyoros/pyoro_tongue.py b/pyoro/entity/entities/pyoros/pyoro_tongue.py new file mode 100644 index 0000000..e3c5ca1 --- /dev/null +++ b/pyoro/entity/entities/pyoros/pyoro_tongue.py @@ -0,0 +1,58 @@ +import pyglet +from pyoro.entity.entities.pyoros.pyoro import Pyoro +from pyoro.entity.entities.pyoros.pyoro_state import PyoroState +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.controllers.controller import Controller + + +class PyoroTongue(Pyoro): + EAT_ANIMATION_INTERVAL = 0.03 + EAT_ANIMATION_DURATION = 0.6 + + def __init__(self, pos: tuple[float, float], controller: Controller): + super().__init__(EntityKind.PYORO, pos, controller) + + controller.push_handlers(on_action_start=self.start_action) # type: ignore + + def start_action(self) -> None: + self.stop_move() + self.state = PyoroState.TONGING + + def end_action(self) -> None: + self.state = PyoroState.NORMAL + + def can_move(self) -> bool: + return self.state not in (PyoroState.TONGING, PyoroState.DYING) + + def start_move(self, direction: EntityDirection) -> None: + if self.can_move(): + return super().start_move(direction) + return None + + def stop_move(self) -> None: + if self.can_move(): + return super().stop_move() + return None + + def jump(self) -> None: + if self.can_move(): + return super().jump() + return None + + def eat(self) -> None: + def switch(_dt: float) -> None: + match self.state: + case PyoroState.EATING: + self.state = PyoroState.NORMAL + case _: + self.state = PyoroState.EATING + + def reset(_dt: float) -> None: + if self.state == PyoroState.EATING: + self.state = PyoroState.NORMAL + + pyglet.clock.schedule_interval_for_duration( # type: ignore + switch, self.EAT_ANIMATION_INTERVAL, self.EAT_ANIMATION_DURATION + ) + pyglet.clock.schedule_once(reset, self.EAT_ANIMATION_DURATION) # type: ignore diff --git a/pyoro/entity/entities/score.py b/pyoro/entity/entities/score.py new file mode 100644 index 0000000..5b01ae8 --- /dev/null +++ b/pyoro/entity/entities/score.py @@ -0,0 +1,25 @@ +import enum + +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entity_kind import EntityKind + + +class ScoreValue(enum.Enum): + SCORE_10 = 10 + SCORE_50 = 50 + SCORE_100 = 100 + SCORE_300 = 300 + SCORE_1000 = 1000 + + +class Score(Entity): + BLINK_INTERVAL = 0.05 + LIFE_TIME = 1 + SIZE = (1.5, 0.7) + HITBOX_SIZE = (0, 0, 0, 0) + + def __init__(self, pos: tuple[float, float], value: ScoreValue, bean: Bean): + super().__init__(EntityKind.SCORE, pos) + self.value = value + self.bean = bean diff --git a/pyoro/entity/entities/tongue.py b/pyoro/entity/entities/tongue.py new file mode 100644 index 0000000..c82ceca --- /dev/null +++ b/pyoro/entity/entities/tongue.py @@ -0,0 +1,68 @@ +import math + +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.entity_kind import EntityKind +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_state import GameState + + +class Tongue(Entity): + SIZE = (1.2, 1.2) + HITBOX = (-0.2, -0.2, 1.6, 1.6) + EXTRACT_SPEED = 20 + RETRACT_SPEED = 36 + ANGLE = math.pi / 4 + POS_OFFSET = (0.25, -0.25) + BEAN_POS_OFFSET = (0.5, 0.5) + + def __init__(self, pyoro: PyoroTongue, controller: Controller): + super().__init__(EntityKind.TONGUE, self.calculate_pos(pyoro)) + + self.direction = pyoro.direction + self._extending = False + + controller.push_handlers( # type: ignore + on_action_start=self.extract, on_action_end=self.retract + ) + + def get_extending(self) -> bool: + return self._extending + + def calculate_pos(self, pyoro: PyoroTongue) -> tuple[float, float]: + direction_factor = 1 if pyoro.direction == EntityDirection.RIGHT else 0 + return ( + pyoro.pos[0] + + pyoro.SIZE[0] / 2 + - self.SIZE[0] * (1 - direction_factor) + + self.POS_OFFSET[0] * pyoro.direction.value, + pyoro.pos[1] + pyoro.SIZE[1] / 2 + self.POS_OFFSET[1], + ) + + def calculate_retract_vel(self) -> tuple[float, float]: + return ( + -self.RETRACT_SPEED * math.cos(self.ANGLE) * self.direction.value, + -self.RETRACT_SPEED * math.sin(self.ANGLE), + ) + + def extract(self): + self._extending = True + self.vel = ( + self.EXTRACT_SPEED * math.cos(self.ANGLE) * self.direction.value, + self.EXTRACT_SPEED * math.sin(self.ANGLE), + ) + + def retract(self): + self._extending = False + self.vel = self.calculate_retract_vel() + + def update(self, deltatime: float, game_state: GameState) -> None: + if ( + self.pos[0] + self.SIZE[0] > game_state.size[0] + or self.pos[0] < 0 + or self.pos[1] + self.SIZE[1] > game_state.size[1] + or self.pos[1] < 0 + ): + self.retract() + return super().update(deltatime, game_state) diff --git a/pyoro/entity/entities/tongue_piece.py b/pyoro/entity/entities/tongue_piece.py new file mode 100644 index 0000000..a524a4b --- /dev/null +++ b/pyoro/entity/entities/tongue_piece.py @@ -0,0 +1,31 @@ +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.entity_kind import EntityKind + + +class TonguePiece(Entity): + SIZE = (0.24, 0.24) + HITBOX = (0, 0, 0, 0) + + def __init__(self, pyoro: PyoroTongue, tongue: Tongue, index: int): + self.index = index + + super().__init__(EntityKind.TONGUE_PIECE, self.calculate_pos(pyoro, tongue)) + + self.direction = pyoro.direction + + def calculate_pos(self, pyoro: PyoroTongue, tongue: Tongue) -> tuple[float, float]: + x_offset = 0 if pyoro.direction == EntityDirection.RIGHT else -self.SIZE[0] + return ( + pyoro.pos[0] + + pyoro.SIZE[0] / 2 + + pyoro.direction.value + * (self.index * self.SIZE[0] / 2 + tongue.POS_OFFSET[0]) + + x_offset, + pyoro.pos[1] + + pyoro.SIZE[1] / 2 + + self.index * self.SIZE[1] / 2 + + tongue.POS_OFFSET[1], + ) diff --git a/pyoro/entity/entity_direction.py b/pyoro/entity/entity_direction.py new file mode 100644 index 0000000..af165f7 --- /dev/null +++ b/pyoro/entity/entity_direction.py @@ -0,0 +1,6 @@ +import enum + + +class EntityDirection(enum.Enum): + LEFT = -1 + RIGHT = 1 diff --git a/pyoro/entity/entity_kind.py b/pyoro/entity/entity_kind.py new file mode 100644 index 0000000..c2f1835 --- /dev/null +++ b/pyoro/entity/entity_kind.py @@ -0,0 +1,15 @@ +import enum + + +class EntityKind(enum.Enum): + ANGEL = 0 + BEAN_GREEN = 1 + BEAN_PINK = 2 + BEAN_SILVER = 3 + CASE = 4 + PYORO = 5 + PYORO_2 = 6 + SCORE = 7 + TONGUE = 8 + TONGUE_PIECE = 9 + EXPLOSION = 10 diff --git a/pyoro/entity/entity_orchestrator.py b/pyoro/entity/entity_orchestrator.py new file mode 100644 index 0000000..db6b665 --- /dev/null +++ b/pyoro/entity/entity_orchestrator.py @@ -0,0 +1,67 @@ +import logging + +from pyoro.entity.entities.entity import Entity +from pyoro.entity.operators.bean_operator import BeanOperator +from pyoro.entity.operators.case_operator import CaseOperator +from pyoro.entity.operators.explosion_operator import ExplosionOperator +from pyoro.entity.operators.operator import Operator +from pyoro.entity.operators.pyoro_operator import PyoroOperator +from pyoro.entity.operators.score_operator import ScoreOperator +from pyoro.entity.operators.tongue_operator import TongueOperator +from pyoro.entity.operators.tongue_piece_operator import TonguePieceOperator +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_state import GameMode, GameState + + +class EntityOrchestrator: + def __init__( + self, game_mode: GameMode, game_size: tuple[int, int], controller: Controller + ): + logging.info("Initializing") + self.entities: list[Entity] = [] + self.operators: list[Operator] = [] + + operator_classes = ( + CaseOperator, + PyoroOperator, + TongueOperator, + TonguePieceOperator, + BeanOperator, + ExplosionOperator, + ScoreOperator, + ) + + for operator_class in operator_classes: + operator = operator_class( + self.get_entities, + self.add_entity, + self.remove_entity, + controller, + ) + operator.setup(game_mode, game_size) + self.operators.append(operator) + + def get_entities(self) -> tuple[Entity, ...]: + return tuple(self.entities) + + def add_entity(self, entity: Entity) -> None: + self.entities.append(entity) + + def remove_entity(self, entity: Entity) -> None: + self.entities = [e for e in self.entities if e != entity] + + def update(self, deltatime: float, game_state: GameState) -> None: + for entity in self.entities: + entity.update(deltatime * game_state.speed, game_state) + + collisions: list[tuple[Entity, Entity]] = [] + for entity1 in self.entities: + for entity2 in tuple(self.entities): + if entity1 != entity2 and entity1.is_colliding(entity2): + collisions.append((entity1, entity2)) + + for operator in self.operators: + operator.update(game_state) + + for collision in collisions: + operator.collide(*collision) diff --git a/pyoro/entity/operators/__init__.py b/pyoro/entity/operators/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/entity/operators/bean_operator.py b/pyoro/entity/operators/bean_operator.py new file mode 100644 index 0000000..6a7d8b3 --- /dev/null +++ b/pyoro/entity/operators/bean_operator.py @@ -0,0 +1,87 @@ +import random +import typing +import numpy +import pyglet + +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.beans.bean_green import BeanGreen +from pyoro.entity.entities.beans.bean_pink import BeanPink +from pyoro.entity.entities.case import Case +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro import Pyoro +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.operators.operator import Operator +from pyoro.game.game_mode import GameMode +from pyoro.game.game_state import GameState + + +class BeanOperator(Operator): + def setup(self, game_mode: GameMode, game_size: tuple[int, int]) -> None: + self.bean_pink_scheduled = False + self.random_generator = numpy.random.Generator(numpy.random.PCG64()) + self.schedule(BeanGreen, game_size) + + return super().setup(game_mode, game_size) + + def schedule( + self, + bean_cls: typing.Type[BeanGreen] | typing.Type[BeanPink], + game_size: tuple[int, int], + ) -> None: + def on_clock(_dt: float) -> None: + self.spawn_bean(bean_cls, game_size) + + delay = self.random_generator.normal( + bean_cls.SCHEDULE_REPARTITION[0], bean_cls.SCHEDULE_REPARTITION[1] + ) + pyglet.clock.schedule_once(on_clock, delay) # type: ignore + + def spawn_bean( + self, + bean_cls: typing.Type[BeanGreen] | typing.Type[BeanPink], + game_size: tuple[int, int], + ) -> None: + pos = (random.randint(0, game_size[0] - 1) - bean_cls.HITBOX[0], game_size[1]) + self.add_entity(bean_cls(pos)) + self.schedule(bean_cls, game_size) + + def update(self, game_state: GameState) -> None: + pyoro = self.find_entity(Pyoro) + beans = self.filter_entities(Bean) + + if pyoro and pyoro.score > 2000 and not self.bean_pink_scheduled: + self.bean_pink_scheduled = True + self.schedule(BeanPink, game_state.size) + + for bean in beans: + if bean.pos[1] + bean.SIZE[1] < 0: + self.remove_bean(bean) + + return super().update(game_state) + + def remove_bean(self, bean: Bean) -> None: + self.remove_entity(bean) + bean.kill() + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if isinstance(entity1, Bean): + if isinstance(entity2, Tongue): + entity1.pos = ( + entity2.pos[0] + + entity2.SIZE[0] / 2 + - entity1.SIZE[0] / 2 + + entity2.BEAN_POS_OFFSET[0] * entity2.direction.value, + entity2.pos[1] + + entity2.SIZE[1] / 2 + - entity1.SIZE[1] / 2 + + entity2.BEAN_POS_OFFSET[1], + ) + entity1.vel = entity2.calculate_retract_vel() + entity1.dangerous = False + elif isinstance(entity2, Pyoro): + self.remove_bean(entity1) + elif isinstance(entity2, Case): + if entity1.dangerous: + self.remove_bean(entity1) + + return super().collide(entity1, entity2) diff --git a/pyoro/entity/operators/case_operator.py b/pyoro/entity/operators/case_operator.py new file mode 100644 index 0000000..46058d2 --- /dev/null +++ b/pyoro/entity/operators/case_operator.py @@ -0,0 +1,27 @@ +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.case import Case +from pyoro.entity.entities.entity import Entity +from pyoro.entity.operators.operator import Operator +from pyoro.game.game_mode import GameMode + + +class CaseOperator(Operator): + def setup(self, game_mode: GameMode, game_size: tuple[int, int]) -> None: + for i in range(game_size[0]): + self.add_entity(Case((i, 0))) + + return super().setup(game_mode, game_size) + + def remove_case(self, case: Case) -> None: + self.remove_entity(case) + case.kill() + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if ( + isinstance(entity1, Case) + and isinstance(entity2, Bean) + and entity2.dangerous + ): + self.remove_case(entity1) + + return super().collide(entity1, entity2) diff --git a/pyoro/entity/operators/explosion_operator.py b/pyoro/entity/operators/explosion_operator.py new file mode 100644 index 0000000..6560cc3 --- /dev/null +++ b/pyoro/entity/operators/explosion_operator.py @@ -0,0 +1,41 @@ +import pyglet + +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.case import Case +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.explosion import Explosion +from pyoro.entity.entities.pyoros.pyoro import Pyoro +from pyoro.entity.operators.operator import Operator + + +class ExplosionOperator(Operator): + def spawn_explosion(self, bean: Bean) -> None: + explosion = Explosion( + ( + bean.pos[0] + + bean.SIZE[0] / 2 + + Explosion.POS_OFFSET[0] + - Explosion.SIZE[0] / 2, + bean.pos[1] + + bean.SIZE[1] / 2 + + Explosion.POS_OFFSET[1] + - Explosion.SIZE[1] / 2, + ) + ) + self.add_entity(explosion) + + pyglet.clock.schedule_once( # type: ignore + lambda _: self.remove_explosion(explosion), explosion.DURATION # type: ignore + ) + + def remove_explosion(self, explosion: Explosion) -> None: + self.remove_entity(explosion) + explosion.kill() + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if isinstance(entity1, Bean) and ( + (isinstance(entity2, Case) or isinstance(entity2, Pyoro)) + and entity1.dangerous + ): + self.spawn_explosion(entity1) + return super().collide(entity1, entity2) diff --git a/pyoro/entity/operators/operator.py b/pyoro/entity/operators/operator.py new file mode 100644 index 0000000..74c7ed2 --- /dev/null +++ b/pyoro/entity/operators/operator.py @@ -0,0 +1,41 @@ +import typing +from pyoro.entity.entities.entity import Entity +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_mode import GameMode +from pyoro.game.game_state import GameState + +T = typing.TypeVar("T", bound=Entity) + + +class Operator: + def __init__( + self, + get_entities_fct: typing.Callable[[], typing.Iterable[Entity]], + add_entity_fct: typing.Callable[[Entity], None], + remove_entity_fct: typing.Callable[[Entity], None], + controller: Controller, + ) -> None: + self.get_entities = get_entities_fct + self.add_entity = add_entity_fct + self.remove_entity = remove_entity_fct + self.controller = controller + + def setup(self, game_mode: GameMode, game_size: tuple[int, int]) -> None: + pass + + def update(self, game_state: GameState) -> None: + pass + + def collide(self, entity1: Entity, entity2: Entity) -> None: + pass + + def filter_entities(self, entity_cls: typing.Type[T]) -> list[T]: + return [ + entity for entity in self.get_entities() if isinstance(entity, entity_cls) + ] + + def find_entity(self, entity_cls: typing.Type[T]) -> T | None: + for entity in self.get_entities(): + if isinstance(entity, entity_cls): + return entity + return None diff --git a/pyoro/entity/operators/pyoro_operator.py b/pyoro/entity/operators/pyoro_operator.py new file mode 100644 index 0000000..94e631c --- /dev/null +++ b/pyoro/entity/operators/pyoro_operator.py @@ -0,0 +1,81 @@ +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.case import Case +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro import Pyoro +from pyoro.entity.entities.pyoros.pyoro_state import PyoroState +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entities.pyoros.pyoro_seed import PyoroSeed +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.operators.operator import Operator +from pyoro.game.game_mode import GameMode +from pyoro.game.game_state import GameState + + +class PyoroOperator(Operator): + def setup(self, game_mode: GameMode, game_size: tuple[int, int]) -> None: + match game_mode: + case GameMode.TONGUE: + self.add_entity(PyoroTongue((1, 1), self.controller)) + case GameMode.SHOOT: + self.add_entity(PyoroSeed((1, 1), self.controller)) + return super().setup(game_mode, game_size) + + def update(self, game_state: GameState) -> None: + pyoro = self.find_entity(Pyoro) + cases = self.filter_entities(Case) + + def get_case_from_x(pos_x: int) -> Case | None: + for c in cases: + if c.pos[0] == pos_x: + return c + return None + + def find_nearest_case(pos_x: int, direction: EntityDirection) -> Case | None: + match direction: + case EntityDirection.RIGHT: + for c in cases[::-1]: + if c.pos[0] <= pos_x: + return c + return None + case EntityDirection.LEFT: + for c in cases: + if c.pos[0] >= pos_x: + return c + return None + + def move_pyoro_to_case(pyoro: Pyoro, c: Case) -> None: + match pyoro.direction: + case EntityDirection.RIGHT: + pyoro.pos = (c.pos[0] + c.SIZE[0] - pyoro.SIZE[0], pyoro.pos[1]) + case EntityDirection.LEFT: + pyoro.pos = (c.pos[0], pyoro.pos[1]) + + if pyoro: + match pyoro.direction: + case EntityDirection.RIGHT: + front_case_x = int(pyoro.pos[0] + pyoro.SIZE[0]) + case EntityDirection.LEFT: + front_case_x = int(pyoro.pos[0]) + front_case = get_case_from_x(front_case_x) + + if not front_case: + nearest_case = find_nearest_case(front_case_x, pyoro.direction) + + if nearest_case: + move_pyoro_to_case(pyoro, nearest_case) + + return super().update(game_state) + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if isinstance(entity1, PyoroTongue): + if isinstance(entity2, Tongue): + if not entity2.get_extending(): + entity1.end_action() + elif isinstance(entity2, Bean): + if entity2.dangerous: + if entity1.state != PyoroState.DYING: + entity1.die() + else: + entity1.eat() + return super().collide(entity1, entity2) diff --git a/pyoro/entity/operators/score_operator.py b/pyoro/entity/operators/score_operator.py new file mode 100644 index 0000000..a488af4 --- /dev/null +++ b/pyoro/entity/operators/score_operator.py @@ -0,0 +1,61 @@ +from typing import Callable, Iterable + +import pyglet +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.score import Score, ScoreValue +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.operators.operator import Operator +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_state import GameState + + +class ScoreOperator(Operator): + def __init__( + self, + get_entities_fct: Callable[[], Iterable[Entity]], + add_entity_fct: Callable[[Entity], None], + remove_entity_fct: Callable[[Entity], None], + controller: Controller, + ) -> None: + super().__init__( + get_entities_fct, add_entity_fct, remove_entity_fct, controller + ) + self.game_height: int = 0 + + def calculate_score(self, bean: Bean) -> int: + ratio = bean.pos[1] / self.game_height + + if ratio >= 0.7: + return 1000 + if ratio >= 0.6: + return 300 + if ratio >= 0.4: + return 100 + if ratio >= 0.2: + return 50 + return 10 + + def spawn_score(self, bean: Bean) -> None: + pos = ( + bean.pos[0] + bean.SIZE[0] / 2 - Score.SIZE[0] / 2, + bean.pos[1] + bean.SIZE[1] / 2 - Score.SIZE[1] / 2, + ) + score = Score(pos, ScoreValue(self.calculate_score(bean)), bean) + self.add_entity(score) + pyglet.clock.schedule_once(lambda _: self.remove_score(score), score.LIFE_TIME) # type: ignore + + def remove_score(self, score: Score) -> None: + self.remove_entity(score) + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if isinstance(entity1, Bean) and isinstance(entity2, Tongue): + beans_already_scored = {score.bean for score in self.filter_entities(Score)} + + if entity1 not in beans_already_scored: + self.spawn_score(entity1) + return super().collide(entity1, entity2) + + def update(self, game_state: GameState) -> None: + self.game_height = game_state.size[0] + return super().update(game_state) diff --git a/pyoro/entity/operators/tongue_operator.py b/pyoro/entity/operators/tongue_operator.py new file mode 100644 index 0000000..66794a9 --- /dev/null +++ b/pyoro/entity/operators/tongue_operator.py @@ -0,0 +1,49 @@ +from pyoro.entity.entities.beans.bean import Bean +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.operators.operator import Operator +from pyoro.exceptions.pyoro_not_found import PyoroNotFoundException +from pyoro.game.game_mode import GameMode + + +class TongueOperator(Operator): + def setup(self, game_mode: GameMode, game_size: tuple[int, int]) -> None: + self.setup_controller(game_mode) + return super().setup(game_mode, game_size) + + def setup_controller(self, game_mode: GameMode) -> None: + if game_mode == GameMode.TONGUE: + self.controller.push_handlers(on_action_start=self.spawn_tongue) # type: ignore + + def spawn_tongue(self) -> None: + pyoro = self.find_entity(PyoroTongue) + tongue = self.find_entity(Tongue) + + if not pyoro: + raise PyoroNotFoundException("Pyoro not found when trying to spawn tongue") + if tongue: + return None + + tongue = Tongue(pyoro, self.controller) + tongue.extract() + self.add_entity(tongue) + + def remove_tongue(self) -> None: + tongue = self.find_entity(Tongue) + + if not tongue: + return None + + self.remove_entity(tongue) + tongue.kill() + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if isinstance(entity1, Tongue): + if isinstance(entity2, PyoroTongue): + if not entity1.get_extending(): + self.remove_tongue() + elif isinstance(entity2, Bean): + if entity1.get_extending(): + entity1.retract() + return super().collide(entity1, entity2) diff --git a/pyoro/entity/operators/tongue_piece_operator.py b/pyoro/entity/operators/tongue_piece_operator.py new file mode 100644 index 0000000..9143be2 --- /dev/null +++ b/pyoro/entity/operators/tongue_piece_operator.py @@ -0,0 +1,95 @@ +import math +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entities.tongue import Tongue +from pyoro.entity.entities.tongue_piece import TonguePiece +from pyoro.entity.entity_direction import EntityDirection +from pyoro.entity.operators.operator import Operator +from pyoro.game.game_state import GameState + + +class TonguePieceOperator(Operator): + def get_tongue_pieces_needed_count(self) -> int | None: + pyoro = self.find_entity(PyoroTongue) + tongue = self.find_entity(Tongue) + + if not pyoro or not tongue: + return None + + match tongue.direction: + case EntityDirection.RIGHT: + return math.ceil( + 2 + * (tongue.pos[0] - (pyoro.pos[0] + pyoro.SIZE[0] / 2)) + / TonguePiece.SIZE[0] + ) + case EntityDirection.LEFT: + return math.ceil( + 2 + * ( + (pyoro.pos[0] + pyoro.SIZE[0] / 2) + - (tongue.pos[0] + tongue.SIZE[0]) + ) + / TonguePiece.SIZE[0] + ) + + def spawn_tongue_piece(self) -> None: + pyoro = self.find_entity(PyoroTongue) + tongue = self.find_entity(Tongue) + tongue_pieces = self.filter_entities(TonguePiece) + tongue_pieces_count = len(tongue_pieces) + need_tongue_pieces_count = self.get_tongue_pieces_needed_count() + + if not pyoro or not tongue or not need_tongue_pieces_count: + return None + + for i in range(tongue_pieces_count, need_tongue_pieces_count): + self.add_entity(TonguePiece(pyoro, tongue, i)) + + def remove_tongue_piece(self) -> None: + tongue_pieces = self.filter_entities(TonguePiece) + tongue_pieces_count = len(tongue_pieces) + need_tongue_pieces_count = self.get_tongue_pieces_needed_count() + + def find_tongue_piece(tongue_piece_index: int) -> TonguePiece | None: + for tongue_piece in tongue_pieces[::-1]: + if tongue_piece.index == tongue_piece_index: + return tongue_piece + return None + + if not need_tongue_pieces_count: + return None + + for i in range(tongue_pieces_count, need_tongue_pieces_count, -1): + tongue_piece = find_tongue_piece(i - 1) + + if tongue_piece: + self.remove_entity(tongue_piece) + tongue_piece.kill() + + def clear_tongue_pieces(self) -> None: + tongue_pieces = self.filter_entities(TonguePiece) + + for tongue_piece in tongue_pieces: + self.remove_entity(tongue_piece) + tongue_piece.kill() + + def update(self, game_state: GameState) -> None: + pyoro = self.find_entity(PyoroTongue) + tongue = self.find_entity(Tongue) + + if pyoro and tongue: + if tongue.get_extending(): + self.spawn_tongue_piece() + else: + self.remove_tongue_piece() + return super().update(game_state) + + def collide(self, entity1: Entity, entity2: Entity) -> None: + if ( + isinstance(entity1, PyoroTongue) + and isinstance(entity2, Tongue) + and not entity2.get_extending() + ): + self.clear_tongue_pieces() + return super().collide(entity1, entity2) diff --git a/pyoro/exceptions/__init__.py b/pyoro/exceptions/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/exceptions/pyoro_not_found.py b/pyoro/exceptions/pyoro_not_found.py new file mode 100644 index 0000000..5774c8c --- /dev/null +++ b/pyoro/exceptions/pyoro_not_found.py @@ -0,0 +1,2 @@ +class PyoroNotFoundException(Exception): + pass diff --git a/pyoro/game/__init__.py b/pyoro/game/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/game/controllers/__init__.py b/pyoro/game/controllers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/game/controllers/controller.py b/pyoro/game/controllers/controller.py new file mode 100644 index 0000000..003439c --- /dev/null +++ b/pyoro/game/controllers/controller.py @@ -0,0 +1,11 @@ +from pyglet import event + + +class Controller(event.EventDispatcher): + def __init__(self) -> None: + super().__init__() + + self.register_event_type("on_move_start") # type: ignore + self.register_event_type("on_move_end") # type: ignore + self.register_event_type("on_action_start") # type: ignore + self.register_event_type("on_action_end") # type: ignore diff --git a/pyoro/game/controllers/user_controller.py b/pyoro/game/controllers/user_controller.py new file mode 100644 index 0000000..d0246b1 --- /dev/null +++ b/pyoro/game/controllers/user_controller.py @@ -0,0 +1,42 @@ +import pyglet + +from pyglet.window import key # type: ignore + +from pyoro.entity.entity_direction import EntityDirection +from pyoro.game.controllers.controller import Controller +from pyoro.graphics.window import Window + + +class UserController(Controller): + def __init__(self) -> None: + super().__init__() + + self.key_state_handler = pyglet.window.key.KeyStateHandler() + + window = Window() + window.push_handlers(self) # type: ignore + window.push_handlers(self.key_state_handler) # type: ignore + + def some_key_pressed(self, *symbols: int) -> bool: + for symbol in symbols: + if self.key_state_handler[symbol]: + return True + return False + + def on_key_press(self, symbol: int, _modifiers: int) -> None: + if symbol in (key.Q, key.LEFT): + self.dispatch_event("on_move_start", EntityDirection.LEFT) # type: ignore + elif symbol in (key.D, key.RIGHT): + self.dispatch_event("on_move_start", EntityDirection.RIGHT) # type: ignore + elif symbol == key.SPACE: + self.dispatch_event("on_action_start") # type: ignore + + def on_key_release(self, symbol: int, _modifiers: int) -> None: + if symbol in (key.Q, key.LEFT): + if not self.some_key_pressed(key.D, key.RIGHT): + self.dispatch_event("on_move_end", EntityDirection.LEFT) # type: ignore + elif symbol in (key.D, key.RIGHT): + if not self.some_key_pressed(key.Q, key.LEFT): + self.dispatch_event("on_move_end", EntityDirection.RIGHT) # type: ignore + elif symbol == key.SPACE: + self.dispatch_event("on_action_end") # type: ignore diff --git a/pyoro/game/game_engine.py b/pyoro/game/game_engine.py new file mode 100644 index 0000000..d35562d --- /dev/null +++ b/pyoro/game/game_engine.py @@ -0,0 +1,21 @@ +from pyoro.entity.entity_orchestrator import EntityOrchestrator +from pyoro.game.controllers.controller import Controller +from pyoro.game.game_loop import GameLoop +from pyoro.game.game_mode import GameMode +from pyoro.game.game_state import GameState + + +class GameEngine: + def __init__(self, game_mode: GameMode, controller: Controller): + self.state = GameState(game_mode) + self.loop = GameLoop(on_tick=self.update) + self.entity_orchestrator = EntityOrchestrator( + game_mode, self.state.size, controller + ) + + def update(self, deltatime: float): + self.entity_orchestrator.update(deltatime, self.state) + self.state.speed_up(deltatime) + + def run(self): + self.loop.start() diff --git a/pyoro/game/game_loop.py b/pyoro/game/game_loop.py new file mode 100644 index 0000000..baa1a8c --- /dev/null +++ b/pyoro/game/game_loop.py @@ -0,0 +1,10 @@ +import pyglet +import typing + + +class GameLoop: + def __init__(self, on_tick: typing.Callable[[float], None]): + self._on_tick = on_tick + + def start(self): + pyglet.clock.schedule(self._on_tick) # type: ignore diff --git a/pyoro/game/game_mode.py b/pyoro/game/game_mode.py new file mode 100644 index 0000000..4bdae35 --- /dev/null +++ b/pyoro/game/game_mode.py @@ -0,0 +1,6 @@ +import enum + + +class GameMode(enum.Enum): + TONGUE = 0 + SHOOT = 1 diff --git a/pyoro/game/game_state.py b/pyoro/game/game_state.py new file mode 100644 index 0000000..b12f737 --- /dev/null +++ b/pyoro/game/game_state.py @@ -0,0 +1,26 @@ +import logging +import math + +from pyoro.configuration import Configuration +from pyoro.game.game_mode import GameMode + + +class GameState: + __slots__ = ("mode", "size", "speed", "background_id") + + def __init__(self, mode: GameMode): + logging.info(f"Creating new game state for mode {mode.name}") + + configuration = Configuration() + + self.mode = mode + self.size = ( + math.ceil(configuration.window_width / configuration.zoom), + math.ceil(configuration.window_height / configuration.zoom), + ) + self.speed = 1.0 + self.background_id = 0 + + def speed_up(self, deltatime: float): + configuration = Configuration() + self.speed += configuration.speed_factor * deltatime diff --git a/pyoro/graphics/__init__.py b/pyoro/graphics/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/graphics/layers/__init__.py b/pyoro/graphics/layers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/graphics/layers/background_layer.py b/pyoro/graphics/layers/background_layer.py new file mode 100644 index 0000000..144ff81 --- /dev/null +++ b/pyoro/graphics/layers/background_layer.py @@ -0,0 +1,41 @@ +import pyglet + +from pyoro.banks.image_bank import ImageBank +from pyoro.configuration import Configuration +from pyoro.game.game_state import GameState +from pyoro.graphics.layers.layer import Layer +from pyoro.graphics.layers.layer_level import LayerLevel + + +class BackgroundLayer(Layer): + def __init__(self, game_state: GameState) -> None: + super().__init__(LayerLevel.BACKGROUND.value) + + self.game_state = game_state + + image_bank = ImageBank() + self.current_background = pyglet.sprite.Sprite( + img=image_bank.get( + f"background_{self.game_state.mode.value + 1}_{self.game_state.background_id}" + ), + batch=self.batch, + group=self.group, + ) + self.next_background: pyglet.sprite.Sprite | None = None + + self.setup_background(self.current_background, first_background=True) + + def setup_background( + self, background_sprite: pyglet.sprite.Sprite, first_background: bool = False + ) -> None: + configuration = Configuration() + background_sprite.update( # type: ignore + x=0, + y=0, + scale_x=(configuration.window_width / self.current_background.width), # type: ignore + scale_y=(configuration.window_height / self.current_background.height), # type: ignore + ) + background_sprite.opacity = 255 if first_background else 0 + + def draw(self): + self.batch.draw() diff --git a/pyoro/graphics/layers/entity_layer.py b/pyoro/graphics/layers/entity_layer.py new file mode 100644 index 0000000..d046a7b --- /dev/null +++ b/pyoro/graphics/layers/entity_layer.py @@ -0,0 +1,162 @@ +import typing +import pyglet + +from pyoro.banks.animation_bank import AnimationBank +from pyoro.banks.image_bank import ImageBank +from pyoro.configuration import Configuration +from pyoro.entity.entities.entity import Entity +from pyoro.entity.entities.pyoros.pyoro_tongue import PyoroTongue +from pyoro.entity.entities.pyoros.pyoro_state import PyoroState +from pyoro.entity.entities.score import Score, ScoreValue +from pyoro.entity.entity_kind import EntityKind +from pyoro.entity.entity_orchestrator import EntityOrchestrator +from pyoro.graphics.layers.layer import Layer +from pyoro.graphics.layers.layer_level import LayerLevel + + +class EntityLayer(Layer): + def __init__(self, entity_orchestrator: EntityOrchestrator) -> None: + super().__init__(LayerLevel.ENTITY.value) + + self.entity_orchestrator = entity_orchestrator + self.pyoro_group = pyglet.graphics.Group(order=LayerLevel.PYORO.value) + self.sprites: dict[int, pyglet.sprite.Sprite] = {} + + @staticmethod + def get_entity_image( + entity: Entity, + ) -> pyglet.image.AbstractImage | pyglet.image.Animation: + image_bank = ImageBank() + animation_bank = AnimationBank() + + match entity.kind: + case EntityKind.CASE: + return image_bank.get("case") + case EntityKind.PYORO: + pyoro = typing.cast(PyoroTongue, entity) + match pyoro.state: + case PyoroState.NORMAL: + return image_bank.get("pyoro_normal") + case PyoroState.JUMPING: + return image_bank.get("pyoro_jump") + case PyoroState.EATING: + return image_bank.get("pyoro_eat") + case PyoroState.DYING: + return image_bank.get("pyoro_dead") + case PyoroState.TONGING: + return image_bank.get("pyoro_tongue") + case state: + raise ValueError(f"{state} is an unknown state for Pyoro") + case EntityKind.TONGUE: + return image_bank.get("tongue") + case EntityKind.TONGUE_PIECE: + return image_bank.get("tongue_piece") + case EntityKind.BEAN_GREEN: + return animation_bank.get("bean_green") + case EntityKind.EXPLOSION: + return animation_bank.get("explosion") + case EntityKind.SCORE: + score = typing.cast(Score, entity) + match score.value: + case ScoreValue.SCORE_10: + return image_bank.get("score_10") + case ScoreValue.SCORE_50: + return image_bank.get("score_50") + case ScoreValue.SCORE_100: + return image_bank.get("score_100") + case ScoreValue.SCORE_300: + return animation_bank.get("score_300") + case ScoreValue.SCORE_1000: + return animation_bank.get("score_1000") + case _: + return image_bank.get_fallback() + + @staticmethod + def convert_pos(pos: tuple[float, float]) -> tuple[int, int]: + configuration = Configuration() + return (int(pos[0] * configuration.zoom), int(pos[1] * configuration.zoom)) + + @staticmethod + def convert_size(size: tuple[float, float]) -> tuple[float, float]: + configuration = Configuration() + return (size[0] * configuration.zoom, size[1] * configuration.zoom) + + def get_entity_group(self, entity: Entity) -> pyglet.graphics.Group: + match entity.kind: + case EntityKind.PYORO: + return self.pyoro_group + case EntityKind.TONGUE: + return self.pyoro_group + case _: + return self.group + + def get_sprite_image_size(self, sprite: pyglet.sprite.Sprite) -> tuple[int, int]: + image = sprite.image # type: ignore + index = sprite.frame_index + + if isinstance(image, pyglet.image.Animation): # type: ignore + return (image.frames[index].image.width, image.frames[index].image.height) # type: ignore + return (image.width, image.height) # type: ignore + + def add_missing_sprite(self, entity: Entity) -> None: + real_pos = self.convert_pos(entity.pos) + real_size = self.convert_size(entity.SIZE) + + image = self.get_entity_image(entity) + sprite = pyglet.sprite.Sprite( + img=image, + group=self.get_entity_group(entity), + batch=self.batch, + ) + image_size = self.get_sprite_image_size(sprite) + sprite.update( # type: ignore + x=real_pos[0] + - ( + real_size[1] * (entity.direction.value - 1) // 2 + ), # shift x if the sprite must be in the opposite direciton + y=real_pos[1], + scale_x=(real_size[0] / image_size[0]) * entity.direction.value, # type: ignore + scale_y=(real_size[1] / image_size[1]), # type: ignore + ) + self.sprites[entity.get_id()] = sprite + + def update_sprite(self, entity: Entity) -> None: + real_pos = self.convert_pos(entity.pos) + real_size = self.convert_size(entity.SIZE) + + sprite = self.sprites[entity.get_id()] + new_image = self.get_entity_image(entity) + + if new_image != sprite.image: # type: ignore + sprite.image = new_image + + image_size = self.get_sprite_image_size(sprite) + sprite.update( # type: ignore + x=real_pos[0] + - ( + real_size[1] * (entity.direction.value - 1) // 2 + ), # shift x if the sprite must be in the opposite direciton + y=real_pos[1], + scale_x=(real_size[0] / image_size[0]) * entity.direction.value, # type: ignore + scale_y=(real_size[1] / image_size[1]), # type: ignore + ) + + def remove_excess_sprites(self) -> None: + sprite_ids = set(self.sprites.keys()) + entity_ids = set( + entity.get_id() for entity in self.entity_orchestrator.entities + ) + excess_entity_ids = sprite_ids - entity_ids + + for entity_id in excess_entity_ids: + self.sprites.pop(entity_id).delete() + + def draw(self) -> None: + self.remove_excess_sprites() + for entity in self.entity_orchestrator.entities: + if entity.get_id() in self.sprites: + self.update_sprite(entity) + else: + self.add_missing_sprite(entity) + self.batch.draw() + return super().draw() diff --git a/pyoro/graphics/layers/gui_layers/__init__.py b/pyoro/graphics/layers/gui_layers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/graphics/layers/gui_layers/gui_layer.py b/pyoro/graphics/layers/gui_layers/gui_layer.py new file mode 100644 index 0000000..20a6268 --- /dev/null +++ b/pyoro/graphics/layers/gui_layers/gui_layer.py @@ -0,0 +1,7 @@ +from pyoro.graphics.layers.layer import Layer +from pyoro.graphics.layers.layer_level import LayerLevel + + +class GuiLayer(Layer): + def __init__(self) -> None: + super().__init__(LayerLevel.GUI.value) diff --git a/pyoro/graphics/layers/gui_layers/main_menu_gui_layer.py b/pyoro/graphics/layers/gui_layers/main_menu_gui_layer.py new file mode 100644 index 0000000..269a0a3 --- /dev/null +++ b/pyoro/graphics/layers/gui_layers/main_menu_gui_layer.py @@ -0,0 +1,74 @@ +import typing +from pyoro.game.game_state import GameMode +from pyoro.graphics.layers.gui_layers.gui_layer import GuiLayer +from pyoro.graphics.widgets.image import Image +from pyoro.graphics.widgets.image_button import ImageButton +from pyoro.graphics.widgets.anchor import AnchorX, AnchorY +from pyoro.graphics.widgets.text_button import TextButton +from pyoro.graphics.window import Window + + +class MainMenuGuiLayer(GuiLayer): + def __init__( + self, + on_click_play: typing.Callable[[GameMode], None], + on_click_settings: typing.Callable[[], None], + on_click_quit: typing.Callable[[], None], + ): + super().__init__() + + window = Window() + + self.title = Image( + self.batch, + self.group, + window.width // 2, + window.height // 4 * 3, + "gui_title", + anchor_x=AnchorX.CENTER, + anchor_y=AnchorY.CENTER, + ) + self.play_tongue_button = ImageButton( # type: ignore + self.batch, + self.group, + window.width // 4, + window.height // 2, + lambda: on_click_play(GameMode.TONGUE), + "gui_button_play_tongue", + "gui_button_play_tongue_pressed", + "gui_button_play_tongue_hovered", + anchor_x=AnchorX.CENTER, + anchor_y=AnchorY.CENTER, + ) + self.play_seed_button = ImageButton( + self.batch, + self.group, + window.width // 4 * 3, + window.height // 2, + lambda: on_click_play(GameMode.SHOOT), + "gui_button_play_seed", + "gui_button_play_seed_pressed", + "gui_button_play_seed_hovered", + anchor_x=AnchorX.CENTER, + anchor_y=AnchorY.CENTER, + ) + self.settings_button = TextButton( + self.batch, + self.group, + window.width // 4, + window.height // 4, + on_click_settings, + "Settings", + anchor_x=AnchorX.CENTER, + anchor_y=AnchorY.CENTER, + ) + self.quit_button = TextButton( + self.batch, + self.group, + window.width // 4 * 3, + window.height // 4, + on_click_quit, + "Quit", + anchor_x=AnchorX.CENTER, + anchor_y=AnchorY.CENTER, + ) diff --git a/pyoro/graphics/layers/layer.py b/pyoro/graphics/layers/layer.py new file mode 100644 index 0000000..2ae106d --- /dev/null +++ b/pyoro/graphics/layers/layer.py @@ -0,0 +1,10 @@ +import pyglet + + +class Layer: + def __init__(self, layer_level: int) -> None: + self.batch = pyglet.graphics.Batch() + self.group = pyglet.graphics.Group(order=layer_level) + + def draw(self) -> None: + self.batch.draw() diff --git a/pyoro/graphics/layers/layer_level.py b/pyoro/graphics/layers/layer_level.py new file mode 100644 index 0000000..d86e39f --- /dev/null +++ b/pyoro/graphics/layers/layer_level.py @@ -0,0 +1,8 @@ +import enum + + +class LayerLevel(enum.Enum): + BACKGROUND = 0 + ENTITY = 1 + PYORO = 2 + GUI = 3 diff --git a/pyoro/graphics/widgets/__init__.py b/pyoro/graphics/widgets/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/graphics/widgets/anchor.py b/pyoro/graphics/widgets/anchor.py new file mode 100644 index 0000000..854953b --- /dev/null +++ b/pyoro/graphics/widgets/anchor.py @@ -0,0 +1,34 @@ +import enum + + +class AnchorX(enum.Enum): + LEFT = "left" + CENTER = "center" + RIGHT = "right" + + +class AnchorY(enum.Enum): + TOP = "top" + CENTER = "center" + BOTTOM = "bottom" + BASELINE = "baseline" + + +def calculate_x(anchor: AnchorX, x: int, width: int) -> int: + if anchor == AnchorX.LEFT: + return x + elif anchor == AnchorX.CENTER: + return x - width // 2 + elif anchor == AnchorX.RIGHT: + return x - width + + +def calculate_y(anchor: AnchorY, y: int, height: int) -> int: + if anchor == AnchorY.TOP: + return y + elif anchor == AnchorY.CENTER: + return y - height // 2 + elif anchor == AnchorY.BOTTOM: + return y - height + elif anchor == AnchorY.BASELINE: + return y diff --git a/pyoro/graphics/widgets/button.py b/pyoro/graphics/widgets/button.py new file mode 100644 index 0000000..8e9fdb8 --- /dev/null +++ b/pyoro/graphics/widgets/button.py @@ -0,0 +1,7 @@ +import pyglet + +from pyoro.graphics.widgets.widget import Widget + + +class Button(Widget, pyglet.gui.PushButton): + pass diff --git a/pyoro/graphics/widgets/image.py b/pyoro/graphics/widgets/image.py new file mode 100644 index 0000000..8f6dd92 --- /dev/null +++ b/pyoro/graphics/widgets/image.py @@ -0,0 +1,30 @@ +import pyglet + +from pyoro.banks.image_bank import ImageBank +from pyoro.graphics.widgets.anchor import AnchorX, AnchorY, calculate_x, calculate_y +from pyoro.graphics.widgets.widget import Widget + + +class Image(Widget): + def __init__( + self, + batch: pyglet.graphics.Batch, + group: pyglet.graphics.Group, + x: int, + y: int, + image_id: str, + anchor_x: AnchorX = AnchorX.LEFT, + anchor_y: AnchorY = AnchorY.BOTTOM, + ): + super().__init__() + + image_bank = ImageBank() + + image = image_bank.get(image_id) + self._image = pyglet.sprite.Sprite( + img=image, + x=calculate_x(anchor_x, x, image.width), + y=calculate_y(anchor_y, y, image.height), + batch=batch, + group=group, + ) diff --git a/pyoro/graphics/widgets/image_button.py b/pyoro/graphics/widgets/image_button.py new file mode 100644 index 0000000..8867119 --- /dev/null +++ b/pyoro/graphics/widgets/image_button.py @@ -0,0 +1,44 @@ +import pyglet +import typing + +from pyoro.banks.image_bank import ImageBank +from pyoro.graphics.widgets.button import Button +from pyoro.graphics.widgets.anchor import AnchorX, AnchorY, calculate_x, calculate_y + + +class ImageButton(Button): + def __init__( + self, + batch: pyglet.graphics.Batch, + group: pyglet.graphics.Group, + x: int, + y: int, + callback: typing.Callable[[], None], + image_id: str, + pressed_image_id: str, + hovered_image_id: str | None = None, + anchor_x: AnchorX = AnchorX.LEFT, + anchor_y: AnchorY = AnchorY.TOP, + ): + image_bank = ImageBank() + image = image_bank.get(image_id) + pressed_image = image_bank.get(pressed_image_id) + hover_image = ( + image_bank.get(hovered_image_id) if hovered_image_id is not None else None + ) + + super().__init__( # type: ignore + x=calculate_x(anchor_x, x, image.width), + y=calculate_y(anchor_y, y, image.height), + pressed=pressed_image, + depressed=image, + hover=hover_image, + batch=batch, + group=group, + ) + + self._callback = callback + + def on_mouse_release(self, x: int, y: int, buttons: int, modifiers: int): + self._callback() + return super().on_mouse_release(x, y, buttons, modifiers) # type: ignore diff --git a/pyoro/graphics/widgets/text_button.py b/pyoro/graphics/widgets/text_button.py new file mode 100644 index 0000000..fb10bd9 --- /dev/null +++ b/pyoro/graphics/widgets/text_button.py @@ -0,0 +1,54 @@ +import pyglet +import typing + +from pyoro.banks.image_bank import ImageBank +from pyoro.graphics.widgets.button import Button +from pyoro.graphics.widgets.anchor import AnchorX, AnchorY, calculate_x, calculate_y + + +class TextButton(Button): + def __init__( + self, + batch: pyglet.graphics.Batch, + group: pyglet.graphics.Group, + x: int, + y: int, + callback: typing.Callable[[], None], + text: str, + anchor_x: AnchorX = AnchorX.LEFT, + anchor_y: AnchorY = AnchorY.TOP, + ): + image_bank = ImageBank() + image = image_bank.get("gui_button_background") + image_pressed = image_bank.get("gui_button_background_pressed") + image_hovered = image_bank.get("gui_button_background_hovered") + + super().__init__( # type: ignore + x=calculate_x(anchor_x, x, image.width), + y=calculate_y(anchor_y, y, image.height), + pressed=image_pressed, + depressed=image, + hover=image_hovered, + batch=batch, + group=group, + ) + + self._callback = callback + + self._label_group = pyglet.graphics.Group(order=group.order + 1) + self._label = pyglet.text.Label( + text, + font_name="Arial", + font_size=12, + x=x + image.width // 2, # type: ignore + y=y + image.height // 2, # type: ignore + anchor_x="center", + anchor_y="center", + color=(255, 255, 255, 255), + batch=batch, + group=self._label_group, + ) + + def on_mouse_release(self, x: int, y: int, buttons: int, modifiers: int): + self._callback() + return super().on_mouse_release(x, y, buttons, modifiers) # type: ignore diff --git a/pyoro/graphics/widgets/widget.py b/pyoro/graphics/widgets/widget.py new file mode 100644 index 0000000..915991d --- /dev/null +++ b/pyoro/graphics/widgets/widget.py @@ -0,0 +1,2 @@ +class Widget: + pass diff --git a/pyoro/graphics/window.py b/pyoro/graphics/window.py new file mode 100644 index 0000000..68f529c --- /dev/null +++ b/pyoro/graphics/window.py @@ -0,0 +1,23 @@ +import logging +import pyglet + +from pyoro.configuration import Configuration +from pyoro.utils.singleton import singleton + + +@singleton +class Window(pyglet.window.Window): + def __init__(self): + logging.info("Initializing") + + super().__init__() # type: ignore + + configuration = Configuration() + self.set_minimum_size(configuration.window_width, configuration.window_height) + self.set_size(configuration.window_width, configuration.window_height) + self.set_caption("Pyoro") # type: ignore + self.set_location(100, 100) # type: ignore + self.set_visible(True) # type: ignore + + def force_update(self): + self.draw(0) diff --git a/pyoro/main.py b/pyoro/main.py new file mode 100644 index 0000000..817ab5b --- /dev/null +++ b/pyoro/main.py @@ -0,0 +1,36 @@ +import logging + +from pyoro.activity.activities.game_activity import GameActivity +from pyoro.activity.activity_manager import ActivityManager +from pyoro.banks.animation_bank import AnimationBank +from pyoro.banks.image_bank import ImageBank +from pyoro.configuration import Configuration +from pyoro.game.game_mode import GameMode +from pyoro.graphics.window import Window + +LOG_FORMAT = "%(asctime)s %(levelname)s [%(module)s] %(message)s" +logging.basicConfig(format=LOG_FORMAT, level=logging.DEBUG) + + +def main(): + logging.info("Initializing singletons") + Window() # Create a window + configuration = Configuration() # Create a default configuration + image_bank = ImageBank() # Create an empty image bank + animation_bank = AnimationBank() + + logging.info("Loading resources") + configuration.load() + image_bank.load() + animation_bank.load() + + logging.info("Starting activities") + activity_manager = ActivityManager() + activity_manager.push_activity(GameActivity(GameMode.TONGUE)) + activity_manager.start() + + logging.info("Nothing to do. Bye!") + + +if __name__ == "__main__": + main() diff --git a/pyoro/utils/__init__.py b/pyoro/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/utils/singleton.py b/pyoro/utils/singleton.py new file mode 100644 index 0000000..a2db313 --- /dev/null +++ b/pyoro/utils/singleton.py @@ -0,0 +1,29 @@ +import typing + +T = typing.TypeVar("T") + + +class SingletonWrapper(typing.Generic[T]): + """ + A singleton wrapper class. Its instances would be created + for each decorated class. + """ + + def __init__(self, cls: typing.Type[T]) -> None: + self.__wrapped__ = cls + self._instance: T | None = None + + def __call__(self, *args: typing.Any, **kwargs: typing.Any) -> T: + """Returns a single instance of decorated class""" + if self._instance is None: + self._instance = self.__wrapped__(*args, **kwargs) + return self._instance + + +def singleton(cls: typing.Type[T]) -> SingletonWrapper[T]: + """ + A singleton decorator. Returns a wrapper objects. A call on that object + returns a single instance object of decorated class. Use the __wrapped__ + attribute to access decorated class directly in unit tests + """ + return SingletonWrapper[T](cls) diff --git a/pyoro/views/__init__.py b/pyoro/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/pyoro/views/game_view.py b/pyoro/views/game_view.py new file mode 100644 index 0000000..fd2b215 --- /dev/null +++ b/pyoro/views/game_view.py @@ -0,0 +1,18 @@ +from pyoro.game.game_engine import GameEngine +from pyoro.graphics.layers.background_layer import BackgroundLayer +from pyoro.graphics.layers.entity_layer import EntityLayer +from pyoro.views.view import View + + +class GameView(View): + def __init__(self, game_engine: GameEngine): + super().__init__() + self.game_engine = game_engine + self.background_layer = BackgroundLayer(self.game_engine.state) + self.entity_layer = EntityLayer(self.game_engine.entity_orchestrator) + + def refresh(self) -> None: + self.background_layer.draw() + self.entity_layer.draw() + + return super().refresh() diff --git a/pyoro/views/main_menu_view.py b/pyoro/views/main_menu_view.py new file mode 100644 index 0000000..d7e5e1f --- /dev/null +++ b/pyoro/views/main_menu_view.py @@ -0,0 +1,23 @@ +import typing +from pyoro.game.game_engine import GameEngine +from pyoro.game.game_mode import GameMode +from pyoro.graphics.layers.gui_layers.main_menu_gui_layer import MainMenuGuiLayer +from pyoro.views.view import View + + +class MainMenuView(View): + def __init__( + self, + game_engine: GameEngine, + on_play: typing.Callable[[GameMode], None], + on_show_settings: typing.Callable[[], None], + on_quit: typing.Callable[[], None], + ) -> None: + super().__init__() + + self.game_engine = game_engine + self.gui_layer = MainMenuGuiLayer( + on_click_play=on_play, + on_click_settings=on_show_settings, + on_click_quit=on_quit, + ) diff --git a/pyoro/views/view.py b/pyoro/views/view.py new file mode 100644 index 0000000..9fcd362 --- /dev/null +++ b/pyoro/views/view.py @@ -0,0 +1,3 @@ +class View: + def refresh(self) -> None: + pass diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..8662254 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,22 @@ +[tool.poetry] +name = "pyoro" +version = "0.1.0" +description = "A GameBoy Advanced game recreated in Python" +authors = ["RedbeanGit "] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +pyglet = "^2.0.15" +numpy = "^2.0.0" + +[tool.poetry.dev-dependencies] +pylint = "^3.0.3" +black = "^23.12.1" + +[tool.poetry.group.dev.dependencies] +pillow = "^10.3.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/src/data/images/entities/angel/angel_0_0.png b/res/images/angels/angel_fly.png similarity index 100% rename from src/data/images/entities/angel/angel_0_0.png rename to res/images/angels/angel_fly.png diff --git a/src/data/images/entities/angel/angel_0_1.png b/res/images/angels/angel_normal.png similarity index 100% rename from src/data/images/entities/angel/angel_0_1.png rename to res/images/angels/angel_normal.png diff --git a/res/images/backgrounds_1/background_1_0.png b/res/images/backgrounds_1/background_1_0.png new file mode 100644 index 0000000..ba1e754 Binary files /dev/null and b/res/images/backgrounds_1/background_1_0.png differ diff --git a/res/images/backgrounds_1/background_1_1.png b/res/images/backgrounds_1/background_1_1.png new file mode 100644 index 0000000..729c3f5 Binary files /dev/null and b/res/images/backgrounds_1/background_1_1.png differ diff --git a/res/images/backgrounds_1/background_1_10.png b/res/images/backgrounds_1/background_1_10.png new file mode 100644 index 0000000..d98ac0a Binary files /dev/null and b/res/images/backgrounds_1/background_1_10.png differ diff --git a/res/images/backgrounds_1/background_1_11.png b/res/images/backgrounds_1/background_1_11.png new file mode 100644 index 0000000..87042c3 Binary files /dev/null and b/res/images/backgrounds_1/background_1_11.png differ diff --git a/res/images/backgrounds_1/background_1_12.png b/res/images/backgrounds_1/background_1_12.png new file mode 100644 index 0000000..eacb927 Binary files /dev/null and b/res/images/backgrounds_1/background_1_12.png differ diff --git a/res/images/backgrounds_1/background_1_13.png b/res/images/backgrounds_1/background_1_13.png new file mode 100644 index 0000000..153e443 Binary files /dev/null and b/res/images/backgrounds_1/background_1_13.png differ diff --git a/res/images/backgrounds_1/background_1_14.png b/res/images/backgrounds_1/background_1_14.png new file mode 100644 index 0000000..eacb927 Binary files /dev/null and b/res/images/backgrounds_1/background_1_14.png differ diff --git a/res/images/backgrounds_1/background_1_15.png b/res/images/backgrounds_1/background_1_15.png new file mode 100644 index 0000000..0f40f6d Binary files /dev/null and b/res/images/backgrounds_1/background_1_15.png differ diff --git a/res/images/backgrounds_1/background_1_16.png b/res/images/backgrounds_1/background_1_16.png new file mode 100644 index 0000000..cf37c08 Binary files /dev/null and b/res/images/backgrounds_1/background_1_16.png differ diff --git a/res/images/backgrounds_1/background_1_17.png b/res/images/backgrounds_1/background_1_17.png new file mode 100644 index 0000000..24c08a1 Binary files /dev/null and b/res/images/backgrounds_1/background_1_17.png differ diff --git a/res/images/backgrounds_1/background_1_18.png b/res/images/backgrounds_1/background_1_18.png new file mode 100644 index 0000000..d10bd9c Binary files /dev/null and b/res/images/backgrounds_1/background_1_18.png differ diff --git a/res/images/backgrounds_1/background_1_19.png b/res/images/backgrounds_1/background_1_19.png new file mode 100644 index 0000000..745b7ae Binary files /dev/null and b/res/images/backgrounds_1/background_1_19.png differ diff --git a/res/images/backgrounds_1/background_1_2.png b/res/images/backgrounds_1/background_1_2.png new file mode 100644 index 0000000..a393b5e Binary files /dev/null and b/res/images/backgrounds_1/background_1_2.png differ diff --git a/res/images/backgrounds_1/background_1_20.png b/res/images/backgrounds_1/background_1_20.png new file mode 100644 index 0000000..43ff03f Binary files /dev/null and b/res/images/backgrounds_1/background_1_20.png differ diff --git a/res/images/backgrounds_1/background_1_3.png b/res/images/backgrounds_1/background_1_3.png new file mode 100644 index 0000000..7267fc2 Binary files /dev/null and b/res/images/backgrounds_1/background_1_3.png differ diff --git a/res/images/backgrounds_1/background_1_4.png b/res/images/backgrounds_1/background_1_4.png new file mode 100644 index 0000000..74053eb Binary files /dev/null and b/res/images/backgrounds_1/background_1_4.png differ diff --git a/res/images/backgrounds_1/background_1_5.png b/res/images/backgrounds_1/background_1_5.png new file mode 100644 index 0000000..1f12d17 Binary files /dev/null and b/res/images/backgrounds_1/background_1_5.png differ diff --git a/res/images/backgrounds_1/background_1_6.png b/res/images/backgrounds_1/background_1_6.png new file mode 100644 index 0000000..8d6c9d2 Binary files /dev/null and b/res/images/backgrounds_1/background_1_6.png differ diff --git a/res/images/backgrounds_1/background_1_7.png b/res/images/backgrounds_1/background_1_7.png new file mode 100644 index 0000000..e51a3bf Binary files /dev/null and b/res/images/backgrounds_1/background_1_7.png differ diff --git a/res/images/backgrounds_1/background_1_8.png b/res/images/backgrounds_1/background_1_8.png new file mode 100644 index 0000000..37c1733 Binary files /dev/null and b/res/images/backgrounds_1/background_1_8.png differ diff --git a/res/images/backgrounds_1/background_1_9.png b/res/images/backgrounds_1/background_1_9.png new file mode 100644 index 0000000..b1d7ce4 Binary files /dev/null and b/res/images/backgrounds_1/background_1_9.png differ diff --git a/src/data/images/entities/bean/bean_0_0.png b/res/images/beans_green/bean_green_left.png similarity index 100% rename from src/data/images/entities/bean/bean_0_0.png rename to res/images/beans_green/bean_green_left.png diff --git a/src/data/images/entities/bean/bean_0_1.png b/res/images/beans_green/bean_green_middle.png similarity index 100% rename from src/data/images/entities/bean/bean_0_1.png rename to res/images/beans_green/bean_green_middle.png diff --git a/src/data/images/entities/bean/bean_0_2.png b/res/images/beans_green/bean_green_right.png similarity index 100% rename from src/data/images/entities/bean/bean_0_2.png rename to res/images/beans_green/bean_green_right.png diff --git a/src/data/images/entities/pink bean/bean_0_0.png b/res/images/beans_pink/bean_pink_left.png similarity index 100% rename from src/data/images/entities/pink bean/bean_0_0.png rename to res/images/beans_pink/bean_pink_left.png diff --git a/src/data/images/entities/pink bean/bean_0_1.png b/res/images/beans_pink/bean_pink_middle.png similarity index 100% rename from src/data/images/entities/pink bean/bean_0_1.png rename to res/images/beans_pink/bean_pink_middle.png diff --git a/src/data/images/entities/pink bean/bean_0_2.png b/res/images/beans_pink/bean_pink_right.png similarity index 100% rename from src/data/images/entities/pink bean/bean_0_2.png rename to res/images/beans_pink/bean_pink_right.png diff --git a/src/data/images/level/block/block_1.png b/res/images/cases/block_1.png similarity index 100% rename from src/data/images/level/block/block_1.png rename to res/images/cases/block_1.png diff --git a/src/data/images/level/block/block_2.png b/res/images/cases/block_2.png similarity index 100% rename from src/data/images/level/block/block_2.png rename to res/images/cases/block_2.png diff --git a/src/data/images/level/block/block_0.png b/res/images/cases/case.png similarity index 100% rename from src/data/images/level/block/block_0.png rename to res/images/cases/case.png diff --git a/src/data/images/entities/smoke/smoke_0_0.png b/res/images/explosions/explosion_0.png similarity index 100% rename from src/data/images/entities/smoke/smoke_0_0.png rename to res/images/explosions/explosion_0.png diff --git a/src/data/images/entities/smoke/smoke_0_1.png b/res/images/explosions/explosion_1.png similarity index 100% rename from src/data/images/entities/smoke/smoke_0_1.png rename to res/images/explosions/explosion_1.png diff --git a/src/data/images/entities/smoke/smoke_0_2.png b/res/images/explosions/explosion_2.png similarity index 100% rename from src/data/images/entities/smoke/smoke_0_2.png rename to res/images/explosions/explosion_2.png diff --git a/res/images/gui/splash.png b/res/images/gui/splash.png new file mode 100644 index 0000000..a521c7e Binary files /dev/null and b/res/images/gui/splash.png differ diff --git a/src/data/images/gui/title.png b/res/images/gui/title.png similarity index 100% rename from src/data/images/gui/title.png rename to res/images/gui/title.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_die_-1.png b/res/images/pyoros/pyoro_1_die_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_die_-1.png rename to res/images/pyoros/pyoro_1_die_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_die_1.png b/res/images/pyoros/pyoro_1_die_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_die_1.png rename to res/images/pyoros/pyoro_1_die_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_eat_0_-1.png b/res/images/pyoros/pyoro_1_eat_0_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_eat_0_-1.png rename to res/images/pyoros/pyoro_1_eat_0_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_eat_0_1.png b/res/images/pyoros/pyoro_1_eat_0_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_eat_0_1.png rename to res/images/pyoros/pyoro_1_eat_0_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_eat_1_-1.png b/res/images/pyoros/pyoro_1_eat_1_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_eat_1_-1.png rename to res/images/pyoros/pyoro_1_eat_1_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_eat_1_1.png b/res/images/pyoros/pyoro_1_eat_1_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_eat_1_1.png rename to res/images/pyoros/pyoro_1_eat_1_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_jump_-1.png b/res/images/pyoros/pyoro_1_jump_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_jump_-1.png rename to res/images/pyoros/pyoro_1_jump_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_jump_1.png b/res/images/pyoros/pyoro_1_jump_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_jump_1.png rename to res/images/pyoros/pyoro_1_jump_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_normal_-1.png b/res/images/pyoros/pyoro_1_normal_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_normal_-1.png rename to res/images/pyoros/pyoro_1_normal_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_1_normal_1.png b/res/images/pyoros/pyoro_1_normal_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_1_normal_1.png rename to res/images/pyoros/pyoro_1_normal_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_die_-1.png b/res/images/pyoros/pyoro_2_die_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_die_-1.png rename to res/images/pyoros/pyoro_2_die_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_die_1.png b/res/images/pyoros/pyoro_2_die_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_die_1.png rename to res/images/pyoros/pyoro_2_die_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_eat_0_-1.png b/res/images/pyoros/pyoro_2_eat_0_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_eat_0_-1.png rename to res/images/pyoros/pyoro_2_eat_0_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_eat_0_1.png b/res/images/pyoros/pyoro_2_eat_0_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_eat_0_1.png rename to res/images/pyoros/pyoro_2_eat_0_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_eat_1_-1.png b/res/images/pyoros/pyoro_2_eat_1_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_eat_1_-1.png rename to res/images/pyoros/pyoro_2_eat_1_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_eat_1_1.png b/res/images/pyoros/pyoro_2_eat_1_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_eat_1_1.png rename to res/images/pyoros/pyoro_2_eat_1_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_jump_-1.png b/res/images/pyoros/pyoro_2_jump_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_jump_-1.png rename to res/images/pyoros/pyoro_2_jump_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_jump_1.png b/res/images/pyoros/pyoro_2_jump_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_jump_1.png rename to res/images/pyoros/pyoro_2_jump_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_normal_-1.png b/res/images/pyoros/pyoro_2_normal_-1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_normal_-1.png rename to res/images/pyoros/pyoro_2_normal_-1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_2_normal_1.png b/res/images/pyoros/pyoro_2_normal_1.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_2_normal_1.png rename to res/images/pyoros/pyoro_2_normal_1.png diff --git a/src/data/images/entities/pyoro 1/pyoro_0_die_1.png b/res/images/pyoros/pyoro_dead.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_0_die_1.png rename to res/images/pyoros/pyoro_dead.png diff --git a/src/data/images/entities/pyoro 1/pyoro_0_eat_0_1.png b/res/images/pyoros/pyoro_eat.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_0_eat_0_1.png rename to res/images/pyoros/pyoro_eat.png diff --git a/src/data/images/entities/pyoro 1/pyoro_0_jump_1.png b/res/images/pyoros/pyoro_jump.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_0_jump_1.png rename to res/images/pyoros/pyoro_jump.png diff --git a/src/data/images/entities/pyoro 1/pyoro_0_normal_1.png b/res/images/pyoros/pyoro_normal.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_0_normal_1.png rename to res/images/pyoros/pyoro_normal.png diff --git a/src/data/images/entities/pyoro 1/pyoro_0_eat_1_1.png b/res/images/pyoros/pyoro_tongue.png similarity index 100% rename from src/data/images/entities/pyoro 1/pyoro_0_eat_1_1.png rename to res/images/pyoros/pyoro_tongue.png diff --git a/res/images/scores/score_10.png b/res/images/scores/score_10.png new file mode 100644 index 0000000..4202f2e Binary files /dev/null and b/res/images/scores/score_10.png differ diff --git a/res/images/scores/score_100.png b/res/images/scores/score_100.png new file mode 100644 index 0000000..3660a68 Binary files /dev/null and b/res/images/scores/score_100.png differ diff --git a/src/data/images/entities/score text/number_1000_0.png b/res/images/scores/score_1000_0.png similarity index 100% rename from src/data/images/entities/score text/number_1000_0.png rename to res/images/scores/score_1000_0.png diff --git a/src/data/images/entities/score text/number_1000_1.png b/res/images/scores/score_1000_1.png similarity index 100% rename from src/data/images/entities/score text/number_1000_1.png rename to res/images/scores/score_1000_1.png diff --git a/src/data/images/entities/score text/number_1000_2.png b/res/images/scores/score_1000_2.png similarity index 100% rename from src/data/images/entities/score text/number_1000_2.png rename to res/images/scores/score_1000_2.png diff --git a/src/data/images/entities/score text/number_1000_3.png b/res/images/scores/score_1000_3.png similarity index 100% rename from src/data/images/entities/score text/number_1000_3.png rename to res/images/scores/score_1000_3.png diff --git a/src/data/images/entities/score text/number_1000_4.png b/res/images/scores/score_1000_4.png similarity index 100% rename from src/data/images/entities/score text/number_1000_4.png rename to res/images/scores/score_1000_4.png diff --git a/src/data/images/entities/score text/number_1000_5.png b/res/images/scores/score_1000_5.png similarity index 100% rename from src/data/images/entities/score text/number_1000_5.png rename to res/images/scores/score_1000_5.png diff --git a/res/images/scores/score_300_0.png b/res/images/scores/score_300_0.png new file mode 100644 index 0000000..ca6e2a8 Binary files /dev/null and b/res/images/scores/score_300_0.png differ diff --git a/res/images/scores/score_300_1.png b/res/images/scores/score_300_1.png new file mode 100644 index 0000000..11cfb9b Binary files /dev/null and b/res/images/scores/score_300_1.png differ diff --git a/res/images/scores/score_300_2.png b/res/images/scores/score_300_2.png new file mode 100644 index 0000000..3326bda Binary files /dev/null and b/res/images/scores/score_300_2.png differ diff --git a/res/images/scores/score_300_3.png b/res/images/scores/score_300_3.png new file mode 100644 index 0000000..071a8c5 Binary files /dev/null and b/res/images/scores/score_300_3.png differ diff --git a/res/images/scores/score_300_4.png b/res/images/scores/score_300_4.png new file mode 100644 index 0000000..5b01502 Binary files /dev/null and b/res/images/scores/score_300_4.png differ diff --git a/res/images/scores/score_300_5.png b/res/images/scores/score_300_5.png new file mode 100644 index 0000000..d74a13f Binary files /dev/null and b/res/images/scores/score_300_5.png differ diff --git a/res/images/scores/score_50.png b/res/images/scores/score_50.png new file mode 100644 index 0000000..31cd5a0 Binary files /dev/null and b/res/images/scores/score_50.png differ diff --git a/res/images/tongues/tongue.png b/res/images/tongues/tongue.png new file mode 100644 index 0000000..0ad0654 Binary files /dev/null and b/res/images/tongues/tongue.png differ diff --git a/res/images/tongues/tongue_piece.png b/res/images/tongues/tongue_piece.png new file mode 100644 index 0000000..95a32c3 Binary files /dev/null and b/res/images/tongues/tongue_piece.png differ diff --git a/scripts/resize_images.py b/scripts/resize_images.py new file mode 100644 index 0000000..543c4f9 --- /dev/null +++ b/scripts/resize_images.py @@ -0,0 +1,22 @@ +import os +from PIL import Image + + +def resize_images(input_folder: str, size: tuple[int, int]): + for filename in os.listdir(input_folder): + if filename.lower().endswith(("png", "jpg", "jpeg", "bmp", "gif")): + image_path = os.path.join(input_folder, filename) + img = Image.open(image_path) # type: ignore + + # Resize without interpolation + img_resized = img.resize(size, Image.NEAREST) # type: ignore + + # Save resized image + output_path = os.path.join(input_folder, filename) + img_resized.save(output_path) # type: ignore + + +input_folder = input("Input folder=") +size = (int(input("New width=")), int(input("New height="))) + +resize_images(input_folder, size) diff --git a/src/audio/audio_player.py b/src/audio/audio_player.py deleted file mode 100644 index db4f714..0000000 --- a/src/audio/audio_player.py +++ /dev/null @@ -1,362 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide methods to play and manage sounds -and musics - -Created on 27/08/2018 -""" - -import os -import audioop -import threading -import pyaudio - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from audio.sound import Sound -from audio.music import Music -from game.config import LOW_AUDIO -from game.util import get_resource_paths - - -class AudioPlayer: - """ - Play sounds and musics with a defined volume and speed. - - Actually, only sound files with 2 channels, a 44100Hz framerate - and an audio format defined on 32bit can be played correctly! It will - be updated in the future. - """ - - default_framerate = 44100 # CD quality (22050 samples per second) - - def __init__(self, nb_channels=2, samples_width=2, chunk_size=1024): - """ - Initialize the AudioPlayer object. - - :type nb_channels: int - :param nb_channels: Number of output channels (1=mono, 2=stereo). - - :type samples_width: int - :param samples_width: Number of bytes per sample - (1 = 8bits, 2 = 16bits, ...). - - :type chunk_size: int - :param chunk_size: Number of samples per chunk. - """ - - print("[INFO] [AudioPlayer.__init__] Opening audio stream") - self.nb_channels = nb_channels - self.samples_width = samples_width - self.chunk_size = chunk_size - self.framerate = AudioPlayer.default_framerate - - self.pyaudio_instance = pyaudio.PyAudio() - self.stream = self.pyaudio_instance.open( - format=self.pyaudio_instance.get_format_from_width( - self.samples_width), - rate=AudioPlayer.default_framerate, - channels=self.nb_channels, - output=True - ) - - self.sounds = {} - self.musics = {} - self.mixer = [] - - self.sound_volume = 1 - self.music_volume = 1 - - self.active = False - self.thread = None - self.lock = threading.RLock() - - def load_audio(self): - """ - Load the sounds and musics in the default audio data location. - """ - - print("[INFO] [AudioPlayer.load_audio] Loading sounds and musics") - for sound_path in get_resource_paths("sounds"): - self.load_sound(os.path.join("data", *sound_path)) - for music_path in get_resource_paths("musics"): - self.load_music(os.path.join("data", *music_path)) - - def load_sound(self, sound_path): - """ - Load a specific wav file as a Sound in a defined path. - - :type sound_path: str - :param sound_path: The file path of the sound to load. - """ - - snd = Sound(self) - snd.load(sound_path) - self.sounds[sound_path] = snd - - def load_music(self, music_path): - """ - Load a specific wav file as a Music in a defined path. - - :type music_path: str - :param music_path: The file path of the music to load. - """ - - msc = Music(self) - msc.load(music_path) - self.musics[music_path] = msc - - def get_sound(self, sound_path): - """ - Get a loaded sound. If the sound file at the given - path is not loaded, return an empty sound. - - :type sound_path: str - :param sound_path: The path of the sound file. - - :rtype: audio.sound.Sound - :returns: A loaded sound. - """ - - if sound_path in self.sounds: - snd = self.sounds[sound_path].copy() - else: - print('[WARNING] [AudioPlayer.get_sound] Unable to get ' - + f'"{sound_path}" ! Creating empty sound') - snd = Sound(self) - snd.file_path = sound_path - self.sounds[sound_path, "copy", snd] = snd - return snd - - def get_music(self, music_path): - """ - Get a loaded music. If the music file at the given - path is not loaded, return an empty sound. - - :type music_path: str - :param music_path: The path of the music file. - - :rtype: audio.music.Music - :returns: A loaded music or empty sound. - """ - - if music_path in self.musics: - return self.musics[music_path] - print('[WARNING] [AudioPlayer.get_music] Unable to get ' - + f'"{music_path}" ! Creating empty sound') - snd = Sound(self) - snd.file_path = music_path - return snd - - def remove_sound(self, sound): - """ - Remove a sound from the sound list. - - :type sound: audio.sound.Sound - :param sound: The sound to remove. - """ - - if (sound.file_path, "copy", sound) in self.sounds: - self.sounds.pop((sound.file_path, "copy", sound)) - - def remove_music(self, music): - """ - Remove a music from the music list. - - :type music: audio.music.Music - :param music: The music to remove. - """ - - if music.file_path in self.musics: - self.musics.pop(music.file_path) - - def is_playable(self, sound): - """ - Check if the sound can be played by this AudioPlayer. - - :type sound: audio.sound.Sound - :param sound: The sound to check. - - :rtype: bool - :returns: True if the sound is playable, otherwise False. - """ - - return sound.samples_width == self.samples_width \ - and sound.nb_channels == self.nb_channels - - def start(self): - """ - Start the audio player in a new thread. - """ - - def loop(): - while self.active: - if LOW_AUDIO: - self.update_low() - else: - self.update() - - self.active = True - self.thread = threading.Thread(target=loop) - self.thread.start() - print("[INFO] [AudioPlayer.start] Player started in a new thread") - - def stop(self): - """ - Stop the audio player if started. - """ - - if self.active and self.thread: - print("[INFO] [AudioPlayer.stop] Stopping player") - self.active = False - self.thread.join() - else: - print("[WARNING] [AudioPlayer.stop] AudioPlayer already stopped") - - def is_music(self, sound): - """ - Return True if the given sound is a Music instance. - - :type sound: audio.sound.Sound - :param sound: The sound to check. - - :rtype: bool - :returns: True if the sound is a music, otherwise False. - """ - return isinstance(sound, Music) - - def update(self): - """ - Update sounds and music and play a new audio sample. - """ - - with self.lock: - framerate = int(self.framerate) - chunks = bytes() - for sound in self.mixer: - if sound.is_playing and self.is_playable(sound): - if self.is_music(sound): - volume = self.music_volume - else: - volume = self.sound_volume - - chunk = sound.set_chunk_framerate( - sound.set_chunk_volume( - sound.update(), - volume * sound.volume), - framerate) - if chunks: - chunks = audioop.add(chunks, chunk, self.samples_width) - else: - chunks = chunk - if chunks: - self.stream.write(chunks) - - def update_low(self): - """ - Update sounds and music and play a new audio samples but use less - resources than AudioPlayer.update() method. - """ - - with self.lock: - framerate = int(self.framerate) - chunks = bytes(self.chunk_size * - self.samples_width * self.nb_channels // 2) - - for sound in self.mixer: - if sound.is_playing and self.is_playable(sound): - if self.is_music(sound): - volume = self.music_volume - else: - volume = self.sound_volume - - chunk = sound.set_chunk_volume(sound.update(), volume - * sound.volume) - chunks = audioop.add(chunks, chunk, self.samples_width) - chunks = audioop.ratecv(chunks, self.samples_width, self.nb_channels, - AudioPlayer.default_framerate, framerate * 2, None)[0] - self.stream.write(chunks) - - def get_music_in_mixer(self): - """ - Get all musics in the mixer. - - :rtype: list - :returns: A list of audio.music.Music. - """ - - return [music for music in self.mixer if isinstance(music, Music)] - - def get_sound_in_mixer(self): - """ - Get all sounds in the mixer. - - :rtype: list - :returns: A list of audio.sound.Sound. - """ - - return [sound for sound in self.mixer if not isinstance(sound, Music)] - - def stop_audio(self): - """ - Stop all sounds and musics in the mixer. - """ - - for sound in self.mixer: - sound.stop() - self.mixer.clear() - - def pause_audio(self): - """ - Pause all sounds and musics in the mixer. - """ - - for sound in self.mixer: - sound.pause() - - def unpause_audio(self): - """ - Unpause sounds and musics in the mixer. - """ - - for sound in self.mixer: - sound.play() - - def set_speed(self, speed): - """ - Set the reading speed of the audio player. - - :type speed: float - :param speed: The speed of the audio player (default is 1) - """ - self.framerate = AudioPlayer.default_framerate / speed - - def get_speed(self): - """ - Get the current reading speed of the audio player. - - :rtype: float - :returns: The current speed of the audio player (-1 if the default - framerate is 0). - """ - - if AudioPlayer.default_framerate != 0: - return AudioPlayer.default_framerate / self.framerate - return -1 diff --git a/src/audio/music.py b/src/audio/music.py deleted file mode 100644 index d5dbf97..0000000 --- a/src/audio/music.py +++ /dev/null @@ -1,150 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a Music class for loading and managing musics. -Ideal for large audio files. For more reactivity, it's better -to use audio.sound.Sound. - -Created on 27/08/2018 -""" - -import os -import wave - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from audio.sound import Sound - - -class Music(Sound): - """ - Made for loading and playing large audio files. - """ - - def __init__(self, audio_player): - """ - Initialize a Music object. - - :type audio_player: audio.audio_player.Audio_player - :param audio_player: The player that will update this Music object. - """ - - Sound.__init__(self, audio_player) - self.wave_file = None - - def load(self, file_path): - """ - Open a wav file at the given path to load it during playback. - - :type file_path: str - :param file_path: The path of the file to load - """ - - if os.path.exists(file_path): - try: - # Openning new stream - self.wave_file = wave.open(file_path, "rb") - self.file_path = file_path, - self.framerate = self.wave_file.getframerate() - self.nb_channels = self.wave_file.getnchannels() - self.samples_width = self.wave_file.getsampwidth() - self.is_loaded = True - except Exception: - print(f'[WARNING] [Music.load] Unable to load "{file_path}"') - else: - print(f'[WARNING] [Music.load] Unable to find "{file_path}"') - - def unload(self): - """ - Clear the sound properties and audio data, and close the wave file. - """ - - if self.is_loaded and self.wave_file: - self.wave_file.close() - Sound.unload(self) - else: - print("[WARNING] [Music.unload] Music not loaded") - - def is_finished(self): - """ - Return True if the playhead has arrived at the end, - otherwise False. - """ - if self.wave_file: - return self.pos >= self.wave_file.getnframes() - - def set_pos(self, pos): - """ - Set the playhead position. - - :type pos: int - :param pos: The new position of the playback - """ - if self.wave_file: - self.wave_file.setpos(pos) - self.pos = pos - - def get_frames(self, nb_frames): - """ - Get a new audio chunk. - - :type nb_frames: int - :param nb_frames: The size of the audio chunk to get - - :rtype: bytes - :returns: A new raw audio chunk - """ - - if self.wave_file: - nb_frames = int(nb_frames) - chunk_size = int(nb_frames / self.nb_channels / self.samples_width) - chunk = self.wave_file.readframes(chunk_size) - self.pos = self.wave_file.tell() - return chunk + bytes(nb_frames - len(chunk)) - - def reset(self): - """ - Set the playhead at the beginning. - """ - - if self.is_loaded and self.wave_file: - self.wave_file.rewind() - else: - print("[WARNING] [Music.get_file_info] Music not loaded") - - def copy(self): - """ - Create a new music with the same properties and audio data as this - music. - - :rtype: audio.music.Music - :returns: A new independant music. - """ - - msc = Music(self.audio_player) - if self.is_loaded: - msc.framerate = self.framerate - msc.nb_channels = self.nb_channels - msc.samples_width = self.samples_width - msc.file_path = self.file_path - msc.samples = self.samples - msc.wave_file = self.wave_file - msc.is_loaded = True - - return msc diff --git a/src/audio/sound.py b/src/audio/sound.py deleted file mode 100644 index 457916b..0000000 --- a/src/audio/sound.py +++ /dev/null @@ -1,323 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a Sound class for loading and managing sounds. -Ideal for small audio files. For larger files, it's better -to use audio.music.Music. - -Created on 23/08/2018 -""" - -import audioop -import os -import wave - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -class Sound: - """ - Made for loading and playing small audio files by loading - them completly in memory. - """ - - def __init__(self, audio_player): - """ - Initialize a Sound object. - - :type audio_player: audio.audio_player.Audio_player - :param audio_player: The player that will update this Sound object. - """ - - self.audio_player = audio_player - self.samples = bytes() - - self.is_loaded = False - self.is_playing = False - - self.file_path = "" - self.framerate = 0 - self.nb_channels = 0 - self.samples_width = 0 - - self.pos = 0 - self.loop = 1 - self.volume = 1 - - def load(self, file_path): - """ - Loads a sound from a wav file at the given path. - - :type file_path: str - :param file_path: The path of the file to load. - """ - - if os.path.exists(file_path): - try: - with wave.open(file_path, "rb") as wave_file: - self.file_path = file_path - self.framerate = wave_file.getframerate() - self.nb_channels = wave_file.getnchannels() - self.samples_width = wave_file.getsampwidth() - - # Loading sounds samples - self.samples = wave_file.readframes( - wave_file.getnframes() - 1) - self.is_loaded = True - - except Exception: - print(f'[WARNING] [Sound.load] Unable to load "{file_path}"') - else: - print(f'[WARNING] [Sound.load] Unable to find "{file_path}"') - - def unload(self): - """ - Clear the sound properties and audio data. - """ - - if self.is_loaded: - self.file_path = "" - self.framerate = 0 - self.nb_channels = 0 - self.samples_width = 0 - self.samples = bytes() - self.is_loaded = False - else: - print("[WARNING] [Sound.unload] Sound not loaded") - - def play(self, loop=None): - """ - Make the sound be playable by the audio player. - - :type loop: int - :param loop: The number of times to play the sound. - """ - - if self.is_loaded: - self.loop = loop if loop else self.loop - self.is_playing = True - if self not in self.audio_player.mixer: - self.audio_player.mixer.append(self) - else: - print("[WARNING] [Sound.play] Sound not loaded") - - def pause(self): - """ - Prevent the audio player to continue to play this sound. - """ - - if self.is_loaded: - self.is_playing = False - else: - print("[WARNING] [Sound.stop] Sound not loaded") - - def stop(self): - """ - Prevent the audio player to play this sound and reset it. - """ - - if self.is_loaded: - if self.is_playing: - self.is_playing = False - if self in self.audio_player.mixer: - self.audio_player.mixer.remove(self) - self.reset() - self.loop = 1 - else: - print( - f'[WARNING] [Sound.stop] Sound "{self.file_path}" not currently playing') - else: - print("[WARNING] [Sound.stop] Sound not loaded") - - def update(self): - """ - Update the sound by playing a new audio chunk. - - :rtype: bytes - :returns: Raw audio data. - """ - - if self.is_loaded: - if self.is_playing: - if self.is_finished(): - self.end_loop() - if self.is_playing: - return self.get_frames(self.get_chunk_size()) - return bytes(self.get_chunk_size()) - - chunk = self.get_frames(self.get_chunk_size()) - return chunk - else: - print( - f'[WARNING] [Sound.update] Sound "{self.file_path}" not currently playing') - else: - print("[WARNING] [Sound.update] Sound not loaded") - - def end_loop(self): - """ - Decrement the loop count and reset the sound if necessary. - """ - - self.loop -= 1 - if self.loop == 0: - self.stop() - else: - self.reset() - - def is_finished(self): - """ - Return True if the playhead has arrived at the end, - otherwise False. - - :rtype: bool - :returns: True if the playback has been arrived at the end, - otherwise False. - """ - - return self.pos >= len(self.samples) - - def set_pos(self, pos): - """ - Set the playhead position. - - :type pos: int - :param pos: The new position of the playback - """ - - if 0 <= pos < len(self.samples): - self.pos = pos - else: - print('[WARNING] [Sound.setPos] Position (defined to ' + - f'{pos}) must be between 0 and {self.samples}') - - def get_frames(self, nb_frames): - """ - Get a new audio chunk. - - :type nb_frames: int - :param nb_frames: The size of the audio chunk to get - - :rtype: bytes - :returns: A new raw audio chunk - """ - - data_length = len(self.samples) - if self.pos < data_length: - chunk = self.samples[self.pos: self.pos+nb_frames] - - # If playback head reached the end - # add some empty bytes to get a chunk of nb_frames size - if self.pos + nb_frames >= data_length: - self.pos = data_length - chunk += bytes(nb_frames - len(chunk)) - else: - self.pos += nb_frames - return chunk - return bytes(nb_frames) - - def set_chunk_volume(self, chunk, volume): - """ - Modify a raw data chunk to change the audio volume. - - :type chunk: bytes - :param chunk: The chunk to modify. - - :type volume: float - :param volume: A floating point value between 0 and 1. - - :rtype: bytes - :returns: A modified audio chunk. - """ - - if self.is_loaded: - return audioop.mul(chunk, - self.samples_width, - volume) - else: - print("[WARNING] [Sound.setChunkVolume] Sound not loaded") - return chunk - - def set_chunk_framerate(self, chunk, framerate): - """ - Modify the framerate of an audio chunk. - - :type chunk: bytes - :param chunk: The chunk to modify. - - :type framerate: int - :param framerate: The new framerate to set. - - :rtype: bytes - :returns: A modified audio chunk. - """ - - if self.is_loaded: - return audioop.ratecv( - chunk, - self.samples_width, - self.nb_channels, - self.framerate, - framerate, - None - )[0] - print("[WARNING] [Sound.setChunkFramerate] Sound not loaded") - return chunk - - def reset(self): - """ - Set the playhead at the beginning. - """ - self.pos = 0 - - def get_chunk_size(self): - """ - Get a the size of an audio chunk according to the number of channels, - the width of each samples and the number of samples per chunk. - - :rtype: int - :returns: The size of an audio chunk in bytes. - """ - - if self.is_loaded: - return int(self.audio_player.chunk_size - * self.nb_channels - * self.samples_width - * self.framerate - / self.audio_player.default_framerate) - print("[WARNING] [Sound.get_chunk_size] Sound not loaded") - return 0 - - def copy(self): - """ - Create a new sound with the same properties and audio data as this - sound. - - :rtype: audio.sound.Sound - :returns: A new independant sound. - """ - - snd = Sound(self.audio_player) - if self.is_loaded: - snd.framerate = self.framerate - snd.nb_channels = self.nb_channels - snd.samples_width = self.samples_width - snd.file_path = self.file_path - snd.samples = self.samples - snd.is_loaded = True - return snd diff --git a/src/data/audio/musics/drums.wav b/src/data/audio/musics/drums.wav deleted file mode 100644 index a6c2d58..0000000 Binary files a/src/data/audio/musics/drums.wav and /dev/null differ diff --git a/src/data/audio/musics/game_over.wav b/src/data/audio/musics/game_over.wav deleted file mode 100644 index 9b5686a..0000000 Binary files a/src/data/audio/musics/game_over.wav and /dev/null differ diff --git a/src/data/audio/musics/intro.wav b/src/data/audio/musics/intro.wav deleted file mode 100644 index f4335ca..0000000 Binary files a/src/data/audio/musics/intro.wav and /dev/null differ diff --git a/src/data/audio/musics/music_0.wav b/src/data/audio/musics/music_0.wav deleted file mode 100644 index 940121c..0000000 Binary files a/src/data/audio/musics/music_0.wav and /dev/null differ diff --git a/src/data/audio/musics/music_1.wav b/src/data/audio/musics/music_1.wav deleted file mode 100644 index d218999..0000000 Binary files a/src/data/audio/musics/music_1.wav and /dev/null differ diff --git a/src/data/audio/musics/music_2.wav b/src/data/audio/musics/music_2.wav deleted file mode 100644 index 7d8f6ed..0000000 Binary files a/src/data/audio/musics/music_2.wav and /dev/null differ diff --git a/src/data/audio/musics/organ.wav b/src/data/audio/musics/organ.wav deleted file mode 100644 index 531173e..0000000 Binary files a/src/data/audio/musics/organ.wav and /dev/null differ diff --git a/src/data/audio/musics/speed_drums.wav b/src/data/audio/musics/speed_drums.wav deleted file mode 100644 index 5190d15..0000000 Binary files a/src/data/audio/musics/speed_drums.wav and /dev/null differ diff --git a/src/data/audio/original unused/angel.mp3 b/src/data/audio/original unused/angel.mp3 deleted file mode 100644 index 9d52353..0000000 Binary files a/src/data/audio/original unused/angel.mp3 and /dev/null differ diff --git a/src/data/audio/original unused/drums.wav b/src/data/audio/original unused/drums.wav deleted file mode 100644 index 78bc6c8..0000000 Binary files a/src/data/audio/original unused/drums.wav and /dev/null differ diff --git a/src/data/audio/original unused/music_1_original.wav b/src/data/audio/original unused/music_1_original.wav deleted file mode 100644 index 07d5bea..0000000 Binary files a/src/data/audio/original unused/music_1_original.wav and /dev/null differ diff --git a/src/data/audio/original unused/music_2_original.wav b/src/data/audio/original unused/music_2_original.wav deleted file mode 100644 index e64e0fb..0000000 Binary files a/src/data/audio/original unused/music_2_original.wav and /dev/null differ diff --git a/src/data/audio/original unused/music_3_original.wav b/src/data/audio/original unused/music_3_original.wav deleted file mode 100644 index a6b4b57..0000000 Binary files a/src/data/audio/original unused/music_3_original.wav and /dev/null differ diff --git a/src/data/audio/original unused/organ.wav b/src/data/audio/original unused/organ.wav deleted file mode 100644 index 88b4c18..0000000 Binary files a/src/data/audio/original unused/organ.wav and /dev/null differ diff --git a/src/data/audio/original unused/rewind_old.wav b/src/data/audio/original unused/rewind_old.wav deleted file mode 100644 index 473af51..0000000 Binary files a/src/data/audio/original unused/rewind_old.wav and /dev/null differ diff --git a/src/data/audio/original unused/speed_drums.mp3 b/src/data/audio/original unused/speed_drums.mp3 deleted file mode 100644 index 0b29c09..0000000 Binary files a/src/data/audio/original unused/speed_drums.mp3 and /dev/null differ diff --git a/src/data/audio/sounds/angel_down.wav b/src/data/audio/sounds/angel_down.wav deleted file mode 100644 index b00c8fd..0000000 Binary files a/src/data/audio/sounds/angel_down.wav and /dev/null differ diff --git a/src/data/audio/sounds/bean_cut.wav b/src/data/audio/sounds/bean_cut.wav deleted file mode 100644 index 4d10c06..0000000 Binary files a/src/data/audio/sounds/bean_cut.wav and /dev/null differ diff --git a/src/data/audio/sounds/bean_explode.wav b/src/data/audio/sounds/bean_explode.wav deleted file mode 100644 index 86edf41..0000000 Binary files a/src/data/audio/sounds/bean_explode.wav and /dev/null differ diff --git a/src/data/audio/sounds/bean_implode.wav b/src/data/audio/sounds/bean_implode.wav deleted file mode 100644 index 86edf41..0000000 Binary files a/src/data/audio/sounds/bean_implode.wav and /dev/null differ diff --git a/src/data/audio/sounds/pyoro_die.wav b/src/data/audio/sounds/pyoro_die.wav deleted file mode 100644 index 210d1d1..0000000 Binary files a/src/data/audio/sounds/pyoro_die.wav and /dev/null differ diff --git a/src/data/audio/sounds/pyoro_eat.wav b/src/data/audio/sounds/pyoro_eat.wav deleted file mode 100644 index 80ca3f0..0000000 Binary files a/src/data/audio/sounds/pyoro_eat.wav and /dev/null differ diff --git a/src/data/audio/sounds/pyoro_move.wav b/src/data/audio/sounds/pyoro_move.wav deleted file mode 100644 index 5d56ff1..0000000 Binary files a/src/data/audio/sounds/pyoro_move.wav and /dev/null differ diff --git a/src/data/audio/sounds/tongue.wav b/src/data/audio/sounds/tongue.wav deleted file mode 100644 index a7cb9bc..0000000 Binary files a/src/data/audio/sounds/tongue.wav and /dev/null differ diff --git a/src/data/images/entities/angel/angel_1_0.png b/src/data/images/entities/angel/angel_1_0.png deleted file mode 100644 index 0deee95..0000000 Binary files a/src/data/images/entities/angel/angel_1_0.png and /dev/null differ diff --git a/src/data/images/entities/angel/angel_1_1.png b/src/data/images/entities/angel/angel_1_1.png deleted file mode 100644 index d7fd1c6..0000000 Binary files a/src/data/images/entities/angel/angel_1_1.png and /dev/null differ diff --git a/src/data/images/entities/angel/angel_2_0.png b/src/data/images/entities/angel/angel_2_0.png deleted file mode 100644 index f526933..0000000 Binary files a/src/data/images/entities/angel/angel_2_0.png and /dev/null differ diff --git a/src/data/images/entities/angel/angel_2_1.png b/src/data/images/entities/angel/angel_2_1.png deleted file mode 100644 index 1f58123..0000000 Binary files a/src/data/images/entities/angel/angel_2_1.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_1_0.png b/src/data/images/entities/bean/bean_1_0.png deleted file mode 100644 index 0fa4c5d..0000000 Binary files a/src/data/images/entities/bean/bean_1_0.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_1_1.png b/src/data/images/entities/bean/bean_1_1.png deleted file mode 100644 index 107f906..0000000 Binary files a/src/data/images/entities/bean/bean_1_1.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_1_2.png b/src/data/images/entities/bean/bean_1_2.png deleted file mode 100644 index 54d02a5..0000000 Binary files a/src/data/images/entities/bean/bean_1_2.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_2_0.png b/src/data/images/entities/bean/bean_2_0.png deleted file mode 100644 index 9050a30..0000000 Binary files a/src/data/images/entities/bean/bean_2_0.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_2_1.png b/src/data/images/entities/bean/bean_2_1.png deleted file mode 100644 index e2b38e6..0000000 Binary files a/src/data/images/entities/bean/bean_2_1.png and /dev/null differ diff --git a/src/data/images/entities/bean/bean_2_2.png b/src/data/images/entities/bean/bean_2_2.png deleted file mode 100644 index 6b3c6bf..0000000 Binary files a/src/data/images/entities/bean/bean_2_2.png and /dev/null differ diff --git a/src/data/images/entities/bean/name_format.txt b/src/data/images/entities/bean/name_format.txt deleted file mode 100644 index d8cfb77..0000000 --- a/src/data/images/entities/bean/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -bean__.png \ No newline at end of file diff --git a/src/data/images/entities/leaf piece/leafpiece_0_0.png b/src/data/images/entities/leaf piece/leafpiece_0_0.png deleted file mode 100644 index f52adeb..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_0_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_0_1.png b/src/data/images/entities/leaf piece/leafpiece_0_1.png deleted file mode 100644 index 4ce316f..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_0_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_0_2.png b/src/data/images/entities/leaf piece/leafpiece_0_2.png deleted file mode 100644 index 9921193..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_0_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_1_0.png b/src/data/images/entities/leaf piece/leafpiece_1_0.png deleted file mode 100644 index 4e9b550..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_1_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_1_1.png b/src/data/images/entities/leaf piece/leafpiece_1_1.png deleted file mode 100644 index 1ee2b1c..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_1_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_1_2.png b/src/data/images/entities/leaf piece/leafpiece_1_2.png deleted file mode 100644 index 801e9cb..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_1_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_2_0.png b/src/data/images/entities/leaf piece/leafpiece_2_0.png deleted file mode 100644 index 0a49e4a..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_2_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_2_1.png b/src/data/images/entities/leaf piece/leafpiece_2_1.png deleted file mode 100644 index 81ddd7a..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_2_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/leafpiece_2_2.png b/src/data/images/entities/leaf piece/leafpiece_2_2.png deleted file mode 100644 index f712709..0000000 Binary files a/src/data/images/entities/leaf piece/leafpiece_2_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf piece/name_format.txt b/src/data/images/entities/leaf piece/name_format.txt deleted file mode 100644 index e336c8c..0000000 --- a/src/data/images/entities/leaf piece/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leafpiece__.png \ No newline at end of file diff --git a/src/data/images/entities/leaf/leaf_0_0.png b/src/data/images/entities/leaf/leaf_0_0.png deleted file mode 100644 index b31d438..0000000 Binary files a/src/data/images/entities/leaf/leaf_0_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_0_1.png b/src/data/images/entities/leaf/leaf_0_1.png deleted file mode 100644 index c1113f7..0000000 Binary files a/src/data/images/entities/leaf/leaf_0_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_0_2.png b/src/data/images/entities/leaf/leaf_0_2.png deleted file mode 100644 index 788a624..0000000 Binary files a/src/data/images/entities/leaf/leaf_0_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_1_0.png b/src/data/images/entities/leaf/leaf_1_0.png deleted file mode 100644 index 92716ec..0000000 Binary files a/src/data/images/entities/leaf/leaf_1_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_1_1.png b/src/data/images/entities/leaf/leaf_1_1.png deleted file mode 100644 index 33b10da..0000000 Binary files a/src/data/images/entities/leaf/leaf_1_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_1_2.png b/src/data/images/entities/leaf/leaf_1_2.png deleted file mode 100644 index 29bd71f..0000000 Binary files a/src/data/images/entities/leaf/leaf_1_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_2_0.png b/src/data/images/entities/leaf/leaf_2_0.png deleted file mode 100644 index 480b5df..0000000 Binary files a/src/data/images/entities/leaf/leaf_2_0.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_2_1.png b/src/data/images/entities/leaf/leaf_2_1.png deleted file mode 100644 index f8de819..0000000 Binary files a/src/data/images/entities/leaf/leaf_2_1.png and /dev/null differ diff --git a/src/data/images/entities/leaf/leaf_2_2.png b/src/data/images/entities/leaf/leaf_2_2.png deleted file mode 100644 index f797b00..0000000 Binary files a/src/data/images/entities/leaf/leaf_2_2.png and /dev/null differ diff --git a/src/data/images/entities/leaf/name_format.txt b/src/data/images/entities/leaf/name_format.txt deleted file mode 100644 index 2dbe2d5..0000000 --- a/src/data/images/entities/leaf/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leaf__.png \ No newline at end of file diff --git a/src/data/images/entities/pink bean/bean_1_0.png b/src/data/images/entities/pink bean/bean_1_0.png deleted file mode 100644 index 2fec86b..0000000 Binary files a/src/data/images/entities/pink bean/bean_1_0.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/bean_1_1.png b/src/data/images/entities/pink bean/bean_1_1.png deleted file mode 100644 index cee7c7e..0000000 Binary files a/src/data/images/entities/pink bean/bean_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/bean_1_2.png b/src/data/images/entities/pink bean/bean_1_2.png deleted file mode 100644 index b05d565..0000000 Binary files a/src/data/images/entities/pink bean/bean_1_2.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/bean_2_0.png b/src/data/images/entities/pink bean/bean_2_0.png deleted file mode 100644 index 81e6c50..0000000 Binary files a/src/data/images/entities/pink bean/bean_2_0.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/bean_2_1.png b/src/data/images/entities/pink bean/bean_2_1.png deleted file mode 100644 index 5276a19..0000000 Binary files a/src/data/images/entities/pink bean/bean_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/bean_2_2.png b/src/data/images/entities/pink bean/bean_2_2.png deleted file mode 100644 index 3b259f9..0000000 Binary files a/src/data/images/entities/pink bean/bean_2_2.png and /dev/null differ diff --git a/src/data/images/entities/pink bean/name_format.txt b/src/data/images/entities/pink bean/name_format.txt deleted file mode 100644 index d8cfb77..0000000 --- a/src/data/images/entities/pink bean/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -bean__.png \ No newline at end of file diff --git a/src/data/images/entities/pink leaf piece/leafpiece_0_0.png b/src/data/images/entities/pink leaf piece/leafpiece_0_0.png deleted file mode 100644 index 7e3cc3d..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_0_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_0_1.png b/src/data/images/entities/pink leaf piece/leafpiece_0_1.png deleted file mode 100644 index a8414a6..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_0_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_0_2.png b/src/data/images/entities/pink leaf piece/leafpiece_0_2.png deleted file mode 100644 index aa5a4b9..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_0_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_1_0.png b/src/data/images/entities/pink leaf piece/leafpiece_1_0.png deleted file mode 100644 index abaf8df..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_1_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_1_1.png b/src/data/images/entities/pink leaf piece/leafpiece_1_1.png deleted file mode 100644 index 4c57971..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_1_2.png b/src/data/images/entities/pink leaf piece/leafpiece_1_2.png deleted file mode 100644 index 6e249e1..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_1_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_2_0.png b/src/data/images/entities/pink leaf piece/leafpiece_2_0.png deleted file mode 100644 index 0a49e4a..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_2_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_2_1.png b/src/data/images/entities/pink leaf piece/leafpiece_2_1.png deleted file mode 100644 index 81ddd7a..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/leafpiece_2_2.png b/src/data/images/entities/pink leaf piece/leafpiece_2_2.png deleted file mode 100644 index f712709..0000000 Binary files a/src/data/images/entities/pink leaf piece/leafpiece_2_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf piece/name_format.txt b/src/data/images/entities/pink leaf piece/name_format.txt deleted file mode 100644 index e336c8c..0000000 --- a/src/data/images/entities/pink leaf piece/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leafpiece__.png \ No newline at end of file diff --git a/src/data/images/entities/pink leaf/leaf_0_0.png b/src/data/images/entities/pink leaf/leaf_0_0.png deleted file mode 100644 index 50d0ff6..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_0_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_0_1.png b/src/data/images/entities/pink leaf/leaf_0_1.png deleted file mode 100644 index 2d80ee8..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_0_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_0_2.png b/src/data/images/entities/pink leaf/leaf_0_2.png deleted file mode 100644 index b4ecc42..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_0_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_1_0.png b/src/data/images/entities/pink leaf/leaf_1_0.png deleted file mode 100644 index c66a524..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_1_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_1_1.png b/src/data/images/entities/pink leaf/leaf_1_1.png deleted file mode 100644 index 9f76a95..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_1_2.png b/src/data/images/entities/pink leaf/leaf_1_2.png deleted file mode 100644 index 3738ac3..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_1_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_2_0.png b/src/data/images/entities/pink leaf/leaf_2_0.png deleted file mode 100644 index 480b5df..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_2_0.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_2_1.png b/src/data/images/entities/pink leaf/leaf_2_1.png deleted file mode 100644 index f8de819..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/leaf_2_2.png b/src/data/images/entities/pink leaf/leaf_2_2.png deleted file mode 100644 index f797b00..0000000 Binary files a/src/data/images/entities/pink leaf/leaf_2_2.png and /dev/null differ diff --git a/src/data/images/entities/pink leaf/name_format.txt b/src/data/images/entities/pink leaf/name_format.txt deleted file mode 100644 index 2dbe2d5..0000000 --- a/src/data/images/entities/pink leaf/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leaf__.png \ No newline at end of file diff --git a/src/data/images/entities/pyoro 1/name_format.txt b/src/data/images/entities/pyoro 1/name_format.txt deleted file mode 100644 index b05248e..0000000 --- a/src/data/images/entities/pyoro 1/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -pyoro___.png \ No newline at end of file diff --git a/src/data/images/entities/pyoro 1/pyoro_0_die_-1.png b/src/data/images/entities/pyoro 1/pyoro_0_die_-1.png deleted file mode 100644 index 78014d8..0000000 Binary files a/src/data/images/entities/pyoro 1/pyoro_0_die_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 1/pyoro_0_eat_0_-1.png b/src/data/images/entities/pyoro 1/pyoro_0_eat_0_-1.png deleted file mode 100644 index e70d6a0..0000000 Binary files a/src/data/images/entities/pyoro 1/pyoro_0_eat_0_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 1/pyoro_0_eat_1_-1.png b/src/data/images/entities/pyoro 1/pyoro_0_eat_1_-1.png deleted file mode 100644 index cab160e..0000000 Binary files a/src/data/images/entities/pyoro 1/pyoro_0_eat_1_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 1/pyoro_0_jump_-1.png b/src/data/images/entities/pyoro 1/pyoro_0_jump_-1.png deleted file mode 100644 index bd48286..0000000 Binary files a/src/data/images/entities/pyoro 1/pyoro_0_jump_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 1/pyoro_0_normal_-1.png b/src/data/images/entities/pyoro 1/pyoro_0_normal_-1.png deleted file mode 100644 index 9c53b7b..0000000 Binary files a/src/data/images/entities/pyoro 1/pyoro_0_normal_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/name_format.txt b/src/data/images/entities/pyoro 2/name_format.txt deleted file mode 100644 index b05248e..0000000 --- a/src/data/images/entities/pyoro 2/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -pyoro___.png \ No newline at end of file diff --git a/src/data/images/entities/pyoro 2/pyoro_0_die_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_die_-1.png deleted file mode 100644 index f7f972b..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_die_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_die_1.png b/src/data/images/entities/pyoro 2/pyoro_0_die_1.png deleted file mode 100644 index 13f6ab8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_die_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_jump_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_jump_-1.png deleted file mode 100644 index 7c5fa85..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_jump_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_jump_1.png b/src/data/images/entities/pyoro 2/pyoro_0_jump_1.png deleted file mode 100644 index ad8f3b5..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_jump_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_normal_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_normal_-1.png deleted file mode 100644 index 831fe41..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_normal_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_normal_1.png b/src/data/images/entities/pyoro 2/pyoro_0_normal_1.png deleted file mode 100644 index 58f94f8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_normal_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_-1.png deleted file mode 100644 index f0b6b07..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_1.png deleted file mode 100644 index e664bb8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_0_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_-1.png deleted file mode 100644 index cf392dc..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_1.png deleted file mode 100644 index ce5b3bb..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_-1.png deleted file mode 100644 index 059e3eb..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_1.png deleted file mode 100644 index a7f0846..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_-1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_-1.png deleted file mode 100644 index cb292ce..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_1.png b/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_1.png deleted file mode 100644 index 01758a9..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_0_shoot_3_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_die_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_die_-1.png deleted file mode 100644 index 5ea2958..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_die_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_die_1.png b/src/data/images/entities/pyoro 2/pyoro_1_die_1.png deleted file mode 100644 index 9613339..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_die_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_jump_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_jump_-1.png deleted file mode 100644 index e527faa..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_jump_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_jump_1.png b/src/data/images/entities/pyoro 2/pyoro_1_jump_1.png deleted file mode 100644 index feebe42..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_jump_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_normal_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_normal_-1.png deleted file mode 100644 index 5bc8936..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_normal_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_normal_1.png b/src/data/images/entities/pyoro 2/pyoro_1_normal_1.png deleted file mode 100644 index 6025467..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_normal_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_-1.png deleted file mode 100644 index 70edf03..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_1.png deleted file mode 100644 index 58c0167..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_0_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_-1.png deleted file mode 100644 index 7554732..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_1.png deleted file mode 100644 index cbb1ff4..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_-1.png deleted file mode 100644 index 729cf0b..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_1.png deleted file mode 100644 index 7d0dad8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_-1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_-1.png deleted file mode 100644 index f94291a..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_1.png b/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_1.png deleted file mode 100644 index d11d053..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_1_shoot_3_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_die_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_die_-1.png deleted file mode 100644 index a53746f..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_die_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_die_1.png b/src/data/images/entities/pyoro 2/pyoro_2_die_1.png deleted file mode 100644 index 9127871..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_die_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_jump_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_jump_-1.png deleted file mode 100644 index 11400c5..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_jump_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_jump_1.png b/src/data/images/entities/pyoro 2/pyoro_2_jump_1.png deleted file mode 100644 index 6d7bf17..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_jump_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_normal_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_normal_-1.png deleted file mode 100644 index db19bd8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_normal_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_normal_1.png b/src/data/images/entities/pyoro 2/pyoro_2_normal_1.png deleted file mode 100644 index 150af98..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_normal_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_-1.png deleted file mode 100644 index 8a7324b..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_1.png deleted file mode 100644 index 128bb4c..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_0_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_-1.png deleted file mode 100644 index 7e11ba8..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_1.png deleted file mode 100644 index b080d1b..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_1_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_-1.png deleted file mode 100644 index f6a059a..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_1.png deleted file mode 100644 index 4010794..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_2_1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_-1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_-1.png deleted file mode 100644 index 4ea68d5..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_-1.png and /dev/null differ diff --git a/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_1.png b/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_1.png deleted file mode 100644 index e8459c6..0000000 Binary files a/src/data/images/entities/pyoro 2/pyoro_2_shoot_3_1.png and /dev/null differ diff --git a/src/data/images/entities/score text/name_format.txt b/src/data/images/entities/score text/name_format.txt deleted file mode 100644 index 33e066d..0000000 --- a/src/data/images/entities/score text/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -number_.png \ No newline at end of file diff --git a/src/data/images/entities/score text/number_10.png b/src/data/images/entities/score text/number_10.png deleted file mode 100644 index 36070e5..0000000 Binary files a/src/data/images/entities/score text/number_10.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_100.png b/src/data/images/entities/score text/number_100.png deleted file mode 100644 index 61fa24c..0000000 Binary files a/src/data/images/entities/score text/number_100.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_0.png b/src/data/images/entities/score text/number_300_0.png deleted file mode 100644 index 3742990..0000000 Binary files a/src/data/images/entities/score text/number_300_0.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_1.png b/src/data/images/entities/score text/number_300_1.png deleted file mode 100644 index afbdca2..0000000 Binary files a/src/data/images/entities/score text/number_300_1.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_2.png b/src/data/images/entities/score text/number_300_2.png deleted file mode 100644 index cce1f12..0000000 Binary files a/src/data/images/entities/score text/number_300_2.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_3.png b/src/data/images/entities/score text/number_300_3.png deleted file mode 100644 index b4b32e6..0000000 Binary files a/src/data/images/entities/score text/number_300_3.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_4.png b/src/data/images/entities/score text/number_300_4.png deleted file mode 100644 index 2dd13c2..0000000 Binary files a/src/data/images/entities/score text/number_300_4.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_300_5.png b/src/data/images/entities/score text/number_300_5.png deleted file mode 100644 index 334de62..0000000 Binary files a/src/data/images/entities/score text/number_300_5.png and /dev/null differ diff --git a/src/data/images/entities/score text/number_50.png b/src/data/images/entities/score text/number_50.png deleted file mode 100644 index a2d802a..0000000 Binary files a/src/data/images/entities/score text/number_50.png and /dev/null differ diff --git a/src/data/images/entities/seed/seed_0.png b/src/data/images/entities/seed/seed_0.png deleted file mode 100644 index 6e438b2..0000000 Binary files a/src/data/images/entities/seed/seed_0.png and /dev/null differ diff --git a/src/data/images/entities/seed/seed_1.png b/src/data/images/entities/seed/seed_1.png deleted file mode 100644 index 6e438b2..0000000 Binary files a/src/data/images/entities/seed/seed_1.png and /dev/null differ diff --git a/src/data/images/entities/seed/seed_2.png b/src/data/images/entities/seed/seed_2.png deleted file mode 100644 index 6e438b2..0000000 Binary files a/src/data/images/entities/seed/seed_2.png and /dev/null differ diff --git a/src/data/images/entities/smoke/name_format.txt b/src/data/images/entities/smoke/name_format.txt deleted file mode 100644 index 47a0171..0000000 --- a/src/data/images/entities/smoke/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -smoke__.png \ No newline at end of file diff --git a/src/data/images/entities/smoke/smoke_1_0.png b/src/data/images/entities/smoke/smoke_1_0.png deleted file mode 100644 index 62438bf..0000000 Binary files a/src/data/images/entities/smoke/smoke_1_0.png and /dev/null differ diff --git a/src/data/images/entities/smoke/smoke_1_1.png b/src/data/images/entities/smoke/smoke_1_1.png deleted file mode 100644 index 2646b8b..0000000 Binary files a/src/data/images/entities/smoke/smoke_1_1.png and /dev/null differ diff --git a/src/data/images/entities/smoke/smoke_1_2.png b/src/data/images/entities/smoke/smoke_1_2.png deleted file mode 100644 index 3554920..0000000 Binary files a/src/data/images/entities/smoke/smoke_1_2.png and /dev/null differ diff --git a/src/data/images/entities/smoke/smoke_2_0.png b/src/data/images/entities/smoke/smoke_2_0.png deleted file mode 100644 index 3520a4c..0000000 Binary files a/src/data/images/entities/smoke/smoke_2_0.png and /dev/null differ diff --git a/src/data/images/entities/smoke/smoke_2_1.png b/src/data/images/entities/smoke/smoke_2_1.png deleted file mode 100644 index 221973d..0000000 Binary files a/src/data/images/entities/smoke/smoke_2_1.png and /dev/null differ diff --git a/src/data/images/entities/smoke/smoke_2_2.png b/src/data/images/entities/smoke/smoke_2_2.png deleted file mode 100644 index dd108fe..0000000 Binary files a/src/data/images/entities/smoke/smoke_2_2.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_0.png b/src/data/images/entities/super bean/bean_0_0.png deleted file mode 100644 index d64a501..0000000 Binary files a/src/data/images/entities/super bean/bean_0_0.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_1.png b/src/data/images/entities/super bean/bean_0_1.png deleted file mode 100644 index 0d9b45e..0000000 Binary files a/src/data/images/entities/super bean/bean_0_1.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_2.png b/src/data/images/entities/super bean/bean_0_2.png deleted file mode 100644 index 07be542..0000000 Binary files a/src/data/images/entities/super bean/bean_0_2.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_3.png b/src/data/images/entities/super bean/bean_0_3.png deleted file mode 100644 index 0768fc0..0000000 Binary files a/src/data/images/entities/super bean/bean_0_3.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_4.png b/src/data/images/entities/super bean/bean_0_4.png deleted file mode 100644 index a6453bb..0000000 Binary files a/src/data/images/entities/super bean/bean_0_4.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_0_5.png b/src/data/images/entities/super bean/bean_0_5.png deleted file mode 100644 index d633350..0000000 Binary files a/src/data/images/entities/super bean/bean_0_5.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_0.png b/src/data/images/entities/super bean/bean_1_0.png deleted file mode 100644 index 9bb21e6..0000000 Binary files a/src/data/images/entities/super bean/bean_1_0.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_1.png b/src/data/images/entities/super bean/bean_1_1.png deleted file mode 100644 index d9b8ec9..0000000 Binary files a/src/data/images/entities/super bean/bean_1_1.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_2.png b/src/data/images/entities/super bean/bean_1_2.png deleted file mode 100644 index c8dcd31..0000000 Binary files a/src/data/images/entities/super bean/bean_1_2.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_3.png b/src/data/images/entities/super bean/bean_1_3.png deleted file mode 100644 index d3e34b2..0000000 Binary files a/src/data/images/entities/super bean/bean_1_3.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_4.png b/src/data/images/entities/super bean/bean_1_4.png deleted file mode 100644 index 3aa882c..0000000 Binary files a/src/data/images/entities/super bean/bean_1_4.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_1_5.png b/src/data/images/entities/super bean/bean_1_5.png deleted file mode 100644 index e530b2a..0000000 Binary files a/src/data/images/entities/super bean/bean_1_5.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_0.png b/src/data/images/entities/super bean/bean_2_0.png deleted file mode 100644 index 90b7edb..0000000 Binary files a/src/data/images/entities/super bean/bean_2_0.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_1.png b/src/data/images/entities/super bean/bean_2_1.png deleted file mode 100644 index b63d79e..0000000 Binary files a/src/data/images/entities/super bean/bean_2_1.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_2.png b/src/data/images/entities/super bean/bean_2_2.png deleted file mode 100644 index d9ea09c..0000000 Binary files a/src/data/images/entities/super bean/bean_2_2.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_3.png b/src/data/images/entities/super bean/bean_2_3.png deleted file mode 100644 index f378e30..0000000 Binary files a/src/data/images/entities/super bean/bean_2_3.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_4.png b/src/data/images/entities/super bean/bean_2_4.png deleted file mode 100644 index c525b9b..0000000 Binary files a/src/data/images/entities/super bean/bean_2_4.png and /dev/null differ diff --git a/src/data/images/entities/super bean/bean_2_5.png b/src/data/images/entities/super bean/bean_2_5.png deleted file mode 100644 index b88b5f2..0000000 Binary files a/src/data/images/entities/super bean/bean_2_5.png and /dev/null differ diff --git a/src/data/images/entities/super bean/name_format.txt b/src/data/images/entities/super bean/name_format.txt deleted file mode 100644 index f144f89..0000000 --- a/src/data/images/entities/super bean/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -bean__.png \ No newline at end of file diff --git a/src/data/images/entities/super leaf piece/leafpiece_0_0.png b/src/data/images/entities/super leaf piece/leafpiece_0_0.png deleted file mode 100644 index a44de6d..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_0_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_0_1.png b/src/data/images/entities/super leaf piece/leafpiece_0_1.png deleted file mode 100644 index 9bfd0c6..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_0_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_0_2.png b/src/data/images/entities/super leaf piece/leafpiece_0_2.png deleted file mode 100644 index bd5d59a..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_0_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_1_0.png b/src/data/images/entities/super leaf piece/leafpiece_1_0.png deleted file mode 100644 index a44de6d..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_1_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_1_1.png b/src/data/images/entities/super leaf piece/leafpiece_1_1.png deleted file mode 100644 index 9bfd0c6..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_1_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_1_2.png b/src/data/images/entities/super leaf piece/leafpiece_1_2.png deleted file mode 100644 index bd5d59a..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_1_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_2_0.png b/src/data/images/entities/super leaf piece/leafpiece_2_0.png deleted file mode 100644 index 0a49e4a..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_2_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_2_1.png b/src/data/images/entities/super leaf piece/leafpiece_2_1.png deleted file mode 100644 index 81ddd7a..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_2_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/leafpiece_2_2.png b/src/data/images/entities/super leaf piece/leafpiece_2_2.png deleted file mode 100644 index f712709..0000000 Binary files a/src/data/images/entities/super leaf piece/leafpiece_2_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf piece/name_format.txt b/src/data/images/entities/super leaf piece/name_format.txt deleted file mode 100644 index e336c8c..0000000 --- a/src/data/images/entities/super leaf piece/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leafpiece__.png \ No newline at end of file diff --git a/src/data/images/entities/super leaf/leaf_0_0.png b/src/data/images/entities/super leaf/leaf_0_0.png deleted file mode 100644 index 925fe85..0000000 Binary files a/src/data/images/entities/super leaf/leaf_0_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_0_1.png b/src/data/images/entities/super leaf/leaf_0_1.png deleted file mode 100644 index 5c17387..0000000 Binary files a/src/data/images/entities/super leaf/leaf_0_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_0_2.png b/src/data/images/entities/super leaf/leaf_0_2.png deleted file mode 100644 index 5eef080..0000000 Binary files a/src/data/images/entities/super leaf/leaf_0_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_1_0.png b/src/data/images/entities/super leaf/leaf_1_0.png deleted file mode 100644 index 925fe85..0000000 Binary files a/src/data/images/entities/super leaf/leaf_1_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_1_1.png b/src/data/images/entities/super leaf/leaf_1_1.png deleted file mode 100644 index 5c17387..0000000 Binary files a/src/data/images/entities/super leaf/leaf_1_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_1_2.png b/src/data/images/entities/super leaf/leaf_1_2.png deleted file mode 100644 index 5eef080..0000000 Binary files a/src/data/images/entities/super leaf/leaf_1_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_2_0.png b/src/data/images/entities/super leaf/leaf_2_0.png deleted file mode 100644 index 480b5df..0000000 Binary files a/src/data/images/entities/super leaf/leaf_2_0.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_2_1.png b/src/data/images/entities/super leaf/leaf_2_1.png deleted file mode 100644 index f8de819..0000000 Binary files a/src/data/images/entities/super leaf/leaf_2_1.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/leaf_2_2.png b/src/data/images/entities/super leaf/leaf_2_2.png deleted file mode 100644 index f797b00..0000000 Binary files a/src/data/images/entities/super leaf/leaf_2_2.png and /dev/null differ diff --git a/src/data/images/entities/super leaf/name_format.txt b/src/data/images/entities/super leaf/name_format.txt deleted file mode 100644 index 2dbe2d5..0000000 --- a/src/data/images/entities/super leaf/name_format.txt +++ /dev/null @@ -1 +0,0 @@ -leaf__.png \ No newline at end of file diff --git a/src/data/images/entities/tongue/tongue_0_-1.png b/src/data/images/entities/tongue/tongue_0_-1.png deleted file mode 100644 index 44f6ded..0000000 Binary files a/src/data/images/entities/tongue/tongue_0_-1.png and /dev/null differ diff --git a/src/data/images/entities/tongue/tongue_0_1.png b/src/data/images/entities/tongue/tongue_0_1.png deleted file mode 100644 index d9d0f8f..0000000 Binary files a/src/data/images/entities/tongue/tongue_0_1.png and /dev/null differ diff --git a/src/data/images/entities/tongue/tongue_1_-1.png b/src/data/images/entities/tongue/tongue_1_-1.png deleted file mode 100644 index 8170169..0000000 Binary files a/src/data/images/entities/tongue/tongue_1_-1.png and /dev/null differ diff --git a/src/data/images/entities/tongue/tongue_1_1.png b/src/data/images/entities/tongue/tongue_1_1.png deleted file mode 100644 index b771d21..0000000 Binary files a/src/data/images/entities/tongue/tongue_1_1.png and /dev/null differ diff --git a/src/data/images/entities/tongue/tongue_2_-1.png b/src/data/images/entities/tongue/tongue_2_-1.png deleted file mode 100644 index f0b2383..0000000 Binary files a/src/data/images/entities/tongue/tongue_2_-1.png and /dev/null differ diff --git a/src/data/images/entities/tongue/tongue_2_1.png b/src/data/images/entities/tongue/tongue_2_1.png deleted file mode 100644 index 474c664..0000000 Binary files a/src/data/images/entities/tongue/tongue_2_1.png and /dev/null differ diff --git a/src/data/images/gui/button/button.png b/src/data/images/gui/button/button.png deleted file mode 100644 index 2e0c0de..0000000 Binary files a/src/data/images/gui/button/button.png and /dev/null differ diff --git a/src/data/images/gui/button/button_click.png b/src/data/images/gui/button/button_click.png deleted file mode 100644 index 756a8dc..0000000 Binary files a/src/data/images/gui/button/button_click.png and /dev/null differ diff --git a/src/data/images/gui/button/button_disable.png b/src/data/images/gui/button/button_disable.png deleted file mode 100644 index 82e5915..0000000 Binary files a/src/data/images/gui/button/button_disable.png and /dev/null differ diff --git a/src/data/images/gui/button/button_hover.png b/src/data/images/gui/button/button_hover.png deleted file mode 100644 index 578d51c..0000000 Binary files a/src/data/images/gui/button/button_hover.png and /dev/null differ diff --git a/src/data/images/gui/button/button_middle_click.png b/src/data/images/gui/button/button_middle_click.png deleted file mode 100644 index 22dae9c..0000000 Binary files a/src/data/images/gui/button/button_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/button/button_right_click.png b/src/data/images/gui/button/button_right_click.png deleted file mode 100644 index 3ef9492..0000000 Binary files a/src/data/images/gui/button/button_right_click.png and /dev/null differ diff --git a/src/data/images/gui/font.ttf b/src/data/images/gui/font.ttf deleted file mode 100644 index 20b92a2..0000000 Binary files a/src/data/images/gui/font.ttf and /dev/null differ diff --git a/src/data/images/gui/frame.png b/src/data/images/gui/frame.png deleted file mode 100644 index a7cf0b1..0000000 Binary files a/src/data/images/gui/frame.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button.png b/src/data/images/gui/play button 1/play_button.png deleted file mode 100644 index bc39df0..0000000 Binary files a/src/data/images/gui/play button 1/play_button.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button_click.png b/src/data/images/gui/play button 1/play_button_click.png deleted file mode 100644 index de570a4..0000000 Binary files a/src/data/images/gui/play button 1/play_button_click.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button_disable.png b/src/data/images/gui/play button 1/play_button_disable.png deleted file mode 100644 index df1a055..0000000 Binary files a/src/data/images/gui/play button 1/play_button_disable.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button_hover.png b/src/data/images/gui/play button 1/play_button_hover.png deleted file mode 100644 index 29f43c0..0000000 Binary files a/src/data/images/gui/play button 1/play_button_hover.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button_middle_click.png b/src/data/images/gui/play button 1/play_button_middle_click.png deleted file mode 100644 index df1a055..0000000 Binary files a/src/data/images/gui/play button 1/play_button_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/play button 1/play_button_right_click.png b/src/data/images/gui/play button 1/play_button_right_click.png deleted file mode 100644 index df1a055..0000000 Binary files a/src/data/images/gui/play button 1/play_button_right_click.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button.png b/src/data/images/gui/play button 2/play_button.png deleted file mode 100644 index e44e688..0000000 Binary files a/src/data/images/gui/play button 2/play_button.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button_click.png b/src/data/images/gui/play button 2/play_button_click.png deleted file mode 100644 index 1f3f681..0000000 Binary files a/src/data/images/gui/play button 2/play_button_click.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button_disable.png b/src/data/images/gui/play button 2/play_button_disable.png deleted file mode 100644 index 7136764..0000000 Binary files a/src/data/images/gui/play button 2/play_button_disable.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button_hover.png b/src/data/images/gui/play button 2/play_button_hover.png deleted file mode 100644 index 857c115..0000000 Binary files a/src/data/images/gui/play button 2/play_button_hover.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button_middle_click.png b/src/data/images/gui/play button 2/play_button_middle_click.png deleted file mode 100644 index 7136764..0000000 Binary files a/src/data/images/gui/play button 2/play_button_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/play button 2/play_button_right_click.png b/src/data/images/gui/play button 2/play_button_right_click.png deleted file mode 100644 index 7136764..0000000 Binary files a/src/data/images/gui/play button 2/play_button_right_click.png and /dev/null differ diff --git a/src/data/images/gui/pyoro_icon.ico b/src/data/images/gui/pyoro_icon.ico deleted file mode 100644 index 0666d7b..0000000 Binary files a/src/data/images/gui/pyoro_icon.ico and /dev/null differ diff --git a/src/data/images/gui/pyoro_icon.png b/src/data/images/gui/pyoro_icon.png deleted file mode 100644 index c446dd6..0000000 Binary files a/src/data/images/gui/pyoro_icon.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor.png b/src/data/images/gui/setting bar/cursor.png deleted file mode 100644 index 8be82a6..0000000 Binary files a/src/data/images/gui/setting bar/cursor.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor_click.png b/src/data/images/gui/setting bar/cursor_click.png deleted file mode 100644 index e080f0f..0000000 Binary files a/src/data/images/gui/setting bar/cursor_click.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor_disable.png b/src/data/images/gui/setting bar/cursor_disable.png deleted file mode 100644 index 4448d73..0000000 Binary files a/src/data/images/gui/setting bar/cursor_disable.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor_hover.png b/src/data/images/gui/setting bar/cursor_hover.png deleted file mode 100644 index 7f51d9f..0000000 Binary files a/src/data/images/gui/setting bar/cursor_hover.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor_middle_click.png b/src/data/images/gui/setting bar/cursor_middle_click.png deleted file mode 100644 index 4d85537..0000000 Binary files a/src/data/images/gui/setting bar/cursor_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/cursor_right_click.png b/src/data/images/gui/setting bar/cursor_right_click.png deleted file mode 100644 index 4d85537..0000000 Binary files a/src/data/images/gui/setting bar/cursor_right_click.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line.png b/src/data/images/gui/setting bar/line.png deleted file mode 100644 index 01c195e..0000000 Binary files a/src/data/images/gui/setting bar/line.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line_click.png b/src/data/images/gui/setting bar/line_click.png deleted file mode 100644 index 4da83dc..0000000 Binary files a/src/data/images/gui/setting bar/line_click.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line_disable.png b/src/data/images/gui/setting bar/line_disable.png deleted file mode 100644 index 0c6e0e6..0000000 Binary files a/src/data/images/gui/setting bar/line_disable.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line_hover.png b/src/data/images/gui/setting bar/line_hover.png deleted file mode 100644 index 3241698..0000000 Binary files a/src/data/images/gui/setting bar/line_hover.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line_middle_click.png b/src/data/images/gui/setting bar/line_middle_click.png deleted file mode 100644 index bd01dd7..0000000 Binary files a/src/data/images/gui/setting bar/line_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/setting bar/line_right_click.png b/src/data/images/gui/setting bar/line_right_click.png deleted file mode 100644 index bd01dd7..0000000 Binary files a/src/data/images/gui/setting bar/line_right_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated.png b/src/data/images/gui/switch button/switch_activated.png deleted file mode 100644 index f36a022..0000000 Binary files a/src/data/images/gui/switch button/switch_activated.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated_click.png b/src/data/images/gui/switch button/switch_activated_click.png deleted file mode 100644 index 8f80a76..0000000 Binary files a/src/data/images/gui/switch button/switch_activated_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated_disable.png b/src/data/images/gui/switch button/switch_activated_disable.png deleted file mode 100644 index 5d324bb..0000000 Binary files a/src/data/images/gui/switch button/switch_activated_disable.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated_hover.png b/src/data/images/gui/switch button/switch_activated_hover.png deleted file mode 100644 index 6353e8c..0000000 Binary files a/src/data/images/gui/switch button/switch_activated_hover.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated_middle_click.png b/src/data/images/gui/switch button/switch_activated_middle_click.png deleted file mode 100644 index d7b9677..0000000 Binary files a/src/data/images/gui/switch button/switch_activated_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_activated_right_click.png b/src/data/images/gui/switch button/switch_activated_right_click.png deleted file mode 100644 index d7b9677..0000000 Binary files a/src/data/images/gui/switch button/switch_activated_right_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated.png b/src/data/images/gui/switch button/switch_desactivated.png deleted file mode 100644 index c6f84fa..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated_click.png b/src/data/images/gui/switch button/switch_desactivated_click.png deleted file mode 100644 index c77c7f9..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated_disable.png b/src/data/images/gui/switch button/switch_desactivated_disable.png deleted file mode 100644 index 20183ce..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated_disable.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated_hover.png b/src/data/images/gui/switch button/switch_desactivated_hover.png deleted file mode 100644 index e73236e..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated_hover.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated_middle_click.png b/src/data/images/gui/switch button/switch_desactivated_middle_click.png deleted file mode 100644 index f97833e..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated_middle_click.png and /dev/null differ diff --git a/src/data/images/gui/switch button/switch_desactivated_right_click.png b/src/data/images/gui/switch button/switch_desactivated_right_click.png deleted file mode 100644 index f97833e..0000000 Binary files a/src/data/images/gui/switch button/switch_desactivated_right_click.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_0.png b/src/data/images/level/background 1/background_0.png deleted file mode 100644 index 69c50d9..0000000 Binary files a/src/data/images/level/background 1/background_0.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_1.png b/src/data/images/level/background 1/background_1.png deleted file mode 100644 index 12fc969..0000000 Binary files a/src/data/images/level/background 1/background_1.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_10.png b/src/data/images/level/background 1/background_10.png deleted file mode 100644 index 83e784e..0000000 Binary files a/src/data/images/level/background 1/background_10.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_11.png b/src/data/images/level/background 1/background_11.png deleted file mode 100644 index 652915f..0000000 Binary files a/src/data/images/level/background 1/background_11.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_12.png b/src/data/images/level/background 1/background_12.png deleted file mode 100644 index e403acb..0000000 Binary files a/src/data/images/level/background 1/background_12.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_13.png b/src/data/images/level/background 1/background_13.png deleted file mode 100644 index 190892d..0000000 Binary files a/src/data/images/level/background 1/background_13.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_14.png b/src/data/images/level/background 1/background_14.png deleted file mode 100644 index e403acb..0000000 Binary files a/src/data/images/level/background 1/background_14.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_15.png b/src/data/images/level/background 1/background_15.png deleted file mode 100644 index ed3f96d..0000000 Binary files a/src/data/images/level/background 1/background_15.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_16.png b/src/data/images/level/background 1/background_16.png deleted file mode 100644 index 0486ece..0000000 Binary files a/src/data/images/level/background 1/background_16.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_17.png b/src/data/images/level/background 1/background_17.png deleted file mode 100644 index 4b47c8b..0000000 Binary files a/src/data/images/level/background 1/background_17.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_18.png b/src/data/images/level/background 1/background_18.png deleted file mode 100644 index 63a14e8..0000000 Binary files a/src/data/images/level/background 1/background_18.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_19.png b/src/data/images/level/background 1/background_19.png deleted file mode 100644 index 05bb250..0000000 Binary files a/src/data/images/level/background 1/background_19.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_2.png b/src/data/images/level/background 1/background_2.png deleted file mode 100644 index 5644aea..0000000 Binary files a/src/data/images/level/background 1/background_2.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_20.png b/src/data/images/level/background 1/background_20.png deleted file mode 100644 index 932013e..0000000 Binary files a/src/data/images/level/background 1/background_20.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_3.png b/src/data/images/level/background 1/background_3.png deleted file mode 100644 index 85e4d01..0000000 Binary files a/src/data/images/level/background 1/background_3.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_4.png b/src/data/images/level/background 1/background_4.png deleted file mode 100644 index 542967d..0000000 Binary files a/src/data/images/level/background 1/background_4.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_5.png b/src/data/images/level/background 1/background_5.png deleted file mode 100644 index 4a2a505..0000000 Binary files a/src/data/images/level/background 1/background_5.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_6.png b/src/data/images/level/background 1/background_6.png deleted file mode 100644 index bba2e8b..0000000 Binary files a/src/data/images/level/background 1/background_6.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_7.png b/src/data/images/level/background 1/background_7.png deleted file mode 100644 index 268ad86..0000000 Binary files a/src/data/images/level/background 1/background_7.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_8.png b/src/data/images/level/background 1/background_8.png deleted file mode 100644 index 9453f91..0000000 Binary files a/src/data/images/level/background 1/background_8.png and /dev/null differ diff --git a/src/data/images/level/background 1/background_9.png b/src/data/images/level/background 1/background_9.png deleted file mode 100644 index 64f51a2..0000000 Binary files a/src/data/images/level/background 1/background_9.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_0.png b/src/data/images/level/background 2/background_0.png deleted file mode 100644 index 06e6d1a..0000000 Binary files a/src/data/images/level/background 2/background_0.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_1.png b/src/data/images/level/background 2/background_1.png deleted file mode 100644 index eb753da..0000000 Binary files a/src/data/images/level/background 2/background_1.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_10.png b/src/data/images/level/background 2/background_10.png deleted file mode 100644 index 799b764..0000000 Binary files a/src/data/images/level/background 2/background_10.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_11.png b/src/data/images/level/background 2/background_11.png deleted file mode 100644 index 94e4dc6..0000000 Binary files a/src/data/images/level/background 2/background_11.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_12.png b/src/data/images/level/background 2/background_12.png deleted file mode 100644 index b032d75..0000000 Binary files a/src/data/images/level/background 2/background_12.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_13.png b/src/data/images/level/background 2/background_13.png deleted file mode 100644 index d9ecf54..0000000 Binary files a/src/data/images/level/background 2/background_13.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_14.png b/src/data/images/level/background 2/background_14.png deleted file mode 100644 index b032d75..0000000 Binary files a/src/data/images/level/background 2/background_14.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_15.png b/src/data/images/level/background 2/background_15.png deleted file mode 100644 index 983c367..0000000 Binary files a/src/data/images/level/background 2/background_15.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_16.png b/src/data/images/level/background 2/background_16.png deleted file mode 100644 index 898050c..0000000 Binary files a/src/data/images/level/background 2/background_16.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_17.png b/src/data/images/level/background 2/background_17.png deleted file mode 100644 index 676c96b..0000000 Binary files a/src/data/images/level/background 2/background_17.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_18.png b/src/data/images/level/background 2/background_18.png deleted file mode 100644 index aabe678..0000000 Binary files a/src/data/images/level/background 2/background_18.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_19.png b/src/data/images/level/background 2/background_19.png deleted file mode 100644 index 05bb250..0000000 Binary files a/src/data/images/level/background 2/background_19.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_2.png b/src/data/images/level/background 2/background_2.png deleted file mode 100644 index dfd94e7..0000000 Binary files a/src/data/images/level/background 2/background_2.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_20.png b/src/data/images/level/background 2/background_20.png deleted file mode 100644 index ec8c929..0000000 Binary files a/src/data/images/level/background 2/background_20.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_3.png b/src/data/images/level/background 2/background_3.png deleted file mode 100644 index 175337e..0000000 Binary files a/src/data/images/level/background 2/background_3.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_4.png b/src/data/images/level/background 2/background_4.png deleted file mode 100644 index 32a4970..0000000 Binary files a/src/data/images/level/background 2/background_4.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_5.png b/src/data/images/level/background 2/background_5.png deleted file mode 100644 index 489b832..0000000 Binary files a/src/data/images/level/background 2/background_5.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_6.png b/src/data/images/level/background 2/background_6.png deleted file mode 100644 index 4225e25..0000000 Binary files a/src/data/images/level/background 2/background_6.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_7.png b/src/data/images/level/background 2/background_7.png deleted file mode 100644 index 3f9f20c..0000000 Binary files a/src/data/images/level/background 2/background_7.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_8.png b/src/data/images/level/background 2/background_8.png deleted file mode 100644 index 63dd68b..0000000 Binary files a/src/data/images/level/background 2/background_8.png and /dev/null differ diff --git a/src/data/images/level/background 2/background_9.png b/src/data/images/level/background 2/background_9.png deleted file mode 100644 index cdac104..0000000 Binary files a/src/data/images/level/background 2/background_9.png and /dev/null differ diff --git a/src/data/images/original/background1_11_original.png b/src/data/images/original/background1_11_original.png deleted file mode 100644 index d5f3ed0..0000000 Binary files a/src/data/images/original/background1_11_original.png and /dev/null differ diff --git a/src/data/images/original/bean1_2_1_original.png b/src/data/images/original/bean1_2_1_original.png deleted file mode 100644 index a52e4f3..0000000 Binary files a/src/data/images/original/bean1_2_1_original.png and /dev/null differ diff --git a/src/data/images/original/bean1_2_2_original.png b/src/data/images/original/bean1_2_2_original.png deleted file mode 100644 index 3553ebd..0000000 Binary files a/src/data/images/original/bean1_2_2_original.png and /dev/null differ diff --git a/src/data/images/original/bean1_2_3_original.png b/src/data/images/original/bean1_2_3_original.png deleted file mode 100644 index d232812..0000000 Binary files a/src/data/images/original/bean1_2_3_original.png and /dev/null differ diff --git a/src/data/images/original/bean2_2_1_original.png b/src/data/images/original/bean2_2_1_original.png deleted file mode 100644 index 2cdc2fa..0000000 Binary files a/src/data/images/original/bean2_2_1_original.png and /dev/null differ diff --git a/src/data/images/original/bean2_2_2_original.png b/src/data/images/original/bean2_2_2_original.png deleted file mode 100644 index 8949b4d..0000000 Binary files a/src/data/images/original/bean2_2_2_original.png and /dev/null differ diff --git a/src/data/images/original/bean2_2_3_original.png b/src/data/images/original/bean2_2_3_original.png deleted file mode 100644 index 0abcd8e..0000000 Binary files a/src/data/images/original/bean2_2_3_original.png and /dev/null differ diff --git a/src/data/images/original/block_2_original.png b/src/data/images/original/block_2_original.png deleted file mode 100644 index 29b63f4..0000000 Binary files a/src/data/images/original/block_2_original.png and /dev/null differ diff --git a/src/data/images/original/cursor_original.png b/src/data/images/original/cursor_original.png deleted file mode 100644 index bcfedd1..0000000 Binary files a/src/data/images/original/cursor_original.png and /dev/null differ diff --git a/src/data/images/original/line_original.png b/src/data/images/original/line_original.png deleted file mode 100644 index 2425efe..0000000 Binary files a/src/data/images/original/line_original.png and /dev/null differ diff --git a/src/data/images/original/play_button2_image.png b/src/data/images/original/play_button2_image.png deleted file mode 100644 index d7d1b4d..0000000 Binary files a/src/data/images/original/play_button2_image.png and /dev/null differ diff --git a/src/data/images/original/play_button_image.png b/src/data/images/original/play_button_image.png deleted file mode 100644 index 0feb163..0000000 Binary files a/src/data/images/original/play_button_image.png and /dev/null differ diff --git a/src/data/images/original/pyoro1_12_die_original.png b/src/data/images/original/pyoro1_12_die_original.png deleted file mode 100644 index e272523..0000000 Binary files a/src/data/images/original/pyoro1_12_die_original.png and /dev/null differ diff --git a/src/data/images/original/pyoro1_12_eat_0_original.png b/src/data/images/original/pyoro1_12_eat_0_original.png deleted file mode 100644 index 97cdb49..0000000 Binary files a/src/data/images/original/pyoro1_12_eat_0_original.png and /dev/null differ diff --git a/src/data/images/original/pyoro1_12_eat_1_original.png b/src/data/images/original/pyoro1_12_eat_1_original.png deleted file mode 100644 index 368e01f..0000000 Binary files a/src/data/images/original/pyoro1_12_eat_1_original.png and /dev/null differ diff --git a/src/data/images/original/pyoro1_12_jump_original.png b/src/data/images/original/pyoro1_12_jump_original.png deleted file mode 100644 index 5cfcb03..0000000 Binary files a/src/data/images/original/pyoro1_12_jump_original.png and /dev/null differ diff --git a/src/data/images/original/pyoro1_12_normal_original.png b/src/data/images/original/pyoro1_12_normal_original.png deleted file mode 100644 index 44d1551..0000000 Binary files a/src/data/images/original/pyoro1_12_normal_original.png and /dev/null differ diff --git a/src/data/images/original/switch_button_original_activated.png b/src/data/images/original/switch_button_original_activated.png deleted file mode 100644 index fd177db..0000000 Binary files a/src/data/images/original/switch_button_original_activated.png and /dev/null differ diff --git a/src/data/images/original/switch_button_original_desactivated.png b/src/data/images/original/switch_button_original_desactivated.png deleted file mode 100644 index dc8300a..0000000 Binary files a/src/data/images/original/switch_button_original_desactivated.png and /dev/null differ diff --git a/src/data/layouts.json b/src/data/layouts.json deleted file mode 100644 index 7260a3d..0000000 --- a/src/data/layouts.json +++ /dev/null @@ -1,368 +0,0 @@ -[ - { - "name": "Wide", - "splash_image": { - "min_mm_format": [60, 60], - "size_mm": [50, 50], - "size": [80, 80], - "pos": [50, 50], - "anchor": [0, 0] - }, - "splash_text": { - "min_mm_format": [60, 60], - "font_size_mm": 8, - "font_size": 4, - "pos": [50, 90], - "anchor": [0, 0] - }, - "ask_for_update_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_failed_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_success_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "title_image": { - "min_mm_format": [200, 45], - "size_mm": [102, 40], - "size": [47, 20], - "pos": [25, 50], - "anchor": [0, 0] - }, - "play_button_1": { - "min_mm_format": [200, 70], - "size_mm": [45, 45], - "size": [20, 20], - "font_size_mm": 4, - "font_size": 2, - "pos": [70, 50], - "anchor": [1, 1] - }, - "play_button_2": { - "min_mm_format": [200, 70], - "size_mm": [45, 45], - "size": [20, 20], - "font_size_mm": 4, - "font_size": 2, - "pos": [75, 50], - "anchor": [-1, 1] - }, - "option_button": { - "min_mm_format": [200, 70], - "size_mm": [45, 22.5], - "size": [20, 10], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [70, 60], - "anchor": [1, -1] - }, - "quit_button": { - "min_mm_format": [200, 70], - "size_mm": [45, 22.5], - "size": [20, 10], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 60], - "anchor": [-1, -1] - }, - "score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [25, 5], - "anchor": [0, -1] - }, - "high_score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 5], - "anchor": [0, -1] - }, - "option_menu": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "font_size_mm": 4, - "font_size": 2, - "pos": [50, 50], - "anchor": [0, 0] - }, - "pause_menu": { - "min_mm_format": [60, 60], - "size_mm": [60, 60], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - }, - "game_over_menu": { - "min_mm_format": [60, 50], - "size_mm": [60, 50], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - } - }, - { - "name": "Square", - "splash_image": { - "min_mm_format": [60, 60], - "size_mm": [50, 50], - "size": [80, 80], - "pos": [50, 50], - "anchor": [0, 0] - }, - "splash_text": { - "min_mm_format": [60, 60], - "font_size_mm": 8, - "font_size": 4, - "pos": [50, 90], - "anchor": [0, 0] - }, - "ask_for_update_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_failed_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_success_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "title_image": { - "min_mm_format": [110, 120], - "size_mm": [108, 46], - "size": [47, 20], - "pos": [50, 5], - "anchor": [0, -1] - }, - "play_button_1": { - "min_mm_format": [110, 120], - "size_mm": [50, 50], - "size": [40, 40], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [25, 50], - "anchor": [0, 0] - }, - "play_button_2": { - "min_mm_format": [110, 120], - "size_mm": [50, 50], - "size": [40, 40], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 50], - "anchor": [0, 0] - }, - "option_button": { - "min_mm_format": [110, 120], - "size_mm": [50, 25], - "size": [40, 20], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [25, 75], - "anchor": [0, 0] - }, - "quit_button": { - "min_mm_format": [110, 120], - "size_mm": [50, 25], - "size": [40, 20], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 75], - "anchor": [0, 0] - }, - "score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [25, 5], - "anchor": [0, -1] - }, - "high_score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 5], - "anchor": [0, -1] - }, - "option_menu": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "font_size_mm": 4, - "font_size": 2, - "pos": [50, 50], - "anchor": [0, 0] - }, - "pause_menu": { - "min_mm_format": [60, 60], - "size_mm": [60, 60], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - }, - "game_over_menu": { - "min_mm_format": [60, 50], - "size_mm": [60, 50], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - } - }, - { - "name": "Narrow", - "splash_image": { - "min_mm_format": [60, 60], - "size_mm": [50, 50], - "size": [80, 80], - "pos": [50, 50], - "anchor": [0, 0] - }, - "splash_text": { - "min_mm_format": [60, 60], - "font_size_mm": 8, - "font_size": 4, - "pos": [50, 90], - "anchor": [0, 0] - }, - "ask_for_update_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_failed_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "update_success_dialog": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "pos": [50, 50], - "anchor": [0, 0] - }, - "title_image": { - "min_mm_format": [110, 180], - "size_mm": [108, 46], - "size": [47, 20], - "pos": [50, 5], - "anchor": [0, -1] - }, - "play_button_1": { - "min_mm_format": [50, 180], - "size_mm": [40, 40], - "size": [20, 20], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 40], - "anchor": [0, 0] - }, - "play_button_2": { - "min_mm_format": [50, 180], - "size_mm": [40, 40], - "size": [20, 20], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 62], - "anchor": [0, 0] - }, - "option_button": { - "min_mm_format": [50, 180], - "size_mm": [40, 20], - "size": [20, 10], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 80], - "anchor": [0, 0] - }, - "quit_button": { - "min_mm_format": [50, 186], - "size_mm": [40, 20], - "size": [20, 10], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 92], - "anchor": [0, 0] - }, - "score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [25, 5], - "anchor": [0, -1] - }, - "high_score_text": { - "min_mm_format": [120, 60], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [75, 5], - "anchor": [0, -1] - }, - "option_menu": { - "min_mm_format": [100, 100], - "size_mm": [100, 100], - "size": [100, 100], - "font_size_mm": 4, - "font_size": 2, - "pos": [50, 50], - "anchor": [0, 0] - }, - "pause_menu": { - "min_mm_format": [60, 60], - "size_mm": [60, 60], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - }, - "game_over_menu": { - "min_mm_format": [60, 50], - "size_mm": [60, 50], - "size": [100, 100], - "font_size_mm": 5, - "font_size": 2.5, - "pos": [50, 50], - "anchor": [0, 0] - } - } -] diff --git a/src/data/resources.json b/src/data/resources.json deleted file mode 100644 index 14acabc..0000000 --- a/src/data/resources.json +++ /dev/null @@ -1,323 +0,0 @@ -{ - "musics": - [ - ["audio", "musics", "drums.wav"], - ["audio", "musics", "game_over.wav"], - ["audio", "musics", "intro.wav"], - ["audio", "musics", "music_0.wav"], - ["audio", "musics", "music_1.wav"], - ["audio", "musics", "music_2.wav"], - ["audio", "musics", "organ.wav"], - ["audio", "musics", "speed_drums.wav"] - ], - "sounds": - [ - ["audio", "sounds", "angel_down.wav"], - ["audio", "sounds", "bean_cut.wav"], - ["audio", "sounds", "bean_explode.wav"], - ["audio", "sounds", "pyoro_die.wav"], - ["audio", "sounds", "pyoro_eat.wav"], - ["audio", "sounds", "pyoro_move.wav"], - ["audio", "sounds", "tongue.wav"] - ], - "images": - [ - ["images", "entities", "angel", "angel_0_0.png"], - ["images", "entities", "angel", "angel_0_1.png"], - ["images", "entities", "angel", "angel_1_0.png"], - ["images", "entities", "angel", "angel_1_1.png"], - ["images", "entities", "angel", "angel_2_0.png"], - ["images", "entities", "angel", "angel_2_1.png"], - ["images", "entities", "bean", "bean_0_0.png"], - ["images", "entities", "bean", "bean_0_1.png"], - ["images", "entities", "bean", "bean_0_2.png"], - ["images", "entities", "bean", "bean_1_0.png"], - ["images", "entities", "bean", "bean_1_1.png"], - ["images", "entities", "bean", "bean_1_2.png"], - ["images", "entities", "bean", "bean_2_0.png"], - ["images", "entities", "bean", "bean_2_1.png"], - ["images", "entities", "bean", "bean_2_2.png"], - ["images", "entities", "leaf", "leaf_0_0.png"], - ["images", "entities", "leaf", "leaf_0_1.png"], - ["images", "entities", "leaf", "leaf_0_2.png"], - ["images", "entities", "leaf", "leaf_1_0.png"], - ["images", "entities", "leaf", "leaf_1_1.png"], - ["images", "entities", "leaf", "leaf_1_2.png"], - ["images", "entities", "leaf", "leaf_2_0.png"], - ["images", "entities", "leaf", "leaf_2_1.png"], - ["images", "entities", "leaf", "leaf_2_2.png"], - ["images", "entities", "leaf piece", "leafpiece_0_0.png"], - ["images", "entities", "leaf piece", "leafpiece_0_1.png"], - ["images", "entities", "leaf piece", "leafpiece_0_2.png"], - ["images", "entities", "leaf piece", "leafpiece_1_0.png"], - ["images", "entities", "leaf piece", "leafpiece_1_1.png"], - ["images", "entities", "leaf piece", "leafpiece_1_2.png"], - ["images", "entities", "leaf piece", "leafpiece_2_0.png"], - ["images", "entities", "leaf piece", "leafpiece_2_1.png"], - ["images", "entities", "leaf piece", "leafpiece_2_2.png"], - ["images", "entities", "pink bean", "bean_0_0.png"], - ["images", "entities", "pink bean", "bean_0_1.png"], - ["images", "entities", "pink bean", "bean_0_2.png"], - ["images", "entities", "pink bean", "bean_1_0.png"], - ["images", "entities", "pink bean", "bean_1_1.png"], - ["images", "entities", "pink bean", "bean_1_2.png"], - ["images", "entities", "pink bean", "bean_2_0.png"], - ["images", "entities", "pink bean", "bean_2_1.png"], - ["images", "entities", "pink bean", "bean_2_2.png"], - ["images", "entities", "pink leaf", "leaf_0_0.png"], - ["images", "entities", "pink leaf", "leaf_0_1.png"], - ["images", "entities", "pink leaf", "leaf_0_2.png"], - ["images", "entities", "pink leaf", "leaf_1_0.png"], - ["images", "entities", "pink leaf", "leaf_1_1.png"], - ["images", "entities", "pink leaf", "leaf_1_2.png"], - ["images", "entities", "pink leaf", "leaf_2_0.png"], - ["images", "entities", "pink leaf", "leaf_2_1.png"], - ["images", "entities", "pink leaf", "leaf_2_2.png"], - ["images", "entities", "pink leaf piece", "leafpiece_0_0.png"], - ["images", "entities", "pink leaf piece", "leafpiece_0_1.png"], - ["images", "entities", "pink leaf piece", "leafpiece_0_2.png"], - ["images", "entities", "pink leaf piece", "leafpiece_1_0.png"], - ["images", "entities", "pink leaf piece", "leafpiece_1_1.png"], - ["images", "entities", "pink leaf piece", "leafpiece_1_2.png"], - ["images", "entities", "pink leaf piece", "leafpiece_2_0.png"], - ["images", "entities", "pink leaf piece", "leafpiece_2_1.png"], - ["images", "entities", "pink leaf piece", "leafpiece_2_2.png"], - ["images", "entities", "pyoro 1", "pyoro_0_die_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_die_1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_eat_0_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_eat_0_1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_eat_1_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_eat_1_1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_jump_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_jump_1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_normal_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_0_normal_1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_die_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_die_1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_eat_0_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_eat_0_1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_eat_1_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_eat_1_1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_jump_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_jump_1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_normal_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_1_normal_1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_die_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_die_1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_eat_0_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_eat_0_1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_eat_1_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_eat_1_1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_jump_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_jump_1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_normal_-1.png"], - ["images", "entities", "pyoro 1", "pyoro_2_normal_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_die_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_die_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_jump_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_jump_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_normal_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_normal_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_0_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_0_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_1_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_1_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_2_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_2_1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_3_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_0_shoot_3_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_die_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_die_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_jump_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_jump_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_normal_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_normal_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_0_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_0_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_1_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_1_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_2_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_2_1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_3_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_1_shoot_3_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_die_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_die_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_jump_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_jump_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_normal_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_normal_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_0_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_0_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_1_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_1_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_2_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_2_1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_3_-1.png"], - ["images", "entities", "pyoro 2", "pyoro_2_shoot_3_1.png"], - ["images", "entities", "score text", "number_10.png"], - ["images", "entities", "score text", "number_100.png"], - ["images", "entities", "score text", "number_1000_0.png"], - ["images", "entities", "score text", "number_1000_1.png"], - ["images", "entities", "score text", "number_1000_2.png"], - ["images", "entities", "score text", "number_1000_3.png"], - ["images", "entities", "score text", "number_1000_4.png"], - ["images", "entities", "score text", "number_1000_5.png"], - ["images", "entities", "score text", "number_300_0.png"], - ["images", "entities", "score text", "number_300_1.png"], - ["images", "entities", "score text", "number_300_2.png"], - ["images", "entities", "score text", "number_300_3.png"], - ["images", "entities", "score text", "number_300_4.png"], - ["images", "entities", "score text", "number_300_5.png"], - ["images", "entities", "score text", "number_50.png"], - ["images", "entities", "seed", "seed_0.png"], - ["images", "entities", "seed", "seed_1.png"], - ["images", "entities", "seed", "seed_2.png"], - ["images", "entities", "smoke", "smoke_0_0.png"], - ["images", "entities", "smoke", "smoke_0_1.png"], - ["images", "entities", "smoke", "smoke_0_2.png"], - ["images", "entities", "smoke", "smoke_1_0.png"], - ["images", "entities", "smoke", "smoke_1_1.png"], - ["images", "entities", "smoke", "smoke_1_2.png"], - ["images", "entities", "smoke", "smoke_2_0.png"], - ["images", "entities", "smoke", "smoke_2_1.png"], - ["images", "entities", "smoke", "smoke_2_2.png"], - ["images", "entities", "super bean", "bean_0_0.png"], - ["images", "entities", "super bean", "bean_0_1.png"], - ["images", "entities", "super bean", "bean_0_2.png"], - ["images", "entities", "super bean", "bean_0_3.png"], - ["images", "entities", "super bean", "bean_0_4.png"], - ["images", "entities", "super bean", "bean_0_5.png"], - ["images", "entities", "super bean", "bean_1_0.png"], - ["images", "entities", "super bean", "bean_1_1.png"], - ["images", "entities", "super bean", "bean_1_2.png"], - ["images", "entities", "super bean", "bean_1_3.png"], - ["images", "entities", "super bean", "bean_1_4.png"], - ["images", "entities", "super bean", "bean_1_5.png"], - ["images", "entities", "super bean", "bean_2_0.png"], - ["images", "entities", "super bean", "bean_2_1.png"], - ["images", "entities", "super bean", "bean_2_2.png"], - ["images", "entities", "super bean", "bean_2_3.png"], - ["images", "entities", "super bean", "bean_2_4.png"], - ["images", "entities", "super bean", "bean_2_5.png"], - ["images", "entities", "super leaf", "leaf_0_0.png"], - ["images", "entities", "super leaf", "leaf_0_1.png"], - ["images", "entities", "super leaf", "leaf_0_2.png"], - ["images", "entities", "super leaf", "leaf_1_0.png"], - ["images", "entities", "super leaf", "leaf_1_1.png"], - ["images", "entities", "super leaf", "leaf_1_2.png"], - ["images", "entities", "super leaf", "leaf_2_0.png"], - ["images", "entities", "super leaf", "leaf_2_1.png"], - ["images", "entities", "super leaf", "leaf_2_2.png"], - ["images", "entities", "super leaf piece", "leafpiece_0_0.png"], - ["images", "entities", "super leaf piece", "leafpiece_0_1.png"], - ["images", "entities", "super leaf piece", "leafpiece_0_2.png"], - ["images", "entities", "super leaf piece", "leafpiece_1_0.png"], - ["images", "entities", "super leaf piece", "leafpiece_1_1.png"], - ["images", "entities", "super leaf piece", "leafpiece_1_2.png"], - ["images", "entities", "super leaf piece", "leafpiece_2_0.png"], - ["images", "entities", "super leaf piece", "leafpiece_2_1.png"], - ["images", "entities", "super leaf piece", "leafpiece_2_2.png"], - ["images", "entities", "tongue", "tongue_0_-1.png"], - ["images", "entities", "tongue", "tongue_0_1.png"], - ["images", "entities", "tongue", "tongue_1_-1.png"], - ["images", "entities", "tongue", "tongue_1_1.png"], - ["images", "entities", "tongue", "tongue_2_-1.png"], - ["images", "entities", "tongue", "tongue_2_1.png"], - ["images", "gui", "button", "button.png"], - ["images", "gui", "button", "button_click.png"], - ["images", "gui", "button", "button_disable.png"], - ["images", "gui", "button", "button_hover.png"], - ["images", "gui", "button", "button_middle_click.png"], - ["images", "gui", "button", "button_right_click.png"], - ["images", "gui", "frame.png"], - ["images", "gui", "play button 1", "play_button.png"], - ["images", "gui", "play button 1", "play_button_click.png"], - ["images", "gui", "play button 1", "play_button_disable.png"], - ["images", "gui", "play button 1", "play_button_hover.png"], - ["images", "gui", "play button 1", "play_button_middle_click.png"], - ["images", "gui", "play button 1", "play_button_right_click.png"], - ["images", "gui", "play button 2", "play_button.png"], - ["images", "gui", "play button 2", "play_button_click.png"], - ["images", "gui", "play button 2", "play_button_disable.png"], - ["images", "gui", "play button 2", "play_button_hover.png"], - ["images", "gui", "play button 2", "play_button_middle_click.png"], - ["images", "gui", "play button 2", "play_button_right_click.png"], - ["images", "gui", "pyoro_icon.png"], - ["images", "gui", "setting bar", "cursor.png"], - ["images", "gui", "setting bar", "cursor_click.png"], - ["images", "gui", "setting bar", "cursor_disable.png"], - ["images", "gui", "setting bar", "cursor_hover.png"], - ["images", "gui", "setting bar", "cursor_middle_click.png"], - ["images", "gui", "setting bar", "cursor_right_click.png"], - ["images", "gui", "setting bar", "line.png"], - ["images", "gui", "setting bar", "line_click.png"], - ["images", "gui", "setting bar", "line_disable.png"], - ["images", "gui", "setting bar", "line_hover.png"], - ["images", "gui", "setting bar", "line_middle_click.png"], - ["images", "gui", "setting bar", "line_right_click.png"], - ["images", "gui", "switch button", "switch_activated.png"], - ["images", "gui", "switch button", "switch_activated_click.png"], - ["images", "gui", "switch button", "switch_activated_disable.png"], - ["images", "gui", "switch button", "switch_activated_hover.png"], - ["images", "gui", "switch button", "switch_activated_middle_click.png"], - ["images", "gui", "switch button", "switch_activated_right_click.png"], - ["images", "gui", "switch button", "switch_desactivated.png"], - ["images", "gui", "switch button", "switch_desactivated_click.png"], - ["images", "gui", "switch button", "switch_desactivated_disable.png"], - ["images", "gui", "switch button", "switch_desactivated_hover.png"], - ["images", "gui", "switch button", "switch_desactivated_middle_click.png"], - ["images", "gui", "switch button", "switch_desactivated_right_click.png"], - ["images", "gui", "title.png"], - ["images", "level", "background 1", "background_0.png"], - ["images", "level", "background 1", "background_1.png"], - ["images", "level", "background 1", "background_10.png"], - ["images", "level", "background 1", "background_11.png"], - ["images", "level", "background 1", "background_12.png"], - ["images", "level", "background 1", "background_13.png"], - ["images", "level", "background 1", "background_14.png"], - ["images", "level", "background 1", "background_15.png"], - ["images", "level", "background 1", "background_16.png"], - ["images", "level", "background 1", "background_17.png"], - ["images", "level", "background 1", "background_18.png"], - ["images", "level", "background 1", "background_19.png"], - ["images", "level", "background 1", "background_2.png"], - ["images", "level", "background 1", "background_20.png"], - ["images", "level", "background 1", "background_3.png"], - ["images", "level", "background 1", "background_4.png"], - ["images", "level", "background 1", "background_5.png"], - ["images", "level", "background 1", "background_6.png"], - ["images", "level", "background 1", "background_7.png"], - ["images", "level", "background 1", "background_8.png"], - ["images", "level", "background 1", "background_9.png"], - ["images", "level", "background 2", "background_0.png"], - ["images", "level", "background 2", "background_1.png"], - ["images", "level", "background 2", "background_10.png"], - ["images", "level", "background 2", "background_11.png"], - ["images", "level", "background 2", "background_12.png"], - ["images", "level", "background 2", "background_13.png"], - ["images", "level", "background 2", "background_14.png"], - ["images", "level", "background 2", "background_15.png"], - ["images", "level", "background 2", "background_16.png"], - ["images", "level", "background 2", "background_17.png"], - ["images", "level", "background 2", "background_18.png"], - ["images", "level", "background 2", "background_19.png"], - ["images", "level", "background 2", "background_2.png"], - ["images", "level", "background 2", "background_20.png"], - ["images", "level", "background 2", "background_3.png"], - ["images", "level", "background 2", "background_4.png"], - ["images", "level", "background 2", "background_5.png"], - ["images", "level", "background 2", "background_6.png"], - ["images", "level", "background 2", "background_7.png"], - ["images", "level", "background 2", "background_8.png"], - ["images", "level", "background 2", "background_9.png"], - ["images", "level", "block", "block_0.png"], - ["images", "level", "block", "block_1.png"], - ["images", "level", "block", "block_2.png"] - ], - "external": - [ - ["resources.json"], - ["images", "gui", "font.ttf"], - ["images", "gui", "pyoro_icon.ico"] - ] -} \ No newline at end of file diff --git a/src/entities/__init__.py b/src/entities/__init__.py deleted file mode 100644 index 7c68785..0000000 --- a/src/entities/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- \ No newline at end of file diff --git a/src/entities/angel.py b/src/entities/angel.py deleted file mode 100644 index 0bc3610..0000000 --- a/src/entities/angel.py +++ /dev/null @@ -1,116 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides an Angel class. -This entity is used to repair destroyed cases - -Created on 21/03/2018 -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from game.config import ANGEL_SPEED, ANGEL_SPRITE_DURATION - - -class Angel(Entity): - """ - Angel that fall from the sky to repair a destroyed block - """ - - def __init__(self, level, repair_case): - """ - Initialize an Angel object. - - :type level: game.level.Level - :param level: The level managing this entity - - :type repair_case: game.case.Case - :param repair_case: The block to repair - """ - - self.sprite_index = 0 - self.case = repair_case - self.case.is_repairing = True - Entity.__init__(self, level, (repair_case.pos + 0.75, 0.75), (1.5, 1.5)) - - def init_images(self): - """ - Load angel images. - """ - - self.__init_images__("angel") - - def init_sounds(self): - """ - Load angel sounds and start playing a falling sound. - """ - - self.__init_sounds__(("angel_down",)) - self.sounds["angel_down"].play() - - def update(self, delta_time): - """ - Update the angel (position, sprite). - - :type delta_time: float - :param delta_time: Time elapsed since the last frame update - """ - - if self.case.is_repairing: - self.pos[1] += ANGEL_SPEED * delta_time - else: - self.pos[1] -= ANGEL_SPEED * delta_time - if self.is_hitting_floor(): - self.repair_case() - Entity.update(self, delta_time) - - def repair_case(self, case=None): - """ - Repair a destroyed block. - - :type case: game.case.Case - :param case: The block to repair. - Leave None to repair the default block. - """ - - case = case if case else self.case - case.is_repairing = False - case.exists = True - self.sounds["angel_down"].stop() - - def update_sprite(self): - """ - Update the images to create a flight animation. - """ - - score = self.level.get_style_type_with_score() - self.sprite_index = 1 if self.sprite_index == 0 else 0 - self.current_image_name = f"angel_{score}_{self.sprite_index}.png" - self.level.set_action_delay( - (self, "updateSprite"), ANGEL_SPRITE_DURATION, self.update_sprite - ) - - def remove(self): - """ - Remove the angel from its level and stop all actions delayed. - """ - - self.level.remove_action_delay((self, "updateSprite")) - Entity.remove(self) diff --git a/src/entities/bean.py b/src/entities/bean.py deleted file mode 100644 index 33c5f40..0000000 --- a/src/entities/bean.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a Bean class to represent falling beans -(as indicated by his name). Beans destroy blocks and kill Pyoro -if they touch it. - -Created on 18/03/2018 -""" - -import random - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from game.config import BEAN_SPEED, BEAN_SPRITE_DURATION - - -class Bean(Entity): - """ - Main class for all falling beans - """ - - def __init__(self, level, pos, speed): - """ - Initialize a Bean object. - - :type level: game.level.Level - :param level: The level managing this bean. - - :type pos: list - :param pos: The default position of the bean. - - :type speed: float - :param speed: The falling speed of the bean. - """ - - self.caught = False - self.speed = speed - self.sprite_index = 0 - Entity.__init__(self, level, pos, (1.5, 1.5)) - - def init_images(self): - """ - Load bean images. - """ - - self.__init_images__("bean") - - def init_sounds(self): - """ - Load bean sounds. - """ - - self.__init_sounds__(("bean_cut", "bean_explode")) - - def update(self, delta_time): - """ - Update the bean (position, sprite). - - :type delta_time: float - :param delta_time: Time elapsed since the last frame update - """ - - if not self.caught: - self.pos[1] += BEAN_SPEED * self.speed * delta_time - if self.is_hitting_floor(): - if self.level.cases[int(self.pos[0])].exists: - self.level.cases[int(self.pos[0])].exists = False - self.explode() - self.remove() - if self.is_hitting_entity(self.level.pyoro) and not self.level.pyoro.dead: - self.explode() - self.remove() - self.level.pyoro.remove() - Entity.update(self, delta_time) - - def update_sprite(self): - """ - Update the images to create a swing animation. - """ - - score = self.level.get_style_type_with_score() - self.sprite_index = self.sprite_index + 1 if self.sprite_index < 2 else 0 - self.current_image_name = f"bean_{score}_{self.sprite_index}.png" - - self.level.set_action_delay( - (self, "update_sprite"), BEAN_SPRITE_DURATION, self.update_sprite - ) - - def catch(self): - """ - Method called when caught by Pyoro. - """ - - self.caught = True - - def explode(self): - """ - Create an explosion animation with smoke and by playing - an explosion sound. - """ - - self.sounds["bean_explode"].play() - self.level.spawn_smoke(self.pos) - - def cut(self): - """ - Spawn leafs to create a cutting animation. - """ - - self.sounds["bean_cut"].play() - for _ in range(2): - rand_pos = [ - self.pos[0] + random.uniform(-0.5, 0.5), - self.pos[1] + random.uniform(-0.5, 0.2), - ] - self.level.spawn_leaf(rand_pos, "leaf") - - def remove(self): - """ - Remove the bean from its level and stop all actions delayed. - """ - - self.level.remove_action_delay((self, "update_sprite")) - Entity.remove(self) diff --git a/src/entities/entity.py b/src/entities/entity.py deleted file mode 100644 index 8029f76..0000000 --- a/src/entities/entity.py +++ /dev/null @@ -1,225 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a base abstract class to create entities - -Created on 18/03/2018 -""" - -import os - -from game.config import ENTITIES_IMAGE_PATH -from game.util import Game -from gui.image_transformer import resize_image - -__author__ = "RedbeanGit" -__version__ = "1.1.1" - - -class Entity: - """ - Abstract class for all moving objects : entities - """ - - def __init__(self, level, pos, size=(1, 1)): - """ - Initialize an Entity object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: The default (x, y) position of the entity. - - :type size: list - :param size: Optional! The (width, height) size of the entity. - Default is [1, 1]. - """ - - self.level = level - - self.size = list(size) - self.pos = list(pos) - self.sounds = {} - self.images = {} - self.current_image_name = "" - - self.init_images() - self.init_sounds() - self.update_sprite() - - def __repr__(self): - """ - Represent the entity as a string. - - :rtype: str - :returns: A string respresenting the entity. - - :Example: - """ - - type_name = type(self).__name__ - return f"<{type_name} at pos x={self.pos[0]:.2f}, y={self.pos[1]:.2f}>" - - def __init_images__(self, folder_name): - """ - Reference all images in a specific folder to use them later. - This method should be used internally by Entity.initImages - (see below). - - :type folder_name: str - :param folder_name: The path to the folder where images to - reference are. - """ - - self.images = {} - case_size = self.level.level_drawer.get_case_size() - image_names = os.listdir(os.path.join(ENTITIES_IMAGE_PATH, folder_name)) - - for image_name in image_names: - if image_name.split(".")[-1] == "png": - self.images[image_name] = resize_image( - self.level.level_drawer.activity.window.get_image( - os.path.join(ENTITIES_IMAGE_PATH, folder_name, image_name) - ), - (case_size[0] * self.size[0], case_size[1] * self.size[1]), - ) - self.update_sprite() - - def init_images(self): - """ - Initialize the images used by the entity. - This method should be override to refer the images of this entity. - It's advisable to use this method with Entity.__initImages__. - """ - - def __init_sounds__(self, sound_names): - """ - Reference sounds to use them later. - This method should be used internally by Entity.initSounds - (see below). - - :type sound_names: list - :param sound_names: The name of the sounds to load. - """ - - audio_player = self.level.get_audio_player() - for sound_name in sound_names: - self.sounds[sound_name] = audio_player.get_sound( - os.path.join("data", "audio", "sounds", f"{sound_name}.wav") - ) - - def init_sounds(self): - """ - Initialize the sounds used by the entity. - This method should be override to refer the sounds of this entity. - It's advisable to use this method with Entity.__initSounds__. - """ - - def update(self, _delta_time): - """ - Update the entity. - - :type delta_time: float - :param delta_time: Elapsed time since the last update (in seconds). - """ - - if self.is_out_of_bound(): - self.remove() - - def update_sprite(self): - """ - Update the image currently used by the entity. - This method should be override. - """ - - def is_hitting_entity(self, entity): - """ - Check if the entity collide another. - - :type entity: entities.entity.Entity - :param entity: An entity which is maybe colliding this one. - - :rtype: bool - :returns: True if the entities are colliding, otherwise False. - """ - - pos = entity.pos - size = entity.size - return ( - (pos[0] + size[0] / 2 > self.pos[0] - self.size[0] / 2) - and (pos[0] - size[0] / 2 < self.pos[0] + self.size[0] / 2) - and (pos[1] + size[1] / 2 > self.pos[1] - self.size[1] / 2) - and (pos[1] - size[1] / 2 < self.pos[1] + self.size[1] / 2) - ) - - def is_out_of_bound(self, included=True): - """ - Check if the entity is in the terrain. - - :type included: bool - :param included: Optional! If True (default), check if the entire - entity is out of the terrain. Otherwise, only check if a part - of the entity is out of bounds. - - :rtype: bool - :returns: True if the entity is out of bounds, otherwise False. - """ - - width, height = self.level.size - if included: - return ( - (self.pos[0] + self.size[0] / 2 <= 0) - or (self.pos[0] - self.size[0] / 2 >= width) - or (self.pos[1] + self.size[1] / 2 <= 0) - or (self.pos[1] - self.size[1] / 2 >= height) - ) - return ( - (self.pos[0] - self.size[0] / 2 <= 0) - or (self.pos[0] + self.size[0] / 2 >= width) - or (self.pos[1] - self.size[1] / 2 <= 0) - or (self.pos[1] + self.size[1] / 2 >= height) - ) - - def is_hitting_floor(self): - """ - Check if the entity collide with the floor. - - :rtype: bool - :returns: True if the entity is colliding the floor, otherwise False. - """ - return self.pos[1] + self.size[1] / 2 >= self.level.size[1] - 1 - - def remove(self): - """ - Remove the entity from its level. - The entity will no longer be updated. - """ - - self.level.remove_entity(self) - self.remove_sounds() - - def remove_sounds(self): - """ - Stop and remove all sounds used by this entity. - """ - - for sound in self.sounds.values(): - if sound.is_playing: - sound.stop() - Game.audio_player.remove_sound(sound) diff --git a/src/entities/leaf.py b/src/entities/leaf.py deleted file mode 100644 index c354a42..0000000 --- a/src/entities/leaf.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a Leaf class. -This entity is used as leaf particles when a bean is destroyed. - -Created on 07/05/2018 -""" - -import random - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import ( - LEAF_SPEED, - LEAF_SPRITE_DURATION, - LEAF_WIND_SPEED, - AIR_RESISTANCE, -) -from entities.entity import Entity - - -class Leaf(Entity): - """ - Define a leaf which appears when a bean is destroyed. There are 3 leaf - types ("leaf", "pink leaf" and "super leaf") depending on the bean - that has just been destroyed. - """ - - def __init__(self, level, pos, speed, leaf_type): - """ - Initialise a Leaf object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: The default position of the leaf in a [x, y] list where x - and y are both float numbers. - - :type speed: float - :param speed: The falling speed of the leaf. - - :type leaf_type: str - :param leaf_type: The type of the leaf. It can be "leaf", "pink leaf" - or "super leaf". - """ - - self.vel = 0 - self.sprite_index = 0 - self.leaf_type = leaf_type - self.speed = speed - Entity.__init__(self, level, pos, (0.75, 0.75)) - - def init_images(self): - """ - Load leaf images. - """ - - self.__init_images__(self.leaf_type) - - def update(self, delta_time): - """ - Update the leaf (position, sprite). - - :type delta_time: float - :param delta_time: Time elapsed since the last frame update - """ - - self.pos[0] += self.vel * delta_time - self.pos[1] += (LEAF_SPEED - abs(self.vel)) * self.speed * delta_time - if self.vel > 0: - self.vel -= AIR_RESISTANCE * delta_time - if self.vel < 0: - self.vel = 0 - elif self.vel < 0: - self.vel += AIR_RESISTANCE * delta_time - if self.vel > 0: - self.vel = 0 - Entity.update(self, delta_time) - - def update_sprite(self): - """ - Update the images to create a flight animation. - """ - - score = self.level.get_style_type_with_score() - self.sprite_index = self.sprite_index + 1 if self.sprite_index < 2 else 0 - self.current_image_name = f"leaf_{score}_{self.sprite_index}.png" - - self.level.set_action_delay( - (self, "updateSprite"), LEAF_SPRITE_DURATION, self.update_sprite - ) - - def set_left_wind(self): - """ - Change the leaf's velocity as if there is wind to the left. - """ - - self.vel = -LEAF_WIND_SPEED - - def set_right_wind(self): - """ - Change the leaf's velocity as if there is wind to the right. - """ - - self.vel = LEAF_WIND_SPEED - - def cut(self): - """ - Replace the leaf by 2 leaf pieces as if it was cut in a half. - """ - - if not random.randint(0, 2): - for delta_pos in (-self.size[0], self.size[0]): - self.level.spawn_leaf_piece( - (self.pos[0] + delta_pos / 2, self.pos[1]), - self.speed, - self.leaf_type + " piece", - self.vel / 2, - ) - self.remove() - - def remove(self): - """ - Remove the leaf and its action delayed. - """ - - self.level.remove_action_delay((self, "updateSprite")) - Entity.remove(self) diff --git a/src/entities/leaf_piece.py b/src/entities/leaf_piece.py deleted file mode 100644 index b46b4b6..0000000 --- a/src/entities/leaf_piece.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a LeafPiece class. -This entity is used as little leaf particles when a normal leaf is cut. - -Created on 08/05/2018 -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import LEAF_SPRITE_DURATION -from entities.leaf import Leaf - - -class LeafPiece(Leaf): - """ - Define a piece of leaf which appears when a normal leaf is cut. There are - 3 leaf types ("leaf", "pink leaf" and "super leaf") depending on the - leaf that has just been cut. - """ - - def __init__(self, level, pos, speed, leafpiece_type, vel=0): - """ - Initialise a Leaf object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: The default position of the leaf in a [x, y] list where x - and y are both float numbers. - - :type speed: float - :param speed: The falling speed of the leaf. - - :type leafpiece_type: str - :param leafpiece_type: The type of the leaf. It can be "leaf", "pink leaf" - or "super leaf". - - :type vel: float - :param vel: (Optional) The default velocity of the leaf. - """ - - Leaf.__init__(self, level, pos, speed, leafpiece_type) - self.vel = vel - - def init_images(self): - """ - Load leaf_pieces images. - """ - - self.__init_images__(self.leaf_type) - - def update_sprite(self): - """ - Update the images to create a flight animation. - """ - - score = self.level.get_style_type_with_score() - - self.sprite_index = self.sprite_index + 1 if self.sprite_index < 2 else 0 - self.current_image_name = f"leafpiece_{score}_{self.sprite_index}.png" - - self.level.set_action_delay( - (self, "update_sprite"), LEAF_SPRITE_DURATION, self.update_sprite - ) - - def cut(self): - """ - A piece of leaf can't be cut so this method do nothing. - """ diff --git a/src/entities/pink_bean.py b/src/entities/pink_bean.py deleted file mode 100644 index 7ca6540..0000000 --- a/src/entities/pink_bean.py +++ /dev/null @@ -1,64 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provides a Pink_bean class. - -Created on 21/03/2018 -""" - -import random - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean - - -class PinkBean(Bean): - """ - Create pink beans. Pink beans have the hability to repair one case when - cut or caught. - """ - - def init_images(self): - """ - Load pink bean images. - """ - - self.__init_images__("pink bean") - - def catch(self): - """ - Repair a case and the follow Pyoro tongue. - """ - - self.level.repair_case() - Bean.catch(self) - - def cut(self): - """ - Spawn pink leafs. - """ - - self.sounds["bean_cut"].play() - for _ in range(2): - rand_pos = [ - self.pos[0] + random.uniform(-0.5, 0.5), - self.pos[1] + random.uniform(-0.5, 0.2), - ] - self.level.spawn_leaf(rand_pos, "pink leaf") diff --git a/src/entities/pyobot.py b/src/entities/pyobot.py deleted file mode 100644 index 0369172..0000000 --- a/src/entities/pyobot.py +++ /dev/null @@ -1,132 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Pyobot class, a Pyoro bot. - -Created on 11/04/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean -from entities.pyoro import Pyoro - - -class Pyobot(Pyoro): - """ - Create a Pyobot used in the main menu. This Pyoro automatically move to - catch falling beans. - """ - - def update(self, delta_time): - """ - Pyobot search for the best position to eat the lowest bean and update - its position. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - if not self.tongue: - pos = self.get_nearest_pos(*self.get_pos_to_eat()) - if pos > 0 and pos < self.level.size[0]: - if self.pos[0] > pos: - self.enable_move_left() - elif self.pos[0] < pos: - self.enable_move_right() - else: - self.disable_move() - - if int(pos) == int(self.pos[0]): - self.look_bean() - self.enable_capacity() - Pyoro.update(self, delta_time) - - def get_pos_to_eat(self): - """ - Find the 2 horizontal position that could allow Pyobot to eat the - lowest bean. - - :rtype: tuple - :returns: A (pos1, pos2) tuple where pos1 is the leftmost position and - pos2 is the rightmost one. - """ - - lowest_bean = self.get_lowest_bean() - if lowest_bean: - return lowest_bean.pos[0] - ( - self.level.size[1] - lowest_bean.pos[1] - ), lowest_bean.pos[0] + (self.level.size[1] - lowest_bean.pos[1]) - return -1, self.level.size[0] - - def look_bean(self): - """ - Turn Pyobot to make him look at the bean he will catch. - """ - - lowest_bean = self.get_lowest_bean() - if lowest_bean: - if self.pos[0] > lowest_bean.pos[0]: - self.enable_move_left() - else: - self.enable_move_right() - self.disable_move() - - def get_nearest_pos(self, pos1, pos2): - """ - Return the nearest horizontal position from Pyobot. - - :type pos1: float - :param pos1: The first horizontal position. - - :type pos2: float - :param pos2: The second horizontal position. - - :rtype: float - :returns: The best position between pos1 and pos2. - """ - - pos = sorted([pos1, pos2], key=lambda x: abs(self.pos[0] - x)) - if pos[0] <= 0 or pos[0] >= self.level.size[0]: - return pos[1] - return pos[0] - - def remove(self): - """ - Reset the level (this entity can't die). - """ - - self.level.reset() - - def get_lowest_bean(self): - """ - Find the bean which has the smallest vertical coordinate. - - :rtype: entities.bean.Bean - :returns: The lowest bean. - """ - - best_entity = None - for entity in self.level.entities: - if isinstance(entity, Bean): - if best_entity is None: - best_entity = entity - elif entity.pos[1] > best_entity.pos[1]: - best_entity = entity - return best_entity diff --git a/src/entities/pyobot_2.py b/src/entities/pyobot_2.py deleted file mode 100644 index 615832a..0000000 --- a/src/entities/pyobot_2.py +++ /dev/null @@ -1,128 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Pyobot_2 class, a Pyoro 2 bot. - -Created on 01/09/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean -from entities.pyoro_2 import Pyoro2 - - -class Pyobot2(Pyoro2): - """ - Create a Pyobot 2 used in the main menu. This Pyoro 2 automatically move - to shoot falling beans. - """ - - def update(self, delta_time): - """ - Pyobot 2 search for the best position to eat the lowest bean and - update its position. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - pos = self.get_nearest_pos(*self.get_pos_to_eat()) - if 0 < pos < self.level.size[0]: - if self.pos[0] > pos: - self.enable_move_left() - elif self.pos[0] < pos: - self.enable_move_right() - else: - self.disable_move() - - if int(pos) == int(self.pos[0]): - self.look_bean() - self.enable_capacity() - Pyoro2.update(self, delta_time) - - def get_pos_to_eat(self): - """ - Find the 2 horizontal position that could allow Pyobot 2 to eat the - lowest bean. - - :rtype: tuple - :returns: A (pos1, pos2) tuple where pos1 is the leftmost position and - pos2 is the rightmost one. - """ - - lowest_bean = self.get_lowest_bean() - if lowest_bean: - return [ - lowest_bean.pos[0] - (self.level.size[0] - lowest_bean.pos[1]), - lowest_bean.pos[0] + (self.level.size[0] - lowest_bean.pos[1]), - ] - return [-1, self.level.size[0]] - - def look_bean(self): - """ - Turn Pyobot 2 to make him look at the bean he will catch. - """ - - lowest_bean = self.get_lowest_bean() - if lowest_bean: - if self.pos[0] > lowest_bean.pos[0]: - self.enable_move_left() - else: - self.enable_move_right() - self.disable_move() - - def get_nearest_pos(self, pos1, pos2): - """ - Return the nearest horizontal position from Pyobot 2. - - :type pos1: float - :param pos1: The first horizontal position. - - :type pos2: float - :param pos2: The second horizontal position. - - :rtype: float - :returns: The best position between pos1 and pos2. - """ - - pos = sorted([pos1, pos2], key=lambda x: abs(self.pos[0] - x)) - if pos[0] <= 0 or pos[0] >= self.level.size[0]: - return pos[1] - return pos[0] - - def remove(self): - """ - Reset the level (this entity can't die). - """ - - self.level.reset() - - def get_lowest_bean(self): - """ - Find the bean which has the smallest vertical coordinate. - - :rtype: entities.bean.Bean - :returns: The lowest bean. - """ - - for entity in self.level.entities: - if isinstance(entity, Bean): - return entity - return None diff --git a/src/entities/pyoro.py b/src/entities/pyoro.py deleted file mode 100644 index f966275..0000000 --- a/src/entities/pyoro.py +++ /dev/null @@ -1,295 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Pyoro class, the main character of the game. - -Created on 18/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from entities.tongue import Tongue -from game.config import ( - PYORO_SPEED, - PYORO_NOTCH_DURATION, - PYORO_EATING_DURATION, - PYORO_DIE_SPEED, -) - - -class Pyoro(Entity): - """ - Create a Pyoro (a little red bird) controlled by the player in game. - """ - - def __init__(self, level): - """ - Initialize a new Pyoro object. - - :type level: game.level.Level - :param level: The level managing this entity. - """ - - self.moving = False - self.notch = False - self.dead = False - self.tongue = None - self.eating_count = 0 - self.direction = 1 - _, height = level.size - Entity.__init__(self, level, (2, height - 2), (2, 2)) - - def init_images(self): - """ - Initialize Pyoro images. - """ - - self.__init_images__("pyoro 1") - - def init_sounds(self): - """ - Load Pyoro sounds. - """ - - self.__init_sounds__(("pyoro_move", "pyoro_die")) - - # directions - def enable_move_right(self): - """ - Make Pyoro move to the right by defining its direction. - """ - - if not self.dead and not self.tongue: - self.direction = 1 - self.moving = True - self.sounds["pyoro_move"].play(-1) - - def enable_move_left(self): - """ - Make Pyoro move to the left by defining its direction. - """ - - if not self.dead and not self.tongue: - self.direction = -1 - self.moving = True - self.sounds["pyoro_move"].play(-1) - - def disable_move(self): - """ - Stop Pyoro movement. - """ - - if self.sounds["pyoro_move"].is_playing: - self.sounds["pyoro_move"].pause() - self.moving = False - self.notch = False - - def move(self, delta_time): - """ - Update Pyoro's position according to elapsed time. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - if not self.dead and not self.tongue: - if not self.notch: - if self.direction == 1: - new_pos = self.pos[0] + self.size[0] / 2 + PYORO_SPEED * delta_time - void_pos = self.get_void_case_pos_on_path(new_pos) - - if new_pos >= self.level.size[0]: - self.pos[0] = self.level.size[0] - self.size[0] / 2 - elif void_pos is not None: - self.pos[0] = void_pos - self.size[0] / 2 - else: - self.pos[0] += PYORO_SPEED * delta_time - - else: - new_pos = self.pos[0] - self.size[0] / 2 - PYORO_SPEED * delta_time - void_pos = self.get_void_case_pos_on_path(new_pos) - if new_pos < 0: - self.pos[0] = self.size[0] / 2 - elif void_pos is not None: - self.pos[0] = void_pos + self.size[0] / 2 + 1 - else: - self.pos[0] -= PYORO_SPEED * delta_time - self.level.create_action_delay( - (self, "enable_notch"), PYORO_NOTCH_DURATION, self.enable_notch - ) - - def get_void_case_pos_on_path(self, new_pos): - """ - Find the nearest hole from Pyoro. If there is no hole, return None. - - :type new_pos: float - :param new_pos: The horizontal position where Pyoro try to go. - - :rtype: int, None - :returns: The nearest destroyed case index (or none if there is no - destroyed case). - """ - - if self.pos[0] < new_pos: - old_pos = int(self.pos[0] + self.size[0] / 2) - new_pos = min(int(new_pos), len(self.level.cases) - 1) - for i in range(old_pos, new_pos + 1): - if not self.level.cases[i].exists: - return i - else: - old_pos = int(self.pos[0] - self.size[0] / 2 - 1) - new_pos = max(int(new_pos), 0) - for i in range(old_pos, new_pos - 1, -1): - if not self.level.cases[i].exists: - return i - return None - - def enable_notch(self): - """ - Make Pyoro do a little jump. - """ - - self.notch = True - self.level.remove_action_delay((self, "enable_notch")) - self.level.create_action_delay( - (self, "disable_notch"), PYORO_NOTCH_DURATION, self.disable_notch - ) - - def disable_notch(self): - """ - Make Pyoro return to normal posture. - """ - - self.notch = False - self.level.remove_action_delay((self, "disable_notch")) - - # update method - def update(self, delta_time): - """ - Update Pyoro (position, posture and sprite). - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - if self.moving: - self.move(delta_time) - else: - self.level.remove_action_delay((self, "enable_notch")) - self.disable_notch() - self.update_sprite() - - if self.dead: - if self.pos[1] - self.size[1] / 2 < self.level.size[0]: - self.pos[1] += PYORO_DIE_SPEED * delta_time - - def update_sprite(self): - """ - Define the sprite to use (normal, eating, jumping, catching, dying) - """ - - if self.eating_count: - self.level.create_action_delay( - (self, "update_eating_count"), - PYORO_EATING_DURATION, - self.update_eating_count, - ) - - style_type = self.level.get_style_type_with_score() - if self.dead: - image_name = "pyoro_{}_die_{}.png" - elif self.tongue: - image_name = "pyoro_{}_eat_1_{}.png" - elif self.notch: - image_name = "pyoro_{}_jump_{}.png" - elif self.eating_count % 2: - image_name = "pyoro_{}_eat_0_{}.png" - else: - image_name = "pyoro_{}_normal_{}.png" - - self.current_image_name = image_name.format(style_type, self.direction) - - def update_eating_count(self): - """ - Update eating count value while in eating animation. - """ - - self.eating_count += 1 - if self.eating_count < 8: - self.level.set_action_delay( - (self, "update_eating_count"), - PYORO_EATING_DURATION, - self.update_eating_count, - ) - else: - self.eating_count = 0 - self.level.remove_action_delay((self, "update_eating_count")) - - def enable_capacity(self): - """ - Stop Pyoro and make him sticks out his tongue. - """ - - if not self.dead: - self.sounds["pyoro_move"].pause() - if self.tongue: - self.tongue.remove() - self.tongue = Tongue(self.level, self.direction) - self.level.entities.append(self.tongue) - - def disable_capacity(self): - """ - Stop Pyoro from sticking out his tongue. - """ - - if not self.dead: - if self.tongue: - self.tongue.go_back = True - - def remove(self): - """ - Remove Pyoro's tongue and kill him starting its death animation. - """ - - if not self.dead: - self.dead = True - if self.tongue: - self.tongue.remove() - - self.disable_move() - - self.level.remove_action_delay( - (self, "enable_notch"), - (self, "disable_notch"), - (self, "update_eating_count"), - ) - - self.level.create_action_delay( - (self, "game_over"), 1.28, self.level.level_drawer.activity.game_over - ) - self.level.create_action_delay( - (self, "removeGame_overActionDelay"), - 1.29, - self.level.remove_action_delay, - (self, "game_over"), - ) - - self.level.get_audio_player().speed = 1 - self.sounds["pyoro_die"].play() diff --git a/src/entities/pyoro_2.py b/src/entities/pyoro_2.py deleted file mode 100644 index dc52240..0000000 --- a/src/entities/pyoro_2.py +++ /dev/null @@ -1,201 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Pyoro class, the main character of the game. - -Created on 18/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean -from entities.leaf import Leaf -from entities.pyoro import Pyoro -from entities.seed import Seed -from game.config import PYORO_SHOOT_SPRITE_DURATION - - -class Pyoro2(Pyoro): - """ - Create a Pyoro 2 (a little yellow bird) controlled by the player in game. - """ - - def __init__(self, level): - """ - Initialize a new Pyoro 2 object. - - :type level: game.level.Level - :param level: The level managing this entity. - """ - - self.shoot_sprite_id = 0 - Pyoro.__init__(self, level) - - def init_images(self): - """ - Initialize Pyoro 2 images. - """ - - self.__init_images__("pyoro 2") - - def init_sounds(self): - """ - Load Pyoro 2 sounds. - """ - - self.__init_sounds__(("pyoro_shoot",)) - Pyoro.init_sounds(self) - - def enable_move_left(self): - """ - Make Pyoro 2 move to the left by defining its direction. - """ - - if self.shoot_sprite_id: - self.shoot_sprite_id = 0 - self.level.remove_action_delay((self, "update_shoot_sprite_id")) - Pyoro.enable_move_left(self) - - def enable_move_right(self): - """ - Make Pyoro 2 move to the right by defining its direction. - """ - - if self.shoot_sprite_id: - self.shoot_sprite_id = 0 - self.level.remove_action_delay((self, "update_shoot_sprite_id")) - Pyoro.enable_move_right(self) - - def update(self, delta_time): - """ - Update Pyoro 2 (position, posture and sprite). - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - if self.shoot_sprite_id == 1: - self.level.create_action_delay( - (self, "update_shoot_sprite_id"), - PYORO_SHOOT_SPRITE_DURATION, - self.update_shoot_sprite_id, - ) - Pyoro.update(self, delta_time) - - def update_shoot_sprite_id(self): - """ - Update shoot sprite index value for shoot animations. - """ - - self.shoot_sprite_id += 1 - if self.shoot_sprite_id < 5: - self.level.set_action_delay( - (self, "update_shoot_sprite_id"), - PYORO_SHOOT_SPRITE_DURATION, - self.update_shoot_sprite_id, - ) - else: - self.shoot_sprite_id = 0 - self.level.remove_action_delay((self, "update_shoot_sprite_id")) - - def update_sprite(self): - """ - Define the sprite to use (normal, shooting, jumping, dying) - """ - - style_type = self.level.get_style_type_with_score() - shoot_type = self.shoot_sprite_id - 1 - if self.dead: - self.current_image_name = f"pyoro_{style_type}_die_{self.direction}.png" - elif self.shoot_sprite_id: - self.current_image_name = ( - f"pyoro_{style_type}_shoot_{shoot_type}_{self.direction}.png" - ) - elif self.notch: - self.current_image_name = f"pyoro_{style_type}_jump_{self.direction}.png" - else: - self.current_image_name = f"pyoro_{style_type}_normal_{self.direction}.png" - - def enable_capacity(self): - """ - Stop Pyoro 2 and make him cut some beans and leafs. - """ - - self.sounds["pyoro_shoot"].play() - self.shoot_sprite_id = 1 - bean_coords = [] - - for entity in self.level.entities: - if self.is_shooting_entity(entity): - if isinstance(entity, Bean): - entity.cut() - entity.catch() - entity.remove() - bean_coords.append(list(entity.pos)) - elif isinstance(entity, Leaf): - entity.cut() - if self.direction == 1: - entity.set_right_wind() - else: - entity.set_left_wind() - - if len(bean_coords) == 1: - score = 50 - elif len(bean_coords) == 2: - score = 100 - elif len(bean_coords) == 3: - score = 300 - else: - score = 1000 - - for bean_pos in bean_coords: - self.level.spawn_score(score, bean_pos) - self.level.entities.append(Seed(self.level, 35, self.direction)) - self.level.entities.append(Seed(self.level, 55, self.direction)) - - def is_shooting_entity(self, entity): - """ - Return True if entity is on the trajectory of a potential shot. - - :rtype: bool - :returns: True if Pyoro 2 can shoot the entity, False otherwise. - """ - - if self.direction == 1: - distance = entity.pos[0] - self.pos[0] - else: - distance = self.pos[0] - entity.pos[0] - return ( - self.pos[1] - entity.pos[1] + entity.size[1] >= distance - entity.size[0] - ) and ( - self.pos[1] - entity.pos[1] - entity.size[1] <= distance + entity.size[0] - ) - - def disable_capacity(self): - """ - Pyoro 2 doesn"t need this method so do nothing. - """ - - def remove(self): - """ - Kill Pyoro 2 and remove its action delayed. - """ - - self.level.remove_action_delay((self, "update_shoot_sprite_id")) - Pyoro.remove(self) diff --git a/src/entities/score_text.py b/src/entities/score_text.py deleted file mode 100644 index 5db8512..0000000 --- a/src/entities/score_text.py +++ /dev/null @@ -1,102 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Score_text class (entity). - -Created on 21/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from game.config import SCORE_TEXT_BLINK_DURATION, SCORE_TEXT_LIFE_DURATION - - -class ScoreText(Entity): - """ - Create a Score_text which is a flashy entity to show points that has just - been earned at a specific position. - """ - - def __init__(self, level, pos, value): - """ - Initialize a new Score_text object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: An [x, y] list where x and y are both float numbers. - - :type value: int - :param value: The value to display (it can be 10, 50, 100, 300 or - 1000). - """ - - pixel_size = 1 - for _ in str(value): - if value == 1: - pixel_size += 2 - else: - pixel_size += 4 - self.value = value - self.color_index = 0 - Entity.__init__(self, level, pos, (pixel_size * 0.125, 0.875)) - - def init_images(self): - """ - Initialize score_text images. - """ - - self.__init_images__("score text") - - def update(self, deltaTime): - """ - Update the score_text. - - :type deltaTime: float - :param deltaTime: Time elapsed since the last update. - """ - - self.level.create_action_delay( - (self, "destroy"), SCORE_TEXT_LIFE_DURATION, self.remove - ) - Entity.update(self, deltaTime) - - def update_sprite(self): - """ - Change the sprite to make a blinking effect. - """ - - if self.value in (300, 1000): - self.color_index = self.color_index + 1 if self.color_index < 5 else 0 - self.current_image_name = f"number_{self.value}_{self.color_index}.png" - else: - self.current_image_name = f"number_{self.value}.png" - self.level.set_action_delay( - (self, "update_sprite"), SCORE_TEXT_BLINK_DURATION, self.update_sprite - ) - - def remove(self): - """ - Remove the score_text actions delayed en the score_text itself. - """ - - self.level.remove_action_delay((self, "destroy"), (self, "update_sprite")) - Entity.remove(self) diff --git a/src/entities/seed.py b/src/entities/seed.py deleted file mode 100644 index 0e15c4e..0000000 --- a/src/entities/seed.py +++ /dev/null @@ -1,124 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Seed class for Pyoro 2 shoot animation. - -Created on 27/03/2018. -""" - -import math -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from gui.image_transformer import resize_image -from game.config import SEED_SPEED, AIR_RESISTANCE, GRAVITY_FORCE, ENTITIES_IMAGE_PATH - - -class Seed(Entity): - """ - Create seeds used for Pyoro 2 shoot animations. - """ - - def __init__(self, level, angle, direction): - """ - Initialize a new Seed object. - - :type level: game.level.Level - :param level: The level managing this object - - :type angle: float - :param angle: The initial trajectory's angle in degree. - - :type direction: int - :param direction: The direction of the seed (1=right, -1=left). - """ - - self.direction = direction - self.sprite_alpha = 255 - self.vel = [ - math.cos(angle * math.pi / 180) * direction * SEED_SPEED, - -math.sin(angle * math.pi / 180) * SEED_SPEED, - ] - - pos = ( - level.pyoro.pos[0] + (level.pyoro.size[0] / 2 + 0.0625) * direction, - level.pyoro.pos[1] - level.pyoro.size[1] / 2 + 0.0625, - ) - - Entity.__init__(self, level, pos, (0.125, 0.125)) - - def __init_images__(self, folder_name): - """ - Internally load seed images in memory. - - :type folder_name: str - :param folder_name: The path to the folder containing the seeds. - """ - - self.images = {} - folder = os.path.join(ENTITIES_IMAGE_PATH, folder_name) - image_names = os.listdir(folder) - case_size = self.level.level_drawer.get_case_size() - - for image_name in image_names: - if image_name.split(".")[-1] == "png": - self.images[image_name] = resize_image( - self.level.level_drawer.activity.window.get_image( - os.path.join(folder, image_name), alpha_channel=False - ), - (case_size[0] * self.size[0], case_size[1] * self.size[1]), - ) - self.images[image_name].set_alpha(self.sprite_alpha) - self.current_image_name = image_name - - def init_images(self): - """ - Initialize seed images. - """ - - self.__init_images__("seed") - - def update(self, deltaTime): - """ - Update the seed (velocity, position, image opacity). - - :type deltaTime: float - :param deltaTime: Time elapsed since the last update. - """ - - self.vel[0] -= AIR_RESISTANCE * self.direction * deltaTime - self.vel[1] += GRAVITY_FORCE * deltaTime - self.pos[0] += self.vel[0] - self.pos[1] += self.vel[1] - - if self.sprite_alpha > 0: - self.sprite_alpha -= 64 * deltaTime - else: - self.remove() - Entity.update(self, deltaTime) - - def update_sprite(self): - """ - Define the sprite to use according to the current level style - """ - - self.current_image_name = f"seed_{self.level.get_style_type_with_score()}.png" - self.images[self.current_image_name].set_alpha(self.sprite_alpha) diff --git a/src/entities/smoke.py b/src/entities/smoke.py deleted file mode 100644 index e0390e7..0000000 --- a/src/entities/smoke.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Smoke class for destruction animations. - -Created on 21/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.entity import Entity -from game.config import SMOKE_SPRITE_DURATION - - -class Smoke(Entity): - """ - Create a Smoke object used for destrution animations. - """ - - def __init__(self, level, pos): - """ - Initialize a new Smoke object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: An [x, y] list where x and y are both float numbers. - """ - - self.sprite_index = 0 - Entity.__init__(self, level, pos, (1.5, 1.5)) - - def init_images(self): - """ - Initialize smoke images. - """ - - self.__init_images__("smoke") - - def update(self, deltaTime): - """ - Update the smoke. - - :type deltaTime: float - :param deltaTime: Time elapsed since the last update. - """ - - self.level.create_action_delay( - (self, "destroy"), - SMOKE_SPRITE_DURATION * 3, - self.remove - ) - Entity.update(self, deltaTime) - - def update_sprite(self): - """ - Define the sprite to use according to the animation's state and the - current level style. - """ - - score = self.level.get_style_type_with_score() - self.sprite_index = self.sprite_index + 1 if self.sprite_index < 2 else 0 - self.current_image_name = f"smoke_{score}_{self.sprite_index}.png" - - self.level.set_action_delay((self, "update_sprite"), - SMOKE_SPRITE_DURATION, self.update_sprite) - - def remove(self): - """ - Remove the smoke actions delayed and the smoke itself. - """ - - self.level.remove_action_delay( - (self, "destroy"), (self, "update_sprite")) - Entity.remove(self) diff --git a/src/entities/super_bean.py b/src/entities/super_bean.py deleted file mode 100644 index 80f940f..0000000 --- a/src/entities/super_bean.py +++ /dev/null @@ -1,160 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Score_text class (entity). - -Created on 17/03/2018. -""" - -import random - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean -from game.config import BEAN_SPRITE_DURATION - - -class SuperBean(Bean): - """ - Create a Super_bean object which have the hability to repair 10 destroyed - cases and to explode all beans currently falling. - """ - - def __init__(self, level, pos, speed): - """ - Initialize a new Super_bean object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type pos: list - :param pos: An [x, y] list where x and y are both float numbers. - - :type speed: float - :param speed: The falling speed multiplicator. - """ - - self.sprite_index = 0 - self.color_index = 0 - Bean.__init__(self, level, pos, speed) - - def init_images(self): - """ - Initialize super_bean images. - """ - - self.__init_images__("super bean") - - def init_sounds(self): - """ - Load super_bean sounds. - """ - - Bean.init_sounds(self) - self.__init_sounds__(("bean_implode",)) - - def update_sprite(self): - """ - Define the sprite to use according to the blinking animation state and - the current level style. - """ - - if not self.color_index % 2: - self.sprite_index = self.sprite_index + 1 if self.sprite_index < 2 else 0 - - self.color_index = self.color_index + 1 if self.color_index < 5 else 0 - self.current_image_name = f"bean_{self.sprite_index}_{self.color_index}.png" - - self.level.set_action_delay( - (self, "update_sprite"), BEAN_SPRITE_DURATION / 6, self.update_sprite - ) - - def catch(self): - """ - Explode all the beans currently falling and repair 10 destroyed cases. - """ - - i = 0 - for entity in self.level.entities: - if isinstance(entity, Bean) and entity != self: - self.level.create_action_delay( - (self, "destroy_bean", i), i * 0.1, self.destroy_bean, entity, i - ) - i += 1 - i = 0 - empty_cases = list(self.level.get_void_cases()) - for i in range(min(10, len(empty_cases))): - self.level.create_action_delay( - (self, "repair_case", empty_cases[i].pos), - i * 0.5, - self.repair_case, - empty_cases[i], - ) - Bean.catch(self) - - def destroy_bean(self, bean, bean_id): - """ - Explode a bean, increase the score and remove action delayed - associated with this bean. - - :type bean: entities.bean.Bean - :param bean: The bean to destroy. - - :type bean_id: int - :param bean_id: An integer associated with this bean when the explosion - was decided. - """ - - self.sounds["bean_implode"].play() - bean.cut() - bean.remove() - self.level.spawn_score(50, bean.pos) - self.level.remove_action_delay((self, "destroy_bean", bean_id)) - - def cut(self): - """ - Spawn super leafs and play a sound. - """ - - self.sounds["bean_cut"].play() - for _ in range(2): - rand_pos = [ - self.pos[0] + random.uniform(-0.5, 0.5), - self.pos[1] + random.uniform(-0.5, 0.2), - ] - self.level.spawn_leaf(rand_pos, "super leaf") - - def repair_case(self, case): - """ - Repair a case and remove the associated action delayed. - - :type case: game.case.Case - :param case: The case to repair. - """ - - self.level.repair_case(case) - self.level.remove_action_delay((self, "repair_case", case.pos)) - - def remove(self): - """ - Remove the super bean action delayed and the super bean itself. - """ - - self.level.remove_action_delay(("override", self, "update_sprite")) - Bean.remove(self) diff --git a/src/entities/tongue.py b/src/entities/tongue.py deleted file mode 100644 index b4f7099..0000000 --- a/src/entities/tongue.py +++ /dev/null @@ -1,140 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Tongue class. - -Created on 21/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.bean import Bean -from entities.entity import Entity -from game.config import TONG_SPEED - - -class Tongue(Entity): - """ - Creat a Tongue object used by Pyoro to catch falling beans. - """ - - def __init__(self, level, direction): - """ - Initialize a new Tongue object. - - :type level: game.level.Level - :param level: The level managing this entity. - - :type direction: int - :param direction: The direction of the tongue (1 = right, -1 = left). - """ - - self.direction = direction - self.caught_bean = None - self.go_back = False - - pos = ( - level.pyoro.pos[0] + (level.pyoro.size[0] / 2 + 0.6) * direction, - level.pyoro.pos[1] - level.pyoro.size[1] / 2 + 0.6, - ) - - Entity.__init__(self, level, pos, (1.2, 1.2)) - - def init_images(self): - """ - Initialize tongue images. - """ - - self.__init_images__("tongue") - - def init_sounds(self): - """ - Load tongue sounds. - """ - - self.__init_sounds__(("tongue", "pyoro_eat")) - self.sounds["tongue"].play() - - def update(self, deltaTime): - """ - Update the tongue (position, direction, ...). - - :type deltaTime: float - :param deltaTime: Time elapsed since the last update. - """ - - _, height = self.level.size - if self.go_back: - self.pos[0] -= TONG_SPEED * 2 * self.direction * deltaTime - self.pos[1] += TONG_SPEED * 2 * deltaTime - - if self.caught_bean: - self.caught_bean.pos[0] -= TONG_SPEED * 2 * self.direction * deltaTime - self.caught_bean.pos[1] += TONG_SPEED * 2 * deltaTime - - if self.pos[1] >= self.level.pyoro.pos[1]: - if self.caught_bean: - self.sounds["pyoro_eat"].play() - self.level.pyoro.eating_count = 1 - self.remove() - else: - self.pos[0] += TONG_SPEED * self.direction * deltaTime - self.pos[1] -= TONG_SPEED * deltaTime - - for entity in self.level.entities: - if self.is_hitting_entity(entity) and isinstance(entity, Bean): - entity.catch() - self.sounds["tongue"].stop() - - _, height = self.level.size - if self.pos[1] < height * 0.2: - score = 1000 - elif self.pos[1] < height * 0.4: - score = 300 - elif self.pos[1] < height * 0.6: - score = 100 - elif self.pos[1] < height * 0.8: - score = 50 - else: - score = 10 - self.level.spawn_score(score, self.pos) - self.caught_bean = entity - self.go_back = True - return None - self.go_back = self.is_out_of_bound(False) - self.update_sprite() - Entity.update(self, deltaTime) - - def update_sprite(self): - """ - Define the sprite to use according to the current level style. - """ - - score = self.level.get_style_type_with_score() - self.current_image_name = f"tongue_{score}_{self.direction}.png" - - def remove(self): - """ - Remove the caught bean and the tongue itself. - """ - - if self.caught_bean: - self.caught_bean.remove() - self.level.pyoro.tongue = None - Entity.remove(self) diff --git a/src/game/__init__.py b/src/game/__init__.py deleted file mode 100644 index 12e0cb3..0000000 --- a/src/game/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -""" -Provide a Game class which store all the game's state. -""" - -import threading - - -class Game: - """Store game's states.""" - - def __init__(self, config, view_cls, controller_cls, audio_player_cls): - self.config = config - self.running = False - - self.view_thread = None - self.controller_thread = None - self.audio_player_thread = None - - self.view = view_cls(self, **config.get('view', {})) - self.controller = controller_cls(self, **config.get('controller', {})) - self.audio_player = audio_player_cls( - self, **config.get('audio_player', {})) - - def run(self): - """Start the game.""" - - if not self.running: - self.view_thread = threading.Thread(target=self.view.run) - self.controller_thread = threading.Thread( - target=self.controller.run) - self.audio_player_thread = threading.Thread( - target=self.audio_player.run) - - self.view_thread.start() - self.controller_thread.start() - self.audio_player_thread.start() - - self.running = True - - def stop(self): - """Stop the game.""" - - if self.running \ - and self.view_thread is not None \ - and self.controller_thread is not None \ - and self.audio_player_thread is not None: - self.view.stop() - self.controller.stop() - self.audio_player.stop() - - self.view_thread.join() - self.controller_thread.join() - self.audio_player_thread.join() - - self.running = False diff --git a/src/game/action_delay.py b/src/game/action_delay.py deleted file mode 100644 index 7c2e000..0000000 --- a/src/game/action_delay.py +++ /dev/null @@ -1,72 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to delay the call of a -function of method. - -Created on 14/08/2018 -""" - -import time - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -class ActionDelay: - """ - Delay the call of a function or method of a defined time. - """ - - def __init__(self, wait_time, fct, *fct_args, **fct_kwargs): - """ - Initialize an ActionDelay object. - - :type wait_time: float - :param wait_time: Delay (in second). - - :type fct: function, method - :param fct: The function or method to call. - - :type *fct_args: objects - :param *fct_args: The arguments to pass to the function - or method to run. - - :type **fct_kwargs: objects - :param **fct_kwargs: The optional arguments to pass to - the function or method to run. - """ - - self.wait_time = wait_time - self.passed_time = 0 - self.fct = fct - self.fct_args = fct_args - self.fct_kwargs = fct_kwargs - self.last_time = time.time() - - def update(self, delta_time): - """ - Update the timer. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - self.passed_time += delta_time - if self.passed_time >= self.wait_time: - self.fct(*self.fct_args, **self.fct_kwargs) diff --git a/src/game/case.py b/src/game/case.py deleted file mode 100644 index 2f4d4b0..0000000 --- a/src/game/case.py +++ /dev/null @@ -1,44 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a simple class representing blocks on which Pyoro can walk. - -Created on 17/03/2018 -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -class Case: - """ - A block on which Pyoro can walk. It can be destroyed and - repaired by entities.angel.Angel. - """ - - def __init__(self, pos): - """ - Initialize a Case object. - - :type pos: int - :param pos: The horizontal position of the block. - """ - - self.pos = pos - self.exists = True - self.is_repairing = False diff --git a/src/game/config.py b/src/game/config.py deleted file mode 100644 index d75a911..0000000 --- a/src/game/config.py +++ /dev/null @@ -1,135 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide useful constants used in the game. - -Created on 17/03/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -# General information about the game -# Debugging mode (if you want to see logs in a console) -DEBUG = True -# frame per seconds -FPS = 60 -# game name -NAME = "PYORO" -# game version -VERSION = "1.1.1" -# background color -WINDOW_COLOR = (120, 120, 120) -# If True, use less resources but cannot read several sounds at the same time -LOW_AUDIO = True - -# Update server address and login -# FTP host -UPDATE_HOST = "ftpupload.net" -# FTP username -UPDATE_USER = "epiz_22757918" -# FTP password -UPDATE_PASSWORD = "6UJDteWTmclaL" - -# Some level constants -# Air resistance value for leaf and seeds wind effect -AIR_RESISTANCE = 25 -# Speed of transition between to backgrounds -BACKGROUND_TRANSITION_DURATION = 3 -# Size of a block (in mm) -CASE_SIZE = 10 -# Gravity force for seeds falling effect -GRAVITY_FORCE = 9.81 -# Acceleration of the level speed each second -SPEED_ACCELERATION = 0.01 -# Duration of each animated background -BACKGROUND_ANIMATED_DURATION = 1 -# (for last backgrounds) -# Duration of each animation during splash screen (currently useless) -SPLASH_ANIMATION_DURATION = 0.125 - -# Main file paths -# File path to Graphical User Interface images -GUI_IMAGE_PATH = os.path.join("data", "images", "gui") -# File path to entities images -ENTITIES_IMAGE_PATH = os.path.join("data", "images", "entities") -# File path to level images (backgrounds, blocks,...) -LEVEL_IMAGE_PATH = os.path.join("data", "images", "level") - -# Entities info -# Angel speed (in case per second) -ANGEL_SPEED = 35 -# Duration of each angel sprite (in second) -ANGEL_SPRITE_DURATION = 0.5 - -# Bean spawn frequency (the value increases with the score) (in second) -BEAN_FREQUENCY = 2 -# Bean speed (in case per second) -BEAN_SPEED = 1.8 -# Duration of each bean sprite (in second) -BEAN_SPRITE_DURATION = 0.2 - -# Duration of each leaf sprite (in second) -LEAF_SPRITE_DURATION = 0.2 -# Leaf speed (in case per second) -LEAF_SPEED = 1.5 -# Wind force applied to bean leaf when shot (in case per second) -LEAF_WIND_SPEED = 15 - -# Duration of each pyoro eating sprite (in second) -PYORO_EATING_DURATION = 0.04 -# Pyoro speed when it dies (in case per second) -PYORO_DIE_SPEED = 2 -# Pyoro notch duration (in second) -PYORO_NOTCH_DURATION = 0.01 -# Sprite frequency when pyoro 2 shoot (in second) -PYORO_SHOOT_SPRITE_DURATION = 0.1 -# Pyoro speed (in case per second) -PYORO_SPEED = 25 - -# Seed speed (in case per second) -SEED_SPEED = 45 - -# Duration of each smoke sprite (in second) -SMOKE_SPRITE_DURATION = 0.2 - -# Duration of each text sprite (in second) -SCORE_TEXT_BLINK_DURATION = 0.05 -# Time before the destruction of each text sprite (in second) -SCORE_TEXT_LIFE_DURATION = 0.3 - -# Pyoro tongue speed (in case per second) -TONG_SPEED = 25 - -# Default options used at first boot and when reset -DEFAULT_OPTIONS = { - "keyboard": {"right": 100, "left": 97, "action": 32, "pause": 27}, - "joystick": { - "right": {"input_type": 9, "hat_id": 0, "value": (1, 0)}, - "left": {"input_type": 9, "hat_id": 0, "value": (-1, 0)}, - "action": {"input_type": 10, "button_id": 2}, - "pause": {"input_type": 10, "button_id": 9}, - }, - "last game": 0, - "high score": [0, 0], - "music volume": 1, - "sound volume": 1, -} diff --git a/src/game/debug_logger.py b/src/game/debug_logger.py deleted file mode 100644 index 4bd2094..0000000 --- a/src/game/debug_logger.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a DebugLogger class to manage outputs debug logs. - -Created on 15/08/2018 -""" - -import sys -import time -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import DEBUG -from game.util import get_external_data_path - - -class DebugLogger: - """ - Replace the default output (sys.stdout). Write debug log files and - display output messages. - """ - - def __init__(self): - """ - Initialize a DebugLogger object. - """ - - self.message = [] - self.log_folder = get_external_data_path() - self.log_file = self.get_log_file() - sys.stdout = self - print("[INFO] [DebugLogger.__init__] Starting DebugLogger") - - def get_log_file(self): - """ - Get the relative path of a new debug log. - - :rtype: _io.TextIOWrapper - :returns: A new file opened in text write mode. - """ - - if not os.path.exists(os.path.join(self.log_folder, "logs")): - os.makedirs(os.path.join(self.log_folder, "logs")) - log_id = 1 - date = time.localtime() - file_name = f"{date.tm_year}-{date.tm_mon}-{date.tm_mday}-{log_id}.txt" - file_path = os.path.join(self.log_folder, "logs", file_name) - while os.path.exists(file_path): - log_id += 1 - file_path = os.path.join(self.log_folder, "logs", file_name) - return open(file_path, "w", encoding="utf-8") - - def write(self, message): - """ - Write something to the debug log and default output. - - :type message: str - :param message: A string to write. - """ - - self.message.append(message) - if DEBUG and sys.__stdout__: - sys.__stdout__.write(message) - if message == "\n": - self.log_file.write("\n") - else: - date = time.localtime() - content = f"[{date.tm_hour}:{date.tm_min}:{date.tm_sec}] {message}" - self.log_file.write(content) - self.log_file.flush() - - def flush(self): - """ - Flush the default output (sys.stdout). - """ - - if sys.__stdout__: - sys.__stdout__.flush() - - def close(self): - """ - Close the default output (sys.stdout). - """ - - sys.stdout = sys.__stdout__ - self.log_file.close() diff --git a/src/game/ftp_manager.py b/src/game/ftp_manager.py deleted file mode 100644 index ec53b0b..0000000 --- a/src/game/ftp_manager.py +++ /dev/null @@ -1,441 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Povides useful class for connecting, sending and receiving -files on a FTPs server. - -Created on 27/10/2018 -""" - -import os -import ftplib - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -class FTPManager: - """ - Simplify sending and downloading files on a FTPs server. - """ - - def __init__(self, host, user="", password=""): - """ - Initialize a FTPManager object. To connect it to the server, - run FTPManager.connect(). - - :type host: str - :param host: The host address (IP or DNS). - - :type user: str - :param user: Optional. The username to use for login. - - :type password: str - :param password: Optional. The password to use for login. - """ - - self.stream = None - self.connected = False - self.host = host - self.user = user - self.password = password - self.buffer = "" - - def __print_error__( - self, error, method_name="__print_error__", msg="An error occured !" - ): - """ - Internal method used to display a specific message according to - a defined error. - - :type error: Exception - :param error: The error to manage. - - :type method_name: str - :param method_name: Optional. The FTPManager method that had - an error. - - :type msg: str - :param msg: Optional. A message to display. - """ - - to_display = "%s%s" - if isinstance(error, ftplib.error_temp): - to_display = "[WARNING] [FTPManager.%s] %s Temporary unvailable" - elif isinstance(error, ftplib.error_perm): - to_display = ( - "[WARNING] [FTPManager.%s]" - + " %s Permanent error, check server file permission" - ) - elif isinstance(error, ftplib.error_proto): - to_display = ( - "[WARNING] [FTPManager.%s]" - + " %s The server reply does not fit the FTP specifications" - ) - elif isinstance(error, ftplib.error_reply): - to_display = ( - "[WARNING] [FTPManager.%s]" + " %s Unexpected reply from the server" - ) - elif isinstance(error, IOError): - to_display = ( - "[WARNING] [FTPManager.%s] %s " - + "An error occured while writing in a local file" - ) - else: - to_display = "[WARNING] [FTPManager.%s] %s Unknown cause" - print(to_display % (method_name, msg)) - - def connect(self, user=None, password=None): - """ - Try to connect to the FTPs server. - - :type user: str - :param user: Optional. If not defined, the default user is used. - - :type password: str - :param password: Optional. If not defined, the default password - is used. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - print("[INFO] [FTPManager.connect] Connecting to the server") - user = user if user else self.user - password = password if password else self.password - try: - self.stream = ftplib.FTP_TLS(self.host, user, password) - self.connected = True - print("[INFO] [FTPManager.connect] Connected successfuly !") - return True - except Exception as error: - self.__print_error__( - error, "connect", "Unable to connect or to login to the server !" - ) - self.connected = False - return False - - def disconnect(self): - """ - Try to disconnect to the FTPs server. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - self.stream.quit() - self.connected = False - return True - except Exception as error: - self.__print_error__( - error, "disconnect", "Unable to disconnect from the server !" - ) - else: - print("[WARNING] [FTPManager.disconnect]" + " Not connected to the server") - return False - - def read_server_file(self, server_file_path): - """ - Read a text file (utf-8 encoding) on the server. - - :type server_file_path: str - :param server_file_path: The path to the file on the server. - - :rtype: str - :returns: A string of the file content. - Empty string if something wrong happen. - """ - - self.buffer = "" - - def write(binary): - self.buffer += binary.decode() - - if self.connected: - try: - self.stream.retrbinary("RETR " + server_file_path, write) - except Exception as error: - self.__print_error__( - error, - "read_server_file", - f'Unable to read "{server_file_path}" from the server !', - ) - return self.buffer - print( - "[WARNING] [FTPManager.read_server_file]" + " Not connected to the server" - ) - return "" - - def download_file(self, server_file_path, local_file_path): - """ - Download a file from the server. - - :type server_file_path: str - :param server_file_path: The path to the file on the server. - - :type local_file_path: str - :param local_file_path: The path of the new local file. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - if not os.path.exists(os.path.dirname(local_file_path)): - os.makedirs(os.path.dirname(local_file_path)) - - with open(local_file_path, "wb") as file: - self.stream.retrbinary("RETR " + server_file_path, file.write) - - return True - except Exception as error: - self.__print_error__( - error, - "download_file", - f'Unable to download "{server_file_path}" from' - + f' the server to "{local_file_path}"!', - ) - else: - print( - "[WARNING] [FTPManager.download_file]" + " Not connected to the server" - ) - return False - - def send_file(self, local_file_path, server_file_path): - """ - Send a file to the server. - - :type local_file_path: str - :param local_file_path: The path of the local file to send. - - :type server_file_path: str - :param server_file_path: The path to the new file on the server. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - - with open(local_file_path, "rb") as file: - self.stream.storbinary("STOR " + server_file_path, file) - - return True - except Exception as error: - self.__print_error__( - error, - "send_file", - f'Unable to send "{local_file_path}"' - + f' to the server from "{server_file_path}" !', - ) - else: - print("[WARNING] [FTPManager.send_file]" + " Not connected to the server") - return False - - def get_server_file_names(self, server_folder_path=None): - """ - Get the names of all files and directories in a specific - folder on the server. - - :type server_folder_path: str - :param server_folder_path: Optional. The path to the folder - on the server. - - :rtype: list - :returns: A list of file names. - """ - - if self.connected: - if not server_folder_path: - server_folder_path = self.stream.pwd() - try: - return self.stream.nlst(server_folder_path) - except Exception as error: - self.__print_error__( - error, - "get_server_file_names", - f'Unable to get file names in "{server_folder_path}" !', - ) - else: - print( - "[WARNING] [FTPManager.get_server_file_names]" - + " Not connected to the server" - ) - return [] - - def get_current_directory(self): - """ - Get the current working directory path on the server. - - :rtype: str - :returns: The path of the current working directory. - Return an empty string if something wrong happen. - """ - - if self.connected: - return self.stream.pwd() - print( - "[WARNING] FTPManager.get_current_directory]" - + " Not connected to the server" - ) - return "" - - def set_current_directory(self, server_path): - """ - Set the working directory path. - - :type server_path: str - :param server_path: The path to the new working directory. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - self.stream.cwd(server_path) - return True - except Exception as error: - self.__print_error__( - error, - "set_current_directory", - f'Unable to define "{server_path}"' + " as the current directory !", - ) - else: - print( - "[WARNING] [FTPManager.get_current_directory]" - + " Not connected to the server" - ) - return False - - def rename_server_path(self, from_name, to_name): - """ - Rename a file or a folder on the server. - - :type from_name: str - :param from_name: The path to the file or folder to rename. - - :type to_name: str - :param to_name: The new path to give to the file - or folder to rename. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - self.stream.rename(from_name, to_name) - return True - except Exception as error: - self.__print_error__( - error, - "rename_server_path", - f'Unable to rename "{from_name}"' + f' to "{to_name}" !', - ) - else: - print( - "[WARNING] [FTPManager.rename_server_path]" - + " Not connected to the server" - ) - return False - - def remove_server_file(self, server_file_path): - """ - Remove a file (doesn't work for folders) on the server. - - :type server_file_path: str - :param server_file_path: The path to the file to remove. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - self.stream.delete(server_file_path) - return True - except Exception as error: - self.__print_error__( - error, - "remove_server_file", - f'Unable to remove "{server_file_path}" from the server !', - ) - else: - print( - "[WARNING] [FTPManager.remove_server_file] Not connected to the server" - ) - return False - - def remove_server_directory(self, server_folder_path): - """ - Remove a folder (doesn't work for a file) on the server. - - :type server_folder_path: str - :param server_folder_path: The path to the folder to remove. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if self.connected: - try: - self.stream.rmd(server_folder_path) - return True - except Exception as error: - self.__print_error__( - error, - "remove_server_directory", - f'Unable to remove "{server_folder_path}" from the server !', - ) - else: - print( - "[WARNING] [FTPManager.remove_server_directory]" - + " Not connected to the server" - ) - return False - - def get_file_size(self, server_file_path): - """ - Get the file of a file on the server. - - :type server_file_path: str - :param server_file_path: The path to the file to get the size. - - :rtype: int - :returns: The size of the file. - """ - - if self.connected: - try: - return self.stream.size(server_file_path) - except Exception as error: - self.__print_error__( - error, - "get_file_size", - f'Unable to get the size of "{server_file_path}" !', - ) - else: - print( - "[WARNING] [FTPManager.get_file_size]" + " Not connected to the server" - ) - return 0 diff --git a/src/game/level.py b/src/game/level.py deleted file mode 100644 index ca2f2a0..0000000 --- a/src/game/level.py +++ /dev/null @@ -1,426 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to manage a game level (entities, flow of time,...) - -Created on 18/03/2018 -""" - -import random - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from entities.angel import Angel -from entities.bean import Bean -from entities.leaf import Leaf -from entities.leaf_piece import LeafPiece -from entities.pink_bean import PinkBean -from entities.pyobot import Pyobot -from entities.pyobot_2 import Pyobot2 -from entities.pyoro import Pyoro -from entities.pyoro_2 import Pyoro2 -from entities.score_text import ScoreText -from entities.smoke import Smoke -from entities.super_bean import SuperBean - -from game.action_delay import ActionDelay -from game.case import Case -from game.config import BEAN_FREQUENCY, SPEED_ACCELERATION, \ - BACKGROUND_ANIMATED_DURATION -from game.util import Game - - -class Level: - """ - Central class that manages the entities, terrain and more. - """ - - def __init__(self, level_drawer, game_id, size, bot_mode=False): - """ - Initialize a new Level object. - - :type level_drawer: gui.level_drawer.Level_drawer - :param activity: The graphical representation of this level. - - :type game_id: int - :param game_id: It can be 0 for Pyoro, or 1 for Pyoro 2. - - :type size: tuple - :param size: The size of the level (in blocks) in a (width, height) - tuple where width and height are floating point values. - - :type bot_mode: bool - :param bot_mode: Optional. If True, Pyoro will be a bot. - Default is False. - """ - - self.level_drawer = level_drawer - self.game_id = game_id - self.size = size - self.bot_mode = bot_mode - - self.loop_active = True - self.pyoro = None - - self.score = 0 - self.speed = 1 - self.animated_background_id = 13 - - self.cases = [] - self.entities = [] - self.action_delays = {} - - self.init_cases(self.size[0]) - self.init_pyoro() - self.spawn_bean() - - def init_cases(self, nb_cases): - """ - Create the terrain with new blocks. - - :type nb_cases: int - :param nb_cases: The number of blocks which will compose the floor. - """ - - self.cases.clear() - for i in range(nb_cases): - self.cases.append(Case(i)) - - def init_pyoro(self): - """ - Create a new bird according to the current game_id - and bot_mode. - """ - - if self.bot_mode and self.game_id: - self.pyoro = Pyobot2(self) - elif self.bot_mode: - self.pyoro = Pyobot(self) - elif self.game_id: - self.pyoro = Pyoro2(self) - else: - self.pyoro = Pyoro(self) - - def reset(self): - """ - Restart the level: - - score = 0 - - speed = 1 - - entities are killed - - action delayed are stopped - - terrain is recreated - """ - - self.score = 0 - self.speed = 1 - for entity in self.entities: - entity.remove() - self.entities.clear() - self.action_delays.clear() - self.init_cases(self.size[0]) - self.spawn_bean() - - def update(self, delta_time): - """ - Update the level, entities and action_delays. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - if self.loop_active: - self.speed += delta_time * SPEED_ACCELERATION - self.pyoro.update(delta_time * self.speed) - for entity in self.entities: - entity.update(delta_time * self.speed) - for action_delay in dict(self.action_delays).values(): - action_delay.update(delta_time * self.speed) - - def update_animated_background(self): - """ - If the current background is animated, update it. - """ - - if self.animated_background_id < 20: - self.animated_background_id = self.animated_background_id + 1 - else: - self.animated_background_id = 13 - - def spawn_bean(self): - """ - Randomly spawn a new bean. Bean type is also random. - """ - - bean_type_id = random.randint(0, 5) - pos = (random.randint(0, self.size[0] - 1) + 0.75, 0) - speed = random.uniform(0.5, 1.5) * (self.speed ** 0.6) - - if bean_type_id < 4: - bean = Bean(self, pos, speed) - elif self.score < 5000 or bean_type_id == 4: - bean = PinkBean(self, pos, speed) - else: - bean = SuperBean(self, pos, speed) - - self.entities.append(bean) - self.set_action_delay((self, "spawn_bean"), - BEAN_FREQUENCY - * random.uniform(0.5, 1.5) - / (self.speed ** 1.5), - self.spawn_bean - ) - - def spawn_angel(self, case): - """ - Spawn a new angel only if case can be repaired. - - :type case: game.case.Case - :param case: The block that will be repaired by the new angel. - """ - - if not case.exists and not case.is_repairing: - self.entities.append(Angel(self, case)) - - def spawn_score(self, score, pos): - """ - Spawn a flashing text and increase the score. - - :type score: int - :param score: The value to add to the current score. - It can be 10, 50, 100, 300 or 1000. - - :type pos: Iterable - :param pos: The position of the flashing text. - """ - - allowed = (10, 50, 100, 300, 1000) - if score in allowed: - self.score += score - self.entities.append(ScoreText(self, pos, score)) - else: - print(f"[WARNING] [Level.addScore] {score} is an invalid " - + f"value ! Allowed are {allowed}") - - def spawn_smoke(self, pos): - """ - Spawn smoke. - - :type pos: Iterable - :param pos: The position of the smoke. - """ - self.entities.append(Smoke(self, pos)) - - def spawn_leaf(self, pos, leaf_type): - """ - Spawn leafs with random speed. - - :type pos: Iterable - :param pos: The position of the leaf. - - :type leaf_type: str - :param leaf_type: The type of the leaf. It can be - "", "pink" or "super". - """ - - speed = random.uniform(0.5, 1.5) - self.entities.append(Leaf(self, pos, speed, leaf_type)) - - def spawn_leaf_piece(self, pos, speed, leaf_piece_type, vel): - """ - Spawn cut leaf. - - :type pos: Iterable - :param pos: The default position of the leaf. - - :type speed: float - :param speed: The speed of the leaf. - - :type leaf_piece_type: str - :param leaf_piece_type: The type of the leaf. It can be - "", "pink" or "super". - - :type vel: float - :param vel: The default horizontal velocity. - """ - self.entities.append(LeafPiece( - self, pos, speed, leaf_piece_type, vel)) - - def repair_case(self, case=None): - """ - Repair a block by spawning an angel. - - :type case: game.case.Case - :param case: Optional. The block to repair. The leftmost destroyed - block is chosen if undefined. - """ - - void_cases = self.get_void_cases() - if void_cases: - case = case if case in void_cases else random.choice(void_cases) - self.spawn_angel(case) - - def create_action_delay(self, action_name, wait_time, fct, *fctArgs, **fctKwargs): - """ - Create a new action_delay. See game.action_delay.Action_delay. - If an action_delay already exists with the same name, do nothing. - - :type action_name: object - :param action_name: The name given to the new action_delay. - - :type wait_time: float - :param wait_time: The time to wait before calling fct. - - :type fct: function or method - :param fct: The function or method to delay. - - :type *fctArgs: object - :param *fctArgs: The arguments to pass to fct. - - :type **fctKwargs: object - :param **fctKwargs: The optional arguments to pass to the fct. - """ - - if action_name not in self.action_delays: - self.action_delays[action_name] = ActionDelay( - wait_time, fct, *fctArgs, **fctKwargs) - - def set_action_delay(self, action_name, wait_time, fct, *fctArgs, **fctKwargs): - """ - Create a new action_delay or replace an existing one. - See game.action_delay.Action_delay. - - :type action_name: object - :param action_name: The name given to the new action_delay. - - :type wait_time: float - :param wait_time: The time to wait before calling fct. - - :type fct: function or method - :param fct: The function or method to delay. - - :type *fctArgs: object - :param *fctArgs: The arguments to pass to fct. - - :type **fctKwargs: object - :param **fctKwargs: The optional arguments to pass to the fct. - """ - - self.action_delays[action_name] = ActionDelay( - wait_time, fct, *fctArgs, **fctKwargs) - - def remove_action_delay(self, *action_names): - """ - Remove action_delay(s). - - :type *action_names: str - :param *action_names: The name of the action_delays to remove. - """ - - for action_name in action_names: - self.action_delays.pop(action_name, None) - - def remove_entity(self, entity): - """ - Remove an Entity. - - :type entity: entities.entity.Entity - :param entity: The entity to remove. - """ - - if entity in self.entities: - self.entities.remove(entity) - else: - print( - f"[WARNING] [Level.remove_entity] Unable to remove {entity} from Entity list") - - def get_style_type_with_score(self, score=None): - """ - Get the style id from the score. - 0 is normal, 1 is black and white and 2 is flashy. - - :type score: int - :param score: Optional. A score. Use the current level score - if undefined. - - :rtype: int - :returns: The style id associated to the given score. - """ - - score = score if score else self.score - if score < 20000: - return 0 - elif score < 30000: - return 1 - else: - return 2 - - def get_background_id_with_score(self, score=None): - """ - Get the background id associated to a specified score. - - :type score: int - :param score: Optional. A score. Use the current level score - if undefined. - - :rtype: int - :returns: The background id associated to the given score. - """ - - score = score if score else self.score - if score < 11000: - return score // 1000 - elif score < 20000: - return 10 - elif score < 30000: - return 11 - elif score < 40000: - return 12 - else: - self.create_action_delay((self, "updateAnimatedBackround"), - BACKGROUND_ANIMATED_DURATION, self.update_animated_background) - return self.animated_background_id - - def get_audio_player(self): - """ - Get the current audio player. - - :rtype: audio.audio_player.Audio_player - :returns: The audio player currently used by the game. - """ - return Game.audio_player - - def get_void_cases(self): - """ - Get the destroyed blocks that are not being repaired. - - :rtype: list - :returns: A list of all destroyed blocks. - """ - return [case for case in self.cases if not case.exists and not case.is_repairing] - - def set_size(self, size): - """ - Define the level size (in case). - - :type size: tuple - :param size: The size in blocks of the level. - """ - - self.size = tuple(size) - self.init_cases(int(size[0])) diff --git a/src/game/mod.py b/src/game/mod.py deleted file mode 100644 index dd34652..0000000 --- a/src/game/mod.py +++ /dev/null @@ -1,168 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to load, update and manage mods - -Created on 18/11/2018 -""" - -import os -import sys - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.util import get_external_data_path - - -class Mod: - """ - Load, update and manage a mod. - """ - - modList = [] - - def __init__(self, name): - """ - Initialize a Mod object. - - :type name: str - :param name: The name of the mod. - """ - - self.name = name - self.module = None - self.loaded = False - Mod.add_folder_to_path() - - def load(self): - """ - Load a mod by importing it. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - try: - exec("import " + self.name) - exec("self.module = " + self.name) - self.loaded = True - return True - except ImportError: - print(f'[WARNING] [Mod.load] Unable to import "{self.name}"') - return False - - def init(self, window): - """ - Initialize a mod by passing to it the current gui.window.Window. - - :type window: gui.window.Window - :param window: The current game window. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if "init" in dir(self.module): - if callable(self.module.init): - try: - self.module.init(window) - return True - except Exception: - print( - "[WARNING] [Mod.init] Something wrong happened " - + f'while initializing "{self.name}"' - ) - return False - - def update(self, window, delta_time): - """ - Update a mod by passing to it the current gui.window.Window - and the elapsed time since the last update. - - :type window: gui.window.Window - :param window: The current game window. - - :type delta_time: float - :param delta_time: Elapsed time since the last update. - - :rtype: bool - :returns: True if it's a success, otherwise False. - """ - - if "update" in dir(self.module): - if callable(self.module.update): - try: - self.module.update(window, delta_time) - return True - except Exception: - print( - "[WARNING] [Mod.update] Something wrong happened" - + f' while updating "{self.name}"' - ) - return False - - @classmethod - def load_mods(cls): - """ - Load all mods in the mod folder. - """ - - mod_folder = os.path.join(get_external_data_path(), "mods") - - if not os.path.exists(mod_folder): - os.makedirs(mod_folder) - - file_names = os.listdir(mod_folder) - - for file_name in file_names: - mod_name, ext = os.path.splitext(file_name) - if mod_name != "__init__" and ext in (".py", ".pyc", ".pyd", ".pyw"): - mod = Mod(mod_name) - cls.modList.append(mod) - mod.load() - - @classmethod - def init_mods(cls, window): - """ - Initialize all loaded mods. - """ - - for mod in cls.modList: - if mod.loaded: - mod.init(window) - - @classmethod - def update_mods(cls, window, delta_time): - """ - Update all loaded mods. - """ - - for mod in cls.modList: - if mod.loaded: - mod.update(window, delta_time) - - @staticmethod - def add_folder_to_path(): - """ - Add the mod folder to path. - """ - - mod_folder = os.path.join(get_external_data_path(), "mods") - if mod_folder not in sys.path: - sys.path.append(mod_folder) diff --git a/src/game/update.py b/src/game/update.py deleted file mode 100644 index 952f848..0000000 --- a/src/game/update.py +++ /dev/null @@ -1,220 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide update functions - -Created on 17/11/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import VERSION, UPDATE_HOST, UPDATE_USER, UPDATE_PASSWORD -from game.ftp_manager import FTPManager -from game.util import get_external_data_path, copy_directory - - -def get_connection_stream(): - """ - Create a new FTPManager and try to connect it to the server. - - :rtype: game.ftp_manager.FTPManager - :returns: A new FTP_manager if successfully connected, - otherwise None. - """ - - ftp = FTPManager(UPDATE_HOST, UPDATE_USER, UPDATE_PASSWORD) - if ftp.connect(): - return ftp - print( - "[WARNING] [update.get_connection_stream] Unable to" + " connect to the server" - ) - return None - - -def get_updates(ftp_mgr): - """ - Search new versions on a server. - - :type ftp_mgr: game.ftp_manager.FTPManager - :param ftp_mgr: The FTPManager used to download files. - - :rtype: list - :returns: A list of new versions. Return an empty list - if something wrong happen. - - :Example: getUpdate(myftp_mgr) -> ["1.2", "1.2.1", "1.3"] - """ - - print("[INFO] [update.checkForUpdate] Checking for new updates") - versions = ftp_mgr.read_server_file("htdocs/game_update/versions.txt").split("\n") - version_found = False - new_versions = [] - - for version in versions: - if version_found: - new_versions.append(version) - if version == VERSION: - version_found = True - return new_versions - - -def download_update(ftp_mgr, version): - """ - Download files associated to a given version from the server. - - :type ftp_mgr: game.ftp_manager.FTPManager - :param ftp_mgr: The FTPManager used to download files. - - :type version: str - :param version: Version name (like "1.2.3") - - :rtype: bool - :returns: False if an error occurs, True otherwise. - """ - - print("[INFO] [update.download_update] Downloading update v" + version) - downloadfp = get_files_to_download(ftp_mgr, version) - removefp = get_files_to_remove(ftp_mgr, version) - server_folder = "htdocs/game_update/" + version + "/" - local_folder = os.path.join(get_external_data_path(), "game_update") - to_return = True - - for file_path in downloadfp: - server_file_path = server_folder + file_path - local_file_path = os.path.join(local_folder, file_path.replace("/", "\\")) - - if not ftp_mgr.download_file(server_file_path, local_file_path): - to_return = False - - for file_path in removefp: - local_file_path = os.path.join(local_folder, file_path.replace("/", "\\")) - try: - os.remove(local_file_path) - except OSError: - to_return = False - return to_return - - -def get_files_to_download(ftp_mgr, version, folder="htdocs/game_update/"): - """ - Get the name of the files to download for a defined version. - - :type ftp_mgr: game.ftp_manager.FTPManager - :param ftp_mgr: The FTPManager to use. - - :type version: str - :param version: The version to download. - - :type folder: str - :param folder: Optional. The remote folder where to search the list - of files to download. - - :rtype: list - :returns: A list of file paths. - """ - - to_remove_content = ftp_mgr.read_server_file(folder + version + "/toDownload.txt") - if to_remove_content: - file_paths = to_remove_content.split("\n") - return file_paths - return [] - - -def get_files_to_remove(ftp_mgr, version, folder="htdocs/game_update/"): - """ - Get the name of the files to remove for a defined version. - - :type ftp_mgr: game.ftp_manager.FTPManager - :param ftp_mgr: The FTPManager to use. - - :type version: str - :param version: In what version. - - :type folder: str - :param folder: Optional. The remote folder where to search the list - of files to remove. - - :rtype: list - :returns: A list of file paths. - """ - - to_download_content = ftp_mgr.read_server_file(folder + version + "/toRemove.txt") - if to_download_content: - file_paths = to_download_content.split("\n") - return file_paths - return [] - - -def get_libs_directory(): - """ - Get the lib folder path. - - :rtype: str - :returns: The absolute path of the lib folder. - """ - - if "lib" in os.listdir(): - return os.path.abspath("lib") - return os.path.abspath("") - - -def install_update(): - """ - Copy updated files to the installation directory. - - :rtype: bool - :returns: True if installation is a success, otherwise False. - """ - - print( - "[INFO] [update.install_update] Copying update files " - + "into game installation folder" - ) - update_directory = os.path.join(get_external_data_path(), "game_update") - lib_directory = get_libs_directory() - to_return = True - - if os.path.exists(update_directory): - file_names = os.listdir(update_directory) - - for file_name in file_names: - file_path = os.path.join(update_directory, file_name) - - if os.path.isdir(file_path) and file_name != "data": - if not copy_directory( - file_path, os.path.join(lib_directory, file_name) - ): - print( - "[WARNING] [update.install_update] Something wrong" - + "happened while copying files to install directory" - ) - to_return = False - else: - if not copy_directory(file_path, file_name): - print( - "[WARNING] [update.install_update] Something wrong" - + "happened while copying files to install directory" - ) - to_return = False - else: - print("[WARNING] [update.install_update] No update found !") - to_return = False - return to_return diff --git a/src/game/util.py b/src/game/util.py deleted file mode 100644 index cacd5e5..0000000 --- a/src/game/util.py +++ /dev/null @@ -1,628 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide useful functions - -Created on 17/11/2018 -""" - -import ctypes -import enum -import json -import os -import platform -import shutil -import subprocess -import sys -import threading - -import pygame -import screeninfo - -from pygame.locals import ( - K_1, - K_2, - K_3, - K_4, - K_5, - K_6, - K_7, - K_8, - K_9, - K_0, - K_q, - K_w, - K_z, - K_m, - K_a, - K_MINUS, - K_LEFTBRACKET, - K_RIGHTBRACKET, - K_SEMICOLON, - K_QUOTE, - K_COMMA, - K_PERIOD, - K_SLASH, - JOYBUTTONDOWN, - JOYHATMOTION, - JOYAXISMOTION, -) - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import DEFAULT_OPTIONS, NAME, VERSION - - -############################################################################## -### Input representation ##################################################### -############################################################################## - - -def get_key_name(key_code): - """ - Get azerty equivalent of a key from a qwerty keyboard - - :type key_code: int - :param key_code: The pygame code of a key. - - :rtype: str - :returns: A key representation. - """ - - new_keys = { - K_1: "&", - K_2: "é", - K_3: '"', - K_4: "'", - K_5: "(", - K_6: "-", - K_7: "è", - K_8: "_", - K_9: "ç", - K_0: "à", - K_MINUS: ")", - K_q: "q", - K_w: "w", - K_LEFTBRACKET: "^", - K_RIGHTBRACKET: "$", - K_a: "a", - K_SEMICOLON: "m", - K_QUOTE: "ù", - K_z: "z", - K_m: ",", - K_COMMA: ";", - K_PERIOD: ":", - K_SLASH: "!", - } - - if key_code in new_keys: - return new_keys[key_code] - return pygame.key.name(key_code) - - -def get_joy_key_name(input_type, **input_kwargs): - """ - Get a representation of a joystick input. - - :type input_type: int - :param input_type: The pygame code of a joystick input type. - It can be JOYBUTTONDOWN, JOYHATMOTION or JOYAXISMOTION. - - :type **input_kwargs: object - :param **input_kwargs: Some data about the input. - - :rtype: str - :returns: A representation of the joystick input. - """ - - if input_type == JOYBUTTONDOWN: - if "button_id" not in input_kwargs: - input_kwargs["button_id"] = "inconnu" - return f"Bouton {input_kwargs['button_id']}" - elif input_type == JOYHATMOTION: - if "value" not in input_kwargs: - input_kwargs["value"] = (0, 0) - input_kwargs["value"] = tuple(input_kwargs["value"]) - if input_kwargs["value"] == (-1, 0): - return "gauche" - elif input_kwargs["value"] == (1, 0): - return "droite" - elif input_kwargs["value"] == (0, -1): - return "bas" - elif input_kwargs["value"] == (0, 1): - return "haut" - else: - return "direction ?" - elif input_type == JOYAXISMOTION: - if "axis_id" not in input_kwargs: - input_kwargs["axis_id"] = 0 - if "value" not in input_kwargs: - input_kwargs["value"] = 0 - if input_kwargs["axis_id"] == 0: - if input_kwargs["value"] < 0: - return "gauche" - elif input_kwargs["value"] > 0: - return "droite" - else: - return "direction ?" - elif input_kwargs["axis_id"] == 1: - if input_kwargs["value"] < 0: - return "haut" - elif input_kwargs["value"] > 0: - return "bas" - else: - return "direction ?" - - -############################################################################## -### Options ################################################################## -############################################################################## - - -def save_options(options): - """ - Save options in a json file. - - :type options: dict - :param options: A dictionary with data to save. - """ - - print("[INFO] [util.save_options] Saving game options") - option_file_path = os.path.join(get_external_data_path(), "options.json") - with open(option_file_path, "w", encoding="utf-8") as file: - json.dump(options, file, indent="\t") - - -def load_config(): - """ - Load options from a json file. If no option found, return - game.config.DEFAULT_OPTIONS. - - :rtype: dict - :returns: A dictionary of saved data. - """ - - print("[INFO] [util.loadOptions] Loading game options") - option_file_path = os.path.join(get_external_data_path(), "options.json") - if os.path.exists(option_file_path): - with open(option_file_path, "r", encoding="utf-8") as file: - return json.load(file) - return DEFAULT_OPTIONS - - -############################################################################## -### Leave, reset and restart ################################################# -############################################################################## - - -def stop_game(): - """ - Stop the audio player, the debug logger and close the current window. - """ - - print(f"[INFO] [util.stop_game] Stopping {NAME.capitalize()}") - pygame.quit() - if Game.audio_player: - Game.audio_player.stop() - if Game.options: - save_options(Game.options) - if Game.debug_logger: - Game.debug_logger.close() - - -def leave_game(error_id=0): - """ - Stop the game and send an error message if something - wrong happened. - - :type error_id: int - :param error_id: Optional. An error id. 0 is used if - not defined. - """ - - print(f"[INFO] [util.leave_game] Leaving {NAME.capitalize()} v{VERSION}") - stop_game() - log_message = " Consultez les logs pour plus de détails " - message = "Une erreur est survenue ! " - - if error_id == 0: - sys.exit() - if error_id == Errors.MODULE_NOT_FOUND: - message += "Un module Python essentiel est absent !" - elif error_id == Errors.DATA_NOT_FOUND: - message += "Impossible de trouver les ressources du jeu !" - elif error_id == Errors.BOOT_ERROR: - message += "Le jeu n'a pas réussi à démarrer !" - elif error_id == Errors.LOOP_ERROR: - message += "Plantage pendant la boucle de jeu !" - elif error_id == Errors.UPDATE_ERROR: - message += "Problème pendant l'installation des mises à jours !" - elif error_id == Errors.BAD_RESOURCE: - message += "Une ressource du jeu (image, son, json) est endommagée !" - elif error_id == Errors.CODE_ERROR: - message += "Mauvaise utilisation du code par l'un des mods !" - - raise RuntimeError(message + log_message + f"(error={error_id})") - - -def restart(*args): - """ - Restart the game with defined arguments. - - :type *args: str - :param *args: The arguments to pass on reboot. - """ - - print("[INFO] [util.restart] Restarting game") - if sys.executable == sys.argv[0]: - subprocess.Popen([sys.executable] + list(args)) - else: - subprocess.Popen([sys.executable, sys.argv[0]] + list(args)) - leave_game() - - -def admin_restart(*args): - """ - Restart by requesting administrator or root privileges. - - :type *args: str - :param *args: The arguments to pass on reboot. - """ - - print("[INFO] [util.admin_restart] Restarting game with admin elevation") - system_name = platform.system() - args = list(args) - - if sys.executable != sys.argv[0]: - args.insert(0, sys.argv[0]) - - def uac_prompt(): - ctypes.windll.shell32.ShellExecuteW( - None, "runas", sys.executable, " ".join(args), None, 1 - ) - - def root_prompt(): - to_return = 0 - # If the user isn't a super user - if os.geteuid() != 0: - msg = "[sudo] password for %u:" - to_return = subprocess.check_call(f"sudo -v -p '{msg}'", shell=True) - return to_return - - if system_name == "Windows": - threading.Thread(target=uac_prompt).start() - leave_game() - else: - if root_prompt() == 0: - restart() - else: - print("[WARNING] [util.admin_restart] Unable to get root privileges") - leave_game() - - -def reset_game(): - """ - Reset the game and restart. - """ - - print("[INFO] [util.reset_game] Reseting game! Restarting...") - option_file_path = os.path.join(get_external_data_path(), "options.json") - if os.path.exists(option_file_path): - os.remove(option_file_path) - restart() - - -############################################################################## -### Data and modules managment ############################################### -############################################################################## - - -def check_data(): - """ - Check if there is resources.json file. - - :rtype: bool - :returns: True if found, otherwise False. - """ - - print("[INFO] [util.check_data] Checking data") - return os.path.exists(os.path.join("data", "resources.json")) - - -def check_modules(): - """ - Check needed python modules. - - :rtype: bool - :returns: True if all needed modules are installed, otherwise False. - """ - - print("[INFO] [util.chechModules] Checking required modules") - required = ( - "os", - "sys", - "pygame", - "json", - "wave", - "audioop", - "pyaudio", - "threading", - "traceback", - "time", - "platform", - "shutil", - "ftplib", - "enum", - "collections", - ) - - for module_name in required: - try: - print(f'[INFO] [util.chechModules] Checking "{module_name}"') - exec("import " + module_name) - except ImportError: - print( - "[WARNING] [util.chechModules] No module " - + f'"{module_name}" detected !' - ) - return False - return True - - -def get_resource_paths(resource_type): - """ - Get the path of all resources in a defined category. - - :type resource_type: str - :param resource_type: The category of resource. It can be - "musics", "sounds" and "images" - - :rtype: list - :returns: A list of paths to files of the specified category. - If somethinf wrong happen, return an empty list. - """ - - print(f'[INFO] [util.get_resource_paths] Detecting "{resource_type}" resources') - res_file_path = os.path.join("data", "resources.json") - if os.path.exists(res_file_path): - with open(res_file_path, "r", encoding="utf-8") as file: - resources = json.load(file) - if resource_type in resources: - return resources[resource_type] - print( - f'[WARNING] [util.get_resource_paths] "{resource_type}"' - + " is not a valid resource type" - ) - else: - print( - "[WARNING] [util.get_resource_paths] " + f'Unable to find "{res_file_path}"' - ) - leave_game(Errors.BAD_RESOURCE) - - -def get_external_data_path(): - r""" - Get the path to the game data folder according to the host - operating system. - - %AppData%\Pyoro on Windows - - /home//share/Pyoro on Linux distributions - - /home//Library/Pyoro on MacOS. - """ - - system_name = platform.system() - if system_name == "Windows": - return os.path.join(os.environ["APPDATA"], NAME.capitalize()) - elif system_name == "Linux": - return os.path.join(os.path.expanduser("~"), "share", NAME.capitalize()) - elif system_name == "Darwin": - return os.path.join(os.path.expanduser("~"), "Library", NAME.capitalize()) - print("[WARNING] [util.get_external_data_path] Unknown operating system") - return "saves" - - -def copy_directory(from_path, to_path): - """ - Recursion copy file or folder. - - :type from_path: str - :param from_path: The folder path to copy from. - - :type to_path: str - :param to_path: The destination file or folder. - - :rtype: bool - :returns: True if files and folders has been copied successfuly, - otherwise False. - """ - - print(f"[INFO] [util.copy_directory] Copying folder {from_path} to {to_path}") - to_return = True - - if os.path.isdir(from_path): - file_names = os.listdir(from_path) - for file_name in file_names: - source_file_path = os.path.join(from_path, file_name) - new_file_path = os.path.join(to_path, file_name) - if not copy_directory(source_file_path, new_file_path): - to_return = False - else: - if os.path.exists(from_path): - if not os.path.exists(os.path.dirname(to_path)): - os.makedirs(os.path.dirname(to_path)) - - try: - shutil.copyfile(from_path, to_path) - except Exception: - print( - "[WARNING] [util.copy_directory] Error while copying" - + f" {from_path} to {to_path} ! Ignoring it" - ) - to_return = False - else: - print( - "[WARNING] [util.copy_directory] File " - + f'"{from_path}" doesn\'t exist' - ) - to_return = False - - return to_return - - -############################################################################## -### Screen Infos ############################################################# -############################################################################## - - -def get_layout_template(ratio): - """ - Get the best layout for a given ratio. - - :type ratio: float - :param ratio: The ratio of the game window. - - :rtype: dict - :returns: A dictionary representing placement informations about - the graphical components of the game menu. - """ - - # Detecting best layout name accourding to the resolution - if ratio > 1: - best_layout_name = "Wide" - elif ratio < 1: - best_layout_name = "Narrow" - else: - best_layout_name = "Square" - - layout_file_path = os.path.join("data", "layouts.json") - if os.path.exists(layout_file_path): - with open(layout_file_path, "r", encoding="utf-8") as file: - layouts = json.load(file) - - # Searching the best layout - for layout in layouts: - if "name" in layout: - if layout["name"] == best_layout_name: - print( - "[INFO] [util.get_layout_template] Layout" - + f' "{best_layout_name}" choosen' - ) - return layout - else: - print( - "[WARNING] [util.get_layout_template] Some layouts" - + " aren't named" - ) - - print( - "[WARNING] [util.get_layout_template] Unable to find a layout" - + " which fit the given ratio" - ) - return {} - print( - "[WARNING] [util.get_layout_template] Unable" + f' to find "{layout_file_path}"' - ) - leave_game(Errors.BAD_RESOURCE) - - -def get_monitor_size(): - """ - Return the screen size in mm. - - :rtype: tuple - :returns: (width, height) tuple where width and height are ints which - represent the default screen size in millimeters. - """ - - monitors = screeninfo.get_monitors() - monitor = monitors[0] - - return monitor.width_mm, monitor.height_mm - - -def get_screen_size(): - """ - Return the screen size in pixels. - - :rtype: tuple - :returns: (width, height) tuple where width and height are ints which - represent the default screen size in pixels. - """ - - monitors = screeninfo.get_monitors() - monitor = monitors[0] - - return monitor.width, monitor.height - - -def get_screen_ratio(): - """ - Return the screen resolution (width / height). - - :rtype: float - :returns: A floating point value representing the ratio width / height. - """ - - width, height = get_screen_size() - if height: - return width / height - print("[WARNING] [util.get_screen_ratio] Height can't be null") - return 1 - - -def get_monitor_density(): - """ - Return the monitor density in dpm. - - :rtype: tuple - :returns: An (w, h) tuple where w and h are bot float numbers. - """ - - monitor_width, monitor_height = get_monitor_size() - screen_width, screen_height = get_screen_size() - return screen_width / monitor_width, screen_height / monitor_height - - -############################################################################## -### Enumerations ############################################################# -############################################################################## - - -class Game: - """ - Store main objects (unique instances). - """ - - window = None - debug_logger = None - audio_player = None - options = None - - -class Errors(enum.Enum): - """ - Provide common errors constants. - """ - - MODULE_NOT_FOUND = 1 - DATA_NOT_FOUND = 2 - BOOT_ERROR = 3 - LOOP_ERROR = 4 - UPDATE_ERROR = 5 - BAD_RESOURCE = 6 - CODE_ERROR = 7 diff --git a/src/gui/__init__.py b/src/gui/__init__.py deleted file mode 100644 index 633f866..0000000 --- a/src/gui/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- - diff --git a/src/gui/activity.py b/src/gui/activity.py deleted file mode 100644 index 60cd292..0000000 --- a/src/gui/activity.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a base class for activities. - -Created on 15/08/2018 -""" - -import collections -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.util import Game -from gui.layout import Layout - - -class Activity: - """ - Abstract class for all activities. - """ - - def __init__(self, window): - """ - Initialize a new Activity object. - - :type window: gui.window.Window - :param window: The parent window which will manage this activity. - """ - - self.window = window - self.layout = Layout(window) - self.widgets = collections.OrderedDict() - self.sounds = {} - - self.layout.load() - self.init_sounds() - self.init_widgets() - - def __init_sounds__(self, sound_names, folder, audio_type="sound"): - """ - Useful method to easily load sounds or musics which will be used later - by this activity. Do not override this method. - - :type sound_names: tuple - :param sound_names: Base filename of the sounds to load. - - :type folder: str - :param folder: The filepath of the folder where sounds are located. - - :type audio_type: str - :param audio_type: (Optional) How to load the sound (as sound or as music). - Default is "sound". It can be "sound" or "music". - """ - - if audio_type == "sound": - fct = Game.audio_player.get_sound - elif audio_type == "music": - fct = Game.audio_player.get_music - for name in sound_names: - self.sounds[name] = fct(os.path.join(folder, f"{name}.wav")) - - def init_sounds(self): - """ - This method should be override. It's called when the activity is - initialized. It's used to load the sounds used by this activity. - """ - - def init_widgets(self): - """ - This method should be override. It's called when the activity is - initialized. It's used to load the widgets used by this activity. - """ - - def add_widget(self, widget_name, widget_type, *args, **kwargs): - """ - Add a widget with a defined name and arguments. - - :type widget_name: str - :param widget_name: The name of the widget. This name can be use later to - get or remove the widget. - - :type widget_type: class - :param widget_type: The class of the widget to add. This class is used to - create the widget. - """ - - if widget_name in self.widgets: - print( - f"[WARNING] [Layout.add_widget] Widget '{widget_name}' already exists" - ) - else: - widget = widget_type(self, *args, **kwargs) - self.widgets[widget_name] = widget - - def remove_widget(self, widget_name): - """ - Remove a widget from this activity. - - :type widget_name: str - :param widget_name: The name of the widget to destroy and remove. - """ - - if widget_name in self.widgets: - if not self.widgets[widget_name].is_destroyed: - self.widgets[widget_name].destroy() - self.widgets.pop(widget_name) - else: - print( - f"[WARNING] [Layout.remove_widget] '{widget_name}' not in widget list" - ) - - def enable_widgets(self): - """ - Enable all widgets of this activity. - """ - - for widget in tuple(self.widgets.values()): - widget.config(enable=True) - - def disable_widgets(self): - """ - Disable all widgets of this activity. - """ - - for widget in tuple(self.widgets.values()): - widget.config(enable=False) - - def update_event(self, event): - """ - Update all widgets of this activity by giving to them a defined pygame - event. - - :type event: pygame.event.Event - :param event: The event to pass to the widgets. - """ - - for widget in tuple(self.widgets.values()): - if not widget.is_destroyed: - widget.on_event(event) - - def update(self, delta_time): - """ - Update all graphical components of this activity. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - for widget in tuple(self.widgets.values()): - if not widget.is_destroyed: - widget.update(delta_time) - - def destroy(self): - """ - Destroy all widgets of this activity. - """ - - for widget in tuple(self.widgets.values()): - if not widget.is_destroyed: - widget.destroy() - self.widgets.clear() diff --git a/src/gui/button.py b/src/gui/button.py deleted file mode 100644 index 2ae8dff..0000000 --- a/src/gui/button.py +++ /dev/null @@ -1,195 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to create button widgets with update on click and on hover. - -Created on 18/08/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH - -from gui.eventable_widget import EventableWidget -from gui.image_transformer import resize_image -from gui.text import Text - - -class Button(EventableWidget): - """ - A simple button widget. - """ - - DEFAULT_KWARGS = { - "text": "", - "text_kwargs": {"anchor": (0, 0)}, - "text_anchor": (0, 0), - "background_image": os.path.join(GUI_IMAGE_PATH, "button", "button.png"), - "on_hover_background_image": os.path.join( - GUI_IMAGE_PATH, "button", "button_hover.png" - ), - "on_click_background_image": os.path.join( - GUI_IMAGE_PATH, "button", "button_click.png" - ), - "on_middle_click_background_image": os.path.join( - GUI_IMAGE_PATH, "button", "button_middle_click.png" - ), - "on_right_click_background_image": os.path.join( - GUI_IMAGE_PATH, "button", "button_right_click.png" - ), - "disable_background_image": os.path.join( - GUI_IMAGE_PATH, "button", "button_disable.png" - ), - } - - def __init__(self, activity, pos, **kwargs): - """ - Initialize a new Button object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the button in a (x, y) tuple where - x and y are integers. - - text, text_kwargs, text_anchor, background_image, on_hover_background_image, - on_click_background_image, on_middle_click_background_image, - on_right_click_background_image and disable_background_image can be defined. - """ - - Button.update_default_kwargs(kwargs) - Button.update_default_text_kwargs(kwargs) - EventableWidget.__init__(self, activity, pos, **kwargs) - self.background_images = {} - self.text = Text( - self.activity, - self.get_text_pos(), - self.kwargs["text"], - **self.kwargs["text_kwargs"] - ) - self.load_background_images() - - @classmethod - def update_default_text_kwargs(cls, kwargs): - """ - Add missing optional text kwargs with - Button.DEFAULT_KWARGS["text_kwargs"]. - - :type kwargs: dict - :param kwargs: A {kwargsName: value} dictionnary to update with - missing kwargs. - """ - - for key, value in cls.DEFAULT_KWARGS["text_kwargs"].items(): - if key not in kwargs["text_kwargs"]: - kwargs["text_kwargs"][key] = value - - def load_background_images(self): - """ - Load the button background images. - """ - - event_names = ( - "", - "on_hover", - "on_click", - "on_middle_click", - "on_right_click", - "disable", - ) - - for event_name in event_names: - if event_name: - background_name = event_name + "_background_image" - else: - background_name = "background_image" - self.background_images[event_name] = resize_image( - self.activity.window.get_image(self.kwargs[background_name]), - self.kwargs["size"], - ) - - def update(self, delta_time): - """ - Redraw the button with the best background for the current event. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - event_name = "" - if not self.kwargs["enable"]: - event_name = "disable" - elif self.clicked: - event_name = "on_click" - elif self.right_clicked: - event_name = "on_right_click" - elif self.middle_clicked: - event_name = "on_middle_click" - elif self.hovered: - event_name = "on_hover" - - if event_name in self.background_images: - self.activity.window.draw_image( - self.background_images[event_name], self.get_real_pos() - ) - - self.text.update(delta_time) - EventableWidget.update(self, delta_time) - - def config(self, **kwargs): - """ - Change some attributes of this button and update it. - """ - - EventableWidget.config(self, **kwargs) - if "text" in kwargs: - self.text.text = kwargs["text"] - if "text_anchor" in kwargs: - self.text.pos = self.get_text_pos() - if "text_kwargs" in kwargs: - self.text.config(**kwargs["text_kwargs"]) - - # If any background is modified - if ( - "background_image" in kwargs - or "on_hover_background_image" in kwargs - or "on_click_background_image" in kwargs - or "on_middle_click_background_image" in kwargs - or "on_right_click_background_image" in kwargs - or "disable_background_image" in kwargs - ): - self.load_background_images() - - def get_text_pos(self): - """ - Return the text position according to this button pos. - - :rtype: tuple - :returns: The central position of the text in an (x, y) tuple where x - and y are both integers. - """ - - pos_x, pos_y = self.get_real_pos() - width, height = self.kwargs["size"] - anchor_x, anchor_y = self.kwargs["text_anchor"] - return (pos_x + width * (anchor_x + 1) / 2, pos_y + height * (anchor_y + 1) / 2) diff --git a/src/gui/clickable_text.py b/src/gui/clickable_text.py deleted file mode 100644 index e8f2e78..0000000 --- a/src/gui/clickable_text.py +++ /dev/null @@ -1,88 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Clickable_text class used to create discreet buttons or links. - -Created on 10/04/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from gui.eventable_widget import EventableWidget -from gui.text import Text - - -class ClickableText(Text, EventableWidget): - """ - Create a text widget which will react on user events. - """ - - DEFAULT_KWARGS = { - "on_click_text_color": (200, 200, 200, 255), - "on_middle_click_text_color": (100, 100, 100, 255), - "on_right_click_text_color": (220, 220, 220, 255), - "on_hover_text_color": (230, 230, 230, 255), - "disable_text_color": (240, 240, 240, 235), - } - - def __init__(self, activity, pos, text, **kwargs): - """ - Initialize a new Text objects. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - :type text: str - :param text: The text to render. - - on_click_text_color, on_middle_click_text_color, on_right_click_text_color, - on_hover_text_color, disable_text_color, can be defined. - """ - - ClickableText.update_default_kwargs(kwargs) - Text.__init__(self, activity, pos, text, **kwargs) - EventableWidget.__init__(self, activity, pos, **self.kwargs) - - def update(self, delta_time): - """ - Update the clickable text by redrawing it on the window with the - appropriate color. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - if not self.kwargs["enable"]: - self.font.fgcolor = self.kwargs["disable_text_color"] - elif self.clicked: - self.font.fgcolor = self.kwargs["on_click_text_color"] - elif self.right_clicked: - self.font.fgcolor = self.kwargs["on_right_click_text_color"] - elif self.middle_clicked: - self.font.fgcolor = self.kwargs["on_middle_click_text_color"] - elif self.hovered: - self.font.fgcolor = self.kwargs["on_hover_text_color"] - else: - self.font.fgcolor = self.kwargs["text_color"] - Text.update(self, delta_time) diff --git a/src/gui/dialog_menu.py b/src/gui/dialog_menu.py deleted file mode 100644 index 19ccec6..0000000 --- a/src/gui/dialog_menu.py +++ /dev/null @@ -1,168 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a DialogMenu class. - -Created on 30/10/2018. -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from gui.menu_widget import MenuWidget -from gui.clickable_text import ClickableText -from gui.text import Text - - -class DialogMenu(MenuWidget): - """ - Create a menu to alert the player or to ask his opinion. - """ - - DEFAULT_KWARGS = { - "font": os.path.join(GUI_IMAGE_PATH, "font.ttf"), - "positive_args": (), - "positive_kwargs": {}, - "negative_fct": None, - "negative_args": (), - "negative_kwargs": {}, - "description": "", - } - - def __init__(self, activity, pos, message, positive_fct, **kwargs): - """ - Initialize a new DialogMenu objects. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - :type message: str - :param message: A message to display to the player. - - :type positive_fct: callable - :param positive_fct: A callable to call on click on the first button. - - font, positive_args, positive_kwargs, negative_fct, negative_args, - negative_kwargs and description can be defined. - - If negative_fct is defined, a second button is created. - """ - - DialogMenu.update_default_kwargs(kwargs) - - self.message = message - self.positive_fct = positive_fct - - MenuWidget.__init__(self, activity, pos, **kwargs) - - def init_widgets(self): - """ - Create and initialize all subwidgets. - """ - - width, height = self.kwargs["size"] - font = self.kwargs["font"] - pos_x = int(width * 0.5) - pos_y = int(height * 0.25) - self.add_sub_widget( - "titleText", - Text, - (pos_x, pos_y), - self.message, - font=font, - font_size=22, - anchor=(0, 0), - ) - - if self.kwargs["description"]: - pos_x = int(width * 0.1) - pos_y = int(height * 0.4) - self.add_sub_widget( - "descText", - Text, - (pos_x, pos_y), - self.kwargs["description"], - font=font, - font_size=18, - anchor=(-1, 0), - ) - - pos_y = int(height * 0.8) - pos_x = int(width * 0.75) - if self.kwargs["negative_fct"]: - self.add_sub_widget( - "positiveText", - ClickableText, - (pos_x, pos_y), - "oui", - font=font, - font_size=18, - anchor=(0, 0), - on_click_fct=self.positive_action, - ) - - pos_x = int(width * 0.25) - self.add_sub_widget( - "negativeText", - ClickableText, - (pos_x, pos_y), - "non", - font=font, - font_size=18, - anchor=(0, 0), - on_click_fct=self.negative_action, - ) - else: - self.add_sub_widget( - "positiveText", - ClickableText, - (pos_x, pos_y), - "ok", - font=font, - font_size=18, - anchor=(0, 0), - on_click_fct=self.positive_action, - ) - - def negative_action(self): - """ - This method is called when the second button is clicked. It destroys - the menu and call negative_fct. - """ - - self.destroy() - self.kwargs["negative_fct"]( - *self.kwargs["negative_args"], **self.kwargs["negative_kwargs"] - ) - - def positive_action(self): - """ - This method is called when the first button is clicked. It destroys - the menu and call positive_fct. - """ - self.destroy() - self.positive_fct( - *self.kwargs["positive_args"], **self.kwargs["positive_kwargs"] - ) diff --git a/src/gui/eventable_widget.py b/src/gui/eventable_widget.py deleted file mode 100644 index 91c67ec..0000000 --- a/src/gui/eventable_widget.py +++ /dev/null @@ -1,369 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide an EventableWidget base class to manage user events and inputs. - -Created on 17/08/2018. -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from pygame.locals import MOUSEMOTION, MOUSEBUTTONDOWN, MOUSEBUTTONUP -from gui.widget import Widget - - -class EventableWidget(Widget): - """ - This class exists to be subclassed by widgets which have to be able to - handle user events. - """ - - DEFAULT_KWARGS = { - "enable": True, - "on_click_fct": None, - "on_click_args": (), - "on_click_kwargs": {}, - "on_hover_fct": None, - "on_hover_args": (), - "on_hover_kwargs": {}, - "on_middle_click_fct": None, - "on_middle_click_args": (), - "on_middle_click_kwargs": {}, - "on_right_click_fct": None, - "on_right_click_args": (), - "on_right_click_kwargs": {}, - "on_wheel_fct": None, - "on_wheel_args": (), - "on_wheel_kwargs": {}, - "on_click_sound": os.path.join("data", "audio", "sounds", "widget_click.wav"), - } - - def __init__(self, activity, pos, **kwargs): - """ - Initialize a new Button object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - on_click_fct, on_click_args, on_click_kwargs, - on_hover_fct, on_hover_args, on_hover_kwargs, - on_middle_click_fct, on_middle_click_args, on_middle_click_kwargs, - on_right_click_fct, on_right_click_args, on_right_click_kwargs, - on_wheel_fct, on_wheel_args, on_wheel_kwargs, - and on_click_sound can be defined. - """ - - EventableWidget.update_default_kwargs(kwargs) - Widget.__init__(self, activity, pos, **kwargs) - self.hovered = False - self.clicked = False - self.middle_clicked = False - self.right_clicked = False - self.uneventable_zones = [] - self.on_click_sound = None - - def on_event(self, event): - """ - This method is called on all user events detected by Pygame. - - :type event: pygame.event.Event - :param event: The event to handle. - """ - - if self.kwargs["enable"]: - if event.type == MOUSEMOTION: - if not self.is_in_uneventable_zone(event.pos): - if self.is_in_widget(event.pos): - self.on_hover() - else: - self.on_end_hover() - - elif event.type == MOUSEBUTTONDOWN: - if not self.is_in_uneventable_zone(event.pos): - if self.is_in_widget(event.pos): - if event.button == 1: - self.on_click() - elif event.button == 2: - self.on_middle_click() - elif event.button == 3: - self.on_right_click() - elif event.button == 4: - self.on_mouse_wheel(1) - elif event.button == 5: - self.on_mouse_wheel(-1) - else: - if event.button == 1: - self.on_click_out() - elif event.button == 2: - self.on_middle_click_out() - elif event.button == 3: - self.on_right_click_out() - elif event.button == 4: - self.on_mouse_wheel_out(1) - elif event.button == 5: - self.on_mouse_wheel_out(-1) - - elif event.type == MOUSEBUTTONUP: - if not self.is_in_uneventable_zone(event.pos): - if self.is_in_widget(event.pos): - if event.button == 1: - self.on_end_click() - elif event.button == 2: - self.on_end_middle_click() - elif event.button == 3: - self.on_end_right_click() - elif event.button == 4: - self.on_end_mouse_wheel(1) - elif event.button == 5: - self.on_end_mouse_wheel(-1) - else: - if event.button == 1: - self.on_end_click_out() - elif event.button == 2: - self.on_end_middle_click_out() - elif event.button == 3: - self.on_end_right_click_out() - elif event.button == 4: - self.on_end_mouse_wheel_out(1) - elif event.button == 5: - self.on_end_mouse_wheel_out(-1) - - def on_hover(self): - """ - Set hovered state to True and call on_hover_fct. - """ - - self.hovered = True - if self.kwargs["on_hover_fct"]: - self.kwargs["on_hover_fct"]( - *self.kwargs["on_hover_args"], **self.kwargs["on_hover_kwargs"] - ) - - def on_end_hover(self): - """ - Set hovered state to False. - """ - - self.hovered = False - - def on_click(self): - """ - Set clicked state to True. - """ - - self.clicked = True - - def on_middle_click(self): - """ - Set middle_clicked state to True. - """ - - self.middle_clicked = True - - def on_right_click(self): - """ - Set right_clicked state to True. - """ - - self.right_clicked = True - - def on_mouse_wheel(self, direction): - """ - Call on_wheel_fct. - """ - - if self.kwargs["on_wheel_fct"]: - self.kwargs["on_wheel_fct"]( - direction, - *self.kwargs["on_wheel_args"], - **self.kwargs["on_wheel_kwargs"] - ) - - def on_click_out(self): - """ - Do nothing by default. This method has to be overridden. - """ - - def on_middle_click_out(self): - """ - Do nothing by default. This method has to be overridden. - """ - - def on_right_click_out(self): - """ - Do nothing by default. This method has to be overridden. - """ - - def on_mouse_wheel_out(self, direction): - """ - Do nothing by default. This method has to be overridden. - """ - - def on_end_click(self): - """ - Set clicked state to False and call on_click_fct. - """ - - if self.clicked: - self.clicked = False - if self.kwargs["on_click_fct"]: - self.kwargs["on_click_fct"]( - *self.kwargs["on_click_args"], **self.kwargs["on_click_kwargs"] - ) - - def on_end_middle_click(self): - """ - Set middle_clicked state to False and call on_middle_click_fct. - """ - - if self.middle_clicked: - self.middle_clicked = False - if self.kwargs["on_middle_click_fct"]: - self.kwargs["on_middle_click_fct"]( - *self.kwargs["on_middle_click_args"], - **self.kwargs["on_middle_click_kwargs"] - ) - - def on_end_right_click(self): - """ - Set right_clicked state to False and call on_right_click_fct. - """ - - if self.right_clicked: - self.right_clicked = False - if self.kwargs["on_right_click_fct"]: - self.kwargs["on_right_click_fct"]( - *self.kwargs["on_right_click_args"], - **self.kwargs["on_right_click_kwargs"] - ) - - def on_end_mouse_wheel(self, direction): - """ - Do nothing by default. This method has to be overridden. - """ - - def on_end_click_out(self): - """ - Set clicked state to False. - """ - - if self.clicked: - self.clicked = False - - def on_end_middle_click_out(self): - """ - Set middle_clicked state to False. - """ - - if self.middle_clicked: - self.middle_clicked = False - - def on_end_right_click_out(self): - """ - Set right_clicked state to False. - """ - - if self.right_clicked: - self.right_clicked = False - - def on_end_mouse_wheel_out(self, direction): - """ - Do nothing by default. This method has to be overridden. - """ - - def add_uneventable_zone(self, pos, size): - """ - Add a zone where mouse events will have no effects for this widget. - - :type pos: tuple - :param pos: A (x, y) tuple representing the top left corner of the - uneventable zone (in pixel). - - :type size: tuple - :param size: A (w, h) tuple representing the size in pixel of the - uneventable zone. - - :rtype: tuple - :returns: A (x, y, w, h) tuple representing the uneventable zone - created. - """ - - real_pos = self.get_real_pos() - - if ( - pos[0] >= real_pos[0] - and pos[0] <= real_pos[0] + self.kwargs["size"][0] - and pos[1] >= real_pos[1] - and pos[1] <= real_pos[1] + self.kwargs["size"][1] - ): - if pos[0] + size[0] > real_pos[0] + self.kwargs["size"][0]: - size[0] = real_pos[0] + self.kwargs["size"][0] - pos[0] - if pos[1] + size[1] > real_pos[1] + self.kwargs["size"][1]: - size[1] = real_pos[1] + self.kwargs["size"][1] - pos[1] - - self.uneventable_zones.append((pos[0], pos[1], size[0], size[1])) - - return (pos[0], pos[1], size[0], size[1]) - else: - print( - "[WARNING] [EventableWidget.add_uneventable_zone] The zone exceeds the widget" - ) - - def remove_uneventable_zone(self, pos, size): - """ - Remove an uneventable zone. - - :type pos: tuple - :param pos: A (x, y) tuple representing the top left corner of the - uneventable zone (in pixel). - - :type size: tuple - :param size: A (w, h) tuple representing the size in pixel of the - uneventable zone. - """ - - if (pos[0], pos[1], size[0], size[1]) in self.uneventable_zones: - self.uneventable_zones.remove((pos[0], pos[1], size[0], size[1])) - - def is_in_uneventable_zone(self, pos): - """ - Check if a position is within an eventable zone. - - :type pos: tuple - :param pos: A (x, y) tuple representing the position to check. - - :rtype: bool - :returns: True if the position is within an uneventable zone. - """ - - for zone in self.uneventable_zones: - if ( - pos[0] >= zone[0] - and pos[0] <= zone[0] + zone[2] - and pos[1] >= zone[1] - and pos[1] <= zone[1] + zone[3] - ): - return True - return False diff --git a/src/gui/game_over_menu.py b/src/gui/game_over_menu.py deleted file mode 100644 index 4173bc2..0000000 --- a/src/gui/game_over_menu.py +++ /dev/null @@ -1,117 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a widget to create a "Game over" menu. - -Created on 21/08/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from gui.clickable_text import ClickableText -from gui.menu_widget import MenuWidget -from gui.text import Text - - -class GameOverMenu(MenuWidget): - """ - This class create a "Game over" menu widget displayed when Pyoro dies - """ - - DEFAULT_KWARGS = {"font_size": 20, "font": os.path.join(GUI_IMAGE_PATH, "font.ttf")} - - def __init__(self, activity, pos, score, quit_fct, **kwargs): - """ - Initialise a new GameOverMenu object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the menu in a (x, y) tuple where - x and y are integers. - - :type score: int - :param score: The score at the of the game. - - :type quit_fct: callable - :param quit_fct: A callable to run when the player click on the "Quit" - button. - """ - - GameOverMenu.update_default_kwargs(kwargs) - - self.quit_fct = quit_fct - self.score = score - - MenuWidget.__init__(self, activity, pos, **kwargs) - - def init_widgets(self): - """ - Create subwidgets which will compose the menu. - """ - - width, height = self.kwargs["size"] - font = self.kwargs["font"] - font_size = self.kwargs["font_size"] - font_size_medium = font_size - 3 - - pos_x = int(width * 0.5) - pos_y = int(height * 0.25) - self.add_sub_widget( - "titleText", - Text, - (pos_x, pos_y), - "Game Over", - anchor=(0, 0), - font=font, - font_size=font_size, - ) - pos_y = int(height * 0.50) - self.add_sub_widget( - "scoreText", - Text, - (pos_x, pos_y), - f"score : {self.score}", - anchor=(0, 0), - font=font, - font_size=font_size_medium, - ) - pos_y = int(height * 0.75) - self.add_sub_widget( - "quitClickableText", - ClickableText, - (pos_x, pos_y), - "quitter", - anchor=(0, 0), - font=font, - font_size=font_size_medium, - on_click_fct=self.destroy, - ) - - def destroy(self): - """ - Destroy the widget and call self.quit_fct. - """ - - MenuWidget.destroy(self) - self.quit_fct() diff --git a/src/gui/image_transformer.py b/src/gui/image_transformer.py deleted file mode 100644 index 6db95d8..0000000 --- a/src/gui/image_transformer.py +++ /dev/null @@ -1,175 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide useful functions on pygame.surface.Surface. - -Created on 18/08/2018. -""" - -import pygame - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -def resize_image(image, new_size): - """ - Resize a pygame surface by stretching its pixels. - - :type image: pygame.surface.Surface - :param image: The surface to resize. - - :type new_size: (tuple) - :param new_size: A (w, h) tuple where w and h are both integers. - - :rtype: pygame.surface.Surface - :returns: A new pygame surface resized from the given one. - """ - - if len(new_size) != 2: - return image - new_size = (int(new_size[0]), int(new_size[1])) - return pygame.transform.scale(image, new_size) - - -def invert_image(image, vertical, horizontal): - """ - Flip a pygame surface vertically and / or horizontally. - - :type image: pygame.surface.Surface - :param image: The surface to flip. - - :type vertical: bool - :param vertical: If True, flip the surface vertically. - - :type horizontal: bool - :param horizontal: If True, flip the surface horizontally. - - :rtype: pygame.surface.Surface - :returns: A new pygame surface flipped from the given one. - """ - - return pygame.transform.flip(image, vertical, horizontal) - - -def stretch_image(image, new_size, border_size): - """ - Try to stretch a pygame surface without deforming it. This technique is - inspired by Android 9-patch. Only the center and borders of the image - can stretch, leaving the corners and the thickness of the borders - intact. - - :type image: pygame.surface.Surface - :param image: The surface to resize. - - :type new_size: (tuple) - :param new_size: A (w, h) tuple where w and h are both integers. - - :type border_size: int - :param border_size: The thickness of the borders (kept after the - operation). - - :rtype: pygame.surface.Surface - :returns: A new pygame surface resized from the given one. - """ - - if len(new_size) != 2: - return image - - new_size = (int(new_size[0]), int(new_size[1])) - - if border_size <= new_size[0] / 2 and border_size <= new_size[1] / 2: - border_size = int(border_size) - else: - border_size = min(new_size) // 2 - - if image.get_alpha is None: - back = pygame.Surface(new_size).convert() - else: - back = pygame.Surface(new_size).convert_alpha() - - side_length = ( - image.get_size()[0] - border_size * 2, - image.get_size()[1] - border_size * 2, - ) - new_side_length = (new_size[0] - border_size * 2, new_size[1] - border_size * 2) - - back.blit(image.subsurface((0, 0), (border_size, border_size)).copy(), (0, 0)) - back.blit( - pygame.transform.scale( - image.subsurface((border_size, 0), (side_length[0], border_size)).copy(), - (new_side_length[0], border_size), - ), - (border_size, 0), - ) - back.blit( - image.subsurface( - (side_length[0] + border_size, 0), (border_size, border_size) - ).copy(), - (new_side_length[0] + border_size, 0), - ) - back.blit( - pygame.transform.scale( - image.subsurface((0, border_size), (border_size, side_length[1])).copy(), - (border_size, new_side_length[1]), - ), - (0, border_size), - ) - back.blit( - pygame.transform.scale( - image.subsurface( - (border_size, border_size), (side_length[0], side_length[1]) - ), - (new_side_length[0], new_side_length[1]), - ), - (border_size, border_size), - ) - back.blit( - pygame.transform.scale( - image.subsurface( - (side_length[0] + border_size, border_size), - (border_size, side_length[1]), - ).copy(), - (border_size, new_side_length[1]), - ), - (new_side_length[0] + border_size, border_size), - ) - back.blit( - image.subsurface( - (0, side_length[1] + border_size), (border_size, border_size) - ).copy(), - (0, new_side_length[1] + border_size), - ) - back.blit( - pygame.transform.scale( - image.subsurface( - (border_size, side_length[1] + border_size), - (side_length[0], border_size), - ).copy(), - (new_side_length[0], border_size), - ), - (border_size, new_side_length[1] + border_size), - ) - back.blit( - image.subsurface( - (side_length[0] + border_size, side_length[1] + border_size), - (border_size, border_size), - ).copy(), - (new_side_length[0] + border_size, new_side_length[1] + border_size), - ) - return back diff --git a/src/gui/image_widget.py b/src/gui/image_widget.py deleted file mode 100644 index 3cb8b5a..0000000 --- a/src/gui/image_widget.py +++ /dev/null @@ -1,96 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a high level image object. - -Created on 31/12/2018 -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from gui.image_transformer import resize_image -from gui.widget import Widget - - -class ImageWidget(Widget): - """ - Create a widget used to render image easily. - """ - - DEFAULT_KWARGS = {} - - def __init__(self, activity, pos, image_path, **kwargs): - """ - Initialize a new ImageWidget object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The position of the widget in a (x, y) tuple, where x and y - are integers. - - :type image_path: str - :param image_path: The image's filepath. - """ - - ImageWidget.update_default_kwargs(kwargs) - self.activity = activity - self.load_image(image_path) - - if "size" in kwargs: - self.resize(kwargs["size"]) - else: - kwargs["size"] = self.size - - Widget.__init__(self, activity, pos, **kwargs) - - def load_image(self, image_path): - """ - Load an image file to this object. - - :type image_path: str - :param image_path: The filepath to the image to load. - """ - - self.image = self.activity.window.get_image(image_path) - self.size = self.image.get_size() - - def update(self, delta_time): - """ - Redraw the image on the game window. - This method should be called each frame. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds) - """ - self.activity.window.draw_image(self.image, self.get_real_pos()) - - def resize(self, new_size): - """ - Resize the widget by stretching the image. - - :type new_size: tuple - :param new_size: The size to give to the widget in a (width, height) - tuple, where width and height are integers. - """ - - self.image = resize_image(self.image, new_size) - self.size = tuple(new_size) diff --git a/src/gui/layout.py b/src/gui/layout.py deleted file mode 100644 index 156a1e4..0000000 --- a/src/gui/layout.py +++ /dev/null @@ -1,179 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to manage widget dispositions, according to the screen -resolution. - -Created on 16/12/2018 -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.util import ( - get_layout_template, - get_screen_ratio, - get_screen_size, - get_monitor_size, -) - - -class Layout: - """ - Layout help to get widgets size, position and anchor according to - the window resolution. - """ - - def __init__(self, window): - """ - Initialize a ne Layout object. - - :type window: gui.window.Window - :param window: A game window to work with. - """ - - self.window = window - self.width = 1 - self.height = 1 - self.width_mm = 1 - self.height_mm = 1 - self.dpm = 1 - self.template = {} - - def load(self): - """ - Try to load a layout template adapted to a defined resolution. - - :type width: int - :param width: (Optional) The width of the window (in pixel). Leave - None to use the current window width. - - :type height: int - :param height: (Optional) The height of the window (in pixel). Leave - None to use the current window height. - """ - - self.width, self.height = get_screen_size() - self.width_mm, self.height_mm = get_monitor_size() - self.dpm = (self.width / self.width_mm + self.height / self.height_mm) / 2 - self.template = get_layout_template(get_screen_ratio()) - - def get_widget_pos(self, widget_name): - """ - Return the absolute position of a widget, in pixel. - - :type widget_name: str - :param widget_name: A string representing a widget. - - :rtype: tuple - :returns: (x, y) coordinates referencing the widget position. - If something wrong happen, return (0, 0) - """ - - width, height = self.get_widget_info(widget_name, "pos", [0, 0]) - return int(width * self.width / 100), int(height * self.height / 100) - - def get_widget_size(self, widget_name): - """ - Return the size of a widget, in pixel. - - :type widget_name: str - :param widget_name: A string representing a widget. - - :rtype: tuple - :returns: (w, h) tuple referencing the widget size. - """ - - min_width_mm, min_height_mm = self.get_widget_info( - widget_name, "min_mm_format", [0, 0] - ) - width_mm, height_mm = self.get_widget_info(widget_name, "size_mm", [1, 1]) - width_pixel, height_pixel = self.get_widget_info(widget_name, "size", [1, 1]) - width, height = width_pixel * self.width / 100, height_pixel * self.height / 100 - - if self.width_mm >= min_width_mm: - width = width_mm * self.dpm - - if self.height_mm >= min_height_mm: - height = height_mm * self.dpm - - return int(width), int(height) - - def get_widget_anchor(self, widget_name): - """ - Return the anchor position of a widget. - - :type widget_name: str - :param widget_name: A string representing a widget. - - :rtype: tuple - :returns: (x, y) coordinates referencing the widget anchor point, - relative to the widget position. If something wrong happen, - return (0, 0). - """ - - return self.get_widget_info(widget_name, "anchor", [0, 0]) - - def get_font_size(self, widget_name): - """ - Return the font size of a text widget. - - :type widget_name: str - :param widget_name: A string representing a text widget. - - :rtype: int - :returns: The font size in pixel. - """ - - min_width_mm, min_height_mm = self.get_widget_info( - widget_name, "min_mm_format", [0, 0] - ) - font_mm = self.get_widget_info(widget_name, "font_size_mm", 1) - font_pixel = self.get_widget_info(widget_name, "font_size", 1) - - if self.height_mm < min_height_mm or self.width_mm < min_width_mm: - return int(font_pixel * (self.height + self.width) / 200) - return int(font_mm * self.dpm) - - def get_widget_info(self, widget_name, info, default_value=None): - """ - Return an information for a given widget. - - :type widget_name: str - :param widget_name: A string representing a widget. - - :type info: str - :param info: The name of info searched. - - :type default_value: object - :param default_value: (Optional). The returned value if something wrong - happen. - - :Example: layout.get_widget_info("play_button_1", "size", [1, 1]) - """ - - if widget_name in self.template: - if info in self.template[widget_name]: - return self.template[widget_name][info] - print( - "[WARNING] [Layout.get_widget_info] No info " - + f'"{info}" for "{widget_name}"' - ) - else: - print(f'[WARNING] [Layout.get_widget_info] No widget "{widget_name}" found') - return default_value diff --git a/src/gui/level_activity.py b/src/gui/level_activity.py deleted file mode 100644 index 31d95d3..0000000 --- a/src/gui/level_activity.py +++ /dev/null @@ -1,412 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide an activity to manage the real game view. - -Created on 10/04/2018 -""" - -import os - -from pygame.locals import ( - KEYDOWN, - KEYUP, - JOYBUTTONDOWN, - JOYBUTTONUP, - JOYHATMOTION, - JOYAXISMOTION, -) - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.util import Game - -from gui.activity import Activity -from gui.game_over_menu import GameOverMenu -from gui.level_drawer import LevelDrawer -from gui.pause_menu import PauseMenu -from gui.text import Text - - -class LevelActivity(Activity): - """ - Activity managing in-game graphical components. - """ - - def __init__(self, window, game_id=0): - """ - Initialize a new LevelActivity object. - - :type window: gui.window.Window - :param window: The parent game window. - - :type game_id: int - :param game_id: (Optional) The id of the game to load. It can be 0 or 1. - 0 = Pyoro, 1 = Pyoro 2. Default is 0. - """ - - self.window = window - self.level_drawer = LevelDrawer(self, game_id) - - self.last_level_style_type = 0 - self.last_level_score = 0 - - self.joy_hat_states = [] - self.joy_axis_states = [] - - Activity.__init__(self, window) - self.init_joy_states() - - def init_sounds(self): - """ - Load sounds and musics which will be used later by this activity. - """ - - self.__init_sounds__( - ( - "music_0", - "music_1", - "music_2", - "drums", - "organ", - "game_over", - "speed_drums", - ), - os.path.join("data", "audio", "musics"), - "music", - ) - Game.audio_player.set_speed(1) - self.sounds["music_0"].play(-1) - - def init_widgets(self): - """ - Create widgets which will be used later by this activity ("score" and "high - score" text). - """ - - spos = self.layout.get_widget_pos("score_text") - ssize = self.layout.get_font_size("score_text") - - hpos = self.layout.get_widget_pos("high_score_text") - hsize = self.layout.get_font_size("high_score_text") - - self.add_widget( - "score_text", Text, spos, "Score: 0", font_size=ssize, anchor=(0, -1) - ) - self.add_widget( - "high_score_text", - Text, - hpos, - f"Meilleur Score: {self.get_high_score()}", - font_size=hsize, - anchor=(0, -1), - ) - - def init_joy_states(self): - """ - Initialize joystick hat and axis values. - """ - - best_joy_hats = max( - self.window.joysticks, key=lambda x: x.get_numhats(), default=None - ) - best_joy_axis = max( - self.window.joysticks, key=lambda x: x.get_numaxes(), default=None - ) - if best_joy_hats: - for _ in range(best_joy_hats.get_numhats()): - self.joy_hat_states.append(None) - if best_joy_axis: - for i in range(best_joy_axis.get_numaxes()): - self.joy_axis_states.append(None) - - # score - def get_high_score(self): - """ - Return the highest score from options. - - :rtype: int - :returns: The highest score for the current game_id. - """ - - return Game.options.get("high score", [0, 0])[self.level_drawer.level.game_id] - - def set_high_score(self, score): - """ - Define a new high score for the current game_id. - """ - - if "high score" not in Game.options: - Game.options["high score"] = [0, 0] - Game.options["high score"][self.level_drawer.level.game_id] = score - - def update_score(self): - """ - Update the score text widget with the current score. - """ - - self.widgets["score_text"].text = f"Score: {self.level_drawer.level.score}" - if self.level_drawer.level.score > self.get_high_score(): - self.widgets[ - "high_score_text" - ].text = f"High Score: {self.level_drawer.level.score}" - - def update_sounds(self, delta_time): - """ - Start or stop musics according to the current score. - """ - - style_type = self.level_drawer.level.get_style_type_with_score() - - # Normal style - if style_type == 0: - if self.last_level_score != self.level_drawer.level.score: - - if ( - self.last_level_score < 5000 - and self.level_drawer.level.score >= 5000 - ): - print( - "[INFO] [LevelActivity.update_sounds] Drums added to the music" - ) - self.sounds["drums"].play(-1) - self.sounds["drums"].set_pos(self.sounds["music_0"].pos) - - elif ( - self.last_level_score < 10000 - and self.level_drawer.level.score >= 10000 - ): - print( - "[INFO] [LevelActivity.update_sounds] Organ added to the music" - ) - self.sounds["organ"].play(-1) - self.sounds["organ"].set_pos(self.sounds["music_0"].pos) - - # Black and white style - elif style_type == 1: - if self.last_level_style_type != style_type: - print("[INFO] [LevelActivity.update_sounds] Music 2 started") - Game.audio_player.set_speed(1) - Game.audio_player.stop_audio() - self.sounds["music_1"].play(-1) - - # Flashy style - elif style_type == 2: - if self.last_level_style_type != style_type: - print("[INFO] [LevelActivity.update_sounds] Music 3 started") - Game.audio_player.set_speed(1) - Game.audio_player.stop_audio() - self.sounds["music_2"].play(-1) - - if self.last_level_score < 41000 and self.level_drawer.level.score >= 41000: - print( - "[INFO] [LevelActivity.update_sounds] Speed drums added to the music" - ) - self.sounds["speed_drums"].play(-1) - self.sounds["speed_drums"].set_pos(self.sounds["music_2"].pos) - - self.last_level_style_type = style_type - self.last_level_score = self.level_drawer.level.score - if not self.level_drawer.level.pyoro.dead: - Game.audio_player.set_speed( - Game.audio_player.get_speed() + 0.002 * delta_time - ) - - def save_level_state(self): - """ - Save the score and the game_id of the current level. - """ - - if self.level_drawer.level.score > self.get_high_score(): - self.set_high_score(self.level_drawer.level.score) - Game.options["last game"] = self.level_drawer.level.game_id - - def pause_game(self): - """ - Stop updating the level. - """ - - if "pause_menu" in self.widgets: - self.on_pause_menu_destroy() - else: - if "gameOverMenu" not in self.widgets: - # Game.audio_player.pauseAudio() - size = self.layout.get_widget_size("pause_menu") - pos = self.layout.get_widget_pos("pause_menu") - anchor = self.layout.get_widget_anchor("pause_menu") - fsize = self.layout.get_font_size("pause_menu") - - self.add_widget( - "pause_menu", - PauseMenu, - pos, - self.on_pause_menu_destroy, - self.window.set_menu_render, - size=size, - anchor=anchor, - font_size=fsize, - ) - self.level_drawer.level.loop_active = False - - def on_pause_menu_destroy(self): - """ - This method is called when the pause menu is destroyed. It re-enable the - level to be updated. - """ - - self.remove_widget("pause_menu") - self.level_drawer.level.loop_active = True - # Game.audio_player.unpauseAudio() - - def game_over(self): - """ - Stop sounds and create a "game over" menu dialog. - """ - - Game.audio_player.stop_audio() - Game.audio_player.set_speed(1) - self.sounds["game_over"].play() - - size = self.layout.get_widget_size("game_over_menu") - pos = self.layout.get_widget_pos("game_over_menu") - anchor = self.layout.get_widget_anchor("game_over_menu") - fsize = self.layout.get_font_size("game_over_menu") - - self.add_widget( - "gameOverMenu", - GameOverMenu, - pos, - self.level_drawer.level.score, - self.on_game_over_menu_destroy, - size=size, - anchor=anchor, - font_size=fsize, - ) - - def on_game_over_menu_destroy(self): - """ - This method is called when the game over menu is destroyed. It makes the - game return to the main menu. - """ - - self.remove_widget("gameOverMenu") - self.window.set_menu_render() - - def update_event(self, event): - """ - Update the level with - """ - - if self.level_drawer.level.loop_active: - keyboard = Game.options.get("keyboard", {}) - joystick = Game.options.get("joystick", {}) - pyoro = self.level_drawer.level.pyoro - - enable_keys = { - "left": pyoro.enable_move_left, - "right": pyoro.enable_move_right, - "action": pyoro.enable_capacity, - "pause": self.pause_game, - } - disable_keys = { - "left": pyoro.disable_move, - "right": pyoro.disable_move, - "action": pyoro.disable_capacity, - "pause": lambda: None, - } - - if event.type == KEYDOWN: - for action_name, action in enable_keys.items(): - if event.key == keyboard.get(action_name, None): - action() - - elif event.type == KEYUP: - for action_name, action in disable_keys.items(): - if event.key == keyboard.get(action_name, None): - action() - - elif event.type == JOYBUTTONDOWN: - for action_name, input_infos in joystick.items(): - if input_infos["inputType"] == JOYBUTTONDOWN: - if input_infos["buttonId"] == event.button: - enable_keys[action_name]() - - elif event.type == JOYBUTTONUP: - for action_name, input_infos in joystick.items(): - if input_infos["inputType"] == JOYBUTTONDOWN: - if input_infos["buttonId"] == event.button: - disable_keys[action_name]() - - elif event.type == JOYHATMOTION: - enabled = event.value - disabled = self.joy_hat_states[event.hat] - self.joy_hat_states[event.hat] = enabled - - for action_name, input_infos in joystick.items(): - if input_infos["inputType"] == JOYHATMOTION: - if input_infos["hatId"] == event.hat: - if input_infos["value"] == enabled: - enable_keys[action_name]() - elif input_infos["value"] == disabled: - disable_keys[action_name]() - - elif event.type == JOYAXISMOTION: - enabled = event.value - disabled = self.joy_axis_states[event.axis] - self.joy_axis_states[event.axis] = enabled - - for action_name, input_infos in joystick.items(): - if input_infos["inputType"] == JOYAXISMOTION: - if input_infos["axisId"] == event.axis: - if ( - input_infos["value"] / enabled > 0 - and abs(event.value) > 0.2 - ): - enable_keys[action_name]() - elif disabled: - if ( - input_infos["value"] / disabled > 0 - or abs(event.value) <= 0.2 - ): - disable_keys[action_name]() - - Activity.update_event(self, event) - - def update(self, delta_time): - """ - Update all graphical components of this activity. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - self.level_drawer.update(delta_time) - if self.level_drawer.level.loop_active: - self.update_score() - self.update_sounds(delta_time) - Activity.update(self, delta_time) - - def destroy(self): - """ - Destroy the activity and all its components. - """ - - self.save_level_state() - Activity.destroy(self) diff --git a/src/gui/level_drawer.py b/src/gui/level_drawer.py deleted file mode 100644 index f0c5e2f..0000000 --- a/src/gui/level_drawer.py +++ /dev/null @@ -1,297 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to draw a game.level.Level and entities.entity.Entity - -Created on 11/10/2018 -""" - -import os -import pygame - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import CASE_SIZE, BACKGROUND_TRANSITION_DURATION, LEVEL_IMAGE_PATH -from game.level import Level -from game.util import get_monitor_density, get_screen_size -from gui.image_transformer import resize_image - - -class LevelDrawer: - """ - Create a LevelDrawer object, usually used to draw a level and its - entities on the screen. - """ - - def __init__(self, activity, game_id, bot_mode=False): - """ - Initialize a new LevelDrawer object, create a new level and load - background images. - - :type activity: gui.activity.Activity - :param activity: The parent activity where to draw the level. - - :type game_id: int - :param game_id: An integer representing Pyoro 1 or 2 (0=Pyoro, - 1=Pyoro 2). - - :type bot_mode: bool - :param bot_mode: (Optional) Define if Pyoro have to be replaced by - Pyobot. Default is False. - """ - - self.activity = activity - self.images = {} - self.case_size = () - self.level = None - - self.init_level(game_id, bot_mode) - - self.last_background_id = self.level.get_background_id_with_score() - self.last_background = None - - self.init_images() - - def init_level(self, game_id, bot_mode): - """ - Create a new level with given game_id and bot_mode value. - - :type game_id: int - :param game_id: An integer representing Pyoro 1 or 2 (0=Pyoro, - 1=Pyoro 2). - - :type bot_mode: bool - :param bot_mode: Define if Pyoro have to be replaced by Pyobot. Default - is False. - """ - - self.level = Level(self, game_id, self.get_level_size(), bot_mode) - - def get_level_size(self): - """ - Return the size of the level (the scale is expressed in case). - - :rtype: tuple - :returns: A (w, h) tuple where w is an integer and h is a float - number. - """ - - width_pixel, height_pixel = get_screen_size() - horizontal_density, vertical_density = get_monitor_density() - case_width, case_height = ( - horizontal_density * CASE_SIZE, - vertical_density * CASE_SIZE, - ) - return int(width_pixel / case_width), height_pixel / case_height - - def get_case_size(self): - """ - Return the size of one case in pixel. - - - :rtype: tuple - :returns: A (w, h) tuple where w and h are both float numbers. - """ - - if not self.case_size: - screen_width, screen_height = get_screen_size() - if self.level: - case_width, case_height = self.level.size - else: - case_width, case_height = self.get_level_size() - self.case_size = screen_width / case_width, screen_height / case_height - return self.case_size - - def init_images(self): - """ - Initialize background images. - """ - - folder = os.path.join(LEVEL_IMAGE_PATH, "block") - size = self.get_case_size() - for i in range(3): - image_name = f"block_{i}.png" - self.images[image_name] = resize_image( - self.activity.window.get_image(os.path.join(folder, image_name)), size - ) - - folder = os.path.join(LEVEL_IMAGE_PATH, f"background {self.level.game_id + 1}") - size = self.activity.window.get_size() - for i in range(21): - image_name = f"background_{i}.png" - self.images[image_name] = resize_image( - self.activity.window.get_image( - os.path.join(folder, image_name), alpha_channel=False - ), - size, - ) - - def draw_pyoro(self): - """ - Draw Pyoro (or Pyoro 2) and its tongue when he tries to catch a bean. - """ - - pyoro = self.level.pyoro - tongue = pyoro.tongue - case_size = self.get_case_size() - if tongue: - # define tongue colors (insideColor, outlineColor) - style_type = self.level.get_style_type_with_score() - if style_type == 0: - color = ((255, 98, 183), (0, 0, 0)) - elif style_type == 1: - color = ((178, 178, 178), (0, 0, 0)) - else: - color = ((0, 0, 0), (255, 255, 255)) - - # define tongue pos - tx1 = tongue.pos[0] - tongue.size[0] * 0.5 * pyoro.direction - tx2 = tongue.pos[0] - tongue.size[0] * 0.4 * pyoro.direction - px1 = pyoro.pos[0] + pyoro.size[0] * 0.25 * pyoro.direction - px2 = pyoro.pos[0] + pyoro.size[0] * 0.3125 * pyoro.direction - - ty1 = tongue.pos[1] + tongue.size[1] * 0.4 - ty2 = tongue.pos[1] + tongue.size[1] * 0.5 - py1 = pyoro.pos[1] - pyoro.size[1] * 0.125 - py2 = pyoro.pos[1] - pyoro.size[1] * 0.0625 - - tongue_coords = [(px1, py1), (tx1, ty1), (tx2, ty2), (px2, py2)] - - for key, pos in enumerate(tongue_coords): - x_pos = int(pos[0] * self.case_size[0] + 5) - y_pos = int(pos[1] * self.case_size[1] + 5) - tongue_coords[key] = (x_pos, y_pos) - - pygame.draw.polygon( - self.activity.window.root_surface, color[0], tongue_coords - ) - pygame.draw.line( - self.activity.window.root_surface, - color[1], - tongue_coords[0], - tongue_coords[1], - int(0.115 * case_size[0]), - ) - pygame.draw.line( - self.activity.window.root_surface, - color[1], - tongue_coords[2], - tongue_coords[3], - int(3.68), - ) - - self.activity.window.draw_image( - pyoro.images[pyoro.current_image_name], - ( - (pyoro.pos[0] - pyoro.size[0] / 2) * case_size[0], - (pyoro.pos[1] - pyoro.size[1] / 2) * case_size[1], - ), - ) - - def draw_background(self): - """ - Draw the appropriate background image by handling smooth transition - animations between different background images. - """ - - back_id = self.level.get_background_id_with_score() - background = self.images[f"background_{back_id}.png"] - - if back_id == 0: - background.set_alpha(255) - else: - if self.last_background_id != back_id: - self.last_background = self.images[ - f"background_{self.last_background_id}.png" - ] - self.last_background_id = back_id - - self.last_background.set_alpha(255) - background.set_alpha(0) - - self.update_background_transition(0) - if background.get_alpha() != 255: - self.activity.window.draw_image(self.last_background, (0, 0)) - self.activity.window.draw_image(background, (0, 0)) - - def draw_blocks(self): - """ - Draw the cases which are not destroyed. - """ - - _, height = self.activity.window.get_size() - case_size = self.get_case_size() - for i in range(self.level.size[0]): - if self.level.cases[i].exists: - self.activity.window.draw_image( - self.images[f"block_{self.level.get_style_type_with_score()}.png"], - (i * case_size[0], height - case_size[1]), - ) - - def update_background_transition(self, opacity): - """ - Increase new background opacity to create a smooth transition - animation. - - :type opacity: float - :param opacity: Opacity of the new background image (1 <= opacity <= 255). - """ - - self.images[ - f"background_{self.level.get_background_id_with_score()}.png" - ].set_alpha(opacity) - - if opacity < 255: - self.level.set_action_delay( - (self, "update_background_transition"), - BACKGROUND_TRANSITION_DURATION / 128, - self.update_background_transition, - opacity + 2, - ) - else: - self.level.remove_action_delay((self, "update_background_transition")) - - def draw_entities(self): - """ - Draw all entities stored in the level except Pyoro (There is another - method to draw Pyoro). - """ - - width, height = self.get_case_size() - for entity in self.level.entities: - x_pos = (entity.pos[0] - entity.size[0] / 2) * width - y_pos = (entity.pos[1] - entity.size[1] / 2) * height - self.activity.window.draw_image( - entity.images[entity.current_image_name], (x_pos, y_pos) - ) - - def update(self, delta_time): - """ - Update the level drawer by drawing background, blocks, Pyoro and - entities images. - - :type delta_time: float - :param delta_time: Time elapsed since the last update. - """ - - self.level.update(delta_time) - self.draw_background() - self.draw_blocks() - self.draw_pyoro() - self.draw_entities() diff --git a/src/gui/menu_activity.py b/src/gui/menu_activity.py deleted file mode 100644 index 84fda60..0000000 --- a/src/gui/menu_activity.py +++ /dev/null @@ -1,180 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide an activity to manage the main menu. - -Created on 10/04/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from game.util import Game - -from gui.activity import Activity -from gui.button import Button -from gui.image_widget import ImageWidget -from gui.level_drawer import LevelDrawer -from gui.play_button import PlayButton -from gui.option_menu import OptionMenu - - -class MenuActivity(Activity): - """ - Layout managing the menu's components - """ - - def __init__(self, window, game_id): - """ - Initialize a new Menu_activity object. - - :type window: gui.window.Window - :param window: The parent game window. - - :type game_id: int - :param game_id: The game_id of the level in background. - 0 = Pyoro, 1 = Pyoro 2. - """ - - Activity.__init__(self, window) - self.level_drawer = LevelDrawer(self, game_id, bot_mode=True) - - def init_sounds(self): - """ - Reference the "intro.wav" music and start to play it. - This method reset the global Audio_player speed. - """ - - self.__init_sounds__( - ("intro",), os.path.join("data", "audio", "musics"), "music" - ) - Game.audio_player.set_speed(1) - self.sounds["intro"].play(-1) - - def init_widgets(self): - """ - Create widgets (Play, option and quit buttons). - """ - - widget_infos = { - "title_image": { - "type": ImageWidget, - "args": (os.path.join(GUI_IMAGE_PATH, "title.png"),), - "kwargs": {}, - }, - "play_button_1": { - "type": PlayButton, - "args": (0,), - "kwargs": { - "on_click_fct": self.window.set_game_render, - "text_anchor": (0, -0.1), - }, - }, - "play_button_2": { - "type": PlayButton, - "args": (1,), - "kwargs": { - "on_click_fct": self.window.set_game_render, - "enable": self.is_pyoro_2_unlocked(), - "text_anchor": (0, -0.1), - }, - }, - "option_button": { - "type": Button, - "args": (), - "kwargs": {"text": "Options", "on_click_fct": self.create_option_menu}, - }, - "quit_button": { - "type": Button, - "args": (), - "kwargs": {"text": "Quitter", "on_click_fct": self.window.destroy}, - }, - } - - for widget_name, kwargs in widget_infos.items(): - pos = self.layout.get_widget_pos(widget_name) - size = self.layout.get_widget_size(widget_name) - anchor = self.layout.get_widget_anchor(widget_name) - fsize = self.layout.get_font_size(widget_name) - - self.add_widget( - widget_name, - kwargs["type"], - pos, - *kwargs["args"], - size=size, - anchor=anchor, - textKwargs={"font_size": fsize}, - **kwargs["kwargs"] - ) - - def create_option_menu(self): - """ - Display an option menu. - """ - - size = self.layout.get_widget_size("option_menu") - pos = self.layout.get_widget_pos("option_menu") - anchor = self.layout.get_widget_anchor("option_menu") - fsize = self.layout.get_font_size("option_menu") - - self.add_widget( - "option_menu", - OptionMenu, - pos, - self.on_option_menu_destroy, - size=size, - anchor=anchor, - font_size=fsize, - ) - - def on_option_menu_destroy(self): - """ - This method is called when the option menu is destroyed. - Remove the option menu from the updatable widgets list. - """ - - self.widgets["play_button_2"].config(enable=self.is_pyoro_2_unlocked()) - self.remove_widget("option_menu") - - def update(self, delta_time): - """ - Update the level and redraw graphical components. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method - (in seconds). - """ - - self.level_drawer.update(delta_time) - Activity.update(self, delta_time) - - def is_pyoro_2_unlocked(self): - """ - Check if Pyoro 2 is unlocked. To unlock Pyoro 2, the score must be - greater than 10000. - - :rtype: bool - :returns: True if Pyoro 2 is unlocked, otherwise False. - """ - - high_score = Game.options.get("high score", [0, 0]) - return high_score[0] >= 10000 diff --git a/src/gui/menu_widget.py b/src/gui/menu_widget.py deleted file mode 100644 index 7448863..0000000 --- a/src/gui/menu_widget.py +++ /dev/null @@ -1,204 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a MenuWidget base class. - -Created on 08/10/2018. -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from gui.image_transformer import stretch_image -from gui.widget import Widget - - -class MenuWidget(Widget): - """ - Create a widget used to pack sub_widgets which will be updated by this - menu. - """ - - DEFAULT_KWARGS = {"background_image": os.path.join(GUI_IMAGE_PATH, "frame.png")} - - def __init__(self, activity, pos, **kwargs): - """ - Initialize a new Menu objects. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - background_image can be defined. - """ - - MenuWidget.update_default_kwargs(kwargs) - Widget.__init__(self, activity, pos, **kwargs) - - self.sub_widgets = {} - self.background_image = None - self.activity.disable_widgets() - self.load_background_image() - self.init_widgets() - - def load_background_image(self): - """ - Create the background from an image stretched to the widget size. - """ - - if self.kwargs["background_image"]: - self.background_image = stretch_image( - self.activity.window.get_image(self.kwargs["background_image"]), - self.kwargs["size"], - 5, - ) - - def init_widgets(self): - """ - Initialize all sub_widgets. - """ - - def add_sub_widget( - self, widget_name, widget_type, pos, *widgetArgs, **widgetKwargs - ): - """ - Create and add a new widget to this menu. - - :type widget_name: str - :param widget_name: A string to identify the subwidget. - - :type widget_type: type - :param widget_type: A type used to create the subwidget. - - :type pos: tuple - :param pos: The default position of the subwidget relative to the - upper left corner of the menu. - - Arguments and keyword arguments to pass to the subwidget can be - defined then. - """ - - if widget_name in self.sub_widgets: - print( - "[WARNING] [MenuWidget.add_sub_widget] A widget " - + f'called "{widget_name}" already exists in' - + " this MenuWidget ! Destroying it" - ) - - if not self.sub_widgets[widget_name].is_destroyed: - self.sub_widgets[widget_name].destroy() - - real_pos = self.get_real_pos() - self.sub_widgets[widget_name] = widget_type( - self.activity, - (pos[0] + real_pos[0], pos[1] + real_pos[1]), - *widgetArgs, - **widgetKwargs, - ) - - def remove_sub_widget(self, widget_name): - """ - Remove a subwidget from this menu. - - :type widget_name: str - :param widget_name: The name used to identify the subwidget. - """ - - if widget_name in self.sub_widgets: - if not self.sub_widgets[widget_name].is_destroyed: - self.sub_widgets[widget_name].destroy() - self.sub_widgets.pop(widget_name) - else: - print( - "[WARNING] [MenuWidget.remove_sub_widget] No widget called" - + f' "{widget_name}" in this MenuWidget' - ) - - def config_sub_widget(self, widget_name, **kwargs): - """ - Call config method on a given subwidget. - - :type widget_name: str - :param widget_name: The name used to identify the subwidget. - - Keyword arguments are passed to the subwidget.config method. - """ - - if widget_name in self.sub_widgets: - self.sub_widgets[widget_name].config(**kwargs) - else: - print( - "[WARNING] [MenuWidget.config_sub_widget] No widget called" - + f' "{widget_name}" in this MenuWidget' - ) - - def update(self, delta_time): - """ - Update the menu and its sub_widgets. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - if self.background_image: - self.activity.window.draw_image(self.background_image, self.get_real_pos()) - - for widget in tuple(self.sub_widgets.values()): - if not widget.is_destroyed: - widget.update(delta_time) - - def on_event(self, event): - """ - This method is called on all user events detected by Pygame. - - :type event: pygame.event.Event - :param event: The event to handle. - """ - - for widget in tuple(self.sub_widgets.values()): - if not widget.is_destroyed: - widget.on_event(event) - - def destroy(self): - """ - Destroy the menu and its sub_widgets. - """ - - for widget in tuple(self.sub_widgets.values()): - if not widget.is_destroyed: - widget.destroy() - self.sub_widgets.clear() - self.activity.enable_widgets() - Widget.destroy(self) - - def config(self, **kwargs): - """ - Change some kwargs of the menu. - """ - - Widget.config(self, **kwargs) - if "enable" in kwargs: - for widget in self.sub_widgets.values(): - widget.config(enable=kwargs["enable"]) diff --git a/src/gui/option_menu.py b/src/gui/option_menu.py deleted file mode 100644 index a395d38..0000000 --- a/src/gui/option_menu.py +++ /dev/null @@ -1,517 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a menu to manage game options. - -Created on 21/08/2018 -""" - -import os -from pygame.locals import KEYDOWN, JOYBUTTONDOWN, JOYAXISMOTION, JOYHATMOTION - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH, NAME, VERSION -from game.util import get_key_name, get_joy_key_name, reset_game, Game - -from gui.button import Button -from gui.setting_bar import SettingBar -from gui.text import Text -from gui.menu_widget import MenuWidget - - -class OptionMenu(MenuWidget): - """ - Create a menu allowing the player to change some game settings. - """ - - DEFAULT_KWARGS = {"font": os.path.join(GUI_IMAGE_PATH, "font.ttf"), "font_size": 20} - - def __init__(self, activity, pos, quit_fct, **kwargs): - """ - Initialize a new Option_menu widget. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of this widget in a (x, y) tuple where - x and y are integers. - - :type quit_fct: callable - :param quit_fct: A function, method or class which can be called when the - player leave this menu. - """ - - OptionMenu.update_default_kwargs(kwargs) - MenuWidget.__init__(self, activity, pos, **kwargs) - - self.quit_fct = quit_fct - self.waiting_input = () - - def init_widgets(self): - """ - Create sub_widgets which will be display in this menu. - """ - - font = self.kwargs["font"] - width, height = self.kwargs["size"] - keyboard_options = Game.options.get("keyboard", {}) - joystick_options = Game.options.get("joystick", {}) - music_volume = Game.options.get("music volume", 1) - sound_volume = Game.options.get("sound volume", 1) - font_size = self.kwargs["font_size"] - medium_font_size = font_size - 3 - mini_font_size = medium_font_size - 3 - - pos_x = int(width * 0.05) - pos_y = int(height * 0.15) - self.add_sub_widget( - "volumeMusicText", - Text, - (pos_x, pos_y), - "Volume de la musique", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.25) - self.add_sub_widget( - "volumeSoundText", - Text, - (pos_x, pos_y), - "Volume des sons", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.35) - self.add_sub_widget( - "commandTitleText", - Text, - (pos_x, pos_y), - "Commandes :", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_x = int(width * 0.15) - pos_y = int(height * 0.45) - self.add_sub_widget( - "rightCommandText", - Text, - (pos_x, pos_y), - "Aller a droite", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.55) - self.add_sub_widget( - "leftCommandText", - Text, - (pos_x, pos_y), - "Aller a gauche", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.65) - self.add_sub_widget( - "actionCommandText", - Text, - (pos_x, pos_y), - "Tirer (la langue)", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.75) - self.add_sub_widget( - "pauseCommandText", - Text, - (pos_x, pos_y), - "Pause / retour", - anchor=(-1, 0), - font_size=medium_font_size, - font=font, - ) - - pos_x = int(width * 0.25) - pos_y = int(height * 0.95) - self.add_sub_widget( - "resetButton", - Button, - (pos_x, pos_y), - text="Réinitialiser", - anchor=(0, 0), - text_kwargs={"font_size": medium_font_size, "font": font}, - size=(int(width * 0.4), int(height * 0.06)), - on_click_fct=reset_game, - ) - - pos_x = int(width * 0.5) - pos_y = int(height * 0.05) - self.add_sub_widget( - "titleText", - Text, - (pos_x, pos_y), - "Options", - anchor=(0, -1), - font_size=font_size, - font=font, - ) - - pos_x = int(width * 0.66) - pos_y = int(height * 0.35) - self.add_sub_widget( - "keyboardCommandText", - Text, - (pos_x, pos_y), - "Clavier", - anchor=(0, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.45) - self.add_sub_widget( - ("commandButton", "keyboard", "right"), - Button, - (pos_x, pos_y), - text=get_key_name(keyboard_options["right"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("keyboard", "right"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.55) - self.add_sub_widget( - ("commandButton", "keyboard", "left"), - Button, - (pos_x, pos_y), - text=get_key_name(keyboard_options["left"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("keyboard", "left"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.65) - self.add_sub_widget( - ("commandButton", "keyboard", "action"), - Button, - (pos_x, pos_y), - text=get_key_name(keyboard_options["action"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("keyboard", "action"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.75) - self.add_sub_widget( - ("commandButton", "keyboard", "pause"), - Button, - (pos_x, pos_y), - text=get_key_name(keyboard_options["pause"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("keyboard", "pause"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_x = int(width * 0.75) - pos_y = int(height * 0.95) - self.add_sub_widget( - "backButton", - Button, - (pos_x, pos_y), - text="Retour", - anchor=(0, 0), - text_kwargs={"font_size": medium_font_size, "font": font}, - size=(int(width * 0.4), int(height * 0.06)), - on_click_fct=self.destroy, - ) - - pos_x = int(width * 0.86) - pos_y = int(height * 0.35) - self.add_sub_widget( - "joystickCommandText", - Text, - (pos_x, pos_y), - "Manette", - anchor=(0, 0), - font_size=medium_font_size, - font=font, - ) - - pos_y = int(height * 0.45) - self.add_sub_widget( - ("commandButton", "joystick", "right"), - Button, - (pos_x, pos_y), - text=get_joy_key_name(**joystick_options["right"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("joystick", "right"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.55) - self.add_sub_widget( - ("commandButton", "joystick", "left"), - Button, - (pos_x, pos_y), - text=get_joy_key_name(**joystick_options["left"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("joystick", "left"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.65) - self.add_sub_widget( - ("commandButton", "joystick", "action"), - Button, - (pos_x, pos_y), - text=get_joy_key_name(**joystick_options["action"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("joystick", "action"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_y = int(height * 0.75) - self.add_sub_widget( - ("commandButton", "joystick", "pause"), - Button, - (pos_x, pos_y), - text=get_joy_key_name(**joystick_options["pause"]), - size=(int(width * 0.18), int(height * 0.08)), - on_click_fct=self.input_command, - on_click_args=("joystick", "pause"), - anchor=(0, 0), - text_kwargs={"font_size": mini_font_size, "font": font}, - ) - - pos_x = int(width * 0.95) - pos_y = int(height * 0.15) - self.add_sub_widget( - ("volumeSettingBar", "music"), - SettingBar, - (pos_x, pos_y), - anchor=(1, 0), - size=(int(width * 0.45), int(height * 0.05)), - cursor_width=int(width * 0.03), - line_thickness=int(height * 0.02), - value=music_volume, - ) - - pos_y = int(height * 0.25) - self.add_sub_widget( - ("volumeSettingBar", "sound"), - SettingBar, - (pos_x, pos_y), - anchor=(1, 0), - size=(int(width * 0.45), int(height * 0.05)), - cursor_width=int(width * 0.03), - line_thickness=int(height * 0.02), - value=sound_volume, - ) - - pos_y = int(height * 0.85) - self.add_sub_widget( - "versionText", - Text, - (pos_x, pos_y), - f"{NAME} v{VERSION}", - font=font, - font_size=mini_font_size, - anchor=(1, 0), - ) - - def on_event(self, event): - """ - Update sub_widgets of this menu by passing to the given event. - - :type event: pygame.event.Event - :param event: The pygame event to give to all sub_widgets. - """ - - MenuWidget.on_event(self, event) - if self.waiting_input: - if self.waiting_input[0] == "keyboard": - if event.type == KEYDOWN: - self.config_sub_widget( - ("commandButton", *self.waiting_input), - text=get_key_name(event.key), - enable=True, - ) - self.set_keyboard_option(self.waiting_input[1], event.key) - self.waiting_input = () - - elif self.waiting_input[0] == "joystick": - - if event.type == JOYBUTTONDOWN: - self.config_sub_widget( - ("commandButton", *self.waiting_input), - text=get_joy_key_name(JOYBUTTONDOWN, buttonId=event.button), - enable=True, - ) - self.set_joystick_option( - self.waiting_input[1], - inputType=JOYBUTTONDOWN, - buttonId=event.button, - ) - self.waiting_input = () - - elif event.type == JOYHATMOTION: - self.config_sub_widget( - ("commandButton", *self.waiting_input), - text=get_joy_key_name( - JOYHATMOTION, hatId=event.hat, value=round(event.value) - ), - enable=True, - ) - self.set_joystick_option( - self.waiting_input[1], - inputType=JOYHATMOTION, - hatId=event.hat, - value=round(event.value), - ) - self.waiting_input = () - - elif event.type == JOYAXISMOTION: - self.config_sub_widget( - ("commandButton", *self.waiting_input), - text=get_joy_key_name( - JOYAXISMOTION, axisId=event.axis, value=round(event.value) - ), - enable=True, - ) - self.set_joystick_option( - self.waiting_input[1], - inputType=JOYAXISMOTION, - axisId=event.axis, - value=round(event.value), - ) - self.waiting_input = () - - elif event.type == KEYDOWN: - self.config_sub_widget( - ("commandButton", *self.waiting_input), enable=True - ) - self.waiting_input = () - - def set_keyboard_option(self, action_name, key_code): - """ - Define a new key for a given action. - - :type action_name: str - :param action_name: The name used to identify the associated action. - - :type key_code: int - :param key_code: A key id. - """ - - if "keyboard" not in Game.options: - Game.options["keyboard"] = {} - Game.options["keyboard"][action_name] = key_code - - def set_joystick_option(self, action_name, **inputKwargs): - """ - Define a new controller button for a given action. - - :type action_name: str - :param action_name: The name used to identify the associated action. - - Keyword arguments depend of the event type. - """ - - if "joystick" not in Game.options: - Game.options["joystick"] = {} - Game.options["joystick"][action_name] = inputKwargs - - def update(self, delta_time): - """ - Update the menu, its sub_widgets and the sound volume. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - MenuWidget.update(self, delta_time) - - if ("volumeSettingBar", "music") in self.sub_widgets: - Game.audio_player.music_volume = self.sub_widgets[ - "volumeSettingBar", "music" - ].get_value() - if ("volumeSettingBar", "sound") in self.sub_widgets: - Game.audio_player.sound_volume = self.sub_widgets[ - "volumeSettingBar", "sound" - ].get_value() - - def destroy(self): - """ - Destroy the menu and its sub_widgets. - """ - - if ("volumeSettingBar", "music") in self.sub_widgets: - Game.options["music volume"] = self.sub_widgets[ - "volumeSettingBar", "music" - ].get_value() - if ("volumeSettingBar", "sound") in self.sub_widgets: - Game.options["sound volume"] = self.sub_widgets[ - "volumeSettingBar", "sound" - ].get_value() - MenuWidget.destroy(self) - self.quit_fct() - - def input_command(self, input_type_name, action_name): - """ - Start to record user event to configure the keyboard or a joystick. - - :type input_type_name: str - :param input_type_name: It can be "keyboard" or "joystick". - - :type action_name: str - :param action_name: The name used to identify the associated action. - """ - - if not self.waiting_input: - self.config_sub_widget( - ("commandButton", input_type_name, action_name), enable=False - ) - self.waiting_input = (input_type_name, action_name) diff --git a/src/gui/pause_menu.py b/src/gui/pause_menu.py deleted file mode 100644 index e1b5f50..0000000 --- a/src/gui/pause_menu.py +++ /dev/null @@ -1,174 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a menu to display when the game is paused. - -Created on 18/08/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH - -from gui.clickable_text import ClickableText -from gui.menu_widget import MenuWidget -from gui.option_menu import OptionMenu -from gui.text import Text - - -class PauseMenu(MenuWidget): - """ - A menu to display when the game is paused. - """ - - DEFAULT_KWARGS = {"font_size": 20, "font": os.path.join(GUI_IMAGE_PATH, "font.ttf")} - - def __init__(self, activity, pos, resume_fct, quit_fct, **kwargs): - """ - Initialize a new Pause_menu object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The position of the widget in a (x, y) tuple where x and y - are integers. - - :type resume_fct: callable - :param resume_fct: A function, class or method which can be called on click - on the "resume" button. - - :type quit_fct: callable - :param quit_fct: A function, class or method which can be called on click - on the "quit" button. - """ - - PauseMenu.update_default_kwargs(kwargs) - MenuWidget.__init__(self, activity, pos, **kwargs) - - self.resume_fct = resume_fct - self.quit_fct = quit_fct - - def init_widgets(self): - """ - Create widgets displayed in this dialog. - """ - - width, height = self.kwargs["size"] - font = self.kwargs["font"] - font_size = self.kwargs["font_size"] - medium_font_size = font_size - 3 - - pos_x = int(width * 0.5) - pos_y = int(height * 0.2) - self.add_sub_widget( - "titleText", - Text, - (pos_x, pos_y), - "Pause", - anchor=(0, 0), - font=font, - font_size=font_size, - ) - - pos_y = int(height * 0.4) - self.add_sub_widget( - "resumeClickableText", - ClickableText, - (pos_x, pos_y), - "continuer", - anchor=(0, 0), - font=font, - font_size=medium_font_size, - on_click_fct=self.destroy, - ) - - pos_y = int(height * 0.6) - self.add_sub_widget( - "optionClickableText", - ClickableText, - (pos_x, pos_y), - "options", - anchor=(0, 0), - font=font, - font_size=medium_font_size, - on_click_fct=self.open_option_menu, - ) - - pos_y = int(height * 0.8) - self.add_sub_widget( - "quitClickableText", - ClickableText, - (pos_x, pos_y), - "quitter", - anchor=(0, 0), - font=font, - font_size=medium_font_size, - on_click_fct=self.leave_level, - ) - - def destroy(self): - """ - Destroy the widget and its subwidgets, then call resume_fct. - """ - - MenuWidget.destroy(self) - self.resume_fct() - - def leave_level(self): - """ - Destroy the widget and its subwidgets, then call quit_fct. - """ - - MenuWidget.destroy(self) - self.quit_fct() - - def open_option_menu(self): - """ - Create an Option_menu. - """ - - layout = self.activity.layout - pos_x, pos_y = layout.get_widget_pos("option_menu") - size = layout.get_widget_size("option_menu") - anchor = layout.get_widget_anchor("option_menu") - fsize = layout.get_font_size("option_menu") - - realpos_x, realpos_y = self.get_real_pos() - pos_x, pos_y = pos_x - realpos_x, pos_y - realpos_y - self.add_sub_widget( - "option_menu", - OptionMenu, - (pos_x, pos_y), - self.on_option_menu_destroy, - size=size, - anchor=anchor, - font_size=fsize, - ) - - def on_option_menu_destroy(self): - """ - This method is called when the Option_menu is destroyed. - """ - - self.remove_sub_widget("option_menu") - self.activity.disable_widgets() - self.config(enable=True) diff --git a/src/gui/play_button.py b/src/gui/play_button.py deleted file mode 100644 index 56dbaec..0000000 --- a/src/gui/play_button.py +++ /dev/null @@ -1,122 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Play_button class. - -Created on 18/08/2018. -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from game.util import Game -from gui.button import Button - - -class PlayButton(Button): - """ - Create a button displayed in the main menu to start a new game. - """ - - DEFAULT_KWARGS = { - "background_anchor": (0, -0.05), - "background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button.png" - ), - "on_hover_background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button_hover.png" - ), - "on_click_background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button_click.png" - ), - "on_middle_click_background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button_middle_click.png" - ), - "on_right_click_background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button_right_click.png" - ), - "disable_background_image": os.path.join( - GUI_IMAGE_PATH, "play button {}", "play_button_disable.png" - ), - } - - def __init__(self, activity, pos, game_id, **kwargs): - """ - Initialize a new Play_button object. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the button in a (x, y) tuple where - x and y are integers. - - :type game_id: int - :param game_id: The game to launch when clicked (0=Pyoro, 1=Pyoro 2). - - background_image, on_hover_background_image, on_click_background_image, - on_middle_click_background_image, on_right_click_background_image and - disable_background_image can be defined. - """ - - PlayButton.update_default_kwargs(kwargs) - self.game_id = game_id - Button.__init__(self, activity, pos, **kwargs) - if self.kwargs["enable"]: - self.config( - text=f"High Score: {Game.options.get('high score', [0, 0])[game_id]}" - ) - - def load_background_images(self): - """ - Load backgrounds by stretching the images associated to the give - game_id. - """ - - back_names = ( - "background_image", - "on_hover_background_image", - "on_click_background_image", - "on_middle_click_background_image", - "on_right_click_background_image", - "disable_background_image", - ) - for back_name in back_names: - if self.kwargs[back_name]: - if "{}" in self.kwargs[back_name]: - self.kwargs[back_name] = self.kwargs[back_name].format( - self.game_id + 1 - ) - Button.load_background_images(self) - - def on_end_click(self): - """ - Launch the game. - """ - - if self.clicked: - self.clicked = False - if self.kwargs["on_click_fct"]: - self.kwargs["on_click_fct"]( - self.game_id, - *self.kwargs["on_click_args"], - **self.kwargs["on_click_kwargs"], - ) diff --git a/src/gui/setting_bar.py b/src/gui/setting_bar.py deleted file mode 100644 index c4f6254..0000000 --- a/src/gui/setting_bar.py +++ /dev/null @@ -1,371 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a SettingBar class. - -Created on 20/08/2018. -""" - -import os -from pygame.locals import MOUSEMOTION - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from gui.eventable_widget import EventableWidget -from gui.image_transformer import stretch_image - - -class SettingBar(EventableWidget): - """ - Create a widget allowing the player to choose an approximate value - within [0; 1]. - """ - - DEFAULT_KWARGS = { - "line_thickness": 16, - "cursor_width": 16, - "line_image_border_size": 4, - "cursor_image_border_size": 4, - "value": 0, - "line_image": os.path.join(GUI_IMAGE_PATH, "setting bar", "line.png"), - "on_hover_line_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "line_hover.png" - ), - "on_click_line_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "line_click.png" - ), - "on_middle_click_line_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "line_middle_click.png" - ), - "on_right_click_line_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "line_right_click.png" - ), - "disable_line_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "line_disable.png" - ), - "cursor_image": os.path.join(GUI_IMAGE_PATH, "setting bar", "cursor.png"), - "on_hover_cursor_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "cursor_hover.png" - ), - "on_click_cursor_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "cursor_click.png" - ), - "on_middle_click_cursor_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "cursor_middle_click.png" - ), - "on_right_click_cursor_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "cursor_right_click.png" - ), - "disable_cursor_image": os.path.join( - GUI_IMAGE_PATH, "setting bar", "cursor_disable.png" - ), - } - - def __init__(self, activity, pos, **kwargs): - """ - Initialize a new Text objects. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - line_thickness, cursor_width, line_image_border_size, - cursor_image_border_size, value, line_image, on_hover_line_image, - on_click_line_image, on_middle_click_line_image, on_right_click_line_image, - disable_line_image, cursor_image, on_hover_cursor_image, - on_middle_click_cursor_image, on_right_click_cursor_image and - disable_cursor_image can be defined. - """ - - SettingBar.update_default_kwargs(kwargs) - EventableWidget.__init__(self, activity, pos, **kwargs) - - self.line_image = None - self.on_hover_line_image = None - self.on_click_line_image = None - self.on_middle_click_line_image = None - self.on_right_click_line_image = None - self.disable_line_image = None - - self.cursor_image = None - self.on_hover_cursor_image = None - self.on_click_cursor_image = None - self.on_middle_click_cursor_image = None - self.on_right_click_cursor_image = None - self.disable_cursor_image = None - - self.cursor_pos = self.get_cursor_pos_with_value(self.kwargs["value"]) - - self.loadline_images() - self.load_cursor_images() - - def loadline_images(self): - """ - Load the line images and stretch them to the right size. - """ - - image_names = ( - "line_image", - "on_hover_line_image", - "on_click_line_image", - "on_middle_click_line_image", - "on_right_click_line_image", - "disable_line_image", - ) - - for image_name in image_names: - if self.kwargs[image_name]: - image = stretch_image( - self.activity.window.get_image(self.kwargs[image_name]), - (self.kwargs["size"][0], self.kwargs["line_thickness"]), - self.kwargs["line_image_border_size"], - ) - setattr(self, image_name, image) - - def load_cursor_images(self): - """ - Load the cursor images and stretch them to the right size. - """ - - image_names = ( - "cursor_image", - "on_hover_cursor_image", - "on_click_cursor_image", - "on_middle_click_cursor_image", - "on_right_click_cursor_image", - "disable_cursor_image", - ) - - for image_name in image_names: - if self.kwargs[image_name]: - image = stretch_image( - self.activity.window.get_image(self.kwargs[image_name]), - (self.kwargs["cursor_width"], self.kwargs["size"][1]), - self.kwargs["cursor_image_border_size"], - ) - setattr(self, image_name, image) - - def update(self, delta_time): - """ - Draw the line and the cursor. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - self.draw_line() - self.draw_cursor() - - def draw_line(self): - """ - Draw the right line image according to the widget state. - """ - - if not self.kwargs["enable"] and self.disable_line_image: - self.activity.window.draw_image( - self.disable_line_image, self.get_line_pos() - ) - - if self.clicked and self.on_click_line_image: - self.activity.window.draw_image( - self.on_click_line_image, self.get_line_pos() - ) - - elif self.right_clicked and self.on_right_click_line_image: - self.activity.window.draw_image( - self.on_right_click_line_image, self.get_line_pos() - ) - - elif self.middle_clicked and self.on_middle_click_line_image: - self.activity.window.draw_image( - self.on_middle_click_line_image, self.get_line_pos() - ) - - elif self.hovered and self.on_hover_line_image: - self.activity.window.draw_image( - self.on_hover_line_image, self.get_line_pos() - ) - - elif self.line_image: - self.activity.window.draw_image(self.line_image, self.get_line_pos()) - - def draw_cursor(self): - """ - Draw the right line image according to the widget state. - """ - - if not self.kwargs["enable"] and self.disable_cursor_image: - self.activity.window.draw_image( - self.disable_cursor_image, self.get_cursor_pos() - ) - - if self.clicked and self.on_click_cursor_image: - self.activity.window.draw_image( - self.on_click_cursor_image, self.get_cursor_pos() - ) - - elif self.right_clicked and self.on_right_click_cursor_image: - self.activity.window.draw_image( - self.on_right_click_cursor_image, self.get_cursor_pos() - ) - - elif self.middle_clicked and self.on_middle_click_cursor_image: - self.activity.window.draw_image( - self.on_middle_click_cursor_image, self.get_cursor_pos() - ) - - elif self.hovered and self.on_hover_cursor_image: - self.activity.window.draw_image( - self.on_hover_cursor_image, self.get_cursor_pos() - ) - - elif self.cursor_image: - self.activity.window.draw_image(self.cursor_image, self.get_cursor_pos()) - - def get_line_pos(self): - """ - Compute the position of the upper left corner of the line. - - :rtype: list - :returns: A [x, y] list where x and y are both integers. - """ - - real_pos = self.get_real_pos() - return [ - real_pos[0], - real_pos[1] - + self.kwargs["size"][1] // 2 - - self.kwargs["line_thickness"] // 2, - ] - - def get_cursor_pos(self): - """ - Compute the position of the upper left corner of the cursor. - - :rtype: list - :returns: A [x, y] list where x and y are both integers. - """ - - real_pos = self.get_real_pos() - return [self.cursor_pos - self.kwargs["cursor_width"] // 2, real_pos[1]] - - def on_event(self, event): - """ - This method is called on all user events detected by Pygame. - - :type event: pygame.event.Event - :param event: The event to handle. - """ - - EventableWidget.on_event(self, event) - if self.kwargs["enable"] and self.clicked: - if event.type == MOUSEMOTION: - real_pos = self.get_real_pos() - - if ( - event.pos[0] >= real_pos[0] + self.kwargs["cursor_width"] / 2 - and event.pos[0] - <= real_pos[0] - + self.kwargs["size"][0] - - self.kwargs["cursor_width"] / 2 - ): - self.cursor_pos = event.pos[0] - - elif event.pos[0] < real_pos[0] + self.kwargs["cursor_width"] / 2: - self.cursor_pos = real_pos[0] + self.kwargs["cursor_width"] / 2 - - else: - self.cursor_pos = ( - real_pos[0] - + self.kwargs["size"][0] - - self.kwargs["cursor_width"] / 2 - ) - - def get_value(self): - """ - Return a value between 0 and 1 from the position of the cursor on the - line. - - :rtype: float - :returns: The value of the setting bar. - """ - - real_pos = self.get_real_pos() - if self.kwargs["size"][0] - self.kwargs["cursor_width"] != 0: - return (self.cursor_pos - real_pos[0] - self.kwargs["cursor_width"] / 2) / ( - self.kwargs["size"][0] - self.kwargs["cursor_width"] - ) - return 0.5 - - def get_cursor_pos_with_value(self, value): - """ - Return the horizontal position of the upper left corner of the cursor - from a give value. - - :type value: float - :param value: Any float number between 0 and 1. - - :rtype: float - :returns: The absolute x position of the cursor. - """ - - return ( - value * (self.kwargs["size"][0] - self.kwargs["cursor_width"]) - + self.kwargs["cursor_width"] / 2 - + self.get_real_pos()[0] - ) - - def config(self, **kwargs): - """ - Change some kwargs of the widget (cursor_width, cursor_image, ...). - """ - - EventableWidget.config(self, **kwargs) - - if ( - "cursor_image_border_size" in kwargs - or "cursor_width" in kwargs - or "cursor_image" in kwargs - or "on_hover_cursor_image" in kwargs - or "on_click_cursor_image" in kwargs - or "on_middle_click_cursor_image" in kwargs - or "on_right_click_cursor_image" in kwargs - or "disable_cursor_image" in kwargs - ): - self.load_cursor_images() - - if ( - "line_image_border_size" in kwargs - or "line_thickness" in kwargs - or "line_image" in kwargs - or "on_hover_line_image" in kwargs - or "on_click_line_image" in kwargs - or "on_middle_click_line_image" in kwargs - or "on_right_click_line_image" in kwargs - or "disable_line_image" in kwargs - ): - self.loadline_images() - - if "value" in kwargs: - self.cursor_pos = self.get_cursor_pos_with_value(kwargs["value"]) diff --git a/src/gui/splash_activity.py b/src/gui/splash_activity.py deleted file mode 100644 index 87a4013..0000000 --- a/src/gui/splash_activity.py +++ /dev/null @@ -1,221 +0,0 @@ -# -*- coding:utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a splash activity while the game is booting. - -Created on 29/10/2018 -""" - -import os - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import ENTITIES_IMAGE_PATH -from game.update import ( - get_connection_stream, - get_updates, - download_update, - install_update, -) -from game.util import admin_restart, restart, Game - -from gui.activity import Activity -from gui.dialog_menu import DialogMenu -from gui.image_widget import ImageWidget -from gui.text import Text - - -class SplashActivity(Activity): - """ - First activity launch while the game is loading resources. - """ - - def __init__(self, window): - """ - Initialize a SplashActivity object. - - :type window: gui.window.Window - :param window: The parent window of this activity. - """ - - Activity.__init__(self, window) - - def init_widgets(self): - """ - Load a text widget which will be used to display loading messages. - """ - - # Loading text size, position and anchor position - pos = self.layout.get_widget_pos("splash_image") - size = self.layout.get_widget_size("splash_image") - anchor = self.layout.get_widget_anchor("splash_image") - path = os.path.join(ENTITIES_IMAGE_PATH, "pyoro 1", "pyoro_0_normal_1.png") - - # Creating the text widget - self.window.load_image(path) - self.add_widget( - "splash_image", ImageWidget, pos, path, size=size, anchor=anchor - ) - - # Loading text size, position and anchor position - pos = self.layout.get_widget_pos("splash_text") - size = self.layout.get_font_size("splash_text") - anchor = self.layout.get_widget_anchor("splash_text") - - # Creating the text widget - self.add_widget( - "splash_text", Text, pos, "Chargement...", font_size=size, anchor=anchor - ) - - def set_info(self, msg): - """ - Change the message currently displayed and update the screen. - - :type msg: str - :param msg: The messaege to display. - """ - - self.widgets["splash_text"].text = msg - # It's important to update the window otherwise the message will not - # be showed - self.window.update(0) - - def boot(self): - """ - Load game resources, search for updates and display messages about the - current loading. This method should be called only once when the game - start. - """ - - self.set_info("Chargement des images...") - self.window.load_images() - self.set_info("Chargement des sons...") - Game.audio_player.load_audio() - Game.audio_player.sound_volume = Game.options.get("sound volume", 1) - Game.audio_player.music_volume = Game.options.get("music volume", 1) - Game.audio_player.start() - self.set_info("Initialisation des manettes...") - self.window.load_joysticks() - self.set_info("Recherche des mises à jour...") - self.search_for_updates() - - def search_for_updates(self): - """ - Search for updates. If an update is available, display a dialog to ask - the user if he wants to install it. - """ - - ftp_mgr = get_connection_stream() - - if ftp_mgr: - new_versions = get_updates(ftp_mgr) - if new_versions: - - # Loading dialog size, position and anchor position - size = self.layout.get_widget_size("ask_for_update_dialog") - pos = self.layout.get_widget_pos("ask_for_update_dialog") - anchor = self.layout.get_widget_anchor("ask_for_update_dialog") - - self.add_widget( - "ask_for_update_dialog", - DialogMenu, - pos, - "Mettre à jour ?", - self.download_update, - size=size, - anchor=anchor, - positive_args=(ftp_mgr, new_versions), - negative_fct=self.window.set_menu_render, - description="Des mises à jours sont disponibles", - ) - else: - print("[INFO] [SplashActivity.search_for_updates] No update available") - self.window.set_menu_render() - else: - print( - "[INFO] [SplashActivity.search_for_updates] Unable" - + " to detect new updates" - ) - self.window.set_menu_render() - - def download_update(self, ftp_mgr, new_versions): - """ - Begin to download updates and display a loading message. Once finished, - display a dialog about the installation status (success or fail). - """ - - success = True - - for key, new_version in enumerate(new_versions): - self.set_info( - f"Téléchargement de la mise à jour {new_version} ({key}/{len(new_versions)})" - ) - - # If something wrong happen, stop downloading - if not download_update(ftp_mgr, new_version): - # Loading widget size, position and anchor position - size = self.layout.get_widget_size("update_failed_dialog") - pos = self.layout.get_widget_pos("update_failed_dialog") - anchor = self.layout.get_widget_anchor("update_failed_dialog") - - self.add_widget( - "update_failed_dialog", - DialogMenu, - pos, - "La mise à jour a échoué !", - self.window.set_menu_render, - size=size, - anchor=anchor, - description="Réessayez plus tard !", - ) - success = False - - if success: - # Loading widget size, position and anchor position - size = self.layout.get_widget_size("update_success_dialog") - pos = self.layout.get_widget_pos("update_success_dialog") - anchor = self.layout.get_widget_anchor("update_success_dialog") - - self.add_widget( - "update_success_dialog", - DialogMenu, - pos, - "Mises à jour téléchargées !", - admin_restart, - size=size, - anchor=anchor, - positive_args=("update",), - description="Les mises à jour vont être installées", - ) - - self.set_info("Téléchargements terminés !") - else: - self.set_info("Erreur lors du téléchargement !") - - ftp_mgr.disconnect() - - def boot_update(self): - """ - Install an update already downloaded and restart the game. This method - should be used with admin or root privileges. - """ - - self.set_info("Installation des mises à jour...") - install_update() - restart() diff --git a/src/gui/text.py b/src/gui/text.py deleted file mode 100644 index 88c498b..0000000 --- a/src/gui/text.py +++ /dev/null @@ -1,123 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Text class widget. - -Created on 29/03/2018. -""" - -import os -import pygame.freetype - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import GUI_IMAGE_PATH -from gui.widget import Widget - - -class Text(Widget): - """ - Create a widget used to render text. - """ - - DEFAULT_KWARGS = { - "font_size": 20, - "font": os.path.join(GUI_IMAGE_PATH, "font.ttf"), - - "bold": False, - "wide": False, - "italic": False, - "underline": False, - "vertical_mode": False, - - "text_color": (255, 255, 255, 255), - "background_color": None - } - - def __init__(self, activity, pos, text, **kwargs): - """ - Initialize a new Text objects. - - :type activity: gui.activity.Activity - :param activity: The parent activity of this widget. - - :type pos: tuple - :param pos: The default position of the widget in a (x, y) tuple where - x and y are integers. - - :type text: str - :param text: The text to render. - - font, font_size, bold, wide, italic, underline, vertical_mode, - text_color, and background_color can be defined. - """ - - Text.update_default_kwargs(kwargs) - Widget.__init__(self, activity, pos, **kwargs) - self.text = text - self.create_font() - - def create_font(self): - """ - Load the font used to render the text. - """ - - self.font = pygame.freetype.Font(self.kwargs["font"]) - kwargs = dict(self.kwargs) - kwargs.pop("font") - self.config(**kwargs) - - def update(self, delta_time): - """ - Update the text by drawing it on the window. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - surface, rect = self.font.render( - self.text, bgcolor=self.kwargs["background_color"]) - self.kwargs["size"] = [rect.width, rect.height] - self.activity.window.draw_image(surface, self.get_real_pos()) - Widget.update(self, delta_time) - - def config(self, **kwargs): - """ - Change some kwargs of the widget (font, font_size, bold, ...). - """ - - Widget.config(self, **kwargs) - if "font" in kwargs: - self.create_font() - else: - if "font_size" in kwargs: - self.font.size = kwargs["font_size"] - if "bold" in kwargs: - self.font.strong = kwargs["bold"] - if "wide" in kwargs: - self.font.wide = kwargs["wide"] - if "italic" in kwargs: - self.font.oblique = kwargs["italic"] - if "underline" in kwargs: - self.font.underline = kwargs["underline"] - if "vertical_mode" in kwargs: - self.font.vertical = kwargs["vertical_mode"] - if "text_color" in kwargs: - self.font.fgcolor = kwargs["text_color"] diff --git a/src/gui/widget.py b/src/gui/widget.py deleted file mode 100644 index c0f748f..0000000 --- a/src/gui/widget.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a Widget abstract base class for all ui components. - -Created in 28/03/2018. -""" - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - - -class Widget: - """ - Create abstract Widget objects. A widget is a User Interface component - (like buttons, texts, title images, ...). All widgets have default - parameters defined in Widget.DEFAULT_KWARGS (replace Widget by the - widget class you want to get the default keyword arguments handled). - """ - - DEFAULT_KWARGS = { - "size": [1, 1], - "anchor": (-1, -1) - } - - def __init__(self, activity, pos, **kwargs): - """ - Initialize a new Widget object. - - :type activity: gui.activity.Activity - :param activity: The parent activity managing the widget. - - :type pos: tuple - :param pos: A (x, y) tuple where x and y are both integers. - - A size (list) and an anchor (tuple) argument can also be passed to - this method. - """ - - Widget.update_default_kwargs(kwargs) - self.activity = activity - self.pos = pos - self.is_destroyed = False - self.kwargs = dict(kwargs) - - @classmethod - def update_default_kwargs(cls, kwargs): - """ - Add missing optional kwargs with Widget.DEFAULT_KWARGS. - - :type kwargs: dict - :param kwargs: A {kwargsName: value} dictionnary to update with - missing kwargs. - """ - - for key, value in cls.DEFAULT_KWARGS.items(): - if key not in kwargs: - kwargs[key] = value - - def update(self, delta_time): - """ - Update the widget. - Do nothing by default. This method has to be overridden. - - :type delta_time: float - :param delta_time: Time elapsed since the last call of this method (in - seconds). - """ - - def on_event(self, event): - """ - This method is called to handled each user events detected by pygame. - Do nothing by default. This method has to be overridden. - - :type event: pygame.event.Event - :param event: A pygame event. - """ - - def config(self, **kwargs): - """ - Change some kwargs of the widget. - """ - - for key, value in kwargs.items(): - self.kwargs[key] = value - - def get_real_pos(self): - """ - Return the (x, y) position in pixel of the top left corner of the - widget. - - :rtype: list - :returns: A [x, y] list where x and y are both integers. - """ - - pos_x = int(self.pos[0] - self.kwargs["size"][0] - * (self.kwargs["anchor"][0] + 1) / 2) - pos_y = int(self.pos[1] - self.kwargs["size"][1] - * (self.kwargs["anchor"][1] + 1) / 2) - - return [pos_x, pos_y] - - def is_in_widget(self, pos): - """ - Check if a given (x, y) position is within the widget box. - - :type pos: tuple - :param pos: A (x, y) position to check where x and y are both float - numbers. - - :rtype: bool - :returns: True if the position is in the widget box. False otherwise. - """ - - real_pos = self.get_real_pos() - - return pos[0] >= real_pos[0] \ - and pos[0] <= real_pos[0] + self.kwargs["size"][0] \ - and pos[1] >= real_pos[1] \ - and pos[1] <= real_pos[1] + self.kwargs["size"][1] - - def destroy(self): - """ - Destroy the widget. - """ - - self.is_destroyed = True diff --git a/src/gui/window.py b/src/gui/window.py deleted file mode 100644 index 0339dc7..0000000 --- a/src/gui/window.py +++ /dev/null @@ -1,302 +0,0 @@ -# -*- coding: utf-8 -*- - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Provide a class to manage the game window. - -Created on 18/03/2018 -""" - -import os -import pygame -from pygame.locals import QUIT, K_F4, K_RALT, K_LALT - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from game.config import NAME, GUI_IMAGE_PATH -from game.util import get_resource_paths, leave_game, Game, Errors -from gui.level_activity import LevelActivity -from gui.menu_activity import MenuActivity -from gui.splash_activity import SplashActivity - - -class Window: - """ - Main game window, manage the levels and all graphical components. - """ - - def __init__(self): - """ - Initialize a new Window. - """ - - self.images = {} - self.joysticks = [] - self.root_surface = None - self.activity = None - - def create_root_surface(self): - """ - Create a pygame window in fullscreen mode. - """ - - print("[INFO] [Window.create_root_surface] Creating new Pygame window " - + "in fullscreen mode with auto definition") - - icon_path = os.path.join(GUI_IMAGE_PATH, "pyoro_icon.png") - self.root_surface = pygame.display.set_mode( - (0, 0), pygame.FULLSCREEN | pygame.HWSURFACE) - pygame.display.set_caption(NAME) - - if os.path.exists(icon_path): - try: - pygame.display.set_icon(pygame.image.load( - icon_path).convert_alpha()) - except Exception: - print("[FATAL ERROR] [Window.create_root_surface] Unable to load" - + " the window icon") - leave_game(Errors.BAD_RESOURCE) - else: - print("[WARNING] [Window.create_root_surface] Window icon not found") - - def load_joysticks(self): - """ - Initialize all connected joysticks. - """ - - print("[INFO] [Window.initJoysticks] Initializing joystick inputs") - self.joysticks.clear() - for i in range(pygame.joystick.get_count()): - joystick = pygame.joystick.Joystick(i) - joystick.init() - self.joysticks.append(joystick) - - def load_images(self): - """ - Load all images to the RAM. - """ - - print("[INFO] [Window.initImages] Loading images to RAM memory") - self.images["unknown"] = self.create_remplacement_image() - image_paths = get_resource_paths("images") - for image_path in image_paths: - image = os.path.join("data", *image_path) - self.load_image(image) - - def load_image(self, image_path): - """ - Load an image to the RAM. - - :type image_path: str - :param image_path: The filepath of the image to load. - """ - - if os.path.exists(image_path): - self.images[image_path] = pygame.image.load(image_path) - else: - print( - f"[WARNING] [Window.initImage] Unable to find '{image_path}'") - - def create_remplacement_image(self): - """ - Create a replacement image and return it. - - :rtype: pygame.surface.Surface - :returns: A purple and black image. - """ - - print("[INFO] [Window.create_remplacement_image] Creating the replacement image") - image = pygame.Surface((16, 16)) - image.fill((255, 0, 255), (0, 0, 8, 8)) - image.fill((255, 0, 255), (8, 8, 8, 8)) - return image - - def get_image(self, image_path, alpha_channel=True): - """ - Get a copy of a loaded image. If the searched image hasn't been - loaded, return a replacement image. - - :type image_path: str - :param image_path: The filepath to the image to get. - - :type alpha_channel: bool - :param alpha_channel: (Optional) If True, return an image with an - alpha channel that can't be modified; otherwise, return an image - fully opaque but alpha can be modified. - - :rtype: pygame.surface.Surface - :returns: A loaded or replacement image. - """ - - if image_path in self.images: - if alpha_channel: - return self.images[image_path].convert_alpha() - return self.images[image_path].convert() - - print( - f'[WARNING] [Window.get_image] Image "{image_path}"' - + ' not loaded! Using a remplacement image') - - if alpha_channel: - return self.images["unknown"].convert() - return self.images["unknown"].convert_alpha() - - def update_events(self): - """ - Update the activity with the current events in the pygame event buffer. - """ - - for event in pygame.event.get(): - if event.type == QUIT: - self.destroy() - elif event.type == K_F4 and pygame.key.get_mods() in (K_RALT, K_LALT): - self.destroy() - elif self.activity: - self.activity.update_event(event) - - def update(self, delta_time): - """ - Update the current level and all graphical components. - - :type delta_time: float - :param delta_time: Time elapsed since the last update (in seconds). - """ - - self.update_events() - - if self.activity: - self.activity.update(delta_time) - pygame.display.update() - - def destroy(self): - """ - Destroy the current activity and leave the game. - """ - - print("[INFO] [Window.destroy] Destroying window") - self.destroy_activity() - leave_game() - - def destroy_activity(self): - """ - Destroy the current activity and stop sounds and musics. - """ - - if self.activity: - print("[INFO] [Window.destroy_activity] Destroying " - + "the current activity") - self.activity.destroy() - Game.audio_player.stop_audio() - else: - print("[INFO] [Window.destroy_activity] No current activity") - - def set_splash_render(self, boot_option="default"): - """ - Replace the current activity by a new - gui.splashActivity.SplashActivity. - - :type boot_option: str - :param boot_option: (Optional) An option for alternate starts. It can be - "default" (default option) or "update". - - :Example: myWindow.set_splash_render("update") will - show an update installation dialog. - """ - - self.destroy_activity() - print("[INFO] [Window.set_splash_render] Creating splash activity " - + f"with boot_option={boot_option}") - self.activity = SplashActivity(self) - - if boot_option == "update": - self.activity.boot_update() - elif boot_option == "default": - self.activity.boot() - else: - print( - "[FATAL ERROR] [Window.set_splash_render] Unknown boot option '{boot_option}'") - leave_game(Errors.CODE_ERROR) - - def set_menu_render(self): - """ - Replace the current activity by a new - gui.menuActivity.MenuActivity. - """ - - self.destroy_activity() - game_id = Game.options.get("last game", 0) - - if game_id not in (0, 1): - print( - f"[FATAL ERROR] [Window.set_menu_render] Unknown game_id {game_id}") - leave_game(Errors.BAD_RESOURCE) - - print( - f"[INFO] [Window.set_menu_render] Creating menu activity with game_id={game_id}") - self.activity = MenuActivity(self, game_id) - - def set_game_render(self, game_id=0): - """ - Replace the current activity by a new - gui.levelActivity.LevelActivity. - - :type game_id: int - :param game_id: An id representing the game to load. - 0 = Pyoro - 1 = Pyoro 2 - """ - - if game_id in (0, 1): - self.destroy_activity() - print( - f"[INFO] [Window.set_menu_render] Creating level activity with game_id={game_id}") - self.activity = LevelActivity(self, game_id) - else: - print( - f"[FATAL ERROR] [Window.set_game_render] Unknown game_id {game_id}") - leave_game(Errors.CODE_ERROR) - - def draw_image(self, image, pos): - """ - Draw an image on the screen. - - :type image: pygame.surface.Surface - :param image: The surface to draw on the screen. - - :type pos: tuple - :param pos: The (x, y) position of the surface on the screen. - (0, 0) = the top left corner of the screen. - """ - - if self.root_surface: - self.root_surface.blit(image, pos) - else: - print("[WARNING] [Window.draw_image] No root surface to draw on") - - def get_size(self): - """ - Return the size of the game window. - - :rtype: tuple - :returns: A (width, height) tuple. - """ - - if self.root_surface: - return self.root_surface.get_size() - else: - print("[WARNING] [Window.get_size] Non root surface") diff --git a/src/main.py b/src/main.py deleted file mode 100644 index 7ece588..0000000 --- a/src/main.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 - -# This file is part of Pyoro (A Python fan game). -# -# Metawars is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Metawars is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with Metawars. If not, see - -""" -Main module and functions of Pyoro. - -Created on 17/03/2018 -""" - -import os -import logging -import sys -import pygame - -__author__ = "RedbeanGit" -__repo__ = "https://github.com/RedbeanGit/Pyoro" - -from audio.audio_player import AudioPlayer -from game.debug_logger import DebugLogger -from game.mod import Mod -from game.util import Errors, Game, leave_game, load_config -from gui.window import Window - - -def main(): - """ - Main function of the game. Must be called first except for updating. - """ - - logging.info("[main] Starting Pyoro") - - try: - pygame.init() - Game.options = load_config() - Game.audio_player = AudioPlayer() - Game.window = Window() - Game.window.create_root_surface() - Game.window.set_splash_render() - - Mod.load_mods() - Mod.init_mods(Game.window) - loop() - except Exception: - print("[FATAL ERROR] [loop] An unknown error occurred while starting !") - leave_game(Errors.BOOT_ERROR) - - -def update(): - """ - Launch update installation. - """ - - try: - print("[INFO] [main] Starting Debug_logger") - Game.debug_logger = DebugLogger() - print("[INFO] [update] Starting Pyoro v1.1 to update") - - pygame.init() - - Game.window = Window() - Game.window.create_root_surface() - Game.window.set_splash_render("update") - except Exception: - print("[FATAL ERROR] [update] An unknown error" + " occurred while updating!") - leave_game(Errors.UPDATE_ERROR) - - -def loop(): - """ - Create an infinite loop and update game components. - """ - - print("[INFO] [startLoop] Starting new game loop") - clock = pygame.time.Clock() - tick = 0 - total_time = 0 - - while True: - try: - pygame.event.pump() - delta_time = clock.tick() / 1000 - - Game.window.update(delta_time) - Mod.update_mods(Game.window, delta_time) - - tick += 1 - total_time += delta_time - except Exception: - print( - "[FATAL ERROR] [loop] An unknown error " - + f"occurred! tick={tick} total_time=%{total_time}s" - ) - leave_game(Errors.LOOP_ERROR) - - -if __name__ == "__main__": - os.chdir(os.path.dirname(os.path.abspath(sys.argv[0]))) - if len(sys.argv) > 1: - if sys.argv[1] == "update": - update() - else: - print(f"[WARNING] [GLOBAL] unknown argument {sys.argv[1]}") - if len(sys.argv) > 2: - if sys.argv[2] == "update": - update() - else: - print(f"[WARNING] [GLOBAL] unknown argument {sys.argv[2]}") - main() - else: - main() - else: - main()