crystalwindow 4.5__py3-none-any.whl → 4.7__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.
@@ -1,61 +1,140 @@
1
- import math, tkinter as tk
1
+ import math
2
2
 
3
+ def _lerp(a, b, t):
4
+ return a + (b - a) * t
5
+
6
+ class CW3DShape:
7
+ def __init__(self, kind, color, size=1.0, thickness=2, fill=None, texture=None,
8
+ points=5, inner_ratio=0.5):
9
+ """
10
+ kind: 'cube', 'triangle', 'circle', 'rectangle', 'pentagon', 'star', 'ngon'
11
+ color: outline color (r,g,b)
12
+ size: scale factor
13
+ thickness: line thickness
14
+ fill: optional fill color
15
+ texture: optional texture placeholder
16
+ points: number of points (for stars/ngons)
17
+ inner_ratio: for stars, inner radius ratio (0.0-1.0)
18
+ """
19
+ self.kind = kind
20
+ self.color = color
21
+ self.size = size
22
+ self.thickness = thickness
23
+ self.fill = fill
24
+ self.texture = texture
25
+
26
+ self.rot_x = 0
27
+ self.rot_y = 0
28
+ self.smooth = False
29
+ self.smooth_strength = 0.15
30
+ self._sx = 0
31
+ self._sy = 0
32
+
33
+ self.points = points
34
+ self.inner_ratio = inner_ratio
35
+
36
+ def spin(self, rx, ry):
37
+ self.rot_x += rx
38
+ self.rot_y += ry
39
+
40
+ def set_smooth(self, enable=True, strength=0.15):
41
+ self.smooth = enable
42
+ self.smooth_strength = strength
43
+
44
+ def _smoothed(self):
45
+ if not self.smooth:
46
+ return self.rot_x, self.rot_y
47
+ self._sx = _lerp(self._sx, self.rot_x, self.smooth_strength)
48
+ self._sy = _lerp(self._sy, self.rot_y, self.smooth_strength)
49
+ return self._sx, self._sy
50
+
51
+ # ----------------------------------------------------------
52
+ # DRAW ROUTE
53
+ # ----------------------------------------------------------
54
+ def draw(self, win):
55
+ w, h = win.width, win.height
56
+ rx, ry = self._smoothed()
57
+
58
+ if self.kind == "cube":
59
+ self._draw_cube(win, w, h, rx, ry)
60
+ elif self.kind == "triangle":
61
+ self._draw_triangle(win, w, h, rx, ry)
62
+ elif self.kind == "circle":
63
+ self._draw_circle(win, w, h, rx, ry)
64
+ elif self.kind == "rectangle":
65
+ self._draw_rectangle(win, w, h, rx, ry)
66
+ elif self.kind == "pentagon":
67
+ self._draw_polygon(win, w, h, 5, rx, ry)
68
+ elif self.kind == "star":
69
+ self._draw_star(win, w, h, rx, ry)
70
+ elif self.kind == "ngon":
71
+ self._draw_polygon(win, w, h, self.points, rx, ry)
72
+
73
+ # ----------------------------------------------------------
74
+ # GENERIC POLYGON
75
+ # ----------------------------------------------------------
76
+ def _draw_polygon(self, win, w, h, sides, rx, ry):
77
+ cx, cy = w//2, h//2
78
+ r = self.size * 80
79
+ verts = []
80
+ for i in range(sides):
81
+ angle = -math.pi/2 + i * 2 * math.pi / sides
82
+ verts.append((cx + math.cos(angle) * r, cy + math.sin(angle) * r))
83
+ if self.fill:
84
+ win.draw_polygon(verts, self.fill)
85
+ win.draw_polygon_outline(verts, self.color, self.thickness)
86
+
87
+ # ----------------------------------------------------------
88
+ # STAR
89
+ # ----------------------------------------------------------
90
+ def _draw_star(self, win, w, h, rx, ry):
91
+ cx, cy = w//2, h//2
92
+ outer_r = self.size * 80
93
+ inner_r = outer_r * self.inner_ratio
94
+ verts = []
95
+ step = math.pi / self.points
96
+ ang = -math.pi / 2
97
+ for i in range(self.points * 2):
98
+ r = outer_r if i % 2 == 0 else inner_r
99
+ verts.append((cx + math.cos(ang) * r, cy + math.sin(ang) * r))
100
+ ang += step
101
+ if self.fill:
102
+ win.draw_polygon(verts, self.fill)
103
+ win.draw_polygon_outline(verts, self.color, self.thickness)
104
+
105
+ # ==========================================================
106
+ # CW3D ENGINE (MANAGER)
107
+ # ==========================================================
3
108
  class CW3D:
