def build(self, cost, inp): grads_noclip = tensor.grad(cost, self.params) grads, grad_norm = tools.clip(grads_noclip, self.config['clip'], params=self.params) update_ab = [(self.beta1t, self.beta1t * self.config['beta1_adam']), (self.beta2t, self.beta2t * self.config['beta2_adam'])] update_gc = [(gc, gr) for gc, gr in zip(self.gc, grads)] update_gc = [(gc, gr) for gc, gr in zip(self.gc, grads)] m_up = [(m, self.config['beta1_adam'] * m + (1. - self.config['beta1_adam']) * gr) for m, gr in zip(self.m, grads)] v_up = [(v, self.config['beta2_adam'] * v + (1. - self.config['beta2_adam']) * (gr**2)) for v, gr in zip(self.v, grads)] update_grads = theano.function(inp, [cost, grad_norm], updates=update_gc + m_up + v_up) param_up = [ (p, p - self.config['alpha_adam'] * (m / (1. - self.beta1t)) / (tensor.sqrt(v / (1. - self.beta2t)) + self.config['eps_adam'])) for p, m, v in zip(self.params, self.m, self.v) ] update_params = theano.function([], [], updates=update_ab + param_up) return update_grads, update_params
def append(self, val) -> [int, int, int]: self.values.append(val) self.values = self.values[-self.memory_count:] max_values = max(self.values) color = convert_to_rgb(0, max_values + 400, clip( 0, max_values, val)) if val != 0 else (0, 0, 0) return color
def build(self, cost, inp): grads_noclip = tensor.grad(cost, self.params) grads, grad_norm = tools.clip(grads_noclip, self.config['clip'], params=self.params) gc_up = [(gc, gr) for gc, gr in zip(self.gc, grads)] g2_up = [ (g2, self.config['rho'] * g2 + (1. - self.config['rho']) * (gr**2.)) for g2, gr in zip(self.g2, grads) ] #noclip = theano.function(inp, [cost]+grads_noclip) #noupdate_grads = theano.function(inp, [cost, grad_norm]) update_grads = theano.function(inp, [cost, grad_norm], updates=gc_up + g2_up) delta = [ tensor.sqrt(u2 + self.config['epsilon']) / tensor.sqrt(g2 + self.config['epsilon']) * gr for g2, u2, gr in zip(self.g2, self.u2, self.gc) ] u2_up = [ (u2, self.config['rho'] * u2 + (1. - self.config['rho']) * (d**2.)) for u2, d in zip(self.u2, delta) ] param_up = [(p, p - d) for p, d in zip(self.params, delta)] #update_params = theano.function([], [], updates=param_up+u2_up) update_params = theano.function([], [], updates=param_up + u2_up) return update_grads, update_params
def build(self, cost, inp): grads_noclip = tensor.grad(cost, self.params) grads, grad_norm = tools.clip(grads_noclip, self.config['clip'], square = False, params = self.params) gc_up = [(gc, gr) for gc, gr in zip(self.gc, grads)] update_grads = theano.function(inp, [cost, tensor.sqrt(grad_norm)], updates = gc_up) lr = numpy.float32(self.config['lr']) delta = [-lr * gr for gr in self.gc] params_up = [(p, p - lr * gr) for p, gr in zip(self.params, self.gc)] update_params = theano.function([], [], updates = params_up) return update_grads, update_params
def __init__(self, path, tile, data, scale=1): self.image = pg.image.load(path).convert_alpha() self.tile = tile if isinstance(data, list): # Se for uma lista, será um dicionário self.sprites = {} for x, name in enumerate(data): sprite = pg.transform.scale( tools.clip(self.image, x * self.tile, 0, self.tile, self.tile), (self.tile * scale, self.tile * scale)) self.sprites[name] = sprite.copy() else: # Caso contrário apenas uma lista self.sprites = [] for x in range(data): sprite = pg.transform.scale( tools.clip(self.image, x * self.tile, 0, self.tile, self.tile), (self.tile * scale, self.tile * scale)) self.sprites.append(sprite.copy())
def __init__(self, path, tile, data, scale=1): self.image = pg.image.load(path).convert_alpha() self.tile = tile self.sprites = {} self.durations = {} y = 0 # Deslocamento vertical (linhas) #for animation, y in zip(data.items(), range(len(data))): # {'animation_name': [frames...]} for y, animation in enumerate(data.items()): name = animation[0] frames = animation[1] self.sprites[name] = [] self.durations[name] = [] for x, frame in enumerate(frames): frame_image = tools.clip(self.image, x * self.tile, y * self.tile, self.tile, self.tile) frame_image = pg.transform.scale( frame_image, (self.tile * scale, self.tile * scale)) self.sprites[name].append(frame_image.copy()) for _ in range(frame): self.durations[name].append(x)
def __init__(self, path): self.spacing = 1 self.character_order = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&'()*+,-./" font_img = pg.image.load(path).convert() font_img.set_colorkey((0, 0, 0)) current_char_width = 0 self.characters = {} character_count = 0 for x in range(font_img.get_width()): c = font_img.get_at((x, 0)) if c[0] == 127: char_img = tools.clip(font_img, x - current_char_width, 0, current_char_width, font_img.get_height()) self.characters[ self.character_order[character_count]] = char_img.copy() character_count += 1 current_char_width = 0 else: current_char_width += 1 self.space_width = self.characters['A'].get_width() self.height = self.characters['A'].get_height()
def spritecast(self, level, player): """ Algoritmo de raycast de sprites baseado do seguinte tutorial em C++: https://lodev.org/cgtutor/raycasting.html """ w, h = self.size self.middle = None for e in level.entities: e.distance = tools.basic_distance((e.x, e.y), (player.x, player.y)) level.entities.sort(key=lambda e: e.distance, reverse=True) for entity in level.entities: if entity.type == "enemy": sprite = entity.next() else: sprite = entity.sprite tex_width, tex_height = sprite.get_size() sprite_x = entity.x - player.x sprite_y = entity.y - player.y inv_det = 1 / (player.px * player.dy - player.dx * player.py) transform_x = inv_det * (player.dy * sprite_x - player.dx * sprite_y) transform_y = inv_det * (-player.py * sprite_x + player.px * sprite_y) if transform_y == 0: transform_y = 0.1 sprite_screen_x = int((w / 2) * (1 + transform_x / transform_y)) # Limite para não deixar o jogo lento sprite_height = abs(int(h / transform_y)) draw_start_y = int(-sprite_height / 2 + h / 2) draw_end_y = int(sprite_height / 2 + h / 2) # Limite para não deixar o jogo lento sprite_width = min(abs(int(h / transform_y)), 500) draw_start_x = int(-sprite_width / 2 + sprite_screen_x) draw_end_x = int(sprite_width / 2 + sprite_screen_x) if (draw_start_x < w / 2 < draw_end_x and 0 < transform_y < self.zbuffer[int(w / 2)] and entity.type == "enemy" and entity.health > 0): # O inimigo está na nossa mira self.middle = entity if draw_start_x < w and draw_end_x > 0: for stripe in range(max(draw_start_x, 0), min(draw_end_x, w)): if (transform_y > 0 and stripe > 0 and stripe < w and transform_y < self.zbuffer[stripe]): tex_x = int( (stripe - (-sprite_width / 2 + sprite_screen_x)) * tex_width / sprite_width) tex_y = ( (draw_end_y - 1) - h / 2 + sprite_height / 2) * tex_height / sprite_height vline = pg.transform.scale( tools.clip(sprite, tex_x, 0, 1, tex_y), (1, sprite_height)) self.surface.blit(vline, (stripe, draw_start_y))
def raycast(self, level, player): """ Desenha o mundo em '3D', utilizando uma abordagem de iteração por todos os pixels horizontais Algoritmo de raycast baseado do seguinte tutorial em C++: https://lodev.org/cgtutor/raycasting.html Acredito que no futuro é possível torná-lo mais rápido, utilizando alguma implementação com numpy, porém não consegui fazer isso... """ w, h = self.size # Dimensões da tela self.zbuffer = [] # Cores do chão e do teto self.surface.fill(level.color[0], pg.Rect(0, h / 2, w, h / 2)) self.surface.fill(level.color[1], pg.Rect(0, 0, w, h / 2)) for x in range(w): camera_x = 2 * x / w - 1 # Definindo direção do raio ray_dx = player.dx + player.px * camera_x ray_dy = player.dy + player.py * camera_x # Salvando a posição atual do player (estimada com int) map_x = int(player.x) map_y = int(player.y) # Definindo os deltas # Deltas são a distância que um ponto precisa para chegar # até a próxima linha horizontal ou vertical (x ou y) delta_x = 0 if ray_dy == 0 else (1 if ray_dx == 0 else abs(1 / ray_dx)) delta_y = 0 if ray_dx == 0 else (1 if ray_dy == 0 else abs(1 / ray_dy)) # Definindo os valores que utilizaremos nos raios no raycasting if ray_dx < 0: step_x = -1 side_x = (player.x - map_x) * delta_x else: step_x = 1 side_x = (1 + map_x - player.x) * delta_x if ray_dy < 0: step_y = -1 side_y = (player.y - map_y) * delta_y else: step_y = 1 side_y = (1 + map_y - player.y) * delta_y # Enquanto não atingirmos uma parede hit = False while not hit: if side_x < side_y: side_x += delta_x map_x += step_x horizontal = True else: side_y += delta_y map_y += step_y horizontal = False if level.map[map_x][map_y] > 0: hit = True # Checa se é horizontal ou vertical if horizontal: distance = (map_x - player.x + (1 - step_x) / 2) / ray_dx else: distance = (map_y - player.y + (1 - step_y) / 2) / ray_dy distance += 0.1 self.zbuffer.append(distance) line_height = int(h / distance) if line_height > 2000: line_height = 2000 # Definimos o começo e fim da parede (y) draw_start = -line_height / 2 + h / 2 draw_end = line_height / 2 + h / 2 # Salvamos a altura da parede, com base na diferença draw_height = int(draw_end - 1) - int(draw_start) # Definimos qual a textura da parede que atingimos tex_image = self.sprites['walls'].sprites[level.map[map_x][map_y] - 1] # Definimos qual o "ponto x" que atingimos da parede if horizontal: wall_x = player.y + distance * ray_dy else: wall_x = player.x + distance * ray_dx # Após isso, "wall_x" será entre 0 e 1 wall_x -= math.floor(wall_x) # Qual o "ponto x" da textura que utilizaremos tex_x = int(wall_x * level.tex) if (horizontal and ray_dx > 0) or (not horizontal and ray_dy < 0): tex_x = level.tex - tex_x - 1 # Definimos o step, para descobrirmos a altura da textura step = level.tex / line_height # Início da textura (y) tex_pos = (draw_start + line_height / 2 - h / 2) * step # Usamos "and" para caso de overflow tex_y = int(tex_pos) & (level.tex - 1) # Definimos a altura da textura (h) tex_height = step * draw_height # Recortamos a linha vertical da textura, e aumentamos a altura vline = pg.transform.scale( tools.clip(tex_image, tex_x, tex_y, 1, tex_height), (1, draw_height)) # Sombra if level.dark: shadow = pg.Surface(vline.get_size()) shadow.set_alpha(max(min(235 - 255 / distance, 255), 0)) vline.blit(shadow, (0, 0)) elif horizontal: shadow = pg.Surface(vline.get_size()) shadow.set_alpha(100) vline.blit(shadow, (0, 0)) # Blit da linha vertical na surface self.surface.blit(vline, (x, draw_start))