Skip to content
This repository was archived by the owner on Mar 31, 2020. It is now read-only.

Commit 1f61f90

Browse files
committed
Bounceball
1 parent 361de26 commit 1f61f90

File tree

4 files changed

+108
-43
lines changed

4 files changed

+108
-43
lines changed

src/animate.py

Lines changed: 70 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import math
77
from typing import NamedTuple, Callable, TypeVar, Generator
88
from enum import Enum
9-
from dataclasses import dataclass
109
from functools import partialmethod
1110

1211

@@ -54,16 +53,12 @@ def running(self):
5453
return bool(self._motions)
5554

5655

57-
@dataclass
5856
class Motion:
59-
"""
60-
61-
"""
62-
canvas: tk.Canvas
63-
id: int
64-
end: Coord
65-
66-
speed: int = 1
57+
def __init__(self, canvas: tk.Canvas, id: str, end: Coord, speed: float = 1):
58+
self.canvas = canvas
59+
self.id = id
60+
self.end = end
61+
self.speed = speed ** 3
6762

6863
def __iter__(self):
6964
return self.start()
@@ -82,9 +77,8 @@ def start(self) -> Generator[Callable]:
8277
The entry point for generating move commands.
8378
"""
8479
self.time = time.time()
85-
self.start = self.current
86-
self.distance = self.start.distance(self.end)
87-
self.speed = self.speed ** 3
80+
self.beg = self.current
81+
self.distance = self.beg.distance(self.end)
8882
while self.current != self.end:
8983
yield self.move
9084

@@ -102,13 +96,16 @@ def time(self, val):
10296

10397
@property
10498
def increment(self):
105-
mult = (self.time * self.speed) / self.distance
106-
point = (self.end - self.start) * mult + self.start
107-
108-
if point.distance(self.end) > self.journey:
99+
future = self.future
100+
if future.distance(self.end) > self.journey:
109101
return self.end - self.current
110102
else:
111-
return point - self.current
103+
return future - self.current
104+
105+
@property
106+
def future(self):
107+
mult = (self.time * self.speed) / self.distance
108+
return (self.end - self.beg) * mult + self.beg
112109

113110
@property
114111
def current(self):
@@ -119,6 +116,56 @@ def journey(self):
119116
return self.current.distance(self.end)
120117

121118

119+
class BounceBall(Motion):
120+
121+
def kick(self, direction: Point, speed=8):
122+
self.direction = direction
123+
self.speed = speed
124+
self.end = self.direction + self.current
125+
126+
@property
127+
def increment(self):
128+
self.canvas.update()
129+
self.end += self.get_bounce()
130+
return self.future - self.current
131+
132+
def get_bounce(self):
133+
x1, y1, x2, y2 = self.canvas.bbox(self.id)
134+
135+
bounce = Coord(0, 0)
136+
if x1 <= self.bound_x1:
137+
print('x1', x1, self.bound_x1)
138+
bounce += Direction.RIGHT
139+
if y1 >= self.bound_y1:
140+
print('y1', y1, self.bound_y1)
141+
bounce += Direction.UP
142+
if x2 >= self.bound_x2:
143+
print('x2', x2, self.bound_x2)
144+
bounce += Direction.LEFT
145+
if y2 >= self.bound_y2:
146+
print('y2', y2, self.bound_y2)
147+
bounce += Direction.DOWN
148+
return bounce
149+
150+
@property
151+
def bound_x1(self):
152+
return self.canvas.winfo_x()
153+
154+
@property
155+
def bound_y1(self):
156+
return self.canvas.winfo_y()
157+
158+
@property
159+
def bound_x2(self):
160+
# self.canvas.update()
161+
return self.bound_x1 + self.canvas.winfo_width()
162+
163+
@property
164+
def bound_y2(self):
165+
# self.canvas.update()
166+
return self.bound_y1 + self.canvas.winfo_height()
167+
168+
122169
class Coord(NamedTuple):
123170
"""
124171
Helper class for managing coordinate values.
@@ -149,10 +196,10 @@ class Coord(NamedTuple):
149196
Operand = TypeVar('Operand', 'Coord', float)
150197

151198
def __apply(self, op: Callable, other: Coord.Operand) -> Coord:
152-
if not isinstance(other, self.__class__):
153-
other = self.__class__(other, other)
154199
if isinstance(other, Direction):
155200
other = other.value
201+
elif not isinstance(other, self.__class__):
202+
other = self.__class__(other, other)
156203

157204
x = op(self.x, other.x)
158205
y = op(self.y, other.y)
@@ -183,6 +230,9 @@ def distance(self, other: Coord) -> float:
183230
diff = other - self
184231
return math.hypot(*diff)
185232

233+
def flip(self):
234+
return Coord(0, 0) - self
235+
186236
__add__ = partialmethod(__apply, operator.add)
187237
__sub__ = partialmethod(__apply, operator.sub)
188238
__mul__ = partialmethod(__apply, operator.mul)

