├── .gitignore ├── LICENSE ├── README.md ├── docs ├── ideas.md ├── tags.md ├── transidea.py ├── transtag.py ├── ~$界面基本设计_old.pptx ├── ~$界面布局.pptx ├── 一些系统设计.docx ├── 界面基本设计_old.pptx ├── 界面布局.pptx ├── 设计文档.docx └── 设计附表_old.xlsx ├── oiasg ├── data │ ├── __user_settings.py │ ├── achievement_data.py │ ├── achievement_pages_data.py │ ├── appendice_data.py │ └── scenarios_data.py ├── define │ ├── __default.py │ ├── _resource.py │ ├── _settings.py │ ├── _ui.py │ ├── achievement.py │ ├── appendice.py │ ├── commons │ │ ├── events.py │ │ ├── game_defines.py │ │ ├── game_init_script.py │ │ ├── play_round_script.py │ │ └── strategies.py │ ├── game_defines.py │ └── scenarios.py ├── dlcs │ └── test_dlc │ │ ├── data │ │ └── __user_settings.py │ │ └── define │ │ └── __default.py ├── icon.ico ├── lib │ ├── __init__.py │ ├── controls.py │ ├── data.py │ ├── game.py │ ├── gameobjects.py │ ├── resource.py │ ├── ui.py │ ├── uidata.py │ └── uiresource.py ├── main.py ├── resources │ ├── ability.png │ ├── ability_icon.png │ ├── add.png │ ├── back.png │ ├── bar_h.png │ ├── bgm.mp3 │ ├── button_select.png │ ├── button_unselect.png │ ├── button_v.png │ ├── button_v_pressed.png │ ├── character.png │ ├── chosen.png │ ├── commonants_icon.png │ ├── commonants_image.png │ ├── contest.png │ ├── contest_disabled.png │ ├── copy.png │ ├── cross.png │ ├── cursor.png │ ├── default.png │ ├── down_button.png │ ├── edit.png │ ├── flag.png │ ├── frame_back.png │ ├── game_stage1.png │ ├── game_stage2.png │ ├── game_stage3.png │ ├── game_stage_contest.png │ ├── goback.png │ ├── header.png │ ├── health_icon.png │ ├── icon.ico │ ├── left.png │ ├── load.png │ ├── log_item.png │ ├── main_back.png │ ├── main_back.xcf │ ├── mood_icon.png │ ├── move_down.png │ ├── move_up.png │ ├── orz.gif │ ├── progress_bar.png │ ├── remove.png │ ├── right.png │ ├── save.png │ ├── scroll_back.png │ ├── scroll_cursor.png │ ├── shift_down.png │ ├── shift_up.png │ ├── slider_back.png │ ├── slider_cursor.png │ ├── smallbutton.png │ ├── smallbutton_pressed.png │ ├── strategy_cursor.png │ ├── strategy_item.png │ ├── strategy_item_selected.png │ ├── stress_icon.png │ ├── switchpage_button_select.png │ ├── tag_button_v.png │ ├── tag_button_v_pressed.png │ ├── tag_rv.png │ ├── tag_rv_selected.png │ ├── test_video.mp4 │ ├── test_video2.mp4 │ ├── timetable.png │ ├── timetable_item.png │ ├── up_button.png │ ├── up_button.svg │ ├── up_button_disabled.png │ ├── 杨任东竹石体-Regular.ttf │ └── 杨任东竹石体-Semibold.ttf └── saves │ ├── save0.oiasgsav │ ├── save1.oiasgsav │ ├── save2.oiasgsav │ └── save3.oiasgsav ├── oiasg_base ├── __commons │ ├── __ini.py │ ├── _vars │ │ ├── code.py │ │ ├── ideas.py │ │ ├── knowledge.py │ │ ├── mood.py │ │ └── thinking.py │ ├── contests │ │ ├── _problemgen.py │ │ └── example.py │ └── events │ │ ├── __system.py │ │ ├── example.py │ │ └── strategy │ │ └── __general.py ├── lib │ ├── __init__.py │ ├── appearance.py │ ├── game.py │ └── ini.py ├── main.py └── scenarios │ └── __general.py ├── oiasg_gui ├── lib │ ├── __init__.py │ ├── appearance.py │ └── controls.py ├── resource │ ├── Button.wav │ ├── CLICK_01.WAV │ ├── ball.bmp │ ├── ball.wav │ ├── ball2.bmp │ ├── bgm.mp3 │ ├── bslider.png │ ├── progressh.png │ ├── scroll.png │ ├── sliderf0.png │ ├── sliderf1.png │ ├── t.png │ ├── tbut.png │ ├── tframe.png │ ├── tico.png │ ├── walk.gif │ └── y.png ├── test.py └── test2.py ├── oiasg_removed_files ├── commons │ └── test.py ├── old__commons │ ├── __ini.py │ ├── _vars │ │ ├── code.py │ │ ├── ideas.py │ │ ├── knowledge.py │ │ ├── mood.py │ │ └── thinking.py │ ├── contests │ │ ├── _problemgen.py │ │ └── example.py │ └── events │ │ ├── __system.py │ │ ├── example.py │ │ └── strategy │ │ └── __general.py ├── old_fonts │ ├── 杨任东竹石体-Regular.ttf │ └── 杨任东竹石体-Semibold.ttf ├── old_game.py └── scenarios │ └── __general.py └── pyglet └── font └── win32.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | 49 | # Translations 50 | *.mo 51 | *.pot 52 | 53 | # Django stuff: 54 | *.log 55 | local_settings.py 56 | 57 | # Flask stuff: 58 | instance/ 59 | .webassets-cache 60 | 61 | # Scrapy stuff: 62 | .scrapy 63 | 64 | # Sphinx documentation 65 | docs/_build/ 66 | 67 | # PyBuilder 68 | target/ 69 | 70 | # Jupyter Notebook 71 | .ipynb_checkpoints 72 | 73 | # pyenv 74 | .python-version 75 | 76 | # celery beat schedule file 77 | celerybeat-schedule 78 | 79 | # SageMath parsed files 80 | *.sage.py 81 | 82 | # dotenv 83 | .env 84 | 85 | # virtualenv 86 | .venv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | .spyproject 93 | 94 | # Rope project settings 95 | .ropeproject 96 | 97 | # mkdocs documentation 98 | /site 99 | 100 | # mypy 101 | .mypy_cache/ 102 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Cheng-ao Liu 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OIASG 2 | An OIer's Adventure-Strategy Game Engine 3 | 4 | OIASG is an light,simple and naive game engine for adventure-strategy games with events(and can be used for plots),tech trees and exams. 5 | 6 | The engine users works with python and APIs in a subnamespace of the game. 7 | 8 | It also has a default GUI and basic OI strategy systems for the certain game project:"OI Diary"(a temporary call). 9 | 10 | ## about development 11 | 12 | OIASG is based on python 3 and [pyglet](http://pyglet.org/). 13 | 14 | We use modified(mainly debugging) pyglet 1.4.0a1 for windows.You can get the modifications form `/pyglet`. 15 | 16 | **The game is chiefly for Windows 10,so it may not work well on other platforms(but this is not normal).** 17 | 18 | **Note that pyglet1.4.0a1 uses FFmpeg to decode medias.** 19 | 20 | ## How to run OIASG 21 | 22 | 1. install Python 3(>=3.6.3) 23 | 24 | 2. install pyglet for python3(>=1.4.0a1) 25 | 26 | 3. if you are using Windows OS(especially Windows 10),cover pyglet library directory(usually at `C:\Users\\AppData\Local\Programs\Python\Python36\Lib\site-packages\pyglet`) with `/pyglet`. 27 | 28 | 4. install FFmpeg(==3.4.2,"shared" version(including libs)) 29 | 30 | 5. clone files from `/oiasg`. 31 | 32 | 6. run `/oiasg/main.py` to start. 33 | -------------------------------------------------------------------------------- /docs/ideas.md: -------------------------------------------------------------------------------- 1 | 状态压缩 2 | 映射 3 | 分治 4 | 延迟处理 5 | 单调性 6 | 二分 7 | 倍增 8 | 分块 9 | 记忆化 10 | 可持久化 11 | 离线 12 | 近似 13 | 随机化 14 | 启发和估价 -------------------------------------------------------------------------------- /docs/tags.md: -------------------------------------------------------------------------------- 1 | 1. 算法 (AG) 2 | 1. 动态规划 (DP) 3 | 1. DAG 模型 4 | 1. 背包DP 5 | 1. 数位DP 6 | 1. 插头DP 7 | 1. 子树DP 8 | 1. 区间DP 9 | 1. 决策优化 10 | 1. 分步式转移 11 | 1. 单调性分治 12 | 1. 维护移动端点 13 | 1. 斜率优化 14 | 1. 四边形不等式 15 | 1. 网络流 (NF) 16 | 1. 网络流线性规划 17 | 1. 上下界网络流 18 | 1. 最小割 19 | 1. 费用流 20 | 1. Edmond-Karp (EK) 21 | 1. Capacity Scaling 22 | 1. Dinic&SAP 23 | 1. HLPP 24 | 1. 差分约束 (DC) 25 | 1. 通用线性规划 (LP) 26 | 1. 单纯形算法 27 | 1. 分数规划 (FP) 28 | 1. 贪心 (GE) 29 | 1. 分治 (DAC) 30 | 1. 序列分治 31 | 1. CDQ&整体二分&线段树分治 32 | 1. 快速排序 33 | 1. 快速选择 34 | 1. Median of Medians 35 | 1. 树分治 36 | 1. 点/边分治 37 | 1. 重链剖分 38 | 1. 树上启发式合并 39 | 1. 长链剖分 40 | 1. 搜索 (SR) 41 | 1. DFS (DFS) 42 | 1. BFS (BFS) 43 | 1. 搜索优化与剪枝 44 | 1. A* (AS) 45 | 1. 迭代加深搜索 (ID) 46 | 1. 折半搜索 (MIM) 47 | 1. 随机化及近似 (RAN) 48 | 1. 爬山 49 | 1. 模拟退火 50 | 1. 遗传算法 51 | 1. 机器学习基础 52 | 1. 离线逆序 53 | 1. 莫队算法 54 | 1. 散列 (HS) 55 | 1. 数据结构 (DS) 56 | 1. 栈 (STK) 57 | 1. 队列 (QUE) 58 | 1. 散列表 (HST) 59 | 1. 堆 (HP) 60 | 1. 二叉堆 61 | 1. 可并堆 62 | 1. 二叉查找树 (BST) 63 | 1. 堆树 (THP) 64 | 1. 伸展树 (SPT) 65 | 1. 红黑树 (RBT) 66 | 1. 替罪羊树 (SGT) 67 | 1. 树状数组 (BIT) 68 | 1. 线段树 (SGM) 69 | 1. 划分树与归并树 70 | 1. 并查集 (UFS) 71 | 1. 带权并查集 72 | 1. 路径压缩 73 | 1. 按秩合并 74 | 1. Sparse Table (ST) 75 | 1. K维树 (KDT) 76 | 1. 动态树 77 | 1. 点/边分治树 (DCT) 78 | 1. Link-Cut Tree (LCT) 79 | 1. 欧拉回路树 (ETT) 80 | 1. AAA Tree & Top Tree 81 | 1. 动态图 82 | 1. 图论 (GT) 83 | 1. 最小生成树 84 | 1. Prim 算法 (PM) 85 | 1. Kruskal 算法 (KS) 86 | 1. Boruvka 算法 87 | 1. 最小树形图 88 | 1. 朱-刘算法 89 | 1. 斯坦纳树 90 | 1. 最短路径 91 | 1. dijkstra 算法 (DJ) 92 | 1. Bellman-Ford 算法 (BFD) 93 | 1. Johnson 算法 94 | 1. Floyd 算法 (FL) 95 | 1. 欧拉路&哈密顿路 96 | 1. 连通性 97 | 1. 点/边双连通分量 (BCC) 98 | 1. 强连通性 (SCC) 99 | 1. 支配树 100 | 1. 匹配、划分与覆盖 101 | 1. KM 算法 (KM) 102 | 1. 交错树 103 | 1. 带花树算法 (BL) 104 | 1. Tutte 矩阵与一般图匹配 105 | 1. 覆盖集与独立集 106 | 1. 稳定婚姻问题与 GS 算法 (GS) 107 | 1. Hall 定理 108 | 1. DAG 路径覆盖 109 | 1. Dilworth 定理 110 | 1. 2-SAT 111 | 1. 虚树 112 | 1. 仙人掌 113 | 1. 圆方树 114 | 1. 弦图与区间图 115 | 1. 图的树分解 116 | 1. 最小割 117 | 1. 最小割树 118 | 1. Stoer-Wagner 算法 119 | 1. 平面图 120 | 1. 平面图对偶图 121 | 1. 网格图 122 | 1. 计算几何 (CG) 123 | 1. 几何向量 124 | 1. 二维凸包 125 | 1. 凸包算法 126 | 1. 卷包裹法 127 | 1. 动态凸包 128 | 1. 三维凸包 129 | 1. 半平面交 130 | 1. 旋转卡壳 131 | 1. 三角剖分 132 | 1. V图 133 | 1. 路径规划 134 | 1. 代数 (AB) 135 | 1. 微积分基础 136 | 1. Simpson 积分算法 137 | 1. 线性代数 138 | 1. 矩阵基础 139 | 1. 高斯消元 140 | 1. 拟阵 141 | 1. Matrix-Tree 定理 142 | 1. 线性递推 143 | 1. 多项式与幂级数 144 | 1. DFT/FFT (FT) 145 | 1. NTT 146 | 1. Bluestein 算法 147 | 1. 多项式基本运算 148 | 1. 多项式除法 149 | 1. 多项式基本初等函数 150 | 1. FWT (FWT) 151 | 1. 子集变换 152 | 1. 抽象代数 153 | 1. 置换群 154 | 1. Schreier-Sims 算法 155 | 1. 数论 (NT) 156 | 1. 同余和整除 157 | 1. 欧几里得算法 158 | 1. 扩展欧几里得算法 159 | 1. 类欧几里得算法 160 | 1. 欧拉定理 161 | 1. 二次剩余 162 | 1. 原根及离散对数 163 | 1. BSGS 164 | 1. lucas 定理 165 | 1. 质数与简单数论函数 166 | 1. 埃氏筛 167 | 1. 欧拉筛 168 | 1. 莫比乌斯反演 169 | 1. 数论函数快速求和 170 | 1. 杜教筛 171 | 1. 洲阁筛 172 | 1. 素性测试 173 | 1. Miller-Robin (MR) 174 | 1. Pollard's Rho 因子分解 175 | 1. 组合计数 (CE) 176 | 1. 计数原理 177 | 1. 容斥原理 178 | 1. 计数数列 179 | 1. 斯特林数 180 | 1. 卡特兰数 181 | 1. 伯努利数 182 | 1. 生成函数 (GF) 183 | 1. 杨氏矩阵 184 | 1. Burnside 引理 185 | 1. Polya 定理 186 | 1. 博弈论与信息论 (GI) 187 | 1. 博弈基础 188 | 1. 组合游戏 189 | 1. 博弈树与 DAG 模型 190 | 1. Sprague-Grundy 函数 (SG) 191 | 1. Nim (NIM) 192 | 1. Nim 积 193 | 1. 威佐夫博弈 194 | 1. 不平等博弈 195 | 1. 超现实数 196 | 1. 不完全信息博弈 197 | 1. 通信与数据压缩 198 | 1. 校验码 199 | 1. 哈夫曼编码 200 | 1. 游程编码 201 | 1. 形式语言,自动机与串处理 (FAS) 202 | 1. 串处理 (STR) 203 | 1. 模式匹配 204 | 1. KMP 算法 (KMP) 205 | 1. AC 自动机 206 | 1. Shift-And 算法 207 | 1. 字典树 (TRI) 208 | 1. 后缀树 209 | 1. 后缀数组 (SA) 210 | 1. 后缀自动机 (SAM) 211 | 1. Border 212 | 1. Periodicity 引理 213 | 1. 回文串 214 | 1. manacher 算法 215 | 1. 回文自动机 (PAM) 216 | 1. 形式语言 217 | 1. 正则表达式 (RE) 218 | 1. 有限状态自动机 (DFA) 219 | 1. 并行计算 -------------------------------------------------------------------------------- /docs/transidea.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | f = open('ideas.md', 'r', encoding = 'utf-8').readlines() 4 | 5 | def pr(id, name): 6 | print( 7 | ''' 8 | %s:{ 9 | 'name':'%s', 10 | 'appearance':None, 11 | 'relations':{}, 12 | 'privilege':0, 13 | 'level':0, 14 | }''' % (id,name)) 15 | 16 | print('''ideas.update({ 17 | ''') 18 | it = 0 19 | 20 | for r in f: 21 | print('\t,') 22 | pr(it,r.strip()) 23 | it += 1 24 | 25 | print('''}) 26 | ''') 27 | 28 | -------------------------------------------------------------------------------- /docs/transtag.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | f = open('tags.md', 'r', encoding = 'utf-8').readlines() 4 | 5 | def gettab(r): 6 | c = 0 7 | while r[0] == '\t': 8 | c += 1 9 | r = r[1:] 10 | return c,r 11 | 12 | def pr(id, name, pa): 13 | print( 14 | ''' 15 | %s:{ 16 | 'name':'%s', 17 | 'appearance':None, 18 | 'parent':%s, 19 | 'relations':{}, 20 | 'privilege':0, 21 | 'difficulty':0, 22 | 'level':0, 23 | 'traits':{ 24 | 'structure':1, 25 | 'graphic':1 26 | } 27 | }''' 28 | % (id,name,pa) 29 | ) 30 | 31 | print('''tags.update({ 32 | ''') 33 | stk = [] 34 | mp = [] 35 | dep = {} 36 | it = 0 37 | 38 | pr(it,'root','None') 39 | stk.append(it) 40 | dep[it] = -1 41 | it += 1 42 | 43 | for r in f: 44 | cnt,x = gettab(r) 45 | dep[it] = cnt 46 | x = x.split() 47 | x.pop(0) 48 | if x[-1][-1] == ')': 49 | n = re.sub('[^A-Z]','',x[-1]) 50 | mp.append((n,it)) 51 | x.pop() 52 | x = ''.join(x) 53 | while dep[stk[-1]] >= cnt: 54 | stk.pop() 55 | print('\t,') 56 | pr(it,x,stk[-1]) 57 | stk.append(it) 58 | it += 1 59 | 60 | print('''}) 61 | ''') 62 | 63 | for i in mp: 64 | print('%s = tags[%s]' % i) 65 | -------------------------------------------------------------------------------- /docs/~$界面基本设计_old.pptx: -------------------------------------------------------------------------------- 1 | 2 | CommonAnts 3 | CommonAnts -------------------------------------------------------------------------------- /docs/~$界面布局.pptx: -------------------------------------------------------------------------------- 1 | 2 | CommonAnts 3 | CommonAnts -------------------------------------------------------------------------------- /docs/一些系统设计.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/docs/一些系统设计.docx -------------------------------------------------------------------------------- /docs/界面基本设计_old.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/docs/界面基本设计_old.pptx -------------------------------------------------------------------------------- /docs/界面布局.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/docs/界面布局.pptx -------------------------------------------------------------------------------- /docs/设计文档.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/docs/设计文档.docx -------------------------------------------------------------------------------- /docs/设计附表_old.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/docs/设计附表_old.xlsx -------------------------------------------------------------------------------- /oiasg/data/__user_settings.py: -------------------------------------------------------------------------------- 1 | {'FULLSCREEN': False, 'VOLUME_MUSIC': 1, 'VOLUME_EFFECT': 1, 'VOLUME_GAME': 1} -------------------------------------------------------------------------------- /oiasg/data/achievement_data.py: -------------------------------------------------------------------------------- 1 | {'ACHIEVEMENT_DATA': {0: {'got': True, 'visible': True}, 1: {'got': False, 'visible': True}, 2: {'got': False, 'visible': True}, 3: {'got': False, 'visible': False}}} -------------------------------------------------------------------------------- /oiasg/data/achievement_pages_data.py: -------------------------------------------------------------------------------- 1 | {'ACHIEVEMENT_PAGES_DATA': {0: {'visible': True}, 1: {'visible': True}, 2: {'visible': False}}} -------------------------------------------------------------------------------- /oiasg/data/appendice_data.py: -------------------------------------------------------------------------------- 1 | {'APPENDICE_DATA': {0: {'visible': True}, 1: {'visible': True}, 2: {'visible': True}, 3: {'visible': True}, 4: {'visible': True}, 5: {'visible': True}, 6: {'visible': True}, 7: {'visible': False}, 8: {'visible': True}, 9: {'visible': True}, 10: {'visible': True}, 11: {'visible': True}, 12: {'visible': True}, 13: {'visible': True}}} -------------------------------------------------------------------------------- /oiasg/data/scenarios_data.py: -------------------------------------------------------------------------------- 1 | {'SCENARIOS_DATA': {'random': {'visible': True}, 'wxhakioi2019': {'visible': True}, 'lcaggctsc2018': {'visible': True}, 'random_1': {'visible': True}, 'wxhakioi2019_1': {'visible': True}, 'lcaggctsc2018_1': {'visible': True}, 'random_2': {'visible': False}, 'wxhakioi2019_2': {'visible': True}, 'lcaggctsc2018_2': {'visible': True}, 'random_3': {'visible': True}, 'wxhakioi2019_3': {'visible': True}, 'lcaggctsc2018_3': {'visible': True}}} -------------------------------------------------------------------------------- /oiasg/define/__default.py: -------------------------------------------------------------------------------- 1 | { 2 | # 基本设置 3 | 4 | '_DEBUG':True, 5 | 6 | # 基本信息 7 | 8 | 'PACKAGE_NAME':'Main game alpha 0.1', 9 | 10 | 'GAME_NAME':'OIASG TEST', 11 | 12 | } -------------------------------------------------------------------------------- /oiasg/define/_resource.py: -------------------------------------------------------------------------------- 1 | { 2 | 'FONTS':[ 3 | ('杨任东竹石体-Regular.ttf','杨任东竹石体-Regular'), 4 | ('杨任东竹石体-Semibold.ttf','杨任东竹石体-Semibold') 5 | ], 6 | } -------------------------------------------------------------------------------- /oiasg/define/_settings.py: -------------------------------------------------------------------------------- 1 | { 2 | 'FULLSCREEN_DEFAULT':False, 3 | 'VOLUME_MUSIC_DEFAULT':1, 4 | 'VOLUME_EFFECT_DEFAULT':1, 5 | 'VOLUME_GAME_DEFAULT':1, 6 | } -------------------------------------------------------------------------------- /oiasg/define/_ui.py: -------------------------------------------------------------------------------- 1 | { 2 | 'UI':{ 3 | # 通用外观 4 | 5 | 'MOUSE_CURSOR':'cursor.png', 6 | 'CAPTION':'OIASG TEST', 7 | 'ICON':'icon.ico', 8 | 'MIN_SIZE':(960,540), 9 | 10 | 'DEFAULT_POS':((0,0),(0,0),(1,0),(1,0)), 11 | 12 | # 通用声音 13 | 14 | 15 | # 通用媒体 16 | 17 | 'ED_FILE':'test_video2.mp4', 18 | 19 | # 通用界面 20 | 21 | 'NORMAL_PAGE_BACK':'back.png', 22 | 'NORMAL_MENU_BACK':'frame_back.png', 23 | 'NORMAL_DEFAULT_IMAGE':'default.png', 24 | 25 | # 通用大标题 26 | 27 | 'NORMAL_TITLE0_FONT':'杨任东竹石体-Semibold', 28 | 'NORMAL_TITLE0_FONT_SIZE':44, 29 | 'NORMAL_TITLE0_COLOR':(131,84,7,255), 30 | 31 | # 通用标题 32 | 33 | 'NORMAL_TITLE_FONT':'杨任东竹石体-Semibold', 34 | 'NORMAL_TITLE_FONT_SIZE':28, 35 | 'NORMAL_TITLE_COLOR':(64,48,0,255), 36 | 37 | # 通用二级标题 38 | 39 | 'NORMAL_TITLE2_FONT':'杨任东竹石体-Semibold', 40 | 'NORMAL_TITLE2_FONT_SIZE':24, 41 | 'NORMAL_TITLE2_COLOR':(131,84,7,255), 42 | 43 | # 通用按钮 44 | 45 | 'NORMAL_BUTTON_FONT':'杨任东竹石体-Regular', 46 | 'NORMAL_BUTTON_FONT_SIZE':20, 47 | 'NORMAL_BUTTON_FONT_COLOR':(255,255,255,255), 48 | 'NORMAL_BUTTON_BACK':'button_v.png', 49 | 'NORMAL_BUTTON_PRESSED_BACK':'button_v_pressed.png', 50 | 'NORMAL_BUTTON_HOVER_COLOR':(252,232,200), 51 | 'NORMAL_BUTTON_COLOR':(255,255,255), 52 | 53 | 'NORMAL_SWITCHBUTTON_BACK':'button_unselect.png', 54 | 'NORMAL_SWITCHBUTTON_SELECT_BACK':'button_select.png', 55 | 56 | 'NORMAL_TAG_RV_IMAGE':'tag_rv.png', 57 | 'NORMAL_TAG_RV_SELECTED_IMAGE':'tag_rv_selected.png', 58 | 59 | # 通用标签 60 | 61 | 'NORMAL_VALUE_FONT':'杨任东竹石体-Regular', 62 | 'NORMAL_VALUE_FONT_SIZE':18, 63 | 'NORMAL_VALUE_FONT_COLOR':(255,255,255,255), 64 | 65 | 'NORMAL_LABEL_FONT':'杨任东竹石体-Regular', 66 | 'NORMAL_LABEL_FONT_SIZE':20, 67 | 'NORMAL_LABEL_COLOR':(131,84,7,255), 68 | 69 | # 通用信息框 70 | 71 | 'NORMAL_MESSAGE_TEXT_STYLE':{'align':'left','color':(131,84,7,255),'font_name':'杨任东竹石体-Regular','font_size':20,'line_spacing':28,'wrap':'char'}, 72 | 'NORMAL_MESSAGE_TEXT_STYLE_TEXT':'''{align 'left'}{color (131,84,7,255)}{font_name '杨任东竹石体-Regular'}{font_size 20}{line_spacing 26}{wrap 'char'}''', 73 | 74 | # 通用输入框 75 | 76 | 'NORMAL_INPUT_TEXT_STYLE':{'align':'left','color':(131,84,7,255),'font_name':'杨任东竹石体-Regular','font_size':20}, 77 | 'NORMAL_INPUT_TEXT_SELECT_BACKCOLOR':(131,84,7,127), 78 | 'NORMAL_INPUT_TEXT_SELECT_TEXTCOLOR':(255,255,255,255), 79 | 'NORMAL_INPUT_TEXT_SELECT_CARETCOLOR':(131,84,7), 80 | 81 | # 通用选择框 82 | 83 | 'NORMAL_CHECKBOX_UNCHECKED_BACK':'cross.png', 84 | 'NORMAL_CHECKBOX_CHECKED_BACK':'chosen.png', 85 | 86 | # 通用滑杆 87 | 88 | 'NORMAL_SLIDER_BACK':'slider_back.png', 89 | 'NORMAL_SLIDER_CURSOR':'slider_cursor.png', 90 | 91 | # 通用滚动条 92 | 93 | 'NORMAL_SCROLLBAR_BACK':'scroll_back.png', 94 | 'NORMAL_SCROLLBAR_CURSOR':'scroll_cursor.png', 95 | 96 | # 通用进度条 97 | 98 | 'NORMAL_PROGRESS_BAR_FRONT':'progress_bar.png', 99 | 'NORMAL_PROGRESS_BAR_BACK':'progress_bar.png', 100 | 101 | # 通用窗口 102 | 103 | 'NORMAL_ALERT_POS':((0.5,-150),(0.5,-120),(0,300),(0,240)), 104 | 'NORMAL_ALERT_NOTITLE_POS':((0.5,-150),(0.5,-100),(0,300),(0,200)), 105 | 'NORMAL_ALERT_BUTTON_TEXT':'确认', 106 | 107 | 'NORMAL_MESSAGE_POS':((0.5,-236),(0.5,-236),(0,472),(0,472)), 108 | 'NORMAL_MESSAGE_BUTTON_TEXT':'返回', 109 | 'NORMAL_MESSAGE_BACK':'frame_back.png', 110 | 111 | # 确认窗口 112 | 113 | 'CONFIRM_BOX_POS':((0.5,-118),(0.5,-79),(0,236),(0,158)), 114 | 'CONFIRM_BOX_POS_MIDDLE':((0.5,-118),(0.5,-118),(0,236),(0,236)), 115 | 'CONFIRM_BOX_YES_TEXT':'是', 116 | 'CONFIRM_BOX_NO_TEXT':'否', 117 | 118 | # 成就界面 119 | 120 | 'ACHIEVEMENT_TAG_HEIGHT':50, 121 | 'ACHIEVEMENT_TAG_WIDTH':150, 122 | 'ACHIEVEMENT_TAG_PADDING':20, 123 | 124 | 'ACHIEVEMENT_PAGE_TITLE':'成就', 125 | 'ACHIEVEMENT_PAGE_TITLE_POS':((0.5,0),(1,-50),(0,0),(0,0)), 126 | 127 | 'ACHIEVEMENT_PAGE_CONFIRM_TEXT':'返回', 128 | 'ACHIEVEMENT_PAGE_CONFIRM_POS':((1,-120),(1,-50),(0,100),(0,30)), 129 | 130 | 'ACHIEVEMENT_PAGE_ITEM_UNGOTTEN_COLOR':(127,127,127), 131 | 'ACHIEVEMENT_PAGE_ITEM_UNGOTTEN_HOVER_COLOR':(192,192,192), 132 | 133 | 'ACHIEVEMENT_MESSAGE_GOTTEN_TITLE':'已获得成就', 134 | 'ACHIEVEMENT_MESSAGE_UNGOTTEN_TITLE':'尚未获得该成就', 135 | 136 | 'ACHIEVEMENT_MESSAGE_POS':((0.5,-400),(0.5,-170),(0,800),(0,340)), 137 | 'ACHIEVEMENT_MESSAGE_ICON_POS':((0,20),(0,20),(0,300),(0,300)), 138 | 'ACHIEVEMENT_MESSAGE_TITLE_POS':((1,-250),(1,-30),(0,0),(0,0)), 139 | 'ACHIEVEMENT_MESSAGE_STATELABEL_POS':((1,-250),(1,-80),(0,0),(0,0)), 140 | 'ACHIEVEMENT_MESSAGE_TEXT_POS':((0,340),(0,50),(1,-360),(1,-150)), 141 | 'ACHIEVEMENT_MESSAGE_CONFIRM_POS':((1,-300),(0,20),(0,100),(0,30)), 142 | 143 | 'ACHIEVEMENT_MESSAGE_CONFIRM_TEXT':'确认', 144 | 145 | # 附录界面 146 | 147 | 'APPENDICE_PAGE_TITLE':'图鉴', 148 | 'APPENDICE_PAGE_TITLE_POS':((0.5,-180),(1,-50),(0,0),(0,0)), 149 | 150 | 'APPENDICE_PAGE_CONFIRM_TEXT':'返回', 151 | 'APPENDICE_PAGE_CONFIRM_POS':((0,20),(1,-50),(0,100),(0,30)), 152 | 153 | 'APPENDICE_PAGE_INFO_POS':((0,20),(0,20),(1,-400),(1,-120)), 154 | 'APPENDICE_PAGE_SELECT_POS':((1,-360),(0,20),(0,340),(1,-40)), 155 | 156 | 'APPENDICE_PAGE_INFO_ICON_POS':((0,20),(1,-340),(0,320),(0,320)), 157 | 'APPENDICE_PAGE_INFO_LABEL_POS':((0,170),(0.5,-160),(0,0),(0,0)), 158 | 'APPENDICE_PAGE_INFO_TEXT_POS':((0,360),(0,20),(1,-380),(1,-40)), 159 | 160 | 'APPENDICE_PAGE_SELECT_ITEM_HEIGHT':64, 161 | 'APPENDICE_PAGE_SELECT_ITEM_BLANKING':15, 162 | 163 | 'APPENDICE_ITEMS_NONE_TEXT':'图鉴里还没有东西喔', 164 | 165 | # 剧本选择界面 166 | 167 | 'SCENARIO_PAGE_TITLE':'选择剧本', 168 | 'SCENARIO_PAGE_TITLE_POS':((0.5,-220),(1,-50),(0,0),(0,0)), 169 | 170 | 'SCENARIO_PAGE_CONFIRM_TEXT':'返回', 171 | 'SCENARIO_PAGE_CONFIRM_POS':((0,20),(1,-50),(0,100),(0,30)), 172 | 173 | 'SCENARIO_PAGE_START_TEXT':'开始', 174 | 'SCENARIO_PAGE_START_POS':((1,-560),(1,-50),(0,100),(0,30)), 175 | 176 | 'SCENARIO_PAGE_INFO_POS':((0,20),(0,20),(1,-480),(1,-120)), 177 | 'SCENARIO_PAGE_SELECT_POS':((1,-440),(0,20),(0,420),(1,-40)), 178 | 179 | 'SCENARIO_PAGE_INFO_ICON_POS':((0,20),(1,-340),(0,320),(0,320)), 180 | 'SCENARIO_PAGE_INFO_LABEL_POS':((0,170),(0.5,-160),(0,0),(0,0)), 181 | 'SCENARIO_PAGE_INFO_TEXT_POS':((0,360),(0,20),(1,-380),(1,-40)), 182 | 183 | 'SCENARIO_PAGE_SELECT_ITEM_HEIGHT':64, 184 | 'SCENARIO_PAGE_SELECT_ITEM_BLANKING':15, 185 | 186 | 'SCENARIO_ITEMS_NONE_TEXT':'没有可用的剧本', 187 | 188 | # 设置窗口 189 | 190 | 'SETTING_MENU_POS':((0.5,-236),(0.5,-236),(0,472),(0,472)), 191 | 192 | 'SETTING_MENU_TITLE':'设置', 193 | 'SETTING_MENU_TITLE_POS':((0.5,0),(1,-60),(0,0),(0,0)), 194 | 195 | 'SETTING_MENU_CONFIRM_TEXT':'返回', 196 | 'SETTING_MENU_CONFIRM_POS':((0.3,0),(0,20),(0.4,0),(0,40)), 197 | 198 | 'SETTING_MENU_SOUND_FRAME_POS':((0,0),(0,200),(1,0),(1,-300)), 199 | 'SETTING_MENU_SOUND_TITLE':'音量', 200 | 'SETTING_MENU_SOUND_TITLE_POS':((0.5,0),(1,-20),(0,0),(0,0)), 201 | 202 | 'SETTING_MENU_VOLUME_MUSIC_TEXT':'音乐', 203 | 'SETTING_MENU_VOLUME_MUSIC_POS':((0,116),(0,0),(1,-136),(0,40)), 204 | 'SETTING_MENU_VOLUME_MUSIC_LABEL_POS':((0,20),(0,0),(0,0),(0,40)), 205 | 'SETTING_MENU_VOLUME_EFFECT_TEXT':'音效', 206 | 'SETTING_MENU_VOLUME_EFFECT_POS':((0,116),(0.5,-40),(1,-136),(0,40)), 207 | 'SETTING_MENU_VOLUME_EFFECT_LABEL_POS':((0,20),(0.5,-40),(0,0),(0,40)), 208 | 'SETTING_MENU_VOLUME_GAME_TEXT':'游戏音', 209 | 'SETTING_MENU_VOLUME_GAME_POS':((0,116),(1,-80),(1,-136),(0,40)), 210 | 'SETTING_MENU_VOLUME_GAME_LABEL_POS':((0,20),(1,-80),(0,0),(0,40)), 211 | 212 | 'SETTING_MENU_FULLSCREEN_TEXT':'全屏显示', 213 | 'SETTING_MENU_FULLSCREEN_POS':((0.5,-15),(0,150),(0,30),(0,30)), 214 | 'SETTING_MENU_FULLSCREEN_LABEL_POS':((0,20),(0,165),(0,0),(0,0)), 215 | 216 | 'SETTING_MENU_RESET_TEXT':'恢复默认', 217 | 'SETTING_MENU_RESET_POS':((0.5,-75),(0,80),(0,150),(0,40)), 218 | 219 | # 版本信息界面 220 | 221 | 'VERSION_PAGE_POS':((0.5,-236),(0.5,-160),(0,472),(0,320)), 222 | 'VERSION_PAGE_TITLE':'版本信息', 223 | 224 | # 关于页面 225 | 226 | 'ABOUT_PAGE_POS':((0.5,-354),(0.5,-236),(0,708),(0,472)), 227 | 'ABOUT_PAGE_TITLE':'关于', 228 | 'ABOUT_PAGE_TEXT':'''T 229 | {font_name '杨任东竹石体-Semibold'}{font_size 28}关于我们{font_size 12}, 230 | 231 | 232 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 233 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 234 | 235 | 236 | ''', 237 | 238 | 'ABOUT_PAGE_CONFIRM_TEXT':'返回', 239 | 'ABOUT_PAGE_WATCH_ED_TEXT':'观看结束动画', 240 | 'ABOUT_PAGE_WATCH_ED_POS':((0,20),(1,-50),(0,200),(0,30)), 241 | 242 | 'ABOUT_PAGE_SHOW_VERSION_PAGE_TEXT':'查看版本信息', 243 | 'ABOUT_PAGE_SHOW_VERSION_PAGE_POS':((1,-220),(1,-50),(0,200),(0,30)), 244 | 245 | # 主菜单 246 | 247 | 'MAIN_MENU_BACK':'main_back.png', 248 | 249 | 'MAIN_MENU_START_POS':((1,-526),(0.5,-48),(0,526),(0,96)), 250 | 'MAIN_MENU_START_TEXT':'开始游戏', 251 | 'MAIN_MENU_START_FONT':'杨任东竹石体-Semibold', 252 | 'MAIN_MENU_START_FONT_SIZE':44, 253 | 'MAIN_MENU_START_COLOR':(255,255,255,255), 254 | 'MAIN_MENU_START_BACK':'tag_button_v.png', 255 | 'MAIN_MENU_START_PRESSED_BACK':'tag_button_v_pressed.png', 256 | 257 | 'MAIN_MENU_BUTTON_FONT':'杨任东竹石体-Regular', 258 | 'MAIN_MENU_BUTTON_HOVERING_FONT':'杨任东竹石体-Semibold', 259 | 'MAIN_MENU_BUTTON_FONT_SIZE':28, 260 | 'MAIN_MENU_BUTTON_COLOR':(0,0,0,255), 261 | 262 | 'MAIN_MENU_LOAD_POS':((1,-440),(0.4,-48),(0,96),(0,48)), 263 | 'MAIN_MENU_LOAD_TEXT':'载入', 264 | 265 | 'MAIN_MENU_ACHIEVEMENT_POS':((1,-340),(0.37,-48),(0,96),(0,48)), 266 | 'MAIN_MENU_ACHIEVEMENT_TEXT':'成就', 267 | 268 | 'MAIN_MENU_APPENDICE_POS':((1,-260),(0.31,-48),(0,96),(0,48)), 269 | 'MAIN_MENU_APPENDICE_TEXT':'图鉴', 270 | 271 | 'MAIN_MENU_SETTING_POS':((1,-200),(0.25,-48),(0,96),(0,48)), 272 | 'MAIN_MENU_SETTING_TEXT':'设置', 273 | 274 | 'MAIN_MENU_ABOUT_POS':((1,-160),(0.18,-48),(0,96),(0,48)), 275 | 'MAIN_MENU_ABOUT_TEXT':'关于', 276 | 277 | 'MAIN_MENU_QUIT_POS':((1,-140),(0.11,-48),(0,96),(0,48)), 278 | 'MAIN_MENU_QUIT_TEXT':'退出', 279 | 'CONFIRM_QUIT_TEXT':'确认退出吗?', 280 | 281 | # 存档 282 | 283 | 'SAVESBOX_SELECT_ITEM_HEIGHT':30, 284 | 'SAVESBOX_SELECT_ITEM_BLANKING':5, 285 | 286 | # 存档页 287 | 288 | 'SAVEPAGE_POS':((0.5,-236),(0.5,-236),(0,472),(0,472)), 289 | 290 | 'SAVEPAGE_TITLE':'保存游戏', 291 | 'SAVEPAGE_TITLE_POS':((0.5,0),(1,-60),(0,0),(0,0)), 292 | 293 | 'SAVEPAGE_CANCEL_TEXT':'返回', 294 | 'SAVEPAGE_CANCEL_POS':((0.5,-165),(0,20),(0,100),(0,40)), 295 | 296 | 'SAVEPAGE_DEL_TEXT':'删除', 297 | 'SAVEPAGE_DEL_POS':((0.5,-50),(0,20),(0,100),(0,40)), 298 | 299 | 'SAVEPAGE_CONFIRM_TEXT':'保存', 300 | 'SAVEPAGE_CONFIRM_POS':((0.5,65),(0,20),(0,100),(0,40)), 301 | 302 | 'SAVEPAGE_NAME_LABEL_TEXT':'名称:', 303 | 'SAVEPAGE_NAME_LABEL_POS':((0,20),(0,100),(0,0),(0,0)), 304 | 305 | 'SAVEPAGE_NAME_POS':((0,120),(0,80),(1,-140),(0,40)), 306 | 307 | 'SAVEPAGE_SELECT_POS':((0,20),(0,140),(1,-40),(1,-240)), 308 | 309 | 'SAVEPAGE_CONFIRM_SAVE_CONFLICT_TEXT':'覆盖存档吗?', 310 | 'SAVEPAGE_DEL_NOTEXIST_TEXT':'该名称的存档不存在', 311 | 'SAVEPAGE_DEL_CONFIRM_TEXT':'确定删除吗?', 312 | 313 | # 读档页 314 | 315 | 'LOADPAGE_POS':((0.5,-236),(0.5,-256),(0,472),(0,512)), 316 | 317 | 'LOADPAGE_TITLE':'载入存档', 318 | 'LOADPAGE_TITLE_POS':((0.5,0),(1,-60),(0,0),(0,0)), 319 | 320 | 'LOADPAGE_CANCEL_TEXT':'返回', 321 | 'LOADPAGE_CANCEL_POS':((0.5,-165),(0,20),(0,100),(0,40)), 322 | 323 | 'LOADPAGE_DEL_TEXT':'删除', 324 | 'LOADPAGE_DEL_POS':((0.5,-50),(0,20),(0,100),(0,40)), 325 | 326 | 'LOADPAGE_CONFIRM_TEXT':'开始', 327 | 'LOADPAGE_CONFIRM_POS':((0.5,65),(0,20),(0,100),(0,40)), 328 | 329 | 'LOADPAGE_CHECKSUM_LABEL_TEXT':'校验和:', 330 | 'LOADPAGE_CHECKSUM_LABEL_POS':((0,20),(0,85),(0,0),(0,0)), 331 | 332 | 'LOADPAGE_CHECKSUM_POS':((0,120),(0,70),(1,-140),(0,30)), 333 | 334 | 'LOADPAGE_VERSION_POS':((0,20),(0,110),(1,-40),(0,120)), 335 | 336 | 'LOADPAGE_SELECT_POS':((0,20),(0,250),(1,-40),(1,-350)), 337 | 338 | 'LOADPAGE_NOTEXIST_TEXT':'该名称的存档不存在', 339 | 'LOADPAGE_DEL_CONFIRM_TEXT':'确定删除吗?', 340 | 'LOADPAGE_NONE_TEXT':'没有可用的存档', 341 | 'LOADPAGE_VERSION_CONFIRM_TEXT':'存档版本不匹配,要继续吗?', 342 | 343 | # 游戏界面 344 | 345 | 'GAME_HEADER_POS':((0,0),(0.94,0),(1,0),(0.06,1)), 346 | 'GAME_HEADER_BACK':'header.png', 347 | 348 | 'GAME_HEADER_MESSAGES_SWITCH_POS':((0,10),(0.5,-15),(0,30),(0,30)), 349 | 'GAME_HEADER_CHARACTER_SWITCH_POS':((1,-40),(0.5,-15),(0,30),(0,30)), 350 | 351 | 'GAME_HEADER_SWITCH_DOWN_ICON':'down_button.png', 352 | 'GAME_HEADER_SWITCH_UP_ICON':'up_button.png', 353 | 'GAME_HEADER_SWITCH_DISABLED_IMAGE':'up_button_disabled.png', 354 | 355 | 'GAME_HEADER_SPEEDBAR_POS':((0,50),(0,0),(0.3,-50),(1,0)), 356 | # 'GAME_HEADER_SPEEDBAR_BACK':'bar_h.png', 357 | 358 | 'GAME_HEADER_SPEEDBAR_FONT':'杨任东竹石体-Semibold', 359 | 'GAME_HEADER_SPEEDBAR_FONT_SIZE':18, 360 | 'GAME_HEADER_SPEEDBAR_FONT_COLOR':(255,255,255,255), 361 | 'GAME_HEADER_SPEEDBAR_COUNT':6, 362 | 363 | 'GAME_HEADER_SPEEDBAR_BUTTON_BACK':'smallbutton.png', 364 | 'GAME_HEADER_SPEEDBAR_BUTTON_PRESSED_BACK':'smallbutton_pressed.png', 365 | 366 | 'GAME_HEADER_SPEEDBAR_PAUSE_TEXT':'‖', 367 | 'GAME_HEADER_SPEEDBAR_TIME_FORMAT':'%Y.%m.%d %H:%M:%S', 368 | 369 | 'GAME_HEADER_MENU_BUTTON_POS':((1,-130),(0,0),(0,80),(1,0)), 370 | 'GAME_HEADER_MENU_BUTTON_TEXT':'菜单', 371 | 372 | 'GAME_HEADER_SWITCH_PAGE_POS':((0.865,-150),(0,0),(0.135,0),(1,0)), 373 | 374 | 'GAME_HEADER_STATUS_BARS_POS':((0.3,10),(0,0),(0.2,10),(1,0)), 375 | 376 | 'GAME_HEADER_RATING_BAR_POS':((0.5,20),(0,0),(0.335,-160),(1,0)), 377 | 'GAME_HEADER_RATING_BAR_DEFAULT_COLOR':(255,255,255), 378 | 379 | 'GAME_HEADER_STATUS_BAR_COUNT':4, 380 | 381 | 'GAME_HEADER_STATUS_BAR_COLORS':((127,255,127),(127,127,255),(255,127,127),(192,192,127)), 382 | 383 | 'GAME_HEADER_STATUS_BAR_ICONS':('health_icon.png','mood_icon.png','stress_icon.png','ability_icon.png'), 384 | 385 | 'GAME_HEADER_STATUS_SWITCHPAGE_COUNT':4, 386 | 387 | 'GAME_HEADER_SWITCHPAGE_ICONS':('character.png','timetable.png','ability.png','contest.png'), 388 | 'GAME_HEADER_SWITCHPAGE_DISABLED_ICONS':(None,None,None,'contest_disabled.png'), 389 | 'GAME_HEADER_SWITCHPAGE_BUTTON_SELECT_BACK':'switchpage_button_select.png', 390 | 391 | 'GAME_PAGES_POS':((0,0),(0,0),(1,0),(0.94,1)), 392 | 393 | 'GAME_PAGES_CHARACTER_BACK':'game_stage1.png', 394 | 'GAME_PAGES_TIMETABLE_BACK':'game_stage2.png', 395 | 'GAME_PAGES_ABILITY_BACK':'game_stage3.png', 396 | 'GAME_PAGES_CONTEST_BACK':'game_stage_contest.png', 397 | 398 | 'GAME_BOARD_BACK':'frame_back.png', 399 | 'GAME_MESSAGES_BOARD_POS':((0,0),(0,0),(0,320),(0.94,1)), 400 | 'GAME_CHARACTER_BOARD_POS':((1,-320),(0.94,-480),(0,320),(0,480)), 401 | 402 | 'GAME_CHARACTER_BOARD_IMAGE_POS':((0,10),(1,-310),(1,-20),(0,300)), 403 | 'GAME_CHARACTER_BOARD_TITLE_POS':((0.5,0),(1,-335),(0,0),(0,0)), 404 | 'GAME_CHARACTER_BOARD_INFO_POS':((0,10),(0,10),(1,-20),(1,-370)), 405 | 'GAME_CHARACTER_BOARD_BIRTH_FORMAT':'%Y.%m.%d', 406 | 'GAME_CHARACTER_BOARD_INFO_COUNT':3, 407 | 408 | 'GAME_MESSAGE_TIMETABLE_BACK':'timetable_item.png', 409 | 'GAME_MESSAGE_LOG_BACK':'log_item.png', 410 | 'GAME_MESSAGE_STRATEGY_BACK':'strategy_item.png', 411 | 'GAME_MESSAGE_STRATEGY_SELECT_BACK':'strategy_item_selected.png', 412 | 'GAME_MESSAGE_STRATEGY_CURSOR':'strategy_cursor.png', 413 | 414 | 'GAME_MESSAGE_FONT_SIZE':18, 415 | 'GAME_MESSAGE_FONT_NAME':'杨任东竹石体-Regular', 416 | 417 | 'GAME_MESSAGES_BOARD_TIMETABLE_TEXT':'时间表', 418 | 'GAME_MESSAGES_BOARD_TIMETABLE_LABEL_POS':((0.5,0),(1,-20),(0,0),(0,0)), 419 | 'GAME_MESSAGES_BOARD_TIMETABLE_POS':((0,0),(1,-145),(1,0),(0,105)), 420 | 'GAME_MESSAGES_BOARD_TIMETABLE_ITEM_HEIGHT':35, 421 | 'GAME_MESSAGES_BOARD_TIMETABLE_ITEM_COUNT':3, 422 | 'GAME_MESSAGES_BOARD_LOG_TEXT':'日记记录', 423 | 'GAME_MESSAGES_BOARD_LOG_LABEL_POS':((0.5,0),(1,-165),(0,0),(0,0)), 424 | 'GAME_MESSAGES_BOARD_LOG_POS':((0,0),(1,-290),(1,0),(0,105)), 425 | 'GAME_MESSAGES_BOARD_LOG_ITEM_HEIGHT':35, 426 | 'GAME_MESSAGES_BOARD_LOG_ITEM_COUNT':3, 427 | 'GAME_MESSAGES_BOARD_PLAN_TEXT':'计划', 428 | 'GAME_MESSAGES_BOARD_PLAN_LABEL_POS':((0.5,0),(1,-310),(0,0),(0,0)), 429 | 'GAME_MESSAGES_BOARD_PLAN_POS':((0,0),(1,-435),(1,0),(0,105)), 430 | 'GAME_MESSAGES_BOARD_PLAN_ITEM_HEIGHT':35, 431 | 'GAME_MESSAGES_BOARD_PLAN_ITEM_COUNT':3, 432 | 'GAME_MESSAGES_BOARD_STRATEGY_TEXT':'执行策略', 433 | 'GAME_MESSAGES_BOARD_STRATEGY_LABEL_POS':((0.5,0),(1,-455),(0,0),(0,0)), 434 | 'GAME_MESSAGES_BOARD_STRATEGY_POS':((0,0),(0,0),(1,0),(1,-475)), 435 | 'GAME_MESSAGES_BOARD_STRATEGY_ITEM_HEIGHT':35, 436 | 437 | 'GAME_PAGES_CHARACTER_BACK_POS':((0,0),(0,0),(1,0),(1,0)), 438 | 'GAME_PAGES_CHARACTER_FRONT_POS':((0.5,0),(0,0),(0.5,0),(0.5,0)), 439 | 440 | 'GAME_PAGES_TIMETABLE_FRAME_BACK':'frame_back.png', 441 | 'GAME_PAGES_TIMETABLE_FRAME_LABEL_POS':((0.5,0),(1,-30),(0,0),(0,0)), 442 | 'GAME_PAGES_TIMETABLE_FRAME_BOARD_POS':((0,0),(0,0),(1,0),(1,-60)), 443 | 'GAME_PAGES_TIMETABLE_FRAME_LEFT_BUTTON_POS':((0,0),(1,-50),(0,50),(0,50)), 444 | 'GAME_PAGES_TIMETABLE_FRAME_RIGHT_BUTTON_POS':((1,-50),(1,-50),(0,50),(0,50)), 445 | 'GAME_PAGES_TIMETABLE_FRAME_LEFT_BUTTON_IMAGE':'left.png', 446 | 'GAME_PAGES_TIMETABLE_FRAME_RIGHT_BUTTON_IMAGE':'right.png', 447 | 'GAME_PAGES_TIMETABLE_FRAME_PLAN_BUTTON_BACK':'smallbutton.png', 448 | 'GAME_PAGES_TIMETABLE_FRAME_PLAN_BUTTON_PRESSED_BACK':'smallbutton_pressed.png', 449 | 'GAME_PAGES_TIMETABLE_MESSAGES_ITEM_HEIGHT':35, 450 | 'GAME_PAGES_TIMETABLE_MESSAGES_STRATEGY_ITEM_HEIGHT':35, 451 | 'GAME_PAGES_TIMETABLE_PLAN_ADD_ICON':'add.png', 452 | 'GAME_PAGES_TIMETABLE_PLAN_EDIT_ICON':'edit.png', 453 | 'GAME_PAGES_TIMETABLE_PLAN_REMOVE_ICON':'remove.png', 454 | 'GAME_PAGES_TIMETABLE_PLAN_SAVE_ICON':'save.png', 455 | # 'GAME_PAGES_TIMETABLE_PLAN_LOAD_ICON':'load.png', 456 | 'GAME_PAGES_TIMETABLE_PLAN_MOVEUP_ICON':'move_up.png', 457 | 'GAME_PAGES_TIMETABLE_PLAN_MOVEDOWN_ICON':'move_down.png', 458 | 'GAME_PAGES_TIMETABLE_PLAN_SHIFTUP_ICON':'shift_up.png', 459 | 'GAME_PAGES_TIMETABLE_PLAN_SHIFTDOWN_ICON':'shift_down.png', 460 | 461 | 'GAME_SLPLAN_SELECT_ITEM_HEIGHT':30, 462 | 'GAME_SLPLAN_SELECT_ITEM_BLANKING':5, 463 | 464 | 'GAME_SLPLAN_BUTTON_BACK':'smallbutton.png', 465 | 'GAME_SLPLAN_BUTTON_PRESSED_BACK':'smallbutton_pressed.png', 466 | 'GAME_SLPLAN_POS':((0.5,-340),(0.5,-236),(0,680),(0,472)), 467 | 'GAME_SLPLAN_TITLE_POS':((0.5,0),(1,-25),(0,0),(0,0)), 468 | 'GAME_SLPLAN_TITLE':'管理计划', 469 | 'GAME_SLPLAN_INFO_BACK':'frame_back.png', 470 | 'GAME_SLPLAN_INFO_POS':((0,15),(0,20),(0.5,-20),(1,-70)), 471 | 'GAME_SLPLAN_SELECT_POS':((0.5,5),(0,70),(0.5,-20),(1,-120)), 472 | 'GAME_SLPLAN_BUTTONS_POS':((0.75,-105),(0,20),(0,200),(0,50)), 473 | 'GAME_SLPLAN_COPY_ICON':'copy.png', 474 | 'GAME_SLPLAN_REMOVE_ICON':'remove.png', 475 | 'GAME_SLPLAN_USE_ICON':'flag.png', 476 | 'GAME_SLPLAN_RENAME_ICON':'edit.png', 477 | 'GAME_SLPLAN_CONFIRM_POS':((1,-50),(0,0),(0,50),(0,50)), 478 | 'GAME_SLPLAN_CONFIRM_IMAGE':'goback.png', 479 | 480 | 'GAME_PAGES_TIMETABLE_TIMETABLE_POS':((0.5,-480),(0.5,0),(0,320),(0.5,0)), 481 | 'GAME_PAGES_TIMETABLE_TIMETABLE_TEXT':'时间表', 482 | 483 | 'GAME_PAGES_TIMETABLE_LOG_POS':((0.5,-480),(0,0),(0,320),(0.5,0)), 484 | 'GAME_PAGES_TIMETABLE_LOG_TEXT':'日记记录', 485 | 486 | 'GAME_PAGES_TIMETABLE_PLAN_POS':((0.5,-160),(0,0),(0,320),(1,0)), 487 | 'GAME_PAGES_TIMETABLE_PLAN_TEXT':'计划', 488 | 'GAME_PAGES_TIMETABLE_PLAN_BOARD_POS':((0,0),(0,80),(1,0),(1,-80)), 489 | 'GAME_PAGES_TIMETABLE_PLAN_BUTTONS_POS':((0,10),(0,20),(1,-10),(0,50)), 490 | 491 | 'GAME_PAGES_TIMETABLE_STRATEGY_POS':((0.5,160),(0,0),(0,320),(1,0)), 492 | 'GAME_PAGES_TIMETABLE_STRATEGY_TEXT':'执行策略', 493 | 494 | 'GAME_STRATEGY_FONT_NAME':'杨任东竹石体-Regular', 495 | 'GAME_STRATEGY_FONT_SIZE':18, 496 | 'GAME_STRATEGY_FONT_COLOR':(131,84,7,255), 497 | 498 | # 游戏菜单 499 | 500 | 'GAME_MENU_POS':((0.5,-160),(0.5,-180),(0,320),(0,360)), 501 | 502 | 'GAME_MENU_TITLE_POS':((0.5,0),(1,-60),(0,0),(0,0)), 503 | 'GAME_MENU_TITLE':'游戏菜单', 504 | 505 | 'GAME_MENU_BUTTONS_POS':((0.5,-90),(0,20),(0,180),(1,-120)), 506 | 507 | 'GAME_MENU_BACK_TEXT':'返回游戏', 508 | 'GAME_MENU_SAVE_TEXT':'保存', 509 | 'GAME_MENU_ACHIEVEMENT_TEXT':'成就', 510 | 'GAME_MENU_APPENDICE_TEXT':'图鉴', 511 | 'GAME_MENU_SETTING_TEXT':'设置', 512 | 'GAME_MENU_QUIT_TEXT':'返回主菜单', 513 | 514 | 'GAME_CONFIRM_QUIT_TEXT':'确认返回吗?' 515 | } 516 | } -------------------------------------------------------------------------------- /oiasg/define/achievement.py: -------------------------------------------------------------------------------- 1 | { 2 | 'ACHIEVEMENT_PAGES':{ 3 | 0:{ 4 | 'name':'页面一', 5 | 'background':'main_back.png', 6 | 'pos':((0,0),(0,0),(1,0),(1,0)) 7 | }, 8 | 1:{ 9 | 'name':'页面二', 10 | 'background':'frame_back.png', 11 | 'pos':((0,0),(0,0),(1,0),(1,0)) 12 | }, 13 | 2:{ 14 | 'name':'页面三', 15 | 'background':'default.png', 16 | 'pos':((0,0),(0,0),(1,0),(1,0)) 17 | } 18 | }, 19 | 'ACHIEVEMENT_ITEMS':{ 20 | 0:{ 21 | 'name':'wxh天下第一', 22 | 'icon':'default.png', 23 | 'text':'wxh天下第一的描述', 24 | 'cond':'wxh天下第一的条件描述', 25 | 'page':0, 26 | 'pos':((0.4,0),(0.4,0),(0.06,0),(0.06,0)) 27 | }, 28 | 1:{ 29 | 'name':'wxh当然天下第一', 30 | 'icon':'default.png', 31 | 'text':'wxh当然天下第一的描述', 32 | 'cond':'wxh当然天下第一的条件描述', 33 | # 定义成就图标的坐标 34 | 'page':0, 35 | 'pos':((0.6,0),(0.5,0),(0.06,0),(0.06,0)) 36 | }, 37 | 2:{ 38 | 'name':'wxh乃天下第一', 39 | 'icon':'default.png', 40 | 'text':'wxh乃天下第一的描述', 41 | 'cond':'wxh乃天下第一的条件描述', 42 | # 定义成就图标的坐标 43 | 'page':1, 44 | 'pos':((0.4,0),(0.4,0),(0.06,0),(0.06,0)) 45 | }, 46 | 3:{ 47 | 'name':'wxh是为天下第一', 48 | 'icon':'default.png', 49 | 'text':'wxh是为天下第一的描述', 50 | 'cond':'wxh是为天下第一的条件描述', 51 | # 定义成就图标的坐标 52 | 'page':1, 53 | 'pos':((0.4,0),(0.4,0),(0.06,0),(0.06,0)) 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /oiasg/define/appendice.py: -------------------------------------------------------------------------------- 1 | { 2 | 'APPENDICE_ITEMS':{ 3 | 0:{ 4 | 'name':'CommonAnts', 5 | 'icon':'commonants_icon.png', 6 | 'image':'orz.gif', 7 | 'text':'''P{wrap 'char'} 8 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡{font_name '楷体'}蒟蒻{font_name '杨任东竹石体-Semibold'}CommonAnts{font_size 12}, 9 | 10 | 11 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 12 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 13 | 14 | 15 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 16 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 17 | 18 | 19 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 20 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 21 | 22 | 23 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 24 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 25 | 26 | 27 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 28 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 29 | 30 | 31 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 32 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 33 | 34 | 35 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 36 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 37 | 38 | 39 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 40 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 41 | 42 | 43 | {font_name 'Times New Roman'}{font_size 28}Hello - - - - -{font_size 12}, 44 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 45 | 46 | 47 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 48 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 49 | 50 | 51 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 52 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 53 | 54 | 55 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 56 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 57 | 58 | ''' 59 | }, 60 | 1:{ 61 | 'name':'CommonAnts2', 62 | 'icon':'commonants_image.png', 63 | 'image':'orz.gif', 64 | 'text':''' 65 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 66 | 67 | 68 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 69 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 70 | 71 | ''' 72 | }, 73 | 2:{ 74 | 'name':'CommonAnts', 75 | 'icon':'commonants_icon.png', 76 | 'image':'commonants_image.png', 77 | 'text':''' 78 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 79 | 80 | 81 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 82 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 83 | 84 | ''' 85 | }, 86 | 3:{ 87 | 'name':'CommonAnts2', 88 | 'icon':'commonants_image.png', 89 | 'image':'commonants_icon.png', 90 | 'text':''' 91 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 92 | 93 | 94 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 95 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 96 | 97 | ''' 98 | }, 99 | 4:{ 100 | 'name':'CommonAnts', 101 | 'icon':'commonants_icon.png', 102 | 'image':'commonants_image.png', 103 | 'text':''' 104 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 105 | 106 | 107 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 108 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 109 | 110 | ''' 111 | }, 112 | 5:{ 113 | 'name':'CommonAnts5-----', 114 | 'icon':'commonants_image.png', 115 | 'image':'commonants_icon.png', 116 | 'text':''' 117 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 118 | 119 | 120 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 121 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 122 | 123 | ''' 124 | }, 125 | 6:{ 126 | 'name':'CommonAnts', 127 | 'icon':'commonants_icon.png', 128 | 'image':'commonants_image.png', 129 | 'text':''' 130 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 131 | 132 | 133 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 134 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 135 | 136 | ''' 137 | }, 138 | 7:{ 139 | 'name':'CommonAnts2', 140 | 'icon':'commonants_image.png', 141 | 'image':'commonants_icon.png', 142 | 'text':''' 143 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 144 | 145 | 146 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 147 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 148 | 149 | ''' 150 | }, 151 | 8:{ 152 | 'name':'CommonAnts', 153 | 'icon':'commonants_icon.png', 154 | 'image':'commonants_image.png', 155 | 'text':''' 156 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 157 | 158 | 159 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 160 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 161 | 162 | ''' 163 | }, 164 | 9:{ 165 | 'name':'CommonAnts2', 166 | 'icon':'commonants_image.png', 167 | 'image':'commonants_icon.png', 168 | 'text':''' 169 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 170 | 171 | 172 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 173 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 174 | 175 | ''' 176 | }, 177 | 10:{ 178 | 'name':'CommonAnts', 179 | 'icon':'commonants_icon.png', 180 | 'image':'commonants_image.png', 181 | 'text':''' 182 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 183 | 184 | 185 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 186 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 187 | 188 | ''' 189 | }, 190 | 11:{ 191 | 'name':'CommonAnts2', 192 | 'icon':'commonants_image.png', 193 | 'image':'commonants_icon.png', 194 | 'text':''' 195 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 196 | 197 | 198 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 199 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 200 | 201 | ''' 202 | }, 203 | 12:{ 204 | 'name':'CommonAnts', 205 | 'icon':'commonants_icon.png', 206 | 'image':'commonants_image.png', 207 | 'text':''' 208 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts{font_size 12}, 209 | 210 | 211 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 212 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 213 | 214 | ''' 215 | }, 216 | 13:{ 217 | 'name':'CommonAnts2', 218 | 'icon':'commonants_image.png', 219 | 'image':'commonants_icon.png', 220 | 'text':''' 221 | {font_name '杨任东竹石体-Semibold'}{font_size 28}辣鸡蒟蒻CommonAnts2{font_size 12}, 222 | 223 | 224 | {font_name 'Times New Roman'}{font_size 28}Hello{font_size 12}, 225 | {color (255, 0, 0, 255)}world{color (0, 0, 0, 255)}! 226 | 227 | ''' 228 | } 229 | } 230 | } -------------------------------------------------------------------------------- /oiasg/define/commons/events.py: -------------------------------------------------------------------------------- 1 | { 2 | 'EVENTS':{ 3 | 0:{ 4 | 'trigger':'True', 5 | 'effect':''' 6 | pages_character_back = 'default.png' 7 | 8 | pages_character_front = 'commonants_image.png' 9 | 10 | messages[cnt] = MessageItem(name = '测试信息TMessage %s' % cnt, text = '测试文本\\n啦啦啦啦啦啦', image = 'orz.gif') 11 | 12 | log_messages.append(cnt) 13 | 14 | timetable_messages.append(cnt) 15 | 16 | strategy_plan = [key for key in strategies.keys()] 17 | 18 | select_strategies = list(strategies.keys()) 19 | 20 | cnt+=1 21 | 22 | # ui.Alert_Notitle(str(cnt)+str(current_strategy)).exe() 23 | ''', 24 | 'privilege':0 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /oiasg/define/commons/game_defines.py: -------------------------------------------------------------------------------- 1 | { 2 | 'GAME_TIME_INTERVAL':[0,2,1,0.5,0.2,0.05], 3 | 'GAME_DEFINE':{ 4 | # 游戏的预定义文件 -- 定义一局游戏的初始数据 5 | 'general':{ 6 | # 游戏开始时间 7 | 'start_time':datetime.datetime(2016,1,1,0), 8 | # 游戏结束时间 9 | 'end_time':datetime.datetime(2018,1,1,0), 10 | # 正常情况下的时间变化量(比赛等特殊情况除外) 11 | 'time_delta':datetime.timedelta(hours = 1), 12 | # 角色 13 | 'CHARACTER':{ 14 | 'name':'CommonAnts', 15 | 'image':'commonants_icon.png', 16 | 'data':{ 17 | 'province':'陕西省', 18 | 'school':'某少女附中', 19 | 'birth':datetime.datetime(2001,7,11), 20 | } 21 | } 22 | } 23 | }, 24 | 'GENERAL_GAME_DEFINE':{ 25 | # 所有游戏通用的预定义文件 26 | 27 | # 基本数据集 28 | 'events':{}, 29 | 'strategies':{}, 30 | 'abilities':{}, 31 | 'abilitypages':{}, 32 | 'messages':{}, 33 | 'contests':{}, 34 | 'strategy_plans':{}, 35 | 36 | # 子集 37 | 'timetable_messages':[], 38 | 'log_messages':[], 39 | 40 | 'strategy_plan':[], 41 | 'strategy_plan_it':0, 42 | 'current_strategy':None, 43 | 44 | 'select_strategies':[], 45 | 46 | 'pages_character_back':None, 47 | 'pages_character_front':None, 48 | } 49 | } -------------------------------------------------------------------------------- /oiasg/define/commons/game_init_script.py: -------------------------------------------------------------------------------- 1 | { 2 | 'GAME_INIT_SCRIPT': 3 | # 所有游戏的初始化脚本 4 | ''' 5 | strategy_plans['current'] = strategy_plan 6 | game_version = data.version 7 | time = start_time 8 | cnt = 0 9 | ''' 10 | } -------------------------------------------------------------------------------- /oiasg/define/commons/play_round_script.py: -------------------------------------------------------------------------------- 1 | { 2 | 'PLAY_ROUND_SCRIPT': 3 | ''' 4 | time = start_time + (((time - start_time) // time_delta) + 1) * time_delta 5 | dispatch_game_event('on_update_speed_time') 6 | 7 | event_queue = [] 8 | 9 | for key, value in events.items(): 10 | if value.check(game): 11 | event_queue.append(value) 12 | event_queue.sort(key = lambda x:x.privilege) 13 | 14 | if event_queue: 15 | event = event_queue[-1] 16 | event_queue.pop() 17 | event.exe(game) 18 | ''' 19 | } -------------------------------------------------------------------------------- /oiasg/define/commons/strategies.py: -------------------------------------------------------------------------------- 1 | { 2 | 'STRATEGIES':{ 3 | 0:{ 4 | 'event':0, 5 | 'name':'测试策略', 6 | 'icon':None 7 | }, 8 | 1:{ 9 | 'event':0, 10 | 'name':'测试策略1', 11 | 'icon':'timetable.png' 12 | }, 13 | 2:{ 14 | 'event':0, 15 | 'name':'测试策略2', 16 | 'icon':'timetable.png' 17 | }, 18 | 3:{ 19 | 'event':0, 20 | 'name':'测试策略3', 21 | 'icon':'timetable.png' 22 | }, 23 | } 24 | } -------------------------------------------------------------------------------- /oiasg/define/game_defines.py: -------------------------------------------------------------------------------- 1 | { 2 | 'GAME_TIME_INTERVAL':[0,2,1,0.5,0.2,0.05], 3 | 'GAME_DEFINE':{ 4 | # 游戏的预定义文件 -- 定义一局游戏的初始数据 5 | 'general':{ 6 | # 游戏开始时间 7 | 'start_time':datetime.datetime(2016,1,1,0), 8 | # 游戏结束时间 9 | 'end_time':datetime.datetime(2018,1,1,0), 10 | # 正常情况下的时间变化量(比赛等特殊情况除外) 11 | 'time_delta':datetime.timedelta(hours = 1), 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /oiasg/define/scenarios.py: -------------------------------------------------------------------------------- 1 | { 2 | 'SCENARIOS':{ 3 | 'random':{ 4 | 'name':'RANDOM', 5 | 'icon':'default.png', 6 | 'image':'default.png', 7 | 'text':'N随机角色', 8 | # 游戏预定义文件 9 | 'game_define':'general', 10 | }, 11 | 'wxhakioi2019':{ 12 | 'name':'WXH AK IOI 2019', 13 | 'icon':'orz.gif', 14 | 'image':'default.png', 15 | 'text':'N大佬wxh\n\nAKIOI2019\n\nDALAODALAODALAODALAODALAODALAODALAODALAO DALAODALAODALAODALAODALAODALAODALAODALAODALAODALAO', 16 | 'game_define':'general', 17 | }, 18 | 'lcaggctsc2018':{ 19 | 'name':'CommonAnts GG CTSC 2018', 20 | 'icon':'commonants_icon.png', 21 | 'image':'commonants_image.png', 22 | 'text':'N蒟蒻CommonAnts\nGG CTSC 2018', 23 | 'game_define':'general', 24 | }, 25 | 'random_1':{ 26 | 'name':'RANDOM', 27 | 'icon':'default.png', 28 | 'image':'default.png', 29 | 'text':'N随机角色', 30 | 'game_define':'general', 31 | }, 32 | 'wxhakioi2019_1':{ 33 | 'name':'WXH AK IOI 2019', 34 | 'icon':'orz.gif', 35 | 'image':'default.png', 36 | 'text':'N大佬wxh\nAKIOI2019', 37 | 'game_define':'general', 38 | }, 39 | 'lcaggctsc2018_1':{ 40 | 'name':'CommonAnts GG CTSC 2018', 41 | 'icon':'commonants_icon.png', 42 | 'image':'commonants_image.png', 43 | 'text':'N蒟蒻CommonAnts\nGG CTSC 2018', 44 | 'game_define':'general', 45 | }, 46 | 'random_2':{ 47 | 'name':'RANDOM', 48 | 'icon':'default.png', 49 | 'image':'default.png', 50 | 'text':'N随机角色', 51 | 'game_define':'general', 52 | }, 53 | 'wxhakioi2019_2':{ 54 | 'name':'WXH AK IOI 2019', 55 | 'icon':'orz.gif', 56 | 'image':'default.png', 57 | 'text':'N大佬wxh\nAKIOI2019', 58 | 'game_define':'general', 59 | }, 60 | # 'lcaggctsc2018_2':{ 61 | # 'name':'CommonAnts GG CTSC 2018', 62 | # 'icon':'commonants_icon.png', 63 | # 'image':'commonants_image.png', 64 | # 'text':'N蒟蒻CommonAnts\nGG CTSC 2018', 65 | # 'game_define':'general', 66 | # }, 67 | # 'random_3':{ 68 | # 'name':'RANDOM', 69 | # 'icon':'default.png', 70 | # 'image':'default.png', 71 | # 'text':'N随机角色', 72 | # 'game_define':'general', 73 | # }, 74 | # 'wxhakioi2019_3':{ 75 | # 'name':'WXH AK IOI 2019', 76 | # 'icon':'orz.gif', 77 | # 'image':'default.png', 78 | # 'text':'N大佬wxh\nAKIOI2019', 79 | # 'game_define':'general', 80 | # }, 81 | # 'lcaggctsc2018_3':{ 82 | # 'name':'CommonAnts GG CTSC 2018', 83 | # 'icon':'commonants_icon.png', 84 | # 'image':'commonants_image.png', 85 | # 'text':'N蒟蒻CommonAnts\nGG CTSC 2018', 86 | # 'game_define':'general', 87 | # } 88 | } 89 | } -------------------------------------------------------------------------------- /oiasg/dlcs/test_dlc/data/__user_settings.py: -------------------------------------------------------------------------------- 1 | {'FULLSCREEN': False, 'VOLUME_MUSIC': 1, 'VOLUME_EFFECT': 1, 'VOLUME_GAME': 1} -------------------------------------------------------------------------------- /oiasg/dlcs/test_dlc/define/__default.py: -------------------------------------------------------------------------------- 1 | { 2 | 'PACKAGE_NAME':'Test DLC 01' 3 | } -------------------------------------------------------------------------------- /oiasg/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/icon.ico -------------------------------------------------------------------------------- /oiasg/lib/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ui','uidata','uiresource','controls','data','resource','game','gameobjects'] -------------------------------------------------------------------------------- /oiasg/lib/data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | # 全局数据文件模块 5 | 6 | import os, hashlib, pickle, datetime 7 | 8 | def _md5_checksum(obj): 9 | md5_gen = hashlib.md5() 10 | md5_gen.update(pickle.dumps(obj)) 11 | return md5_gen.hexdigest() 12 | 13 | class DataFileIO(object): 14 | # 数据交互接口 15 | @staticmethod 16 | def set_file(s, w): 17 | # 写文件 18 | with open(s, "w", encoding = 'utf-8') as f: 19 | f.write(str(w)) 20 | @staticmethod 21 | def get_file(s): 22 | # 读文件 23 | r = '' 24 | with open(s, "r", encoding = 'utf-8') as f: 25 | r = f.read() 26 | return eval(r) 27 | 28 | class FileSystemIO(object): 29 | @staticmethod 30 | def _get_py_paths(path): 31 | objs = [] 32 | files = os.listdir(path) 33 | for file in files: 34 | abs_path = os.path.join(path, file) 35 | if os.path.isfile(abs_path) and os.path.splitext(file)[1].lower() == '.py': 36 | objs.append(abs_path) 37 | elif os.path.isdir(abs_path): 38 | objs += FileSystemIO._get_py_paths(abs_path) 39 | return objs 40 | @staticmethod 41 | def get_py_paths(path): 42 | # 取得 path 下所有 '.py' 文件的绝对路径 43 | objs = FileSystemIO._get_py_paths(path) 44 | objs.sort() 45 | return objs 46 | @staticmethod 47 | def get_subdirs(path): 48 | # 取得 path 所有子目录的绝对路径 49 | objs = [] 50 | files = os.listdir(path) 51 | for file in files: 52 | abs_path = os.path.join(path, file) 53 | if os.path.isdir(abs_path): 54 | objs.append(abs_path) 55 | return objs 56 | # 抽象数据系统 57 | class DataSet(object): 58 | # 读写数据文件 59 | def __init__(self, path, readonly = False): 60 | self.readonly = readonly 61 | self.PATH = path 62 | self.load() 63 | def save(self): 64 | # [(file,data)] 65 | if self.readonly: 66 | return False 67 | for file in self.data: 68 | DataFileIO.set_file(file[0],file[1]) 69 | return True 70 | def load(self): 71 | files = FileSystemIO.get_py_paths(self.PATH) 72 | self.data = [] 73 | self._data_value = [] 74 | for file in files: 75 | file_data = DataFileIO.get_file(file) 76 | self.data.append((file,file_data)) 77 | self._data_value.append(file_data) 78 | def get(self,key_seq,default = None): 79 | for i in self.data: 80 | d = i[1] 81 | got = True 82 | for j in key_seq: 83 | if j in d: 84 | d = d[j] 85 | else: 86 | got = False 87 | break 88 | if got: 89 | return d 90 | return default 91 | def set(self,key_seq, value): 92 | if self.readonly: 93 | return False 94 | for i in self.data: 95 | d = i[1] 96 | got = True 97 | for j in key_seq: 98 | if j in d: 99 | d = d[j] 100 | else: 101 | got = False 102 | break 103 | if got: 104 | d = i[1] 105 | for j in key_seq[:-1]: 106 | d = d[j] 107 | d[key_seq[-1]] = value 108 | return True 109 | return False 110 | def checksum(self): 111 | return _md5_checksum(self._data_value) 112 | 113 | class GameVersion(object): 114 | def __init__(self, data = None): 115 | if data is None: 116 | self.checksum = '' 117 | self.name = '' 118 | else: 119 | dlc_versions = [i.version for i in data.dlcs] 120 | 121 | dlc_md5s = [i.checksum for i in dlc_versions] 122 | dlc_md5s.append(data._self_md5_checksum()) 123 | self.checksum = _md5_checksum(dlc_md5s) 124 | 125 | dlc_names = [i.name for i in dlc_versions] 126 | dlc_names.append(data._package_name()) 127 | self.name = dlc_names 128 | def __eq__(self, x): 129 | if isinstance(x, GameVersion): 130 | return self.checksum == x.checksum 131 | else: 132 | return False 133 | def _name_to_str(self, name, depth): 134 | __SEPARATE = ' ' 135 | if isinstance(name, list): 136 | res = __SEPARATE*depth + name[1] + '\n' 137 | for i in name[0]: 138 | res += self._name_to_str(i, depth+1) 139 | return res 140 | else: 141 | return __SEPARATE*depth + name + '\n' 142 | def name_to_str(self): 143 | return self._name_to_str(self.name, 0)+'\n' 144 | def checksum_to_str(self): 145 | return self.checksum[:16] 146 | # 数据管理器 147 | # 单类 148 | class Data(object): 149 | def __init__(self, game_path): 150 | self._checksum = None 151 | self.PATH = game_path 152 | self.define = DataSet(os.path.join(self.PATH,'define'), readonly = True) 153 | self.data = DataSet(os.path.join(self.PATH,'data'), readonly = False) 154 | self.dlcs = self._get_dlcs() 155 | self._version = None 156 | def _self_md5_checksum(self): 157 | return self.define.checksum() 158 | def _package_name(self): 159 | return self.define.get(['PACKAGE_NAME'],'') 160 | def save(self): 161 | self.data.save() 162 | for i in self.dlcs: 163 | i.save() 164 | def _get_dlcs(self): 165 | dlcs = [] 166 | dlcpath = os.path.join(self.PATH,'dlcs') 167 | if os.path.isdir(dlcpath): 168 | dlc_paths = FileSystemIO.get_subdirs(dlcpath) 169 | dlcs = [Data(dlc_path) for dlc_path in dlc_paths] 170 | return dlcs 171 | def get(self, key_seq, default = None): 172 | res = None 173 | for i in range(len(self.dlcs)-1,-1,-1): 174 | if res is None: 175 | res = self.dlcs[i].get(key_seq) 176 | if res is None: 177 | res = self.data.get(key_seq) 178 | if res is None: 179 | res = self.define.get(key_seq) 180 | if res is None: 181 | res = default 182 | return res 183 | def get_all(self, key_seq): 184 | res = [] 185 | for i in range(len(self.dlcs)-1,-1,-1): 186 | t = self.dlcs[i].get(key_seq) 187 | if t is not None: 188 | res += t 189 | t = self.data.get(key_seq) 190 | if t is not None: 191 | res.append(t) 192 | t = self.define.get(key_seq) 193 | if t is not None: 194 | res.append(t) 195 | return res 196 | def get_all_list(self, key_seq): 197 | t = self.get_all(key_seq) 198 | t.reverse() 199 | res = [] 200 | for i in t: 201 | res += i 202 | return res 203 | def get_all_dict(self, key_seq): 204 | t = self.get_all(key_seq) 205 | t.reverse() 206 | res = {} 207 | for i in t: 208 | res.update(i) 209 | return res 210 | def set(self, key_seq, value): 211 | res = False 212 | for i in range(len(self.dlcs)-1,-1,-1): 213 | if not res: 214 | res = self.dlcs[i].set(key_seq, value) 215 | if not res: 216 | res = self.data.set(key_seq, value) 217 | return res 218 | def get_subdirs(self, path): 219 | # 取得所有DLC的path子目录(如果存在) 220 | res = [] 221 | self_path = os.path.join(self.PATH, path) 222 | if os.path.isdir(self_path): 223 | res.append(self_path) 224 | for i in self.dlcs: 225 | res += i.get_subdirs(path) 226 | return res 227 | @property 228 | def version(self): 229 | if self._version is not None: 230 | return self._version 231 | self._version = GameVersion(self) 232 | return self._version 233 | 234 | class DataSystem(object): 235 | def init(self, game_path): 236 | self.data = Data(game_path) 237 | @property 238 | def version(self): 239 | return self.data.version 240 | def save(self): 241 | self.data.save() 242 | def get(self, key_seq, default = None): 243 | return self.data.get(key_seq, default) 244 | def get_all(self, key_seq): 245 | return self.data.get_all(self, key_seq) 246 | def get_all_list(self, key_seq): 247 | return self.data.get_all_list(key_seq) 248 | def get_all_dict(self, key_seq): 249 | return self.data.get_all_dict(key_seq) 250 | def set(self, key_seq, value): 251 | return self.data.set(key_seq, value) 252 | def get_subdirs(self, path): 253 | return self.data.get_subdirs(path) 254 | 255 | class SaveFileIO(object): 256 | @staticmethod 257 | def set_file(file, data): 258 | with open(file, 'wb') as f: 259 | pickle.dump(data, f) 260 | @staticmethod 261 | def get_file(file): 262 | with open(file, 'rb') as f: 263 | return pickle.load(f) 264 | return None 265 | @staticmethod 266 | def remove_file(file): 267 | try: 268 | os.remove(file) 269 | finally: 270 | pass 271 | 272 | _SAVE_EXT = '.oiasgsav' 273 | # 存档管理器 274 | # 单类 275 | class GameSaveManager(object): 276 | def init(self, game_path): 277 | self.PATH = game_path 278 | self.savepath = os.path.join(game_path, 'saves') 279 | if not os.path.isdir(self.savepath): 280 | os.makedirs(self.savepath) 281 | def get_save_abspath(self, savename): 282 | return os.path.join(self.savepath,savename + _SAVE_EXT) 283 | def get_save_names(self): 284 | # 得到所有存档的名称 285 | objs = [] 286 | files = os.listdir(self.savepath) 287 | for file in files: 288 | ext = os.path.splitext(file) 289 | if ext[1].lower() == _SAVE_EXT: 290 | objs.append(ext[0]) 291 | return objs 292 | def trans_name(self,name): 293 | # 过滤存档名的关键字符 294 | return name.translate(str.maketrans("""|\?*<":>+[]/'""",' '*13)) 295 | def test_save_exists(self,save): 296 | # 指定名称的存档是否存在 297 | return os.path.isfile(self.get_save_abspath(save)) 298 | def get_available_save_name(self): 299 | # 获得一个合法的未使用的存档名 300 | i = 0 301 | gname = lambda i:('save%s' % i) 302 | while self.test_save_exists(gname(i)): 303 | i += 1 304 | return gname(i) 305 | def save(self, name, gamedata): 306 | SaveFileIO.set_file(self.get_save_abspath(name), gamedata) 307 | def load(self, name): 308 | return SaveFileIO.get_file(self.get_save_abspath(name)) 309 | def remove(self, name): 310 | SaveFileIO.remove_file(self.get_save_abspath(name)) 311 | saves = GameSaveManager() 312 | data = DataSystem() -------------------------------------------------------------------------------- /oiasg/lib/game.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import datetime 5 | import pyglet 6 | 7 | from .resource import resource 8 | from .gameobjects import * 9 | from .uidata import * 10 | from . import ui 11 | 12 | def build_from_data(cls, data): 13 | res = cls() 14 | res.__dict__.update(data) 15 | return res 16 | 17 | # 一局游戏的抽象模型 18 | # UI 与此模型分离,此模型通过调用UI的接口交互 19 | class GamePlay(pyglet.event.EventDispatcher): 20 | # gamedata:游戏数据 21 | def __init__(self, gamedata = None, load_from_save = False): 22 | game = self 23 | self.game = self 24 | self.data = data 25 | self.resource = resource 26 | self.ui = ui.ui 27 | self._load_from_save = load_from_save 28 | self.gamedata = gamedata if gamedata is not None else {} 29 | self.ui_data = GameUIDataManager(self) 30 | self.exe = lambda x:exec(x,self.__dict__,self.gamedata) 31 | self.val = lambda x:eval(x,self.__dict__,self.gamedata) 32 | # 初始化游戏数据 33 | self.dispatch_game_event = self.dispatch_event 34 | 35 | self.Event = Event 36 | self.Strategy = Strategy 37 | self.Ability = Ability 38 | self.BasicAbility = BasicAbility 39 | self.KnowledgeAbility = KnowledgeAbility 40 | self.AbilityPage = AbilityPage 41 | self.MessageItem = MessageItem 42 | self.SolVertice = SolVertice 43 | self.SolGraph = SolGraph 44 | self.Problem = Problem 45 | self.Contest = Contest 46 | self.StrategyPlan = StrategyPlan 47 | def _init_system_data(self): 48 | self.speed = 0 49 | def _init_game_data(self): 50 | self.exe(self.data.get(['GAME_INIT_SCRIPT'],'')) 51 | def _load_define(self): 52 | # 初始化基本数据 53 | self.gamedata.update(self.data.get_all_dict(['GENERAL_GAME_DEFINE'])) 54 | # 初始化角色(注意这个不是从全局加载) 55 | self.gamedata['character'] = build_from_data(Character, self.gamedata.get('CHARACTER',{})) 56 | # 初始化事件 57 | events = self.data.get_all_dict(['EVENTS']) 58 | self.gamedata['events'].update({key:build_from_data(Event, val) for key, val in events.items()}) 59 | # 初始化策略 60 | strategies = self.data.get_all_dict(['STRATEGIES']) 61 | self.gamedata['strategies'].update({key:build_from_data(Strategy, val) for key, val in strategies.items()}) 62 | def _init_data(self): 63 | if not self._load_from_save: 64 | # 加载游戏全局常量数据(如事件、比赛、TAG等) 65 | self._load_define() 66 | # 初始化基本数据 67 | self._init_game_data() 68 | # 初始化游戏系统 69 | self._init_system_data() 70 | def _set_speed(self,speed): 71 | self._speed = speed 72 | # 设置游戏速度 73 | pyglet.clock.unschedule(self.play_round) 74 | if speed > 0: 75 | pyglet.clock.schedule_interval(self.play_round, self.data.get(['GAME_TIME_INTERVAL'])[speed]) 76 | self.dispatch_event('on_update_speed_time') 77 | speed = property(lambda self:self._speed,_set_speed) 78 | def pause(self): 79 | self.speed = 0 80 | def _set_current_strategy(self, value): 81 | self.gamedata['current_strategy'] = value 82 | self.dispatch_event('on_update_message') 83 | current_strategy = property(lambda self:self.gamedata['current_strategy'],_set_current_strategy) 84 | def play_round(self, dt): 85 | self.exe(self.data.get(['PLAY_ROUND_SCRIPT'],'')) 86 | self.dispatch_event('on_update') 87 | def _play(self): 88 | self._init_data() 89 | self.dispatch_event('on_update') 90 | def _end(self): 91 | pyglet.clock.unschedule(self.play_round) 92 | self.__dict__.clear() 93 | GamePlay.register_event_type('on_update') 94 | GamePlay.register_event_type('on_update_speed_time') 95 | GamePlay.register_event_type('on_update_message') 96 | GamePlay.register_event_type('on_update_pages_character') 97 | -------------------------------------------------------------------------------- /oiasg/lib/gameobjects.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import datetime 5 | 6 | _DEFAULT_TIME = datetime.datetime(2018,1,1) 7 | _DEFAULT_TIMEDELTA = datetime.timedelta(0) 8 | class Event(object): 9 | def __init__(self, trigger = 'False', effect = '', privilege = 0): 10 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 11 | def check(self, game): 12 | return bool(game.val(self.trigger)) 13 | def exe(self, game): 14 | game.exe(self.effect) 15 | 16 | class Character(object): 17 | def __init__(self, name = '', image = None, data = None): 18 | if data is None: 19 | data = {} 20 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 21 | 22 | class Strategy(object): 23 | def __init__(self, event = None, name = '', icon = None): 24 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 25 | class StrategyPlan(object): 26 | def __init__(self, plan = None, name = ''): 27 | if plan is None: 28 | plan = [] 29 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 30 | 31 | class Ability(object): 32 | name = '' 33 | val = 0 34 | class BasicAbility(Ability): 35 | def __init__(self, page = None, name = '', color = (0,0,0)): 36 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 37 | class KnowledgeAbility(Ability): 38 | visible = False 39 | privilege = 0 40 | def __init__(self, page = None, name = '', text = '', icon = None, image = None, parent = None, difficulty = 0): 41 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 42 | 43 | class AbilityPage(object): 44 | def __init__(self, name = '', icon = None, image = None): 45 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 46 | 47 | class MessageItem(object): 48 | def __init__(self, name = '', time = _DEFAULT_TIME, timeformat = '', text = '', image = None, font_name = None, font_color = (0,0,0,255), pos = None): 49 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 50 | 51 | class SolVertice(object): 52 | visible = False 53 | rate = 0 54 | error = 0 55 | def __init__(self, ability = None, parent = None): 56 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 57 | class SolGraph(object): 58 | def __init__(self, vertices = None): 59 | if vertices is None: 60 | vertices = [] 61 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 62 | class Problem(object): 63 | idea = None 64 | code = None 65 | def __init__(self, idea = None, code = None): 66 | self.vertices = {} 67 | 68 | class Contest(object): 69 | def __init__(self, name = '', image = None, problems = None, start_time = _DEFAULT_TIME, end_time = _DEFAULT_TIME, time_delta = _DEFAULT_TIMEDELTA, ranklist = None): 70 | if problems is None: 71 | problems = {} 72 | if ranklist is None: 73 | ranklist = lambda:{} 74 | self.__dict__.update({key:value for key,value in locals().items() if key != 'self'}) 75 | -------------------------------------------------------------------------------- /oiasg/lib/resource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import os 5 | 6 | import pyglet 7 | 8 | from .data import * 9 | 10 | class Resource(object): 11 | def init(self): 12 | pyglet.resource.path = data.get_subdirs('resources') 13 | self.load_fonts(data.get_all_list(['FONTS'])) 14 | def load_fonts(self,fonts): 15 | if fonts is not None: 16 | for font in fonts: 17 | pyglet.resource.add_font(font[0]) 18 | pyglet.font.load(font[1]) 19 | def load_image(self,path): 20 | if os.path.splitext(path)[1].lower() == '.gif': 21 | return pyglet.resource.animation(path) 22 | else: 23 | return pyglet.resource.image(path) 24 | def load_static_image(self,path): 25 | return pyglet.resource.image(path) 26 | def decode_text(self,str): 27 | if len(str) < 1: 28 | return pyglet.text.decode_text(str) 29 | elif str[0] == 'N': 30 | # 游戏默认格式 31 | return self.default_formatted_text(str[1:]) 32 | elif str[0] == 'H': 33 | # HTML 34 | return pyglet.text.decode_html(str[1:]) 35 | elif str[0] == 'P': 36 | # 纯文本 37 | return pyglet.text.decode_text(str[1:]) 38 | else: 39 | # pyglet标准格式 40 | return pyglet.text.decode_attributed(str[1:]) 41 | def default_formatted_text(self,str): 42 | return self.decode_text('F'+data.get(['UI','NORMAL_MESSAGE_TEXT_STYLE_TEXT'],'')+str) 43 | 44 | resource = Resource() -------------------------------------------------------------------------------- /oiasg/lib/uidata.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import pyglet 5 | from .controls import * 6 | from .data import * 7 | from .resource import * 8 | from .gameobjects import * 9 | from . import ui 10 | from . import uiresource 11 | 12 | class UIData_Base(object): 13 | def build_control(self): 14 | pass 15 | @property 16 | def control(self): 17 | # 生成控件 18 | if not self._built_control: 19 | self._control = self.build_control() 20 | self._built_control = True 21 | return self._control 22 | # UI数据:从某个字典项读取数据并生成UI数据(仅外观) 23 | class UIData_DictItem(UIData_Base): 24 | def __init__(self, data): 25 | key, value = data 26 | self.__dict__.update(value) 27 | self.key = key 28 | self._built_control = False 29 | class UIData(UIData_Base): 30 | def __init__(self, data): 31 | self.data = data 32 | self._built_control = False 33 | # 静态UI数据集:静态(类)存储的UI数据 34 | class UIDataStaticSet(object): 35 | @classmethod 36 | def build_dataset(cls): 37 | pass 38 | @classmethod 39 | def dataset(cls): 40 | # 生成控件 41 | if not cls._built_dataset: 42 | cls._dataset = cls.build_dataset() 43 | cls._built_dataset = True 44 | return cls._dataset 45 | 46 | class Contest_UIData(UIData): 47 | def build_control(self): 48 | image = None if self.data.image is None else Sprite(resource.load_image(self.data.image)) 49 | title = self.data.name 50 | info = [] 51 | for key,value in self.data.data.items(): 52 | info.append((value.strftime(ui.GAME_CHARACTER_BOARD_BIRTH_FORMAT)) if key == 'birth' else str(value)) 53 | return image,title,info 54 | class Message_Log_UIData(UIData): 55 | def build_control(self): 56 | button_text = self.data.time.strftime(self.data.timeformat) + ' ' + self.data.name 57 | button_label = pyglet.text.Label(button_text,font_name = self.data.font_name if self.data.font_name is not None else ui.GAME_MESSAGE_FONT_NAME,font_size = ui.GAME_MESSAGE_FONT_SIZE,color = self.data.font_color,anchor_x = 'center',anchor_y = 'center') 58 | button = Button([ui.ui.window], label = button_label, 59 | image = Sprite(uiresource.game_message_log_back), 60 | hover_color = ui.NORMAL_BUTTON_HOVER_COLOR, 61 | color = ui.NORMAL_BUTTON_COLOR) 62 | messagewindow = ui.ui.MessageWindow(self.data.text, self.data.name, Sprite(resource.load_image(self.data.image)) if self.data.image is not None else None, self.data.pos) 63 | @button.event 64 | def on_press(): 65 | messagewindow.exe() 66 | return button 67 | class Message_Timetable_UIData(UIData): 68 | def build_control(self): 69 | button_text = self.data.time.strftime(self.data.timeformat) + ' ' + self.data.name 70 | button_label = pyglet.text.Label(button_text,font_name = self.data.font_name if self.data.font_name is not None else ui.GAME_MESSAGE_FONT_NAME,font_size = ui.GAME_MESSAGE_FONT_SIZE,color = self.data.font_color,anchor_x = 'center',anchor_y = 'center') 71 | button = Button([ui.ui.window], label = button_label, 72 | image = Sprite(uiresource.game_message_timetable_back), 73 | hover_color = ui.NORMAL_BUTTON_HOVER_COLOR, 74 | color = ui.NORMAL_BUTTON_COLOR) 75 | messagewindow = ui.ui.MessageWindow(self.data.text, self.data.name, Sprite(resource.load_image(self.data.image)) if self.data.image is not None else None, self.data.pos) 76 | @button.event 77 | def on_press(): 78 | messagewindow.exe() 79 | return button 80 | class Strategy_UIData(UIData): 81 | def build_control(self): 82 | button_label = pyglet.text.Label(self.data.name,font_name = ui.GAME_STRATEGY_FONT_NAME,font_size = ui.GAME_STRATEGY_FONT_SIZE,color = ui.GAME_STRATEGY_FONT_COLOR,anchor_x = 'center',anchor_y = 'center') 83 | icon = Sprite(resource.load_image(self.data.icon)) if self.data.icon is not None else None 84 | button = SwitchButton( 85 | [ui.ui.window], 86 | [button_label,button_label], 87 | [Sprite(uiresource.game_message_strategy_back),Sprite(uiresource.game_message_strategy_select_back)], 88 | [icon,icon], 89 | hover_color = ui.NORMAL_BUTTON_HOVER_COLOR, 90 | color = ui.NORMAL_BUTTON_COLOR 91 | ) 92 | return button 93 | class Image_UIData(UIData): 94 | def build_control(self): 95 | return Sprite(resource.load_image(self.data)) 96 | class GameUIDataManager(object): 97 | def __init__(self, game): 98 | self.game = game 99 | self.images_uidata = {} 100 | self.character_uidata = None 101 | self.messages_log_uidata = {} 102 | self.messages_timetable_uidata = {} 103 | self.messages_strategies_uidata = {} 104 | self.strategies_uidata = {} 105 | 106 | def get_image(self, key): 107 | if key not in self.images_uidata: 108 | self.images_uidata[key] = Image_UIData(key) 109 | res = self.images_uidata[key].control 110 | res.key = key 111 | return res 112 | def get_message_log_button(self, key): 113 | if key not in self.messages_log_uidata: 114 | self.messages_log_uidata[key] = Message_Log_UIData(self.game.gamedata['messages'][key]) 115 | res = self.messages_log_uidata[key].control 116 | res.key = key 117 | return res 118 | def get_message_timetable_button(self, key): 119 | if key not in self.messages_timetable_uidata: 120 | self.messages_timetable_uidata[key] = Message_Timetable_UIData(self.game.gamedata['messages'][key]) 121 | res = self.messages_timetable_uidata[key].control 122 | res.key = key 123 | return res 124 | def get_message_strategy_button(self, key): 125 | if key not in self.messages_strategies_uidata: 126 | self.messages_strategies_uidata[key] = Strategy_UIData(self.game.gamedata['strategies'][key]) 127 | res = self.messages_strategies_uidata[key].control 128 | res.key = key 129 | return res 130 | def get_strategy_button(self, key): 131 | if key not in self.strategies_uidata: 132 | self.strategies_uidata[key] = Strategy_UIData(self.game.gamedata['strategies'][key]) 133 | res = self.strategies_uidata[key].control 134 | res.key = key 135 | return res 136 | 137 | @property 138 | def character_board_ui(self): 139 | if self.character_uidata is None: 140 | self.character_uidata = Contest_UIData(self.game.gamedata['character']) 141 | return self.character_uidata.control 142 | def flush_character_board_ui(self): 143 | self.character_uidata = None 144 | 145 | @property 146 | def messages_board_ui(self): 147 | plans = self.game.gamedata['strategy_plan'] 148 | 149 | strategy_board_items = [] 150 | if plans: 151 | it = self.game.gamedata['strategy_plan_it'] % len(plans) 152 | for i in range(min(len(plans),ui.GAME_MESSAGES_BOARD_PLAN_ITEM_COUNT)): 153 | strategy_board_items.append(self.get_message_strategy_button(plans[it])) 154 | it = (it + 1)%len(plans) 155 | 156 | return list(map(self.get_message_timetable_button, self.game.gamedata['timetable_messages'][-ui.GAME_MESSAGES_BOARD_TIMETABLE_ITEM_COUNT:])),list(map(self.get_message_log_button, self.game.gamedata['log_messages'][-ui.GAME_MESSAGES_BOARD_LOG_ITEM_COUNT:])), strategy_board_items, list(map(self.get_strategy_button, self.game.gamedata['select_strategies'])) 157 | 158 | @property 159 | def pages_character_ui(self): 160 | back, front = None, None 161 | if self.game.gamedata['pages_character_back'] is not None: 162 | back = self.get_image(self.game.gamedata['pages_character_back']) 163 | if self.game.gamedata['pages_character_front'] is not None: 164 | front = self.get_image(self.game.gamedata['pages_character_front']) 165 | return back, front 166 | 167 | @property 168 | def select_strategy_plans(self): 169 | # 坑 170 | return [] 171 | 172 | @property 173 | def time(self): 174 | return self.game.gamedata['time'] 175 | -------------------------------------------------------------------------------- /oiasg/lib/uiresource.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | from .data import data 5 | from .resource import resource 6 | 7 | vars = {} 8 | 9 | def init(): 10 | vars.update(data.get_all_dict(['UI'])) # 引入命名空间 11 | globals().update(vars) 12 | # 预加载资源 13 | 14 | normal_button_back = resource.load_image(NORMAL_BUTTON_BACK) 15 | normal_button_pressed_back = resource.load_image(NORMAL_BUTTON_PRESSED_BACK) 16 | normal_menu_back = resource.load_image(NORMAL_MENU_BACK) 17 | normal_page_back = resource.load_image(NORMAL_PAGE_BACK) 18 | normal_default_image = resource.load_image(NORMAL_DEFAULT_IMAGE) 19 | normal_slider_back = resource.load_image(NORMAL_SLIDER_BACK) 20 | normal_slider_cursor = resource.load_image(NORMAL_SLIDER_CURSOR) 21 | normal_checkbox_unchecked_back = resource.load_image(NORMAL_CHECKBOX_UNCHECKED_BACK) 22 | normal_checkbox_checked_back = resource.load_image(NORMAL_CHECKBOX_CHECKED_BACK) 23 | normal_scrollbar_back = resource.load_image(NORMAL_SCROLLBAR_BACK) 24 | normal_scrollbar_cursor = resource.load_image(NORMAL_SCROLLBAR_CURSOR) 25 | normal_switchbutton_back = resource.load_image(NORMAL_SWITCHBUTTON_BACK) 26 | normal_switchbutton_select_back = resource.load_image(NORMAL_SWITCHBUTTON_SELECT_BACK) 27 | normal_tag_rv_back = resource.load_image(NORMAL_TAG_RV_IMAGE) 28 | normal_tag_rv_selected_back = resource.load_image(NORMAL_TAG_RV_SELECTED_IMAGE) 29 | normal_progress_bar_front = resource.load_image(NORMAL_PROGRESS_BAR_FRONT) 30 | normal_progress_bar_back = resource.load_image(NORMAL_PROGRESS_BAR_BACK) 31 | normal_message_back = resource.load_image(NORMAL_MESSAGE_BACK) 32 | 33 | main_menu_back = resource.load_image(MAIN_MENU_BACK) 34 | main_menu_start_back = resource.load_image(MAIN_MENU_START_BACK) 35 | main_menu_start_pressed_back = resource.load_image(MAIN_MENU_START_PRESSED_BACK) 36 | 37 | game_header_back = resource.load_image(GAME_HEADER_BACK) 38 | # game_header_speedbar_back = resource.load_image(GAME_HEADER_SPEEDBAR_BACK) 39 | game_header_speedbar_button_back = resource.load_image(GAME_HEADER_SPEEDBAR_BUTTON_BACK) 40 | game_header_speedbar_pressed_back = resource.load_image(GAME_HEADER_SPEEDBAR_BUTTON_PRESSED_BACK) 41 | 42 | game_pages_character_back = resource.load_image(GAME_PAGES_CHARACTER_BACK) 43 | game_pages_timetable_back = resource.load_image(GAME_PAGES_TIMETABLE_BACK) 44 | game_pages_ability_back = resource.load_image(GAME_PAGES_ABILITY_BACK) 45 | game_pages_contest_back = resource.load_image(GAME_PAGES_CONTEST_BACK) 46 | 47 | game_header_status_bar_icons = [resource.load_image(i) for i in GAME_HEADER_STATUS_BAR_ICONS] 48 | 49 | game_header_switchpage_icons = [resource.load_image(i) for i in GAME_HEADER_SWITCHPAGE_ICONS] 50 | game_header_switchpage_disabled_icons = [(resource.load_image(i) if i is not None else None) for i in GAME_HEADER_SWITCHPAGE_DISABLED_ICONS] 51 | game_header_switchpage_button_select_back = resource.load_image(GAME_HEADER_SWITCHPAGE_BUTTON_SELECT_BACK) 52 | 53 | game_header_switch_down_icon = resource.load_image(GAME_HEADER_SWITCH_DOWN_ICON) 54 | game_header_switch_up_icon = resource.load_image(GAME_HEADER_SWITCH_UP_ICON) 55 | game_header_switch_disabled_image = resource.load_image(GAME_HEADER_SWITCH_DISABLED_IMAGE) 56 | 57 | game_board_back = resource.load_image(GAME_BOARD_BACK) 58 | 59 | game_message_timetable_back = resource.load_image(GAME_MESSAGE_TIMETABLE_BACK) 60 | game_message_log_back = resource.load_image(GAME_MESSAGE_LOG_BACK) 61 | game_message_strategy_back = resource.load_image(GAME_MESSAGE_STRATEGY_BACK) 62 | game_message_strategy_select_back = resource.load_image(GAME_MESSAGE_STRATEGY_SELECT_BACK) 63 | game_message_strategy_cursor = resource.load_image(GAME_MESSAGE_STRATEGY_CURSOR) 64 | 65 | game_slplan_button_back = resource.load_image(GAME_SLPLAN_BUTTON_BACK) 66 | game_slplan_button_pressed_back = resource.load_image(GAME_SLPLAN_BUTTON_PRESSED_BACK) 67 | game_slplan_info_back = resource.load_image(GAME_SLPLAN_INFO_BACK) 68 | game_slplan_copy_icon = resource.load_image(GAME_SLPLAN_COPY_ICON) 69 | game_slplan_remove_icon = resource.load_image(GAME_SLPLAN_REMOVE_ICON) 70 | game_slplan_use_icon = resource.load_image(GAME_SLPLAN_USE_ICON) 71 | game_slplan_rename_icon = resource.load_image(GAME_SLPLAN_RENAME_ICON) 72 | game_slplan_confirm_image = resource.load_image(GAME_SLPLAN_CONFIRM_IMAGE) 73 | 74 | game_pages_timetable_plan_add_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_ADD_ICON) 75 | game_pages_timetable_plan_edit_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_EDIT_ICON) 76 | game_pages_timetable_plan_remove_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_REMOVE_ICON) 77 | game_pages_timetable_plan_save_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_SAVE_ICON) 78 | # game_pages_timetable_plan_load_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_LOAD_ICON) 79 | game_pages_timetable_plan_moveup_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_MOVEUP_ICON) 80 | game_pages_timetable_plan_movedown_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_MOVEDOWN_ICON) 81 | game_pages_timetable_plan_shiftup_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_SHIFTUP_ICON) 82 | game_pages_timetable_plan_shiftdown_icon = resource.load_image(GAME_PAGES_TIMETABLE_PLAN_SHIFTDOWN_ICON) 83 | 84 | game_pages_timetable_frame_back = resource.load_image(GAME_PAGES_TIMETABLE_FRAME_BACK) 85 | game_pages_timetable_frame_left_button_image = resource.load_image(GAME_PAGES_TIMETABLE_FRAME_LEFT_BUTTON_IMAGE) 86 | game_pages_timetable_frame_right_button_image = resource.load_image( 87 | GAME_PAGES_TIMETABLE_FRAME_RIGHT_BUTTON_IMAGE) 88 | game_pages_timetable_frame_plan_button_back = resource.load_image(GAME_PAGES_TIMETABLE_FRAME_PLAN_BUTTON_BACK) 89 | game_pages_timetable_frame_plan_button_pressed_back = resource.load_image(GAME_PAGES_TIMETABLE_FRAME_PLAN_BUTTON_PRESSED_BACK) 90 | 91 | vars.update(locals()) 92 | globals().update(locals()) -------------------------------------------------------------------------------- /oiasg/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import os 5 | import pyglet 6 | from lib import * 7 | from lib.data import data, saves 8 | from lib.resource import resource 9 | from lib.ui import ui 10 | GAMEPATH = os.path.dirname(os.path.realpath(__file__)) 11 | class GameObject(object): 12 | # 游戏体(单类) 13 | def __init__(self): 14 | # 加载数据 15 | data.init(GAMEPATH) 16 | # 加载存档 17 | saves.init(GAMEPATH) 18 | # 加载资源 19 | resource.init() 20 | # 创建UI 21 | ui.init() 22 | def run(self): 23 | # 显示UI 24 | ui.show() 25 | # 运行应用程序 26 | pyglet.app.run() 27 | # 保存数据 28 | data.save() 29 | 30 | game = GameObject() 31 | game.run() -------------------------------------------------------------------------------- /oiasg/resources/ability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/ability.png -------------------------------------------------------------------------------- /oiasg/resources/ability_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/ability_icon.png -------------------------------------------------------------------------------- /oiasg/resources/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/add.png -------------------------------------------------------------------------------- /oiasg/resources/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/back.png -------------------------------------------------------------------------------- /oiasg/resources/bar_h.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/bar_h.png -------------------------------------------------------------------------------- /oiasg/resources/bgm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/bgm.mp3 -------------------------------------------------------------------------------- /oiasg/resources/button_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/button_select.png -------------------------------------------------------------------------------- /oiasg/resources/button_unselect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/button_unselect.png -------------------------------------------------------------------------------- /oiasg/resources/button_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/button_v.png -------------------------------------------------------------------------------- /oiasg/resources/button_v_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/button_v_pressed.png -------------------------------------------------------------------------------- /oiasg/resources/character.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/character.png -------------------------------------------------------------------------------- /oiasg/resources/chosen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/chosen.png -------------------------------------------------------------------------------- /oiasg/resources/commonants_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/commonants_icon.png -------------------------------------------------------------------------------- /oiasg/resources/commonants_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/commonants_image.png -------------------------------------------------------------------------------- /oiasg/resources/contest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/contest.png -------------------------------------------------------------------------------- /oiasg/resources/contest_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/contest_disabled.png -------------------------------------------------------------------------------- /oiasg/resources/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/copy.png -------------------------------------------------------------------------------- /oiasg/resources/cross.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/cross.png -------------------------------------------------------------------------------- /oiasg/resources/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/cursor.png -------------------------------------------------------------------------------- /oiasg/resources/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/default.png -------------------------------------------------------------------------------- /oiasg/resources/down_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/down_button.png -------------------------------------------------------------------------------- /oiasg/resources/edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/edit.png -------------------------------------------------------------------------------- /oiasg/resources/flag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/flag.png -------------------------------------------------------------------------------- /oiasg/resources/frame_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/frame_back.png -------------------------------------------------------------------------------- /oiasg/resources/game_stage1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/game_stage1.png -------------------------------------------------------------------------------- /oiasg/resources/game_stage2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/game_stage2.png -------------------------------------------------------------------------------- /oiasg/resources/game_stage3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/game_stage3.png -------------------------------------------------------------------------------- /oiasg/resources/game_stage_contest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/game_stage_contest.png -------------------------------------------------------------------------------- /oiasg/resources/goback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/goback.png -------------------------------------------------------------------------------- /oiasg/resources/header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/header.png -------------------------------------------------------------------------------- /oiasg/resources/health_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/health_icon.png -------------------------------------------------------------------------------- /oiasg/resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/icon.ico -------------------------------------------------------------------------------- /oiasg/resources/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/left.png -------------------------------------------------------------------------------- /oiasg/resources/load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/load.png -------------------------------------------------------------------------------- /oiasg/resources/log_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/log_item.png -------------------------------------------------------------------------------- /oiasg/resources/main_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/main_back.png -------------------------------------------------------------------------------- /oiasg/resources/main_back.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/main_back.xcf -------------------------------------------------------------------------------- /oiasg/resources/mood_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/mood_icon.png -------------------------------------------------------------------------------- /oiasg/resources/move_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/move_down.png -------------------------------------------------------------------------------- /oiasg/resources/move_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/move_up.png -------------------------------------------------------------------------------- /oiasg/resources/orz.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/orz.gif -------------------------------------------------------------------------------- /oiasg/resources/progress_bar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/progress_bar.png -------------------------------------------------------------------------------- /oiasg/resources/remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/remove.png -------------------------------------------------------------------------------- /oiasg/resources/right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/right.png -------------------------------------------------------------------------------- /oiasg/resources/save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/save.png -------------------------------------------------------------------------------- /oiasg/resources/scroll_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/scroll_back.png -------------------------------------------------------------------------------- /oiasg/resources/scroll_cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/scroll_cursor.png -------------------------------------------------------------------------------- /oiasg/resources/shift_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/shift_down.png -------------------------------------------------------------------------------- /oiasg/resources/shift_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/shift_up.png -------------------------------------------------------------------------------- /oiasg/resources/slider_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/slider_back.png -------------------------------------------------------------------------------- /oiasg/resources/slider_cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/slider_cursor.png -------------------------------------------------------------------------------- /oiasg/resources/smallbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/smallbutton.png -------------------------------------------------------------------------------- /oiasg/resources/smallbutton_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/smallbutton_pressed.png -------------------------------------------------------------------------------- /oiasg/resources/strategy_cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/strategy_cursor.png -------------------------------------------------------------------------------- /oiasg/resources/strategy_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/strategy_item.png -------------------------------------------------------------------------------- /oiasg/resources/strategy_item_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/strategy_item_selected.png -------------------------------------------------------------------------------- /oiasg/resources/stress_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/stress_icon.png -------------------------------------------------------------------------------- /oiasg/resources/switchpage_button_select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/switchpage_button_select.png -------------------------------------------------------------------------------- /oiasg/resources/tag_button_v.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/tag_button_v.png -------------------------------------------------------------------------------- /oiasg/resources/tag_button_v_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/tag_button_v_pressed.png -------------------------------------------------------------------------------- /oiasg/resources/tag_rv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/tag_rv.png -------------------------------------------------------------------------------- /oiasg/resources/tag_rv_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/tag_rv_selected.png -------------------------------------------------------------------------------- /oiasg/resources/test_video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/test_video.mp4 -------------------------------------------------------------------------------- /oiasg/resources/test_video2.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/test_video2.mp4 -------------------------------------------------------------------------------- /oiasg/resources/timetable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/timetable.png -------------------------------------------------------------------------------- /oiasg/resources/timetable_item.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/timetable_item.png -------------------------------------------------------------------------------- /oiasg/resources/up_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/up_button.png -------------------------------------------------------------------------------- /oiasg/resources/up_button.svg: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /oiasg/resources/up_button_disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/up_button_disabled.png -------------------------------------------------------------------------------- /oiasg/resources/杨任东竹石体-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/杨任东竹石体-Regular.ttf -------------------------------------------------------------------------------- /oiasg/resources/杨任东竹石体-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/resources/杨任东竹石体-Semibold.ttf -------------------------------------------------------------------------------- /oiasg/saves/save0.oiasgsav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/saves/save0.oiasgsav -------------------------------------------------------------------------------- /oiasg/saves/save1.oiasgsav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/saves/save1.oiasgsav -------------------------------------------------------------------------------- /oiasg/saves/save2.oiasgsav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/saves/save2.oiasgsav -------------------------------------------------------------------------------- /oiasg/saves/save3.oiasgsav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg/saves/save3.oiasgsav -------------------------------------------------------------------------------- /oiasg_base/__commons/__ini.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import random 3 | 4 | # definition 5 | 6 | val = lambda x:eval(x,globals(),globals()) 7 | exe = lambda x:exec(x,globals(),globals()) 8 | 9 | time = datetime.datetime 10 | timed = datetime.timedelta 11 | 12 | rand_expect = (lambda x:random.randint(0,x) == 0) 13 | 14 | class event(object): 15 | def __init__(self, appearance = None, trigger = None, effects = None, user = None): 16 | self.appearance = appearance 17 | self.trigger = trigger 18 | self.effects = effects 19 | self.user = user 20 | if self.effects is not None: 21 | self.options = self.effects.get('options') 22 | self.immediate = self.effects.get('immediate') 23 | def check(self): 24 | if self.trigger is None: 25 | return False 26 | return val(self.trigger) 27 | def execute_options(self, option_chosen): 28 | if self.options is not None: 29 | for i in range(self.options.len()): 30 | if option_chosen[i]: 31 | exe(self.options[i]['effect']) 32 | def execute(self): 33 | if self.immediate is not None: 34 | exe(self.immediate) 35 | if self.appearance is not None: 36 | exe(self.appearance) 37 | # options 38 | 39 | # class problem(object): 40 | # def __init__(self, tags): 41 | # self.tags = tags 42 | # self.sols = {} 43 | 44 | class contest(object): 45 | def __init__(self, appearance = None, problems = None, strategies = None,user = None): 46 | self.appearance = appearance 47 | self.problems = problems 48 | self.strategies = strategies 49 | self.user = user 50 | 51 | self.strategy = None 52 | self.running = False 53 | def start(self): 54 | self.running = True 55 | self.cur_problems = list(map(val,self.problems)) 56 | global cur_timedelta, cur_contest 57 | cur_contest = self 58 | cur_timedelta = contest_timedelta 59 | def end(self): 60 | self.running = False 61 | global cur_timedelta, cur_contest 62 | cur_contest = None 63 | cur_timedelta = round_timedelta 64 | 65 | class game_log(object): 66 | pass 67 | 68 | check_event = lambda e:events[e].check() 69 | execute_event = lambda e:events[e].execute() 70 | trigger_event = lambda e:event_q.append(events[e]) 71 | execute_event_options = lambda e,o:events[e].execute_options(o) 72 | 73 | def end(): 74 | global running,event_q 75 | running = False 76 | event_q.clear() 77 | 78 | # system 79 | 80 | start_time = time(2016,9,1,7) 81 | cur_time = start_time 82 | round_timedelta = timed(hours = 8) 83 | contest_timedelta = timed(minutes = 1) 84 | cur_timedelta = round_timedelta 85 | end_time = time(2016,9,5,7) 86 | events = {} 87 | contests = {} 88 | log = game_log() 89 | event_q = [] 90 | cur_contest = None 91 | strategies = {} 92 | timetable_menu = [] 93 | timetable = [] 94 | timetable_it = None 95 | 96 | def play_round(): 97 | global cur_time 98 | global event_q 99 | cur_time = start_time + (((cur_time - start_time) // cur_timedelta) + 1) * cur_timedelta 100 | print(cur_time) 101 | event_q.clear() 102 | for e in events.values(): 103 | if e.check(): 104 | event_q.append(e) 105 | global timetable_it 106 | if cur_contest is None and timetable_it is not None: 107 | event_q.append(events[strategies[timetable[timetable_it]]]) 108 | timetable_it = (timetable_it + 1) % timetable.len() 109 | elif cur_contest is not None and cur_contest.strategy is not None: 110 | event_q.append(events[strategies[cur_contest.strategy]]) 111 | event_q.sort(key = lambda x:x.user['privilege'] if x.user is not None and 'privilege' in x.user else -2147483648) 112 | while event_q: 113 | e = event_q[-1] 114 | event_q.pop() 115 | e.execute() 116 | 117 | # abilities 118 | 119 | thinking = {} 120 | code = {} 121 | tags = {} 122 | ideas = {} 123 | moods = {} 124 | -------------------------------------------------------------------------------- /oiasg_base/__commons/_vars/code.py: -------------------------------------------------------------------------------- 1 | code.update({ 2 | 0:{ 3 | 'name':'代码熟练度', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'代码设计', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | }) 16 | 17 | coding = code[0] 18 | designing = code[1] -------------------------------------------------------------------------------- /oiasg_base/__commons/_vars/ideas.py: -------------------------------------------------------------------------------- 1 | ideas.update({ 2 | 0:{ 3 | 'name':'状态压缩', 4 | 'appearance':None, 5 | 'relations':{}, 6 | 'privilege':0, 7 | 'level':0, 8 | } 9 | , 10 | 11 | 1:{ 12 | 'name':'映射', 13 | 'appearance':None, 14 | 'relations':{}, 15 | 'privilege':0, 16 | 'level':0, 17 | } 18 | , 19 | 20 | 2:{ 21 | 'name':'分治', 22 | 'appearance':None, 23 | 'relations':{}, 24 | 'privilege':0, 25 | 'level':0, 26 | } 27 | , 28 | 29 | 3:{ 30 | 'name':'延迟处理', 31 | 'appearance':None, 32 | 'relations':{}, 33 | 'privilege':0, 34 | 'level':0, 35 | } 36 | , 37 | 38 | 4:{ 39 | 'name':'单调性', 40 | 'appearance':None, 41 | 'relations':{}, 42 | 'privilege':0, 43 | 'level':0, 44 | } 45 | , 46 | 47 | 5:{ 48 | 'name':'二分', 49 | 'appearance':None, 50 | 'relations':{}, 51 | 'privilege':0, 52 | 'level':0, 53 | } 54 | , 55 | 56 | 6:{ 57 | 'name':'倍增', 58 | 'appearance':None, 59 | 'relations':{}, 60 | 'privilege':0, 61 | 'level':0, 62 | } 63 | , 64 | 65 | 7:{ 66 | 'name':'分块', 67 | 'appearance':None, 68 | 'relations':{}, 69 | 'privilege':0, 70 | 'level':0, 71 | } 72 | , 73 | 74 | 8:{ 75 | 'name':'记忆化', 76 | 'appearance':None, 77 | 'relations':{}, 78 | 'privilege':0, 79 | 'level':0, 80 | } 81 | , 82 | 83 | 9:{ 84 | 'name':'可持久化', 85 | 'appearance':None, 86 | 'relations':{}, 87 | 'privilege':0, 88 | 'level':0, 89 | } 90 | , 91 | 92 | 10:{ 93 | 'name':'离线', 94 | 'appearance':None, 95 | 'relations':{}, 96 | 'privilege':0, 97 | 'level':0, 98 | } 99 | , 100 | 101 | 11:{ 102 | 'name':'近似', 103 | 'appearance':None, 104 | 'relations':{}, 105 | 'privilege':0, 106 | 'level':0, 107 | } 108 | , 109 | 110 | 12:{ 111 | 'name':'随机化', 112 | 'appearance':None, 113 | 'relations':{}, 114 | 'privilege':0, 115 | 'level':0, 116 | } 117 | , 118 | 119 | 13:{ 120 | 'name':'启发和估价', 121 | 'appearance':None, 122 | 'relations':{}, 123 | 'privilege':0, 124 | 'level':0, 125 | } 126 | }) 127 | 128 | -------------------------------------------------------------------------------- /oiasg_base/__commons/_vars/mood.py: -------------------------------------------------------------------------------- 1 | moods.update({ 2 | 0:{ 3 | 'name':'心情', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'心理压力', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | }) 16 | 17 | mood = moods[0] 18 | stress = moods[1] 19 | -------------------------------------------------------------------------------- /oiasg_base/__commons/_vars/thinking.py: -------------------------------------------------------------------------------- 1 | thinking.update({ 2 | 0:{ 3 | 'name':'抽象思维', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'形象思维', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | , 16 | 2:{ 17 | 'name':'想象力', 18 | 'appearance':None, 19 | 'privilege':0, 20 | 'level':0 21 | } 22 | }) 23 | 24 | structure = thinking[0] 25 | graphic = thinking[1] 26 | imagination = thinking[2] 27 | -------------------------------------------------------------------------------- /oiasg_base/__commons/contests/_problemgen.py: -------------------------------------------------------------------------------- 1 | def problem_basic(name): 2 | return { 3 | 'name':name, 4 | 'tags':{ 5 | 0:{ 6 | 'parents':None, 7 | 'parent':None, 8 | 'score':30, 9 | 'tag':AB['name'], 10 | 'relations':{ 11 | 134:1.0 # AB 12 | }, 13 | 'difficulty':0.5, 14 | 'rate':0 15 | }, 16 | 1:{ 17 | 'parents':[0], 18 | 'parent':None, 19 | 'score':70, 20 | 'tag':FT['name'], 21 | 'relations':{ 22 | 144:1.0 # FFT 23 | }, 24 | 'difficulty':2, 25 | 'rate':0 26 | } 27 | }, 28 | 'sols':{} 29 | } -------------------------------------------------------------------------------- /oiasg_base/__commons/contests/example.py: -------------------------------------------------------------------------------- 1 | contests.update({ 2 | 'example_contest':contest( 3 | appearance = None, 4 | problems = [ 5 | 'problem_basic("A")', 6 | 'problem_basic("B")' 7 | ], 8 | strategies = {} 9 | ) 10 | }) 11 | 12 | # _TC = contests['example_contest'] -------------------------------------------------------------------------------- /oiasg_base/__commons/events/__system.py: -------------------------------------------------------------------------------- 1 | events.update({ 2 | 'check_timeline':event( 3 | appearance = None, 4 | trigger = 'cur_time > end_time', 5 | effects = { 6 | 'immediate': 7 | ''' 8 | print("Game has ended:time up.") 9 | end() 10 | ''' 11 | }, 12 | user = {'privilege':2147483647} 13 | ) 14 | }) -------------------------------------------------------------------------------- /oiasg_base/__commons/events/example.py: -------------------------------------------------------------------------------- 1 | events.update({ 2 | 'example_event':event( 3 | appearance = None, 4 | trigger = 'True # rand_expect(10)', 5 | effects = { 6 | 'immediate': 7 | 'print("test_event")\n' + 8 | 'trigger_event("example_event_triggered")\n' 9 | , 10 | 'options':[ 11 | { 12 | 'name':'option1', 13 | 'effect':'' 14 | }, 15 | { 16 | 'name':'option2', 17 | 'effect':'' 18 | } 19 | ] 20 | } 21 | ), 22 | 'example_event_triggered':event( 23 | appearance = None, 24 | trigger = None, 25 | effects = { 26 | 'immediate': 27 | 'print("test_event_triggered")\n' 28 | } 29 | ) 30 | }) -------------------------------------------------------------------------------- /oiasg_base/__commons/events/strategy/__general.py: -------------------------------------------------------------------------------- 1 | strategies.update({ 2 | 'example_strategy':'example_event' 3 | }) -------------------------------------------------------------------------------- /oiasg_base/lib/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ini', 'game', 'appearance'] -------------------------------------------------------------------------------- /oiasg_base/lib/appearance.py: -------------------------------------------------------------------------------- 1 | # def tst(): 2 | # print('tst') -------------------------------------------------------------------------------- /oiasg_base/lib/game.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import traceback 4 | # import functools 5 | 6 | from . import appearance 7 | 8 | def getobj(s): 9 | return open(s, "r", encoding = 'utf-8').read() 10 | 11 | def getobjs(s): 12 | objs = [] 13 | fs = os.listdir(s) 14 | for f in fs: 15 | absf = os.path.join(s, f) 16 | if os.path.isfile(absf) and os.path.splitext(f)[1] == '.py': 17 | objs.append(absf) 18 | elif os.path.isdir(absf): 19 | objs += getobjs(absf) 20 | return objs 21 | 22 | class gameplay(object): 23 | def __init__(self, scenario = "__general", _basedir = None): 24 | print("A new game object is constructed.") 25 | if _basedir is None: 26 | _basedir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 27 | self.__basedir = _basedir 28 | self.var = { 29 | "load_script":self.load_script, 30 | "load_scripts":self.load_scripts, 31 | 32 | "running":True 33 | # "output":self.output 34 | } 35 | self.load_scripts("__commons") 36 | 37 | self.load_script(os.path.join("scenarios",scenario + '.py')) 38 | 39 | self.paused = True 40 | self.speed = 0 41 | 42 | def end(self): 43 | print("A game has ended.") 44 | def run(self): 45 | print("A game has started.") 46 | try: 47 | # definition 48 | # execution 49 | while self.var['running']: 50 | self.var['play_round']() 51 | self.pause_game() 52 | while self.paused: 53 | # self.output() 54 | ope = input() 55 | # print("Game object got operation:" + ope) 56 | exec(ope) 57 | time.sleep(2*(0.5**self.speed)) 58 | except: 59 | print("!!!!! --- 游戏体抛出异常 --- !!!!!") 60 | traceback.print_exc() 61 | self.end() 62 | def output(self): 63 | print(self.var) 64 | def load_script(self, scriptpath): 65 | exec(getobj(os.path.join(self.__basedir,scriptpath)), self.var, self.var) 66 | def load_scripts(self, scriptdir): 67 | objs = getobjs(os.path.join(self.__basedir, scriptdir)) 68 | objs.sort() 69 | for i in objs: 70 | exec(getobj(i), self.var, self.var) 71 | def pause_game(self): 72 | self.paused = True 73 | def continue_game(self): 74 | self.paused = False 75 | def set_speed(self, speed): 76 | self.speed = speed -------------------------------------------------------------------------------- /oiasg_base/lib/ini.py: -------------------------------------------------------------------------------- 1 | def init_sys(): 2 | pass -------------------------------------------------------------------------------- /oiasg_base/main.py: -------------------------------------------------------------------------------- 1 | # importing system modules 2 | 3 | import os 4 | import traceback 5 | 6 | # import game lib 7 | 8 | # import pygame 9 | # from pygame.locals import * 10 | 11 | # importing my modules 12 | 13 | from lib import * 14 | 15 | try: 16 | ini.init_sys() 17 | 18 | # debugging mode:read operations from console 19 | 20 | def start_game(scenario): 21 | g = game.gameplay(scenario,os.path.dirname(os.path.realpath(__file__))) 22 | g.run() 23 | 24 | while True: 25 | ope = input() 26 | print("Main system got operation:" + ope) 27 | exec(ope) 28 | except: 29 | print("!!!!! --- 主程序抛出异常 --- !!!!!") 30 | traceback.print_exc() 31 | 32 | exit() -------------------------------------------------------------------------------- /oiasg_base/scenarios/__general.py: -------------------------------------------------------------------------------- 1 | name,sex,school,province,image,birthday = "李华","女","育才中学","北京","",time(2001,1,1) -------------------------------------------------------------------------------- /oiasg_gui/lib/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['appearance','controls'] -------------------------------------------------------------------------------- /oiasg_gui/lib/appearance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | from . import controls 5 | 6 | -------------------------------------------------------------------------------- /oiasg_gui/lib/controls.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import pyglet 5 | 6 | class Posattr(object): 7 | def __init__(self,x = (0,0), y = (0,0), width = (1,0), height = (1,0)): 8 | self.x = x 9 | self.y = y 10 | self.width = width 11 | self.height = height 12 | def __call__(self,x,y,width,height): 13 | def c_h(p): 14 | return int(width*p[0]+p[1]) 15 | def c_v(p): 16 | return int(height*p[0]+p[1]) 17 | return x+c_h(self.x),y+c_v(self.y),c_h(self.width),c_v(self.height) 18 | 19 | # 精灵(用于控件) 20 | class Sprite(pyglet.sprite.Sprite): 21 | def show(self): 22 | self.visible = True 23 | def hide(self): 24 | self.visible = False 25 | def on_resize(self): 26 | pass 27 | @property 28 | def t_width(self): 29 | return self._texture.width 30 | @property 31 | def t_height(self): 32 | return self._texture.height 33 | 34 | # 控件 35 | class Control(pyglet.event.EventDispatcher): 36 | # x,y:控件位置 37 | # width,height:控件大小 38 | # visible:是否在显示 39 | def __init__(self, window = None, x = 0, y = 0, width = 1, height = 1, parent = None, pos = Posattr()): 40 | super(Control, self).__init__() 41 | # parent:控件的上级 42 | self.visible = False 43 | self.sons = [] 44 | self.window = window 45 | self.x = x 46 | self.y = y 47 | self.width = width 48 | self.height = height 49 | self.parent = parent 50 | self.pos = pos 51 | # 碰撞检测:坐标是否在控件的矩形区域之内(严格) 52 | def on_resize(self): 53 | pass 54 | def hit_test(self, x, y): 55 | return (self.x < x < self.x + self.width and 56 | self.y < y < self.y + self.height) 57 | def intersect(self,x,y,width,height): 58 | if x > self.x+self.width or self.x > x + width or y > self.y+height or self.y > y+height: 59 | return False 60 | return True 61 | # 显示和隐藏 62 | def show(self): 63 | for i in self.sons: 64 | i.show() 65 | self.visible = True 66 | def hide(self): 67 | for i in self.sons: 68 | i.hide() 69 | self.visible = False 70 | def _draw(self, x): 71 | if x is not None: 72 | x.draw() 73 | def draw(self): 74 | for i in self.sons: 75 | if i.visible and i.intersect(self.x,self.y,self.width,self.height): 76 | i.draw() 77 | def on_mouse_press(self, x, y, button, modifiers): 78 | for i in self.sons: 79 | if i.visible and i.hit_test(x,y): 80 | i.on_mouse_press(x, y, button, modifiers) 81 | # 事件处理句柄:在点击激活控件后跟踪后续事件 82 | def capture_events(self): 83 | if self.window is not None: 84 | self.window.push_handlers(self) 85 | def release_events(self): 86 | if self.window is not None: 87 | self.window.remove_handlers(self) 88 | Control.register_event_type('on_mouse_press') 89 | 90 | # 标签(用于控件) 91 | class Label(Control): 92 | def __init__(self, control, label = None): 93 | super(Label, self).__init__(*control) 94 | self.label = label 95 | self.on_resize() 96 | def set_text(self, x): 97 | self.label.text = x 98 | text = property(lambda self:self.label.text,set_text) 99 | def on_resize(self): 100 | super(Label, self).on_resize() 101 | if self.label is not None: 102 | self.label.x = self.x + self.width / 2 103 | self.label.y = self.y + self.height / 2 104 | def draw(self): 105 | super(Label, self).draw() 106 | self._draw(self.label) 107 | 108 | # 精灵控件 109 | class SpriteControl(Control): 110 | def __init__(self, control, image = None): 111 | super(SpriteControl, self).__init__(*control) 112 | self.image = image 113 | self.on_resize() 114 | def on_resize(self): 115 | super(SpriteControl, self).on_resize() 116 | if self.image is not None: 117 | self.image.update(x = self.x, y = self.y, scale_x = self.width / self.image.t_width , scale_y = self.height / self.image.t_height) 118 | def draw(self): 119 | super(SpriteControl, self).draw() 120 | self._draw(self.image) 121 | 122 | class Button(Control): 123 | # image:背景图片(Sprite类型) 124 | # icon:(左侧)图标(Sprite类型) 125 | # pressed_image:按下时的背景图片(Sprite类型) 126 | # label:文字(Lable/HTMLLable类型) 127 | # text:文字值 128 | # charged:是否被按下 129 | # direction:方向{0:图标靠左,1:图标靠右,2:图标靠上,3:图标靠下} 130 | 131 | # 按钮于按下到松开之间获取事件控制句柄 132 | charged = False 133 | def __init__(self, control, label = None, image = None, icon = None, pressed_image = None, direction = 0): 134 | super(Button, self).__init__(*control) 135 | self.label = label 136 | self.image = image 137 | self.icon = icon 138 | self.pressed_image = pressed_image 139 | self.direction = direction 140 | self.on_resize() 141 | def set_text(self, x): 142 | self.label.text = x 143 | text = property(lambda self:self.label.text,set_text) 144 | def on_resize(self): 145 | super(Button, self).on_resize() 146 | if self.image is not None: 147 | self.image.update(x = self.x, y = self.y, scale_x = self.width / self.image.t_width , scale_y = self.height / self.image.t_height) 148 | if self.pressed_image is not None: 149 | self.pressed_image.update(x = self.x, y = self.y, scale_x = self.width / self.pressed_image.t_width , scale_y = self.height / self.pressed_image.t_height) 150 | if self.icon is not None: 151 | if self.direction == 0: 152 | k = self.height / self.icon.t_height 153 | self.icon.update(x = self.x, y = self.y, scale = k) 154 | elif self.direction == 1: 155 | k = self.height / self.icon.t_height 156 | self.icon.update(x = self.x+self.width-k*self.icon.t_width, y = self.y, scale = k) 157 | elif self.direction == 2: 158 | k = self.width / self.icon.t_width 159 | self.icon.update(x = self.x, y = self.y+self.height-k*self.icon.t_height, scale = k) 160 | elif self.direction == 3: 161 | k = self.width / self.icon.t_width 162 | self.icon.update(x = self.x, y = self.y, scale = k) 163 | if self.label is not None: 164 | self.label.x = self.x + self.width / 2 165 | self.label.y = self.y + self.height / 2 166 | def draw_image(self): 167 | if self.charged: 168 | if self.pressed_image is not None: 169 | self.pressed_image.draw() 170 | elif self.image is not None: 171 | # self.image.color = (216,204,192) 172 | self.image.draw() 173 | else: 174 | if self.image is not None: 175 | # self.image.color = (255,255,255) 176 | self.image.draw() 177 | def draw(self): 178 | # print('drawn a button') 179 | super(Button, self).draw() 180 | self.draw_image() 181 | self._draw(self.label) 182 | self._draw(self.icon) 183 | def on_mouse_press(self, x, y, button, modifiers): 184 | # print('got mouse press') 185 | super(Button, self).on_mouse_press(x, y, button, modifiers) 186 | self.capture_events() 187 | self.dispatch_event('on_click') 188 | self.charged = True 189 | def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): 190 | # print('got mouse drag') 191 | self.charged = self.hit_test(x, y) 192 | def on_mouse_release(self, x, y, button, modifiers): 193 | # print('got mouse release') 194 | self.release_events() 195 | if self.hit_test(x, y): 196 | self.dispatch_event('on_press') 197 | self.charged = False 198 | def on_press(self): 199 | pass 200 | # on_press:从按钮松开时触发事件 201 | Button.register_event_type('on_click') 202 | Button.register_event_type('on_press') 203 | 204 | # 多外观按钮 205 | class SwitchButton(Button): 206 | def __init__(self, control, labels = None, images = None, icons = None, pressed_images = None, direction = 0): 207 | super(SwitchButton, self).__init__(control) 208 | self.labels = labels 209 | self.images = images 210 | self.icons = icons 211 | self.pressed_images = pressed_images 212 | self.direction = direction 213 | self.stage = 0 214 | def _get(self, x, id): 215 | if x is None: 216 | return None 217 | elif len(x) > id: 218 | return x[id] 219 | else: 220 | return None 221 | def set_stage(self, _stage): 222 | self._stage = _stage 223 | self.label = self._get(self.labels,self.stage) 224 | self.image = self._get(self.images,self.stage) 225 | self.icon = self._get(self.icons,self.stage) 226 | self.pressed_image = self._get(self.pressed_images,self.stage) 227 | self.on_resize() 228 | stage = property(lambda self:self._stage,set_stage) 229 | 230 | # 光标(不返回EVENT_HANDLED) 231 | class Caret(pyglet.text.caret.Caret): 232 | def on_mouse_press(self, x, y, button, modifiers): 233 | super(Caret, self).on_mouse_press(x, y, button, modifiers) 234 | 235 | # 文本框 236 | class TextBox(Control): 237 | # text:pyglet.text.document.UnformattedDocumentl类型,表示文本 238 | # editable:是否允许编辑 239 | # multiline:是否多行 240 | # back:背景,Sprite类型 241 | 242 | # layout:文本 243 | # caret:光标(文本的) 244 | def __init__(self, control, text = None, style = None, editable = False, multiline = False, back = None, padding = 0, select_backcolor = None, select_textcolor = None, caret_color = None): 245 | super(TextBox, self).__init__(*control) 246 | if text is None: 247 | text = '' 248 | if style is None: 249 | style = {} 250 | self.doc = pyglet.text.document.UnformattedDocument(text) 251 | self.doc.set_style(0, len(self.doc.text), style) 252 | self.editable = editable 253 | self.back = back 254 | self.padding = padding 255 | self.layout = pyglet.text.layout.IncrementalTextLayout( 256 | self.doc, self.width-padding*2, self.height-padding*2, multiline) 257 | if select_backcolor is not None: 258 | self.layout.selection_background_color = select_backcolor 259 | if select_textcolor is not None: 260 | self.layout.selection_color = select_textcolor 261 | self.layout.x = self.x + padding 262 | self.layout.y = self.y + padding 263 | self.caret = None 264 | if self.editable: 265 | self.caret = Caret(self.layout,color = (caret_color if caret_color is not None else (style['color'][:3] if style.get('color') else (0,0,0)))) 266 | self.on_resize() 267 | def set_text(self,x): 268 | self.doc.text = x 269 | text = property(lambda self:self.doc.text,set_text) 270 | def on_resize(self): 271 | super(TextBox, self).on_resize() 272 | if self.back is not None: 273 | self.back.update(x = self.x, y = self.y, scale_x = self.width / self.back.t_width , scale_y = self.height / self.back.t_height) 274 | if self.layout is not None: 275 | self.layout.x = self.x + self.padding 276 | self.layout.y = self.y + self.padding 277 | self.layout.width = self.width-self.padding*2 278 | self.layout.height = self.height-self.padding*2 279 | def draw(self): 280 | super(TextBox, self).draw() 281 | self._draw(self.back) 282 | self._draw(self.layout) 283 | def on_mouse_press(self, x, y, button, modifiers): 284 | # print('got mouse press') 285 | super(TextBox, self).on_mouse_press(x, y, button, modifiers) 286 | if self.window is not None and self.caret is not None: 287 | self.window.push_handlers(self.caret) 288 | 289 | class FormattedTextBox(TextBox): 290 | def __init__(self, control, doc = None, editable = False, multiline = False, back = None, padding = 0, select_backcolor = None, select_textcolor = None, caret_color = None): 291 | super(TextBox, self).__init__(*control) 292 | self.editable = editable 293 | self.back = back 294 | self.padding = padding 295 | self.multiline = multiline 296 | self.layout = None 297 | self.doc = doc 298 | self.layout.x = self.x + padding 299 | self.layout.y = self.y + padding 300 | 301 | if select_backcolor is not None: 302 | self.layout.selection_background_color = select_backcolor 303 | if select_textcolor is not None: 304 | self.layout.selection_color = select_textcolor 305 | self.caret = None 306 | if self.editable: 307 | self.caret = Caret(self.layout,color = (caret_color if caret_color is not None else (0,0,0))) 308 | self.on_resize() 309 | def set_doc(self, doc): 310 | self._doc = doc 311 | if doc is not None: 312 | self.layout = pyglet.text.layout.IncrementalTextLayout( 313 | self.doc, self.width-self.padding*2, self.height-self.padding*2, self.multiline) 314 | doc = property(lambda self:self._doc,set_doc) 315 | 316 | # 进度条 317 | class ProgressBar(Control): 318 | # label:文字标签 319 | # back:背景图片 320 | # bar:进度条图片(注意:缩放) 321 | # bar_sizerate:进度条图片占比(left,bottom,width,height,以比例计) 322 | # direction:{0:从左到右,1:从右到左,2:从下到上,3:从上到下} 323 | def __init__(self, control, label = None, back = None, bar = None, bar_sizerate = (0,0,1,1), direction = 0, rate = 1): 324 | super(ProgressBar, self).__init__(*control) 325 | self.label = label 326 | self.back = back 327 | self.bar = bar 328 | self.bar_sizerate = bar_sizerate 329 | self.direction = direction 330 | self.rate = rate 331 | def set_rate(self, x): 332 | self._rate = x 333 | self.on_resize() 334 | rate = property(lambda self:self._rate,set_rate) 335 | def on_resize(self): 336 | super(ProgressBar, self).on_resize() 337 | if self.back is not None: 338 | self.back.update(x = self.x, y = self.y, scale_x = self.width / self.back.t_width , scale_y = self.height / self.back.t_height) 339 | if self.bar is not None: 340 | K = self.bar_sizerate 341 | ra = self._rate 342 | L,R,U,D = self.x + self.width*K[0],self.x + self.width*(K[0]+K[2]),self.y + self.height*(K[1]+K[3]),self.y + self.height*K[1] 343 | if self.direction == 0: 344 | self.bar.update(x = L, y = D, scale_x = (R-L)*ra/self.bar.t_width, scale_y = (U-D)/self.bar.t_height) 345 | elif self.direction == 1: 346 | self.bar.update(x = R-(R-L)*ra/self.bar.t_width, y = D, scale_x = (R-L)*ra/self.bar.t_width, scale_y = (U-D)/self.bar.t_height) 347 | elif self.direction == 2: 348 | self.bar.update(x = L, y = D, scale_x = (R-L)/self.bar.t_width, scale_y = (U-D)*ra/self.bar.t_height) 349 | elif self.direction == 3: 350 | self.bar.update(x = L, y = U-(U-D)*ra/self.height, scale_x = (R-L)/self.bar.t_width, scale_y = (U-D)*ra/self.bar.t_height) 351 | if self.label is not None: 352 | self.label.x = self.x + self.width / 2 353 | self.label.y = self.y + self.height / 2 354 | def set_text(self,x): 355 | self.label.text = x 356 | text = property(lambda self:self.label.text,set_text) 357 | def draw(self): 358 | super(ProgressBar, self).draw() 359 | self._draw(self.back) 360 | self._draw(self.bar) 361 | self._draw(self.label) 362 | 363 | # 水平滚动条 364 | class Slider(Control): 365 | # image:背景图片(Sprite类型) 366 | # cursor:游标(Sprite类型) 367 | 368 | # 游标于按下到松开之间获取事件控制句柄 369 | def __init__(self, control, image = None, cursor = None, rate = 1): 370 | super(Slider, self).__init__(*control) 371 | self.image = image 372 | self.cursor = cursor 373 | self.rate = rate 374 | def set_rate(self, x): 375 | x = max(0,min(x,1)) 376 | self._rate = x 377 | self.on_resize() 378 | rate = property(lambda self:self._rate,set_rate) 379 | def on_resize(self): 380 | super(Slider, self).on_resize() 381 | if self.image is not None: 382 | self.image.update(x = self.x, y = self.y + self.height/2 - self.image.t_height/2, scale_x = self.width / self.image.t_width) 383 | if self.cursor is not None: 384 | k = self.height / self.cursor.t_height 385 | self.cursor.update(x = self.x + self.rate*(self.width - k * self.cursor.t_width), y = self.y, scale = k) 386 | def draw(self): 387 | super(Slider, self).draw() 388 | self._draw(self.image) 389 | self._draw(self.cursor) 390 | def on_mouse_press(self, x, y, button, modifiers): 391 | # print('got mouse press') 392 | super(Slider, self).on_mouse_press(x, y, button, modifiers) 393 | self.rate = (x-self.x-self.cursor.width/2)/max(1,self.width-self.cursor.width) 394 | self.capture_events() 395 | self.dispatch_event('on_begin_scroll') 396 | self.dispatch_event('on_change', self.rate) 397 | def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): 398 | self.rate = (x-self.x-self.cursor.width/2)/max(1,self.width-self.cursor.width) 399 | self.dispatch_event('on_change', self.rate) 400 | def on_mouse_release(self, x, y, button, modifiers): 401 | self.release_events() 402 | self.dispatch_event('on_end_scroll') 403 | def on_change(self,val): 404 | # print(val) 405 | pass 406 | 407 | Slider.register_event_type('on_begin_scroll') 408 | Slider.register_event_type('on_end_scroll') 409 | Slider.register_event_type('on_change') 410 | 411 | # 垂直滚动条 412 | class ScrollBar(Slider): 413 | def on_resize(self): 414 | super(Slider, self).on_resize() 415 | if self.image is not None: 416 | self.image.update(x = self.x + self.width/2 - self.image.t_width/2, y = self.y, scale_y = self.height / self.image.t_height) 417 | if self.cursor is not None: 418 | k = self.width / self.cursor.t_width 419 | self.cursor.update(x = self.x, y = self.y + (1-self.rate)*(self.height - k * self.cursor.t_height), scale = k) 420 | def on_mouse_press(self, x, y, button, modifiers): 421 | # print('got mouse press') 422 | super(Slider, self).on_mouse_press(x, y, button, modifiers) 423 | self.rate = 1-(y-self.y-self.cursor.height/2)/max(1,self.height-self.cursor.height) 424 | self.capture_events() 425 | self.dispatch_event('on_begin_scroll') 426 | self.dispatch_event('on_change', self.rate) 427 | def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers): 428 | self.rate = 1-(y-self.y-self.cursor.height/2)/max(1,self.height-self.cursor.height) 429 | self.dispatch_event('on_change', self.rate) 430 | 431 | # 框架(控件组及布局容器) 432 | class Frame(Control): 433 | def __init__(self, control): 434 | super(Frame, self).__init__(*control) 435 | self.on_resize() 436 | def on_resize(self): 437 | # print(self.x,self.y,self.height,self.width) 438 | super(Frame, self).on_resize() 439 | for i in self.sons: 440 | i.x , i.y , i.width ,i.height = i.pos(self.x,self.y,self.width,self.height) 441 | i.on_resize() 442 | 443 | # 视口 444 | class Viewport(Frame): 445 | def draw(self): 446 | t = pyglet.image.get_buffer_manager().get_color_buffer().get_texture() 447 | super(Viewport, self).draw() 448 | f = pyglet.image.get_buffer_manager().get_color_buffer().get_region(self.x,self.y,self.width,self.height).get_texture() 449 | t.blit(0,0) 450 | f.blit(self.x,self.y) 451 | 452 | # 自动布局框架 453 | class LayoutFrame(Frame): 454 | _layouter = None 455 | def relayout(self): 456 | self.layouter(self) 457 | def set_layouter(self, layouter): 458 | self._layouter = layouter 459 | self.relayout() 460 | layouter = property(lambda self:self._layouter,set_layouter) 461 | 462 | # 图片框架 463 | class ImageFrame(Frame): 464 | # back:背景图片(AbstractImage) 465 | # front:前景图片(AbstractImage) 466 | def __init__(self, control, back = None, front = None): 467 | self.back = back 468 | self.front = front 469 | super(ImageFrame, self).__init__(control) 470 | def draw(self): 471 | self._draw(self.back) 472 | super(ImageFrame, self).draw() 473 | self._draw(self.front) 474 | def on_resize(self): 475 | super(ImageFrame, self).on_resize() 476 | if self.back is not None: 477 | self.back.update(x = self.x, y = self.y, scale_x = self.width / self.back.t_width , scale_y = self.height / self.back.t_height) 478 | if self.front is not None: 479 | self.front.update(x = self.x, y = self.y, scale_x = self.width / self.front.t_width , scale_y = self.height / self.front.t_height) 480 | 481 | def ScrollTextBox_defaultlayout(self): 482 | SCROLL_BAR_WIDTH = 20 483 | if self.scrollbar is not None: 484 | self.scrollbar.pos = Posattr((1,-SCROLL_BAR_WIDTH),(0,0),(0,SCROLL_BAR_WIDTH),(1,0)) 485 | if self.doc is not None: 486 | self.doc.pos = Posattr((0,0),(0,0),(1,-SCROLL_BAR_WIDTH),(1,0)) 487 | class ScrollTextBox(LayoutFrame): 488 | def __init__(self, control, doc = None, scrollbar = None, layouter = ScrollTextBox_defaultlayout): 489 | super(ScrollTextBox, self).__init__(control) 490 | self._layouter = layouter 491 | self._doc = doc 492 | self._scrollbar = scrollbar 493 | self.doc = doc 494 | self.scrollbar = scrollbar 495 | self.layouter = layouter 496 | self.on_resize() 497 | iskey = lambda self, x: x is self.scrollbar or x is self.doc 498 | def set_text(self,x): 499 | if self.doc is not None: 500 | self.doc.text = x 501 | text = property(lambda self:self.doc.text if self.doc is not None else None,set_text) 502 | def set_doc(self,doc): 503 | self._doc = doc 504 | if doc is not None and doc not in self.sons: 505 | self.sons.append(doc) 506 | self.sons = list(filter(self.iskey,self.sons)) 507 | self.relayout() 508 | doc = property(lambda self:self._doc, set_doc) 509 | def set_scrollbar(self,scrollbar): 510 | self._scrollbar = scrollbar 511 | if scrollbar is not None: 512 | if scrollbar not in self.sons: 513 | self.sons.append(scrollbar) 514 | if self.doc is not None and self.doc.layout is not None: 515 | def f(event): 516 | def g(*args, **kw): 517 | self.doc.layout.ensure_line_visible(min(max(int(args[0]*self.doc.layout.get_line_count()),0),self.doc.layout.get_line_count()-1)) 518 | return event(*args, **kw) 519 | return g 520 | self.scrollbar.on_change = f(self.scrollbar.on_change) 521 | self.sons = list(filter(self.iskey,self.sons)) 522 | self.relayout() 523 | scrollbar = property(lambda self:self._scrollbar,set_scrollbar) 524 | 525 | def ButtonSlider_defaultlayout(self): 526 | PADDING_RATE = 0.2 527 | HPADDING_RATE = 0.5 528 | VPADDING_RATE = 0.15 529 | rate = 1/(len(self.sons)*(1+PADDING_RATE)-PADDING_RATE+2*HPADDING_RATE) 530 | padding_rate = PADDING_RATE * rate 531 | hpadding_rate = HPADDING_RATE * rate 532 | cur_t = hpadding_rate 533 | for i in self.sons: 534 | i.pos = Posattr((cur_t,0),(VPADDING_RATE,0),(rate,0),(1-VPADDING_RATE*2,0)) 535 | cur_t += rate + padding_rate 536 | # 按钮条 537 | class ButtonSlider(ImageFrame, LayoutFrame): 538 | def __init__(self, control, back = None, front = None, buttons = None, layouter = ButtonSlider_defaultlayout): 539 | super(ButtonSlider, self).__init__(control, back, front) 540 | self.layouter = layouter 541 | self.val = 0 542 | if buttons is not None: 543 | self.buttons = buttons 544 | def set_buttons(self, v): 545 | # print('set_buttons') 546 | self.sons = v 547 | for i in range(len(self.sons)): 548 | def g(i): 549 | def f(): 550 | self.val = i 551 | return f 552 | self.sons[i].on_press = g(i+1) 553 | self.relayout() 554 | buttons = property(lambda self:self.sons,set_buttons) 555 | def set_val(self, v): 556 | self._val = v 557 | for i in range(min(v,len(self.sons))): 558 | self.sons[i].stage = 0 559 | for i in range(v,len(self.sons)): 560 | self.sons[i].stage = 1 561 | self.dispatch_event('on_change',self._val) 562 | val = property(lambda self:self._val,set_val) 563 | def on_change(self, val): 564 | pass 565 | ButtonSlider.register_event_type('on_change') 566 | 567 | # 交互式事件窗口 568 | class MessageInteractor(ImageFrame): 569 | def set_submit_key_event(self, event): 570 | obj, eventname = event 571 | # print('set_submit_key_event') 572 | def f(event): 573 | def g(*args, **kw): 574 | self.dispatch_event('on_submit') 575 | # print('on_submit_') 576 | return event(*args, **kw) 577 | return g 578 | setattr(obj, eventname ,f(getattr(obj, eventname))) 579 | self._submit_key = getattr(obj, eventname) 580 | def on_submit(self): 581 | # print('on_submit') 582 | self.hide() 583 | submit_key = property(lambda self:self._submit_key,set_submit_key_event) 584 | MessageInteractor.register_event_type('on_submit') 585 | 586 | def AlertBox_defaultlayout(self): 587 | BUTTON_HEIGHT = 30 588 | BUTTON_BLANKING = 10 589 | PADDING = 20 590 | TITLE_PADDING = 20 591 | TITLE_HEIGHT = 30 592 | if self.title is not None: 593 | self.title.pos = Posattr((0.5,0),(1,-TITLE_PADDING-TITLE_HEIGHT/2),(0,0),(0,0)) 594 | cur_h = PADDING 595 | if self.button is not None: 596 | self.button.pos = Posattr((0.2,PADDING),(0,cur_h),(0.6,-2*PADDING),(0,BUTTON_HEIGHT)) 597 | cur_h += BUTTON_HEIGHT + BUTTON_BLANKING 598 | if self.doc is not None: 599 | self.doc.pos = Posattr((0,PADDING),(0,cur_h),(1,-2*PADDING),(1,-cur_h-TITLE_PADDING-TITLE_HEIGHT)) 600 | class AlertBox(MessageInteractor, LayoutFrame): 601 | def __init__(self, control, back = None, front = None, title = Label(()), doc = None, button = None, layouter = AlertBox_defaultlayout): 602 | super(AlertBox, self).__init__(control, back, front) 603 | self._layouter = layouter 604 | self._title = None 605 | self._doc = None 606 | self._button = None 607 | self.title = title 608 | self.doc = doc 609 | self.button = button 610 | self.relayout() 611 | self.on_resize() 612 | # 注意:请不要多次设置button,否则可能导致on_submit事件触发多次 613 | iskey = lambda self, x: x is self.title or x is self.doc or x is self.button 614 | def set_button(self, button): 615 | self._button = button 616 | if button is not None: 617 | if button not in self.sons: 618 | self.sons.append(button) 619 | self.submit_key = (button, 'on_press') 620 | self.sons = list(filter(self.iskey,self.sons)) 621 | self.relayout() 622 | button = property(lambda self:self._button, set_button) 623 | def set_text(self,x): 624 | if self.doc is not None: 625 | self.doc.text = x 626 | text = property(lambda self:self.doc.text if self.doc is not None else None,set_text) 627 | def set_title_text(self,x): 628 | if self.title is not None: 629 | self.title.text = x 630 | title_text = property(lambda self:self.title.text if self.title is not None else None,set_title_text) 631 | def set_title(self,title): 632 | self._title = title 633 | if title is not None and title not in self.sons: 634 | self.sons.append(title) 635 | self.sons = list(filter(self.iskey,self.sons)) 636 | self.relayout() 637 | title = property(lambda self:self._title, set_title) 638 | def set_doc(self,doc): 639 | self._doc = doc 640 | if doc is not None and doc not in self.sons: 641 | self.sons.append(doc) 642 | self.sons = list(filter(self.iskey,self.sons)) 643 | self.relayout() 644 | doc = property(lambda self:self._doc, set_doc) 645 | 646 | def MessageBox_defaultlayout(self): 647 | BUTTON_HEIGHT = 30 648 | BUTTON_BLANKING = 10 649 | PADDING = 20 650 | TITLE_PADDING = 20 651 | TITLE_HEIGHT = 30 652 | if self.title is not None: 653 | self.title.pos = Posattr((0.5,0),(1,-TITLE_PADDING-TITLE_HEIGHT/2),(0,0),(0,0)) 654 | cur_h = PADDING 655 | if self.buttons is not None: 656 | for i in range(len(self.buttons)): 657 | self.buttons[i].pos = Posattr((0.2,PADDING),(0,cur_h),(0.6,-2*PADDING),(0,BUTTON_HEIGHT)) 658 | cur_h += BUTTON_HEIGHT + BUTTON_BLANKING 659 | if self.doc is not None: 660 | self.doc.pos = Posattr((0,PADDING),(0,cur_h),(1,-2*PADDING),(1,-cur_h-TITLE_PADDING-TITLE_HEIGHT)) 661 | # 提示选择框(含交互) 662 | class MessageBox(MessageInteractor, LayoutFrame): 663 | def __init__(self, control, back = None, front = None, title = None, doc = None, buttons = None, layouter = MessageBox_defaultlayout): 664 | super(MessageBox, self).__init__(control, back, front) 665 | self._layouter = layouter 666 | self._title = None 667 | self._doc = None 668 | self._buttons = None 669 | self.title = title 670 | self.doc = doc 671 | self.buttons = buttons if buttons is not None else [] 672 | self.on_resize() 673 | self.result = 0 674 | # 注意:请不要多次设置buttons,否则可能导致on_submit事件触发多次 675 | iskey = lambda self, x: x is self.title or x is self.doc or x in self.buttons 676 | def set_buttons(self, buttons): 677 | self._buttons = buttons 678 | for button in buttons: 679 | if button not in self.sons: 680 | self.sons.append(button) 681 | self.sons = list(filter(self.iskey,self.sons)) 682 | def f(event, id): 683 | def g(*args, **kw): 684 | self.result = id 685 | self.dispatch_event('on_submit', self.result) 686 | return event(*args, **kw) 687 | return g 688 | if buttons is not None: 689 | for i in range(len(buttons)): 690 | buttons[i].on_press = f(buttons[i].on_press, i) 691 | self.relayout() 692 | buttons = property(lambda self:self._buttons, set_buttons) 693 | def set_text(self,x): 694 | if self.doc is not None: 695 | self.doc.text = x 696 | text = property(lambda self:self.doc.text if self.doc is not None else None,set_text) 697 | def set_title_text(self,x): 698 | if self.title is not None: 699 | self.title.text = x 700 | title_text = property(lambda self:self.title.text if self.title is not None else None,set_title_text) 701 | def set_title(self,title): 702 | self._title = title 703 | if title is not None and title not in self.sons: 704 | self.sons.append(title) 705 | self.sons = list(filter(self.iskey,self.sons)) 706 | self.relayout() 707 | title = property(lambda self:self._title, set_title) 708 | def set_doc(self,doc): 709 | self._doc = doc 710 | if doc is not None and doc not in self.sons: 711 | self.sons.append(doc) 712 | self.sons = list(filter(self.iskey,self.sons)) 713 | self.relayout() 714 | doc = property(lambda self:self._doc, set_doc) 715 | def on_submit(self, result): 716 | # print(result) 717 | self.hide() 718 | 719 | # 提示输入框(含交互) 720 | class MessageInput(AlertBox): 721 | # editable 722 | def set_submit_key_event(self, event): 723 | obj, eventname = event 724 | # print('set_submit_key_event') 725 | def f(event): 726 | def g(*args, **kw): 727 | self.dispatch_event('on_submit', self.text) 728 | # print('on_submit_') 729 | return event(*args, **kw) 730 | return g 731 | setattr(obj, eventname ,f(getattr(obj, eventname))) 732 | self._submit_key = getattr(obj, eventname) 733 | def on_submit(self, text): 734 | # print('on_submit:%s' % text) 735 | self.hide() 736 | submit_key = property(lambda self:self._submit_key,set_submit_key_event) 737 | 738 | def MessagePage_defaultlayout(self): 739 | return MessageBox_defaultlayout(self) 740 | # 待填 741 | 742 | # 事件页面 743 | # 布局待设计 …… 744 | class MessagePage(MessageBox): 745 | def __init__(self, control, back = None, front = None, title = Label(()), doc = TextBox((),'',{}), buttons = None, layouter = MessagePage_defaultlayout): 746 | super(MessagePage, self).__init__(control, back, front, title, doc, buttons, layouter) 747 | 748 | def TagPages_defaultlayoutV(self): 749 | TAG_WIDTH = 90 750 | TAG_PADDING = 5 751 | tag_c = TAG_PADDING*(len(self.pages)+1)/max(1,len(self.pages)) 752 | tag_k = 1/max(1,len(self.pages)) 753 | cur_k = 0 754 | cur_h = TAG_PADDING 755 | for i in range(len(self.pages)): 756 | self.pages[i][0].pos = Posattr((0,0),(cur_k,cur_h),(0,TAG_WIDTH),(tag_k,-tag_c)) 757 | cur_k += tag_k 758 | cur_h += - tag_c + TAG_PADDING 759 | self.pages[i][1].pos = Posattr((0,TAG_WIDTH),(0,0),(1,-TAG_WIDTH),(1,0)) 760 | 761 | def TagPages_defaultlayoutH(self): 762 | TAG_HEIGHT = 30 763 | TAG_PADDING = 5 764 | tag_c = TAG_PADDING*(len(self.pages)+1)/max(1,len(self.pages)) 765 | tag_k = 1/max(1,len(self.pages)) 766 | cur_k = 0 767 | cur_w = TAG_PADDING 768 | for i in range(len(self.pages)): 769 | self.pages[i][0].pos = Posattr((cur_k,cur_w),(1,-TAG_HEIGHT),(tag_k,-tag_c),(0,TAG_HEIGHT)) 770 | cur_k += tag_k 771 | cur_w += - tag_c + TAG_PADDING 772 | self.pages[i][1].pos = Posattr((0,0),(0,0),(1,0),(1,-TAG_HEIGHT)) 773 | 774 | # 带标签的页面 775 | class TagPages(LayoutFrame): 776 | def __init__(self, control, pages = None, layouter = TagPages_defaultlayoutV): 777 | super(TagPages, self).__init__(control) 778 | self._layouter = layouter 779 | self.pages = pages if pages is not None else [] 780 | def set_pages(self, pages): 781 | # print('set_buttons') 782 | self._pages = pages 783 | self.sons = [] 784 | for i in range(len(pages)): 785 | def g(i): 786 | def f(): 787 | self.page = i 788 | return f 789 | pages[i][0].on_press = g(i) 790 | self.sons += pages[i] 791 | self.relayout() 792 | self.page = 0 793 | pages = property(lambda self:self._pages,set_pages) 794 | def set_page(self, page): 795 | self._page = page 796 | for i in range(len(self.pages)): 797 | if i == page: 798 | self.pages[i][0].stage = 1 799 | if self.visible: 800 | self.pages[i][1].show() 801 | else: 802 | self.pages[i][0].stage = 0 803 | self.pages[i][1].hide() 804 | self.dispatch_event('on_switch',self.page) 805 | page = property(lambda self:self._page,set_page) 806 | def show(self): 807 | super(TagPages, self).show() 808 | for i in range(len(self.pages)): 809 | if i != self.page: 810 | self.pages[i][1].hide() 811 | def on_switch(self, page): 812 | # print('on switch:%d' % page) 813 | pass 814 | TagPages.register_event_type('on_switch') 815 | 816 | # 科技树 817 | # 也许不应该放在这里 …… 818 | # class TechTree(Frame): 819 | # class TechTreeNode(object): 820 | # pass 821 | # pass 822 | 823 | class Form(pyglet.window.Window): 824 | def __init__(self, width=None, height=None, caption=None, resizable=False, style=None, fullscreen=False, visible=True, vsync=True, display=None, screen=None, config=None, context=None, mode=None): 825 | super(Form, self).__init__(width, height, caption, resizable, style, fullscreen, visible, vsync, display, screen, config, context, mode) 826 | 827 | self.root_control = Frame((self,0,0,width,height)) 828 | # self.root_control.capture_events() 829 | def on_draw(self): 830 | pyglet.gl.glClearColor(1, 1, 1, 1) 831 | pyglet.gl.glClear(pyglet.gl.GL_COLOR_BUFFER_BIT) 832 | self.clear() 833 | self.root_control.draw() 834 | def on_mouse_press(self, x, y, symbol, modifiers): 835 | # 按下鼠标时清除所有控件句柄 836 | self.remove_handlers() 837 | # print('removed handlers') 838 | self.root_control.on_mouse_press(x, y, symbol, modifiers) 839 | def draw(self): 840 | self.clear() 841 | self.root_control.draw() 842 | def show(self): 843 | self.root_control.show() 844 | def hide(self): 845 | self.root_control.hide() -------------------------------------------------------------------------------- /oiasg_gui/resource/Button.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/Button.wav -------------------------------------------------------------------------------- /oiasg_gui/resource/CLICK_01.WAV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/CLICK_01.WAV -------------------------------------------------------------------------------- /oiasg_gui/resource/ball.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/ball.bmp -------------------------------------------------------------------------------- /oiasg_gui/resource/ball.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/ball.wav -------------------------------------------------------------------------------- /oiasg_gui/resource/ball2.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/ball2.bmp -------------------------------------------------------------------------------- /oiasg_gui/resource/bgm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/bgm.mp3 -------------------------------------------------------------------------------- /oiasg_gui/resource/bslider.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/bslider.png -------------------------------------------------------------------------------- /oiasg_gui/resource/progressh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/progressh.png -------------------------------------------------------------------------------- /oiasg_gui/resource/scroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/scroll.png -------------------------------------------------------------------------------- /oiasg_gui/resource/sliderf0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/sliderf0.png -------------------------------------------------------------------------------- /oiasg_gui/resource/sliderf1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/sliderf1.png -------------------------------------------------------------------------------- /oiasg_gui/resource/t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/t.png -------------------------------------------------------------------------------- /oiasg_gui/resource/tbut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/tbut.png -------------------------------------------------------------------------------- /oiasg_gui/resource/tframe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/tframe.png -------------------------------------------------------------------------------- /oiasg_gui/resource/tico.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/tico.png -------------------------------------------------------------------------------- /oiasg_gui/resource/walk.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/walk.gif -------------------------------------------------------------------------------- /oiasg_gui/resource/y.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_gui/resource/y.png -------------------------------------------------------------------------------- /oiasg_gui/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import copy 5 | import random 6 | import time 7 | 8 | import pyglet 9 | from lib import * 10 | 11 | # pyglet.clock.set_default(pyglet.clock.Clock()) 12 | fps_display = pyglet.clock.ClockDisplay() 13 | 14 | pyglet.resource.path = ['resource'] 15 | 16 | window = controls.Form(800,600,resizable = True) 17 | root = window.root_control 18 | def on_draw(): 19 | window.clear() 20 | root.draw() 21 | fps_display.draw() 22 | window.on_draw = on_draw 23 | 24 | @window.event 25 | def on_resize(width, height): 26 | root.width = width 27 | root.height = height 28 | root.on_resize() 29 | # mv = pyglet.resource.media('tmp4.mp4', streaming=False) 30 | # mv.play() 31 | 32 | tbut_img = pyglet.resource.image('tbut.png') 33 | root.sons = [ 34 | controls.ImageFrame( 35 | (window,0,0,800,600,root), 36 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 37 | front = controls.Sprite(pyglet.resource.image('tframe.png')) 38 | ) 39 | , 40 | controls.Button( 41 | (window,25,15,150,30,root,controls.Posattr((0,25),(0,15),(0,150),(0,30))), 42 | pyglet.text.Label('隐藏其它',font_name='微软雅黑',font_size=16,anchor_x = 'center',anchor_y = 'center'), 43 | controls.Sprite(pyglet.resource.image('tbut.png')), 44 | controls.Sprite(pyglet.resource.image('tico.png')), 45 | controls.Sprite(pyglet.resource.image('t.png')) 46 | ) 47 | ] 48 | f1,button0 = root.sons 49 | f1.sons = [ 50 | controls.Viewport((window,0,0,1,1,f1,controls.Posattr((0.1,0),(0.1,0),(0.8,0),(0.8,0)))) 51 | ] 52 | vport = f1.sons[0] 53 | gbutton = lambda:controls.Button( 54 | (window,25,15,150,30), 55 | pyglet.text.Label('提交',font_name='黑体',font_size=16,anchor_x = 'center',anchor_y = 'center'), 56 | controls.Sprite(pyglet.resource.image('tbut.png')), 57 | controls.Sprite(pyglet.resource.image('tico.png')) 58 | ) 59 | gtitle = lambda:controls.Label( 60 | [window], 61 | pyglet.text.Label( 62 | 'TITLE',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center') 63 | ) 64 | gtxtbox = lambda:controls.TextBox( 65 | [window], 66 | '''这是一个多行文本框 67 | qwq''', 68 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 69 | editable = False,multiline = True, 70 | back = controls.Sprite(pyglet.resource.animation('walk.gif')),select_backcolor = (0, 0, 200, 127) 71 | ) 72 | def gdoc(): 73 | doc = pyglet.text.document.FormattedDocument('''这是一个可编辑的多行文本框 74 | qwq''') 75 | doc.set_style(0, len(doc.text)-4, {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}) 76 | return doc 77 | geditbox = lambda:controls.FormattedTextBox( 78 | [window], 79 | gdoc(), 80 | editable = True,multiline = True, 81 | back = controls.Sprite(pyglet.resource.animation('walk.gif')),select_backcolor = (0, 0, 200, 127) 82 | ) 83 | gsbutton = lambda:controls.SwitchButton( 84 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,300),(0,150),(0,30))), 85 | [ 86 | pyglet.text.Label('switch0',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center'), 87 | pyglet.text.Label('switch1',font_size=16,color = (0,255,0,255),bold = True,anchor_x = 'center',anchor_y = 'center') 88 | ] 89 | , 90 | [ 91 | controls.Sprite(pyglet.resource.image('tbut.png')), 92 | controls.Sprite(pyglet.resource.animation('walk.gif')) 93 | ] 94 | , 95 | [ 96 | controls.Sprite(pyglet.resource.image('tico.png')) 97 | ] 98 | , 99 | direction = 1 100 | ) 101 | gscrollbar = lambda:controls.ScrollBar( 102 | (window,25,380,150,30,vport,controls.Posattr((0,25),(0,380),(0,20),(0,120))), 103 | image = controls.Sprite(pyglet.resource.image('scroll.png')), 104 | cursor = controls.Sprite(pyglet.resource.image('sliderf1.png')) 105 | ) 106 | vport.sons = [ 107 | controls.Button( 108 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,55),(0,150),(0,30))), 109 | pyglet.text.Label('+=10%',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center'), 110 | controls.Sprite(pyglet.resource.image('tbut.png')), 111 | controls.Sprite(pyglet.resource.image('tico.png')) 112 | ), 113 | controls.TextBox( 114 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,100),(0,150),(0,150))), 115 | '''这是一个多行文本框 116 | qwq''', 117 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 118 | editable = False,multiline = True, 119 | back = controls.Sprite(pyglet.resource.animation('walk.gif')),select_backcolor = (0, 0, 200, 127) 120 | ) 121 | , 122 | controls.ProgressBar( 123 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,265),(0,150),(0,20))), 124 | pyglet.text.Label('%',font_size=14,bold = True,anchor_x = 'center',anchor_y = 'center'), 125 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 126 | bar = controls.Sprite(pyglet.resource.image('progressh.png')), bar_sizerate = (0.05,0.2,0.9,0.6), 127 | direction = 0, 128 | rate = 1 129 | ) 130 | , 131 | gsbutton() 132 | , 133 | controls.ButtonSlider( 134 | (window,25,340,150,30,vport,controls.Posattr((0,25),(0,340),(0,150),(0,30))), 135 | back = controls.Sprite(pyglet.resource.image('bslider.png')) 136 | ) 137 | , 138 | controls.MessageInteractor( 139 | (window,0,0,800,600,vport,controls.Posattr((0,200),(0,30),(0,250),(0,250))), 140 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 141 | front = controls.Sprite(pyglet.resource.image('tframe.png')) 142 | ) 143 | , 144 | controls.Label( 145 | (window,0,0,1,1,vport,controls.Posattr((0.5,0),(0.8,0),(0,0),(0,0))), 146 | pyglet.text.Label( 147 | 'SSSSSS',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center') 148 | ) 149 | , 150 | controls.SpriteControl( 151 | (window,0,0,1,1,vport,controls.Posattr((0.6,0),(0.8,0),(0.1,0),(0.1,0))), 152 | controls.Sprite(pyglet.resource.animation('walk.gif')) 153 | ) 154 | , 155 | controls.MessageBox( 156 | (window,0,0,800,600,vport,controls.Posattr((0,480),(0,30),(0,250),(0,450))), 157 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 158 | title = gtitle(), 159 | doc = gtxtbox() 160 | ) 161 | , 162 | controls.AlertBox( 163 | (window,0,0,800,600,vport,controls.Posattr((0,200),(0,300),(0,250),(0,150))), 164 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 165 | title = gtitle(), 166 | doc = gtxtbox(), 167 | button = gbutton() 168 | ) 169 | , 170 | controls.MessageInput( 171 | (window,0,0,800,600,vport,controls.Posattr((0,750),(0,30),(0,250),(0,150))), 172 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 173 | title = gtitle(), 174 | doc = geditbox(), 175 | button = gbutton() 176 | ) 177 | , 178 | gscrollbar() 179 | , 180 | controls.TagPages( 181 | (window,0,0,800,600,vport,controls.Posattr((0,750),(0,200),(0,250),(0,200))), 182 | layouter = controls.TagPages_defaultlayoutH 183 | ) 184 | ] 185 | 186 | button1,txtbox1,prog,sbutton0,slider0,msg,lbl,img,msg1,alrt,inp,sld0,tagp = vport.sons 187 | 188 | tagp.pages = [ 189 | (gsbutton(),controls.ScrollTextBox([window],geditbox(),gscrollbar())), 190 | (gsbutton(),geditbox()), 191 | (gsbutton(),gbutton()), 192 | (gsbutton(),gsbutton()), 193 | (gsbutton(),gtxtbox()) 194 | ] 195 | slider0.buttons = [ 196 | controls.SwitchButton( 197 | (window,0,0,1,1,slider0), 198 | images = [ 199 | controls.Sprite(pyglet.resource.image('sliderf0.png')), 200 | controls.Sprite(pyglet.resource.image('sliderf1.png')) 201 | ] 202 | ) 203 | for i in range(10) 204 | ] 205 | msg.sons = [ 206 | controls.Button( 207 | (window,25,15,150,30,root,controls.Posattr((0,50),(0,30),(0,150),(0,30))), 208 | pyglet.text.Label('提交',font_name='微软雅黑',font_size=16,anchor_x = 'center',anchor_y = 'center'), 209 | controls.Sprite(pyglet.resource.image('tbut.png')), 210 | controls.Sprite(pyglet.resource.image('tico.png')) 211 | ) 212 | , 213 | controls.TextBox( 214 | (window,0,0,1,1,vport,controls.Posattr((0,50),(0,65),(0,150),(0,150))), 215 | '''写在这里的文字会提交到左侧''', 216 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 217 | editable = True,multiline = True, 218 | back = controls.Sprite(pyglet.resource.animation('walk.gif')),select_backcolor = (0, 0, 200, 127) 219 | ) 220 | ] 221 | submitb,intertxt = msg.sons 222 | msg.submit_key = (submitb, 'on_press') 223 | 224 | msg1.buttons = [gbutton(),gbutton(),gbutton()] 225 | # button1.label.text = '111' 226 | # print(button1.text) 227 | # button1.text = '11' 228 | BALL_SOUND = pyglet.resource.media('ball.wav', streaming=False) 229 | BGM = pyglet.resource.media('bgm.mp3', streaming=False) 230 | bgm_player = BGM.play() 231 | 232 | # def lop(): 233 | # print('23') 234 | # bgm_player.queue(BGM) 235 | # bgm_player.next_source() 236 | # bgm_player.on_source_group_eos = lop 237 | 238 | def onp(): 239 | print('pressed button 0') 240 | BALL_SOUND.play() 241 | if button0.text == '隐藏其它': 242 | button0.text = '显示其它' 243 | bgm_player.pause() 244 | else: 245 | button0.text = '隐藏其它' 246 | bgm_player.play() 247 | if button1.visible: 248 | button1.hide() 249 | else: 250 | button1.show() 251 | if txtbox1.visible: 252 | txtbox1.hide() 253 | else: 254 | txtbox1.show() 255 | if prog.visible: 256 | prog.hide() 257 | else: 258 | prog.show() 259 | if vport.visible: 260 | vport.hide() 261 | else: 262 | vport.show() 263 | print(len(alrt.sons)) 264 | alrt.title = None 265 | alrt.doc = None 266 | alrt.button = None 267 | msg1.doc = None 268 | msg1.title = None 269 | window.set_fullscreen(not window.fullscreen) 270 | 271 | 272 | def onp1(): 273 | print('pressed button 1') 274 | # print(button1.text) 275 | # button1.text = '11' 276 | prog.rate = (prog.rate + 0.1 - (prog.rate + 0.1)// 1) 277 | prog.text = '%.1f%%' % (prog.rate*100) 278 | bgm_player.volume = prog.rate 279 | 280 | def onps(): 281 | print('pressed sbutton switch') 282 | sbutton0.stage ^= 1 283 | 284 | def onschange(val): 285 | print('slider changed:new val = %s' % val) 286 | 287 | def onsubmit(): 288 | print() 289 | print('submitted') 290 | msg.hide() 291 | txtbox1.text = intertxt.text 292 | 293 | # def onsubmit1(result): 294 | # print('submitted msg1') 295 | # msg1.hide() 296 | # print(msg1.result) 297 | 298 | @sld0.event 299 | def on_change(rate): 300 | lbl.pos.x = (rate,0) 301 | root.on_resize() 302 | button0.on_press = onp 303 | button1.on_press = onp1 304 | sbutton0.on_press = onps 305 | slider0.on_change = onschange 306 | msg.on_submit = onsubmit 307 | # msg1.on_submit = onsubmit1 308 | 309 | window.show() 310 | pyglet.app.run() 311 | -------------------------------------------------------------------------------- /oiasg_gui/test2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: UTF-8 -*- 3 | 4 | import copy 5 | import random 6 | import time 7 | 8 | import pyglet 9 | from lib import * 10 | 11 | 12 | fps_display = pyglet.clock.ClockDisplay() 13 | 14 | pyglet.resource.path = ['resource'] 15 | 16 | window = controls.Form(800,600,resizable = True) 17 | root = window.root_control 18 | 19 | bat = pyglet.graphics.Batch() 20 | def on_draw(): 21 | window.clear() 22 | root.draw() 23 | fps_display.draw() 24 | window.on_draw = on_draw 25 | 26 | @window.event 27 | def on_resize(width, height): 28 | root.width = width 29 | root.height = height 30 | root.on_resize() 31 | # mv = pyglet.resource.media('tmp4.mp4', streaming=False) 32 | # mv.play() 33 | 34 | root.sons = [ 35 | controls.ImageFrame( 36 | (window,0,0,800,600,root), 37 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 38 | front = controls.Sprite(pyglet.resource.image('tframe.png')) 39 | ) 40 | , 41 | controls.Button( 42 | (window,25,15,150,30,root,controls.Posattr((0,25),(0,15),(0,150),(0,30))), 43 | pyglet.text.Label('隐藏其它',font_name='微软雅黑',font_size=16,anchor_x = 'center',anchor_y = 'center'), 44 | controls.Sprite(pyglet.resource.image('tbut.png')), 45 | controls.Sprite(pyglet.resource.image('tico.png')), 46 | controls.Sprite(pyglet.resource.image('t.png')) 47 | ) 48 | ] 49 | f1,button0 = root.sons 50 | f1.sons = [ 51 | controls.Viewport((window,0,0,1,1,f1,controls.Posattr((0.1,0),(0.1,0),(0.8,0),(0.8,0)))) 52 | ] 53 | vport = f1.sons[0] 54 | gbutton = lambda:controls.Button( 55 | (window,25,15,150,30,root,controls.Posattr((0,random.randint(0,800)),(0,random.randint(0,600)),(0,100),(0,100))), 56 | pyglet.text.Label('提交',font_name='黑体',font_size=16,anchor_x = 'center',anchor_y = 'center') 57 | , 58 | controls.Sprite(pyglet.resource.animation('walk.gif')) 59 | , 60 | controls.Sprite(pyglet.resource.image('tico.png')) 61 | ) 62 | gtitle = lambda:controls.Label( 63 | [window], 64 | pyglet.text.Label( 65 | 'TITLE',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center') 66 | ) 67 | gtxtbox = lambda:controls.TextBox( 68 | [window], 69 | '''这是一个多行文本框 70 | qwq''', 71 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 72 | editable = False,multiline = True, 73 | back = controls.Sprite(pyglet.resource.animation('walk.gif')),select_backcolor = (0, 0, 200, 127) 74 | ) 75 | def gdoc(): 76 | doc = pyglet.text.document.FormattedDocument('''这是一个可编辑的多行文本框 77 | qwq''') 78 | doc.set_style(0, len(doc.text)-4, {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}) 79 | return doc 80 | geditbox = lambda:controls.FormattedTextBox( 81 | [window], 82 | gdoc(), 83 | editable = True,multiline = True, 84 | back = controls.Sprite(pyglet.resource.image('tbut.png')),select_backcolor = (0, 0, 200, 127) 85 | ) 86 | gsbutton = lambda:controls.SwitchButton( 87 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,300),(0,150),(0,30))), 88 | [ 89 | pyglet.text.Label('switch0',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center'), 90 | pyglet.text.Label('switch1',font_size=16,color = (0,255,0,255),bold = True,anchor_x = 'center',anchor_y = 'center') 91 | ] 92 | , 93 | [ 94 | controls.Sprite(pyglet.resource.image('tbut.png')), 95 | controls.Sprite(pyglet.resource.image('tbut.png')) 96 | ] 97 | , 98 | [ 99 | controls.Sprite(pyglet.resource.image('tico.png')) 100 | ] 101 | , 102 | direction = 1 103 | ) 104 | gscrollbar = lambda:controls.ScrollBar( 105 | (window,25,380,150,30,vport,controls.Posattr((0,25),(0,380),(0,20),(0,120))), 106 | image = controls.Sprite(pyglet.resource.image('scroll.png')), 107 | cursor = controls.Sprite(pyglet.resource.image('sliderf1.png')) 108 | ) 109 | vport.sons = [ 110 | controls.Button( 111 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,55),(0,150),(0,30))), 112 | pyglet.text.Label('+=10%',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center'), 113 | controls.Sprite(pyglet.resource.image('tbut.png')), 114 | controls.Sprite(pyglet.resource.image('tico.png')) 115 | ), 116 | controls.TextBox( 117 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,100),(0,150),(0,150))), 118 | '''这是一个多行文本框 119 | qwq''', 120 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 121 | editable = False,multiline = True, 122 | back = controls.Sprite(pyglet.resource.image('tbut.png')),select_backcolor = (0, 0, 200, 127) 123 | ) 124 | , 125 | controls.ProgressBar( 126 | (window,0,0,1,1,vport,controls.Posattr((0,25),(0,265),(0,150),(0,20))), 127 | pyglet.text.Label('%',font_size=14,bold = True,anchor_x = 'center',anchor_y = 'center'), 128 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 129 | bar = controls.Sprite(pyglet.resource.image('progressh.png')), bar_sizerate = (0.05,0.2,0.9,0.6), 130 | direction = 0, 131 | rate = 1 132 | ) 133 | , 134 | gsbutton() 135 | , 136 | controls.ButtonSlider( 137 | (window,25,340,150,30,vport,controls.Posattr((0,25),(0,340),(0,150),(0,30))), 138 | back = controls.Sprite(pyglet.resource.image('bslider.png')) 139 | ) 140 | , 141 | controls.MessageInteractor( 142 | (window,0,0,800,600,vport,controls.Posattr((0,200),(0,30),(0,250),(0,250))), 143 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 144 | front = controls.Sprite(pyglet.resource.image('tframe.png')) 145 | ) 146 | , 147 | controls.Label( 148 | (window,0,0,1,1,vport,controls.Posattr((0.5,0),(0.8,0),(0,0),(0,0))), 149 | pyglet.text.Label( 150 | 'SSSSSS',font_size=16,bold = True,anchor_x = 'center',anchor_y = 'center') 151 | ) 152 | , 153 | controls.SpriteControl( 154 | (window,0,0,1,1,vport,controls.Posattr((0.6,0),(0.8,0),(0.1,0),(0.1,0))), 155 | controls.Sprite(pyglet.resource.image('tbut.png')) 156 | ) 157 | , 158 | controls.MessageBox( 159 | (window,0,0,800,600,vport,controls.Posattr((0,480),(0,30),(0,250),(0,450))), 160 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 161 | title = gtitle(), 162 | doc = gtxtbox() 163 | ) 164 | , 165 | controls.AlertBox( 166 | (window,0,0,800,600,vport,controls.Posattr((0,200),(0,300),(0,250),(0,150))), 167 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 168 | title = gtitle(), 169 | doc = gtxtbox(), 170 | button = gbutton() 171 | ) 172 | , 173 | controls.MessageInput( 174 | (window,0,0,800,600,vport,controls.Posattr((0,750),(0,30),(0,250),(0,150))), 175 | back = controls.Sprite(pyglet.resource.image('tbut.png')), 176 | title = gtitle(), 177 | doc = geditbox(), 178 | button = gbutton() 179 | ) 180 | , 181 | gscrollbar() 182 | , 183 | controls.TagPages( 184 | (window,0,0,800,600,vport,controls.Posattr((0,750),(0,200),(0,250),(0,200))), 185 | layouter = controls.TagPages_defaultlayoutH 186 | ) 187 | ] 188 | 189 | button1,txtbox1,prog,sbutton0,slider0,msg,lbl,img,msg1,alrt,inp,sld0,tagp = vport.sons 190 | 191 | tagp.pages = [ 192 | (gsbutton(),controls.ScrollTextBox([window],geditbox(),gscrollbar())), 193 | (gsbutton(),geditbox()), 194 | (gsbutton(),gbutton()), 195 | (gsbutton(),gsbutton()), 196 | (gsbutton(),gtxtbox()) 197 | ] 198 | slider0.buttons = [ 199 | controls.SwitchButton( 200 | (window,0,0,1,1,slider0), 201 | images = [ 202 | controls.Sprite(pyglet.resource.image('sliderf0.png')), 203 | controls.Sprite(pyglet.resource.image('sliderf1.png')) 204 | ] 205 | ) 206 | for i in range(10) 207 | ] 208 | msg.sons = [ 209 | controls.Button( 210 | (window,25,15,150,30,root,controls.Posattr((0,50),(0,30),(0,150),(0,30))), 211 | pyglet.text.Label('提交',font_name='微软雅黑',font_size=16,anchor_x = 'center',anchor_y = 'center'), 212 | controls.Sprite(pyglet.resource.image('tbut.png')), 213 | controls.Sprite(pyglet.resource.image('tico.png')) 214 | ) 215 | , 216 | controls.TextBox( 217 | (window,0,0,1,1,vport,controls.Posattr((0,50),(0,65),(0,150),(0,150))), 218 | '''写在这里的文字会提交到左侧''', 219 | {'color':(0, 0, 200, 255),'font_name':'仿宋','font_size':14,'line_spacing':24,'wrap':'char'}, 220 | editable = True,multiline = True, 221 | back = controls.Sprite(pyglet.resource.image('tbut.png')),select_backcolor = (0, 0, 200, 127) 222 | ) 223 | ] 224 | submitb,intertxt = msg.sons 225 | msg.submit_key = (submitb, 'on_press') 226 | 227 | msg1.buttons = [gbutton(),gbutton(),gbutton()] 228 | # button1.label.text = '111' 229 | # print(button1.text) 230 | # button1.text = '11' 231 | BALL_SOUND = pyglet.resource.media('ball.wav', streaming=False) 232 | BGM = pyglet.resource.media('bgm.mp3', streaming=False) 233 | bgm_player = BGM.play() 234 | 235 | def lop(): 236 | print('23') 237 | bgm_player.queue(BGM) 238 | bgm_player.next_source() 239 | bgm_player.on_source_group_eos = lop 240 | 241 | def onp(): 242 | print('pressed button 0') 243 | BALL_SOUND.play() 244 | if button0.text == '隐藏其它': 245 | button0.text = '显示其它' 246 | bgm_player.pause() 247 | else: 248 | button0.text = '隐藏其它' 249 | bgm_player.play() 250 | if button1.visible: 251 | button1.hide() 252 | else: 253 | button1.show() 254 | if txtbox1.visible: 255 | txtbox1.hide() 256 | else: 257 | txtbox1.show() 258 | if prog.visible: 259 | prog.hide() 260 | else: 261 | prog.show() 262 | if vport.visible: 263 | vport.hide() 264 | else: 265 | vport.show() 266 | print(len(alrt.sons)) 267 | alrt.title = None 268 | alrt.doc = None 269 | alrt.button = None 270 | msg1.doc = None 271 | msg1.title = None 272 | 273 | 274 | def onp1(): 275 | print('pressed button 1') 276 | # print(button1.text) 277 | # button1.text = '11' 278 | prog.rate = (prog.rate + 0.1 - (prog.rate + 0.1)// 1) 279 | prog.text = '%.1f%%' % (prog.rate*100) 280 | 281 | def onps(): 282 | print('pressed sbutton switch') 283 | sbutton0.stage ^= 1 284 | 285 | def onschange(val): 286 | print('slider changed:new val = %s' % val) 287 | 288 | def onsubmit(): 289 | print() 290 | print('submitted') 291 | msg.hide() 292 | txtbox1.text = intertxt.text 293 | 294 | # def onsubmit1(result): 295 | # print('submitted msg1') 296 | # msg1.hide() 297 | # print(msg1.result) 298 | 299 | button0.on_press = onp 300 | button1.on_press = onp1 301 | sbutton0.on_press = onps 302 | slider0.on_change = onschange 303 | msg.on_submit = onsubmit 304 | # msg1.on_submit = onsubmit1 305 | 306 | # TST = controls.SpriteControl([window],controls.Sprite(pyglet.resource.animation('walk.gif'))) 307 | # root.sons.append(TST) 308 | 309 | # print(bat.__dict__) 310 | for i in range(50): 311 | b = gbutton() 312 | vport.sons.append(gbutton()) 313 | 314 | # print(bat.__dict__) 315 | 316 | window.show() 317 | pyglet.app.run() 318 | -------------------------------------------------------------------------------- /oiasg_removed_files/commons/test.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_removed_files/commons/test.py -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/__ini.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import random 3 | 4 | # definition 5 | 6 | val = lambda x:eval(x) 7 | exe = lambda x:exec(x) 8 | 9 | time = datetime.datetime 10 | timed = datetime.timedelta 11 | 12 | rand_expect = (lambda x:random.randint(0,x) == 0) 13 | 14 | class event(object): 15 | def __init__(self, appearance = None, trigger = None, effects = None, user = None): 16 | self.appearance = appearance 17 | self.trigger = trigger 18 | self.effects = effects 19 | self.user = user 20 | if self.effects is not None: 21 | self.options = self.effects.get('options') 22 | self.immediate = self.effects.get('immediate') 23 | def check(self): 24 | if self.trigger is None: 25 | return False 26 | return val(self.trigger) 27 | def execute_options(self, option_chosen): 28 | if self.options is not None: 29 | for i in range(self.options.len()): 30 | if option_chosen[i]: 31 | exe(self.options[i]['effect']) 32 | def execute(self): 33 | if self.immediate is not None: 34 | exe(self.immediate) 35 | if self.appearance is not None: 36 | exe(self.appearance) 37 | # options 38 | 39 | # class problem(object): 40 | # def __init__(self, tags): 41 | # self.tags = tags 42 | # self.sols = {} 43 | 44 | class contest(object): 45 | def __init__(self, appearance = None, problems = None, strategies = None,user = None): 46 | self.appearance = appearance 47 | self.problems = problems 48 | self.strategies = strategies 49 | self.user = user 50 | 51 | self.strategy = None 52 | self.running = False 53 | def start(self): 54 | self.running = True 55 | self.cur_problems = list(map(val,self.problems)) 56 | global cur_timedelta, cur_contest 57 | cur_contest = self 58 | cur_timedelta = contest_timedelta 59 | def end(self): 60 | self.running = False 61 | global cur_timedelta, cur_contest 62 | cur_contest = None 63 | cur_timedelta = round_timedelta 64 | 65 | class game_log(object): 66 | pass 67 | 68 | check_event = lambda e:events[e].check() 69 | execute_event = lambda e:events[e].execute() 70 | trigger_event = lambda e:event_q.append(events[e]) 71 | execute_event_options = lambda e,o:events[e].execute_options(o) 72 | 73 | def end(): 74 | global running,event_q 75 | running = False 76 | event_q.clear() 77 | 78 | # system 79 | 80 | start_time = time(2016,9,1,7) 81 | cur_time = start_time 82 | round_timedelta = timed(hours = 8) 83 | contest_timedelta = timed(minutes = 1) 84 | cur_timedelta = round_timedelta 85 | end_time = time(2016,9,5,7) 86 | events = {} 87 | contests = {} 88 | log = game_log() 89 | event_q = [] 90 | cur_contest = None 91 | strategies = {} 92 | timetable_menu = [] 93 | timetable = [] 94 | timetable_it = None 95 | 96 | def play_round(): 97 | global cur_time 98 | global event_q 99 | cur_time = start_time + (((cur_time - start_time) // cur_timedelta) + 1) * cur_timedelta 100 | print(cur_time) 101 | event_q.clear() 102 | for e in events.values(): 103 | if e.check(): 104 | event_q.append(e) 105 | global timetable_it 106 | if cur_contest is None and timetable_it is not None: 107 | event_q.append(events[strategies[timetable[timetable_it]]]) 108 | timetable_it = (timetable_it + 1) % timetable.len() 109 | elif cur_contest is not None and cur_contest.strategy is not None: 110 | event_q.append(events[strategies[cur_contest.strategy]]) 111 | event_q.sort(key = lambda x:x.user['privilege'] if x.user is not None and 'privilege' in x.user else -2147483648) 112 | while event_q: 113 | e = event_q[-1] 114 | event_q.pop() 115 | e.execute() 116 | 117 | # abilities 118 | 119 | thinking = {} 120 | code = {} 121 | tags = {} 122 | ideas = {} 123 | moods = {} 124 | -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/_vars/code.py: -------------------------------------------------------------------------------- 1 | code.update({ 2 | 0:{ 3 | 'name':'代码熟练度', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'代码设计', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | }) 16 | 17 | coding = code[0] 18 | designing = code[1] -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/_vars/ideas.py: -------------------------------------------------------------------------------- 1 | ideas.update({ 2 | 0:{ 3 | 'name':'状态压缩', 4 | 'appearance':None, 5 | 'relations':{}, 6 | 'privilege':0, 7 | 'level':0, 8 | } 9 | , 10 | 11 | 1:{ 12 | 'name':'映射', 13 | 'appearance':None, 14 | 'relations':{}, 15 | 'privilege':0, 16 | 'level':0, 17 | } 18 | , 19 | 20 | 2:{ 21 | 'name':'分治', 22 | 'appearance':None, 23 | 'relations':{}, 24 | 'privilege':0, 25 | 'level':0, 26 | } 27 | , 28 | 29 | 3:{ 30 | 'name':'延迟处理', 31 | 'appearance':None, 32 | 'relations':{}, 33 | 'privilege':0, 34 | 'level':0, 35 | } 36 | , 37 | 38 | 4:{ 39 | 'name':'单调性', 40 | 'appearance':None, 41 | 'relations':{}, 42 | 'privilege':0, 43 | 'level':0, 44 | } 45 | , 46 | 47 | 5:{ 48 | 'name':'二分', 49 | 'appearance':None, 50 | 'relations':{}, 51 | 'privilege':0, 52 | 'level':0, 53 | } 54 | , 55 | 56 | 6:{ 57 | 'name':'倍增', 58 | 'appearance':None, 59 | 'relations':{}, 60 | 'privilege':0, 61 | 'level':0, 62 | } 63 | , 64 | 65 | 7:{ 66 | 'name':'分块', 67 | 'appearance':None, 68 | 'relations':{}, 69 | 'privilege':0, 70 | 'level':0, 71 | } 72 | , 73 | 74 | 8:{ 75 | 'name':'记忆化', 76 | 'appearance':None, 77 | 'relations':{}, 78 | 'privilege':0, 79 | 'level':0, 80 | } 81 | , 82 | 83 | 9:{ 84 | 'name':'可持久化', 85 | 'appearance':None, 86 | 'relations':{}, 87 | 'privilege':0, 88 | 'level':0, 89 | } 90 | , 91 | 92 | 10:{ 93 | 'name':'离线', 94 | 'appearance':None, 95 | 'relations':{}, 96 | 'privilege':0, 97 | 'level':0, 98 | } 99 | , 100 | 101 | 11:{ 102 | 'name':'近似', 103 | 'appearance':None, 104 | 'relations':{}, 105 | 'privilege':0, 106 | 'level':0, 107 | } 108 | , 109 | 110 | 12:{ 111 | 'name':'随机化', 112 | 'appearance':None, 113 | 'relations':{}, 114 | 'privilege':0, 115 | 'level':0, 116 | } 117 | , 118 | 119 | 13:{ 120 | 'name':'启发和估价', 121 | 'appearance':None, 122 | 'relations':{}, 123 | 'privilege':0, 124 | 'level':0, 125 | } 126 | }) 127 | 128 | -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/_vars/mood.py: -------------------------------------------------------------------------------- 1 | moods.update({ 2 | 0:{ 3 | 'name':'心情', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'心理压力', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | }) 16 | 17 | mood = moods[0] 18 | stress = moods[1] 19 | -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/_vars/thinking.py: -------------------------------------------------------------------------------- 1 | thinking.update({ 2 | 0:{ 3 | 'name':'抽象思维', 4 | 'appearance':None, 5 | 'privilege':0, 6 | 'level':0 7 | } 8 | , 9 | 1:{ 10 | 'name':'形象思维', 11 | 'appearance':None, 12 | 'privilege':0, 13 | 'level':0 14 | } 15 | , 16 | 2:{ 17 | 'name':'想象力', 18 | 'appearance':None, 19 | 'privilege':0, 20 | 'level':0 21 | } 22 | }) 23 | 24 | structure = thinking[0] 25 | graphic = thinking[1] 26 | imagination = thinking[2] 27 | -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/contests/_problemgen.py: -------------------------------------------------------------------------------- 1 | def problem_basic(name): 2 | return { 3 | 'name':name, 4 | 'tags':{ 5 | 0:{ 6 | 'parents':None, 7 | 'parent':None, 8 | 'score':30, 9 | 'tag':AB['name'], 10 | 'relations':{ 11 | 134:1.0 # AB 12 | }, 13 | 'difficulty':0.5, 14 | 'rate':0 15 | }, 16 | 1:{ 17 | 'parents':[0], 18 | 'parent':None, 19 | 'score':70, 20 | 'tag':FT['name'], 21 | 'relations':{ 22 | 144:1.0 # FFT 23 | }, 24 | 'difficulty':2, 25 | 'rate':0 26 | } 27 | }, 28 | 'sols':{} 29 | } -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/contests/example.py: -------------------------------------------------------------------------------- 1 | contests.update({ 2 | 'example_contest':contest( 3 | appearance = None, 4 | problems = [ 5 | 'problem_basic("A")', 6 | 'problem_basic("B")' 7 | ], 8 | strategies = {} 9 | ) 10 | }) 11 | 12 | # _TC = contests['example_contest'] -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/events/__system.py: -------------------------------------------------------------------------------- 1 | events.update({ 2 | 'check_timeline':event( 3 | appearance = None, 4 | trigger = 'cur_time > end_time', 5 | effects = { 6 | 'immediate': 7 | ''' 8 | print("Game has ended:time up.") 9 | end() 10 | ''' 11 | }, 12 | user = {'privilege':2147483647} 13 | ) 14 | }) -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/events/example.py: -------------------------------------------------------------------------------- 1 | events.update({ 2 | 'example_event':event( 3 | appearance = None, 4 | trigger = 'True # rand_expect(10)', 5 | effects = { 6 | 'immediate': 7 | 'print("test_event")\n' + 8 | 'trigger_event("example_event_triggered")\n' 9 | , 10 | 'options':[ 11 | { 12 | 'name':'option1', 13 | 'effect':'' 14 | }, 15 | { 16 | 'name':'option2', 17 | 'effect':'' 18 | } 19 | ] 20 | } 21 | ), 22 | 'example_event_triggered':event( 23 | appearance = None, 24 | trigger = None, 25 | effects = { 26 | 'immediate': 27 | 'print("test_event_triggered")\n' 28 | } 29 | ) 30 | }) -------------------------------------------------------------------------------- /oiasg_removed_files/old__commons/events/strategy/__general.py: -------------------------------------------------------------------------------- 1 | strategies.update({ 2 | 'example_strategy':'example_event' 3 | }) -------------------------------------------------------------------------------- /oiasg_removed_files/old_fonts/杨任东竹石体-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_removed_files/old_fonts/杨任东竹石体-Regular.ttf -------------------------------------------------------------------------------- /oiasg_removed_files/old_fonts/杨任东竹石体-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CommonAnts/OIASG/d340d47395554cae45802cfb65a9b78f7d0cfde9/oiasg_removed_files/old_fonts/杨任东竹石体-Semibold.ttf -------------------------------------------------------------------------------- /oiasg_removed_files/old_game.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import traceback 4 | # import functools 5 | 6 | from . import appearance 7 | 8 | def getobj(s): 9 | return open(s, "r", encoding = 'utf-8').read() 10 | 11 | def getobjs(s): 12 | objs = [] 13 | fs = os.listdir(s) 14 | for f in fs: 15 | absf = os.path.join(s, f) 16 | if os.path.isfile(absf) and os.path.splitext(f)[1] == '.py': 17 | objs.append(absf) 18 | elif os.path.isdir(absf): 19 | objs += getobjs(absf) 20 | return objs 21 | 22 | class gameplay(object): 23 | def __init__(self, scenario = "__general", _basedir = None): 24 | print("A new game object is constructed.") 25 | if _basedir is None: 26 | _basedir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 27 | self.__basedir = _basedir 28 | self.var = { 29 | "load_script":self.load_script, 30 | "load_scripts":self.load_scripts, 31 | 32 | "running":True 33 | # "output":self.output 34 | } 35 | self.load_scripts("__commons") 36 | 37 | self.load_script(os.path.join("scenarios",scenario + '.py')) 38 | 39 | self.paused = True 40 | self.speed = 0 41 | 42 | def end(self): 43 | print("A game has ended.") 44 | def run(self): 45 | print("A game has started.") 46 | try: 47 | # definition 48 | # execution 49 | while self.var['running']: 50 | self.var['play_round']() 51 | self.pause_game() 52 | while self.paused: 53 | # self.output() 54 | ope = input() 55 | # print("Game object got operation:" + ope) 56 | exec(ope) 57 | time.sleep(2*(0.5**self.speed)) 58 | except: 59 | print("!!!!! --- 游戏体抛出异常 --- !!!!!") 60 | traceback.print_exc() 61 | self.end() 62 | def output(self): 63 | print(self.var) 64 | def load_script(self, scriptpath): 65 | exec(getobj(os.path.join(self.__basedir,scriptpath)), self.var, self.var) 66 | def load_scripts(self, scriptdir): 67 | objs = getobjs(os.path.join(self.__basedir, scriptdir)) 68 | objs.sort() 69 | for i in objs: 70 | exec(getobj(i), self.var, self.var) 71 | def pause_game(self): 72 | self.paused = True 73 | def continue_game(self): 74 | self.paused = False 75 | def set_speed(self, speed): 76 | self.speed = speed -------------------------------------------------------------------------------- /oiasg_removed_files/scenarios/__general.py: -------------------------------------------------------------------------------- 1 | name,sex,school,province,image,birthday = "李华","女","育才中学","北京","",time(2001,1,1) -------------------------------------------------------------------------------- /pyglet/font/win32.py: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------- 2 | # pyglet 3 | # Copyright (c) 2006-2008 Alex Holkner 4 | # All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions 8 | # are met: 9 | # 10 | # * Redistributions of source code must retain the above copyright 11 | # notice, this list of conditions and the following disclaimer. 12 | # * Redistributions in binary form must reproduce the above copyright 13 | # notice, this list of conditions and the following disclaimer in 14 | # the documentation and/or other materials provided with the 15 | # distribution. 16 | # * Neither the name of pyglet nor the names of its 17 | # contributors may be used to endorse or promote products 18 | # derived from this software without specific prior written 19 | # permission. 20 | # 21 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 | # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 | # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 | # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 29 | # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | # POSSIBILITY OF SUCH DAMAGE. 33 | # ---------------------------------------------------------------------------- 34 | 35 | ''' 36 | ''' 37 | 38 | # TODO Windows Vista: need to call SetProcessDPIAware? May affect GDI+ calls 39 | # as well as font. 40 | 41 | from ctypes import * 42 | import ctypes 43 | import math 44 | 45 | from sys import byteorder 46 | import pyglet 47 | from pyglet.font import base 48 | from pyglet.font import win32query 49 | import pyglet.image 50 | from pyglet.libs.win32.constants import * 51 | from pyglet.libs.win32.types import * 52 | from pyglet.libs.win32 import _gdi32 as gdi32, _user32 as user32 53 | from pyglet.libs.win32 import _kernel32 as kernel32 54 | # from pyglet.compat import asbytes 55 | import pyglet.compat 56 | 57 | _debug_font = pyglet.options['debug_font'] 58 | 59 | 60 | def str_ucs2(text): 61 | if byteorder == 'big': 62 | text = text.encode('utf_16_be') 63 | else: 64 | text = text.encode('utf_16_le') # explicit endian avoids BOM 65 | return create_string_buffer(text + '\0') 66 | 67 | _debug_dir = 'debug_font' 68 | def _debug_filename(base, extension): 69 | import os 70 | if not os.path.exists(_debug_dir): 71 | os.makedirs(_debug_dir) 72 | name = '%s-%%d.%%s' % os.path.join(_debug_dir, base) 73 | num = 1 74 | while os.path.exists(name % (num, extension)): 75 | num += 1 76 | return name % (num, extension) 77 | 78 | def _debug_image(image, name): 79 | filename = _debug_filename(name, 'png') 80 | image.save(filename) 81 | _debug('Saved image %r to %s' % (image, filename)) 82 | 83 | _debug_logfile = None 84 | def _debug(msg): 85 | global _debug_logfile 86 | if not _debug_logfile: 87 | _debug_logfile = open(_debug_filename('log', 'txt'), 'wt') 88 | _debug_logfile.write(msg + '\n') 89 | 90 | class Win32GlyphRenderer(base.GlyphRenderer): 91 | 92 | 93 | def __init__(self, font): 94 | self._bitmap = None 95 | self._dc = None 96 | self._bitmap_rect = None 97 | super(Win32GlyphRenderer, self).__init__(font) 98 | self.font = font 99 | 100 | # Pessimistically round up width and height to 4 byte alignment 101 | width = font.max_glyph_width 102 | height = font.ascent - font.descent 103 | width = (width | 0x3) + 1 104 | height = (height | 0x3) + 1 105 | self._create_bitmap(width, height) 106 | 107 | gdi32.SelectObject(self._dc, self.font.hfont) 108 | 109 | def _create_bitmap(self, width, height): 110 | pass 111 | 112 | def render(self, text): 113 | raise NotImplementedError('abstract') 114 | 115 | class GDIGlyphRenderer(Win32GlyphRenderer): 116 | def __del__(self): 117 | try: 118 | if self._dc: 119 | gdi32.DeleteDC(self._dc) 120 | if self._bitmap: 121 | gdi32.DeleteObject(self._bitmap) 122 | except: 123 | pass 124 | 125 | def render(self, text): 126 | # Attempt to get ABC widths (only for TrueType) 127 | abc = ABC() 128 | if gdi32.GetCharABCWidthsW(self._dc, 129 | ord(text), ord(text), byref(abc)): 130 | width = abc.abcB 131 | lsb = abc.abcA 132 | advance = abc.abcA + abc.abcB + abc.abcC 133 | else: 134 | width_buf = c_int() 135 | gdi32.GetCharWidth32W(self._dc, 136 | ord(text), ord(text), byref(width_buf)) 137 | width = width_buf.value 138 | lsb = 0 139 | advance = width 140 | 141 | # Can't get glyph-specific dimensions, use whole line-height. 142 | height = self._bitmap_height 143 | image = self._get_image(text, width, height, lsb) 144 | 145 | glyph = self.font.create_glyph(image) 146 | glyph.set_bearings(-self.font.descent, lsb, advance) 147 | 148 | if _debug_font: 149 | _debug('%r.render(%s)' % (self, text)) 150 | _debug('abc.abcA = %r' % abc.abcA) 151 | _debug('abc.abcB = %r' % abc.abcB) 152 | _debug('abc.abcC = %r' % abc.abcC) 153 | _debug('width = %r' % width) 154 | _debug('height = %r' % height) 155 | _debug('lsb = %r' % lsb) 156 | _debug('advance = %r' % advance) 157 | _debug_image(image, 'glyph_%s' % text) 158 | _debug_image(self.font.textures[0], 'tex_%s' % text) 159 | 160 | return glyph 161 | 162 | def _get_image(self, text, width, height, lsb): 163 | # There's no such thing as a greyscale bitmap format in GDI. We can 164 | # create an 8-bit palette bitmap with 256 shades of grey, but 165 | # unfortunately antialiasing will not work on such a bitmap. So, we 166 | # use a 32-bit bitmap and use the red channel as OpenGL's alpha. 167 | 168 | gdi32.SelectObject(self._dc, self._bitmap) 169 | gdi32.SelectObject(self._dc, self.font.hfont) 170 | gdi32.SetBkColor(self._dc, 0x0) 171 | gdi32.SetTextColor(self._dc, 0x00ffffff) 172 | gdi32.SetBkMode(self._dc, OPAQUE) 173 | 174 | # Draw to DC 175 | user32.FillRect(self._dc, byref(self._bitmap_rect), self._black) 176 | gdi32.ExtTextOutA(self._dc, -lsb, 0, 0, None, text, 177 | len(text), None) 178 | gdi32.GdiFlush() 179 | 180 | # Create glyph object and copy bitmap data to texture 181 | image = pyglet.image.ImageData(width, height, 182 | 'AXXX', self._bitmap_data, self._bitmap_rect.right * 4) 183 | return image 184 | 185 | def _create_bitmap(self, width, height): 186 | self._black = gdi32.GetStockObject(BLACK_BRUSH) 187 | self._white = gdi32.GetStockObject(WHITE_BRUSH) 188 | 189 | if self._dc: 190 | gdi32.ReleaseDC(self._dc) 191 | if self._bitmap: 192 | gdi32.DeleteObject(self._bitmap) 193 | 194 | pitch = width * 4 195 | data = POINTER(c_byte * (height * pitch))() 196 | info = BITMAPINFO() 197 | info.bmiHeader.biSize = sizeof(info.bmiHeader) 198 | info.bmiHeader.biWidth = width 199 | info.bmiHeader.biHeight = height 200 | info.bmiHeader.biPlanes = 1 201 | info.bmiHeader.biBitCount = 32 202 | info.bmiHeader.biCompression = BI_RGB 203 | 204 | self._dc = gdi32.CreateCompatibleDC(None) 205 | self._bitmap = gdi32.CreateDIBSection(None, 206 | byref(info), DIB_RGB_COLORS, byref(data), None, 207 | 0) 208 | # Spookiness: the above line causes a "not enough storage" error, 209 | # even though that error cannot be generated according to docs, 210 | # and everything works fine anyway. Call SetLastError to clear it. 211 | kernel32.SetLastError(0) 212 | 213 | self._bitmap_data = data.contents 214 | self._bitmap_rect = RECT() 215 | self._bitmap_rect.left = 0 216 | self._bitmap_rect.right = width 217 | self._bitmap_rect.top = 0 218 | self._bitmap_rect.bottom = height 219 | self._bitmap_height = height 220 | 221 | if _debug_font: 222 | _debug('%r._create_dc(%d, %d)' % (self, width, height)) 223 | _debug('_dc = %r' % self._dc) 224 | _debug('_bitmap = %r' % self._bitmap) 225 | _debug('pitch = %r' % pitch) 226 | _debug('info.bmiHeader.biSize = %r' % info.bmiHeader.biSize) 227 | 228 | class Win32Font(base.Font): 229 | glyph_renderer_class = GDIGlyphRenderer 230 | 231 | def __init__(self, name, size, bold=False, italic=False, dpi=None): 232 | super(Win32Font, self).__init__() 233 | 234 | self.logfont = self.get_logfont(name, size, bold, italic, dpi) 235 | self.hfont = gdi32.CreateFontIndirectA(byref(self.logfont)) 236 | 237 | # Create a dummy DC for coordinate mapping 238 | dc = user32.GetDC(0) 239 | metrics = TEXTMETRIC() 240 | gdi32.SelectObject(dc, self.hfont) 241 | gdi32.GetTextMetricsA(dc, byref(metrics)) 242 | self.ascent = metrics.tmAscent 243 | self.descent = -metrics.tmDescent 244 | self.max_glyph_width = metrics.tmMaxCharWidth 245 | user32.ReleaseDC(0, dc) 246 | 247 | def __del__(self): 248 | gdi32.DeleteObject(self.hfont) 249 | 250 | @staticmethod 251 | def get_logfont(name, size, bold, italic, dpi): 252 | # Create a dummy DC for coordinate mapping 253 | dc = user32.GetDC(0) 254 | if dpi is None: 255 | dpi = 96 256 | logpixelsy = dpi 257 | 258 | logfont = LOGFONT() 259 | # Conversion of point size to device pixels 260 | logfont.lfHeight = int(-size * logpixelsy // 72) 261 | if bold: 262 | logfont.lfWeight = FW_BOLD 263 | else: 264 | logfont.lfWeight = FW_NORMAL 265 | logfont.lfItalic = italic 266 | logfont.lfFaceName = pyglet.compat.asbytes_filename(name) 267 | logfont.lfQuality = ANTIALIASED_QUALITY 268 | user32.ReleaseDC(0, dc) 269 | return logfont 270 | 271 | @classmethod 272 | def have_font(cls, name): 273 | # [ ] add support for loading raster fonts 274 | return win32query.have_font(name) 275 | 276 | @classmethod 277 | def add_font_data(cls, data): 278 | numfonts = c_uint32() 279 | gdi32.AddFontMemResourceEx(data, len(data), 0, byref(numfonts)) 280 | 281 | # --- GDI+ font rendering --- 282 | 283 | from pyglet.image.codecs.gdiplus import PixelFormat32bppARGB, gdiplus, Rect 284 | from pyglet.image.codecs.gdiplus import ImageLockModeRead, BitmapData 285 | 286 | DriverStringOptionsCmapLookup = 1 287 | DriverStringOptionsRealizedAdvance = 4 288 | TextRenderingHintAntiAlias = 4 289 | TextRenderingHintAntiAliasGridFit = 3 290 | 291 | StringFormatFlagsDirectionRightToLeft = 0x00000001 292 | StringFormatFlagsDirectionVertical = 0x00000002 293 | StringFormatFlagsNoFitBlackBox = 0x00000004 294 | StringFormatFlagsDisplayFormatControl = 0x00000020 295 | StringFormatFlagsNoFontFallback = 0x00000400 296 | StringFormatFlagsMeasureTrailingSpaces = 0x00000800 297 | StringFormatFlagsNoWrap = 0x00001000 298 | StringFormatFlagsLineLimit = 0x00002000 299 | StringFormatFlagsNoClip = 0x00004000 300 | 301 | class Rectf(ctypes.Structure): 302 | _fields_ = [ 303 | ('x', ctypes.c_float), 304 | ('y', ctypes.c_float), 305 | ('width', ctypes.c_float), 306 | ('height', ctypes.c_float), 307 | ] 308 | 309 | class GDIPlusGlyphRenderer(Win32GlyphRenderer): 310 | def __del__(self): 311 | try: 312 | if self._matrix: 313 | res = gdiplus.GdipDeleteMatrix(self._matrix) 314 | if self._brush: 315 | res = gdiplus.GdipDeleteBrush(self._brush) 316 | if self._graphics: 317 | res = gdiplus.GdipDeleteGraphics(self._graphics) 318 | if self._bitmap: 319 | res = gdiplus.GdipDisposeImage(self._bitmap) 320 | if self._dc: 321 | res = user32.ReleaseDC(0, self._dc) 322 | except: 323 | pass 324 | 325 | def _create_bitmap(self, width, height): 326 | self._data = (ctypes.c_byte * (4 * width * height))() 327 | self._bitmap = ctypes.c_void_p() 328 | self._format = PixelFormat32bppARGB 329 | gdiplus.GdipCreateBitmapFromScan0(width, height, width * 4, 330 | self._format, self._data, ctypes.byref(self._bitmap)) 331 | 332 | self._graphics = ctypes.c_void_p() 333 | gdiplus.GdipGetImageGraphicsContext(self._bitmap, 334 | ctypes.byref(self._graphics)) 335 | gdiplus.GdipSetPageUnit(self._graphics, UnitPixel) 336 | 337 | self._dc = user32.GetDC(0) 338 | gdi32.SelectObject(self._dc, self.font.hfont) 339 | 340 | gdiplus.GdipSetTextRenderingHint(self._graphics, 341 | TextRenderingHintAntiAliasGridFit) 342 | 343 | 344 | self._brush = ctypes.c_void_p() 345 | gdiplus.GdipCreateSolidFill(0xffffffff, ctypes.byref(self._brush)) 346 | 347 | 348 | self._matrix = ctypes.c_void_p() 349 | gdiplus.GdipCreateMatrix(ctypes.byref(self._matrix)) 350 | 351 | self._flags = (DriverStringOptionsCmapLookup | 352 | DriverStringOptionsRealizedAdvance) 353 | 354 | self._rect = Rect(0, 0, width, height) 355 | 356 | self._bitmap_height = height 357 | 358 | def render(self, text): 359 | 360 | ch = ctypes.create_unicode_buffer(text) 361 | len_ch = len(text) 362 | 363 | # Layout rectangle; not clipped against so not terribly important. 364 | width = 10000 365 | height = self._bitmap_height 366 | rect = Rectf(0, self._bitmap_height 367 | - self.font.ascent + self.font.descent, 368 | width, height) 369 | 370 | # Set up GenericTypographic with 1 character measure range 371 | generic = ctypes.c_void_p() 372 | gdiplus.GdipStringFormatGetGenericTypographic(ctypes.byref(generic)) 373 | format = ctypes.c_void_p() 374 | gdiplus.GdipCloneStringFormat(generic, ctypes.byref(format)) 375 | gdiplus.GdipDeleteStringFormat(generic) 376 | 377 | # Measure advance 378 | 379 | # XXX HACK HACK HACK 380 | # Windows GDI+ is a filthy broken toy. No way to measure the bounding 381 | # box of a string, or to obtain LSB. What a joke. 382 | # 383 | # For historical note, GDI cannot be used because it cannot composite 384 | # into a bitmap with alpha. 385 | # 386 | # It looks like MS have abandoned GDI and GDI+ and are finally 387 | # supporting accurate text measurement with alpha composition in .NET 388 | # 2.0 (WinForms) via the TextRenderer class; this has no C interface 389 | # though, so we're entirely screwed. 390 | # 391 | # So anyway, we first try to get the width with GdipMeasureString. 392 | # Then if it's a TrueType font, we use GetCharABCWidthsW to get the 393 | # correct LSB. If it's a negative LSB, we move the layoutRect `rect` 394 | # to the right so that the whole glyph is rendered on the surface. 395 | # For positive LSB, we let the renderer render the correct white 396 | # space and we don't pass the LSB info to the Glyph.set_bearings 397 | 398 | bbox = Rectf() 399 | flags = (StringFormatFlagsMeasureTrailingSpaces | 400 | StringFormatFlagsNoClip | 401 | StringFormatFlagsNoFitBlackBox) 402 | gdiplus.GdipSetStringFormatFlags(format, flags) 403 | gdiplus.GdipMeasureString(self._graphics, 404 | ch, 405 | len_ch, 406 | self.font._gdipfont, 407 | ctypes.byref(rect), 408 | format, 409 | ctypes.byref(bbox), 410 | None, 411 | None) 412 | lsb = 0 413 | advance = int(math.ceil(bbox.width)) 414 | width = advance 415 | 416 | # This hack bumps up the width if the font is italic; 417 | # this compensates for some common fonts. It's also a stupid 418 | # waste of texture memory. 419 | if self.font.italic: 420 | width += width // 2 421 | # Do not enlarge more than the _rect width. 422 | width = min(width, self._rect.Width) 423 | 424 | # GDI functions only work for a single character so we transform 425 | # grapheme \r\n into \r 426 | if text == '\r\n': 427 | text = '\r' 428 | 429 | abc = ABC() 430 | # Check if ttf font. 431 | if gdi32.GetCharABCWidthsW(self._dc, 432 | ord(text), ord(text), byref(abc)): 433 | 434 | lsb = abc.abcA 435 | if lsb < 0: 436 | # Negative LSB: we shift the layout rect to the right 437 | # Otherwise we will cut the left part of the glyph 438 | rect.x = -lsb 439 | width -= lsb 440 | # XXX END HACK HACK HACK 441 | 442 | # Draw character to bitmap 443 | 444 | gdiplus.GdipGraphicsClear(self._graphics, 0x00000000) 445 | gdiplus.GdipDrawString(self._graphics, 446 | ch, 447 | len_ch, 448 | self.font._gdipfont, 449 | ctypes.byref(rect), 450 | format, 451 | self._brush) 452 | gdiplus.GdipFlush(self._graphics, 1) 453 | gdiplus.GdipDeleteStringFormat(format) 454 | 455 | bitmap_data = BitmapData() 456 | gdiplus.GdipBitmapLockBits(self._bitmap, 457 | byref(self._rect), ImageLockModeRead, self._format, 458 | byref(bitmap_data)) 459 | 460 | # Create buffer for RawImage 461 | buffer = create_string_buffer( 462 | bitmap_data.Stride * bitmap_data.Height) 463 | memmove(buffer, bitmap_data.Scan0, len(buffer)) 464 | 465 | # Unlock data 466 | gdiplus.GdipBitmapUnlockBits(self._bitmap, byref(bitmap_data)) 467 | 468 | image = pyglet.image.ImageData(width, height, 469 | 'BGRA', buffer, -bitmap_data.Stride) 470 | 471 | glyph = self.font.create_glyph(image) 472 | # Only pass negative LSB info 473 | lsb = min(lsb, 0) 474 | glyph.set_bearings(-self.font.descent, lsb, advance) 475 | 476 | return glyph 477 | 478 | FontStyleBold = 1 479 | FontStyleItalic = 2 480 | UnitPixel = 2 481 | UnitPoint = 3 482 | 483 | class GDIPlusFont(Win32Font): 484 | glyph_renderer_class = GDIPlusGlyphRenderer 485 | 486 | _private_fonts = None 487 | 488 | _default_name = 'Arial' 489 | 490 | def __init__(self, name, size, bold=False, italic=False, dpi=None): 491 | if not name: 492 | name = self._default_name 493 | super(GDIPlusFont, self).__init__(name, size, bold, italic, dpi) 494 | 495 | family = ctypes.c_void_p() 496 | name = ctypes.c_wchar_p(name) 497 | 498 | # Look in private collection first: 499 | if self._private_fonts: 500 | gdiplus.GdipCreateFontFamilyFromName(name, 501 | self._private_fonts, ctypes.byref(family)) 502 | 503 | # Then in system collection: 504 | if not family: 505 | gdiplus.GdipCreateFontFamilyFromName(name, 506 | None, ctypes.byref(family)) 507 | 508 | # Nothing found, use default font. 509 | if not family: 510 | name = self._default_name 511 | gdiplus.GdipCreateFontFamilyFromName(ctypes.c_wchar_p(name), 512 | None, ctypes.byref(family)) 513 | 514 | if dpi is None: 515 | unit = UnitPoint 516 | self.dpi = 96 517 | else: 518 | unit = UnitPixel 519 | size = (size * dpi) // 72 520 | self.dpi = dpi 521 | 522 | style = 0 523 | if bold: 524 | style |= FontStyleBold 525 | if italic: 526 | style |= FontStyleItalic 527 | self._gdipfont = ctypes.c_void_p() 528 | gdiplus.GdipCreateFont(family, ctypes.c_float(size), 529 | style, unit, ctypes.byref(self._gdipfont)) 530 | gdiplus.GdipDeleteFontFamily(family) 531 | 532 | def __del__(self): 533 | super(GDIPlusFont, self).__del__() 534 | result = gdiplus.GdipDeleteFont(self._gdipfont) 535 | 536 | @classmethod 537 | def add_font_data(cls, data): 538 | super(GDIPlusFont, cls).add_font_data(data) 539 | 540 | if not cls._private_fonts: 541 | cls._private_fonts = ctypes.c_void_p() 542 | gdiplus.GdipNewPrivateFontCollection( 543 | ctypes.byref(cls._private_fonts)) 544 | gdiplus.GdipPrivateAddMemoryFont(cls._private_fonts, data, len(data)) 545 | 546 | @classmethod 547 | def have_font(cls, name): 548 | family = ctypes.c_void_p() 549 | 550 | # Look in private collection first: 551 | num_count = ctypes.c_int() 552 | gdiplus.GdipGetFontCollectionFamilyCount( 553 | cls._private_fonts, ctypes.byref(num_count)) 554 | gpfamilies = (ctypes.c_void_p * num_count.value)() 555 | numFound = ctypes.c_int() 556 | gdiplus.GdipGetFontCollectionFamilyList( 557 | cls._private_fonts, num_count, gpfamilies, ctypes.byref(numFound)) 558 | 559 | font_name = ctypes.create_unicode_buffer(32) 560 | for gpfamily in gpfamilies: 561 | gdiplus.GdipGetFamilyName(gpfamily, font_name, '\0') 562 | if font_name.value == name: 563 | return True 564 | 565 | # Else call parent class for system fonts 566 | return super(GDIPlusFont, cls).have_font(name) --------------------------------------------------------------------------------