4
109
  def __init__(self, win):
5
- self.canvas = win.canvas
6
- self.angle_x = 0
7
- self.angle_y = 0
8
- self.zoom = 200
9
- self.objects = []
10
-
11
- def project(self, x, y, z):
12
- """Simple 3D 2D projection"""
13
- scale = self.zoom / (z + 4)
14
- px = self.canvas.winfo_width()/2 + x * scale
15
- py = self.canvas.winfo_height()/2 + y * scale
16
- return px, py
17
-
18
- def rotate_point(self, x, y, z):
19
- """Rotate around X/Y axes"""
20
- y2 = y * math.cos(self.angle_x) - z * math.sin(self.angle_x)
21
- z2 = y * math.sin(self.angle_x) + z * math.cos(self.angle_x)
22
- x2 = x * math.cos(self.angle_y) + z2 * math.sin(self.angle_y)
23
- z3 = -x * math.sin(self.angle_y) + z2 * math.cos(self.angle_y)
24
- return x2, y2, z3
25
-
26
- def add_cube(self, size=1, color="cyan"):
27
- """Add a simple cube"""
28
- s = size
29
- points = [
30
- [-s, -s, -s], [s, -s, -s],
31
- [s, s, -s], [-s, s, -s],
32
- [-s, -s, s], [s, -s, s],
33
- [s, s, s], [-s, s, s],
34
- ]
35
- edges = [
36
- (0,1),(1,2),(2,3),(3,0),
37
- (4,5),(5,6),(6,7),(7,4),
38
- (0,4),(1,5),(2,6),(3,7)
39
- ]
40
- self.objects.append(("cube", points, edges, color))
110
+ self.win = win
111
+ self.shapes = []
112
+
113
+ def add_cube(self, size=1.0, color=(255,255,255), thickness=2, fill=None):
114
+ self.shapes.append(CW3DShape("cube", color, size, thickness, fill, None))
115
+
116
+ def add_triangle(self, size=1.0, color=(255,255,255), thickness=2, fill=None):
117
+ self.shapes.append(CW3DShape("triangle", color, size, thickness, fill, None))
118
+
119
+ def add_circle(self, size=1.0, color=(255,255,255), thickness=2):
120
+ self.shapes.append(CW3DShape("circle", color, size, thickness, None, None))
121
+
122
+ def add_rectangle(self, size=1.0, color=(255,255,255), thickness=2, fill=None):
123
+ self.shapes.append(CW3DShape("rectangle", color, size, thickness, fill, None))
124
+
125
+ def add_pentagon(self, size=1.0, color=(255,255,255), thickness=2, fill=None):
126
+ self.shapes.append(CW3DShape("pentagon", color, size, thickness, fill, None))
127
+
128
+ def add_star(self, size=1.0, color=(255,255,255), thickness=2, fill=None, points=5, inner_ratio=0.5):
129
+ self.shapes.append(CW3DShape("star", color, size, thickness, fill, None, points, inner_ratio))
130
+
131
+ def add_ngon(self, size=1.0, points=6, color=(255,255,255), thickness=2, fill=None):
132
+ self.shapes.append(CW3DShape("ngon", color, size, thickness, fill, None, points))
133
+
134
+ def spin(self, rx, ry):
135
+ for s in self.shapes:
136
+ s.spin(rx, ry)
41
137
 
42
138
  def draw(self):
43
- """Draw all objects"""
44
- self.canvas.delete("all")
45
- for obj in self.objects:
46
- _, pts, edges, color = obj
47
- rotated = [self.rotate_point(*p) for p in pts]
48
- for a, b in edges:
49
- x1, y1 = self.project(*rotated[a])
50
- x2, y2 = self.project(*rotated[b])
51
- self.canvas.create_line(x1, y1, x2, y2, fill=color, width=2)
52
-
53
- def spin(self, ax=0.02, ay=0.03):
54
- self.angle_x += ax
55
- self.angle_y += ay
56
-
57
- def run(self):
58
- """Auto loop"""
59
- self.draw()
60
- self.spin()
61
- self.canvas.after(16, self.run)
139
+ for s in self.shapes:
140
+ s.draw(self.win)
@@ -12,6 +12,10 @@ def random_name():
12
12
  syllables = ["ka","zi","lo","ra","mi","to","na","ve"]
