crystalwindow 3.8.1__tar.gz → 3.8.4__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 (44) hide show
  1. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/LICENSE +1 -1
  2. {crystalwindow-3.8.1/crystalwindow.egg-info → crystalwindow-3.8.4}/PKG-INFO +1 -1
  3. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/__init__.py +4 -0
  4. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/assets.py +41 -0
  5. crystalwindow-3.8.4/crystalwindow/sprites.py +108 -0
  6. {crystalwindow-3.8.1 → crystalwindow-3.8.4/crystalwindow.egg-info}/PKG-INFO +1 -1
  7. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/setup.py +1 -1
  8. crystalwindow-3.8.1/crystalwindow/sprites.py +0 -115
  9. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/MANIFEST.in +0 -0
  10. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/README.md +0 -0
  11. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/FileHelper.py +0 -0
  12. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/Icons/default_icon.png +0 -0
  13. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/animation.py +0 -0
  14. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/camera.py +0 -0
  15. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/clock.py +0 -0
  16. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/collision.py +0 -0
  17. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/crystal3d.py +0 -0
  18. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/docs/getting_started.md +0 -0
  19. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/docs/index.md +0 -0
  20. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/draw_helpers.py +0 -0
  21. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/draw_rects.py +0 -0
  22. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/draw_text_helper.py +0 -0
  23. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/draw_tool.py +0 -0
  24. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/fun_helpers.py +0 -0
  25. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/3dsquare.py +0 -0
  26. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/__init__.py +0 -0
  27. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/__main__.py +0 -0
  28. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/gravitytest.py +0 -0
  29. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/guitesting.py +0 -0
  30. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/sandbox.py +0 -0
  31. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/squaremove.py +0 -0
  32. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gametests/windowtesting.py +0 -0
  33. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gravity.py +0 -0
  34. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gui.py +0 -0
  35. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/gui_ext.py +0 -0
  36. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/math.py +0 -0
  37. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/player.py +0 -0
  38. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/tilemap.py +0 -0
  39. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/ver_warner.py +0 -0
  40. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow/window.py +0 -0
  41. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow.egg-info/SOURCES.txt +0 -0
  42. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow.egg-info/dependency_links.txt +0 -0
  43. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/crystalwindow.egg-info/top_level.txt +0 -0
  44. {crystalwindow-3.8.1 → crystalwindow-3.8.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 C
3
+ Copyright (c) 2025 CrystalBallyHereXD
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 3.8.1
3
+ Version: 3.8.4
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (MEEEEEE)! Easier apps, smoother UI and all-in-one helpers!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -20,6 +20,8 @@ from .assets import (
20
20
  flip_image,
21
21
  flip_horizontal,
22
22
  flip_vertical,
23
+ LoopAnim,
24
+ loop_image,
23
25
  )
24
26
  from .animation import Animation
25
27
 
@@ -60,6 +62,8 @@ __all__ = [
60
62
  "flip_horizontal",
61
63
  "flip_vertical",
62
64
  "Animation",
65
+ "LoopAnim",
66
+ "loop_image",
63
67
 
64
68
  # --- Collision ---
65
69
  "check_collision", "resolve_collision",
@@ -118,6 +118,47 @@ def flip_horizontal(img):
118
118
  def flip_vertical(img):
119
119
  return flip_image(img, flip_v=True)
120
120
 
121
+ # --------------------------------------------------------
122
+ # LOOPING ANIMAITONS/IMAGES
123
+ # --------------------------------------------------------
124
+ class LoopAnim:
125
+ def __init__(self, frames, speed=0.2):
126
+ self.frames = frames
127
+ self.i = 0
128
+ self.speed = speed
129
+
130
+ def next(self):
131
+ """Return next frame automatically looping."""
132
+ if not self.frames:
133
+ return None
134
+
135
+ self.i += self.speed
136
+ if self.i >= len(self.frames):
137
+ self.i = 0
138
+
139
+ return self.frames[int(self.i)]
140
+
141
+
142
+ def loop_image(*imgs, speed=0.2):
143
+ """
144
+ Usage:
145
+ anim = loop_image(img1, img2, img3)
146
+ anim = loop_image(load_image("p1.png"), load_image("p2.png"))
147
+
148
+ Returns a LoopAnim object.
149
+ """
150
+ frames = [x for x in imgs if x is not None]
151
+
152
+ # If nothing was passed → fallback
153
+ if not frames:
154
+ print("⚠️ loop_image() got no frames.")
155
+ fb = load_image("fallback.png") if os.path.exists("fallback.png") else None
156
+ if fb is None:
157
+ return LoopAnim([None], speed=speed)
158
+ return LoopAnim([fb], speed=speed)
159
+
160
+ return LoopAnim(frames, speed=speed)
161
+
121
162
 
122
163
  # --------------------------------------------------------
123
164
  # FOLDER LOADING
@@ -0,0 +1,108 @@
1
+ # sprites.py
2
+ import random
3
+ from tkinter import PhotoImage
4
+
5
+ try:
6
+ from PIL import Image, ImageTk
7
+ except ImportError:
8
+ Image = None
9
+ ImageTk = None
10
+
11
+ class Sprite:
12
+ def __init__(self, pos, size=None, image=None, color=(255, 0, 0)):
13
+ """
14
+ pos: (x, y)
15
+ size: (w, h) optional
16
+ image: PhotoImage or PIL ImageTk.PhotoImage
17
+ color: fallback rectangle color
18
+ """
19
+ self.pos = pos
20
+ self.x, self.y = pos
21
+ self.image = image
22
+ self.color = color
23
+
24
+ # Determine width/height
25
+ if image is not None:
26
+ try:
27
+ # Tkinter PhotoImage
28
+ self.width = image.width()
29
+ self.height = image.height()
30
+ except Exception:
31
+ try:
32
+ # PIL ImageTk.PhotoImage
33
+ self.width = image.width
34
+ self.height = image.height
35
+ except Exception:
36
+ raise ValueError("Sprite image has no size info")
37
+ elif size is not None:
38
+ self.width, self.height = size
39
+ else:
40
+ raise ValueError("Sprite needs 'size' or 'image'")
41
+
42
+ # Optional velocity
43
+ self.vel_x = 0
44
+ self.vel_y = 0
45
+
46
+ # === CLASS METHODS ===
47
+ @classmethod
48
+ def image(cls, img, pos):
49
+ """
50
+ Create a sprite from an image.
51
+ Accepts fallback dict or actual PhotoImage.
52
+ """
53
+ if isinstance(img, dict) and img.get("fallback"):
54
+ w, h = img["size"]
55
+ color = img["color"]
56
+ return cls(pos, size=(w, h), color=color)
57
+ return cls(pos, image=img)
58
+
59
+ @classmethod
60
+ def rect(cls, pos, w, h, color=(255, 0, 0)):
61
+ """Create sprite using a plain colored rectangle"""
62
+ return cls(pos, size=(w, h), color=color)
63
+
64
+ # === METHODS ===
65
+ def draw(self, win, cam=None):
66
+ """Draw sprite on CrystalWindow / Tk canvas"""
67
+ if cam:
68
+ draw_x, draw_y = cam.apply(self)
69
+ else:
70
+ draw_x, draw_y = self.x, self.y
71
+
72
+ if self.image:
73
+ win.canvas.create_image(draw_x, draw_y, anchor="nw", image=self.image)
74
+ else:
75
+ win.draw_rect(self.color, (draw_x, draw_y, self.width, self.height))
76
+
77
+ def move(self, dx, dy):
78
+ self.x += dx
79
+ self.y += dy
80
+ self.pos = (self.x, self.y)
81
+
82
+ def apply_velocity(self, dt=1):
83
+ self.x += self.vel_x * dt
84
+ self.y += self.vel_y * dt
85
+ self.pos = (self.x, self.y)
86
+
87
+ def colliderect(self, other):
88
+ return (
89
+ self.x < other.x + getattr(other, "width", 0) and
90
+ self.x + getattr(self, "width", 0) > other.x and
91
+ self.y < other.y + getattr(other, "height", 0) and
92
+ self.y + getattr(self, "height", 0) > other.y
93
+ ) # returns tuple for consistency
94
+
95
+ def set_image(self, img):
96
+ """Update sprite's image at runtime (like flipping)"""
97
+ self.image = img
98
+ # update width/height
99
+ if img is not None:
100
+ try:
101
+ self.width = img.width()
102
+ self.height = img.height()
103
+ except Exception:
104
+ try:
105
+ self.width = img.width
106
+ self.height = img.height
107
+ except:
108
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crystalwindow
3
- Version: 3.8.1
3
+ Version: 3.8.4
4
4
  Summary: A Tkinter powered window + GUI toolkit made by Crystal (MEEEEEE)! Easier apps, smoother UI and all-in-one helpers!
5
5
  Home-page: https://pypi.org/project/crystalwindow/
6
6
  Author: CrystalBallyHereXD
@@ -7,7 +7,7 @@ with open("README.md", encoding="utf-8") as f:
7
7
 
8
8
  setup(
9
9
  name="crystalwindow",
10
- version="3.8.1", # Force metadata refresh
10
+ version="3.8.4", # Force metadata refresh
11
11
  packages=find_packages(include=["crystalwindow", "crystalwindow.*"]),
12
12
 
13
13
  include_package_data=True, # include package_data files
@@ -1,115 +0,0 @@
1
- # sprites.py
2
- from tkinter import PhotoImage
3
- from PIL import Image, ImageTk
4
-
5
-
6
- class Sprite:
7
- def __init__(self, pos, size=None, image=None, color=(255, 0, 0)):
8
- self.x, self.y = pos
9
- self.pos = pos
10
-
11
- self.image = None
12
- self.color = color
13
-
14
- # If fallback dict provided from assets
15
- if isinstance(image, dict) and image.get("fallback"):
16
- self.width, self.height = image["size"]
17
- self.color = image["color"]
18
-
19
- # Normal image
20
- elif isinstance(image, PhotoImage):
21
- self.set_image(image)
22
-
23
- # Rectangle sprite
24
- elif size is not None:
25
- self.width, self.height = size
26
-
27
- else:
28
- raise ValueError("Sprite needs 'size' or 'image'")
29
-
30
- # Movement physics
31
- self.vel_x = 0
32
- self.vel_y = 0
33
-
34
- # Optional direction flag
35
- self.facing_left = False
36
-
37
- # --------------------------------------
38
- # Constructors
39
- # --------------------------------------
40
- @classmethod
41
- def image(cls, img, pos):
42
- if isinstance(img, dict) and img.get("fallback"):
43
- w, h = img["size"]
44
- color = img["color"]
45
- return cls(pos, size=(w, h), color=color)
46
- return cls(pos, image=img)
47
-
48
- @classmethod
49
- def rect(cls, pos, w, h, color=(255, 0, 0)):
50
- return cls(pos, size=(w, h), color=color)
51
-
52
- # --------------------------------------
53
- # Draw
54
- # --------------------------------------
55
- def draw(self, win, cam=None):
56
- if cam:
57
- draw_x, draw_y = cam.apply(self)
58
- else:
59
- draw_x, draw_y = self.x, self.y
60
-
61
- if self.image:
62
- win.canvas.create_image(draw_x, draw_y, anchor="nw", image=self.image)
63
- else:
64
- win.draw_rect(self.color, (draw_x, draw_y, self.width, self.height))
65
-
66
- # --------------------------------------
67
- # Movement
68
- # --------------------------------------
69
- def move(self, dx, dy):
70
- self.x += dx
71
- self.y += dy
72
- self.pos = (self.x, self.y)
73
-
74
- def apply_velocity(self, dt=1):
75
- self.x += self.vel_x * dt
76
- self.y += self.vel_y * dt
77
- self.pos = (self.x, self.y)
78
-
79
- # --------------------------------------
80
- # Image setter
81
- # --------------------------------------
82
- def set_image(self, new_image):
83
- """Set sprite image and update size."""
84
- self.image = new_image
85
- self.width = new_image.width()
86
- self.height = new_image.height()
87
-
88
- # --------------------------------------
89
- # In-place flipping (optional)
90
- # --------------------------------------
91
- def flip_horizontal(self):
92
- if not self.image:
93
- return
94
- pil = ImageTk.getimage(self.image)
95
- flipped = pil.transpose(Image.FLIP_LEFT_RIGHT)
96
- self.set_image(ImageTk.PhotoImage(flipped))
97
- self.facing_left = not self.facing_left
98
-
99
- def flip_vertical(self):
100
- if not self.image:
101
- return
102
- pil = ImageTk.getimage(self.image)
103
- flipped = pil.transpose(Image.FLIP_TOP_BOTTOM)
104
- self.set_image(ImageTk.PhotoImage(flipped))
105
-
106
- # --------------------------------------
107
- # Collision
108
- # --------------------------------------
109
- def colliderect(self, other):
110
- return (
111
- self.x < other.x + other.width and
112
- self.x + self.width > other.x and
113
- self.y < other.y + other.height and
114
- self.y + self.height > other.y
115
- )
File without changes
File without changes
File without changes