crystalwindow 5.1__py3-none-any.whl → 5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
crystalwindow/Fonts.py ADDED
@@ -0,0 +1,30 @@
1
+ import os
2
+ from PIL import ImageFont
3
+
4
+ class Font:
5
+ def __init__(self, size=16, font_name="Arial", font_path=None):
6
+ self.size = size
7
+ self.font_name = font_name
8
+ self.font_path = font_path
9
+ self.font = self.load_font()
10
+
11
+ def load_font(self):
12
+ try:
13
+ if self.font_path and os.path.isfile(self.font_path):
14
+ return ImageFont.truetype(self.font_path, self.size)
15
+
16
+ return ImageFont.truetype(self.font_name, self.size)
17
+
18
+ except Exception as e:
19
+ print(f"[Font] Fallback used: {e}")
20
+ return ImageFont.load_default()
21
+
22
+ def set_size(self, new_size):
23
+ self.size = new_size
24
+ self.font = self.load_font()
25
+
26
+ def set_font(self, new_font_name=None, new_font_path=None):
27
+ if new_font_name:
28
+ self.font_name = new_font_name
29
+ self.font_path = new_font_path
30
+ self.font = self.load_font()
crystalwindow/__init__.py CHANGED
@@ -58,6 +58,12 @@ from .chatvpn import ChatVPN, ChatVPNServer
58
58
  # ==== Message Bus ====
59
59
  from .messagebus import send_message, view_message, clear_messages
60
60
 