13
13
  return "".join(random.choice(syllables) for _ in range(3))
14
14
 
15
+ #Choose a random number
16
+ def random_number(min_val, max_val):
17
+ return random.randint(min_val, max_val)
18
+
15
19
  # tween helper
16
20
  def lerp(a, b, t):
17
21
  return a + (b - a) * t
@@ -1,8 +1,8 @@
1
- from crystalwindow import Window, CW3D, Clock
1
+ from crystalwindow import Window, CW3DShape, Clock
2
2
 
3
3
  win = Window(800, 600, "CrystalWindow 3D Wavy Background")
4
4
  clock = Clock()
5
- cw3d = CW3D(win)
5
+ cw3d = CW3DShape(win)
6
6
  cw3d.add_cube(size=1.3, color="cyan")
7
7
 
8
8
  # brightness wave vars
@@ -1,26 +1,17 @@
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
1
+ import sys
2
+ sys.path.insert(0, r"c:/Users/USUARIO/Desktop/crystalwindow")
12
3
 
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))
4
+ from crystalwindow import *
5
+ import time
16
6
 
17
- # --- setup window ---
18
- win = Window(800, 600, "Gravity Sprite/Rect Test")
7
+ # --- window ---
8
+ win = Window(800, 600, "Debug Panel Test")
19
9
 
20
- # --- player as colored rect ---
21
- player = PlayerRect(100, 100, 50, 50, color=(0,255,0))
10
+ # --- player ---
11
+ player = Player(name="Player", pos=(0, 0), size=(32, 32), speed=4,hp=100)
12
+ enemy = Enemy((100, 100), 50, 50, 10, 0, color=(255, 0, 0))
22
13
 
23
- # --- platform as rect ---
14
+ # --- platform ---
24
15
  class Platform:
25
16
  def __init__(self, x, y, w, h, color=(100,200,100)):
26
17
  self.x = x
@@ -33,15 +24,97 @@ class Platform:
33
24
 
34
25
  platform = Platform(0, 500, 800, 50)
35
26
 
36
- # --- attach gravity ---
27
+ # --- gravity ---
37
28
  player.gravity = Gravity(player, force=1, bouncy=True, bounce_strength=0.7)
38
29
 
39
- # --- main loop ---
30
+ # ==========================================
31
+ # DEBUG PANEL SYSTEM
32
+ # ==========================================
33
+ gui = GUIManager()
34
+
35
+ panel_open = False
36
+ fly_mode = False
37
+
38
+ # panel background (Sprite.rect)
39
+ debug_panel = Sprite.rect((20, 20), 220, 140, color=(0,0,0))
40
+ debug_panel.alpha = 160 # make it transparent
41
+
42
+ # BUTTON CALLBACKS
43
+ def toggle_fly():
44
+ global fly_mode
45
+ fly_mode = not fly_mode
46
+ fly_button.text = f"Fly: {'ON' if fly_mode else 'OFF'}"
47
+
48
+ # create buttons
49
+ fly_button = Button(rect=(35, 60, 180, 40),
50
+ text="Fly: OFF",
51
+ color=(150,150,150),
52
+ hover_color=(200,200,200),
53
+ callback=toggle_fly)
54
+
55
+ gui.add(fly_button)
56
+
57
+ cooldown = 0
58
+
59
+ # ==========================================
60
+ # MAIN UPDATE
61
+ # ==========================================
40
62
  def update(win):
