From 6eeba99520405d92766e9ac025a68fe81df7f428 Mon Sep 17 00:00:00 2001 From: wzc <2747604107@qq.com> Date: Thu, 30 May 2024 14:24:13 +0800 Subject: [PATCH] first commit --- modules/TankGame.py | 147 ++++++ __init__.py => modules/__init__.py | 0 modules/__pycache__/TankGame.cpython-310.pyc | Bin 0 -> 4539 bytes modules/__pycache__/TankGame.cpython-312.pyc | Bin 0 -> 7300 bytes modules/__pycache__/TankGame.cpython-38.pyc | Bin 0 -> 4531 bytes modules/__pycache__/__init__.cpython-310.pyc | Bin 0 -> 151 bytes modules/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 145 bytes modules/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 145 bytes modules/levels/1.lvl | 39 ++ modules/levels/2.lvl | 39 ++ modules/levels/3.lvl | 39 ++ modules/levels/4.lvl | 39 ++ modules/levels/5.lvl | 39 ++ modules/sprites/__init__.py | 7 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 670 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 684 bytes .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 664 bytes .../__pycache__/bullet.cpython-310.pyc | Bin 0 -> 1350 bytes .../__pycache__/bullet.cpython-312.pyc | Bin 0 -> 2675 bytes .../sprites/__pycache__/bullet.cpython-38.pyc | Bin 0 -> 1338 bytes .../sprites/__pycache__/foods.cpython-310.pyc | Bin 0 -> 1209 bytes .../sprites/__pycache__/foods.cpython-312.pyc | Bin 0 -> 1730 bytes .../sprites/__pycache__/foods.cpython-38.pyc | Bin 0 -> 1201 bytes .../__pycache__/groups.cpython-310.pyc | Bin 0 -> 5068 bytes .../__pycache__/groups.cpython-312.pyc | Bin 0 -> 9970 bytes .../sprites/__pycache__/groups.cpython-38.pyc | Bin 0 -> 5333 bytes .../sprites/__pycache__/home.cpython-310.pyc | Bin 0 -> 1128 bytes .../sprites/__pycache__/home.cpython-312.pyc | Bin 0 -> 1554 bytes .../sprites/__pycache__/home.cpython-38.pyc | Bin 0 -> 1114 bytes .../__pycache__/scenes.cpython-310.pyc | Bin 0 -> 2436 bytes .../__pycache__/scenes.cpython-312.pyc | Bin 0 -> 3595 bytes .../sprites/__pycache__/scenes.cpython-38.pyc | Bin 0 -> 2550 bytes .../sprites/__pycache__/tanks.cpython-310.pyc | Bin 0 -> 12074 bytes .../sprites/__pycache__/tanks.cpython-312.pyc | Bin 0 -> 23177 bytes .../sprites/__pycache__/tanks.cpython-38.pyc | Bin 0 -> 12060 bytes modules/sprites/bullet.py | 36 ++ modules/sprites/foods.py | 30 ++ modules/sprites/groups.py | 158 ++++++ modules/sprites/home.py | 25 + modules/sprites/scenes.py | 66 +++ modules/sprites/tanks.py | 466 ++++++++++++++++++ modules/views/AbstractView.py | 45 ++ modules/views/GameLevelView.py | 432 ++++++++++++++++ modules/views/GameOverView.py | 95 ++++ modules/views/GameStartView.py | 92 ++++ modules/views/SwitchLevelView.py | 80 +++ modules/views/ViewManager.py | 30 ++ modules/views/__init__.py | 6 + .../__pycache__/AbstractView.cpython-310.pyc | Bin 0 -> 1782 bytes .../__pycache__/AbstractView.cpython-312.pyc | Bin 0 -> 2347 bytes .../__pycache__/AbstractView.cpython-38.pyc | Bin 0 -> 1796 bytes .../__pycache__/GameLevelView.cpython-310.pyc | Bin 0 -> 11913 bytes .../__pycache__/GameLevelView.cpython-312.pyc | Bin 0 -> 25977 bytes .../__pycache__/GameLevelView.cpython-38.pyc | Bin 0 -> 12150 bytes .../__pycache__/GameOverView.cpython-310.pyc | Bin 0 -> 3624 bytes .../__pycache__/GameOverView.cpython-312.pyc | Bin 0 -> 7958 bytes .../__pycache__/GameOverView.cpython-38.pyc | Bin 0 -> 3612 bytes .../__pycache__/GameStartView.cpython-310.pyc | Bin 0 -> 3664 bytes .../__pycache__/GameStartView.cpython-312.pyc | Bin 0 -> 8017 bytes .../__pycache__/GameStartView.cpython-38.pyc | Bin 0 -> 3652 bytes .../SwitchLevelView.cpython-310.pyc | Bin 0 -> 3233 bytes .../SwitchLevelView.cpython-312.pyc | Bin 0 -> 6810 bytes .../SwitchLevelView.cpython-38.pyc | Bin 0 -> 3222 bytes .../__pycache__/ViewManager.cpython-310.pyc | Bin 0 -> 1210 bytes .../__pycache__/ViewManager.cpython-312.pyc | Bin 0 -> 1766 bytes .../__pycache__/ViewManager.cpython-38.pyc | Bin 0 -> 1152 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 543 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 545 bytes .../views/__pycache__/__init__.cpython-38.pyc | Bin 0 -> 537 bytes 69 files changed, 1910 insertions(+) create mode 100644 modules/TankGame.py rename __init__.py => modules/__init__.py (100%) create mode 100644 modules/__pycache__/TankGame.cpython-310.pyc create mode 100644 modules/__pycache__/TankGame.cpython-312.pyc create mode 100644 modules/__pycache__/TankGame.cpython-38.pyc create mode 100644 modules/__pycache__/__init__.cpython-310.pyc create mode 100644 modules/__pycache__/__init__.cpython-312.pyc create mode 100644 modules/__pycache__/__init__.cpython-38.pyc create mode 100644 modules/levels/1.lvl create mode 100644 modules/levels/2.lvl create mode 100644 modules/levels/3.lvl create mode 100644 modules/levels/4.lvl create mode 100644 modules/levels/5.lvl create mode 100644 modules/sprites/__init__.py create mode 100644 modules/sprites/__pycache__/__init__.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/__init__.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/__init__.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/bullet.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/bullet.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/bullet.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/foods.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/foods.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/foods.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/groups.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/groups.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/groups.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/home.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/home.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/home.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/scenes.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/scenes.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/scenes.cpython-38.pyc create mode 100644 modules/sprites/__pycache__/tanks.cpython-310.pyc create mode 100644 modules/sprites/__pycache__/tanks.cpython-312.pyc create mode 100644 modules/sprites/__pycache__/tanks.cpython-38.pyc create mode 100644 modules/sprites/bullet.py create mode 100644 modules/sprites/foods.py create mode 100644 modules/sprites/groups.py create mode 100644 modules/sprites/home.py create mode 100644 modules/sprites/scenes.py create mode 100644 modules/sprites/tanks.py create mode 100644 modules/views/AbstractView.py create mode 100644 modules/views/GameLevelView.py create mode 100644 modules/views/GameOverView.py create mode 100644 modules/views/GameStartView.py create mode 100644 modules/views/SwitchLevelView.py create mode 100644 modules/views/ViewManager.py create mode 100644 modules/views/__init__.py create mode 100644 modules/views/__pycache__/AbstractView.cpython-310.pyc create mode 100644 modules/views/__pycache__/AbstractView.cpython-312.pyc create mode 100644 modules/views/__pycache__/AbstractView.cpython-38.pyc create mode 100644 modules/views/__pycache__/GameLevelView.cpython-310.pyc create mode 100644 modules/views/__pycache__/GameLevelView.cpython-312.pyc create mode 100644 modules/views/__pycache__/GameLevelView.cpython-38.pyc create mode 100644 modules/views/__pycache__/GameOverView.cpython-310.pyc create mode 100644 modules/views/__pycache__/GameOverView.cpython-312.pyc create mode 100644 modules/views/__pycache__/GameOverView.cpython-38.pyc create mode 100644 modules/views/__pycache__/GameStartView.cpython-310.pyc create mode 100644 modules/views/__pycache__/GameStartView.cpython-312.pyc create mode 100644 modules/views/__pycache__/GameStartView.cpython-38.pyc create mode 100644 modules/views/__pycache__/SwitchLevelView.cpython-310.pyc create mode 100644 modules/views/__pycache__/SwitchLevelView.cpython-312.pyc create mode 100644 modules/views/__pycache__/SwitchLevelView.cpython-38.pyc create mode 100644 modules/views/__pycache__/ViewManager.cpython-310.pyc create mode 100644 modules/views/__pycache__/ViewManager.cpython-312.pyc create mode 100644 modules/views/__pycache__/ViewManager.cpython-38.pyc create mode 100644 modules/views/__pycache__/__init__.cpython-310.pyc create mode 100644 modules/views/__pycache__/__init__.cpython-312.pyc create mode 100644 modules/views/__pycache__/__init__.cpython-38.pyc diff --git a/modules/TankGame.py b/modules/TankGame.py new file mode 100644 index 0000000..92f9013 --- /dev/null +++ b/modules/TankGame.py @@ -0,0 +1,147 @@ +import threading + +import pygame +import sys +import os +import random + + +class TankGame(object): + _instance_lock = threading.Lock() + _init_flag = False + + def __init__(self, config=None): + if not self._init_flag: + if not config: + raise Exception('Config was not specified while initializing game instance!') + + self.__screen = None + self.__levels = None + self.__sounds = {} + self.__multiplayer_mode = False + self.__config = config + self.__is_win = False + self.__quit_game_flag = False + self._init_flag = True + self.__last_level = None + self.__start() + + def __new__(cls, *args, **kwargs): + if not hasattr(TankGame, "_instance"): + with TankGame._instance_lock: + if not hasattr(TankGame, "_instance"): + TankGame._instance = object.__new__(cls) + return TankGame._instance + + @property + def sounds(self): + return self.__sounds + + @property + def screen(self): + return self.__screen + + @property + def quit_game_flag(self): + return self.__quit_game_flag + + @quit_game_flag.setter + def quit_game_flag(self, quit_game_flag): + self.__quit_game_flag = quit_game_flag + + @property + def config(self): + return self.__config + + @property + def level(self): + return self.__level + + @property + def level_file(self): + + weights = [1] * len(self.__levels) + if self.__last_level is not None: + weights[self.__last_level] = 0 + + self.__last_level = random.choices(range(len(self.__levels)), weights=weights)[0] + return self.__levels[self.__last_level] + # return self.__levels[self.__level] + + @property + def is_win(self): + return self.__is_win + + @is_win.setter + def is_win(self, is_win): + self.__is_win = is_win + + @property + def multiplayer_mode(self): + return self.__multiplayer_mode + + @multiplayer_mode.setter + def multiplayer_mode(self, multiplayer_mode): + self.__multiplayer_mode = multiplayer_mode + + def init_game_window(self, size_tuple=None): + if size_tuple is None: + self.__screen = pygame.display.set_mode( + (self.config.WIDTH, self.config.HEIGHT) + ) + else: + self.__screen = pygame.display.set_mode(size_tuple) + + def __init_sounds(self): + for sound, file in self.config.AUDIO_PATHS.items(): + self.__sounds[sound] = pygame.mixer.Sound(file) + self.__sounds[sound].set_volume(1) + + def __load_level_templates(self): + self.__levels = [ + os.path.join( + self.config.LEVELFILEDIR, + filename + ) for filename in sorted(os.listdir(self.config.LEVELFILEDIR)) + ] + + def __enter_loop(self): + from modules.views import ViewManager + ViewManager().show('GameStart') + level = 0 + while True: + self.__level = level + ViewManager().show('SwitchLevel') + ViewManager().show('GameLevelView') + if not self.is_win: + ViewManager().show('GameOver') + level = 0 + else: + level += 1 + if self.quit_game_flag: + break + + + # while True: + # for level in range(len(self.__levels)): + # self.__level = level + # ViewManager().show('SwitchLevel') + # ViewManager().show('GameLevelView') + # if not self.is_win: + # break + # + # ViewManager().show('GameOver') + # if self.quit_game_flag: + # break + + def __init_game(self): + pygame.init() + pygame.mixer.init() + pygame.display.set_caption(self.config.TITLE) + self.init_game_window() + self.__init_sounds() + self.__load_level_templates() + + def __start(self): + self.__init_game() + self.__enter_loop() diff --git a/__init__.py b/modules/__init__.py similarity index 100% rename from __init__.py rename to modules/__init__.py diff --git a/modules/__pycache__/TankGame.cpython-310.pyc b/modules/__pycache__/TankGame.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dad2021740ec031b91d4b28733f69ef390785fe4 GIT binary patch literal 4539 zcma)9TW=f36`t7}mlP#aS4VYh%g(I~S~YH3v@ld7t|i+-Rk^5?xLqh%Y&auo=@m)O ztjw68UMd4kABrOXKzj6F=}*|#0tNDHv=2pN_dByBManX25_9IdXU_ecX-!U+7=C}B z)zQB$F!m3cjQ$)L(~5Rkc_Yfmb8zZ6Bf9Fq&?x5*E0Q6Xc>5qF{7gH|y5&sk9(_&9bo~w zJr3xZalt@e*jRzK0E<0#TsmPKvn|uA&Sv-KomO)(>O}vZrrRd)j=#)bQ(2l^4i_)>O@uw=|s4jMD?t=_H|9R)40{lro#bqVW?|L z%JHQ{K9PwYKh-*D3Y}dV`EdUrN#k}BJ(VilZwWbezGmniTZ(nqiJRHt2#UuCAdbk+ zDV!hKN+O+xhLEf>vJB=_TD3Aq%Van6@@t+mRe>V@bMwy4ozJyYdgr#-2jeg_ES$cL6-^aG!gY$H)I=?!4$u55FCJ zSL66*@FSP;(H@}buK-eJjKk8)DQ{SRyTVUbE~jv%9y{SF58a1Qy@UUejT5}#Zn4)_ zZZKW#a1K-9?2l;qxvI696~RNU{;HQ1_97jnsZwOE+0<|=Oj@-^nb-QNA!}(?2*alA zgrSeoQ(fDQe_GFFXKpp)K~DZ&tY~VE&w|DRgIU&OB|b@O}D>nDVUdh2cf{-W%^x zmk1&06?eEaCLUhD!Faja&SWhWA_?@-cqmjiKiSWd##Z zOt3JVscTrPTDk156K-;g5!KP!Cul}`CF?Difv}2%;~ZfrWFz)7+B_qv+$rA*`Iv7T zZ$Iy*%r#rT9NslGl$O~TyNV2ha-xaPn-~aQ=P8*OV)Gn3L=0{qHXm>`gBWaPD=f7e zPU;R$9q}F)_FpYwEmCAg>~5HIi!f3|#N)MGw=S|`n~(x zCYtpr4@x@j$}l}>C-MvfS;dqBCfgzpi&p0$NHr#gEJq>y)r`|UmEqabV|ugk>Cnl@ zRKcEM_JpmnFXwlxLw;zHQysfK!*avx@fA9Sevus)1lZ>6u}8%YGMD-YII4cm-o)+C zSJxkezq`GCe=Bq2RPJka1N)h~AAc=X;BHYGFo^>ELNZTU$-%y?+9vP?uE_+MLtb=7 z2Ek-MTj$9l1X4|wHpgf1cV2cEh9)$2aEy0yFiIdK1N|YupV=-7KVd!dDa#*Q-x!6T zAl$5?0R9GrpW)Kp9797^L&1XbuD$|Lhj_l6I7F->tI3h{_=)wc^%xbY;iT$jRtxF5 z9i@Aj(`d!bTw>*owJ+8-?yhgFt*-wb)seOQN#+y(O_FR6#x9YV4PKq^Yu zK0k!v_4pAx#tVpyP{34+tVb2P-CuWUy+8KMm^B=#@y%C-!B)*y_Y-ZEu4L?O>8N%#e-;K20Aykt%lz zFPQAttIJQYtram8IC`(uQ6FGvqN}=&QQrZ~0Y!#+*80m~D4QwD^`zBmCpcj0+%iW+ z3(b4z%LaPfN7ak9e|P6cM1K11n4rlYhJwC@Ny?5nJ!D|W)^KEM+=koei}ScZC-CI) z`+bpm5?~$#OUB~^hoX=&iT|g-988eA*CO+Z>BqwD_3e!{^>gfI3nLE&6TWgc&#sQF zpJ!(y9%3?=vB`;k1fYQV7hu z3|raU2$e&0+31_-Q~~Ewj8fh_kG>^pDLNY}M@w^5tmPY_% zkfz`@C4xz@q&2lh;4Xpt1WYMHkFXKz9csnAWvC$4zXtHZp~Fj-U$F`$ZlO@3=Jfl) z+$x=}(O${+ecwg9T=osVYC&z#eK!CyTR+t%fT@pZjovus(0SBk{z@*lTjT?|fiT}9 J^YHnc{XdD++64dr literal 0 HcmV?d00001 diff --git a/modules/__pycache__/TankGame.cpython-312.pyc b/modules/__pycache__/TankGame.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e113caa41ea40bdbb65057977d86ec9ccc629c5b GIT binary patch literal 7300 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 B(SiT~ literal 0 HcmV?d00001 diff --git a/modules/__pycache__/__init__.cpython-310.pyc b/modules/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d36ddcfd638b9f20a9bcd0836d9c4b77397060ef GIT binary patch literal 151 zcmd1j<>g`kf>Xl9i6Hthh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wt*(xTqIJKxa z#xW%~GcU8aq$sf@zbM8fwK%&ZzaXY0F)zD3u_z`tKczG$wKyg|9;m1!K3=b&@)m~; PMAQysW-$|xU||3Na;+oF literal 0 HcmV?d00001 diff --git a/modules/__pycache__/__init__.cpython-312.pyc b/modules/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..701af12f97051ddb86aea5e1cdef0bdd43eb90a2 GIT binary patch literal 145 zcmX@j%ge<81S$+=DIoeWh(HIQS%4zb87dhx8U0o=6fpsLpFwJV8Ms)*6jUZ>Bo^fY z>4KvCtkmR^n3BZ2?DE8-nB4r7(wx-dnE3e2yv&mLc)fzkUmP|NQM)2mpaG0PTnu7- MWM*V!EMf+-0HPxzJ^%m! literal 0 HcmV?d00001 diff --git a/modules/__pycache__/__init__.cpython-38.pyc b/modules/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..843167ce103a3b6b0c7195c4631a5fe93a397c40 GIT binary patch literal 145 zcmWIL<>g`kf>Xl9i6Hthh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6wv*(xTqIJKxa zCMPp5y(+aTBQwS&wK%&ZzaXY0F)zD3u_z`tKczG$wKyg|J~J<~BtBlRpz;=n4Mfxq KWZq{WW&i+*4I-KV literal 0 HcmV?d00001 diff --git a/modules/levels/1.lvl b/modules/levels/1.lvl new file mode 100644 index 0000000..732bbda --- /dev/null +++ b/modules/levels/1.lvl @@ -0,0 +1,39 @@ +############################################## +# Explain: # +# Grid: 26 * 26 # +# Grid SIZE: 24 * 24 pixels # +# S: Space B: Brick I: Iron # +# R: River1/2 C: Ice T: Tree # +############################################## +%TOTALENEMYNUM:1 +%MAXENEMYNUM:6 +%HOMEPOS:12,24 +%HOMEAROUNDPOS:11,23 12,23 13,23 14,23 11,24 14,24 11,25 14,25 +%PLAYERTANKPOS:8,24 16,24 +%ENEMYTANKPOS:0,0 12,0 24,0 +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S B B B B S S S S S S S S S S B B B B S S S S +I I S S B B B B S S S S S S S S S S B B B B S S I I +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S S S S S S S B B B B B B S S S S S S S S S S +S S B B S S B B S S B B B B B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S B B B B S S S B B S S B B S S +S S S S S S S S S S S B S S B S S S S S S S S S S S +S S S S S S S S S S S B S S B S S S S S S S S S S S \ No newline at end of file diff --git a/modules/levels/2.lvl b/modules/levels/2.lvl new file mode 100644 index 0000000..65277c2 --- /dev/null +++ b/modules/levels/2.lvl @@ -0,0 +1,39 @@ +############################################## +# Explain: # +# Grid: 26 * 26 # +# Grid SIZE: 24 * 24 pixels # +# S: Space B: Brick I: Iron # +# R: River1/2 C: Ice T: Tree # +############################################## +%TOTALENEMYNUM:45 +%MAXENEMYNUM:9 +%HOMEPOS:12,24 +%HOMEAROUNDPOS:11,23 12,23 13,23 14,23 11,24 14,24 11,25 14,25 +%PLAYERTANKPOS:8,24 16,24 +%ENEMYTANKPOS:0,0 12,0 24,0 +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S S S S S S S S S R R R R R R S S S S S S S S S S +S S S S S S S S S S R R R R R R S S S S S S S S S S +S S S S T T T T S S S S S S S S S S T T T T S S S S +I I S S T T T T S S S S S S S S S S T T T T S S I I +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S S S S S S S B B B B B B S S S S S S S S S S +S S B B S S B B S S B B B B B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S B B B B S S S B B S S B B S S +S S S S S S S S S S S B S S B S S S S S S S S S S S +S S S S S S S S S S S B S S B S S S S S S S S S S S \ No newline at end of file diff --git a/modules/levels/3.lvl b/modules/levels/3.lvl new file mode 100644 index 0000000..139e10f --- /dev/null +++ b/modules/levels/3.lvl @@ -0,0 +1,39 @@ +############################################## +# Explain: # +# Grid: 26 * 26 # +# Grid SIZE: 24 * 24 pixels # +# S: Space B: Brick I: Iron # +# R: River1/2 C: Ice T: Tree # +############################################## +%TOTALENEMYNUM:60 +%MAXENEMYNUM:12 +%HOMEPOS:12,24 +%HOMEAROUNDPOS:11,23 12,23 13,23 14,23 11,24 14,24 11,25 14,25 +%PLAYERTANKPOS:8,24 16,24 +%ENEMYTANKPOS:0,0 12,0 24,0 +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B I I B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S S S S S S S S S R R R R R R S S S S S S S S S S +S S S S S S S S S S R R R R R R S S S S S S S S S S +S S S S C C C C S S S S S S S S S S C C C C S S S S +I I S S C C C C S S S S S S S S S S C C C C S S I I +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S S S S S S S B B B B B B S S S S S S S S S S +S S B B S S B B S S B B B B B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S B B B B S S S B B S S B B S S +S S S S S S S S S S S B S S B S S S S S S S S S S S +S S S S S S S S S S S B S S B S S S S S S S S S S S \ No newline at end of file diff --git a/modules/levels/4.lvl b/modules/levels/4.lvl new file mode 100644 index 0000000..bd1a454 --- /dev/null +++ b/modules/levels/4.lvl @@ -0,0 +1,39 @@ +############################################## +# Explain: # +# Grid: 26 * 26 # +# Grid SIZE: 24 * 24 pixels # +# S: Space B: Brick I: Iron # +# R: River1/2 C: Ice T: Tree # +############################################## +%TOTALENEMYNUM:60 +%MAXENEMYNUM:12 +%HOMEPOS:12,24 +%HOMEAROUNDPOS:11,23 12,23 13,23 14,23 11,24 14,24 11,25 14,25 +%PLAYERTANKPOS:8,24 16,24 +%ENEMYTANKPOS:0,0 12,0 24,0 +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S T T S S T T S S T T S S T T S S T T S S T T S S +S S T T S S T T S S T T S S T T S S T T S S T T S S +S S T T S S T T S S T T S S T T S S T T S S T T S S +S S T T S S T T S S T T S S T T S S T T S S T T S S +S S T T S S T T S S T T I I T T S S T T S S T T S S +S S T T S S T T S S T T I I T T S S T T S S T T S S +S S T T S S T T S S T T S S T T S S T T S S T T S S +T T T T T T T T T T T T T T T T T T T T T T T T T T +T T T T T T T T T T T T T T T T T T T T T T T T T T +R R R R R R R R R R R R R R R R R R R R R R R R R R +R R R R R R R R R R R R R R R R R R R R R R R R R R +S S S S C C C C S S S S S S S S S S C C C C S S S S +S S S S C C C C S S S S S S S S S S C C C C S S S S +S S S S S S S S S S B B S S B B S S S S S S S S S S +S S S S S S S S S S B B B B B B S S S S S S S S S S +S S B B S S B B S S B B B B B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S B B S S B B S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S B B B B S S S B B S S B B S S +S S S S S S S S S S S B S S B S S S S S S S S S S S +S S S S S S S S S S S B S S B S S S S S S S S S S S \ No newline at end of file diff --git a/modules/levels/5.lvl b/modules/levels/5.lvl new file mode 100644 index 0000000..3c2797d --- /dev/null +++ b/modules/levels/5.lvl @@ -0,0 +1,39 @@ +############################################## +# Explain: # +# Grid: 26 * 26 # +# Grid SIZE: 24 * 24 pixels # +# S: Space B: Brick I: Iron # +# R: River1/2 C: Ice T: Tree # +############################################## +%TOTALENEMYNUM:60 +%MAXENEMYNUM:12 +%HOMEPOS:12,24 +%HOMEAROUNDPOS:11,23 12,23 13,23 14,23 11,24 14,24 11,25 14,25 +%PLAYERTANKPOS:8,24 16,24 +%ENEMYTANKPOS:0,0 12,0 24,0 +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +S S R R S S R R S S R R S S R R S S R R S S R R S S +C C C C C C C C C C C C C C C C C C C C C C C C C C +C C C C C C C C C C C C C C C C C C C C C C C C C C +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S S S S S S S S S S S S S S S S S S S S S S S +S S S S T T T T S S S S R R S S S S T T T T S S S S +S S S S T T T T S S S S R R S S S S T T T T S S S S +S S S S S S S S S S C C R R C C S S S S S S S S S S +S S S S S S S S S S C C C C C C S S S S S S S S S S +S S C C S S C C S S C C C C C C S S C C S S C C S S +S S C C S S C C S S C C S S C C S S C C S S C C S S +S S C C S S C C S S C C S S C C S S C C S S C C S S +S S C C S S C C S S C C S S C C S S C C S S C C S S +S S C C S S C C S S S S S S S S S S C C S S C C S S +S S B B S S B B S S S S S S S S S S B B S S B B S S +S S B B S S B B S S S B B B B S S S B B S S B B S S +C C C C C C C C C C C B S S B C C C C C C C C C C C +C C C C C C C C C C C B S S B C C C C C C C C C C C \ No newline at end of file diff --git a/modules/sprites/__init__.py b/modules/sprites/__init__.py new file mode 100644 index 0000000..8f3128c --- /dev/null +++ b/modules/sprites/__init__.py @@ -0,0 +1,7 @@ +from modules.sprites.bullet import Bullet +from modules.sprites.foods import Foods +from modules.sprites.home import Home +from modules.sprites.scenes import SceneFactory, SceneElement, Ice, Brick, Tree, River, Iron +from modules.sprites.tanks import TankFactory, EnemyTank, PlayerTank, Tank +from modules.sprites.groups import SceneElementsGroup, EntityGroup + diff --git a/modules/sprites/__pycache__/__init__.cpython-310.pyc b/modules/sprites/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4b755a7b432ea7589088dda350d962c0ddc37e0 GIT binary patch literal 670 zcmZWn%Z}496t$bANtGLb!!0+wP4 zE3xuAzGFr5%Xel4cf<8jDQP{6ZnUnAC*fNSvWQ)Fx09{BsdiRlcTyWALAKTfw>#;g zH8#7w3-3{S@uB%9(S^6D+ah%7ebw&&eLLE;5;~f3eFFJ*4dhd0vn9H zi9>>zAR!nL(5+(X!JT!qK8nGN3UY!Af{BOoE?+31!6{YDJUlR55GVM(e*LWcXe65Q zRSiws7>kuZ|MFUzz14@3`h2gjJf$j6$5C##zSwTJSBK6e&;PnF{J+Nx?I~j!&-hdR HgfICYRm{C< literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/__init__.cpython-312.pyc b/modules/sprites/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7b852d5468ed1bc2aef1ffc684a3aade374b95e4 GIT binary patch literal 684 zcmZWnzi-n(6h6mx?8Hg)gQNpuLkM~4j4H$sHHCISh;}+zii~}wruS^?`2zBv(TTr- zzl8t>j^jiX zShv+u3J|%{_DLeNyTB~D(#|;wQ@qVS3e?UC7J2CC;5^Q+?(X)MxqzBZbpMTvYk>`S z2*Zw^HiO#M)k`ear4E+4%2eGHufu)44@J6`qB^Kb%#_*RHSb2-#L)Bm;sr%PhqT#! z?b4(}m!zGZ6$P%aYee)2e1aYUeM}4p1_pK~Difu`AsO}vMg(KB?o4@40V|x4V`|_F zyD`XapB)`WWu08c2xc#__#hG$QR7cBMs19!%^$5+S)QrY>Y%J|{pbJH7x>6DGJhMZ n9vk>;Tb8w9;f6ikuqRs<{bbR17H!$-4|cj`i*Ia!4~_316gtXY literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/__init__.cpython-38.pyc b/modules/sprites/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ba41f0ce01a604ac9d308fa89600dcaa3ebdfc75 GIT binary patch literal 664 zcmZWnOK#gR6eKOlk}WCz2R%SH+T;L55fn+CHk%-5k_{oiP%SnQ%qJO-bPMH1y-JS2 zZC1TPSK(7!pol4GG{bq~<50Rw(;;)?X{L*kGxkj4|Iu^ele@KXP_mLM23&AXyr+8L z39sXx@*xmG$9>g@P=pYP2nJ#RLotL{#E^&tQjvBwfjWYb7{OSKVIn3l71M6MuVye8 zb6ALl)8P%vqCc)P%ed{I?Ua(nvEZUxhHn~~LT3!@u(_p(-OC>?p#(I}) zX@fJY)*I{JqIBY0^;4qtFR`gJ-^RB^z4`aim?NG(9yUk8WSo=362Ox4i3BAQ$USls+c(V&2UDX;P2`Ahx|@U z)VZqa`$zfsQ01Sc-k4^aQ;%N-=KDnX{wVU*s;VoqTAgfL8-09rPu+jVG;KKHbiL>A F_zR9+yQlyF literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/bullet.cpython-310.pyc b/modules/sprites/__pycache__/bullet.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..700399b75f6c0451bdf64a606314bcbbd9120aee GIT binary patch literal 1350 zcmZWp&2Hm15GE-~mKEneyUq4*7X|ubpa{@gQ53}{8*dUIb&E|F1q1_xA~KF-S#n7^ zi!5~80Q(yDF)z|XAA#4N@(R7QGm^7#Q33PK42K+&-wai(t_B3YKetWv2Pfn&be2CD zBhNw17XXq-nvsyS$q|uEI=4hRilj7U@0`$)^o(@*JMa=C z6x$UCd#7>%A5|XUV@cqQwBP;6dXt-BG*;F#6P=Wx&l>Fuk>p7!gmsf~G*p&nMI`Ok z!Ryo0-nlsWdH<*EKn zF2AAKD+W#?c zJJ2L;0s14p@Y?^01>miWI27IKYuxxAq1(}qKv_O6u2n-^2mG2Q>i`LQ3&Y+;QI^G6 zZ`5-$bqUqhSWmqUBX?APf{T#U20lmY83594FypuEQ=oT6NcLCt{%NxvtI2v$1p$c)bkh1U&NVtxG-W_R7X(&2gnRfpES5lyMWPNPL!OmjH8 znNF~aMoE_GFJavswQV8dEHXxjr5k(=v1cI01MukvU1J~4j*GkOrN*N|=fPvi;Ss@O z34~}G2JDUyzfYsAiPYUvv!XGvU0rM$t1Nriwx;kKi0Ya`1{U_1!9R#k0_Jb-cp68$ iT;oqpWBX`4UOl>0f;tl>vHp+Ed49rzFRsGauJbRmi#X2! literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/bullet.cpython-312.pyc b/modules/sprites/__pycache__/bullet.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..61168cbd4e38a558b4a557e6091f56d19c0b0820 GIT binary patch literal 2675 zcmb7FO-vg{6rQoy&Khh?6H^kBH2gGy6=`xv(nzR6Nn{G9)U5(Z6AL;uy9?O(ud{|= zho0~Xm6u&WmQ1vIUiWfRZ=#4Kv_TvQg8xAkOw(XCsG{KNO7tt?y%g; zeH@Vf*;bsUCF0CsNqE5rVR@^Qg|m4QtY5%>DvDqQMI4Ht;AtFj@*N|>3>w0Ub6SkJ zX3zwVxO(ephwH!zPrYft^xh~rz)N~`l|1<-iITM5Km9|?VU zv9p7Ge6g>qmpO;kEOU)V6JsiKeG&@xbuo8WN2s%_kGXEdlLU`+bWnmT2j6gO%=fS5v0#i}{q ztgj#*(ZwSL@whG?UsRrmtxszXFZ9p%7iv!EH76Fw3(Xhw<_m@9pxzw(>H06^XR_XW zWxeL=jBvA}*x0gsa_Qu4_g&u|-zOt23~0V@gzr4xdY&9?0XIJLvH~4y;1kbk>Slyn6`K$;l1o*~ zb!0QcD}xyz>kRXD5ijx8Rx5bg^;WjW-DTa<6nqHO-K%2~_WvJ9j( zxAn3TH<-RW<{Eg~wO^hY1Ac=_{vOtw+V1r|h}@6pO`WTOM{hlRs}LH{Lj!A{5Nuxn6UM7nQYr-!fSu zdf@DalP@Z^wLg&VOAk)pKfM}!)cvqqZ@c=^i9Odat%u0Bl@c!!duY@Tj zDLC0pJGOh8PT<{&Ou>_IL$ZU|NLjn=X5kUJ1vg+lF&F{;JHjvcok=c(Aelb~WC@I) zBPPu;uh|nhJ(hxN)W$NLd`Dx6gyb;pk$DJ_6H!egMB|&*Pnmc64(Rrsa{qcTXs1BD znnFeYfw|mluHbKZ>~AT0tLH+qp@O&ZvA1z?Q1`a{=5734^v&*@_1>y74pVZxPbF9i z{0>i23Z5!>k}3!>xfygXA)k*$6XuLT%tlgC9tHE2B9zrcf)L0*9)*#A7tB~WTTw3f ztDx~`WW_q#hDkEHH*)W!OGi@+Gor2NbX`3s%Z0dwRv zh}i>>MADQ5xFilfcyu06l?5MG_G1?x;TM%;%P*nGsyCqpr ziXNMLrJL}1qoj$ypbJ_O!C&4@6pe#%CP}=Q-i__EY zxj6at%~4nU{^tDn%(??rSnoPar^@+MhD!tN=p`iLHfaOu1UBv^vi!;v`a4j6zk2&~|H3G3`e~dEZq@BD z?jI^MD)LDmPxuh({y3M@RGEHV8`Hn6DBYjjXymX7Vvt=zAJJX9O?}E~8*J`z=XRs! zfB&J55yh3uf%cackl+AOWDYbYP6AE&41KnPh`#gSFB~ARTAKiw2_KQkC1{c~0R0hL zdd>gDTHvjX7!dCEG#-49&}r)@pe!5b*QzdB8~mz7)`cSIZ4C3vyeRUq-mKQ9>I#_F z$fe$ZnLDb#!6Ynb4d0`+2Y{tExFd0Xq~Fr^KMu(4+OjBk=>H0W?+wMg0H{8TnqAZk z${^`a#38~d+>d0=7KFmPhEH;O8dEx6#d5F_1LM%PH=?F0XxCaq`80#8o9P5QXcVWZ zehzte)Ha2P($E+oR=(gR#P&c82OvP~rt{_QnA~yR)#o-WJd_L`5ImHY5Ou?V-4^1{ zX_(fLs#~h6Xx!MYFOQ5=nm!y`mGB3M>Z*heSlDCL1$?Kq<#Ua59j5W;rm=Z6Uap#5 VA)wj^x3K=J`Zm8{oFVe^}%8DH%xmE zgd&O-M66aSs0tJ-f+-V>l4nG56&?{4YIev3S9F*3qEom<2B#EckNWm*rc3>#&{JKy z3|;Gkoo(z(P&9$(i3k)GOa<^96QSZFQlV(6NW`ioHolNOs$#Wq6pKV}szhxbkwYrl zs;xRlM0CCoPDB@Abba`=s+9HoT~$pz&rMbOFe|ET;@SSJ^xUQ8#J6fwIh{GrtxHXI zjt60dFe8{~vu{B-a!eIn1S+@+q+B7(;HQP1TlRv_46K1;3wq3#fNe=X^95fJ8M^3@ z9Jdzei5KKUxTMQ~0)^n)Py{fCgHr`@3{q#HG9>>7!F!31Oj;_)qJ?W-Iv-{4t31=5 z7r6!O6Fs-SEt`a;EYqp>p`F#*_*lxk%$<~ww01txpWuRY`Be8p$XOSAVrvh0lKC{< z*RoFCdn*!~8Ldm3A82u56MAq-N85?3>M>IOZ)(QVO3eyw$F?@PgB9Phck8*i1W9kfwAi6{=tUaQ%QOiN zx=m_#&y&fJq4R+{&OS_w1p{u8O*-gNa}o9@)cgsHx%N|B2MrovUh6BMS)@7&4w6+6 zH2)R=o1h7B87%Q6rR~X|HN(`u-mkzBq#=CRjP~lQIv+CkS0~t;xs>SSVBh5&Lr8yf9!4` zwp_`8tELA;b3nOp=&?~QJyHp&R}dE)BQ+X=REZ0@1*M>>C*JIOn*crVWWD$1?faeg z?fS=PG>m{!=o9*bgwSu|;FH=>_TKCrW`iuEH?DBZ=?u~LcJT$wAC z3S2R*Qjx1hzGN(Od10l<6(?6*=7F+Ra+u+8#ddO*(HX=|ssR`0{UI3TYrKIRF_KG5 ze($~kB*is}N+(>c3Rk?<@%bN7@_(b|rK|FxNaawWj_L$_TMaLTeEmTBH?!60+Lu?A zno>i=Uo~p?e+QlpbIr;XDQqVoq*-*hW-OLWgK;Hq+OU&lRckEVru$?&f z-3Rw(@6LWd(wz9PIrC9#Vzx=g-)yqj#NMt_#Z9>jaCYKyvV?MYBX?N$7=>J(SuUJZ$Wmq$5Eos*?pJ#4Pw4`I#GTYsW zjo$U%Td(}oomz`GrOfRYfw{A#j|!{`=mJ*5gm@?cJwnLGE4h5 z>d58skxN{@@P3vn)5Fzcco6UhZ-P^?Qeptn7LRsdYp{Ht z5SXo3bS#$gj=K~~fZ1h2vCjj0)Ii(8BlWn)La};cI}oWq>m9q|_2aJgP}8Indod(; z{UKo~u`h$RC$zsbNjmEe>ZVPrTq{==U|LHcoNKoD`rDS`*WE;(a~~KU2Zy}dc*_$1 gH=<2jplDCV82^Hz@cR|@J=A*e*|p1mA`ouu-~BCx`Tzg` literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/foods.cpython-38.pyc b/modules/sprites/__pycache__/foods.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d197221dca83d902d51137a28b6fe3d91b7c88c6 GIT binary patch literal 1201 zcmZWpL2uJA6t-h0&9ZhwfX0A315;E!l=M|s2Nl@T#uM1FeAc)>j?7&Wr6TnO$00yHMVeu4zLKt!fD7NxhNvBc#2LitBbm5 zoFdjZLlm(kfU#u#&7u(6(oaP(uryUgZv7-HlD;K}!`xC6=Y3l%RbgaeEY&7f$u%Aa z%ZDC7cRu|Q27}JAz!Oh+cY%~uH1+;^$hGIdJ0{@u44L3_It6S~d`u^Fg1B#j6Lemi zxJWobpZzJGdKf5#*n&WS*>7J8$fF!}3Y0vSyH@+>tk3!R#@$l2nR!=1Xoc7gLGi?!zb0{wp8de+<5Qt4in=7(cB zK1zFUrS6-e>^Zu>#;P|c#4wY(r%RO@nB6^ky&S3AQ1A`tx_X`XF}{fdyyA_Qs#3t({J5+mfyQwx!+I z?QL88u-oZww7Qn=bzkpRG}{oKJvyCJYKAz(b@B&8 CmK+TL literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/groups.cpython-310.pyc b/modules/sprites/__pycache__/groups.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b1a69ecd6de7c170c0f79f1de388d4b552fcdaf9 GIT binary patch literal 5068 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 GHT(}8C*Sb^ literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/groups.cpython-38.pyc b/modules/sprites/__pycache__/groups.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64c5bdf20e0d6f8fc9ebdf021064af78f191b644 GIT binary patch literal 5333 zcmdTI%WfOVv3p(|4xf5hw&lkv&I4ewQ8v!zwQ(F}ZF%irAsBuD0ik3_nf9fxD&ZOujvu)Munc= z^a=MszSu1Gf@aVwHA}s6v)rpRE4^y7%Gqa36oh}sgfDAv?PeY3MG?R}p!tH}Pg$e% z4tBt{8eF?+E8a~2@jl&;BAFuTLBB7M@x%bKT^F*p-JL<$cLpgla*}gB6-Lya0#_)OFQro@0*pFngogFvXrsE{*g9Giu z`QlC*h9$Hx-4I?L{|&F5HOKly{*0T@RpcfQkP+*Gu~h}o23HI4Ppu%p9cSPwV7fT9 z?IKJQ^fa@E*K^cP1uvo(7tPfhbf!MTZA}#4$WuI(yohE&PDQW6oLpN1{7G{|M;rl>UI|9?%~Gy)dP(6Ws^;pMYMR(pQKc z0R0P~mnL+~Dp{bHb z0K1mD1*c?3JhLL;)&!3~1PKcywt#9+sDL{L?oM#Zy7tyP%n$F-XALhiiz8I)b#{ER z3m%{B(y%idd({Z^E56kba04^)33ReC@>CC6mGBe#*qFw2og6mCKnp6;ucEvUVACr%Y^(AYF> z9}}J`13<4QsK)1h!Qz2EKdNPtYlFzl2c5J5Bl#>EGL-R4Vg)D*a#1dc%P_wpuEKm-tU_78rc0Y~+DQ-o2lYI=c|JKo)xa*Q z4nVJl#ty=8Kv5r3H>I!6@*utR4#uqOv#jygUQq9q=xejw?28lT(k$~Oc4>LFhXU-^ z=*78WyKLa5Q`H}tNWdS}HhqWa_WR99vK;<2Ims;PNK>LQANdY)pJg6)~1aKThaTqvcU zq)T~z4aKxVHI8>JsB){6-JNk29gR6Ia6Sf(cQoO=AWi}3p99^W(tk(vBGCVWST{(s zbrndJCQ^G}PIW1b@r_46hRC+^wzQ((`yX?!S)Lvh%GyI~d4DRecLB zgE6gx$8^)5LEo!>hSXa~EpFl+C*seMh)+HB2?9*1+QGb_eu48};=G8@8U(%z+=_lhHuR@Sr~FS$knd^88=yvGnb!jvVd;3 zR`z}Nhw2-9G^Op`28n6I6)%rlG6B??)=Oc>2rU;Km--Tn@$7PtZSWp6ocWH6Of+W> z{PqEi1m9Iz+l5cXVBCHU>!u;F=W1BGI@7-=+Ia=PTFh7m`(zwsnZE&o7J<_)XQw@8 z%7atGlb^Fa53Mr8yEWxuyXpY1{KgqMM=r_V1)2x6CqQFIg^_~~0_2W3N+Wk<9Xs3B z8yB>(BR`W!iz7S5Mjz4<&}{matDc;$u?Kj!1S_w+@kSnMQ(qI;L)pErPp@y8EUz7m zNbT%)qKJ~rI8yfqqLs=lNHN;7j*{}3jZ<BeH#r`N_mg{+T%3dzdG${cllY+&?(zBJFwdON($dU>9Q;hk-s y9tiXZq^DmI#Ipw9LipC?*O@iDe*53b`hBke literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/home.cpython-310.pyc b/modules/sprites/__pycache__/home.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a4881622c0543187782a945317ccd70140b7935 GIT binary patch literal 1128 zcmZWo%}(1u5T0GH9Va4`LR6J&PqkF>09A#k=--J8>cxt*a=i<6SjXw^A{3Mxk$4R_ z@+y6Vz4pW_^wQ2am_~G@8PD$6^L_KEMK<&k2?kR|u{HXPkEv>6K<$EBX?k4D#e>Prf(OZ0GX`{-!M znSz{O!wFMN@nxDvTBt~gC0wyQ*6}1!ad%RQ>MbGfU4wu;Mc_1uFHNmWqTLDkF)HD> zH)uRu!3|rm1y^hrZm|gT_%19!Vqs{b1zDj0Gm0ZiRak5ee9GbwyYrd0A(gV4R$j{R zLK32sN;_|xxmL2Oi&Gu8p5BMei^3QuXN{|T)l4%Hgwy6Eq}@&Ex1XL=M%zB(-LcS@ zvNVNrQr^Mu{lmB8uTEPxey?hTN5H~2cKkuRGvCa{zL=g}6n0!U>fC5Ib~9Ufe11oQ zd$YMsFlP_drD(RJ)l*Wnosds@i0bI;1x&ChckC!*mXhFu_QyVZG+XF} z{$n#X@#v^`3BTNIfgVF8U3Wr04X8zWg$|AfBwG8-vkAY!flS0L-EkTVseO*GWpT?R zB(wQxQR@(|nlDUKC`+|we8q4Z{UZm0=JWWs54 z{t=0S_+~0^>8&8FF8u>^NL*>Po<2bjLfPWtCBakiBX-$e^#^aWJ}uZ33&I5(NVys) z`WsUII4{g9(#{jN$2Pc;e%_XYVA^|a?Jm(6K5S2^jgfMVz!0OBMrFId!_lNt*x>dlo4s(RwRS=(4?=kUJfJ@4=L<~{#XC`<#M zGJGwsbAZ3e8J*0~7%Zc)4-zDcpaPOhCt?j=;S4x@4AR{NnNj@6N%JdChxysZlz91RmI8I`H$ zht7nO&SVaOs!Z*{H>{G|06&wspR^h(bSDak9zh;dQT)XAAs%1eb-VB#-gjA-OE!=3 zqajWP7~vG@f*4^3>7X~Hk2mCvztjQWUDuSVDdQu=k}+FtrIVZxwPr0ABDo+4oe)x) zShqS#idrMMp_0(Kdu=F>QejoFz{r z4ec?KpS@_`;rC4OQR%{d{>S`D>C$oO(qZ}J^2+h$mETJ5_O5-q+IJxP%8Sh*!nQe| zqCw56Pre|==pfy3i_*w2`jU42zgZ*VPU3zU)nYw|MTx6%GKW-?tO>PJ%}KV2D|N8F z5ZLu+%4V0eT_S|vj{@PvC{e?!7B{6D^yV=1kPiLK2I&VZs$>F(X@h=&%B4?*)BYF zUB1*Wf^+T(XMADcpw%a!e?-co^Xe+(#>mqvi_ZB{ECHcf6aIG>-byL5&UB{ vni^{_?n9bH%kVt6mhyUEFQH4Q3{~|V#@HWF_!AbNX3w)Ldu#syDqHv;`V>Bd literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/home.cpython-38.pyc b/modules/sprites/__pycache__/home.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f46ef0afbb45027d0da09e768cf481e9d3f3bf02 GIT binary patch literal 1114 zcmZWo%}(1u5T0GH9VbdCg{mq&^ju374}dC!1pPU2L0qgzE7!Y#!^Tc`7okMC5sBA; zBd^j&*lSO`LQkD>2#x4SGoBxN=9?d%4hB6y`nBzf0}k+;jCB%d93Z=oC=@7WAP2=& zWZ0PJoWVCxLd6SEvF0~X9w~MLS@MW)!|@|SnX%A6DRr&C7(LdtFDbN6(Ual!QPGey z1v$TkGp3m0i!_h4P>~V~xM6v$<58mGm8BBZSwP;o1p#@Ah0`FuH)CBA>=lt7BU2ss z35ACnxMOoR=ZfvXJvMICn*$QMsaMZ3yZ^nuUQ;ocQw&Aq*7LO<)sX7 zB~_GCY3FS-)k;?5;#`N#m;SJET^Qr!q;Zw6nmQ9fIBm{Cy7Gi>`{`L_wC!TO2Nt?g zmZoq{$_Mzfcepn^b=tb2sp|8Yo?TSKBkeAIGa34#zPv8%aNMXXqutO=Y~}HJf#7y0 zQ=4GE4zf#80NY|cmay4?u^NhVlHh}G$G&ku!8E=*G>OMPa1iEaz^7Z5G^h}*V+Crq&a0MXU7fZm`oXLr;-LKtznmwzy# zAbyz2TY4)9t4se>I3%vLTGuaX2cc|n{f>&aBVe=cax&=6x^z}Gwu5KYlXAIA)caEY zyeiBx(ryxO#x{6|e%dyJ#kBX@+8u&1c)FQV8zbc!fB{A=Ey=F_3D-v}<^2w4y-2WL n+(t5Cwqmb9EL!dx literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/scenes.cpython-310.pyc b/modules/sprites/__pycache__/scenes.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aad67d542cef9d49f8096b6783a5c5bc759362a8 GIT binary patch literal 2436 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 literal 0 HcmV?d00001 diff --git a/modules/sprites/__pycache__/tanks.cpython-310.pyc b/modules/sprites/__pycache__/tanks.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed0e542eea24d05f3a91f2fad8561237863d27c3 GIT binary patch literal 12074 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 O*~;gPr^`|K$NvX1BqA38 literal 0 HcmV?d00001 diff --git a/modules/sprites/bullet.py b/modules/sprites/bullet.py new file mode 100644 index 0000000..a9d77fb --- /dev/null +++ b/modules/sprites/bullet.py @@ -0,0 +1,36 @@ + +import pygame + +'''子弹''' + + +class Bullet(pygame.sprite.Sprite): + + def __init__(self, direction, position, config, tank, enhanced=False, speed=20): + pygame.sprite.Sprite.__init__(self) + self.image = pygame.image.load(config.BULLET_IMAGE_PATHS.get(direction.value)) + self.width, self.height = config.WIDTH, config.HEIGHT + self.border_len = config.BORDER_LEN + self.direction = direction + self.rect = self.image.get_rect() + self.position = self.rect.center = position + self.tank = tank + + # 地图边缘宽度 + + # 是否为加强版子弹(加强版可碎铁墙) + self.enhanced = enhanced + # 子弹速度 + self.speed = speed + + def move(self): + # 移动子弹, 若子弹越界, 则返回True, 否则为False + self.rect = self.rect.move(self.direction.value[0] * self.speed, self.direction.value[1] * self.speed) + return (self.rect.top < self.border_len) or (self.rect.bottom > self.height) or ( + self.rect.left < self.border_len) or (self.rect.right > self.width) + + def kill(self): + if not self.tank.infinity_bullet: + self.tank.bullet_count -= 20 + + super().kill() \ No newline at end of file diff --git a/modules/sprites/foods.py b/modules/sprites/foods.py new file mode 100644 index 0000000..1958720 --- /dev/null +++ b/modules/sprites/foods.py @@ -0,0 +1,30 @@ +import pygame +import random +from .scenes import SceneElement + + +class Foods(SceneElement): + BOOM = 'boom' + IRON = 'iron' + CLOCK = 'clock' + GUN = 'gun' + TANK = 'tank' + PROTECT = 'protect' + STAR = 'star' + + # 食物类. 用于获得奖励 + def __init__(self, food_image_paths, screensize): + random_position = (random.randint(100, screensize[0]-100), random.randint(100, screensize[1]-100)) + random_food = random.choice(list(food_image_paths.keys())) + self.__name = random_food + super().__init__(random_position, food_image_paths.get(self.__name)) + + self.exist_time = 1000 + + @property + def type(self): + return self.__name + + def update(self): + self.exist_time -= 1 + return True if self.exist_time < 0 else False \ No newline at end of file diff --git a/modules/sprites/groups.py b/modules/sprites/groups.py new file mode 100644 index 0000000..2f44f7b --- /dev/null +++ b/modules/sprites/groups.py @@ -0,0 +1,158 @@ +import pygame + +from modules.sprites import tanks +from modules.sprites.bullet import Bullet +from modules.sprites.foods import Foods +from modules.sprites.home import Home +from modules.sprites import SceneElement, Ice, Brick, Tree, River, Iron + + +class SceneElementsGroup(object): + def __init__(self): + self.__ice_group = pygame.sprite.Group() + self.__iron_group = pygame.sprite.Group() + self.__brick_group = pygame.sprite.Group() + self.__tree_group = pygame.sprite.Group() + self.__river_group = pygame.sprite.Group() + + @property + def ice_group(self): + return self.__ice_group + + @property + def iron_group(self): + return self.__iron_group + + @property + def brick_group(self): + return self.__brick_group + + @property + def tree_group(self): + return self.__tree_group + + @property + def river_group(self): + return self.__river_group + + def add(self, scene_element: SceneElement): + if isinstance(scene_element, Ice): + self.ice_group.add(scene_element) + elif isinstance(scene_element, Brick): + self.brick_group.add(scene_element) + elif isinstance(scene_element, Tree): + self.tree_group.add(scene_element) + elif isinstance(scene_element, River): + self.river_group.add(scene_element) + elif isinstance(scene_element, Iron): + self.iron_group.add(scene_element) + + def draw(self, screen: pygame.Surface, layer: int): + if layer == 1: + self.ice_group.draw(screen) + self.river_group.draw(screen) + elif layer == 2: + self.brick_group.draw(screen) + self.iron_group.draw(screen) + self.tree_group.draw(screen) + + +class EntityGroup(object): + def __init__(self): + self.__player_tanks = pygame.sprite.Group() + self.__enemy_tanks = pygame.sprite.Group() + self.__player_bullets = pygame.sprite.Group() + self.__enemy_bullets = pygame.sprite.Group() + self.__foods = pygame.sprite.Group() + + @property + def player_tanks(self): + return self.__player_tanks + + @property + def enemy_tanks(self): + return self.__enemy_tanks + + @property + def player_bullets(self): + return self.__player_bullets + + @property + def enemy_bullets(self): + return self.__enemy_bullets + + @property + def foods(self): + return self.__foods + + def add(self, entity: pygame.sprite): + if isinstance(entity, tanks.PlayerTank): + self.player_tanks.add(entity) + elif isinstance(entity, tanks.EnemyTank): + self.enemy_tanks.add(entity) + elif isinstance(entity, Foods): + self.foods.add(entity) + elif isinstance(entity, Bullet): + if isinstance(entity.tank, tanks.PlayerTank): + self.player_bullets.add(entity) + elif isinstance(entity.tank, tanks.EnemyTank): + self.enemy_bullets.add(entity) + else: + raise TypeError('Unknown Entity Type') + + def clear_enemy_tanks(self): + self.enemy_tanks.empty() + + def remove(self, entity: pygame.sprite): + if isinstance(entity, tanks.PlayerTank): + self.player_tanks.remove(entity) + elif isinstance(entity, tanks.EnemyTank): + self.enemy_tanks.remove(entity) + elif isinstance(entity, Foods): + self.foods.remove(entity) + elif isinstance(entity, Bullet): + if isinstance(entity.tank, tanks.PlayerTank): + self.player_bullets.remove(entity) + elif isinstance(entity.tank, tanks.EnemyTank): + self.enemy_bullets.remove(entity) + else: + raise TypeError('Unknown Entity Type') + + def draw(self, screen: pygame.Surface, layer: int): + if layer == 1: + self.player_bullets.draw(screen) + self.enemy_bullets.draw(screen) + self.player_tanks.draw(screen) + for tank in self.player_tanks: + tank.draw(screen) + self.enemy_tanks.draw(screen) + elif layer == 2: + self.foods.draw(screen) + + def update(self, scene_elements: SceneElementsGroup, home: Home): + # 更新并画我方子弹 + for bullet in self.player_bullets: + if bullet.move(): + bullet.kill() + # 更新并画敌方子弹 + for bullet in self.enemy_bullets: + if bullet.move(): + bullet.kill() + # 更新并画我方坦克 + for tank in self.player_tanks: + tank.update() + # 更新并画敌方坦克 + for tank in self.enemy_tanks: + self.remove(tank) + remove_flag, bullet = tank.update( + scene_elements, self.player_tanks, self.enemy_tanks, home + ) + self.add(tank) + if isinstance(bullet, Bullet): + self.add(bullet) + if remove_flag: + self.remove(tank) + # 更新食物 + for food in self.foods: + if food.update(): + self.remove(food) \ No newline at end of file diff --git a/modules/sprites/home.py b/modules/sprites/home.py new file mode 100644 index 0000000..882bd59 --- /dev/null +++ b/modules/sprites/home.py @@ -0,0 +1,25 @@ +import pygame +from .scenes import SceneElement + + +class Home(SceneElement): + # 大本营 + def __init__(self, position, imagefile, walls_position): + super().__init__(position, imagefile[0]) + self.__destroyed_image = imagefile[1] + self.__destroyed = False + self.walls_position = walls_position + + + @property + def destroyed(self): + return self.__destroyed + + @destroyed.setter + def destroyed(self, destroyed): + self.__destroyed = destroyed + if destroyed: + self.image = pygame.image.load(self.__destroyed_image) + + def draw(self, screen): + screen.blit(self.image, self.rect) \ No newline at end of file diff --git a/modules/sprites/scenes.py b/modules/sprites/scenes.py new file mode 100644 index 0000000..fe9ddfd --- /dev/null +++ b/modules/sprites/scenes.py @@ -0,0 +1,66 @@ +import pygame + + +class SceneElement(pygame.sprite.Sprite): + def __init__(self, position, imagefile, blitimage=False): + pygame.sprite.Sprite.__init__(self) + self.image = pygame.image.load(imagefile) + if blitimage: + self.image = pygame.Surface((24, 24)) + for i in range(2): + for j in range(2): + self.image.blit(pygame.image.load(imagefile), (12 * i, 12 * j)) + self.rect = self.image.get_rect() + self.rect.left, self.rect.top = position + + +class Brick(SceneElement): + # 砖墙 + pass + + +class Iron(SceneElement): + # 铁墙 + pass + + +class Ice(SceneElement): + # 冰 + def __init__(self, position, imagefile): + super().__init__(position, imagefile, True) + + +class River(SceneElement): + # 河流 + def __init__(self, position, imagefile): + super().__init__(position, imagefile, True) + + +class Tree(SceneElement): + # 树 + def __init__(self, position, imagefile): + super().__init__(position, imagefile, True) + + +class SceneFactory(object): + BRICK = 'brick' + IRON = 'iron' + RIVER_1 = 'river1' + RIVER_2 = 'river2' + ICE = 'ice' + TREE = 'tree' + SCENE_MAPS = { + BRICK: Brick, + IRON: Iron, + RIVER_1: River, + RIVER_2: River, + ICE: Ice, + TREE: Tree, + } + + def __init__(self, game_config): + self.__scene_images = game_config.SCENE_IMAGE_PATHS + + def create_element(self, position, element_type): + return SceneFactory.SCENE_MAPS[element_type](position, self.__scene_images.get(element_type)) + diff --git a/modules/sprites/tanks.py b/modules/sprites/tanks.py new file mode 100644 index 0000000..3158c0e --- /dev/null +++ b/modules/sprites/tanks.py @@ -0,0 +1,466 @@ +import pygame +import random + +from modules.TankGame import TankGame +from modules.sprites import groups + +from modules.sprites.foods import Foods +from modules.sprites.bullet import Bullet +from enum import Enum +from pygame.sprite import spritecollide + + + + +class DIRECTION(Enum): + UP = (0, -1) + DOWN = (0, 1) + LEFT = (-1, 0) + RIGHT = (1, 0) + + @classmethod + def list(cls): + return [DIRECTION.UP, DIRECTION.DOWN, DIRECTION.LEFT, DIRECTION.RIGHT] + + @classmethod + def random(cls): + return random.choice([DIRECTION.UP, DIRECTION.DOWN, DIRECTION.LEFT, DIRECTION.RIGHT]) + + +class COLLISION: + WITH_TANK = 0b00001 + WITH_HOME = 0b00010 + WITH_BORDER = 0b00100 + WITH_SCENE_ELEMENTS = 0b01000 + + +class Tank(pygame.sprite.Sprite): + def __init__(self, game_config): + super().__init__() + self.__game_config = game_config + # 坦克轮子转动效果 + self._switch_count = 0 + self._switch_time = 1 + self._switch_pointer = False + # 移动缓冲 + self._move_cache_time = 4 + self._move_cache_count = 0 + # 爆炸 + self._boom_last_time = 5 + self._boom_count = 0 + self._booming_flag = False + + self._level = 0 + self._speed = 8 + # 地图边缘宽度/屏幕大小 + self._border_len = game_config.BORDER_LEN + self._screen_size = [game_config.WIDTH, game_config.HEIGHT] + self._init_resources() + + self.bullet_count = 0 + self._is_bullet_cooling = False + self._bullet_config = { + 0: { + 'speed': 8, + 'enhanced': False + }, + 1: { + 'speed': 10, + 'enhanced': False + }, + 2: { + 'speed': 10, + 'enhanced': True + }, + 'count': 1, + 'infinity': False + } + + @property + def infinity_bullet(self): + return self._bullet_config['infinity'] + + @property + def bullet_limit(self): + return self._bullet_config['count'] + + @property + def _game_config(self): + return self.__game_config + + def shoot(self): + if self._booming_flag: + return False + if not self._is_bullet_cooling: + if not self.infinity_bullet: + if self.bullet_count >= self.bullet_limit: + return False + else: + self.bullet_count += 1 + + self._is_bullet_cooling = True + position = (self.rect.centerx + self._direction.value[0], self.rect.centery + self._direction.value[1]) + bullet = Bullet(direction=self._direction, position=position, tank=self, config=self._game_config) + configkey = self._level + if configkey >= 2: + configkey = 2 + bullet.speed = self._bullet_config[configkey]['speed'] + bullet.enhanced = self._bullet_config[configkey]['enhanced'] + return bullet + + return False + + @property + def image(self): + if self._booming_flag: + return self._boom_image + return self._tank_direction_image.subsurface((48 * int(self._switch_pointer), 0), (48, 48)) + + def decrease_level(self): + if self._booming_flag: + return False + self._level -= 1 + self._tank_image = pygame.image.load(self._level_images[self._level]).convert_alpha() + self._update_direction(self._direction) + # self.image = self._tank_direction_image.subsurface((48 * int(self._switch_pointer), 0), (48, 48)) + if self._level < 0: + self._booming_flag = True + return True if self._level < 0 else False + + '''设置坦克方向''' + def _update_direction(self, direction): + self._direction = direction + if self._direction == DIRECTION.UP: + self._tank_direction_image = self._tank_image.subsurface((0, 0), (96, 48)) + elif self._direction == DIRECTION.DOWN: + self._tank_direction_image = self._tank_image.subsurface((0, 48), (96, 48)) + elif self._direction == DIRECTION.LEFT: + self._tank_direction_image = self._tank_image.subsurface((0, 96), (96, 48)) + elif self._direction == DIRECTION.RIGHT: + self._tank_direction_image = self._tank_image.subsurface((0, 144), (96, 48)) + + def _init_resources(self): + config = self._game_config + self._bullet_images = config.BULLET_IMAGE_PATHS + self._boom_image = pygame.image.load(config.OTHER_IMAGE_PATHS.get('boom_static')) + pass + + def roll(self): + # 为了坦克轮动特效切换图片 + self._switch_count += 1 + if self._switch_count > self._switch_time: + self._switch_count = 0 + self._switch_pointer = not self._switch_pointer + + def move(self, direction, scene_elems, player_tanks_group, enemy_tanks_group, home): + # 爆炸时无法移动 + if self._booming_flag: + return + # 方向不一致先改变方向 + if self._direction != direction: + self._update_direction(direction) + self._switch_count = self._switch_time + self._move_cache_count = self._move_cache_time + # 移动(使用缓冲) + self._move_cache_count += 1 + if self._move_cache_count < self._move_cache_time: + return + self._move_cache_count = 0 + + new_position = (self._direction.value[0] * self._speed, self._direction.value[1] * self._speed) + old_rect = self.rect + self.rect = self.rect.move(new_position) + # --碰到场景元素 + collisons = 0 + cannot_passthrough = [scene_elems.brick_group, scene_elems.iron_group, scene_elems.river_group] + for i in cannot_passthrough: + if spritecollide(self, i, False, None): + self.rect = old_rect + collisons |= COLLISION.WITH_SCENE_ELEMENTS + + + + # --碰到其他玩家坦克/碰到敌方坦克 + if spritecollide(self, player_tanks_group, False, None) or spritecollide(self, enemy_tanks_group, False, None): + collisons |= COLLISION.WITH_TANK + self.rect = old_rect + + # --碰到玩家大本营 + if pygame.sprite.collide_rect(self, home): + collisons |= COLLISION.WITH_HOME + self.rect = old_rect + + # --碰到边界 + if self.rect.left < self._border_len: + self.rect.left = self._border_len + collisons |= COLLISION.WITH_BORDER + elif self.rect.right > self._screen_size[0] - self._border_len: + collisons |= COLLISION.WITH_BORDER + self.rect.right = self._screen_size[0] - self._border_len + elif self.rect.top < self._border_len: + collisons |= COLLISION.WITH_BORDER + self.rect.top = self._border_len + elif self.rect.bottom > self._screen_size[1] - self._border_len: + collisons |= COLLISION.WITH_BORDER + self.rect.bottom = self._screen_size[1] - self._border_len + + if collisons == 0 and spritecollide(self, scene_elems.ice_group, False, None): + self.rect = self.rect.move(new_position) + + return collisons + + +class PlayerTank(Tank): + def __init__(self, name, position, game_config, **kwargs): + super().__init__(game_config=game_config) + self._level_images = self._game_config.PLAYER_TANK_IMAGE_PATHS.get(name) + + # 玩家1/玩家2 + self.name = name + # 初始坦克方向 + self.__init_direction = DIRECTION.UP + # 初始位置 + self.__init_position = position + # 保护罩 + self.__protected = False + self.__protected_mask_flash_time = 25 + self.__protected_mask_flash_count = 0 + self.__protected_mask_pointer = False + # 坦克生命数量 + self.health = 3 + # 重置 + self.__reborn() + + def _init_resources(self): + super()._init_resources() + # 保护罩 + self.__protected_mask = pygame.image.load(self._game_config.OTHER_IMAGE_PATHS.get('protect')) + + def update(self): + # 坦克子弹冷却更新 + if self._is_bullet_cooling: + self._bullet_cooling_count += 1 + if self._bullet_cooling_count >= self._bullet_cooling_time: + self._bullet_cooling_count = 0 + self._is_bullet_cooling = False + # 无敌状态更新 + if self.protected: + self.__protected_count += 1 + if self.__protected_count > self.__protected_time: + self.protected = False + self.__protected_count = 0 + # 爆炸状态更新 + if self._booming_flag: + self._boom_count += 1 + if self._boom_count > self._boom_last_time: + self._boom_count = 0 + self._booming_flag = False + self.__reborn() + + def improve_level(self): + # 提高坦克等级 + if self._booming_flag: + return False + self._level = min(self._level + 1, len(self._level_images) - 1) + self._tank_image = pygame.image.load(self._level_images[self._level]).convert_alpha() + self._update_direction(self._direction) + return True + + def decrease_level(self): + # 降低坦克等级 + res = super().decrease_level() + if self._level < 0: + self.health -= 1 + + return res + + def add_health(self): + # 增加生命值 + self.health += 1 + + @property + def protected(self): + return self.__protected + + @protected.setter + def protected(self, protected): + self.__protected = protected + + def draw(self, screen): + # 画我方坦克 + screen.blit(self.image, self.rect) + if self.protected: + self.__protected_mask_flash_count += 1 + if self.__protected_mask_flash_count > self.__protected_mask_flash_time: + self.__protected_mask_pointer = not self.__protected_mask_pointer + self.__protected_mask_flash_count = 0 + screen.blit(self.__protected_mask.subsurface((48 * self.__protected_mask_pointer, 0), (48, 48)), self.rect) + + def __reborn(self): + # 重置坦克, 重生的时候用 + + # 移动缓冲, 用于避免坦克连续运行不方便调整位置 + self._move_cache_time = 4 + self._move_cache_count = 0 + # 是否无敌状态 + self.protected = False + self.__protected_time = 1500 + self.__protected_count = 0 + # 坦克移动速度 + self._speed = 8 + # 子弹冷却时间 + self._bullet_cooling_time = 30 + self._bullet_cooling_count = 0 + self._is_bullet_cooling = False + # 坦克等级 + self._level = 0 + + # 坦克图片 + self._tank_image = pygame.image.load(self._level_images[self._level]).convert_alpha() + self._update_direction(self.__init_direction) + self.rect = self.image.get_rect() + self.rect.left, self.rect.top = self.__init_position + + +'''敌方坦克类''' + + +class EnemyTank(Tank): + def __init__(self, position, game_config, **kwargs): + super().__init__(game_config=game_config) + enemy_level_images = self._game_config.ENEMY_TANK_IMAGE_PATHS + self.__tank_type = random.choices(['0', '1', '2'], weights=[10, 10, TankGame().level+10])[0]#random.choice(list(enemy_level_images.keys())) + self._level_images = enemy_level_images.get(self.__tank_type) + self._bullet_config[2]['enhanced'] = False + + self._level = int(self.__tank_type) #random.randint(0, len(self._level_images) - 2) + # 子弹冷却时间 + self._bullet_cooling_time = 120 - self._level * 10 + self._bullet_cooling_count = 0 + self._is_bullet_cooling = False + # 用于给刚生成的坦克播放出生特效 + self._is_borning = True + self._borning_left_time = 90 + # 坦克是否可以行动(玩家坦克捡到食物clock可以触发为True) + self.is_keep_still = False + self.keep_still_time = 500 + self.keep_still_count = 0 + + # 坦克移动速度,等级越高速度越低 + self._speed = 10 - self._level * 3 + + self.__food = None + # 坦克出场特效 + appear_image = pygame.image.load(self._game_config.OTHER_IMAGE_PATHS.get('appear')).convert_alpha() + self.__appear_images = [ + appear_image.subsurface((0, 0), (48, 48)), + appear_image.subsurface((48, 0), (48, 48)), + appear_image.subsurface((96, 0), (48, 48)) + ] + if random.random() <= 0.3 * self._level: + # if (random.random() >= 0.6) and (self._level == len(self._level_images) - 2): + # self._level += 1 + self.__food = Foods(food_image_paths=self._game_config.FOOD_IMAGE_PATHS, screensize=self._screen_size) + + # 坦克图片路径 + self._tank_image = pygame.image.load(self._level_images[self._level]).convert_alpha() + self._direction = DIRECTION.random() + self._update_direction(self._direction) + self.rect = self.image.get_rect() + self.rect.left, self.rect.top = position + # 坦克爆炸图 + + @property + def food(self): + return self.__food + + def clear_food(self): + self.__food = None + + @property + def image(self): + if self._is_borning: + return self.__appear_images[(90 - self._borning_left_time // 10) % 3] + return super().image + + def update(self, scene_elems, player_tanks_group, enemy_tanks_group, home): + # 死后爆炸 + remove_flag = False + bullet = None + if self._booming_flag: + + self._boom_count += 1 + if self._boom_count > self._boom_last_time: + self._boom_count = 0 + self._booming_flag = False + remove_flag = True + return remove_flag, bullet + + # 禁止行动时不更新 + if self.is_keep_still: + self.keep_still_count += 1 + if self.keep_still_count > self.keep_still_time: + self.is_keep_still = False + self.keep_still_count = 0 + return remove_flag, bullet + + # 播放出生特效 + if self._is_borning: + self._borning_left_time -= 1 + if self._borning_left_time < 0: + self._is_borning = False + # 出生后实时更新 + else: + # --坦克移动 + self.move(self._direction, scene_elems, player_tanks_group, enemy_tanks_group, home) + self.roll() + # --坦克子弹冷却更新 + if self._is_bullet_cooling: + self._bullet_cooling_count += 1 + if self._bullet_cooling_count >= self._bullet_cooling_time: + self._bullet_cooling_count = 0 + self._is_bullet_cooling = False + # --能射击就射击 + bullet = self.shoot() + return remove_flag, bullet + + def random_change_direction(self, exclude_current_direction=False): + list = DIRECTION.list() + if exclude_current_direction: + list.remove(self._direction) + + self._update_direction(random.choice(list)) + self._switch_count = self._switch_time + self._move_cache_count = self._move_cache_time + + def move(self, direction, scene_elems, player_tanks_group, enemy_tanks_group, home): + # 遇到障碍物考虑改变方向 + collisions = super().move(direction, scene_elems, player_tanks_group, enemy_tanks_group, home) + if collisions is None or collisions == 0: + return + + change_direction = False + if collisions & COLLISION.WITH_SCENE_ELEMENTS & COLLISION.WITH_BORDER: + change_direction = True + self.random_change_direction(change_direction) + + def set_still(self): + self.is_keep_still = True + + +class TankFactory(object): + ENEMY_TANK = 0 + PLAYER1_TANK = 1 + PLAYER2_TANK = 2 + + def __init__(self, config): + self.__game_config = config + + def create_tank(self, position, tank_type): + if tank_type == TankFactory.ENEMY_TANK: + return EnemyTank(position=position, game_config=self.__game_config) + elif tank_type == TankFactory.PLAYER1_TANK: + return PlayerTank(name='player1', position=position, game_config=self.__game_config) + elif tank_type == TankFactory.PLAYER2_TANK: + return PlayerTank(name='player2', position=position, game_config=self.__game_config) + diff --git a/modules/views/AbstractView.py b/modules/views/AbstractView.py new file mode 100644 index 0000000..5177d71 --- /dev/null +++ b/modules/views/AbstractView.py @@ -0,0 +1,45 @@ +import pygame,sys + +from modules.TankGame import TankGame + + +class AbstractView(object): + def __init__(self): + self._init_resources() + self._init_logo() + + @property + def config(self): + return TankGame().config + + def _init_resources(self): + pass + + def _init_logo(self): + pass + + def _init_text(self): + pass + + def _init_bottons(self): + pass + + def _draw_interface(self): + pass + + def _main_loop(self): + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + self._draw_interface() + pass + + def show(self): + TankGame().init_game_window() + self._init_text() + self._init_bottons() + self._main_loop() + pass + diff --git a/modules/views/GameLevelView.py b/modules/views/GameLevelView.py new file mode 100644 index 0000000..8cc27df --- /dev/null +++ b/modules/views/GameLevelView.py @@ -0,0 +1,432 @@ +import sys +import pygame +import random +from modules.TankGame import TankGame +from modules.sprites import * +from modules.views.AbstractView import AbstractView + +from modules.sprites.tanks import DIRECTION +from pygame.sprite import spritecollide, groupcollide, collide_rect + + +class GameLevelView(AbstractView): + + def _init_resources(self): + config = self.config + self.__sounds = TankGame().sounds + self.__other_images = config.OTHER_IMAGE_PATHS + self.__home_images = config.HOME_IMAGE_PATHS + self.__background_img = pygame.image.load(self.__other_images.get('background')) + self.__font = pygame.font.Font(config.FONTPATH, config.HEIGHT // 35) + + self.__border_len = config.BORDER_LEN + self.__grid_size = config.GRID_SIZE + self.__screen_width, self.__screen_height = config.WIDTH, config.HEIGHT + self.__panel_width = config.PANEL_WIDTH + self.__tank_factory = TankFactory(self.config) + self.__scene_factory = SceneFactory(self.config) + self.__scene_elements = None + + def _init_text(self): + color_white = (255, 255, 255) + self.__fix_text_tips = { + 1: {'text': 'Operate-P1'}, + 2: {'text': 'K_w: Up'}, + 3: {'text': 'K_s: Down'}, + 4: {'text': 'K_a: Left'}, + 5: {'text': 'K_d: Right'}, + 6: {'text': 'K_SPACE: Shoot'}, + 8: {'text': 'Operate-P2:'}, + 9: {'text': 'K_UP: Up'}, + 10: {'text': 'K_DOWN: Down'}, + 11: {'text': 'K_LEFT: Left'}, + 12: {'text': 'K_RIGHT: Right'}, + 13: {'text': 'K_KP0: Shoot'}, + 15: {'text': 'State-P1:'}, + 19: {'text': 'State-P2:'}, + } + for pos, tip in self.__fix_text_tips.items(): + tip['render'] = self.__font.render(tip['text'], True, color_white) + tip['rect'] = tip['render'].get_rect() + tip['rect'].left, tip['rect'].top = self.__screen_width + 5, self.__screen_height * pos / 30 + + pass + + '''开始游戏''' + def _init_game_window(self): + TankGame().init_game_window( + (self.config.WIDTH + self.config.PANEL_WIDTH, self.config.HEIGHT) + ) + + def __play_sound(self, sound): + self.__sounds[sound].play() + + def __dispatch_player_operation(self): + key_pressed = pygame.key.get_pressed() + key_maps = { + 'dir': { + self.__tank_player1: { + pygame.K_w: DIRECTION.UP, + pygame.K_s: DIRECTION.DOWN, + pygame.K_a: DIRECTION.LEFT, + pygame.K_d: DIRECTION.RIGHT, + }, + self.__tank_player2: { + pygame.K_UP: DIRECTION.UP, + pygame.K_DOWN: DIRECTION.DOWN, + pygame.K_LEFT: DIRECTION.LEFT, + pygame.K_RIGHT: DIRECTION.RIGHT, + }, + }, + 'fire': { + self.__tank_player1: pygame.K_SPACE, + self.__tank_player2: pygame.K_KP0, + }, + + } + + # 玩家一, WSAD移动, 空格键射击 + player_tank_list = [] + if self.__tank_player1.health >= 0: + player_tank_list.append(self.__tank_player1) + if TankGame().multiplayer_mode and (self.__tank_player1.health >= 0): + player_tank_list.append(self.__tank_player2) + + for tank in player_tank_list: + for key, dir in key_maps['dir'][tank].items(): + if key_pressed[key]: + self.__entities.remove(tank) + tank.move(dir, self.__scene_elements, self.__entities.player_tanks, + self.__entities.enemy_tanks, self.__home) + tank.roll() + self.__entities.add(tank) + break + + if key_pressed[key_maps['fire'][tank]]: + bullet = tank.shoot() + if bullet: + self.__play_sound('fire') if tank._level < 2 else self.__play_sound('Gunfire') + self.__entities.add(bullet) + + def __dispatch_food_effect(self, food: Foods, player_tank: PlayerTank): + self.__play_sound('add') + + if food.type == Foods.BOOM: + for _ in self.__entities.enemy_tanks: + self.__play_sound('bang') + self.__total_enemy_num -= len(self.__entities.enemy_tanks) + self.__entities.clear_enemy_tanks() + elif food.type == Foods.CLOCK: + for enemy_tank in self.__entities.enemy_tanks: + enemy_tank.set_still() + elif food.type == Foods.GUN: + player_tank.improve_level() + elif food.type == Foods.IRON: + for x, y in self.__home.walls_position: + self.__scene_elements.add( + self.__scene_factory.create_element((x, y), SceneFactory.IRON) + ) + elif food.type == Foods.PROTECT: + player_tank.protected = True + elif food.type == Foods.STAR: + player_tank.improve_level() + player_tank.improve_level() + elif food.type == Foods.TANK: + player_tank.add_health() + + self.__entities.foods.remove(food) + + def __dispatch_collisions(self): + collision_results = { + 'group': {}, + 'sprite': {}, + 'foreach_sprite': {}, + } + for (collision, args) in self.__collisions['group'].items(): + collision_results['group'][collision] = groupcollide(*args) + + for (collision, args) in self.__collisions['sprite'].items(): + collision_results['sprite'][collision] = spritecollide(*args) + + for (collision, args) in self.__collisions['foreach_sprite'].items(): + arg_list = list(args) + sprite_list = arg_list[0] + for sprite in sprite_list: + arg_list[0] = sprite + args = tuple(arg_list) + collision_results['foreach_sprite'][sprite] = spritecollide(*args) + + for bullet in self.__entities.player_bullets: + collision_result = spritecollide(bullet, self.__scene_elements.iron_group, bullet.enhanced, None) + if collision_result: + bullet.kill() + + for player_tank in self.__entities.player_tanks: + for food in self.__entities.foods: + collision_result = collide_rect(player_tank, food) + if collision_result: + self.__dispatch_food_effect(food, player_tank) + + # --我方子弹撞敌方坦克 + for tank in self.__entities.enemy_tanks: + if collision_results['foreach_sprite'][tank]: + if tank.food: + self.__entities.add(tank.food) + tank.clear_food() + if tank.decrease_level(): + self.__play_sound('bang') + self.__total_enemy_num -= 1 + + # --敌方子弹撞我方坦克 + for tank in self.__entities.player_tanks: + if collision_results['foreach_sprite'][tank]: + if tank.protected: + self.__play_sound('blast') + else: + if tank.decrease_level(): + self.__play_sound('bang') + if tank.health < 0: + self.__entities.remove(tank) + + if collision_results['sprite']['PlayerBulletWithHome'] or collision_results['sprite']['EnemyBulletWithHome']: + self.__is_win_flag = False + self.__has_next_loop = False + self.__play_sound('bang') + self.__home.destroyed = True + + if collision_results['group']['PlayerTankWithTree']: + self.__play_sound('hit') + + def _draw_interface(self): + screen = TankGame().screen + screen.fill((0, 0, 0)) + screen.blit(self.__background_img, (0, 0)) + self.__scene_elements.draw(screen, 1) + self.__entities.draw(screen, 1) + self.__scene_elements.draw(screen, 2) + self.__home.draw(screen) + self.__entities.draw(screen, 2) + self.__draw_game_panel() + pygame.display.flip() + + def _main_loop(self): + clock = pygame.time.Clock() + # cheat for test + # self.__tank_player1.improve_level() + # self.__tank_player1.improve_level() + # self.__tank_player1.protected = True + while self.__has_next_loop: + # 用户事件捕捉 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + # --敌方坦克生成 + elif event.type == self.__generate_enemies_event: + if self.max_enemy_num > len(self.__entities.enemy_tanks): + for position in self.__enemy_spawn_point: + if len(self.__entities.enemy_tanks) == self.__total_enemy_num: + break + enemy_tank = self.__tank_factory.create_tank(position, TankFactory.ENEMY_TANK) + if spritecollide(enemy_tank, self.__entities.enemy_tanks, False, None) or\ + spritecollide(enemy_tank, self.__entities.player_tanks, False, None): + del enemy_tank + else: + self.__entities.add(enemy_tank) + # --用户按键 + self.__dispatch_player_operation() + # 碰撞检测 + self.__dispatch_collisions() + self.__entities.update(self.__scene_elements, self.__home) + self._draw_interface() + # 我方坦克都挂了 + if len(self.__entities.player_tanks) == 0: + self.__is_win_flag = False + self.__has_next_loop = False + # 敌方坦克都挂了 + if self.__total_enemy_num <= 0: + self.__is_win_flag = True + self.__has_next_loop = False + + clock.tick(60) + + def __init_collision_config(self): + self.__collisions = { + 'group': { + 'PlayerBulletWithBrick': (self.__entities.player_bullets, self.__scene_elements.brick_group, True, True), + 'EnemyBulletWithBrick': (self.__entities.enemy_bullets, self.__scene_elements.brick_group, True, True), + 'EnemyBulletWithIron': (self.__entities.enemy_bullets, self.__scene_elements.iron_group, True, False), + 'BulletWithBullet': (self.__entities.player_bullets, self.__entities.enemy_bullets, True, True), + 'PlayerTankWithTree': (self.__entities.player_tanks, self.__scene_elements.tree_group, False, False), + }, + 'sprite': { + 'EnemyBulletWithHome': (self.__home, self.__entities.enemy_bullets, True, None), + 'PlayerBulletWithHome': (self.__home, self.__entities.player_bullets, True, None), + + }, + 'foreach_sprite': { + 'PlayerTankWithEnemyBullet': (self.__entities.player_tanks, self.__entities.enemy_bullets, True, None), + 'EnemyTankWithPlayerBullet': (self.__entities.enemy_tanks, self.__entities.player_bullets, True, None), + } + } + + def __init_tanks(self): + self.__tank_player1 = self.__tank_factory.create_tank( + self.__player_spawn_point[0], TankFactory.PLAYER1_TANK + ) + self.__entities.add(self.__tank_player1) + + self.__tank_player2 = None + if TankGame().multiplayer_mode: + self.__tank_player2 = self.__tank_factory.create_tank( + self.__player_spawn_point[1], TankFactory.PLAYER2_TANK + ) + self.__entities.add(self.__tank_player2) + # 敌方坦克 + for position in self.__enemy_spawn_point: + self.__entities.add( + self.__tank_factory.create_tank(position, TankFactory.ENEMY_TANK) + ) + + def __init_user_event(self): + self.__generate_enemies_event = pygame.constants.USEREVENT + pygame.time.set_timer(self.__generate_enemies_event, 20000) + + def __init_entities(self): + self.__entities = EntityGroup() + + def show(self): + self._init_game_window() + self._init_text() + self.__load_level_file() + self.__init_entities() + self.__init_user_event() + self.__init_tanks() + self.__init_collision_config() + self.__play_sound('start') + self.__is_win_flag = False + self.__has_next_loop = True + self._main_loop() + TankGame().is_win = self.__is_win_flag + + + '''显示游戏面板''' + def __draw_game_panel(self): + color_white = (255, 255, 255) + dynamic_text_tips = { + 16: {'text': 'Health: %s' % self.__tank_player1.health}, + 17: {'text': 'Level: %s' % self.__tank_player1._level}, + 23: {'text': 'Game Level: %s' % (TankGame().level + 1)}, + 24: {'text': 'Remain Enemy: %s' % self.__total_enemy_num} + } + if self.__tank_player2: + dynamic_text_tips[20] = {'text': 'Health: %s' % self.__tank_player2.health} + dynamic_text_tips[21] = {'text': 'Level: %s' % self.__tank_player2._level} + else: + dynamic_text_tips[20] = {'text': 'Health: %s' % None} + dynamic_text_tips[21] = {'text': 'Level: %s' % None} + + for pos, tip in dynamic_text_tips.items(): + tip['render'] = self.__font.render(tip['text'], True, color_white) + tip['rect'] = tip['render'].get_rect() + tip['rect'].left, tip['rect'].top = self.__screen_width + 5, self.__screen_height * pos / 30 + + screen = TankGame().screen + for pos, tip in self.__fix_text_tips.items(): + screen.blit(tip['render'], tip['rect']) + for pos, tip in dynamic_text_tips.items(): + screen.blit(tip['render'], tip['rect']) + + + def __load_level_file(self): + self.__scene_elements = groups.SceneElementsGroup() + + elems_map = { + 'B': SceneFactory.BRICK, + 'I': SceneFactory.IRON, + 'C': SceneFactory.ICE, + 'T': SceneFactory.TREE, + 'R': SceneFactory.RIVER_1 + } + + home_walls_position = [] + home_position = () + + f = open(TankGame().level_file, errors='ignore') + num_row = -1 + for line in f.readlines(): + line = line.strip('\n') + # 注释 + if line.startswith('#') or (not line): + continue + # 敌方坦克总数量 + elif line.startswith('%TOTALENEMYNUM'): + self.__total_enemy_num = 15 + TankGame().level #int(line.split(':')[-1]) + # 场上敌方坦克最大数量 + elif line.startswith('%MAXENEMYNUM'): + self.max_enemy_num = 15 + TankGame().level #int(line.split(':')[-1]) + # 大本营位置 + elif line.startswith('%HOMEPOS'): + home_position = line.split(':')[-1] + home_position = [ + int(home_position.split(',')[0]), int(home_position.split(',')[1]) + ] + home_position = ( + self.__border_len + home_position[0] * self.__grid_size, + self.__border_len + home_position[1] * self.__grid_size + ) + # 大本营周围位置 + elif line.startswith('%HOMEAROUNDPOS'): + home_walls_position = line.split(':')[-1] + home_walls_position = [ + [ + int(pos.split(',')[0]), int(pos.split(',')[1]) + ] for pos in home_walls_position.split(' ') + ] + home_walls_position = [ + ( + self.__border_len + pos[0] * self.__grid_size, self.__border_len + pos[1] * self.__grid_size + ) for pos in home_walls_position + ] + # 我方坦克初始位置 + elif line.startswith('%PLAYERTANKPOS'): + self.__player_spawn_point = line.split(':')[-1] + self.__player_spawn_point = [ + [ + int(pos.split(',')[0]), int(pos.split(',')[1]) + ] for pos in self.__player_spawn_point.split(' ') + ] + self.__player_spawn_point = [ + ( + self.__border_len + pos[0] * self.__grid_size, self.__border_len + pos[1] * self.__grid_size + ) for pos in self.__player_spawn_point + ] + # 敌方坦克初始位置 + elif line.startswith('%ENEMYTANKPOS'): + self.__enemy_spawn_point = line.split(':')[-1] + self.__enemy_spawn_point = [ + [ + int(pos.split(',')[0]), int(pos.split(',')[1]) + ] for pos in self.__enemy_spawn_point.split(' ') + ] + self.__enemy_spawn_point = [ + ( + self.__border_len + pos[0] * self.__grid_size, self.__border_len + pos[1] * self.__grid_size + ) for pos in self.__enemy_spawn_point + ] + # 地图元素 + else: + num_row += 1 + for num_col, elem in enumerate(line.split(' ')): + position = self.__border_len + num_col * self.__grid_size, self.__border_len + num_row * self.__grid_size + + scene_element = None + if elem in elems_map: + scene_element = self.__scene_factory.create_element(position, elems_map[elem]) + elif elem == 'R': + scene_element = self.__scene_factory.create_element( + position, random.choice([SceneFactory.RIVER_1, SceneFactory.RIVER_2]) + ) + if scene_element is not None: + self.__scene_elements.add(scene_element) + self.__home = Home(position=home_position, imagefile=self.__home_images, walls_position=home_walls_position) \ No newline at end of file diff --git a/modules/views/GameOverView.py b/modules/views/GameOverView.py new file mode 100644 index 0000000..37c8b76 --- /dev/null +++ b/modules/views/GameOverView.py @@ -0,0 +1,95 @@ +import sys +import pygame + +from modules.TankGame import TankGame +from modules.views.AbstractView import AbstractView + + +class GameOverView(AbstractView): + + def _init_resources(self): + config = self.config + self.__background_img = pygame.image.load(config.OTHER_IMAGE_PATHS.get('background')) + self.__gameover_logo = pygame.image.load(config.OTHER_IMAGE_PATHS.get('gameover')) + self.__gameover_logo = pygame.transform.scale(self.__gameover_logo, (150, 75)) + self.__font = pygame.font.Font(config.FONTPATH, config.WIDTH // 12) + self.__tank_cursor = pygame.image.load( + config.PLAYER_TANK_IMAGE_PATHS.get('player1')[0] + ).convert_alpha().subsurface((0, 144), (48, 48)) + + def _init_text(self): + config = self.config + if TankGame().is_win: + self.__font_render = self.__font.render('Congratulations, You win!', True, (255, 255, 255)) + else: + self.__font_render = self.__font.render('Sorry, You fail!', True, (255, 0, 0)) + self.__font_rect = self.__font_render.get_rect() + self.__font_rect.centerx, self.__font_rect.centery = config.WIDTH / 2, config.HEIGHT / 3 + self.__restart_render_white = self.__font.render('RESTART', True, (255, 255, 255)) + self.__restart_render_red = self.__font.render('RESTART', True, (255, 0, 0)) + self.__quit_render_white = self.__font.render('QUIT', True, (255, 255, 255)) + self.__quit_render_red = self.__font.render('QUIT', True, (255, 0, 0)) + + def _init_logo(self): + config = self.config + self.__gameover_logo_rect = self.__gameover_logo.get_rect() + self.__gameover_logo_rect.midtop = config.WIDTH / 2, config.HEIGHT / 8 + + def _draw_interface(self): + screen = TankGame().screen + screen.blit(self.__background_img, (0, 0)) + + if self.__gameover_show_flag: + screen.blit(self.__gameover_logo, self.__gameover_logo_rect) + + screen.blit(self.__font_render, self.__font_rect) + + if not self.__is_quit_game: + screen.blit(self.__tank_cursor, self.__tank_rect) + screen.blit(self.__restart_render_red, self.__restart_rect) + screen.blit(self.__quit_render_white, self.__quit_rect) + else: + screen.blit(self.__tank_cursor, self.__tank_rect) + screen.blit(self.__restart_render_white, self.__restart_rect) + screen.blit(self.__quit_render_red, self.__quit_rect) + + def _init_bottons(self): + config = self.config + self.__tank_rect = self.__tank_cursor.get_rect() + self.__restart_rect = self.__restart_render_white.get_rect() + self.__restart_rect.left, self.__restart_rect.top = config.WIDTH / 2.4, config.HEIGHT / 2 + self.__quit_rect = self.__quit_render_white.get_rect() + self.__quit_rect.left, self.__quit_rect.top = config.WIDTH / 2.4, config.HEIGHT / 1.6 + + def _main_loop(self): + gameover_flash_time = 25 + gameover_flash_count = 0 + self.__gameover_show_flag = True + self.__is_quit_game = False + + clock = pygame.time.Clock() + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_RETURN: + TankGame().quit_game_flag = self.__is_quit_game + return + elif event.key in [pygame.K_UP, pygame.K_DOWN, pygame.K_w, pygame.K_s]: + self.__is_quit_game = not self.__is_quit_game + + gameover_flash_count += 1 + if gameover_flash_count > gameover_flash_time: + self.__gameover_show_flag = not self.__gameover_show_flag + gameover_flash_count = 0 + if self.__is_quit_game: + self.__tank_rect.right, self.__tank_rect.top = self.__quit_rect.left - 10, self.__quit_rect.top + else: + self.__tank_rect.right, self.__tank_rect.top = self.__restart_rect.left - 10, self.__restart_rect.top + + self._draw_interface() + + pygame.display.update() + clock.tick(60) diff --git a/modules/views/GameStartView.py b/modules/views/GameStartView.py new file mode 100644 index 0000000..d507a71 --- /dev/null +++ b/modules/views/GameStartView.py @@ -0,0 +1,92 @@ + +import sys +import pygame + +from modules.TankGame import TankGame +from modules.views.AbstractView import AbstractView + + +class GameStartView(AbstractView): + + def _init_resources(self): + config = self.config + self.__background_img = pygame.image.load(config.OTHER_IMAGE_PATHS.get('background')) + self.__font = pygame.font.Font(config.FONTPATH, config.WIDTH // 20) + self.__logo_img = pygame.image.load(config.OTHER_IMAGE_PATHS.get('logo')) + self.__logo_img = pygame.transform.scale(self.__logo_img, (446, 70)) + self.__tank_cursor = pygame.image.load( + config.PLAYER_TANK_IMAGE_PATHS.get('player1')[0] + ).convert_alpha().subsurface((0, 144), (48, 48)) + + def _init_logo(self): + config = self.config + self.__logo_rect = self.__logo_img.get_rect() + self.__logo_rect.centerx, self.__logo_rect.centery = config.WIDTH / 2, config.HEIGHT // 4 + + def _init_text(self): + color_white = (255, 255, 255) + color_red = (255, 0, 0) + config = self.config + self.__player_render_white = self.__font.render('1 PLAYER', True, color_white) + self.__player_render_red = self.__font.render('1 PLAYER', True, color_red) + self.__players_render_white = self.__font.render('2 PLAYERS', True, color_white) + self.__players_render_red = self.__font.render('2 PLAYERS', True, color_red) + self.__game_tip = self.__font.render('press to start', True, color_white) + self.__game_tip_rect = self.__game_tip.get_rect() + self.__game_tip_rect.centerx, self.__game_tip_rect.top = config.WIDTH / 2, config.HEIGHT / 1.4 + + def _init_bottons(self): + config = self.config + self.__player_rect = self.__player_render_white.get_rect() + self.__player_rect.left, self.__player_rect.top = config.WIDTH / 2.8, config.HEIGHT / 2.5 + self.__players_rect = self.__players_render_white.get_rect() + self.__players_rect.left, self.__players_rect.top = config.WIDTH / 2.8, config.HEIGHT / 2 + self.__tank_rect = self.__tank_cursor.get_rect() + + def _draw_interface(self): + screen = TankGame().screen + screen.blit(self.__background_img, (0, 0)) + screen.blit(self.__logo_img, self.__logo_rect) + if self.__game_tip_show_flag: + screen.blit(self.__game_tip, self.__game_tip_rect) + + if not self.__is_multiplayer_mode: + screen.blit(self.__tank_cursor, self.__tank_rect) + screen.blit(self.__player_render_red, self.__player_rect) + screen.blit(self.__players_render_white, self.__players_rect) + else: + screen.blit(self.__tank_cursor, self.__tank_rect) + screen.blit(self.__player_render_white, self.__player_rect) + screen.blit(self.__players_render_red, self.__players_rect) + + def _main_loop(self): + game_tip_flash_time = 25 + game_tip_flash_count = 0 + self.__game_tip_show_flag = True + self.__is_multiplayer_mode = False + clock = pygame.time.Clock() + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_RETURN: + TankGame().multiplayer_mode = self.__is_multiplayer_mode + return + elif event.key == pygame.K_UP or event.key == pygame.K_DOWN or event.key == pygame.K_w or event.key == pygame.K_s: + self.__is_multiplayer_mode = not self.__is_multiplayer_mode + + game_tip_flash_count += 1 + if game_tip_flash_count > game_tip_flash_time: + self.__game_tip_show_flag = not self.__game_tip_show_flag + game_tip_flash_count = 0 + + if self.__is_multiplayer_mode: + self.__tank_rect.right, self.__tank_rect.top = self.__players_rect.left - 10, self.__players_rect.top + else: + self.__tank_rect.right, self.__tank_rect.top = self.__player_rect.left - 10, self.__player_rect.top + + self._draw_interface() + pygame.display.update() + clock.tick(60) diff --git a/modules/views/SwitchLevelView.py b/modules/views/SwitchLevelView.py new file mode 100644 index 0000000..ff616cc --- /dev/null +++ b/modules/views/SwitchLevelView.py @@ -0,0 +1,80 @@ +import sys +import pygame + +from modules.TankGame import TankGame +from modules.views.AbstractView import AbstractView + + +class SwitchLevelView(AbstractView): + + def _init_resources(self): + config = self.config + self.__loadbar = pygame.image.load(config.OTHER_IMAGE_PATHS.get('loadbar')).convert_alpha() + self.__background_img = pygame.image.load(config.OTHER_IMAGE_PATHS.get('background')) + self.__logo_img = pygame.image.load(config.OTHER_IMAGE_PATHS.get('logo')) + self.__logo_img = pygame.transform.scale(self.__logo_img, (446, 70)) + self.__font = pygame.font.Font(config.FONTPATH, config.WIDTH // 20) + self.__tank_cursor_img = pygame.image.load( + config.ENEMY_TANK_IMAGE_PATHS.get('1')[0] + ).convert_alpha().subsurface((0, 144), (48, 48)) + + def _init_text(self): + config = self.config + self.__font_render = self.__font.render( + 'LEVEL%d' % (TankGame().level + 1), + True, + (255, 255, 255) # White + ) + self.__font_rect = self.__font_render.get_rect() + self.__font_rect.centerx, self.__font_rect.centery = config.WIDTH / 2, config.HEIGHT / 2 + + def _init_loadbar(self): + config = self.config + self.__loadbar_rect = self.__loadbar.get_rect() + self.__loadbar_rect.centerx, self.__loadbar_rect.centery = config.WIDTH / 2, config.HEIGHT / 1.4 + self.__tank_rect = self.__tank_cursor_img.get_rect() + self.__tank_rect.left = self.__loadbar_rect.left + self.__tank_rect.centery = self.__loadbar_rect.centery + + def _init_logo(self): + self.__logo_rect = self.__logo_img.get_rect() + self.__logo_rect.centerx, self.__logo_rect.centery = self.config.WIDTH / 2, self.config.HEIGHT // 4 + + def _draw_interface(self): + screen = TankGame().screen + screen.blit(self.__background_img, (0, 0)) + screen.blit(self.__logo_img, self.__logo_rect) + screen.blit(self.__font_render, self.__font_rect) + screen.blit(self.__loadbar, self.__loadbar_rect) + screen.blit(self.__tank_cursor_img, self.__tank_rect) + pygame.draw.rect( + screen, + (192, 192, 192), # Gray + ( + self.__loadbar_rect.left + 8, + self.__loadbar_rect.top + 8, + self.__tank_rect.left - self.__loadbar_rect.left - 8, + self.__tank_rect.bottom - self.__loadbar_rect.top - 16 + ) + ) + self.__tank_rect.left += 8 + + def _main_loop(self): + load_time_left = self.__loadbar_rect.right - self.__tank_rect.right + 8 + clock = pygame.time.Clock() + + while True: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + sys.exit() + if load_time_left <= 0: + return + self._draw_interface() + load_time_left -= 8 + pygame.display.update() + clock.tick(60) + + def show(self): + self._init_loadbar() + super().show() diff --git a/modules/views/ViewManager.py b/modules/views/ViewManager.py new file mode 100644 index 0000000..da96335 --- /dev/null +++ b/modules/views/ViewManager.py @@ -0,0 +1,30 @@ +import threading + +from modules.views import * + + +class ViewManager(object): + _instance_lock = threading.Lock() + _init_flag = False + + def __init__(self): + self.__views = { + 'SwitchLevel': SwitchLevelView(), + 'GameOver': GameOverView(), + 'GameStart': GameStartView(), + 'GameLevelView': GameLevelView(), + } + + def __new__(cls, *args, **kwargs): + if not hasattr(ViewManager, "_instance"): + with ViewManager._instance_lock: + if not hasattr(ViewManager, "_instance"): + ViewManager._instance = object.__new__(cls) + return ViewManager._instance + + def show(self, view: str): + if view not in self.__views: + raise Exception('View is not found!') + else: + self.__views[view].show() + diff --git a/modules/views/__init__.py b/modules/views/__init__.py new file mode 100644 index 0000000..520f8d6 --- /dev/null +++ b/modules/views/__init__.py @@ -0,0 +1,6 @@ +from modules.views.GameOverView import GameOverView +from modules.views.GameStartView import GameStartView +from modules.views.SwitchLevelView import SwitchLevelView +from modules.views.GameLevelView import GameLevelView +from modules.views.AbstractView import AbstractView +from modules.views.ViewManager import ViewManager diff --git a/modules/views/__pycache__/AbstractView.cpython-310.pyc b/modules/views/__pycache__/AbstractView.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ab9dadda289216afed6a7a021d971a98fb01ebb9 GIT binary patch literal 1782 zcmbtV%}(1u5Z<+�d@w1ZYK3kF9b+Jyum!6@i3$L8^cXMX4;4T~dd{8+JE@L{zE- z4-$^NN*`gbJ@w43y>!M7A*P`{;Am&Y>)H8cc77s?#R7rndqo8YHX%RoW%_a8Nwn;7Fv_|3GYFizd0Fn9ZC^!W`~g*tHC!yQG@=38%o{|4sYPj z^aH2~!T|`Jpw*hiD6=j}&E`&G^@4)M49mh^mgSfWJje2^0NiDB%mbchMK%w-z)GwP ze2y)!Mc^K*fG11F+c;EO1`YiwBkAy^gC12P9op{8pMD=E%+bMp$E|N8y!xCWAhJYA%n027fj|yqB=FS_%_0jO`v*vaZM$`CR@= z&uPns9p~7RE1HZl*nB!W${|0=LOZ&#M3V~6n{0Q`gqdP8{FF!9*iEjDqX%7XoR9k- z_Kb7V3t?LglyUf3sO18HLgiyO$O;nd)Vqp@{B?pb^4mgmpTieb24c~9=r|XC);Czc z?^n*`L@L(QP4OB}X%L&y5Fz>NDgIrt8fp%AuAJZs7R1FsrsWdHyG literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/AbstractView.cpython-312.pyc b/modules/views/__pycache__/AbstractView.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecfca65f5c20584f03fc86c001b18c2fdaf6b207 GIT binary patch literal 2347 zcmb_e-D?|15Z^uBNvn^uY%7T)SxuC$w$~QF6!Kt7pkRobw1(0&6rpm+y0ari(kXjq zD<@L$gI`JljUh$!sT2yuL!h09*}0wB{q4-o z%-+wk93wy%$+q@Ih>+j#BOu8a2A4r-6OCxJO7h-F^Ax^?s!$8%LzD>QD$zo_L=$!K zG3$k5KYkCQ10up>-@G%H&q7&RVFKBd^O^7hKWeI zm&+^5g@#?aRpd1o8{DYqC97aTh?+%Ss2SQ;RW}RUaB#CQ>c&#Tc9`mItF}&#se+W}3#^qIJE>=@X@r6j>(fT`_9=XIg@Jghi|7Dcp$DQI}(?uryHdrfzyVgxy4 z>36NEP^dVGDE}Qw_CmF8Se8*YTbU`2`8v$5{{b+mYP{G4R7>X@#gaaGbK}~@e+R_` zbPM`#5ZWY4EEqkSmbsOnwFO2n2ARG>zFZ~bD|(Ms!Xs*59N8CBZGvvUjj8|O+^~Ks zZhIX!3y>(WDzkUazdNB<%pKu z&>iv9&p*21h_UfK=(0KM%~A^`Fb7;19!p ykBoJER9*Xtlf7ggcx$fkCD;L9J97b8KSU{gM&|w?m;MaDN#%!^{~|EBxc>lEOT5Pb literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/AbstractView.cpython-38.pyc b/modules/views/__pycache__/AbstractView.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e6ae65ec81fb417f1a65cf1409bf81404330edc6 GIT binary patch literal 1796 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 literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameLevelView.cpython-312.pyc b/modules/views/__pycache__/GameLevelView.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1cbdd071183379a66b08bf5bd134edaad281378a GIT binary patch literal 25977 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 F{{`x{6afGL literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameOverView.cpython-310.pyc b/modules/views/__pycache__/GameOverView.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b486b67d54d4e1e9f0ff4afaedc705f71a03e5e6 GIT binary patch literal 3624 zcmaJ^TW=f36`t7}mlP?{l5ES8c=0wuI7(+x~07_2x;iWJFJ zW|x*FNI(GxeeP3%_KA8-eoBABy!NI13GG9Z@61v(MaibHXJ*cvGc#xAI~PTTLXP40 zuemsQGR@e(X)ykCFj&DCe-0v<TVCZDTWzajS8Yx_yX|z`s>|5}CLQU1&!ii= zuk5NP`BPT%23UcWOI-Vvpu77Z=!EF!SGVIt1-0bQ&2Ya)65~G$gB5&c_mI(!RZDVd zeb1`4w55XKqZ>&dLlq0PuCnMdo(0(PI)dD`*ui%^-J_}DhIi;M3b?etfW zBi3TaJmD>?Zy)iN(|095!QT-R-WjenNgI}XjBvqQzUM=d@n+@&l9nfOhZFYi2sGW8cNPX#X<>C6K zc=Yw^gLUy_wes+(wi{uh-x1?CC&cR`iDsvvuTM;$o>H`f`Wz>#td=*<9IpU#a36^X+Iu^J&c(g$ zxToqtE!2w>3nhS@sP$AFsUIxu#9_Ox3b>RXn0gP*|JLr^-Fg;>D&AU^oo2U5piCmQ zwHC&^Nwl{``ul;}>O`{F4&$vCfNQ)pelfTA4)lzGY9dq^M?F;wWAd$d9>n8U@HfjB zxW}it^;6#R|9^P>jQWIX?TrZi5$l~I^c8Da>JmnF-yy#M`fQ-j?GhG==YZ#?JaF8; zcLH6J0VaLvEitrNnOR~MFx$$AoS{=gU4OJ*evFf@Rv2=!Bbn(jPAW5FP@F3tUb`1{ z8@SJ2J4l*QH~wh(dDL6pZ+351O7`F<*rVP*C5OeQkx~b#NIht_ZIJ|gt#g>9 zH!xB2Had8JL`_iMw+zZm?3CP~%$3#>s}ss>;Tc@mW%U8H20lnBlRg|BOML`#?vl<# z74u5wEfj66y-riYN#ABP1*4mgjXe;L=lS)E%_O;VW>OL~W|HeA3{J;kD9j{tkQyvb z#yjfDkmq9L8Ez_*!5D$vNM+;S52eW2rpBbm$qHj*a;O;^({;T;r#PWQpXVBWc0 zE?xlf5r#dh$cvVt@PQ&m^L#QWpH)AHjFAJhuqN()(gA>qp)_Khd0FQ{iO z>r3iU1WUcfX@~Vh+vGTO)oO*vGLeZ(ETnN`J4zA+@83cqrh0LubO~3I)-f^{@)GJsP@Y(nyH41#on`2othL6zy>sjwIjsyh{;s7y zNUVPLgmIRj&Z73a%fs0`X1_we0Lf|e@8WWKGV_Xw;?SAWxl5Rz#W#m1y0FP)B?+CJ`IzPdzp$<;8TO$hBSM#;)`)ydQ{j3thCk_CHTmzaXHQ(iKPG Jd6Wk8_Rp0Up$h;2 literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameOverView.cpython-312.pyc b/modules/views/__pycache__/GameOverView.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..462f3557507cb7ae25591d005cb349243641a7c6 GIT binary patch literal 7958 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 literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameOverView.cpython-38.pyc b/modules/views/__pycache__/GameOverView.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6156edfaedfd7ecd419aaf4f229f5c20acb4f2b GIT binary patch literal 3612 zcmaJ^&2k&Z5uTm>!2$$Gij*aalxfOJQbt8l*>O@%T#ijfq<+E#Qb;f^q3D`gViq7k zaF?E4h$4$T$(3_XsY*`3EzSevA@T@Qx#fgMh!1wYo&_loqy!XtW_r43rl-H|X>65B z1%}VRXOrOBBxC=j!RW`qU>U#UGZ4w7)nT=)wQ3f|yufTH#@xBt}0RgJt~8?jfTc zYg}5Af5U3Fw55X&d(U&KUcO$9&CJcySK$#Ezic=2O zi4;L}?w}JKh3X?kW|g^V27fXA!G~xRNtI`{SC6ActEs(%BU((mt^J@GYNrziQeS&o zeZ00Ip8R3u(VBR+QhmIs?Pi$jcg5(<3GwPANKZGuC-HH%c0@+ShJU z4?5Va5l5+Z9uoB*KCM(~EA4*yWEIWq*kVTZ=Cj|gJjcnZE0y&N$1A}c+(#;c&cSY= z3rTk;>8eIh5B2=mLMb38>Rpw@>RYazB0_Y95Ej zyRGfjFxgAvgKg414Al01EW4dB*?s}2CflQza{u5+Pl;C4N`(rOxU1@6LUEPc0AZGA z-N1LonnQ2$2cL7szdycxVSzE_`Wx~2Pb_$b&sVI?)%zIPJ%^$K*t3B>H<}sp9Pr$X z2aenG`p^|QAkvrK0z;dZxdp~)#hfS@Ix*Ds&(|xCaI)1(Lr(r&W^#m+$xImx7b?fM z9>h^o1!=bvq^&qg?kzo!yGw_y=uWk44}O3>>c?l~czQEd>L?Rw1g*}UvYpM+g=Dy< za2?nnwcN(qW_4wws+~V>J*k$bjYk#DYp<0EY@rs+K!uSE)g@36y5KM~=L72K*Hb+= z2A!c)Jyr8&vBzsq9zCw=Ts@4^P`y0s9O=7bihx2I0G-(m;&8W>hWgIig;Xf@(wNBC zU4tt+=5Ue4w@6?GwS;D6*yP^-rc%1q{zmO+^-`2uSoFSc#r8C=*E^%H0fe2{W3a~z#W-2=IF zNf&a8@sja{qK&n;-;xN^w;4^T=niBP4}^>^UTr4HT{4rNKx5`V&`BAB&Vr#Zlgz=x zz%4S~QTK*C7bDMbGnpL5Nb5!_pQJ-63bu(6DGIXE$e03ZipJ50Z_t@OBB`q|jI^`UX{Blw2EF;Nlim1GG&(_38OMAAVf9lYKO?n;F$f~w3{J^a z>OGPek0Xl>0j58~wE6`IY$U&`Pl-?>9|8Q7kSaI?>Jg>% zCJ^3|IS>ZSPjb(i=F>#+o#8~sQ}RXiOSm|Pe;Z5U?#JN|ObkQ8MWRI!WI`cFp7VXh`jNvQ)zx|KK8PSq2}NJMxXzEQ7&e2M7M9^NPSK{ zb6H1IORv>USyc z<@?NHDJm>#zy4r2Tf{8&OOTvIU*T%4bm|oo(^R2uvft zSXd3O<|piwpYRiF&r$!v95ZvMcfp0E`VZ(k?HkgYBiFyvzG+-KCvIUhCvHZIXy?!8 z=f~$ySZ~2tz}vTb?^5r??k&n(--0!Z#?5|Za0{1Z!ngWxK=0q6K!hss@_ULJ^&29n z+nILK78P_4I&pnZyWtBwPHHBbI64T`2c}CAr0wJ=(N6dh-Q4=x^VO$cR>>*7$`>mtdp^IJLyIo4oKyQT} zt%QnH?R5`ifOin*t?!jx6TY?C^8}B4lk5tzrFMOcSw|I|YPU`nDyn_Qv04!OK`TPt z86PZTI-xYfEC*lD@_2zy0<6AO04;)g*1T2ZzTuF>5?|y#FI;*U&eyDz^V%08LV^D?tBy)g6;n$YsOU+_!5>(BVU znZff|At~eL>0uFi|Li|h=BxQLwy90;kN&Arl&8!>SM9C+&ob4|31A7G0$0LuMfU#z DwC10Z literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameStartView.cpython-310.pyc b/modules/views/__pycache__/GameStartView.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..93136c105eaa2f8055ff43d725f1e5d5009cb1d9 GIT binary patch literal 3664 zcmai1OLH5?5#HGs79c=^6eUrlMbom&2`VW?avn}(MHVAbk1&B035rT6rlyvdB?u6} zLNg0dWKmVAk}Kz&at4mhkH`mM|j{J9w1#iwqg5td*rtD5$#$}qNDcH5~sjCfAVZF^OZSr0AY3hygR zc#-$ssrrIFw@UsHD_G?c(?KQd96Su$5$OEpu1aKBOMc&o4r?Sa`Li*&i_h#HS+rx- z7EIV*Sye|k!bOjrgpb}684;lOMONg{XT+SyqYp#@yU*(a?f5(iWx5rc*oU_9@ZF=W z{)FblYFh7D!kTv9Iblt=?+G@*--*S2a5Mb?+$_GFuve{t4gTDev@?>cNy$#h%cQ6z6lx>CtD-SE$b9^ODF=ZLwL;=oPT>B-e}jgyBBv7?LMG3c<`iLAzkgge0(3> z@~pBEUYX_6jm%AWwX3Jb+`g9^CprB4_n>+Q0G){ zSM}sxSc~-9?D`4d#%n#PV)?bLT@|(VWF9v8+L9lk`}fwpTRSgQB-PHQXg4|y0%Q`) zo%@kGNaF4e=^uu2ryYx4D^fde09Ca!WtZ#SBfY?(n{XMaxF>6oBC{*3aRXAp)+|8MBS_kSWYgikX)^{) zPI*W;A5uh@0%HKV0$K;~GfrJg^p#o58PCv^yhM`zqpimeA60aw7Il(HzC9(5mm3fFo&|AMQ7jNPqOdg=8f3C+CZ(>4mQSA1PYt zOkCHIWq8u)%1`OwS7(3ghQ7D4X zf-Z^PCaah+@#iuZk+(Gd`)&x5+7tvSV#cA@!~kwbWk?}&Ug(VgG7ddR2BRRQdf|?P z)EPsG0GQtLm}J(KdrU>Jq2u`E)3w3kTA zAd(7${$SQ6sT%nndg~-|CMB3;YUa<2`9d1=yK$1l9YuaulxZpK*UeXC$7|;W|48GE z@hJzGy!TfSiS-__3iBggVJ-(n*=ERjW<;^>nX%RM<@$(AW<^Pb6pXCC7;$qL%}wZ1 zG#4huRInFlOpf>to#Kqn;-pT=E{`g4T9ub1AxZnHCZnjM-Q89rkxO8i6fD0-lV@UV z93W~xKID6?ur5C%l^>JznfPxg-tM&!Zss+>QLG~4Lir2Q`4KfgqsBZ5eomCZ&rMJ` z>IN~spk^kZ7Pye%A>4`tMdg*06xEFYwXBG^!eYaPyHZ$M^2e$k)vHRJ9#jGUPpQHZu z#nEgYvoApxAUO~E7W~ALh4&UOj{KX>EgsnF*+_0_g1#_8FPpWXpQozJu!k+Y&n;9W z`-C01vW~SaGl!S4sZ&fIgLkocN%$*-!HdnyrZ%teD;TZt%bf-EtK<3A+4&Qzzh>@b zH$UiKCF;cKuZzrp;f}>pP##_(uTi0?JQz|pq!;~=-s`0gUwznc3cYb^poBvUU!lBOPq>XIqsQ z&&nyLi?gWH?lyn%RQuaJ)!F8U+S%qx8qj@CXE7;=aH&1nsP88!GQT87Ml=*bSo^)M z2vNgup(>266uw*u+CAu{YSd9oRYI{`1URX1sK{l+^*}9jbyHuOSLa zydOd5Ie*;?Tj`Aam`?ZuYJN)1Eo#UV@)b4ThNGeAWhE&oX7MTf$7Tf<4wehNARh$z zqM0jYM7g2X0K2F8zw0v%|hqxu7lgD>Ky``BCrLpR^HCD GW#_-^GOGUo literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameStartView.cpython-312.pyc b/modules/views/__pycache__/GameStartView.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf30524d00005667650f2dd4962aac9b0ca50a37 GIT binary patch literal 8017 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 H>H_`_`Y!MP literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/GameStartView.cpython-38.pyc b/modules/views/__pycache__/GameStartView.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bf69b0767fa1046b9c35e494abe7c36ce4c2596b GIT binary patch literal 3652 zcmai1OLH5?5uVu>79hZvUKDB3^rIZ3oKhs^;lxp7u_WqYCXgb6b_vDQ))KP>@my$T zA&M;OBvsBiS;qcNozs5~I(PA@+aQ7o-eQ%s&4?M1N9&6MR-e@cT5&50Wx5nUwGJ)g;=4yn{Tbw# zHP~yO@P^g5k9ouCyMhn!J7$3gX{PT(n#GqB)-oGdkk3qL+av8fq=o)0=F1Dm=#eCy zbq=$-11`L)Y{2{T1J+-lBN(kk!LaFUN#}OMYO^NeUPlZsVrSZE#kII-)&GG53?Gmr z(`|)^k-RDCNJYyu!@n4Qcms``A^w8)s&QwpUejLpum)FXx84qG5lt8hz3`;`XyaM% z_z&w3H-e|@qkRSjE_zVh_<>(8;T@_K1=Vsix?=4B+4AZ&H_L!DE-UDcC& zVKve#)AJ_?x1idSDwbbc+EGz!Pv+s1ubF%g%{S}!KHJ$=kyJaadZ%_29qre5?nkPb z#N8dTJqYDaI~KiGq;_5+Ox4bWPp)?l^;}Tz)RRC)D(=Z@q{!v!G6>@yzs#5LErOf< z&bKUPeS36ma)v4E>U410n8*a@FTkY13CjD{0KLG3sNgFM0qIgeTBKtKo}n2NN_J^T zQ9dL*7kzVlxddMOxMl3Sn&_+3elzz%Ly}ISy+<35A3iGUOf~8xk$iQ+9LjewY+RX= z_endKo{8qTgue1X$QgNlv~=F#Npa%bw9_#t|B8;_uYvs602{z*r{|{}aLfnj!3)MC zMq(L>Gm^Mt9ru(Z)gd3jkHQ=4WFP^+jc2pRHXxpXXYIy}@K;jLW`jI*vO!@4(xN^5 z4*QcoJt0Lq<>?v?9FP2)YiT5xkFvK$?AFocE&@ia-QFO7-dRiHHAVSJeh9nTp85Ol z=f&Cdwyr>^JsEXGB=rZ=ca`P#wdpBNhE4350Fxh+yNaZ31A0YAu7R)2RO41WI#MN@cCcXT6vFS>pi81x z$udS1WlY8${5;_AHGCk(5Cs zl?DCI^p&J$boa1ZC6zNN!K6|%ejervDdu> z$^j@3v+c=X;g*Nio7T(j0&!Z(lpdP9p<}-?ZcxiPg^z7-vbYKSS+{k4K|< zj1pgf<}7%LTjI&w8y3vddv%MA#ul2E`rC+KJjGu)#a}dY!9GtFmtze}xSujqBkPzq z9r-WJ&CD3y#HL1Z`5(wGH7*NpiQ?~4k zYE!$>OVn|>kPaMn@e=&w_T#d4Ui9jTw$-81PV@?FW^?2D{U=|QwB3vjwZ9oW+bC~8 zE2U9AKOJ}4*$lRyYHu@0Z8n1gZEprjny~wn_F_^HMW%LTy|$mEvH3X(GNP_1h_%=2 ziV!snTdp>XZdwX1j8OqVsC`tIc2v1IC9LADoM^X7hm`a{o{s8V&<^XJpcThma*ZNf zofHX==d4*IDxc>-^PnET!Sj}HBo2ao&00k-clH%Cp0rfVYCi}%RR03Jg9wgzJA%&# z!HZtlN=M`ew6{-){F2CLM92y9Ig#(7XgGRPNlJ%Vd?u^7e=()1asU7T literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/SwitchLevelView.cpython-310.pyc b/modules/views/__pycache__/SwitchLevelView.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..750ae426b87117e95389775bffbdadda68eed381 GIT binary patch literal 3233 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 literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/SwitchLevelView.cpython-38.pyc b/modules/views/__pycache__/SwitchLevelView.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ceb5338a62eb766ca14de25b1cba665606bfd366 GIT binary patch literal 3222 zcmZ`*TW=gi7Ov{s^xSO6363$FU=|P=Eo7Hn5G)JqMu`(g8wN-wfgKsO+Fd>49`{^Q z)f2~7A|WLbulp0)k9p+>AfEXN^~%%y0UlP%X8?UCwSW;RyFB6K?E2 zvD=>DcUZ%lzyfPFxb|D&VEabckHOcjY^qF#QFbqhcOn{b^k+{y>K2%o(TZ(LaA7@V zZClvFL5r1yht?G(;iL6LSya%LL{-$#`roh)7j-fB)Nhx+VGe6ou$y^3e`hDjqODu; zgE%#d^CK%;;9Y!I@u?i-5$mzXJmWnpw;%DIle>cNb2OUA=O01f9j`%7~eP>I`LHyDAD(?5i^zWZJn-)W7~|vqiho z?iV+&p;~JW3}-Bv9C6c zL3MewtLKAckYs_3)o?7MSW&L3We~Xiqx?3k z7Eun$bEH{jKVdybSm)Uik{hvVBUW8#-Git{wEDt*iJ>i1YmtRgP%*S>;?isGm2R!w zTf6nTn9$m-hCTTet$gEvOeonJHG`hK0A71C9*9^Y-p(V5q;pJ zOuzKpfl(&^V9c+t-Mq2h(xoUKWU+jB!0gIbpf>I+$ZIsZQXrVc53?80R|_BnKS1Xe zw|@5A8sA$v9d?>@0&yy8rmlPm21ucNUrD@AZx21sibqzT<}4PP#yDX=-^h^F??5epnCl8&MCjLScgl=A;%0MUGk zc}0scI_z_Th6c`@l+vJ#&jii4U^0fpsQa`Kp>NzeTK{m^{hV1i%X}PyB<*L2;LbHr=uuQsY?@TcQ5@(rpP$FO#a);6U z_kejYZ^F@SPOqBc+Oa3!;~esX12XZ!O(?Y*i$&UdDw1(L(9UL>WRfzkaL;?h{fWq1 zL`*o7_vI>)zY&=O(TPDHyXFI$iC9HxpbLQ3 zQmY`0`$+kP>EGi>eyhSOsKAT=w|;gir_|nAOEXTTC^!t?uh9W)a4M+PHRr4CP_b-tPx4FDWz&~PnourWQ z_X~@2`Mi->IUKvsG2^0fk<*m_z&?rx0X_E`XCxu3U72*ZvZL5$2|Wm|ro(7kyC~0t zOfJ$$C)*w2D*pWL&6alVkCRN>YFB9|eh42@`0A2K)F=&iwKpD#FvH+1iMAV#@ke`( z5Y7+s?z>ET@@)WY<& va{1u(UgYV@f!I7^E+2i)OM=lDI^sOD1zKJE9~M(TCe#(}1KzT54cNZ{>G2vr literal 0 HcmV?d00001 diff --git a/modules/views/__pycache__/ViewManager.cpython-310.pyc b/modules/views/__pycache__/ViewManager.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2f528c9e168aa8d9c44527fd18c88eaf90368cf0 GIT binary patch literal 1210 zcmZuw&2AGh5VpO}W|Jmu)mDfisEWj8IaK1p0U-oxp_kGg%8!U5S=+Vq({6W*?KTkQ zM0)21IJ8Gzg-7s}6R&`vFyo}K71)~DneljjKF=1-W}U$LvS^ZxfRL}Kloto(F_5_f zOcF^m(!wvx=nJw*WFYw|kzBEH&1O25c4qdgEn8aGGu^2b|=SXBldf>uhZ(pU>RfWja zKnOh#UUA@pG&7DTx@%mBFm;Vbb;4%BM=t?e05aEr)oDcQbe7gH!hl`We}%#P&oCG+ zUPZ`fa2%0N8Qi*DC?okf!(U@WM`WLzP+jwI(GOl9(PeVR&Y{)mybTvH{%YT>=7nAD z6vw%|9S3>_BDmVqcd0tE{UV34=oN#Q=?2*Kb!0dorB-f$x(sAOVA#q68_t(Y#{k>$ z430w%(<_9l3o#iSkQ+k0Jx;ReNzL}ON@PFpI=%%EYXk}W{Ty|&q^sw^;Nf!t45h~G zrHXuQ9$|bitjJ*D5s6^xA{IppRsWPR*DGLm&FKKIA*@C(g3X`*FQkhePP`xCukG7~ IxNIr-4KJpd_@aM60TQN*gIq_kh$2%gSo&UBHg9>CA!y z_<$-7t<@F#8jq1VC51cEBqV6y_GX;ljBXN7?R*TGh|z}6gP7rkku)iq}5 ze-TU>OtP^oL4PQ9aB>4d6&y%28`6pbj+zhoM$L7%4%52L(g9o9f^?7$Oo#Bu@VsK{ zTUxqpEnoy?#$ZR?1W*29iRi_|B*R3Vz(^ZGdFriu3;;w8b=;To>q-7r3^#@r%iY~Fm^C7QR^Sx>8M>C z-MLhIWo*ZM8rJ*UzSh2ro}dl9P>cWyV)#E9#Uxvc;ri4-mhIND_`E62Hy)Z|o{u+y zwUo1I+Y({Or4zl85BsROR$#YIho-mLC_XYBe||Q2RwKu}*EP*Jgl1o=Pr@V!R>sbm z!^~eE@3uMzWrnnpVXTM1(q$bZAcKpRuw0jON>p|}suZ z@ThZqzjOR4DDCgFTHnz9ji06u`=)9Wum6&IkoxtFgNgU(SFrXc?UYk@JF|^ z&a#^;6|o@~OJzgh#Cbl5lb}oZZ+;2!dc5_`$(%9}S8&>d<4A1Vtyb<-_9Mw!*TCN3 z)q}3dz3AklX#D$`Z)WcG>_>-=qRIVe@{i~Ur%I)a2(@n!KQX2$+f4Jk(Gf>Y^UD>h zP}hXrMebO3uDBqz8RQM`MQ614`hLD(E$~hhc&w1BK(bM;55PO)oG|o89tEkx#5hh{ zaC{-TJy*SX=jOqMk=}CvlPO^)J$8 zDz)H!DD$H8*9g(oykpNo@0=UH%MFxKIR)81Q5jpgz*oY70_OVp9j?#{am9Z@p z-8<$DD|W8rf>(Ct(#>hk-npWxYEXu4bCfS?=KL5G4G{TSX8YfWYJttKXKRl;yILyU z$fvV_aGvI=;T&hG-C&td-RJjc zv21*4cm+HhP910)y&nNH0G*%{rtcftXJ41;zni-ThBhYW)KFe|PacrhL)S_#h zexdm+-i+xIIb-L9!t%QYM+=x^CDki=VOI8wqg>nyJ=KI5w*KN%A`eYk)Y_LajjJQs5B5!Lk&Y#)7DJQ>{%Zp2SypLa&_o z0w>mKsnQ~Bc|E&3UeDUqaM&j}K8}nSQ9?eQ(;gjkM!3ubO+gB(h^CBEhdZjHJ?1so zQ@##Z&|qJ6b;!a72P)D%)@yKA_4R-a5QiB_qA#pS61s|SgqHWUgvU}Y(H}ZLvjXfU zaF8uaJAIkRTBVKMhY*b` zydn(8$g#nz!gS0WS9wiXj+JAR+oJB&b6n#M(R7*wQmbQsY3UA`wyvpQcQM2JkR>W_ z>wF+7%A&9_NJ8lk`z&U>%qbUImk*Id>M!0jHSvay=p)11PHVa=#=#3`Q8!lgs9PS1 zhVn7p`%74Qz^Z2KuQJw5q4|%>(k0e3W6em}Hd>mnvpS}<2imIt1~V05etdQ6PEvnJ zQK)-@<0s}zSJKgQLeVWW+