61
+ # ==== Fonts =======
62
+ from .Fonts import Font
63
+
64
+ # === App/Window ====
65
+ from .apphelper import GameAppHelper
66
+
61
67
  __all__ = [
62
68
  # --- Core ---
63
69
  "Window", "Sprite", "TileMap", "Player", "Block", "Enemy", "Gravity", "FileHelper", "Mathematics",
@@ -103,4 +109,10 @@ __all__ = [
103
109
 
104
110
  # --- Message Bus ---
105
111
  "send_message", "view_message", "clear_messages",
112
+
113
+ # === Fonts ===
114
+ "Font",
115
+
116
+ # --- App/Window ---
117
+ "GameAppHelper",
106
118
  ]
@@ -0,0 +1,101 @@
1
+ import os
2
+ import sys
3
+ import subprocess
4
+
5
+ class GameAppHelper:
6
+ DEFAULT_APPS = {
7
+ "notepad": "notepad.exe",
8
+ "calculator": "calc.exe",
9
+ "explorer": "explorer.exe",
10
+ "cmd": "cmd.exe",
11
+ "powershell": "powershell.exe",
12
+ "taskmgr": "taskmgr.exe",
13
+ "paint": "mspaint.exe"
14
+ }
15
+
16
+ def __init__(self):
17
+ # exe_name -> list of processes
18
+ self.running_apps = {}
19
+
20
+ # -------------------------------
21
+ # OPEN DEFAULT WINDOWS APP
22
+ # -------------------------------
23
+ def open_default_app(self, app_name):
24
+ app = self.DEFAULT_APPS.get(app_name.lower())
25
+ if not app:
26
+ print(f"[AppHelper] Unknown default app: {app_name}")
27
+ return
28
+
29
+ self._launch_process(app)
30
+
31
+ # -------------------------------
32
+ # OPEN ANY APP BY PATH OR EXE
33
+ # -------------------------------
34
+ def open_app(self, app_path):
35
+ exe = os.path.basename(app_path)
36
+ self._launch_process(app_path, exe)
37
+
38
+ # -------------------------------
39
+ # INTERNAL LAUNCH
40
+ # -------------------------------
41
+ def _launch_process(self, command, exe_name=None):
42
+ try:
43
+ proc = subprocess.Popen(command)
44
+
45
+ exe = exe_name or os.path.basename(command)
46
+ exe = exe.lower()
47
+
48
+ self.running_apps.setdefault(exe, []).append(proc)
49
+
50
+ print(f"[AppHelper] Opened {exe}")
51
+
52
+ except Exception as e:
53
+ print(f"[AppHelper] Failed to open app: {e}")
54
+
55
+ # -------------------------------
56
+ # CLOSE / KILL BY EXE NAME
57
+ # -------------------------------
58
+ def close_app(self, exe_name):
59
+ exe = exe_name.lower()
60
+ procs = self.running_apps.get(exe)
61
+
62
+ if not procs:
63
+ print(f"[AppHelper] No running app named {exe}")
64
+ return
65
+
66
+ for proc in procs:
67
+ try:
68
+ proc.kill() # HARD kill
69
+ except Exception:
70
+ os.system(f"taskkill /PID {proc.pid} /F")
71
+
72
+ del self.running_apps[exe]
73
+ print(f"[AppHelper] Closed all instances of {exe}")
74
+
75
+ # -------------------------------
76
+ # CLOSE ONLY ONE INSTANCE (OPTIONAL)
77
+ # -------------------------------
78
+ def close_one(self, exe_name):
79
+ exe = exe_name.lower()
80
+ procs = self.running_apps.get(exe)
81
+
82
+ if not procs:
83
+ print(f"[AppHelper] No running app named {exe}")
84
+ return
85
+
86
+ proc = procs.pop()
87
+ try:
88
+ proc.kill()
89
+ except:
90
+ os.system(f"taskkill /PID {proc.pid} /F")
91
+
92
+ if not procs:
93
+ del self.running_apps[exe]
94
+
95
+ print(f"[AppHelper] Closed one instance of {exe}")
96
+
97
+ # -------------------------------
98
+ # CLOSE PYTHON APP
99
+ # -------------------------------
100
+ def close_current_app(self):
101
+ sys.exit()
crystalwindow/camera.py CHANGED
@@ -4,23 +4,28 @@ class Camera:
4
4
  self.offset_x = 0
5
5
  self.offset_y = 0
6
6
  self.speed = speed # smoothness
7
+ self.shake = None
7
8
 
8
9
  def update(self, win_width, win_height, dt):
9
- # camera aims for target center
10
- target_x = self.target.x - win_width // 2
11
- target_y = self.target.y - win_height // 2
10
+ # camera aims for target selected
11
+ if self.target is not None:
12
+ target_x = self.target.x - win_width // 2
13
+ target_y = self.target.y - win_height // 2
12
14
 
13
- # smooth lerp follow
14
- self.offset_x += (target_x - self.offset_x) * self.speed
15
- self.offset_y += (target_y - self.offset_y) * self.speed
15
+ # smooth lerp follow
16
+ self.offset_x += (target_x - self.offset_x) * self.speed
17
+ self.offset_y += (target_y - self.offset_y) * self.speed
18
+
19
+ if self.shake:
20
+ alive = self.shake.update(dt)
21
+ if not alive:
22
+ self.shake = None # 💥 ACTUALLY STOPS IT
16
23
 
17
- if hasattr(self, "shake"):
18
- self.shake.update(dt)
19
24
 
20
25
  def apply(self, obj):
21
26
  # shift object's draw position by camera offset
22
27
  sx, sy = (0, 0)
23
- if hasattr(self, "shake"):
28
+ if self.shake:
24
29
  sx, sy = self.shake.offset
25
30
 
26
31
  return (
@@ -33,6 +38,10 @@ class Camera:
33
38
  from .draw_helpers import CameraShake
34
39
  self.shake = CameraShake(intensity, secs)
35
40
 
41
+ # Helper if the shake_scrn dosent want to stop
42
+ def stop_shake(self):
43
+ self.shake = None
44
+
36
45
  def move_to(self, x, y):
37
46
  self.offset_x = x
38
47
  self.offset_y = y
@@ -20,11 +20,14 @@ class CameraShake:
20
20
 
21
21
  def update(self, dt):
22
22
  import random
23
+
23
24
  if self.time_left > 0:
24
25
  self.time_left -= dt
25
26
  self.offset = (
26
27
  random.randint(-self.intensity, self.intensity),
27
28
  random.randint(-self.intensity, self.intensity)
28
29
  )
30
+ return True
29
31
  else:
30
32
  self.offset = (0, 0)
33
+ return False
crystalwindow/objects.py CHANGED
@@ -128,12 +128,20 @@ class Player(Sprite):
128
128
  # BLOCK (same)
129
129
  # ============================================================
130
130
  class Block(Sprite):
131
- def __init__(self, pos, w, h, color=None, texture=None):
131
+ def __init__(self, x, y, w, h, color=None, texture=None):
132
+ self.x = x
133
+ self.y = y
134
+ self.w, self.h = w, h
135
+ self.color = color
136
+
132
137
  if texture:
133
138
  img = load_image(texture)
134
- super().__init__(pos, size=(w, h), image=img)
139
+ super().__init__((x, y), size=(w, h), image=img)
135
140
  else:
136
- super().__init__(pos, size=(w, h), color=color or (150,150,150))
141
+ super().__init__((x, y), size=(w, h), color=color or (150,150,150))
142
+
143
+ def draw(self, win):
144
+ win.draw_rect(self.color, (self.x, self.y, self.w, self.h))
137
145
 
138
146
  def collide_with(self, other):
139
147
  return self.colliderect(other)
crystalwindow/window.py CHANGED
@@ -153,7 +153,7 @@ class Window:
153
153
  self._bg_color = (20, 20, 50)
154
154
  self.draw_calls = []
155
155
  self._key_last = {} # new dict to store last press time per key
156
- self._key_cooldown = 0.00001 # seconds, tweak for faster/slower input
156
+ self._key_cooldown = 0.0001 # seconds, tweak for faster/slower input
157
157
 
158
158
  # === Event bindings ===
159
159
  self.root.bind("<KeyPress>", self._on_keydown)
@@ -193,6 +193,7 @@ class Window:
193
193
  pressed[event.num - 1] = False
194
194
  self._mouse_pressed = tuple(pressed)
195
195
 
196
+
196
197
  # === Helpers ===
197
198
  def key_pressed(self, key):
198
199
  if isinstance(key, str):
@@ -208,6 +209,11 @@ class Window:
208
209
 
209
210
  return False
210
211
 
212
+ def key_held(self, key):
213
+ if isinstance(key, str):
214
+ key = self.KEY_MAP.get(key, key)
215
+ return self.keys.get(key, False)
216
+
211
217
  def mouse_pressed(self, button=1):
212
218
  return self._mouse_pressed[button - 1]
213
219
  def add_tab(self, title, widget):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 5.1
3
+ Version: 5.3
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (ME)! Easier apps, smoother UI and all-in-one helpers!, Gui, Buttons, FileHelper, Sprites, Animations, Colors, Math, Gravity, Camera, 3D and more!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -1,15 +1,17 @@
1
1
  crystalwindow/FileHelper.py,sha256=U20iwND4jX1y91TOK46e8MPH8xyw7GOrZ697nPEnOPk,10706
2
- crystalwindow/__init__.py,sha256=dqow94sID2DEnUwiIFtmz38RrVGautAVMz1c4Wrt6BU,2953
2
+ crystalwindow/Fonts.py,sha256=XGqmM3GaauM5a74BtqhKk9zzKgQPcHyN3vcOP1TeoOs,954
3
+ crystalwindow/__init__.py,sha256=9KgD3KnjkDbq2sFUaT3_uDwHd_vgGnAFO2vy0f59ZtA,3151
3
4
  crystalwindow/ai.py,sha256=YIt6dNe1QljSAlNECCVa3DMUSIqQEJRIAAbQpYqFNNo,11525
4
5
  crystalwindow/animation.py,sha256=zHjrdBXQeyNaLAuaGPldJueX05OZ5j31YR8NizmR0uQ,427
6
+ crystalwindow/apphelper.py,sha256=CAcX5n0Jq7zdBMFZkwbMt3_M0mBVVZRoXldOcXsZan4,2924
5
7
  crystalwindow/assets.py,sha256=8MxPSk7W5YcBnKDh6KcLdg34uxmACf_m6feSYFCWHqA,11405
6
- crystalwindow/camera.py,sha256=1PGGzCCelI6a7aWOuiqqM2OgmrHOBeyobAnSbX-tWgw,1338
8
+ crystalwindow/camera.py,sha256=fe0DXIcZ-TSVPPHxRptFufadnkhysWRZDTJxjxf6SEo,1606
7
9
  crystalwindow/chatvpn.py,sha256=Ij3wRNrMbPINO-SX9vx8xlrKRLvG7zJgzAN2T0jzSz8,2477
8
10
  crystalwindow/clock.py,sha256=M7oMjnGNkFOcchqtQn_voWao4kFtxXpTJe2VUjqvGKQ,5041
9
11
  crystalwindow/collision.py,sha256=hpkHTp_KparghVK-itp_rxuYdd2GbQMxICHlUBv0rSw,472
10
12
  crystalwindow/color_handler.py,sha256=K3LipCPOjYt1NemeT-hNWf886LL59QgRN8ifHOi7-0M,3255
11
13
  crystalwindow/crystal3d.py,sha256=8n42S71NZWgBgYwP8ZWfobXFeWvNrhJY80YGK-PzI8s,5375
12
- crystalwindow/draw_helpers.py,sha256=S1jkZbq-9NZrBPJ3tAl1abIc0M-GgNJkHfOtEnQZuS4,1019
14
+ crystalwindow/draw_helpers.py,sha256=ufRmThOJi4MlZsoR8GRx0eoH55qu8EGUlg_uPtkW9WA,1073
13
15
  crystalwindow/draw_rects.py,sha256=o7siET3y35N2LPeNBGe8QhsQbOH8J-xF6fOUz07rymU,1484
14
16
  crystalwindow/draw_text_helper.py,sha256=qv5fFCuTCKWeGDk9Z_ZpOzrTFP8YYwlgQrrorwrq9Hg,1298
15
17
  crystalwindow/draw_tool.py,sha256=1YYEqjmgt4HpV3S15sTjCSmcqgHup4fD8gskTkxU0t4,1638
@@ -19,12 +21,12 @@ crystalwindow/gui.py,sha256=9JA25IztgqSYN1NnWVKK99G0rlEosXf2ATWww2rUZIQ,5353
19
21
  crystalwindow/gui_ext.py,sha256=JctpNPr7gtGdro3csyUo9ft3FFArj3JhkVlgKF0lyME,3407
20
22
  crystalwindow/math.py,sha256=slOY3KQZ99VDMUMxsSJabMyRtJcwVzEyxR2RoXspHho,963
21
23
  crystalwindow/messagebus.py,sha256=9K2P_TkdQ1rt-oouIkRg_XHwMTwykttBt-9gFYaItyI,696
22
- crystalwindow/objects.py,sha256=zps-5taLGTmIvlZ76VQhvVHK2NtrrQyxBQMHGwEsCIM,5401
24
+ crystalwindow/objects.py,sha256=InChyxjOWya-XdYXGIAn9rp0waQkLvhTsRWZ0ANYHIU,5606
23
25
  crystalwindow/sprites.py,sha256=IADCQetFDQoat3qGpKkH93TdtqqgldfHl4N0HKX1Ajc,7480
24
26
  crystalwindow/tilemap.py,sha256=endJ8KcbP9EjPvL9qWsOpV4jc_Re1yH080aUyDkwufA,3378
25
27
  crystalwindow/ver_warner.py,sha256=qEN3ulc1NixBy15FFx2R3Zu0DhyJTVJwiESGAPwpynM,3373
26
28
  crystalwindow/websearch.py,sha256=IgsoKt27yCBHeq8yFVfSq_8sEj5KP6mqn2yNRTsRw1A,5161
27
- crystalwindow/window.py,sha256=qfz0e8dhLH0ZfoqjswFu20NJqh3Ln6rhaZ3v626Uewk,31849
29
+ crystalwindow/window.py,sha256=BKCoWRvMPz2wpY8gud-pI8c7KlvN213g-Z0ma9NWgYo,32004
28
30
  crystalwindow/Icons/default_icon.png,sha256=Loq27Pxb8Wb3Sz-XwtNF1RmlLNxR4TcfOWfK-1lWcII,7724
29
31
  crystalwindow/Icons/file_icons.png,sha256=kqjvz3gMaIbepW4XGrLZOjDYu-yhFbVxjvylS-0RO4U,5659
30
32
  crystalwindow/docs/getting_started.md,sha256=e_XEhJk8eatS22MX0nRX7hQNkYkwN9both1ObabZSTw,5759
@@ -38,8 +40,8 @@ crystalwindow/gametests/sandbox.py,sha256=Oo2tU2N0y3BPVa6T5vs_h9N6islhQrjSrr_78X
38
40
  crystalwindow/gametests/squaremove.py,sha256=ei6DMnvcgpOhmxbGv-Yqmx5EqiZjKbVlZhI7YbT2hY8,643
39
41
  crystalwindow/gametests/testtttagain.py,sha256=oIhK9MGgMVly_W2lRwD9Hn9WyPdd8JnX2HGrLTGZdxY,373
40
42
  crystalwindow/gametests/windowtesting.py,sha256=_9X6wnV1-_X_PtNS-0zu-k209NtFIwAc4vpxLPp7V2o,97
41
- crystalwindow-5.1.dist-info/licenses/LICENSE,sha256=Gt5cJRchdNt0guxyQMHKsATN5PM5mjuDhdO6Gzs9qQc,1096
42
- crystalwindow-5.1.dist-info/METADATA,sha256=FZFBz4n7kKSScSqNqT1mxn5pM05SgwcCBqMmwqC29XE,7523
43
- crystalwindow-5.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
44
- crystalwindow-5.1.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
45
- crystalwindow-5.1.dist-info/RECORD,,
43
+ crystalwindow-5.3.dist-info/licenses/LICENSE,sha256=Gt5cJRchdNt0guxyQMHKsATN5PM5mjuDhdO6Gzs9qQc,1096
44
+ crystalwindow-5.3.dist-info/METADATA,sha256=9idMbxFLS1FsRrERYM_3EdKxzsdk94uarm--gID2PpM,7523
45
+ crystalwindow-5.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
46
+ crystalwindow-5.3.dist-info/top_level.txt,sha256=PeQSld4b19XWT-zvbYkvE2Xg8sakIMbDzSzSdOSRN8o,14
47
+ crystalwindow-5.3.dist-info/RECORD,,