-
Notifications
You must be signed in to change notification settings - Fork 1
/
renderer.py
162 lines (124 loc) · 5.52 KB
/
renderer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
'''
Contains the Renderer of Gim Descent.
'''
from functools import lru_cache
import pygame
import constants
@lru_cache(maxsize=None)
def _import_image(name):
try:
image = pygame.image.load(constants.IMAGES+name+".png").convert_alpha()
except pygame.error:
image = pygame.image.load(constants.DEFAULT_IMAGES+name+".png").convert_alpha()
return image
class Renderer:
"""Rendering wrapper which stores cached surfaces."""
def __init__(self):
self.total_images = 0
@lru_cache(maxsize=None)
def get_image(self, **args):
"""Get an image. Optional modifier parameters like scale and color can be used.
Function is cached with lru_cache.
"""
if "scale" not in args:
args["scale"] = 1
self.total_images += 1
image = _import_image(args["name"]).copy()
if "scale" in args:
image = pygame.transform.scale(image, (int(image.get_width()*args["scale"]), int(image.get_height()*args["scale"])))
if "color" in args:
image.fill(args["color"][0:3], special_flags=args["color"][3])
if "blinking" in args:
if args["blinking"]:
image.fill((50, 50, 50), special_flags=pygame.BLEND_ADD)
return image
def draw_text(self, surface, color, pos, text, size, centered=False):
"""Draw text to a surface.
size refers to the height of each character in pixels.
"""
color = (color[0], color[1], color[2], pygame.BLEND_ADD)
character_width = size * 0.8
if centered:
pos = (pos[0] - (len(text)/2) * character_width + 0.1 * size, pos[1] - size * 0.5)
for i, character in enumerate(text):
if character in constants.SPECIAL_CHARS:
char_name = "txt_"+ constants.SPECIAL_CHARS[character]
else:
char_name = "txt-"+character.lower()
surface.blit(self.get_image(name=char_name, scale=size*0.2, color=color), (pos[0] + i * character_width, pos[1]))
def make_text(self, color, text, size):
"""Return a surface containing text."""
surface = pygame.Surface(self.text_rect(text, size).size)
surface.set_colorkey(constants.COLOR_KEY)
surface.fill(constants.COLOR_KEY)
self.draw_text(surface, color, (0, 0), text, size)
return surface
def text_rect(self, text, size, pos=(0, 0)):
"""Return the rect that text would occupy if drawn."""
rect = pygame.Rect(pos, (size * (len(text) * 0.8 - 0.2), size))
return rect
def draw_image(self, surface, image, pos):
"""Blit an image to a surface."""
surface.blit(image, pos)
def draw_centered_image(self, surface, image, centerpos):
"""Blit an image to a surface, centering it at centerpos."""
surface.blit(image, (centerpos[0] - image.get_width()//2, centerpos[1] - image.get_height()//2))
@lru_cache(maxsize=None)
def _icon_image(self, icons, scale):
"""Return an icons surface."""
images = []
for i, icon in enumerate(icons):
image_name = icon[0]
images.append(self.get_image(name=image_name, scale=scale))
tile_size = scale * constants.TILE_SIZE
rects = []
text_rects = []
for i, image in enumerate(images):
pos = (tile_size*(i*0.2), 0)
rects.append(image.get_rect(center=pos))
if icons[i][1]:
text_pos = (pos[0], pos[1]-tile_size*0.3)
text_rect = self.text_rect(str(icons[i][1]), scale*10)
text_rect.center = text_pos
text_rects.append(text_rect)
else:
text_rects.append(pygame.Rect(0, 0, 0, 0))
surface_rect = pygame.Rect(0, 0, 0, 0).unionall(rects)
surface_rect.unionall_ip(text_rects)
x, y = surface_rect.topleft
surface = pygame.Surface(surface_rect.size)
surface.set_colorkey(constants.COLOR_KEY)
surface.fill(constants.COLOR_KEY)
for i, image in enumerate(images):
rects[i].move_ip(-x, -y)
#pygame.draw.rect(surface, constants.BLACK, rects[i])
surface.blit(image, rects[i])
if icons[i][1]:
text_rects[i].move_ip(-x, -y)
#pygame.draw.rect(surface, constants.BLACK, text_rects[i])
self.draw_text(surface, constants.WHITE, text_rects[i], str(icons[i][1]), 10 * scale)
return surface
@lru_cache(maxsize=None)
def entity_image(self, scale, **draw_data):
"""Return an entity surface given draw data."""
images = []
rects = []
# Entity image
images.append(self.get_image(scale=scale, **draw_data))
rects.append(images[0].get_rect())
center = rects[0].center
tile_size = scale * constants.TILE_SIZE
# Icon images
if draw_data["icons"]:
images.append(self._icon_image(draw_data["icons"], scale))
rects.append(images[-1].get_rect(left=center[0]-tile_size*0.4, bottom=center[1]+0.4*tile_size))
# Frozen ice cube
if draw_data["frozen"]:
images.append(self.get_image(name="ice-cube", scale=scale))
rects.append(images[-1].get_rect(center=center))
surface_rect = pygame.Rect(center, (0, 0)).unionall(rects)
surface = pygame.Surface(surface_rect.size, pygame.SRCALPHA)
x, y = surface_rect.topleft
for i, image in enumerate(images):
surface.blit(image, rects[i].move(-x, -y))
return surface