Skip to content

Commit 694ae00

Browse files
committed
make an easing functions example
this has revealed fundamental issues with bounce and elastic
1 parent 93611e0 commit 694ae00

21 files changed

+217
-0
lines changed
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
"""
2+
Example showing the different easing functions.
3+
4+
If Python and Arcade are installed, this example can be run from the command line with:
5+
python -m arcade.examples.easing_functions
6+
"""
7+
import arcade
8+
from arcade import SpriteCircle, SpriteList
9+
from arcade.anim.easing import Easing, ease
10+
from arcade.clock import GLOBAL_CLOCK
11+
from arcade.types.rect import LBWH, Rect
12+
13+
from pyglet.graphics import Batch
14+
15+
WINDOW_WIDTH = 1200
16+
WINDOW_HEIGHT = 800
17+
WINDOW_TITLE = "Easing Example"
18+
19+
# Load our brand font
20+
arcade.resources.load_josefin_sans()
21+
22+
# Load an actually good monospace font
23+
arcade.load_font(":system:fonts/ttf/Fira Code/Fira_Code_Medium.ttf")
24+
25+
# Label all the functions
26+
# There's nine "types", not counting linear, and three of each.
27+
28+
EASING_TYPES = 9
29+
EASING_SUB_TYPES = 3
30+
31+
easing_functions = {
32+
"Linear": Easing.LINEAR,
33+
"Sine": Easing.SINE,
34+
"Sine In": Easing.SINE_IN,
35+
"Sine Out": Easing.SINE_OUT,
36+
"Quad": Easing.QUAD,
37+
"Quad In": Easing.QUAD_IN,
38+
"Quad Out": Easing.QUAD_OUT,
39+
"Cubic": Easing.CUBIC,
40+
"Cubic In": Easing.CUBIC_IN,
41+
"Cubic Out": Easing.CUBIC_OUT,
42+
"Quart": Easing.QUART,
43+
"Quart In": Easing.QUART_IN,
44+
"Quart Out": Easing.QUART_OUT,
45+
"Quint": Easing.QUINT,
46+
"Quint In": Easing.QUINT_IN,
47+
"Quint Out": Easing.QUINT_OUT,
48+
"Expo": Easing.EXPO,
49+
"Expo In": Easing.EXPO_IN,
50+
"Expo Out": Easing.EXPO_OUT,
51+
"Circ": Easing.CIRC,
52+
"Circ In": Easing.CIRC_IN,
53+
"Circ Out": Easing.CIRC_OUT,
54+
"Elastic": Easing.ELASTIC,
55+
"Elastic In": Easing.ELASTIC_IN,
56+
"Elastic Out": Easing.ELASTIC_OUT,
57+
"Bounce": Easing.BOUNCE,
58+
"Bounce In": Easing.BOUNCE_IN,
59+
"Bounce Out": Easing.BOUNCE_OUT
60+
}
61+
62+
# We need these for sorting them later; they're in reverse order since we draw bottom-up.
63+
function_names = ["Bounce", "Elastic", "Circ", "Expo", "Quint", "Quart", "Cubic", "Quad", "Sine", "Linear"]
64+
65+
def px_to_pt(px: int) -> int:
66+
return round(px // (4 / 3))
67+
68+
class GameView(arcade.View):
69+
"""
70+
Main application class.
71+
"""
72+
73+
def __init__(self):
74+
super().__init__()
75+
76+
self.background_color = arcade.color.ARCADE_GREEN
77+
self.time = 0.0
78+
79+
# "Layouting"
80+
rect = self.window.rect
81+
self.areas: list[Rect] = []
82+
# We want a 9 x 3 grid, but pretending there's an 11 x 3 grid
83+
# and we're ignoring the first two rows.
84+
buffer = 10 # px
85+
cols = 3
86+
rows = 11
87+
rect_width = rect.width / cols
88+
rect_height = rect.height / rows
89+
90+
# Generate a gird of rectangles. We'll use these to place the
91+
# easing demos.
92+
for i in range(EASING_TYPES * EASING_SUB_TYPES + 1):
93+
new_rect = LBWH(0, 0, rect_width, rect_height)
94+
row = i // cols
95+
col = i % cols
96+
if col == 0:
97+
new_rect = new_rect.align_left(rect.left)
98+
elif col == 1:
99+
new_rect = new_rect.align_center_x(rect.center_x)
100+
elif col == 2:
101+
new_rect = new_rect.align_right(rect.right)
102+
new_rect = new_rect.align_bottom(rect.bottom + rect_height * row)
103+
new_rect = new_rect.resize(new_rect.width - buffer, new_rect.height - buffer)
104+
self.areas.append(new_rect)
105+
106+
self.random_colors = [arcade.types.Color.random(a = 255) for _ in range(len(self.areas))]
107+
108+
self.title_text = arcade.Text("Easing Functions", buffer, self.window.rect.top - buffer, font_size = px_to_pt(int(rect_height - buffer)), font_name = "Josefin Sans", anchor_y = "top")
109+
110+
self.labels = []
111+
self.progress_labels = []
112+
self.text_batch = Batch()
113+
self.sprites = []
114+
self.spritelist = SpriteList()
115+
for n, a in enumerate(self.areas):
116+
name = self.idx_to_func_name(n)
117+
func = easing_functions[name]
118+
label = arcade.Text(func.__name__, a.left, a.bottom, font_size = px_to_pt(int(a.height / 2 - buffer)), font_name = "Fira Code", batch = self.text_batch)
119+
self.labels.append(label)
120+
progress_label = arcade.Text("0.00", a.right, a.bottom, font_size = px_to_pt(int(a.height / 2 - buffer)), font_name = "Josefin Sans", bold = "light", anchor_x = "right", batch = self.text_batch)
121+
self.progress_labels.append(progress_label)
122+
sprite = SpriteCircle(int(a.height / 4), arcade.color.ARCADE_YELLOW)
123+
sprite.left = a.left
124+
sprite.center_y = a.bottom + (a.height * 0.75)
125+
self.sprites.append(sprite)
126+
self.spritelist.append(sprite)
127+
128+
def idx_to_func_name(self, i: int) -> str:
129+
if i >= len(self.areas):
130+
raise ValueError
131+
else:
132+
t = function_names[i // 3]
133+
if i % 3 == 0:
134+
return t
135+
elif i % 3 == 1:
136+
return f"{t} In"
137+
else:
138+
return f"{t} Out"
139+
140+
def on_update(self, delta_time):
141+
if int(GLOBAL_CLOCK.time) % 2:
142+
self.time = 1 - (GLOBAL_CLOCK.time % 1)
143+
else:
144+
self.time = GLOBAL_CLOCK.time % 1
145+
146+
for n, a in enumerate(self.areas):
147+
name = self.idx_to_func_name(n)
148+
func = easing_functions[name]
149+
sprite = self.sprites[n]
150+
151+
right = a.right - sprite.width
152+
x = ease(a.left, right, 0, 1, self.time, func)
153+
p = ease(0.0, 1.0, 0, 1, self.time, func)
154+
sprite.left = x
155+
self.progress_labels[n].text = f"{p:.02}"
156+
157+
158+
def on_draw(self):
159+
"""
160+
Render the screen.
161+
"""
162+
self.clear()
163+
self.title_text.draw()
164+
for n, r in enumerate(self.areas):
165+
arcade.draw_rect_filled(r, arcade.color.BLACK.replace(a = 64))
166+
self.text_batch.draw()
167+
self.spritelist.draw()
168+
169+
def on_key_press(self, symbol: int, modifiers: int):
170+
""" Handle key press events """
171+
if symbol == arcade.key.ESCAPE:
172+
self.window.close()
173+
174+
175+
def main():
176+
""" Main function """
177+
# Create a window class. This is what actually shows up on screen
178+
window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
179+
180+
# Create the GameView
181+
game = GameView()
182+
183+
# Show GameView on screen
184+
window.show_view(game)
185+
186+
# Start the arcade game loop
187+
arcade.run()
188+
189+
190+
if __name__ == "__main__":
191+
main()

arcade/resources/__init__.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,3 +303,29 @@ def load_liberation_fonts() -> None:
303303
load_font(":system:fonts/ttf/Liberation/Liberation_Serif_Bold.ttf")
304304
load_font(":system:fonts/ttf/Liberation/Liberation_Serif_Italic.ttf")
305305
load_font(":system:fonts/ttf/Liberation/Liberation_Serif_Regular.ttf")
306+
307+
def load_josefin_sans() -> None:
308+
"""Loads all styles for Josefin Sans, our brand font.
309+
310+
.. tip:: This function is best for prototyping and experimenting!
311+
312+
For best performance, you may want to switch to
313+
:py:class:`arcade.load_font` before release.
314+
315+
"""
316+
from arcade.text import load_font
317+
318+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_BoldItalic.ttf")
319+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Bold.ttf")
320+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Italic.ttf")
321+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Regular.ttf")
322+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Medium.ttf")
323+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_MediumItalic.ttf")
324+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Thin.ttf")
325+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_ThinItalic.ttf")
326+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Light.ttf")
327+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_LightItalic.ttf")
328+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_Semibold.ttf")
329+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_SemiboldItalic.ttf")
330+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_ExtraLight.ttf")
331+
load_font(":system:fonts/ttf/Josefin/Josefin_Sans_ExtraLightItalic.ttf")
312 KB
Binary file not shown.
282 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
58.4 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)