41
- player.gravity.update(1/60, [platform])
42
- win.screen.fill((20,20,50))
63
+ global panel_open, fly_mode, cooldown
64
+
65
+ win.fill((20,20,50))
66
+
67
+ # PANEL TOGGLE KEY
68
+ if win.key_pressed("f1") and time.time() > cooldown:
69
+ panel_open = not panel_open
70
+ cooldown = time.time() + 0.25
71
+
72
+ if win.key_pressed("f") and not panel_open and time.time() > cooldown:
73
+ fly_mode = not fly_mode
74
+ cooldown = time.time() + 0.2
75
+
76
+ # -------------------------------
77
+ # GAME LOGIC
78
+ # -------------------------------
79
+ if fly_mode:
80
+ # disable gravity
81
+ player.gravity.vel_y = 0
82
+
83
+ # free fly movement
84
+ if win.key_pressed("keyw"): player.y -= 6
85
+ if win.key_pressed("keys"): player.y += 6
86
+ if win.key_pressed("keya"): player.x -= 6
87
+ if win.key_pressed("keyd"): player.x += 6
88
+ else:
89
+ # normal gravity
90
+ player.gravity.update(1/60, [platform])
91
+
92
+ # jumping + movement
93
+ if win.key_pressed("keyw"): player.vel_y = -6
94
+ if win.key_pressed("keya"): player.x -= 10
95
+ if win.key_pressed("keyd"): player.x += 10
96
+
97
+ # draw world
43
98
  player.draw(win)
44
99
  platform.draw(win)
100
+ enemy.draw(win)
101
+
102
+ enemy.update(60)
103
+
104
+ if enemy.collide_with(player):
105
+ player.hp -= enemy.dmg
106
+ if player.dead:
107
+ player.respawn(win)
108
+
109
+ win.draw_text(f"CurrentHP: {player.hp}", font="Arial", size=16, color=(255, 255, 255))
110
+ # -------------------------------
111
+ # SHOW DEBUG PANEL
112
+ # -------------------------------
113
+ if panel_open:
114
+ debug_panel.draw(win) # panel bg
115
+ gui.draw(win) # buttons
116
+ gui.update(win) # button callbacks
117
+
45
118
 
46
119
  win.run(update)
47
120
  win.quit()
@@ -1,5 +1,9 @@
1
+ import sys
2
+ sys.path.insert(0, r"c:/Users/USUARIO/Desktop/crystalwindow")
3
+
1
4
  from crystalwindow import *
2
5
 
6
+
3
7
  # --- Window setup ---
4
8
  win = Window(800, 600, "CrystalWindowLib Mega Sandbox")
5
9
 
@@ -49,8 +53,6 @@ def update(win):
49
53
  # --- draw random name + color ---
50
54
  win.draw_text(f"Random Name: {random_name()}", pos=(50, 420), size=20, color=random_color())
51
55
 
52
- # --- debug overlay ---
53
- debug.draw(win, fps=int(win.clock.get_fps()))
54
56
 
55
57
  win.run(update)
56
58
  win.quit()
@@ -6,7 +6,7 @@ PlayerCube = Sprite.rect((400, 300), 50, 50, color=(0,100,254))
6
6
  def gamerun(win):
7
7
  PlayerCube.draw(win)
8
8
 
9
- win.draw_text("This is a crystalwindow test. (you can leave)", size=30, color=(255,255,255), pos=(25,25))
9
+ win.draw_text("This is a crystalwindow test. (you can leave using ESC)", size=21, color=(255,255,255), pos=(25,25))
10
10
 
11
11
  if win.key_pressed("keyw"):
12
12
  PlayerCube.y -= 10
@@ -17,5 +17,8 @@ def gamerun(win):
17
17
  if win.key_pressed("keyd"):
18
18
  PlayerCube.x += 10
19
19
 
20
+ if win.key_pressed("escape"):
21
+ win.quit()
22
+
20
23
  win.run(gamerun)
21
24
  win.quit()
@@ -0,0 +1,17 @@
1
+ import sys
2
+ sys.path.insert(0, r"c:/Users/USUARIO/Desktop/crystalwindow")
3
+
4
+ from crystalwindow import *
5
+
6
+ win = Window(800, 600, "Debug Panel Test")
7
+
8
+ # THIS WILL FAIL TO LOAD → fallback → checkerboard
9
+ game = load_image("SAKJDNSAOJDOSAJND;ONJSIOAJVO")
10
+
11
+ player = Sprite.image(game, (100, 100))
12
+
13
+ def gameruns(win):
14
+ player.draw(win)
15
+
16
+ win.run()
17
+ win.quit()
crystalwindow/gui.py CHANGED
@@ -2,6 +2,7 @@
2
2
  import random
3
3
  import tkinter as tk
4
4
  from crystalwindow import *
5
+ import time
5
6
 
6
7
  # ----------------- Color Helpers -----------------