src/main.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from contextlib import suppress
44

55
from .front import Front
6-
# from .splash import Splash
6+
from .splash import Splash
77
from . import SETTINGS, widget
88

99

@@ -23,13 +23,13 @@ def __init__(self, *args, **kwds):
2323

2424
self.frame = widget.PrimaryFrame(self)
2525
self.frame.pack(expand=True, fill='both')
26-
27-
# self.splash = Splash(self.frame)
28-
# self.splash.pack(expand=True, fill='both')
29-
self.front = Front(self.frame)
30-
self.front.pack(fill='both', expand=True)
26+
27+
self.splash = Splash(self.frame)
28+
self.splash.pack(expand=True, fill='both')
29+
# self.front = Front(self.frame)
30+
# self.front.pack(fill='both', expand=True)
3131

3232
def cleanup(self):
3333
with suppress(Exception):
34-
self.front.cleanup()
34+
# self.front.cleanup()
3535
self.destroy()

src/splash.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import json
22

3-
from .view import Window, View
3+
from .view import Window, View, BounceBall
4+
from .animate import Direction
45
from . import widget, DOCS
56

67

@@ -33,24 +34,32 @@ class Splash(widget.PrimaryFrame):
3334
questions = json.load(fp)
3435

3536
def init(self):
37+
self.window = Window(self, bg='gray')
3638
self.title = widget.PrimaryLabel(
3739
self, text=self.master.master.title(),
38-
font=('Courier', 14), wraplength=300
40+
font=('Courier', 17), wraplength=300
3941
)
40-
41-
self.window = Window(self, bg='gray')
4242
self.intro = View(
4343
self.window,
4444
text=self.intro,
4545
width=self.window.winfo_reqwidth(),
46-
font=('sys', 10), justify='center'
46+
font=('sys', 12), justify='center'
4747
)
4848
self.window.set_view(self.intro)
4949

50-
self.btn_confirm = widget.PrimaryButton(self, command=self.begin, text='Okay')
50+
self.btn_confirm = widget.PrimaryButton(self.window, command=self.begin, text='Okay')
51+
52+
self.title.pack(fill='x', pady=10)
53+
self.window.pack(fill='both', expand=True)
54+
self.bounce()
55+
56+
def bounce(self):
57+
bouncer = View(self.window, window=self.btn_confirm)
58+
wid = self.window.set_view(bouncer, self.window.center)
59+
motion = BounceBall(self.window, wid, self.window.origin)
60+
motion.kick(Direction.RIGHT)
5161

52-
self.title.pack(fill='x', pady=20)
53-
self.btn_confirm.pack(side='bottom', expand=True)
62+
self.after(0, self.window.run, motion)
5463

5564
def begin(self):
5665
pass

src/view.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from enum import Enum
44

55
from . import widget
6-
from .animate import Coord, Animater, Direction
6+
from .animate import Coord, Animater, Direction, Motion
77

88

99
class Window(widget.PrimaryCanvas):
@@ -19,12 +19,12 @@ def __coord(self, id):
1919

2020
def __set(self, view: View, coord: Coord):
2121
wid = view.draw(coord, anchor='nw')
22+
self.current = view
2223
self.views[view] = wid
2324
return wid
2425

25-
def set_view(self, view: View):
26-
self.current = view
27-
self.__set(self.current, self.origin)
26+
def set_view(self, view: View, coord: Coord = None):
27+
return self.__set(view, coord or self.origin)
2828

2929
def move_view(self, view: View, end: Coord):
3030
wid = self.views.get(view)
@@ -52,14 +52,11 @@ def change_view(self, view: View, direction: Direction = None):
5252
return
5353
if not isinstance(direction, Direction):
5454
direction = Direction[direction.upper()] # Cast string for convenience
55-
5655
self.animater.clear()
57-
5856
last = self.current
59-
self.current = view
57+
6058
self.move_in(self.current, direction.flip())
6159
self.move_out(last, direction)
62-
6360
self.animater.start()
6461

6562
def get_distance(self, direction: Direction):
@@ -73,6 +70,10 @@ def get_distance(self, direction: Direction):
7370
else:
7471
raise NotImplementedError
7572

73+
def run(self, motion: Motion):
74+
self.animater.add(motion)
75+
self.animater.start()
76+
7677
@property
7778
def active(self):
7879
return self.animater.running
@@ -81,6 +82,11 @@ def active(self):
8182
def origin(self):
8283
return Coord(self.canvasx(0), self.canvasy(0))
8384

85+
@property
86+
def center(self):
87+
br = self.origin + Coord(self.winfo_reqwidth(), self.winfo_reqheight())
88+
return self.origin.midpoint(br)
89+
8490

8591
class DrawType(Enum):
8692
image = 'create_image'

0 commit comments

Comments
 (0)