crystalwindow 2.5.8__tar.gz → 2.7.8__tar.gz

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.
Files changed (39) hide show
  1. crystalwindow-2.7.8/LICENSE +21 -0
  2. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/PKG-INFO +3 -1
  3. crystalwindow-2.7.8/crystalwindow/FileHelper.py +142 -0
  4. crystalwindow-2.7.8/crystalwindow/__init__.py +57 -0
  5. crystalwindow-2.7.8/crystalwindow/animation.py +15 -0
  6. crystalwindow-2.7.8/crystalwindow/assets.py +30 -0
  7. crystalwindow-2.7.8/crystalwindow/collision.py +15 -0
  8. crystalwindow-2.7.8/crystalwindow/draw_helpers.py +23 -0
  9. crystalwindow-2.7.8/crystalwindow/draw_rects.py +36 -0
  10. crystalwindow-2.7.8/crystalwindow/draw_text_helper.py +46 -0
  11. crystalwindow-2.7.8/crystalwindow/draw_tool.py +49 -0
  12. crystalwindow-2.7.8/crystalwindow/fun_helpers.py +28 -0
  13. crystalwindow-2.7.8/crystalwindow/gametests/__init__.py +14 -0
  14. crystalwindow-2.7.8/crystalwindow/gametests/__main__.py +23 -0
  15. crystalwindow-2.7.8/crystalwindow/gametests/gravitytest.py +47 -0
  16. crystalwindow-2.7.8/crystalwindow/gametests/guitesting.py +56 -0
  17. crystalwindow-2.7.8/crystalwindow/gametests/sandbox.py +49 -0
  18. crystalwindow-2.7.8/crystalwindow/gametests/windowtesting.py +5 -0
  19. crystalwindow-2.7.8/crystalwindow/gravity.py +75 -0
  20. crystalwindow-2.7.8/crystalwindow/gui.py +69 -0
  21. crystalwindow-2.7.8/crystalwindow/gui_ext.py +66 -0
  22. crystalwindow-2.7.8/crystalwindow/math.py +40 -0
  23. crystalwindow-2.7.8/crystalwindow/player.py +106 -0
  24. crystalwindow-2.7.8/crystalwindow/sprites.py +37 -0
  25. crystalwindow-2.7.8/crystalwindow/tilemap.py +13 -0
  26. crystalwindow-2.7.8/crystalwindow/ver_warner.py +54 -0
  27. crystalwindow-2.7.8/crystalwindow/window.py +218 -0
  28. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/crystalwindow.egg-info/PKG-INFO +3 -1
  29. crystalwindow-2.7.8/crystalwindow.egg-info/SOURCES.txt +35 -0
  30. crystalwindow-2.7.8/crystalwindow.egg-info/top_level.txt +1 -0
  31. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/setup.py +2 -2
  32. crystalwindow-2.5.8/crystalwindow.egg-info/SOURCES.txt +0 -9
  33. crystalwindow-2.5.8/crystalwindow.egg-info/top_level.txt +0 -1
  34. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/MANIFEST.in +0 -0
  35. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/README.md +0 -0
  36. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/crystalwindow/Icons/default_icon.png +0 -0
  37. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/crystalwindow.egg-info/dependency_links.txt +0 -0
  38. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/crystalwindow.egg-info/requires.txt +0 -0
  39. {crystalwindow-2.5.8 → crystalwindow-2.7.8}/setup.cfg +0 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 C
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 2.5.8
3
+ Version: 2.7.8
4
4
  Summary: Easier Pygame!, Made by Crystal!!
5
5
  Author: CrystalBallyHereXD
6
6
  Author-email: mavilla.519@gmail.com
@@ -8,12 +8,14 @@ Classifier: Programming Language :: Python :: 3
8
8
  Classifier: Operating System :: OS Independent
9
9
  Requires-Python: >=3.1
10
10
  Description-Content-Type: text/markdown
11
+ License-File: LICENSE
11
12
  Requires-Dist: pygame>=2.3.0