7
8
  def hex_to_rgb(hex_str):
@@ -15,28 +16,96 @@ def lerp_color(c1, c2, t):
15
16
 
16
17
  # ----------------- GUI Elements -----------------
17
18
  class Button:
18
- def __init__(self, rect, text, color=(200,200,200), hover_color=(255,255,255), callback=None):
19
- self.rect = rect # (x, y, w, h)
19
+ def __init__(self, rect, text,
20
+ color=(200,200,200),
21
+ hover_color=(255,255,255),
22
+ press_color=(180,180,180),
23
+ text_color=(0,0,0)):
24
+
25
+ self.rect = rect
20
26
  self.text = text
27
+
21
28
  self.color = color
22
29
  self.hover_color = hover_color
23
- self.callback = callback
30
+ self.press_color = press_color
31
+ self.text_color = text_color
32
+
33
+ # States
24
34
  self.hovered = False
35
+ self._held = False
36
+ self._clicked = False
37
+ self._released = False
25
38
 
26
- def draw(self, win):
27
- x, y, w, h = self.rect
28
- mx, my = win.mouse_pos
29
- self.hovered = x <= mx <= x+w and y <= my <= y+h
30
- cur_color = self.hover_color if self.hovered else self.color
31
- win.draw_rect(cur_color, self.rect)
32
- win.draw_text(self.text, pos=(x+5, y+5))
39
+ self._was_down = False # mouse prev frame
40
+ self._cooldown = 0.05 # tiny debounce like Toggle
41
+ self._last_click = 0
33
42
 
34
- def check_click(self, win):
43
+ # ======================================
44
+ # UPDATE (same style as slider/toggle)
45
+ # ======================================
46
+ def update(self, win):
35
47
  mx, my = win.mouse_pos
36
48
  x, y, w, h = self.rect
37
- if x <= mx <= x+w and y <= my <= y+h and win.mouse_pressed(1):
38
- if self.callback:
39
- self.callback()
49
+
50
+ # Reset transient states
51
+ self._clicked = False
52
+ self._released = False
53
+
54
+ # Hover
55
+ self.hovered = (x <= mx <= x + w and y <= my <= y + h)
56
+
57
+ mouse_down = win.mouse_pressed(1)
58
+
59
+ # HELD
60
+ if self.hovered and mouse_down:
61
+ self._held = True
62
+ else:
63
+ self._held = False
64
+
65
+ # CLICKED (fires once)
66
+ now = time.time()
67
+ if self.hovered and mouse_down and not self._was_down:
68
+ if now - self._last_click >= self._cooldown:
69
+ self._clicked = True
70
+ self._last_click = now
71
+
72
+ # RELEASED (fires once)
73
+ if not mouse_down and self._was_down and self.hovered:
74
+ self._released = True
75
+
76
+ self._was_down = mouse_down
77
+
78
+ # ======================================
79
+ # PUBLIC GETTERS
80
+ # ======================================
81
+ def clicked(self):
82
+ return self._clicked
83
+
84
+ def held(self):
85
+ return self._held
86
+
87
+ def released(self):
88
+ return self._released
89
+
90
+ def hovering(self):
91
+ return self.hovered
92
+
93
+ # ======================================
94
+ # DRAW
95
+ # ======================================
96
+ def draw(self, win):
97
+ x, y, w, h = self.rect
98
+
99
+ # choose color by state
100
+ if self._held:
101
+ col = self.press_color
102
+ elif self.hovered:
103
+ col = self.hover_color
104
+ else:
105
+ col = self.color
106
+
107
+ win.draw_rect(col, (x, y, w, h))
108
+ win.draw_text(self.text, pos=(x + 5, y + 5), color=self.text_color)
40
109
 
41
110
  class Label:
42
111
  def __init__(self, pos, text, color=(255,255,255), font="Arial", size=16):
@@ -106,9 +175,10 @@ class GUIManager:
106
175
 
107
176
  def draw(self, win):
108
177
  for e in self.elements:
109
- e.draw(win)
178
+ if hasattr(e, "draw"):
179
+ e.draw(win)
110
180
 
111
181
  def update(self, win):
112
182
  for e in self.elements:
113
- if isinstance(e, Button):
114
- e.check_click(win)
183
+ if hasattr(e, "update"):
184
+ e.update(win)