1"""
2Example showing how to use the easing functions for position.
3
4See:
5https://easings.net/
6...for a great guide on the theory behind how easings can work.
7
8See example 2 for how to use easings for angles.
9
10If Python and Arcade are installed, this example can be run from the command line with:
11python -m arcade.examples.easing_example_1
12"""
13from __future__ import annotations
14
15import arcade
16from arcade import easing
17from arcade.types import Color
18
19SPRITE_SCALING = 0.5
20
21SCREEN_WIDTH = 800
22SCREEN_HEIGHT = 600
23SCREEN_TITLE = "Easing Example"
24
25BACKGROUND_COLOR = "#F5D167"
26TEXT_COLOR = "#4B1DF2"
27BALL_COLOR = "#42B5EB"
28LINE_COLOR = "#45E6D0"
29LINE_WIDTH = 3
30
31X_START = 40
32X_END = 760
33Y_INTERVAL = 50
34BALL_RADIUS = 13
35TIME = 3.0
36
37
38class EasingCircle(arcade.SpriteCircle):
39 """ Player class """
40
41 def __init__(self, radius, color):
42 """ Set up the player """
43
44 # Call the parent init
45 super().__init__(radius, color)
46
47 self.easing_x_data = None
48 self.easing_y_data = None
49
50 def on_update(self, delta_time: float = 1 / 60):
51 if self.easing_x_data is not None:
52 done, self.center_x = easing.ease_update(self.easing_x_data, delta_time)
53 if done:
54 x = X_START
55 if self.center_x < SCREEN_WIDTH / 2:
56 x = X_END
57 ex, ey = easing.ease_position(self.position,
58 (x, self.center_y),
59 rate=180,
60 ease_function=self.easing_x_data.ease_function)
61 self.easing_x_data = ex
62
63 if self.easing_y_data is not None:
64 done, self.center_y = easing.ease_update(self.easing_y_data, delta_time)
65 if done:
66 self.easing_y_data = None
67
68
69class MyGame(arcade.Window):
70 """ Main application class. """
71
72 def __init__(self, width, height, title):
73 """ Initializer """
74
75 # Call the parent class initializer
76 super().__init__(width, height, title)
77
78 # Set the background color
79 self.background_color = Color.from_hex_string(BACKGROUND_COLOR)
80
81 self.ball_list = None
82 self.text_list = []
83 self.lines = None
84
85 def setup(self):
86 """ Set up the game and initialize the variables. """
87
88 # Sprite lists
89 self.ball_list = arcade.SpriteList()
90 self.lines = arcade.shape_list.ShapeElementList()
91
92 def create_ball(ball_y, ease_function):
93 ball = EasingCircle(BALL_RADIUS, Color.from_hex_string(BALL_COLOR))
94 ball.position = X_START, ball_y
95 p1 = ball.position
96 p2 = (X_END, ball_y)
97 ex, ey = easing.ease_position(p1, p2, time=TIME, ease_function=ease_function)
98 ball.ease_function = ease_function
99 ball.easing_x_data = ex
100 ball.easing_y_data = ey
101 return ball
102
103 def create_line(line_y):
104 line = arcade.shape_list.create_line(
105 X_START, line_y - BALL_RADIUS - LINE_WIDTH,
106 X_END, line_y - BALL_RADIUS,
107 line_color, line_width=LINE_WIDTH,
108 )
109 return line
110
111 def create_text(text_string):
112 text = arcade.Text(text_string, X_START, y - BALL_RADIUS, color=text_color, font_size=14)
113 return text
114
115 def add_item(item_y, ease_function, text):
116 ball = create_ball(item_y, ease_function)
117 self.ball_list.append(ball)
118 text = create_text(text)
119 self.text_list.append(text)
120 line = create_line(item_y)
121 self.lines.append(line)
122
123 text_color = Color.from_hex_string(TEXT_COLOR)
124 line_color = Color.from_hex_string(LINE_COLOR)
125
126 y = Y_INTERVAL
127 add_item(y, easing.linear, "Linear")
128
129 y += Y_INTERVAL
130 add_item(y, easing.ease_out, "Ease out")
131
132 y += Y_INTERVAL
133 add_item(y, easing.ease_in, "Ease in")
134
135 y += Y_INTERVAL
136 add_item(y, easing.smoothstep, "Smoothstep")
137
138 y += Y_INTERVAL
139 add_item(y, easing.ease_in_out, "Ease in/out")
140
141 y += Y_INTERVAL
142 add_item(y, easing.ease_out_elastic, "Ease out elastic")
143
144 y += Y_INTERVAL
145 add_item(y, easing.ease_in_back, "Ease in back")
146
147 y += Y_INTERVAL
148 add_item(y, easing.ease_out_back, "Ease out back")
149
150 y += Y_INTERVAL
151 add_item(y, easing.ease_in_sin, "Ease in sin")
152
153 y += Y_INTERVAL
154 add_item(y, easing.ease_out_sin, "Ease out sin")
155
156 y += Y_INTERVAL
157 add_item(y, easing.ease_in_out_sin, "Ease in out sin")
158
159 def on_draw(self):
160 """ Render the screen. """
161
162 # This command has to happen before we start drawing
163 self.clear()
164
165 self.lines.draw()
166
167 # Draw all the sprites.
168 self.ball_list.draw()
169
170 for text in self.text_list:
171 text.draw()
172
173 def on_update(self, delta_time):
174 """ Movement and game logic """
175
176 # Call update on all sprites (The sprites don't do much in this
177 # example though.)
178 self.ball_list.on_update(delta_time)
179
180
181def main():
182 """ Main function """
183 window = MyGame(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
184 window.setup()
185 arcade.run()
186
187
188if __name__ == "__main__":
189 main()