Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bfb9688b2 | ||
|
|
e718d329d9 | ||
|
|
4dfe1e3f18 | ||
|
|
6de8fc10fb | ||
|
|
99c1645c39 |
14
.github/workflows/build-pr.yml
vendored
14
.github/workflows/build-pr.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python_version:
|
||||
- "3.12"
|
||||
- "3.11"
|
||||
name: Windows Python ${{ matrix.python_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -46,7 +46,6 @@ jobs:
|
||||
-i ./pypvz.ico
|
||||
|
||||
- name: Release the version built by pyinstaller
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
@ -68,22 +67,22 @@ jobs:
|
||||
--show-memory `
|
||||
--output-dir=out `
|
||||
--windows-icon-from-ico=pypvz.ico `
|
||||
--include-data-dir=resources=resources `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libogg-0.dll=libogg-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libopus-0.dll=libopus-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libopusfile-0.dll=libopusfile-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libjpeg-9.dll=libjpeg-9.dll `
|
||||
--include-data-dir=resources=resources `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbisfile-3.dll=libvorbisfile-3.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbis-0.dll=libvorbis-0.dll `
|
||||
--windows-disable-console `
|
||||
-o pypvz-with-python${{ matrix.python_version }}-nuitka-windows-x64.exe `
|
||||
pypvz.py
|
||||
|
||||
- name: Release the version built by nuitka
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
tag: Dev
|
||||
artifacts: ./out/*nuitka*.exe
|
||||
artifacts: ./*nuitka*.exe
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
@ -93,7 +92,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python_version:
|
||||
- "3.12"
|
||||
- "3.11"
|
||||
name: Ubuntu Python ${{ matrix.python_version }}
|
||||
steps:
|
||||
- name: 🛎️ Checkout
|
||||
@ -133,7 +132,6 @@ jobs:
|
||||
pypvz.py
|
||||
|
||||
- name: Release the version built by nuitka
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: ncipollo/release-action@v1
|
||||
with:
|
||||
allowUpdates: true
|
||||
|
||||
11
.github/workflows/build.yml
vendored
11
.github/workflows/build.yml
vendored
@ -16,7 +16,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python_version:
|
||||
- "3.12"
|
||||
- "3.11"
|
||||
name: Windows Python ${{ matrix.python_version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@ -69,11 +69,12 @@ jobs:
|
||||
--show-memory `
|
||||
--output-dir=out `
|
||||
--windows-icon-from-ico=pypvz.ico `
|
||||
--include-data-dir=resources=resources `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libogg-0.dll=libogg-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libopus-0.dll=libopus-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libopusfile-0.dll=libopusfile-0.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libjpeg-9.dll=libjpeg-9.dll `
|
||||
--include-data-dir=resources=resources `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbisfile-3.dll=libvorbisfile-3.dll `
|
||||
--include-data-file=c:\hostedtoolcache\windows\python\${{ matrix.python_version }}*\x64\lib\site-packages\pygame\libvorbis-0.dll=libvorbis-0.dll `
|
||||
--windows-disable-console `
|
||||
-o pypvz-with-python${{ matrix.python_version }}-nuitka-windows-x64.exe `
|
||||
pypvz.py
|
||||
@ -84,7 +85,7 @@ jobs:
|
||||
with:
|
||||
allowUpdates: true
|
||||
tag: Latest
|
||||
artifacts: ./out/*nuitka*.exe
|
||||
artifacts: ./*nuitka*.exe
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
linux:
|
||||
@ -93,7 +94,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python_version:
|
||||
- "3.12"
|
||||
- "3.11"
|
||||
name: Ubuntu Python ${{ matrix.python_version }}
|
||||
steps:
|
||||
- name: 🛎️ Checkout
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -4,11 +4,7 @@ test-build/
|
||||
release/
|
||||
# 忽略调试内容
|
||||
.vscode/
|
||||
# 忽略 Pycharm 项目文件
|
||||
.idea/
|
||||
__pycache__/
|
||||
*/__pycache__/
|
||||
# 忽略测试文件
|
||||
test*.py
|
||||
# uv 管理的虚拟环境
|
||||
.venv
|
||||
|
||||
@ -1 +0,0 @@
|
||||
3.12
|
||||
12
README.md
12
README.md
@ -38,17 +38,7 @@
|
||||
* 光标移动到向日葵奖杯上是显示当前各个模式通关次数
|
||||
* 含有游戏帮助界面 QwQ
|
||||
|
||||
## 环境安装
|
||||
|
||||
建议使用 [uv](https://docs.astral.sh/uv/) 安装依赖:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/wszqkzqk/pypvz.git
|
||||
cd pypvz
|
||||
uv sync
|
||||
```
|
||||
|
||||
或者参考:
|
||||
## 环境要求
|
||||
|
||||
* `Python3` (建议 >= 3.10,最好使用最新版)
|
||||
* `Python-Pygame` (建议 >= 2.0,最好使用最新版)
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
[project]
|
||||
name = "pypvz"
|
||||
version = "0.1.0"
|
||||
description = "Add your description here"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"blue>=0.9.1",
|
||||
"pygame>=2.6.1",
|
||||
"setuptools>=80.9.0",
|
||||
"wheel>=0.45.1",
|
||||
]
|
||||
43
pypvz.py
43
pypvz.py
@ -1,30 +1,24 @@
|
||||
#!/usr/bin/env python
|
||||
import logging
|
||||
import os
|
||||
import traceback
|
||||
from logging.handlers import RotatingFileHandler
|
||||
|
||||
import os
|
||||
import pygame as pg
|
||||
|
||||
from logging.handlers import RotatingFileHandler
|
||||
# 由于在后续本地模块中存在对pygame的调用,在此处必须完成pygame的初始化
|
||||
os.environ[
|
||||
'SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR'
|
||||
] = '0' # 设置临时环境变量以避免Linux下禁用x11合成器
|
||||
os.environ["SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"]="0" # 设置临时环境变量以避免Linux下禁用x11合成器
|
||||
pg.init()
|
||||
|
||||
from source import constants as c
|
||||
from source import tool
|
||||
from source.state import level, mainmenu, screen
|
||||
from source import constants as c
|
||||
from source.state import mainmenu, screen, level
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
# 日志设置
|
||||
if not os.path.exists(os.path.dirname(c.USERLOG_PATH)):
|
||||
os.makedirs(os.path.dirname(c.USERLOG_PATH))
|
||||
logger = logging.getLogger('main')
|
||||
formatter = logging.Formatter('%(asctime)s - %(levelname)s: %(message)s')
|
||||
fileHandler = RotatingFileHandler(
|
||||
c.USERLOG_PATH, 'a', 1_000_000, 0, 'utf-8'
|
||||
)
|
||||
logger = logging.getLogger("main")
|
||||
formatter = logging.Formatter("%(asctime)s - %(levelname)s: %(message)s")
|
||||
fileHandler = RotatingFileHandler(c.USERLOG_PATH, "a", 1_000_000, 0, "utf-8")
|
||||
# 设置日志文件权限,Unix为644,Windows为可读写;Python的os.chmod与Unix chmod相同,但要显式说明8进制
|
||||
os.chmod(c.USERLOG_PATH, 0o644)
|
||||
fileHandler.setFormatter(formatter)
|
||||
@ -36,16 +30,15 @@ if __name__ == '__main__':
|
||||
try:
|
||||
# 控制状态机运行
|
||||
game = tool.Control()
|
||||
state_dict = {
|
||||
c.MAIN_MENU: mainmenu.Menu(),
|
||||
c.GAME_VICTORY: screen.GameVictoryScreen(),
|
||||
c.GAME_LOSE: screen.GameLoseScreen(),
|
||||
c.LEVEL: level.Level(),
|
||||
c.AWARD_SCREEN: screen.AwardScreen(),
|
||||
c.HELP_SCREEN: screen.HelpScreen(),
|
||||
}
|
||||
state_dict = { c.MAIN_MENU: mainmenu.Menu(),
|
||||
c.GAME_VICTORY: screen.GameVictoryScreen(),
|
||||
c.GAME_LOSE: screen.GameLoseScreen(),
|
||||
c.LEVEL: level.Level(),
|
||||
c.AWARD_SCREEN: screen.AwardScreen(),
|
||||
c.HELP_SCREEN: screen.HelpScreen(),
|
||||
}
|
||||
game.setup_states(state_dict, c.MAIN_MENU)
|
||||
game.run()
|
||||
except:
|
||||
print() # 将日志输出与上文内容分隔开,增加可读性
|
||||
logger.error(f'\n{traceback.format_exc()}')
|
||||
print() # 将日志输出与上文内容分隔开,增加可读性
|
||||
logger.error(f"\n{traceback.format_exc()}")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -1,9 +1,7 @@
|
||||
import random
|
||||
|
||||
import pygame as pg
|
||||
|
||||
from .. import constants as c
|
||||
from .. import tool
|
||||
from .. import constants as c
|
||||
|
||||
|
||||
def getSunValueImage(sun_value):
|
||||
@ -23,19 +21,13 @@ def getSunValueImage(sun_value):
|
||||
image.set_colorkey(c.BLACK)
|
||||
return image
|
||||
|
||||
|
||||
def getCardPool(data):
|
||||
card_pool = {
|
||||
c.PLANT_CARD_INFO[c.PLANT_CARD_INDEX[card_name]]: data[card_name]
|
||||
for card_name in data
|
||||
}
|
||||
card_pool = {c.PLANT_CARD_INFO[c.PLANT_CARD_INDEX[card_name]]: data[card_name]
|
||||
for card_name in data}
|
||||
return card_pool
|
||||
|
||||
|
||||
class Card:
|
||||
def __init__(
|
||||
self, x: int, y: int, index: int, scale: float = 0.5, not_recommend=0
|
||||
):
|
||||
class Card():
|
||||
def __init__(self, x:int, y:int, index:int, scale:float=0.5, not_recommend=0):
|
||||
self.info = c.PLANT_CARD_INFO[index]
|
||||
self.loadFrame(self.info[c.CARD_INDEX], scale)
|
||||
self.rect = self.orig_image.get_rect()
|
||||
@ -43,21 +35,12 @@ class Card:
|
||||
self.rect.y = y
|
||||
# 绘制植物阳光消耗大小
|
||||
font = pg.font.Font(c.FONT_PATH, 12)
|
||||
self.sun_cost_img = font.render(
|
||||
str(self.info[c.SUN_INDEX]), True, c.BLACK
|
||||
)
|
||||
self.sun_cost_img = font.render(str(self.info[c.SUN_INDEX]), True, c.BLACK)
|
||||
self.sun_cost_img_rect = self.sun_cost_img.get_rect()
|
||||
sun_cost_img_x = 32 - self.sun_cost_img_rect.w
|
||||
self.orig_image.blit(
|
||||
self.sun_cost_img,
|
||||
(
|
||||
sun_cost_img_x,
|
||||
52,
|
||||
self.sun_cost_img_rect.w,
|
||||
self.sun_cost_img_rect.h,
|
||||
),
|
||||
)
|
||||
|
||||
self.orig_image.blit(self.sun_cost_img,
|
||||
(sun_cost_img_x, 52, self.sun_cost_img_rect.w, self.sun_cost_img_rect.h))
|
||||
|
||||
self.index = index
|
||||
self.sun_cost = self.info[c.SUN_INDEX]
|
||||
self.frozen_time = self.info[c.FROZEN_TIME_INDEX]
|
||||
@ -69,9 +52,7 @@ class Card:
|
||||
if self.not_recommend:
|
||||
self.orig_image.set_alpha(128)
|
||||
self.image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
self.image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
self.image.blit(self.orig_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
else:
|
||||
self.image = self.orig_image
|
||||
self.image.set_alpha(255)
|
||||
@ -81,25 +62,18 @@ class Card:
|
||||
rect = frame.get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
self.orig_image = tool.get_image(
|
||||
frame, 0, 0, width, height, c.BLACK, scale
|
||||
)
|
||||
self.orig_image = tool.get_image(frame, 0, 0, width, height, c.BLACK, scale)
|
||||
self.image = self.orig_image
|
||||
|
||||
def checkMouseClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if (
|
||||
self.rect.x <= x <= self.rect.right
|
||||
and self.rect.y <= y <= self.rect.bottom
|
||||
):
|
||||
if (self.rect.x <= x <= self.rect.right and
|
||||
self.rect.y <= y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def canClick(self, sun_value, current_time):
|
||||
if (
|
||||
self.sun_cost <= sun_value
|
||||
and (current_time - self.frozen_timer) > self.frozen_time
|
||||
):
|
||||
if self.sun_cost <= sun_value and (current_time - self.frozen_timer) > self.frozen_time:
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -112,18 +86,14 @@ class Card:
|
||||
if self.not_recommend % 2:
|
||||
self.orig_image.set_alpha(128)
|
||||
self.image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
self.image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
self.image.blit(self.orig_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
else:
|
||||
self.image = self.orig_image
|
||||
self.image.set_alpha(255)
|
||||
else:
|
||||
self.orig_image.set_alpha(64)
|
||||
self.image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
self.image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
self.image.blit(self.orig_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
|
||||
def setFrozenTime(self, current_time):
|
||||
self.frozen_timer = current_time
|
||||
@ -131,35 +101,26 @@ class Card:
|
||||
def createShowImage(self, sun_value, current_time):
|
||||
# 有关是否满足冷却与阳光条件的图片形式
|
||||
time = current_time - self.frozen_timer
|
||||
if time < self.frozen_time: # cool down status
|
||||
if time < self.frozen_time: #cool down status
|
||||
image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
frozen_image = self.orig_image
|
||||
frozen_image.set_alpha(128)
|
||||
frozen_height = (
|
||||
(self.frozen_time - time) / self.frozen_time
|
||||
) * self.rect.h
|
||||
|
||||
image.blit(
|
||||
frozen_image, (0, 0), (0, 0, self.rect.w, frozen_height)
|
||||
)
|
||||
frozen_height = ((self.frozen_time - time)/self.frozen_time) * self.rect.h
|
||||
|
||||
image.blit(frozen_image, (0,0), (0, 0, self.rect.w, frozen_height))
|
||||
self.orig_image.set_alpha(192)
|
||||
image.blit(
|
||||
self.orig_image,
|
||||
(0, frozen_height),
|
||||
(0, frozen_height, self.rect.w, self.rect.h - frozen_height),
|
||||
)
|
||||
elif self.sun_cost > sun_value: # disable status
|
||||
image.blit(self.orig_image, (0,frozen_height),
|
||||
(0, frozen_height, self.rect.w, self.rect.h - frozen_height))
|
||||
elif self.sun_cost > sun_value: #disable status
|
||||
image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
self.orig_image.set_alpha(192)
|
||||
image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
image.blit(self.orig_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
elif self.clicked:
|
||||
image = pg.Surface((self.rect.w, self.rect.h)) # 黑底
|
||||
chosen_image = self.orig_image
|
||||
chosen_image.set_alpha(128)
|
||||
|
||||
image.blit(chosen_image, (0, 0), (0, 0, self.rect.w, self.rect.h))
|
||||
|
||||
image.blit(chosen_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
else:
|
||||
image = self.orig_image
|
||||
image.set_alpha(255)
|
||||
@ -173,15 +134,14 @@ class Card:
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
|
||||
# 植物栏
|
||||
class MenuBar:
|
||||
class MenuBar():
|
||||
def __init__(self, card_list, sun_value):
|
||||
self.loadFrame(c.MENUBAR_BACKGROUND)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
|
||||
|
||||
self.sun_value = sun_value
|
||||
self.card_offset_x = 26
|
||||
self.setupCards(card_list)
|
||||
@ -211,9 +171,9 @@ class MenuBar:
|
||||
self.rect.y = y
|
||||
for i in range(num):
|
||||
x = i * width
|
||||
self.image.blit(img, (x, 0))
|
||||
self.image.blit(img, (x,0))
|
||||
self.image.set_colorkey(c.BLACK)
|
||||
|
||||
|
||||
def setupCards(self, card_list):
|
||||
self.card_list = []
|
||||
x = self.card_offset_x
|
||||
@ -227,22 +187,17 @@ class MenuBar:
|
||||
for card in self.card_list:
|
||||
if card.checkMouseClick(mouse_pos):
|
||||
if card.canClick(self.sun_value, self.current_time):
|
||||
result = (
|
||||
c.PLANT_CARD_INFO[card.index][c.PLANT_NAME_INDEX],
|
||||
card,
|
||||
)
|
||||
result = (c.PLANT_CARD_INFO[card.index][c.PLANT_NAME_INDEX], card)
|
||||
else:
|
||||
# 播放无法使用该卡片的警告音
|
||||
c.SOUND_CANNOT_CHOOSE_WARNING.play()
|
||||
break
|
||||
return result
|
||||
|
||||
|
||||
def checkMenuBarClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if (
|
||||
self.rect.x <= x <= self.rect.right
|
||||
and self.rect.y <= y <= self.rect.bottom
|
||||
):
|
||||
if (self.rect.x <= x <= self.rect.right and
|
||||
self.rect.y <= y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
@ -265,7 +220,7 @@ class MenuBar:
|
||||
self.value_rect = self.value_image.get_rect()
|
||||
self.value_rect.x = 21
|
||||
self.value_rect.y = self.rect.bottom - 24
|
||||
|
||||
|
||||
self.image.blit(self.value_image, self.value_rect)
|
||||
|
||||
def draw(self, surface):
|
||||
@ -274,9 +229,8 @@ class MenuBar:
|
||||
for card in self.card_list:
|
||||
card.draw(surface)
|
||||
|
||||
|
||||
# 关卡模式选植物的界面
|
||||
class Panel:
|
||||
class Panel():
|
||||
def __init__(self, card_list, sun_value, background_type=c.BACKGROUND_DAY):
|
||||
self.loadImages(sun_value)
|
||||
self.selected_cards = []
|
||||
@ -302,12 +256,13 @@ class Panel:
|
||||
self.panel_rect.x = 0
|
||||
self.panel_rect.y = c.PANEL_Y_START
|
||||
|
||||
|
||||
self.value_image = getSunValueImage(sun_value)
|
||||
self.value_rect = self.value_image.get_rect()
|
||||
self.value_rect.x = 21
|
||||
self.value_rect.y = self.menu_rect.bottom - 24
|
||||
|
||||
self.button_image = self.loadFrame(c.START_BUTTON)
|
||||
self.button_image = self.loadFrame(c.START_BUTTON)
|
||||
self.button_rect = self.button_image.get_rect()
|
||||
self.button_rect.x = 155
|
||||
self.button_rect.y = 547
|
||||
@ -322,26 +277,15 @@ class Panel:
|
||||
y += c.PANEL_Y_INTERNAL
|
||||
x += c.PANEL_X_INTERNAL
|
||||
plant_name = c.PLANT_CARD_INFO[index][c.PLANT_NAME_INDEX]
|
||||
if (
|
||||
plant_name in c.WATER_PLANTS
|
||||
and self.background_type not in c.POOL_EQUIPPED_BACKGROUNDS
|
||||
):
|
||||
if (plant_name in c.WATER_PLANTS
|
||||
and self.background_type not in c.POOL_EQUIPPED_BACKGROUNDS):
|
||||
not_recommend = c.REASON_OTHER
|
||||
elif (
|
||||
plant_name == c.GRAVEBUSTER
|
||||
and self.background_type != c.BACKGROUND_NIGHT
|
||||
):
|
||||
elif (plant_name == c.GRAVEBUSTER
|
||||
and self.background_type != c.BACKGROUND_NIGHT):
|
||||
not_recommend = c.REASON_OTHER
|
||||
elif (
|
||||
plant_name in c.CAN_SLEEP_PLANTS
|
||||
and self.background_type in c.DAYTIME_BACKGROUNDS
|
||||
):
|
||||
elif (plant_name in c.CAN_SLEEP_PLANTS
|
||||
and self.background_type in c.DAYTIME_BACKGROUNDS):
|
||||
not_recommend = c.REASON_WILL_SLEEP
|
||||
elif (
|
||||
plant_name == c.COFFEEBEAN
|
||||
and self.background_type not in c.DAYTIME_BACKGROUNDS
|
||||
):
|
||||
not_recommend = c.REASON_OTHER
|
||||
# 还有屋顶场景,以及其他植物没有实现的植物没有写进来
|
||||
else:
|
||||
not_recommend = 0
|
||||
@ -350,7 +294,7 @@ class Panel:
|
||||
def checkCardClick(self, mouse_pos):
|
||||
delete_card = None
|
||||
for card in self.selected_cards:
|
||||
if delete_card: # when delete a card, move right cards to left
|
||||
if delete_card: # when delete a card, move right cards to left
|
||||
card.rect.x -= c.BAR_CARD_X_INTERNAL
|
||||
elif card.checkMouseClick(mouse_pos):
|
||||
self.deleteCard(card.index)
|
||||
@ -367,9 +311,7 @@ class Panel:
|
||||
i.not_recommend = c.REASON_WILL_SLEEP
|
||||
i.orig_image.set_alpha(128)
|
||||
i.image = pg.Surface((i.rect.w, i.rect.h)) # 黑底
|
||||
i.image.blit(
|
||||
i.orig_image, (0, 0), (0, 0, i.rect.w, i.rect.h)
|
||||
)
|
||||
i.image.blit(i.orig_image, (0,0), (0, 0, i.rect.w, i.rect.h))
|
||||
|
||||
if self.selected_num >= c.CARD_MAX_NUM:
|
||||
return
|
||||
@ -383,14 +325,12 @@ class Panel:
|
||||
if card.info[c.PLANT_NAME_INDEX] == c.COFFEEBEAN:
|
||||
for i in self.card_list:
|
||||
if i.not_recommend == c.REASON_WILL_SLEEP:
|
||||
i.not_recommend = (
|
||||
c.REASON_SLEEP_BUT_COFFEE_BEAN
|
||||
)
|
||||
i.not_recommend = c.REASON_SLEEP_BUT_COFFEE_BEAN
|
||||
i.image = i.orig_image
|
||||
i.image.set_alpha(255)
|
||||
break
|
||||
|
||||
def addCard(self, card: Card):
|
||||
def addCard(self, card:Card):
|
||||
card.setSelect(False)
|
||||
y = 8
|
||||
x = 77 + self.selected_num * c.BAR_CARD_X_INTERNAL
|
||||
@ -405,11 +345,9 @@ class Panel:
|
||||
return False
|
||||
|
||||
x, y = mouse_pos
|
||||
if (
|
||||
self.button_rect.x <= x <= self.button_rect.right
|
||||
and self.button_rect.y <= y <= self.button_rect.bottom
|
||||
):
|
||||
return True
|
||||
if (self.button_rect.x <= x <= self.button_rect.right and
|
||||
self.button_rect.y <= y <= self.button_rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def getSelectedCards(self):
|
||||
@ -430,9 +368,8 @@ class Panel:
|
||||
if self.selected_num >= c.CARD_LIST_NUM:
|
||||
surface.blit(self.button_image, self.button_rect)
|
||||
|
||||
|
||||
# 传送带模式的卡片
|
||||
class MoveCard:
|
||||
class MoveCard():
|
||||
def __init__(self, x, y, card_name, plant_name, scale=0.5):
|
||||
self.loadFrame(card_name, scale)
|
||||
self.rect = self.orig_image.get_rect()
|
||||
@ -452,41 +389,33 @@ class MoveCard:
|
||||
rect = frame.get_rect()
|
||||
width, height = rect.w, rect.h
|
||||
|
||||
self.orig_image = tool.get_image(
|
||||
frame, 0, 0, width, height, c.BLACK, scale
|
||||
)
|
||||
self.orig_image = tool.get_image(frame, 0, 0, width, height, c.BLACK, scale)
|
||||
self.orig_rect = self.orig_image.get_rect()
|
||||
self.image = self.orig_image
|
||||
|
||||
def checkMouseClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if (
|
||||
self.rect.x <= x <= self.rect.right
|
||||
and self.rect.y <= y <= self.rect.bottom
|
||||
):
|
||||
if (self.rect.x <= x <= self.rect.right and
|
||||
self.rect.y <= y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
def createShowImage(self):
|
||||
# 新增卡片时显示图片
|
||||
if self.rect.w < self.orig_rect.w: # create a part card image
|
||||
if self.rect.w < self.orig_rect.w: #create a part card image
|
||||
image = pg.Surface([self.rect.w, self.rect.h])
|
||||
if self.clicked:
|
||||
self.orig_image.set_alpha(128)
|
||||
else:
|
||||
self.orig_image.set_alpha(255)
|
||||
image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
image.blit(self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h))
|
||||
self.rect.w += 1
|
||||
else:
|
||||
if self.clicked:
|
||||
image = pg.Surface([self.rect.w, self.rect.h]) # 黑底
|
||||
self.orig_image.set_alpha(128)
|
||||
|
||||
image.blit(
|
||||
self.orig_image, (0, 0), (0, 0, self.rect.w, self.rect.h)
|
||||
)
|
||||
|
||||
image.blit(self.orig_image, (0,0), (0, 0, self.rect.w, self.rect.h))
|
||||
else:
|
||||
self.orig_image.set_alpha(255)
|
||||
image = self.orig_image
|
||||
@ -504,15 +433,14 @@ class MoveCard:
|
||||
def draw(self, surface):
|
||||
surface.blit(self.image, self.rect)
|
||||
|
||||
|
||||
# 传送带
|
||||
class MoveBar:
|
||||
class MoveBar():
|
||||
def __init__(self, card_pool):
|
||||
self.loadFrame(c.MOVEBAR_BACKGROUND)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 20
|
||||
self.rect.y = 0
|
||||
|
||||
|
||||
self.card_start_x = self.rect.x + 8
|
||||
self.card_end_x = self.rect.right - 5
|
||||
self.card_pool = card_pool
|
||||
@ -529,24 +457,12 @@ class MoveBar:
|
||||
self.image = tool.get_image(tool.GFX[name], *frame_rect, c.WHITE, 1)
|
||||
|
||||
def createCard(self):
|
||||
if (
|
||||
len(self.card_list) > 0
|
||||
and self.card_list[-1].rect.right > self.card_end_x
|
||||
):
|
||||
if len(self.card_list) > 0 and self.card_list[-1].rect.right > self.card_end_x:
|
||||
return False
|
||||
x = self.card_end_x
|
||||
y = 6
|
||||
selected_card = random.choices(
|
||||
self.card_pool_name, self.card_pool_weight
|
||||
)[0]
|
||||
self.card_list.append(
|
||||
MoveCard(
|
||||
x,
|
||||
y,
|
||||
selected_card[c.CARD_INDEX],
|
||||
selected_card[c.PLANT_NAME_INDEX],
|
||||
)
|
||||
)
|
||||
selected_card = random.choices(self.card_pool_name, self.card_pool_weight)[0]
|
||||
self.card_list.append(MoveCard(x, y, selected_card[c.CARD_INDEX], selected_card[c.PLANT_NAME_INDEX]))
|
||||
return True
|
||||
|
||||
def update(self, current_time):
|
||||
@ -567,13 +483,11 @@ class MoveBar:
|
||||
result = (card.plant_name, card)
|
||||
break
|
||||
return result
|
||||
|
||||
|
||||
def checkMenuBarClick(self, mouse_pos):
|
||||
x, y = mouse_pos
|
||||
if (
|
||||
self.rect.x <= x <= self.rect.right
|
||||
and self.rect.y <= y <= self.rect.bottom
|
||||
):
|
||||
if (self.rect.x <= x <= self.rect.right and
|
||||
self.rect.y <= y <= self.rect.bottom):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,16 +1,14 @@
|
||||
import os
|
||||
|
||||
import pygame as pg
|
||||
|
||||
from .. import constants as c
|
||||
import os
|
||||
from .. import tool
|
||||
|
||||
from .. import constants as c
|
||||
|
||||
class Menu(tool.State):
|
||||
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
|
||||
def startup(self, current_time: int, persist):
|
||||
|
||||
def startup(self, current_time:int, persist):
|
||||
self.next = c.LEVEL
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
@ -19,7 +17,7 @@ class Menu(tool.State):
|
||||
self.setupOptionMenu()
|
||||
self.setupSunflowerTrophy()
|
||||
pg.mixer.music.stop()
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, 'intro.opus'))
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, "intro.opus"))
|
||||
pg.mixer.music.play(-1, 0)
|
||||
pg.display.set_caption(c.ORIGINAL_CAPTION)
|
||||
pg.mixer.music.set_volume(self.game_info[c.SOUND_VOLUME])
|
||||
@ -32,9 +30,7 @@ class Menu(tool.State):
|
||||
# 2、双星号同上,区别是x视为字典。
|
||||
# 3、在变量前加单星号表示将元组(列表、集合)拆分为单个元素。
|
||||
# 4、双星号同上,区别是目标为字典,字典前加单星号的话可以得到“键”。
|
||||
self.bg_image = tool.get_image(
|
||||
tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect
|
||||
)
|
||||
self.bg_image = tool.get_image(tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect)
|
||||
self.bg_rect = self.bg_image.get_rect()
|
||||
self.bg_rect.x = 0
|
||||
self.bg_rect.y = 0
|
||||
@ -43,12 +39,7 @@ class Menu(tool.State):
|
||||
# 冒险模式
|
||||
frame_rect = (0, 0, 330, 144)
|
||||
# 写成列表生成器方便IDE识别与自动补全
|
||||
self.adventure_frames = [
|
||||
tool.get_image_alpha(
|
||||
tool.GFX[f'{c.OPTION_ADVENTURE}_{i}'], *frame_rect
|
||||
)
|
||||
for i in range(2)
|
||||
]
|
||||
self.adventure_frames = [tool.get_image_alpha(tool.GFX[f"{c.OPTION_ADVENTURE}_{i}"], *frame_rect) for i in range(2)]
|
||||
self.adventure_image = self.adventure_frames[0]
|
||||
self.adventure_rect = self.adventure_image.get_rect()
|
||||
self.adventure_rect.x = 400
|
||||
@ -57,12 +48,7 @@ class Menu(tool.State):
|
||||
|
||||
# 小游戏
|
||||
littleGame_frame_rect = (0, 7, 317, 135)
|
||||
self.littleGame_frames = [
|
||||
tool.get_image_alpha(
|
||||
tool.GFX[f'{c.LITTLEGAME_BUTTON}_{i}'], *littleGame_frame_rect
|
||||
)
|
||||
for i in range(2)
|
||||
]
|
||||
self.littleGame_frames = [tool.get_image_alpha(tool.GFX[f"{c.LITTLEGAME_BUTTON}_{i}"], *littleGame_frame_rect) for i in range(2)]
|
||||
self.littleGame_image = self.littleGame_frames[0]
|
||||
self.littleGame_rect = self.littleGame_image.get_rect()
|
||||
self.littleGame_rect.x = 397
|
||||
@ -71,12 +57,7 @@ class Menu(tool.State):
|
||||
|
||||
# 退出按钮
|
||||
exit_frame_rect = (0, 0, 47, 27)
|
||||
self.exit_frames = [
|
||||
tool.get_image_alpha(
|
||||
tool.GFX[f'{c.EXIT}_{i}'], *exit_frame_rect, scale=1.1
|
||||
)
|
||||
for i in range(2)
|
||||
]
|
||||
self.exit_frames = [tool.get_image_alpha(tool.GFX[f"{c.EXIT}_{i}"], *exit_frame_rect, scale=1.1) for i in range(2)]
|
||||
self.exit_image = self.exit_frames[0]
|
||||
self.exit_rect = self.exit_image.get_rect()
|
||||
self.exit_rect.x = 730
|
||||
@ -85,12 +66,7 @@ class Menu(tool.State):
|
||||
|
||||
# 选项按钮
|
||||
option_button_frame_rect = (0, 0, 81, 31)
|
||||
self.option_button_frames = [
|
||||
tool.get_image_alpha(
|
||||
tool.GFX[f'{c.OPTION_BUTTON}_{i}'], *option_button_frame_rect
|
||||
)
|
||||
for i in range(2)
|
||||
]
|
||||
self.option_button_frames = [tool.get_image_alpha(tool.GFX[f"{c.OPTION_BUTTON}_{i}"], *option_button_frame_rect) for i in range(2)]
|
||||
self.option_button_image = self.option_button_frames[0]
|
||||
self.option_button_rect = self.option_button_image.get_rect()
|
||||
self.option_button_rect.x = 560
|
||||
@ -99,23 +75,20 @@ class Menu(tool.State):
|
||||
|
||||
# 帮助菜单
|
||||
help_frame_rect = (0, 0, 48, 22)
|
||||
self.help_frames = [
|
||||
tool.get_image_alpha(tool.GFX[f'{c.HELP}_{i}'], *help_frame_rect)
|
||||
for i in range(2)
|
||||
]
|
||||
self.help_frames = [tool.get_image_alpha(tool.GFX[f"{c.HELP}_{i}"], *help_frame_rect) for i in range(2)]
|
||||
self.help_image = self.help_frames[0]
|
||||
self.help_rect = self.help_image.get_rect()
|
||||
self.help_rect.x = 653
|
||||
self.help_rect.y = 520
|
||||
self.help_hilight_time = 0
|
||||
|
||||
|
||||
# 计时器与点击信号记录器
|
||||
self.adventure_start = 0
|
||||
self.adventure_timer = 0
|
||||
self.adventure_clicked = False
|
||||
self.option_button_clicked = False
|
||||
|
||||
def checkHilight(self, x: int, y: int):
|
||||
def checkHilight(self, x:int, y:int):
|
||||
# 高亮冒险模式按钮
|
||||
if self.inArea(self.adventure_rect, x, y):
|
||||
self.adventure_highlight_time = self.current_time
|
||||
@ -133,25 +106,15 @@ class Menu(tool.State):
|
||||
self.help_hilight_time = self.current_time
|
||||
|
||||
# 处理按钮高亮情况
|
||||
self.adventure_image = self.chooseHilightImage(
|
||||
self.adventure_highlight_time, self.adventure_frames
|
||||
)
|
||||
self.exit_image = self.chooseHilightImage(
|
||||
self.exit_highlight_time, self.exit_frames
|
||||
)
|
||||
self.option_button_image = self.chooseHilightImage(
|
||||
self.option_button_highlight_time, self.option_button_frames
|
||||
)
|
||||
self.littleGame_image = self.chooseHilightImage(
|
||||
self.littleGame_highlight_time, self.littleGame_frames
|
||||
)
|
||||
self.help_image = self.chooseHilightImage(
|
||||
self.help_hilight_time, self.help_frames
|
||||
)
|
||||
self.adventure_image = self.chooseHilightImage(self.adventure_highlight_time, self.adventure_frames)
|
||||
self.exit_image = self.chooseHilightImage(self.exit_highlight_time, self.exit_frames)
|
||||
self.option_button_image = self.chooseHilightImage(self.option_button_highlight_time, self.option_button_frames)
|
||||
self.littleGame_image = self.chooseHilightImage(self.littleGame_highlight_time, self.littleGame_frames)
|
||||
self.help_image = self.chooseHilightImage(self.help_hilight_time, self.help_frames)
|
||||
|
||||
def chooseHilightImage(self, hilightTime: int, frames):
|
||||
def chooseHilightImage(self, hilightTime:int, frames):
|
||||
if (self.current_time - hilightTime) < 80:
|
||||
index = 1
|
||||
index= 1
|
||||
else:
|
||||
index = 0
|
||||
return frames[index]
|
||||
@ -185,9 +148,7 @@ class Menu(tool.State):
|
||||
def setupOptionMenu(self):
|
||||
# 选项菜单框
|
||||
frame_rect = (0, 0, 500, 500)
|
||||
self.big_menu = tool.get_image_alpha(
|
||||
tool.GFX[c.BIG_MENU], *frame_rect, c.BLACK, 1.1
|
||||
)
|
||||
self.big_menu = tool.get_image_alpha(tool.GFX[c.BIG_MENU], *frame_rect, c.BLACK, 1.1)
|
||||
self.big_menu_rect = self.big_menu.get_rect()
|
||||
self.big_menu_rect.x = 150
|
||||
self.big_menu_rect.y = 0
|
||||
@ -201,7 +162,7 @@ class Menu(tool.State):
|
||||
self.return_button_rect.y = 440
|
||||
font = pg.font.Font(c.FONT_PATH, 40)
|
||||
font.bold = True
|
||||
text = font.render('返回游戏', True, c.YELLOWGREEN)
|
||||
text = font.render("返回游戏", True, c.YELLOWGREEN)
|
||||
text_rect = text.get_rect()
|
||||
text_rect.x = 105
|
||||
text_rect.y = 18
|
||||
@ -212,72 +173,51 @@ class Menu(tool.State):
|
||||
font = pg.font.Font(c.FONT_PATH, 35)
|
||||
font.bold = True
|
||||
# 音量+
|
||||
self.sound_volume_plus_button = tool.get_image_alpha(
|
||||
tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK
|
||||
)
|
||||
sign = font.render('+', True, c.YELLOWGREEN)
|
||||
self.sound_volume_plus_button = tool.get_image_alpha(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
sign = font.render("+", True, c.YELLOWGREEN)
|
||||
sign_rect = sign.get_rect()
|
||||
sign_rect.x = 8
|
||||
sign_rect.y = -4
|
||||
self.sound_volume_plus_button.blit(sign, sign_rect)
|
||||
self.sound_volume_plus_button_rect = (
|
||||
self.sound_volume_plus_button.get_rect()
|
||||
)
|
||||
self.sound_volume_plus_button_rect = self.sound_volume_plus_button.get_rect()
|
||||
self.sound_volume_plus_button_rect.x = 500
|
||||
# 音量-
|
||||
self.sound_volume_minus_button = tool.get_image_alpha(
|
||||
tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK
|
||||
)
|
||||
sign = font.render('-', True, c.YELLOWGREEN)
|
||||
self.sound_volume_minus_button = tool.get_image_alpha(tool.GFX[c.SOUND_VOLUME_BUTTON], *frame_rect, c.BLACK)
|
||||
sign = font.render("-", True, c.YELLOWGREEN)
|
||||
sign_rect = sign.get_rect()
|
||||
sign_rect.x = 12
|
||||
sign_rect.y = -6
|
||||
self.sound_volume_minus_button.blit(sign, sign_rect)
|
||||
self.sound_volume_minus_button_rect = (
|
||||
self.sound_volume_minus_button.get_rect()
|
||||
)
|
||||
self.sound_volume_minus_button_rect = self.sound_volume_minus_button.get_rect()
|
||||
self.sound_volume_minus_button_rect.x = 450
|
||||
# 音量+、-应当处于同一高度
|
||||
self.sound_volume_minus_button_rect.y = (
|
||||
self.sound_volume_plus_button_rect.y
|
||||
) = 250
|
||||
self.sound_volume_minus_button_rect.y = self.sound_volume_plus_button_rect.y = 250
|
||||
|
||||
def setupSunflowerTrophy(self):
|
||||
# 设置金银向日葵图片信息
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
or self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
and self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] or self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] and self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
frame_rect = (157, 0, 157, 269)
|
||||
else:
|
||||
frame_rect = (0, 0, 157, 269)
|
||||
self.sunflower_trophy = tool.get_image_alpha(
|
||||
tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, c.BLACK
|
||||
)
|
||||
self.sunflower_trophy = tool.get_image_alpha(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, c.BLACK)
|
||||
self.sunflower_trophy_rect = self.sunflower_trophy.get_rect()
|
||||
self.sunflower_trophy_rect.x = 0
|
||||
self.sunflower_trophy_rect.y = 280
|
||||
self.sunflower_trophy_show_info_time = 0
|
||||
|
||||
def checkSunflowerTrophyInfo(self, surface: pg.Surface, x: int, y: int):
|
||||
def checkSunflowerTrophyInfo(self, surface:pg.Surface, x:int, y:int):
|
||||
if self.inArea(self.sunflower_trophy_rect, x, y):
|
||||
self.sunflower_trophy_show_info_time = self.current_time
|
||||
if (self.current_time - self.sunflower_trophy_show_info_time) < 80:
|
||||
font = pg.font.Font(c.FONT_PATH, 14)
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
and self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
infoText = f'目前您一共完成了:冒险模式{self.game_info[c.LEVEL_COMPLETIONS]}轮,玩玩小游戏{self.game_info[c.LITTLEGAME_COMPLETIONS]}轮'
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] and self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
infoText = f"目前您一共完成了:冒险模式{self.game_info[c.LEVEL_COMPLETIONS]}轮,玩玩小游戏{self.game_info[c.LITTLEGAME_COMPLETIONS]}轮"
|
||||
elif self.game_info[c.LEVEL_COMPLETIONS]:
|
||||
infoText = f'目前您一共完成了:冒险模式{self.game_info[c.LEVEL_COMPLETIONS]}轮;完成其他所有游戏模式以获得金向日葵奖杯!'
|
||||
infoText = f"目前您一共完成了:冒险模式{self.game_info[c.LEVEL_COMPLETIONS]}轮;完成其他所有游戏模式以获得金向日葵奖杯!"
|
||||
else:
|
||||
infoText = f'目前您一共完成了:玩玩小游戏{self.game_info[c.LITTLEGAME_COMPLETIONS]}轮;完成其他所有游戏模式以获得金向日葵奖杯!'
|
||||
infoImg = font.render(infoText, True, c.BLACK, c.LIGHTYELLOW)
|
||||
infoText = f"目前您一共完成了:玩玩小游戏{self.game_info[c.LITTLEGAME_COMPLETIONS]}轮;完成其他所有游戏模式以获得金向日葵奖杯!"
|
||||
infoImg = font.render(infoText , True, c.BLACK, c.LIGHTYELLOW)
|
||||
infoImg_rect = infoImg.get_rect()
|
||||
infoImg_rect.x = self.sunflower_trophy_rect.x
|
||||
infoImg_rect.y = self.sunflower_trophy_rect.bottom - 14
|
||||
@ -288,38 +228,25 @@ class Menu(tool.State):
|
||||
# 播放点击音效
|
||||
c.SOUND_BUTTON_CLICK.play()
|
||||
|
||||
def showCurrentVolumeImage(self, surface: pg.Surface):
|
||||
def showCurrentVolumeImage(self, surface:pg.Surface):
|
||||
# 由于音量可变,因此这一内容不能在一开始就结束加载,而应当不断刷新不断显示
|
||||
font = pg.font.Font(c.FONT_PATH, 30)
|
||||
volume_tips = font.render(
|
||||
f'音量:{round(self.game_info[c.SOUND_VOLUME]*100):3}%',
|
||||
True,
|
||||
c.LIGHTGRAY,
|
||||
)
|
||||
volume_tips = font.render(f"音量:{round(self.game_info[c.SOUND_VOLUME]*100):3}%", True, c.LIGHTGRAY)
|
||||
volume_tips_rect = volume_tips.get_rect()
|
||||
volume_tips_rect.x = 275
|
||||
volume_tips_rect.y = 247
|
||||
surface.blit(volume_tips, volume_tips_rect)
|
||||
|
||||
def update(
|
||||
self,
|
||||
surface: pg.Surface,
|
||||
current_time: int,
|
||||
mouse_pos: list,
|
||||
mouse_click,
|
||||
):
|
||||
def update(self, surface:pg.Surface, current_time:int, mouse_pos:list, mouse_click):
|
||||
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
||||
|
||||
|
||||
surface.blit(self.bg_image, self.bg_rect)
|
||||
surface.blit(self.adventure_image, self.adventure_rect)
|
||||
surface.blit(self.littleGame_image, self.littleGame_rect)
|
||||
surface.blit(self.exit_image, self.exit_rect)
|
||||
surface.blit(self.option_button_image, self.option_button_rect)
|
||||
surface.blit(self.help_image, self.help_rect)
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
or self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
if self.game_info[c.LEVEL_COMPLETIONS] or self.game_info[c.LITTLEGAME_COMPLETIONS]:
|
||||
surface.blit(self.sunflower_trophy, self.sunflower_trophy_rect)
|
||||
|
||||
# 点到冒险模式后播放动画
|
||||
@ -335,14 +262,8 @@ class Menu(tool.State):
|
||||
elif self.option_button_clicked:
|
||||
surface.blit(self.big_menu, self.big_menu_rect)
|
||||
surface.blit(self.return_button, self.return_button_rect)
|
||||
surface.blit(
|
||||
self.sound_volume_plus_button,
|
||||
self.sound_volume_plus_button_rect,
|
||||
)
|
||||
surface.blit(
|
||||
self.sound_volume_minus_button,
|
||||
self.sound_volume_minus_button_rect,
|
||||
)
|
||||
surface.blit(self.sound_volume_plus_button, self.sound_volume_plus_button_rect)
|
||||
surface.blit(self.sound_volume_minus_button, self.sound_volume_minus_button_rect)
|
||||
self.showCurrentVolumeImage(surface)
|
||||
if mouse_pos:
|
||||
# 返回
|
||||
@ -350,12 +271,8 @@ class Menu(tool.State):
|
||||
self.option_button_clicked = False
|
||||
c.SOUND_BUTTON_CLICK.play()
|
||||
# 音量+
|
||||
elif self.inArea(
|
||||
self.sound_volume_plus_button_rect, *mouse_pos
|
||||
):
|
||||
self.game_info[c.SOUND_VOLUME] = round(
|
||||
min(self.game_info[c.SOUND_VOLUME] + 0.05, 1), 2
|
||||
)
|
||||
elif self.inArea(self.sound_volume_plus_button_rect, *mouse_pos):
|
||||
self.game_info[c.SOUND_VOLUME] = round(min(self.game_info[c.SOUND_VOLUME] + 0.05, 1), 2)
|
||||
# 一般不会有人想把音乐和音效分开设置,故pg.mixer.Sound.set_volume()和pg.mixer.music.set_volume()需要一起用
|
||||
pg.mixer.music.set_volume(self.game_info[c.SOUND_VOLUME])
|
||||
for i in c.SOUNDS:
|
||||
@ -363,12 +280,8 @@ class Menu(tool.State):
|
||||
c.SOUND_BUTTON_CLICK.play()
|
||||
self.saveUserData()
|
||||
# 音量-
|
||||
elif self.inArea(
|
||||
self.sound_volume_minus_button_rect, *mouse_pos
|
||||
):
|
||||
self.game_info[c.SOUND_VOLUME] = round(
|
||||
max(self.game_info[c.SOUND_VOLUME] - 0.05, 0), 2
|
||||
)
|
||||
elif self.inArea(self.sound_volume_minus_button_rect, *mouse_pos):
|
||||
self.game_info[c.SOUND_VOLUME] = round(max(self.game_info[c.SOUND_VOLUME] - 0.05, 0), 2)
|
||||
# 一般不会有人想把音乐和音效分开设置,故pg.mixer.Sound.set_volume()和pg.mixer.music.set_volume()需要一起用
|
||||
pg.mixer.music.set_volume(self.game_info[c.SOUND_VOLUME])
|
||||
for i in c.SOUNDS:
|
||||
@ -380,10 +293,7 @@ class Menu(tool.State):
|
||||
# 先检查选项高亮预览
|
||||
x, y = pg.mouse.get_pos()
|
||||
self.checkHilight(x, y)
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
or self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] or self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
self.checkSunflowerTrophyInfo(surface, x, y)
|
||||
if mouse_pos:
|
||||
if self.inArea(self.adventure_rect, *mouse_pos):
|
||||
|
||||
@ -1,11 +1,8 @@
|
||||
import os
|
||||
from abc import abstractmethod
|
||||
|
||||
import pygame as pg
|
||||
|
||||
from .. import constants as c
|
||||
from abc import abstractmethod
|
||||
from .. import tool
|
||||
|
||||
from .. import constants as c
|
||||
|
||||
class Screen(tool.State):
|
||||
def __init__(self):
|
||||
@ -17,9 +14,7 @@ class Screen(tool.State):
|
||||
|
||||
def setupImage(self, name, frame_rect=(0, 0, 800, 600), color_key=c.BLACK):
|
||||
# 背景图本身
|
||||
self.image = tool.get_image(
|
||||
tool.GFX[name], *frame_rect, colorkey=color_key
|
||||
)
|
||||
self.image = tool.get_image(tool.GFX[name], *frame_rect, colorkey=color_key)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
@ -27,45 +22,33 @@ class Screen(tool.State):
|
||||
# 按钮
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.main_menu_button_image_rect = (
|
||||
self.main_menu_button_image.get_rect()
|
||||
)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 620
|
||||
### 主菜单按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
main_menu_text = font.render('主菜单', True, c.NAVYBLUE)
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
## 继续按钮
|
||||
self.next_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.next_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image_rect = self.next_button_image.get_rect()
|
||||
self.next_button_image_rect.x = 70
|
||||
### 继续按钮上的文字
|
||||
if name == c.GAME_VICTORY_IMAGE:
|
||||
next_text = font.render('下一关', True, c.NAVYBLUE)
|
||||
next_text = font.render("下一关", True, c.NAVYBLUE)
|
||||
next_text_rect = next_text.get_rect()
|
||||
next_text_rect.x = 29
|
||||
self.next_button_image_rect.y = (
|
||||
self.main_menu_button_image_rect.y
|
||||
) = 555
|
||||
self.next_button_image_rect.y = self.main_menu_button_image_rect.y = 555
|
||||
else:
|
||||
next_text = font.render('重新开始', True, c.NAVYBLUE)
|
||||
next_text = font.render("重新开始", True, c.NAVYBLUE)
|
||||
next_text_rect = next_text.get_rect()
|
||||
next_text_rect.x = 21
|
||||
self.next_button_image_rect.y = (
|
||||
self.main_menu_button_image_rect.y
|
||||
) = 530
|
||||
self.next_button_image_rect.y = self.main_menu_button_image_rect.y = 530
|
||||
self.next_button_image.blit(next_text, next_text_rect)
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.next_button_image, self.next_button_image_rect)
|
||||
self.image.blit(
|
||||
self.main_menu_button_image, self.main_menu_button_image_rect
|
||||
)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
surface.fill(c.WHITE)
|
||||
@ -80,39 +63,36 @@ class Screen(tool.State):
|
||||
self.next = c.MAIN_MENU
|
||||
self.done = True
|
||||
|
||||
|
||||
class GameVictoryScreen(Screen):
|
||||
def __init__(self):
|
||||
Screen.__init__(self)
|
||||
self.image_name = c.GAME_VICTORY_IMAGE
|
||||
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
self.setupImage(self.image_name)
|
||||
pg.display.set_caption('pypvz: 战斗胜利!')
|
||||
pg.display.set_caption("pypvz: 战斗胜利!")
|
||||
pg.mixer.music.stop()
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, 'zenGarden.opus'))
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, "zenGarden.opus"))
|
||||
pg.mixer.music.play(-1, 0)
|
||||
pg.mixer.music.set_volume(self.game_info[c.SOUND_VOLUME])
|
||||
|
||||
|
||||
class GameLoseScreen(Screen):
|
||||
def __init__(self):
|
||||
Screen.__init__(self)
|
||||
self.image_name = c.GAME_LOSE_IMAGE
|
||||
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
self.setupImage(self.image_name, (-118, -40, 800, 600), c.WHITE)
|
||||
pg.display.set_caption('pypvz: 战斗失败!')
|
||||
pg.display.set_caption("pypvz: 战斗失败!")
|
||||
# 停止播放原来关卡中的音乐
|
||||
pg.mixer.music.stop()
|
||||
|
||||
|
||||
class AwardScreen(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
@ -120,9 +100,7 @@ class AwardScreen(tool.State):
|
||||
def setupImage(self):
|
||||
# 主体
|
||||
frame_rect = (0, 0, 800, 600)
|
||||
self.image = tool.get_image(
|
||||
tool.GFX[c.AWARD_SCREEN_IMAGE], *frame_rect
|
||||
)
|
||||
self.image = tool.get_image(tool.GFX[c.AWARD_SCREEN_IMAGE], *frame_rect)
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
@ -130,54 +108,41 @@ class AwardScreen(tool.State):
|
||||
# 文字
|
||||
# 标题处文字
|
||||
font = pg.font.Font(c.FONT_PATH, 37)
|
||||
title_text = font.render('您获得了新的战利品!', True, c.PARCHMENT_YELLOW)
|
||||
title_text = font.render("您获得了新的战利品!", True, c.PARCHMENT_YELLOW)
|
||||
title_text_rect = title_text.get_rect()
|
||||
title_text_rect.x = 220
|
||||
title_text_rect.y = 23
|
||||
self.image.blit(title_text, title_text_rect)
|
||||
|
||||
|
||||
# 按钮
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
if self.show_only_one_option:
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.main_menu_button_image_rect = (
|
||||
self.main_menu_button_image.get_rect()
|
||||
)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 343
|
||||
self.main_menu_button_image_rect.y = 520
|
||||
### 主菜单按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
main_menu_text = font.render('主菜单', True, c.NAVYBLUE)
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.main_menu_button_image.blit(
|
||||
main_menu_text, main_menu_text_rect
|
||||
)
|
||||
self.image.blit(
|
||||
self.main_menu_button_image, self.main_menu_button_image_rect
|
||||
)
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
# 绘制向日葵奖杯
|
||||
if (
|
||||
self.game_info[c.LEVEL_COMPLETIONS]
|
||||
and self.game_info[c.LITTLEGAME_COMPLETIONS]
|
||||
):
|
||||
if (self.game_info[c.LEVEL_COMPLETIONS] and self.game_info[c.LITTLEGAME_COMPLETIONS]):
|
||||
frame_rect = (157, 0, 157, 269)
|
||||
intro_title = '金向日葵奖杯'
|
||||
intro_content = '您已通过所有关卡,获得此奖励!'
|
||||
intro_title = "金向日葵奖杯"
|
||||
intro_content = "您已通过所有关卡,获得此奖励!"
|
||||
else:
|
||||
frame_rect = (0, 0, 157, 269)
|
||||
intro_title = '银向日葵奖杯'
|
||||
intro_title = "银向日葵奖杯"
|
||||
if self.game_info[c.LEVEL_COMPLETIONS]:
|
||||
intro_content = '您已完成冒险模式,获得此奖励!'
|
||||
intro_content = "您已完成冒险模式,获得此奖励!"
|
||||
else:
|
||||
intro_content = '您已完成玩玩小游戏,获得此奖励!'
|
||||
sunflower_trophy_image = tool.get_image_alpha(
|
||||
tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, scale=0.7
|
||||
)
|
||||
intro_content = "您已完成玩玩小游戏,获得此奖励!"
|
||||
sunflower_trophy_image = tool.get_image_alpha(tool.GFX[c.TROPHY_SUNFLOWER], *frame_rect, scale=0.7)
|
||||
sunflower_trophy_rect = sunflower_trophy_image.get_rect()
|
||||
sunflower_trophy_rect.x = 348
|
||||
sunflower_trophy_rect.y = 108
|
||||
@ -185,9 +150,7 @@ class AwardScreen(tool.State):
|
||||
|
||||
# 绘制介绍标题
|
||||
font = pg.font.Font(c.FONT_PATH, 22)
|
||||
intro_title_img = font.render(
|
||||
intro_title, True, c.PARCHMENT_YELLOW
|
||||
)
|
||||
intro_title_img = font.render(intro_title, True, c.PARCHMENT_YELLOW)
|
||||
intro_title_rect = intro_title_img.get_rect()
|
||||
intro_title_rect.x = 333
|
||||
intro_title_rect.y = 305
|
||||
@ -202,56 +165,40 @@ class AwardScreen(tool.State):
|
||||
self.image.blit(intro_content_img, intro_content_rect)
|
||||
else:
|
||||
## 继续按钮
|
||||
self.next_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.next_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.next_button_image_rect = self.next_button_image.get_rect()
|
||||
self.next_button_image_rect.x = 70
|
||||
### 继续按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
next_text = font.render('继续', True, c.NAVYBLUE)
|
||||
next_text = font.render("继续", True, c.NAVYBLUE)
|
||||
next_text_rect = next_text.get_rect()
|
||||
next_text_rect.x = 37
|
||||
## 主菜单按钮
|
||||
self.main_menu_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.main_menu_button_image_rect = (
|
||||
self.main_menu_button_image.get_rect()
|
||||
)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 620
|
||||
self.next_button_image_rect.y = (
|
||||
self.main_menu_button_image_rect.y
|
||||
) = 540
|
||||
self.next_button_image_rect.y = self.main_menu_button_image_rect.y = 540
|
||||
### 主菜单按钮上的文字
|
||||
main_menu_text = font.render('主菜单', True, c.NAVYBLUE)
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.next_button_image.blit(next_text, next_text_rect)
|
||||
self.main_menu_button_image.blit(
|
||||
main_menu_text, main_menu_text_rect
|
||||
)
|
||||
self.image.blit(
|
||||
self.next_button_image, self.next_button_image_rect
|
||||
)
|
||||
self.image.blit(
|
||||
self.main_menu_button_image, self.main_menu_button_image_rect
|
||||
)
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(self.next_button_image, self.next_button_image_rect)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
def startup(self, current_time, persist):
|
||||
self.start_time = current_time
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
if (c.PASSED_ALL in self.game_info) and (
|
||||
not self.game_info[c.PASSED_ALL]
|
||||
):
|
||||
if (c.PASSED_ALL in self.game_info) and (not self.game_info[c.PASSED_ALL]):
|
||||
self.show_only_one_option = False
|
||||
else:
|
||||
self.show_only_one_option = True
|
||||
self.setupImage()
|
||||
pg.display.set_caption('pypvz: 您获得了新的战利品!')
|
||||
pg.display.set_caption("pypvz: 您获得了新的战利品!")
|
||||
pg.mixer.music.stop()
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, 'zenGarden.opus'))
|
||||
pg.mixer.music.load(os.path.join(c.PATH_MUSIC_DIR, "zenGarden.opus"))
|
||||
pg.mixer.music.play(-1, 0)
|
||||
pg.mixer.music.set_volume(self.game_info[c.SOUND_VOLUME])
|
||||
|
||||
@ -267,7 +214,6 @@ class AwardScreen(tool.State):
|
||||
self.next = c.LEVEL
|
||||
self.done = True
|
||||
|
||||
|
||||
class HelpScreen(tool.State):
|
||||
def __init__(self):
|
||||
tool.State.__init__(self)
|
||||
@ -277,39 +223,31 @@ class HelpScreen(tool.State):
|
||||
self.persist = persist
|
||||
self.game_info = persist
|
||||
self.setupImage()
|
||||
pg.display.set_caption('pypvz: 帮助')
|
||||
pg.display.set_caption("pypvz: 帮助")
|
||||
pg.mixer.music.stop()
|
||||
c.SOUND_HELP_SCREEN.play()
|
||||
|
||||
def setupImage(self):
|
||||
# 主体
|
||||
frame_rect = (-100, -50, 800, 600)
|
||||
self.image = tool.get_image(
|
||||
tool.GFX[c.HELP_SCREEN_IMAGE], *frame_rect, colorkey=(0, 255, 255)
|
||||
)
|
||||
self.image = tool.get_image(tool.GFX[c.HELP_SCREEN_IMAGE], *frame_rect, colorkey=(0, 255, 255))
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 0
|
||||
self.rect.y = 0
|
||||
|
||||
|
||||
# 主菜单按钮
|
||||
frame_rect = (0, 0, 111, 26)
|
||||
self.main_menu_button_image = tool.get_image_alpha(
|
||||
tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect
|
||||
)
|
||||
self.main_menu_button_image_rect = (
|
||||
self.main_menu_button_image.get_rect()
|
||||
)
|
||||
self.main_menu_button_image = tool.get_image_alpha(tool.GFX[c.UNIVERSAL_BUTTON], *frame_rect)
|
||||
self.main_menu_button_image_rect = self.main_menu_button_image.get_rect()
|
||||
self.main_menu_button_image_rect.x = 343
|
||||
self.main_menu_button_image_rect.y = 500
|
||||
### 主菜单按钮上的文字
|
||||
font = pg.font.Font(c.FONT_PATH, 18)
|
||||
main_menu_text = font.render('主菜单', True, c.NAVYBLUE)
|
||||
main_menu_text = font.render("主菜单", True, c.NAVYBLUE)
|
||||
main_menu_text_rect = main_menu_text.get_rect()
|
||||
main_menu_text_rect.x = 29
|
||||
self.main_menu_button_image.blit(main_menu_text, main_menu_text_rect)
|
||||
self.image.blit(
|
||||
self.main_menu_button_image, self.main_menu_button_image_rect
|
||||
)
|
||||
self.image.blit(self.main_menu_button_image, self.main_menu_button_image_rect)
|
||||
|
||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||
surface.fill(c.BLACK)
|
||||
|
||||
158
source/tool.py
158
source/tool.py
@ -1,17 +1,14 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import json
|
||||
from abc import abstractmethod
|
||||
|
||||
import pygame as pg
|
||||
from pygame.locals import *
|
||||
|
||||
from . import constants as c
|
||||
|
||||
logger = logging.getLogger('main')
|
||||
logger = logging.getLogger("main")
|
||||
|
||||
# 状态机 抽象基类
|
||||
class State:
|
||||
class State():
|
||||
def __init__(self):
|
||||
self.start_time = 0
|
||||
self.current_time = 0
|
||||
@ -21,31 +18,30 @@ class State:
|
||||
|
||||
# 当从其他状态进入这个状态时,需要进行的初始化操作
|
||||
@abstractmethod
|
||||
def startup(self, current_time: int, persist: dict):
|
||||
def startup(self, current_time:int, persist:dict):
|
||||
# 前面加了@abstractmethod表示抽象基类中必须要重新定义的method(method是对象和函数的结合)
|
||||
pass
|
||||
|
||||
# 当从这个状态退出时,需要进行的清除操作
|
||||
def cleanup(self):
|
||||
self.done = False
|
||||
return self.persist
|
||||
|
||||
# 在这个状态运行时进行的更新操作
|
||||
@abstractmethod
|
||||
def update(self, surface: pg.Surface, keys, current_time: int):
|
||||
def update(self, surface:pg.Surface, keys, current_time:int):
|
||||
# 前面加了@abstractmethod表示抽象基类中必须要重新定义的method
|
||||
pass
|
||||
|
||||
# 工具:范围判断函数,用于判断点击
|
||||
def inArea(self, rect: pg.Rect, x: int, y: int):
|
||||
if rect.x <= x <= rect.right and rect.y <= y <= rect.bottom:
|
||||
def inArea(self, rect:pg.Rect, x:int, y:int):
|
||||
if (rect.x <= x <= rect.right and
|
||||
rect.y <= y <= rect.bottom):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# 工具:用户数据保存函数
|
||||
def saveUserData(self):
|
||||
with open(c.USERDATA_PATH, 'w', encoding='utf-8') as f:
|
||||
with open(c.USERDATA_PATH, "w", encoding="utf-8") as f:
|
||||
userdata = {}
|
||||
for i in self.game_info:
|
||||
if i in c.INIT_USERDATA:
|
||||
@ -53,19 +49,15 @@ class State:
|
||||
data_to_save = json.dumps(userdata, sort_keys=True, indent=4)
|
||||
f.write(data_to_save)
|
||||
|
||||
|
||||
# 进行游戏控制 循环 事件响应
|
||||
class Control:
|
||||
class Control():
|
||||
def __init__(self):
|
||||
self.screen = pg.display.get_surface()
|
||||
self.done = False
|
||||
self.clock = pg.time.Clock() # 创建一个对象来帮助跟踪时间
|
||||
self.keys = pg.key.get_pressed()
|
||||
self.mouse_pos = None
|
||||
self.mouse_click = [
|
||||
False,
|
||||
False,
|
||||
] # value:[left mouse click, right mouse click]
|
||||
self.mouse_click = [False, False] # value:[left mouse click, right mouse click]
|
||||
self.current_time = 0.0
|
||||
self.state_dict = {}
|
||||
self.state_name = None
|
||||
@ -74,12 +66,12 @@ class Control:
|
||||
# 存在存档即导入
|
||||
# 先自动修复读写权限(Python权限规则和Unix不一样,420表示unix的644,Windows自动忽略不支持项)
|
||||
os.chmod(c.USERDATA_PATH, 420)
|
||||
with open(c.USERDATA_PATH, encoding='utf-8') as f:
|
||||
with open(c.USERDATA_PATH, encoding="utf-8") as f:
|
||||
userdata = json.load(f)
|
||||
except FileNotFoundError:
|
||||
self.setupUserData()
|
||||
except json.JSONDecodeError:
|
||||
logger.warning('用户存档解码错误!程序将新建初始存档!\n')
|
||||
logger.warning("用户存档解码错误!程序将新建初始存档!\n")
|
||||
self.setupUserData()
|
||||
else: # 没有引发异常才执行
|
||||
self.game_info = {}
|
||||
@ -92,10 +84,8 @@ class Control:
|
||||
self.game_info[key] = c.INIT_USERDATA[key]
|
||||
need_to_rewrite = True
|
||||
if need_to_rewrite:
|
||||
with open(c.USERDATA_PATH, 'w', encoding='utf-8') as f:
|
||||
savedata = json.dumps(
|
||||
self.game_info, sort_keys=True, indent=4
|
||||
)
|
||||
with open(c.USERDATA_PATH, "w", encoding="utf-8") as f:
|
||||
savedata = json.dumps(self.game_info, sort_keys=True, indent=4)
|
||||
f.write(savedata)
|
||||
# 存档内不包含即时游戏时间信息,需要新建
|
||||
self.game_info[c.CURRENT_TIME] = 0
|
||||
@ -106,12 +96,12 @@ class Control:
|
||||
def setupUserData(self):
|
||||
if not os.path.exists(os.path.dirname(c.USERDATA_PATH)):
|
||||
os.makedirs(os.path.dirname(c.USERDATA_PATH))
|
||||
with open(c.USERDATA_PATH, 'w', encoding='utf-8') as f:
|
||||
with open(c.USERDATA_PATH, "w", encoding="utf-8") as f:
|
||||
savedata = json.dumps(c.INIT_USERDATA, sort_keys=True, indent=4)
|
||||
f.write(savedata)
|
||||
self.game_info = c.INIT_USERDATA.copy() # 内部全是不可变对象,浅拷贝即可
|
||||
self.game_info = c.INIT_USERDATA.copy() # 内部全是不可变对象,浅拷贝即可
|
||||
|
||||
def setup_states(self, state_dict: dict, start_state):
|
||||
def setup_states(self, state_dict:dict, start_state):
|
||||
self.state_dict = state_dict
|
||||
self.state_name = start_state
|
||||
self.state = self.state_dict[self.state_name]
|
||||
@ -123,10 +113,8 @@ class Control:
|
||||
|
||||
if self.state.done:
|
||||
self.flip_state()
|
||||
|
||||
self.state.update(
|
||||
self.screen, self.current_time, self.mouse_pos, self.mouse_click
|
||||
)
|
||||
|
||||
self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click)
|
||||
self.mouse_pos = None
|
||||
self.mouse_click[0] = False
|
||||
self.mouse_click[1] = False
|
||||
@ -148,24 +136,17 @@ class Control:
|
||||
elif event.type == pg.KEYDOWN:
|
||||
self.keys = pg.key.get_pressed()
|
||||
if event.key == pg.K_f:
|
||||
pg.display.set_mode(
|
||||
c.SCREEN_SIZE, pg.HWSURFACE | pg.FULLSCREEN
|
||||
)
|
||||
pg.display.set_mode(c.SCREEN_SIZE, pg.HWSURFACE|pg.FULLSCREEN)
|
||||
elif event.key == pg.K_u:
|
||||
pg.display.set_mode(c.SCREEN_SIZE)
|
||||
elif event.type == pg.KEYUP:
|
||||
self.keys = pg.key.get_pressed()
|
||||
elif event.type == pg.MOUSEBUTTONDOWN:
|
||||
self.mouse_pos = pg.mouse.get_pos()
|
||||
(
|
||||
self.mouse_click[0],
|
||||
_,
|
||||
self.mouse_click[1],
|
||||
) = pg.mouse.get_pressed()
|
||||
self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed()
|
||||
# self.mouse_click[0]表示左键,self.mouse_click[1]表示右键
|
||||
print(
|
||||
f'点击位置: ({self.mouse_pos[0]:3}, {self.mouse_pos[1]:3}) 左右键点击情况: {self.mouse_click}'
|
||||
)
|
||||
print(f"点击位置: ({self.mouse_pos[0]:3}, {self.mouse_pos[1]:3}) 左右键点击情况: {self.mouse_click}")
|
||||
|
||||
|
||||
def run(self):
|
||||
while not self.done:
|
||||
@ -174,57 +155,39 @@ class Control:
|
||||
pg.display.update()
|
||||
self.clock.tick(self.fps)
|
||||
|
||||
def get_image( sheet:pg.Surface, x:int, y:int, width:int, height:int,
|
||||
colorkey:tuple[int]=c.BLACK, scale:int=1) -> pg.Surface:
|
||||
# 不保留alpha通道的图片导入
|
||||
image = pg.Surface([width, height])
|
||||
rect = image.get_rect()
|
||||
|
||||
def get_image(
|
||||
sheet: pg.Surface,
|
||||
x: int,
|
||||
y: int,
|
||||
width: int,
|
||||
height: int,
|
||||
colorkey: tuple[int] = c.BLACK,
|
||||
scale: int = 1,
|
||||
) -> pg.Surface:
|
||||
# 不保留alpha通道的图片导入
|
||||
image = pg.Surface([width, height])
|
||||
rect = image.get_rect()
|
||||
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||
if colorkey:
|
||||
image.set_colorkey(colorkey)
|
||||
image = pg.transform.scale(image,
|
||||
(int(rect.width*scale),
|
||||
int(rect.height*scale)))
|
||||
return image
|
||||
|
||||
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||
if colorkey:
|
||||
image.set_colorkey(colorkey)
|
||||
image = pg.transform.scale(
|
||||
image, (int(rect.width * scale), int(rect.height * scale))
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
def get_image_alpha(
|
||||
sheet: pg.Surface,
|
||||
x: int,
|
||||
y: int,
|
||||
width: int,
|
||||
height: int,
|
||||
colorkey: tuple[int] = c.BLACK,
|
||||
scale: int = 1,
|
||||
) -> pg.Surface:
|
||||
def get_image_alpha(sheet:pg.Surface, x:int, y:int, width:int, height:int,
|
||||
colorkey:tuple[int]=c.BLACK, scale:int=1) -> pg.Surface:
|
||||
# 保留alpha通道的图片导入
|
||||
image = pg.Surface([width, height], SRCALPHA)
|
||||
rect = image.get_rect()
|
||||
|
||||
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||
image.set_colorkey(colorkey)
|
||||
image = pg.transform.scale(
|
||||
image, (int(rect.width * scale), int(rect.height * scale))
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
def load_image_frames(
|
||||
directory: str, image_name: str, colorkey: tuple[int], accept: tuple[str]
|
||||
) -> list[pg.Surface]:
|
||||
image = pg.transform.scale(image,
|
||||
(int(rect.width*scale),
|
||||
int(rect.height*scale)))
|
||||
return image
|
||||
|
||||
def load_image_frames( directory:str, image_name:str,
|
||||
colorkey:tuple[int], accept:tuple[str]) -> list[pg.Surface]:
|
||||
frame_list = []
|
||||
tmp = {}
|
||||
# image_name is "Peashooter", pic name is "Peashooter_1", get the index 1
|
||||
index_start = len(image_name) + 1
|
||||
index_start = len(image_name) + 1
|
||||
frame_num = 0
|
||||
for pic in os.listdir(directory):
|
||||
name, ext = os.path.splitext(pic)
|
||||
@ -236,20 +199,16 @@ def load_image_frames(
|
||||
else:
|
||||
img = img.convert()
|
||||
img.set_colorkey(colorkey)
|
||||
tmp[index] = img
|
||||
tmp[index]= img
|
||||
frame_num += 1
|
||||
|
||||
for i in range(frame_num): # 这里注意编号必须连续,否则会出错
|
||||
frame_list.append(tmp[i])
|
||||
return frame_list
|
||||
|
||||
|
||||
# colorkeys 是设置图像中的某个颜色值为透明,这里用来消除白边
|
||||
def load_all_gfx(
|
||||
directory: str,
|
||||
colorkey: tuple[int] = c.WHITE,
|
||||
accept: tuple[str] = ('.png', '.jpg', '.bmp', '.gif', '.webp'),
|
||||
) -> dict[str : pg.Surface]:
|
||||
def load_all_gfx( directory:str, colorkey:tuple[int]=c.WHITE,
|
||||
accept:tuple[str]=(".png", ".jpg", ".bmp", ".gif", ".webp")) -> dict[str:pg.Surface]:
|
||||
graphics = {}
|
||||
for name1 in os.listdir(directory):
|
||||
# subfolders under the folder resources\graphics
|
||||
@ -258,25 +217,21 @@ def load_all_gfx(
|
||||
for name2 in os.listdir(dir1):
|
||||
dir2 = os.path.join(dir1, name2)
|
||||
if os.path.isdir(dir2):
|
||||
# e.g. subfolders under the folder resources\graphics\Zombies
|
||||
# e.g. subfolders under the folder resources\graphics\Zombies
|
||||
for name3 in os.listdir(dir2):
|
||||
dir3 = os.path.join(dir2, name3)
|
||||
# e.g. subfolders or pics under the folder resources\graphics\Zombies\ConeheadZombie
|
||||
if os.path.isdir(dir3):
|
||||
# e.g. it"s the folder resources\graphics\Zombies\ConeheadZombie\ConeheadZombieAttack
|
||||
image_name, _ = os.path.splitext(name3)
|
||||
graphics[image_name] = load_image_frames(
|
||||
dir3, image_name, colorkey, accept
|
||||
)
|
||||
graphics[image_name] = load_image_frames(dir3, image_name, colorkey, accept)
|
||||
else:
|
||||
# e.g. pics under the folder resources\graphics\Plants\Peashooter
|
||||
image_name, _ = os.path.splitext(name2)
|
||||
graphics[image_name] = load_image_frames(
|
||||
dir2, image_name, colorkey, accept
|
||||
)
|
||||
graphics[image_name] = load_image_frames(dir2, image_name, colorkey, accept)
|
||||
break
|
||||
else:
|
||||
# e.g. pics under the folder resources\graphics\Screen
|
||||
# e.g. pics under the folder resources\graphics\Screen
|
||||
name, ext = os.path.splitext(name2)
|
||||
if ext.lower() in accept:
|
||||
img = pg.image.load(dir2)
|
||||
@ -288,13 +243,10 @@ def load_all_gfx(
|
||||
graphics[name] = img
|
||||
return graphics
|
||||
|
||||
|
||||
pg.display.set_caption(c.ORIGINAL_CAPTION) # 设置标题
|
||||
SCREEN = pg.display.set_mode(c.SCREEN_SIZE, pg.SCALED) # 设置初始屏幕
|
||||
SCREEN = pg.display.set_mode(c.SCREEN_SIZE) # 设置初始屏幕
|
||||
pg.mixer.set_num_channels(255) # 设置可以同时播放的音频数量,默认为8,经常不够用
|
||||
if os.path.exists(
|
||||
c.ORIGINAL_LOGO
|
||||
): # 设置窗口图标,仅对非Nuitka时生效,Nuitka不需要包括额外的图标文件,自动跳过这一过程即可
|
||||
if os.path.exists(c.ORIGINAL_LOGO): # 设置窗口图标,仅对非Nuitka时生效,Nuitka不需要包括额外的图标文件,自动跳过这一过程即可
|
||||
pg.display.set_icon(pg.image.load(c.ORIGINAL_LOGO))
|
||||
|
||||
GFX = load_all_gfx(c.PATH_IMG_DIR)
|
||||
|
||||
209
uv.lock
generated
209
uv.lock
generated
@ -1,209 +0,0 @@
|
||||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "black"
|
||||
version = "22.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "click" },
|
||||
{ name = "mypy-extensions" },
|
||||
{ name = "pathspec" },
|
||||
{ name = "platformdirs" },
|
||||
{ name = "tomli" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/42/58/8a3443a5034685152270f9012a9d196c9f165791ed3f2777307708b15f6c/black-22.1.0.tar.gz", hash = "sha256:a7c0192d35635f6fc1174be575cb7915e92e5dd629ee79fdaf0dcfa41a80afb5", size = 559521, upload-time = "2022-01-29T20:38:08.749Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/59/bd6d44da2b364fd2bd7a0b2ce2edfe200b79faad1cde14ce5ef13d504393/black-22.1.0-py3-none-any.whl", hash = "sha256:3524739d76b6b3ed1132422bf9d82123cd1705086723bc3e235ca39fd21c667d", size = 160408, upload-time = "2022-01-29T20:38:07.336Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blue"
|
||||
version = "0.9.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "black" },
|
||||
{ name = "flake8" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/68/5a/ef15e7accbe49dbeeb8e7c01e13b8459006c6fed4db8fe833f2ae4924fd7/blue-0.9.1.tar.gz", hash = "sha256:76b4f26884a8425042356601d80773db6e0e14bebaa7a59d7c54bf8cef2e2af5", size = 10594, upload-time = "2022-08-01T16:38:53.798Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/7b/e6bfbe69b8b22abbfbdd993142bcabd1b2ce237a42c250181c5152052feb/blue-0.9.1-py3-none-any.whl", hash = "sha256:037742c072c58a2ff024f59fb9164257b907f97f8f862008db3b013d1f27cc22", size = 10590, upload-time = "2022-08-01T16:38:51.556Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flake8"
|
||||
version = "4.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "mccabe" },
|
||||
{ name = "pycodestyle" },
|
||||
{ name = "pyflakes" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e6/84/d8db922289195c435779b4ca3a3f583f263f87e67954f7b2e83c8da21f48/flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d", size = 154905, upload-time = "2021-10-11T12:42:48.941Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/34/39/cde2c8a227abb4f9ce62fe55586b920f438f1d2903a1a22514d0b982c333/flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", size = 64091, upload-time = "2021-10-11T12:42:47.401Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mccabe"
|
||||
version = "0.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/18/fa675aa501e11d6d6ca0ae73a101b2f3571a565e0f7d38e062eec18a91ee/mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f", size = 8612, upload-time = "2017-01-26T22:13:15.699Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/87/89/479dc97e18549e21354893e4ee4ef36db1d237534982482c3681ee6e7b57/mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", size = 8556, upload-time = "2017-01-26T22:13:14.36Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "1.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.12.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "4.3.8"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fe/8b/3c73abc9c759ecd3f1f7ceff6685840859e8070c4d947c93fae71f6a0bf2/platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", size = 21362, upload-time = "2025-05-07T22:47:42.121Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/39/979e8e21520d4e47a0bbe349e2713c0aac6f3d853d0e5b34d76206c439aa/platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4", size = 18567, upload-time = "2025-05-07T22:47:40.376Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycodestyle"
|
||||
version = "2.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/08/dc/b29daf0a202b03f57c19e7295b60d1d5e1281c45a6f5f573e41830819918/pycodestyle-2.8.0.tar.gz", hash = "sha256:eddd5847ef438ea1c7870ca7eb78a9d47ce0cdb4851a5523949f2601d0cbbe7f", size = 102299, upload-time = "2021-10-11T00:56:27.496Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/15/94/bc43a2efb7b8615e38acde2b6624cae8c9ec86faf718ff5676c5179a7714/pycodestyle-2.8.0-py2.py3-none-any.whl", hash = "sha256:720f8b39dde8b293825e7ff02c475f3077124006db4f440dcbc9a20b76548a20", size = 42112, upload-time = "2021-10-11T00:56:25.599Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyflakes"
|
||||
version = "2.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/15/60/c577e54518086e98470e9088278247f4af1d39cb43bcbd731e2c307acd6a/pyflakes-2.4.0.tar.gz", hash = "sha256:05a85c2872edf37a4ed30b0cce2f6093e1d0581f8c19d7393122da7e25b2b24c", size = 69101, upload-time = "2021-10-06T20:39:50.936Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/fb/38848eb494af7df9aeb2d7673ace8b213313eb7e391691a79dbaeb6a838f/pyflakes-2.4.0-py2.py3-none-any.whl", hash = "sha256:3bb3a3f256f4b7968c9c788781e4ff07dce46bdf12339dcda61053375426ee2e", size = 69704, upload-time = "2021-10-06T20:39:49.185Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pygame"
|
||||
version = "2.6.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/49/cc/08bba60f00541f62aaa252ce0cfbd60aebd04616c0b9574f755b583e45ae/pygame-2.6.1.tar.gz", hash = "sha256:56fb02ead529cee00d415c3e007f75e0780c655909aaa8e8bf616ee09c9feb1f", size = 14808125, upload-time = "2024-09-29T13:41:34.698Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/92/16/2c602c332f45ff9526d61f6bd764db5096ff9035433e2172e2d2cadae8db/pygame-2.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4ee7f2771f588c966fa2fa8b829be26698c9b4836f82ede5e4edc1a68594942e", size = 13118279, upload-time = "2024-09-29T14:26:30.427Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/53/77ccbc384b251c6e34bfd2e734c638233922449a7844e3c7a11ef91cee39/pygame-2.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c8040ea2ab18c6b255af706ec01355c8a6b08dc48d77fd4ee783f8fc46a843bf", size = 12384524, upload-time = "2024-09-29T14:26:49.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/be/3ed337583f010696c3b3435e89a74fb29d0c74d0931e8f33c0a4246307a9/pygame-2.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c47a6938de93fa610accd4969e638c2aebcb29b2fca518a84c3a39d91ab47116", size = 13587123, upload-time = "2024-09-29T11:10:50.072Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/ca/b015586a450db59313535662991b34d24c1f0c0dc149cc5f496573900f4e/pygame-2.6.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33006f784e1c7d7e466fcb61d5489da59cc5f7eb098712f792a225df1d4e229d", size = 14275532, upload-time = "2024-09-29T11:39:59.356Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/f2/d31e6ad42d657af07be2ffd779190353f759a07b51232b9e1d724f2cda46/pygame-2.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1206125f14cae22c44565c9d333607f1d9f59487b1f1432945dfc809aeaa3e88", size = 13952653, upload-time = "2024-09-29T11:40:01.781Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/42/8ea2a6979e6fa971702fece1747e862e2256d4a8558fe0da6364dd946c53/pygame-2.6.1-cp312-cp312-win32.whl", hash = "sha256:84fc4054e25262140d09d39e094f6880d730199710829902f0d8ceae0213379e", size = 10252421, upload-time = "2024-09-29T11:14:26.877Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/90/7d766d54bb95939725e9a9361f9c06b0cfbe3fe100aa35400f0a461a278a/pygame-2.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:3a9e7396be0d9633831c3f8d5d82dd63ba373ad65599628294b7a4f8a5a01a65", size = 10624591, upload-time = "2024-09-29T11:52:54.489Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/91/718acf3e2a9d08a6ddcc96bd02a6f63c99ee7ba14afeaff2a51c987df0b9/pygame-2.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae6039f3a55d800db80e8010f387557b528d34d534435e0871326804df2a62f2", size = 13090765, upload-time = "2024-09-29T14:27:02.377Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/c6/9cb315de851a7682d9c7568a41ea042ee98d668cb8deadc1dafcab6116f0/pygame-2.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2a3a1288e2e9b1e5834e425bedd5ba01a3cd4902b5c2bff8ed4a740ccfe98171", size = 12381704, upload-time = "2024-09-29T14:27:10.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/8f/617a1196e31ae3b46be6949fbaa95b8c93ce15e0544266198c2266cc1b4d/pygame-2.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27eb17e3dc9640e4b4683074f1890e2e879827447770470c2aba9f125f74510b", size = 13581091, upload-time = "2024-09-29T11:30:27.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/87/2851a564e40a2dad353f1c6e143465d445dab18a95281f9ea458b94f3608/pygame-2.6.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c1623180e70a03c4a734deb9bac50fc9c82942ae84a3a220779062128e75f3b", size = 14273844, upload-time = "2024-09-29T11:40:04.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/b5/aa23aa2e70bcba42c989c02e7228273c30f3b44b9b264abb93eaeff43ad7/pygame-2.6.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef07c0103d79492c21fced9ad68c11c32efa6801ca1920ebfd0f15fb46c78b1c", size = 13951197, upload-time = "2024-09-29T11:40:06.785Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/06/29e939b34d3f1354738c7d201c51c250ad7abefefaf6f8332d962ff67c4b/pygame-2.6.1-cp313-cp313-win32.whl", hash = "sha256:3acd8c009317190c2bfd81db681ecef47d5eb108c2151d09596d9c7ea9df5c0e", size = 10249309, upload-time = "2024-09-29T11:10:23.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/11/17f7f319ca91824b86557e9303e3b7a71991ef17fd45286bf47d7f0a38e6/pygame-2.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:813af4fba5d0b2cb8e58f5d95f7910295c34067dcc290d34f1be59c48bd1ea6a", size = 10620084, upload-time = "2024-09-29T11:48:51.587Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pypvz"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "blue" },
|
||||
{ name = "pygame" },
|
||||
{ name = "setuptools" },
|
||||
{ name = "wheel" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "blue", specifier = ">=0.9.1" },
|
||||
{ name = "pygame", specifier = ">=2.6.1" },
|
||||
{ name = "setuptools", specifier = ">=80.9.0" },
|
||||
{ name = "wheel", specifier = ">=0.45.1" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "80.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/5d/3bf57dcd21979b887f014ea83c24ae194cfcd12b9e0fda66b957c69d1fca/setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c", size = 1319958, upload-time = "2025-05-27T00:56:51.443Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/dc/17031897dae0efacfea57dfd3a82fdd2a2aeb58e0ff71b77b87e44edc772/setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", size = 1201486, upload-time = "2025-05-27T00:56:49.664Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.2.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wheel"
|
||||
version = "0.45.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8a/98/2d9906746cdc6a6ef809ae6338005b3f21bb568bea3165cfc6a243fdc25c/wheel-0.45.1.tar.gz", hash = "sha256:661e1abd9198507b1409a20c02106d9670b2576e916d58f520316666abca6729", size = 107545, upload-time = "2024-11-23T00:18:23.513Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/2c/87f3254fd8ffd29e4c02732eee68a83a1d3c346ae39bc6822dcbcb697f2b/wheel-0.45.1-py3-none-any.whl", hash = "sha256:708e7481cc80179af0e556bbf0cc00b8444c7321e2700b8d8580231d13017248", size = 72494, upload-time = "2024-11-23T00:18:21.207Z" },
|
||||
]
|
||||
Loading…
x
Reference in New Issue
Block a user