12
13
  Dynamic: author
13
14
  Dynamic: author-email
14
15
  Dynamic: classifier
15
16
  Dynamic: description
16
17
  Dynamic: description-content-type
18
+ Dynamic: license-file
17
19
  Dynamic: requires-dist
18
20
  Dynamic: requires-python
19
21
  Dynamic: summary
@@ -0,0 +1,142 @@
1
+ """
2
+ CrystalWindow FileHelper
3
+ ------------------------
4
+ A utility class that handles saving/loading text, JSON, and pickle files,
5
+ with optional Tk file dialogs and a default 'saves' directory.
6
+ """
7
+
8
+ import os
9
+ import json
10
+ import pickle
11
+ import tkinter as tk
12
+ from tkinter import filedialog
13
+
14
+
15
+ class FileHelper:
16
+ """CrystalWindow integrated file helper with default folders & Tk dialogs."""
17
+
18
+ def __init__(self, default_save_folder="saves"):
19
+ """
20
+ Initialize the FileHelper.
21
+
22
+ Args:
23
+ default_save_folder (str): Folder to save files in by default.
24
+ Created automatically if missing.
25
+ """
26
+ self.default_save_folder = default_save_folder
27
+ os.makedirs(self.default_save_folder, exist_ok=True)
28
+
29
+ # -------------------------------------------------------------------------
30
+ # TK FILE DIALOGS
31
+ # -------------------------------------------------------------------------
32
+ def ask_save_file(self, default_name="save.json",
33
+ filetypes=[("JSON files", "*.json"), ("All files", "*.*")]):
34
+ """Open a Tkinter Save dialog starting in the default folder."""
35
+ root = tk.Tk()
36
+ root.withdraw()
37
+ path = filedialog.asksaveasfilename(
38
+ title="Save As",
39
+ initialdir=self.default_save_folder,
40
+ initialfile=default_name,
41
+ filetypes=filetypes,
42
+ defaultextension=filetypes[0][1]
43
+ )
44
+ root.destroy()
45
+ return path if path else None # Return None if cancelled
46
+
47
+ def ask_open_file(self,
48
+ filetypes=[("JSON files", "*.json"), ("All files", "*.*")]):
49
+ """Open a Tkinter Open dialog starting in the default folder."""
50
+ root = tk.Tk()
51
+ root.withdraw()
52
+ path = filedialog.askopenfilename(
53
+ title="Open File",
54
+ initialdir=self.default_save_folder,
55
+ filetypes=filetypes
56
+ )
57
+ root.destroy()
58
+ return path if path else None
59
+
60
+ # -------------------------------------------------------------------------
61
+ # INTERNAL PATH HELPER
62
+ # -------------------------------------------------------------------------
63
+ def _resolve_path(self, filename):
64
+ """Return a full path, resolving relative paths to the default folder."""
65
+ if not filename:
66
+ return None
67
+ if os.path.isabs(filename):
68
+ return filename
69
+ return os.path.join(self.default_save_folder, filename)
70
+
71
+ # -------------------------------------------------------------------------
72
+ # TEXT FILES
73
+ # -------------------------------------------------------------------------
74
+ def save_text(self, filename, content):
75
+ """Save plain text data to a file."""
76
+ path = self._resolve_path(filename)
77
+ if not path:
78
+ print("[CANCELLED] No save path provided.")
79
+ return None
80
+ os.makedirs(os.path.dirname(path), exist_ok=True)
81
+ with open(path, "w", encoding="utf-8") as f:
82
+ f.write(content)
83
+ print(f"[INFO] Text saved to: {path}")
84
+ return path
85
+
86
+ def load_text(self, filename):
87
+ """Load plain text data from a file."""
88
+ path = self._resolve_path(filename)
89
+ if path and os.path.exists(path):
90
+ with open(path, "r", encoding="utf-8") as f:
91
+ return f.read()
92
+ print(f"[WARN] Text file not found: {path}")
93
+ return None
94
+
95
+ # -------------------------------------------------------------------------
96
+ # JSON FILES
97
+ # -------------------------------------------------------------------------
98
+ def save_json(self, filename, data):
99
+ """Save JSON-serializable data."""
100
+ path = self._resolve_path(filename)
101
+ if not path:
102
+ print("[CANCELLED] No save path provided.")
103
+ return None
104
+ os.makedirs(os.path.dirname(path), exist_ok=True)
105
+ with open(path, "w", encoding="utf-8") as f:
106
+ json.dump(data, f, indent=4)
107
+ print(f"[INFO] JSON saved to: {path}")
108
+ return path
109
+
110
+ def load_json(self, filename):
111
+ """Load JSON data."""
112
+ path = self._resolve_path(filename)
113
+ if path and os.path.exists(path):
114
+ with open(path, "r", encoding="utf-8") as f:
115
+ return json.load(f)
116
+ print(f"[WARN] JSON file not found: {path}")
117
+ return None
118
+
119
+ # -------------------------------------------------------------------------
120
+ # PICKLE FILES
121
+ # -------------------------------------------------------------------------
122
+ def save_pickle(self, filename, obj):
123
+ """Save a Python object using pickle."""
124
+ path = self._resolve_path(filename)
125
+ if not path:
126
+ print("[CANCELLED] No save path provided.")
127
+ return None
128
+ os.makedirs(os.path.dirname(path), exist_ok=True)
129
+ with open(path, "wb") as f:
130
+ pickle.dump(obj, f)
131
+ print(f"[INFO] Pickle saved to: {path}")
132
+ return path
133
+
134
+ def load_pickle(self, filename):
135
+ """Load a pickled Python object."""
136
+ path = self._resolve_path(filename)
137
+ if path and os.path.exists(path):
138
+ with open(path, "rb") as f:
139
+ return pickle.load(f)
140
+ print(f"[WARN] Pickle file not found: {path}")
141
+ return None
142
+
@@ -0,0 +1,57 @@
1
+ # crystalwindow/__init__.py
2
+ # 💎 CrystalWindow - Master Import Hub
3
+ from .ver_warner import check_for_update
4
+ check_for_update("crystalwindow")
5
+
6
+ # === Core Systems ===
7
+ from .window import Window
8
+ from .sprites import Sprite
9
+ from .tilemap import TileMap
10
+ from .player import Player
11
+ from .gravity import Gravity
12
+ from .FileHelper import FileHelper
13
+ from .math import Mathematics
14
+
15
+ # === Assets & Animation ===
16
+ from .assets import load_image, load_folder_images, load_music, play_music
17
+ from .animation import Animation
18
+
19
+ # === Collision ===
20
+ from .collision import check_collision, resolve_collision
21
+
22
+ # === GUI & Extensions ===
23
+ from .gui import Button, Label, GUIManager, random_color, hex_to_rgb
24
+ from .gui_ext import Toggle, Slider
25
+
26
+ # === Drawing Helpers ===
27
+ from .draw_helpers import gradient_rect, CameraShake
28
+ from .draw_rects import DrawHelper
29
+ from .draw_text_helper import DrawTextManager
30
+ from .draw_tool import CrystalDraw
31
+
32
+ # === Misc Helpers ===
33
+ from .fun_helpers import random_name, DebugOverlay
34
+
35
+
36
+ __all__ = [
37
+ # --- Core ---
38
+ "Window", "Sprite", "TileMap", "Player", "Gravity", "FileHelper", "Mathematics",
39
+
40
+ # --- Assets & Animation ---
41
+ "load_image", "load_folder_images", "load_music", "play_music", "Animation",
42
+
43
+ # --- Collision ---
44
+ "check_collision", "resolve_collision",
45
+
46
+ # --- GUI ---
47
+ "Button", "Label", "GUIManager", "random_color", "hex_to_rgb",
48
+
49
+ # --- GUI Extensions ---
50
+ "Toggle", "Slider",
51
+
52
+ # --- Drawing ---
53
+ "gradient_rect", "CameraShake", "DrawHelper", "DrawTextManager", "CrystalDraw",
54
+
55
+ # --- Misc ---
56
+ "random_name", "DebugOverlay",
57
+ ]
@@ -0,0 +1,15 @@
1
+ class Animation:
2
+ def __init__(self, frames, speed=0.1):
3
+ self.frames = frames
4
+ self.speed = speed
5
+ self.current = 0
6
+ self.timer = 0
7
+
8
+ def update(self, dt):
9
+ self.timer += dt
10
+ if self.timer >= self.speed:
11
+ self.timer = 0
12
+ self.current = (self.current + 1) % len(self.frames)
13
+
14
+ def get_frame(self):
15
+ return self.frames[self.current]
@@ -0,0 +1,30 @@
1
+ import os
2
+ from tkinter import PhotoImage
3
+
4
+ ASSETS = {}
5
+
6
+ def load_image(path, size=None):
7
+ if not os.path.exists(path):
8
+ raise FileNotFoundError(f"Image not found: {path}")
9
+ img = PhotoImage(file=path)
10
+ ASSETS[path] = img
11
+ return img
12
+
13
+ def load_folder_images(folder, nested=True):
14
+ result = {}
15
+ for item in os.listdir(folder):
16
+ full_path = os.path.join(folder, item)
17
+ if os.path.isdir(full_path) and nested:
18
+ result[item] = load_folder_images(full_path, nested=True)
19
+ elif item.lower().endswith((".png", ".gif")): # Tk supports PNG/GIF
20
+ result[item] = load_image(full_path)
21
+ return result
22
+
23
+ def load_music(path):
24
+ """No-op: Tkinter does not handle music. Placeholder for compatibility."""
25
+ print(f"[assets] Music loading not supported in this current crystalwindow ver sorry! ~Crystal: {path}")
26
+ return None
27
+
28
+ def play_music(loop=-1):
29
+ """No-op: placeholder."""
30
+ print("[assets] Music playback not supported in this current crystalwindow ver sorry! ~Crystal")
@@ -0,0 +1,15 @@
1
+ def check_collision(sprite, tiles):
2
+ for t in tiles:
3
+ if sprite.rect.colliderect(t.rect):
4
+ return True
5
+ return False
6
+
7
+ def resolve_collision(sprite, tiles, dy):
8
+ sprite.rect.y += dy
9
+ collided = [t for t in tiles if sprite.rect.colliderect(t.rect)]
10
+ for t in collided:
11
+ if dy > 0:
12
+ sprite.rect.bottom = t.rect.top
13
+ elif dy < 0:
14
+ sprite.rect.top = t.rect.bottom
15
+ sprite.y = sprite.rect.y
@@ -0,0 +1,23 @@
1
+ from .window import Window
2
+
3
+ def gradient_rect(win, rect, color_start, color_end, vertical=True):
4
+ x,y,w,h = rect
5
+ for i in range(h if vertical else w):
6
+ t = i/(h if vertical else w)
7
+ r = int(color_start[0]*(1-t) + color_end[0]*t)
8
+ g = int(color_start[1]*(1-t) + color_end[1]*t)
9
+ b = int(color_start[2]*(1-t) + color_end[2]*t)
10
+ if vertical:
11
+ win.draw_rect((r,g,b), (x,y+i,w,1))
12
+ else:
13
+ win.draw_rect((r,g,b), (x+i,y,1,h))
14
+
15
+ class CameraShake:
16
+ def __init__(self, intensity=5):
17
+ self.intensity = intensity
18
+ self.offset = (0,0)
19
+
20
+ def update(self):
21
+ import random
22
+ self.offset = (random.randint(-self.intensity,self.intensity),
23
+ random.randint(-self.intensity,self.intensity))
@@ -0,0 +1,36 @@
1
+ from crystalwindow import *
2
+
3
+ class DrawHelper:
4
+ def rect(self, win, x, y, w, h, color):
5
+ win.draw_rect(color, (x, y, w, h))
6
+ return self
7
+
8
+ def square(self, win, x, y, size, color):
9
+ win.draw_rect(color, (x, y, size, size))
10
+ return self
11
+
12
+ def circle(self, win, x, y, radius, color):
13
+ win.draw_circle(color, (x, y), radius)
14
+ return self
15
+
16
+ def triangle(self, win, points, color):
17
+ flat_points = [coord for pt in points for coord in pt]
18
+ win.canvas.create_polygon(flat_points, fill=win._to_hex(color))
19
+ return self
20
+
21
+ def text(self, win, text, font="Arial", size=16, x=0, y=0, color=(255,255,255), bold=False, cursive=False):
22
+ win.draw_text(text, font=font, size=size, pos=(x, y), color=color, bold=bold, italic=cursive)
23
+ return self
24
+
25
+ def gradient_rect(self, win, x, y, w, h, start_color, end_color, vertical=True):
26
+ for i in range(h if vertical else w):
27
+ ratio = i / (h if vertical else w)
28
+ r = int(start_color[0]*(1-ratio) + end_color[0]*ratio)
29
+ g = int(start_color[1]*(1-ratio) + end_color[1]*ratio)
30
+ b = int(start_color[2]*(1-ratio) + end_color[2]*ratio)
31
+ color = f"#{r:02x}{g:02x}{b:02x}"
32
+ if vertical:
33
+ win.canvas.create_line(x, y+i, x+w, y+i, fill=color)
34
+ else:
35
+ win.canvas.create_line(x+i, y, x+i, y+h, fill=color)
36
+ return self
@@ -0,0 +1,46 @@
1
+ #draw_text_helper.py
2
+ from .window import Window
3
+
4
+ class DrawTextManager:
5
+ def __init__(self):
6
+ self.texts = []
7
+
8
+ def add_text(self, text, pos=(0,0), size=16, color=(255,255,255), bold=False, italic=False, duration=None):
9
+ """
10
+ text: str
11
+ pos: (x,y)
12
+ size: int
13
+ color: RGB tuple
14
+ bold: bool
15
+ italic: bool
16
+ duration: float seconds or None for permanent
17
+ """
18
+ self.texts.append({
19
+ "text": text,
20
+ "pos": pos,
21
+ "size": size,
22
+ "color": color,
23
+ "bold": bold,
24
+ "italic": italic,
25
+ "duration": duration,
26
+ "timer": 0
27
+ })
28
+
29
+ def update(self, dt):
30
+ # update timers and remove expired text
31
+ for t in self.texts[:]:
32
+ if t["duration"] is not None:
33
+ t["timer"] += dt
34
+ if t["timer"] >= t["duration"]:
35
+ self.texts.remove(t)
36
+
37
+ def draw(self, win: Window):
38
+ for t in self.texts:
39
+ win.draw_text(
40
+ t["text"],
41
+ pos=t["pos"],
42
+ size=t["size"],
43
+ color=t["color"],
44
+ bold=t["bold"],
45
+ italic=t["italic"]
46
+ )
@@ -0,0 +1,49 @@
1
+ from .gui import hex_to_rgb
2
+
3
+ class CrystalDraw:
4
+ def __init__(self, win, brush_color="#00aaff", brush_size=8, canvas_rect=None):
5
+ """
6
+ win: CrystalWindow instance
7
+ brush_color: color string or tuple
8
+ brush_size: int
9
+ canvas_rect: (x, y, w, h) optional drawing area
10
+ """
11
+ self.win = win
12
+ self.brush_color = hex_to_rgb(brush_color)
13
+ self.brush_size = brush_size
14
+ self.drawing = False
15
+ self.last_pos = None
16
+ self.canvas_rect = canvas_rect or (0, 0, win.width, win.height)
17
+
18
+ def set_color(self, color):
19
+ if isinstance(color, str):
20
+ self.brush_color = hex_to_rgb(color)
21
+ else:
22
+ self.brush_color = color
23
+
24
+ def set_brush_size(self, size):
25
+ self.brush_size = max(1, int(size))
26
+
27
+ def clear(self):
28
+ self.win.fill((255,255,255))
29
+
30
+ def update(self):
31
+ """Draw if mouse pressed."""
32
+ x, y, w, h = self.canvas_rect
33
+ mx, my = self.win.mouse_pos
34
+ in_bounds = x <= mx <= x+w and y <= my <= y+h
35
+
36
+ if self.win.mouse_pressed(1) and in_bounds:
37
+ if self.last_pos:
38
+ self.win.canvas.create_line(
39
+ self.last_pos[0], self.last_pos[1], mx, my,
40
+ fill=self._to_hex(self.brush_color),
41
+ width=self.brush_size,
42
+ capstyle="round", smooth=True
43
+ )
44
+ self.last_pos = (mx, my)
45
+ else:
46
+ self.last_pos = None
47
+
48
+ def _to_hex(self, color):
49
+ return f"#{color[0]:02x}{color[1]:02x}{color[2]:02x}"
@@ -0,0 +1,28 @@
1
+ import random
2
+
3
+ # random color helpers
4
+ def random_color():
5
+ return (random.randint(0,255), random.randint(0,255), random.randint(0,255))
6
+
7
+ def random_palette(n=5):
8
+ return [random_color() for _ in range(n)]
9
+
10
+ # random name generator
11
+ def random_name():
12
+ syllables = ["ka","zi","lo","ra","mi","to","na","ve"]
13
+ return "".join(random.choice(syllables) for _ in range(3))
14
+
15
+ # tween helper
16
+ def lerp(a, b, t):
17
+ return a + (b - a) * t
18
+
19
+ # debug overlay
20
+ class DebugOverlay:
21
+ def __init__(self):
22
+ self.active = True
23
+
24
+ def draw(self, win, fps=60):
25
+ if self.active:
26
+ win.draw_text(f"FPS: {fps}", pos=(10,10))
27
+ mx,my = win.mouse_pos
28
+ win.draw_text(f"Mouse: {mx},{my}", pos=(10,30))
@@ -0,0 +1,14 @@
1
+ """
2
+ CrystalWindow Example Demos
3
+ ---------------------------
4
+ Run demos like this:
5
+
6
+ python -m CrystalWindow.examples.<demo_name>
7
+
8
+ Available demos:
9
+ guitesting → GUI widgets & layout demo
10
+ gravitytest → Physics & gravity simulation
11
+ windowtesting → Basic window + drawing
12
+ sandbox → Open testbed for experiments
13
+ """
14
+ __all__ = ["guitesting", "gravitytest", "windowtesting", "sandbox"]
@@ -0,0 +1,23 @@
1
+ # crystalWindow/examples/__main__.py
2
+ import importlib
3
+
4
+ DEMO_SCRIPTS = {
5
+ "guitesting": "GUI widgets & layout demo",
6
+ "gravitytest": "Gravity + physics test",
7
+ "windowtesting": "Basic window and draw test",
8
+ "sandbox": "Free experiment playground",
9
+ }
10
+
11
+ def list_demos():
12
+ print("CrystalWindow Example Demos 🧊")
13
+ print("--------------------------------")
14
+ for name, desc in DEMO_SCRIPTS.items():
15
+ print(f"{name:<15} - {desc}")
16
+ print("\nRun one with:")
17
+ print(" python -m cystalWindow.examples.<demo_name>\n")
18
+
19
+ def main():
20
+ list_demos()
21
+
22
+ if __name__ == "__main__":
23
+ main()
@@ -0,0 +1,47 @@
1
+ from crystalwindow import *
2
+
3
+ # --- custom player/ball class ---
4
+ class PlayerRect:
5
+ def __init__(self, x, y, w=32, h=32, color=(255,0,0)):
6
+ self.x = x
7
+ self.y = y
8
+ self.width = w
9
+ self.height = h
10
+ self.color = color
11
+ self.vel_y = 0
12
+
13
+ # draw either sprite or rect
14
+ def draw(self, win):
15
+ win.draw_rect(self.color, (self.x, self.y, self.width, self.height))
16
+
17
+ # --- setup window ---
18
+ win = Window(800, 600, "Gravity Sprite/Rect Test")
19
+
20
+ # --- player as colored rect ---
21
+ player = PlayerRect(100, 100, 50, 50, color=(0,255,0))
22
+
23
+ # --- platform as rect ---
24
+ class Platform:
25
+ def __init__(self, x, y, w, h, color=(100,200,100)):
26
+ self.x = x
27
+ self.y = y
28
+ self.width = w
29
+ self.height = h
30
+ self.color = color
31
+ def draw(self, win):
32
+ win.draw_rect(self.color, (self.x, self.y, self.width, self.height))
33
+
34
+ platform = Platform(0, 500, 800, 50)
35
+
36
+ # --- attach gravity ---
37
+ player.gravity = Gravity(player, force=1, bouncy=True, bounce_strength=0.7)
38
+
39
+ # --- main loop ---
40
+ def update(win):
41
+ player.gravity.update(1/60, [platform])
42
+ win.screen.fill((20,20,50))
43
+ player.draw(win)
44
+ platform.draw(win)
45
+
46
+ win.run(update)
47
+ win.quit()
@@ -0,0 +1,56 @@
1
+ from crystalwindow import *
2
+
3
+ # --- Window setup ---
4
+ win = Window(800, 600, "CrystalWindowLib Mega Sandbox")
5
+
6
+ # --- GUI ---
7
+ gui = GUIManager()
8
+ toggle1 = Toggle((50, 50, 100, 40), value=False)
9
+ slider1 = Slider((50, 120, 200, 30), min_val=0, max_val=100, value=50)
10
+
11
+ btn1 = Button(rect=(50, 200, 150, 50), text="Click Me!", color=random_color(),
12
+ hover_color=random_color(), callback=lambda: print("Button clicked!"))
13
+ lbl1 = Label((250, 50), "Hello GUI!", color=random_color(), size=24)
14
+
15
+ gui.add(toggle1)
16
+ gui.add(slider1)
17
+ gui.add(btn1)
18
+ gui.add(lbl1)
19
+
20
+ # --- Debug Overlay ---
21
+ debug = DebugOverlay()
22
+
23
+ # --- Camera Shake ---
24
+ shake = CameraShake(intensity=20)
25
+
26
+ # --- Main loop ---
27
+ def update(win):
28
+ gui.update(win)
29
+ gui.draw(win)
30
+
31
+ # --- draw text examples ---
32
+ win.draw_text("Normal Text", pos=(400, 50), size=18, color=random_color())
33
+ win.draw_text("Bold Text", pos=(400, 80), size=20, color=random_color(), bold=True)
34
+ win.draw_text("Italic Text", pos=(400, 110), size=20, color=random_color(), italic=True)
35
+ win.draw_text("Bold + Italic", pos=(400, 140), size=22, color=random_color(), bold=True, italic=True)
36
+
37
+ # --- draw toggle/slider values ---
38
+ win.draw_text(f"Toggle: {toggle1.value}", pos=(50, 90), size=18)
39
+ win.draw_text(f"Slider: {int(slider1.value)}", pos=(50, 160), size=18)
40
+
41
+ # --- draw gradient ---
42
+ gradient_rect(win, (50, 300, 200, 100), (255,0,0), (0,0,255))
43
+
44
+ # --- screen shake example (move a rectangle with shake) ---
45
+ shake.update()
46
+ x_off, y_off = shake.offset
47
+ win.draw_rect((0,255,0), (500+x_off, 300+y_off, 100, 50))
48
+
49
+ # --- draw random name + color ---
50
+ win.draw_text(f"Random Name: {random_name()}", pos=(50, 420), size=20, color=random_color())
51
+
52
+ # --- debug overlay ---
53
+ debug.draw(win, fps=int(win.clock.get_fps()))
54
+
55
+ win.run(update)
56
+ win.quit()