37
|
1 import pygame
|
|
2 from pygame.locals import *
|
|
3 from pygame import Surface, Rect, Color
|
|
4 from pygame.font import Font
|
|
5
|
|
6 from gamelib import data
|
|
7
|
|
8
|
|
9 # different font sizes
|
|
10 pygame.font.init()
|
|
11 font_small = Font(data.filepath('fonts/DejaVuSans.ttf'), 10)
|
|
12 font_medium = Font(data.filepath('fonts/DejaVuSans.ttf'), 14)
|
|
13 font_large = Font(data.filepath('fonts/DejaVuSans.ttf'), 18)
|
|
14
|
|
15
|
|
16 class Drawable(object):
|
38
|
17
|
|
18 def __init__(self, rect):
|
|
19 if isinstance(rect, Rect):
|
|
20 self.rect = rect
|
|
21 else:
|
|
22 self.rect = Rect(rect[0], rect[1], rect[2], rect[3])
|
|
23
|
|
24 def draw(self, surface):
|
|
25 pass
|
|
26
|
|
27
|
37
|
28 class Clickable(object):
|
38
|
29
|
|
30 def on_mouse_down(self, pos):
|
|
31 pass
|
|
32
|
|
33 def on_mouse_up(self, pos):
|
|
34 pass
|
|
35
|
|
36 def on_mouse_move(self, pos):
|
|
37 pass
|
|
38
|
|
39 def on_mouse_cancel(self):
|
|
40 pass
|
|
41
|
|
42 def on_click(self):
|
|
43 pass
|
|
44
|
37
|
45
|
|
46 class ContainerView(Drawable):
|
38
|
47
|
|
48 def __init__(self):
|
|
49 self.children = []
|
|
50
|
|
51 def add_child(self, child):
|
|
52 self.children.append(child)
|
|
53
|
|
54 def remove_child(self, child):
|
|
55 self.children.remove(child)
|
|
56
|
|
57 def get_child_by_pos(self, pos):
|
|
58 for child in self.children:
|
|
59 if child.rect.collidepoint(pos):
|
|
60 if isinstance(child, ContainerView):
|
|
61 # calculates position relative to child
|
|
62 x = pos[0] - child.rect[0]
|
|
63 y = pos[1] - child.rect[1]
|
|
64 return child.get_child_by_pos((x, y))
|
|
65 else:
|
|
66 return child
|
|
67
|
|
68 def draw_children(self, surface):
|
|
69 for child in self.children:
|
|
70 child.draw(surface)
|
|
71
|
|
72
|
37
|
73 class Window(Clickable, ContainerView):
|
38
|
74
|
|
75 def __init__(self, screen):
|
|
76 super(Window, self).__init__()
|
|
77 self.surface = Surface((screen.get_width(), screen.get_height()))
|
|
78 self.background_colour = None
|
|
79 self.background_image = None
|
|
80 self.pressed_child = None
|
|
81
|
|
82 def on_mouse_down(self, pos):
|
|
83 child = self.get_child_by_pos(pos)
|
|
84 if isinstance(child, Clickable):
|
|
85 # calculates position relative to child
|
|
86 x = pos[0] - child.rect[0]
|
|
87 y = pos[1] - child.rect[1]
|
|
88 child.on_mouse_down((x, y))
|
|
89 self.pressed_child = child
|
|
90
|
|
91 def on_mouse_up(self, pos):
|
|
92 if self.pressed_child:
|
|
93 child = self.pressed_child
|
|
94 x = pos[0] - child.rect[0]
|
|
95 y = pos[1] - child.rect[1]
|
|
96 child.on_mouse_up((x, y))
|
|
97 self.pressed_child = None
|
|
98
|
|
99 def on_mouse_move(self, pos):
|
|
100 if self.pressed_child:
|
|
101 if self.pressed_child != self.get_child_by_pos(pos):
|
|
102 self.pressed_child.on_mouse_cancel()
|
|
103 self.pressed_child = None
|
|
104
|
|
105 def draw(self, screen):
|
|
106 if self.background_colour:
|
|
107 self.surface.fill(self.background_colour)
|
|
108 if self.background_image:
|
|
109 self.surface.blit(self.background_image, (0, 0))
|
|
110 self.draw_children(self.surface)
|
|
111 screen.blit(self.surface, (0, 0))
|
|
112
|
37
|
113
|
|
114 class StateDrawable(Drawable):
|
38
|
115
|
|
116 def __init__(self, rect):
|
|
117 super(StateDrawable, self).__init__(rect)
|
|
118 self.state = -1
|
|
119 self.states = {}
|
|
120 self.drawables = []
|
|
121 self.surface = Surface((self.rect[2], self.rect[3]))
|
|
122
|
|
123 def draw(self, surface):
|
|
124 if self.state != -1 and self.drawables[self.state]:
|
|
125 self.drawables[self.state].draw(surface)
|
|
126
|
|
127 def add_state(self, state_name, drawable):
|
|
128 self.states[state_name] = len(self.drawables)
|
|
129 self.drawables.append(drawable)
|
|
130
|
|
131 def set_state(self, state_name):
|
|
132 self.state = self.states[state_name]
|
|
133
|
|
134
|
37
|
135 class Button(Clickable, StateDrawable):
|
38
|
136
|
|
137 def __init__(self, rect, normal_drawable, down_drawable):
|
|
138 super(Button, self).__init__(rect)
|
|
139 self.add_state('NORMAL', normal_drawable)
|
|
140 self.add_state('DOWN', down_drawable)
|
|
141 self.set_state('NORMAL')
|
|
142
|
|
143 def on_mouse_down(self, pos):
|
|
144 self.set_state('DOWN')
|
|
145
|
|
146 def on_mouse_up(self, pos):
|
|
147 self.set_state('NORMAL')
|
|
148 self.on_click()
|
|
149
|
|
150 def on_mouse_cancel(self):
|
|
151 self.set_state('NORMAL')
|
|
152
|
|
153
|
37
|
154 class TextButton(Button):
|
|
155
|
38
|
156 def __init__(self, rect, normal_drawable, down_drawable, text):
|
|
157 super(TextButton, self).__init__(rect, normal_drawable, down_drawable)
|
|
158 self.surface = Surface((rect[2], rect[3]))
|
|
159 self.text = text
|
|
160 font_large.set_bold(True)
|
|
161 self.text_surface = font_large.render(self.text, True, (128, 128, 128))
|
|
162 shadow = font_large.render(self.text, True, (0, 0, 0))
|
|
163 font_large.set_bold(False)
|
|
164 self.text_surface.blit(shadow, (-2, -2))
|
|
165 size = font_large.size(self.text)
|
|
166 self.text_offset = ((rect[2] - size[0]) / 2, (rect[3] - size[1]) / 2)
|
37
|
167
|
38
|
168 def draw(self, surface):
|
|
169 self.surface.fill((0, 0, 0, 0))
|
|
170 super(TextButton, self).draw(self.surface)
|
|
171 self.surface.blit(self.text_surface, self.text_offset)
|
|
172 surface.blit(self.surface, self.rect)
|