import os from pygame import Rect, image import pygame from utils import load_image class Block: BRICK = "brick" GRASS = "grass" KUST = "kust" STONE = "stone" WATER = "water" PLAYER_SPAWN = "player_spawn" ENEMY_SPAWN = "enemy_spawn" def __init__(self, game, x, y, i, j, type: str): self.game = game self.settings = self.game.settings self.height = self.settings.block_size self.width = self.settings.block_size self.image_folder = os.path.join(self.settings.img_folder, "map") self.type = type self.passable = self.is_passable() self.projectile_passable = self.is_projectile_passable() #print(os.path.join(self.image_folder, self.type, ".png")) self.image = load_image(self.settings, os.path.join(self.image_folder, self.type + ".png")) #print(os.path.join(self.image_folder, self.type + ".png")) self.x = x self.y = y self.i = i self.j = j self.update() def update(self): self.rect = self.game.screen.blit(self.image, (self.x, self.y)) def is_passable(self): if self.type == "brick" or self.type == "stone" or self.type == "water": return False else: return True def is_projectile_passable(self): if self.type == "brick" or self.type == "stone": return False else: return True def __str__(self): return "{} block on x: {}, y: {}".format(self.type, self.x, self.y) class Map: def __init__(self, game, lc_x: int, lc_y: int): self.game = game self.settings = game.settings self.x = lc_x self.y = lc_y self.charmap = self.load_map("BattleCity.txt") self.blockmap = [] self.enemy_spawns = [] k = 0 i = self.y j = self.x for line in self.charmap: self.blockmap.append([]) j = self.x l = 0 for block in line: self.blockmap[k].append(self.get_block_by_char(block, j, i, k, l)) if block == "P": self.player_spawn = self.blockmap[k][-1] if block == "E": self.enemy_spawns.append(self.blockmap[k][-1]) j += self.settings.block_size l += 1 k += 1 i += self.settings.block_size self.enemies = None es = self.settings.entity_size self.tank_rect = Rect(self.settings.c_x - es // 2, self.settings.c_y - es // 2, es, es) def load_map(self, filename: str) -> list: f = open(os.path.join(self.settings.map_folder, filename)) lines = f.readlines() f.close() i = 0 result = [] for line in lines: result.append([]) for c in line: if c in "BGKSWPE": result[i].append(c) i += 1 #print(result) return result def get_block_by_char(self, char, x, y, i, j): tp = None if char == "B": tp = Block.BRICK elif char == "G": tp = Block.GRASS elif char == "K": tp = Block.KUST elif char == "S": tp = Block.STONE elif char == "W": tp = Block.WATER elif char == "P": tp = Block.PLAYER_SPAWN elif char == "E": tp = Block.ENEMY_SPAWN if tp != None: return Block(self.game, x, y, i, j, tp) else: return False def add_enemies(self, enemies): self.enemies = enemies def update(self): for line in self.blockmap: for block in line: block.update() def change_coords(self, x = None, y = None): if self.enemies != None: dx = self.x - x if x != None else 0 dy = self.y - y if y != None else 0 for enemy in self.enemies.sprites(): enemy.change_coords_by_delta(dx, dy) for projectile in self.game.projectiles.projectiles: projectile.change_coords_by_delta(dx, dy) k = 0 self.x = x if x != None else self.x self.y = y if y != None else self.y j = self.x i = self.y for line in self.blockmap: j = self.x for block in line: block.x = j block.y = i j += self.settings.block_size k += 1 i += self.settings.block_size def get_block_collision_vars(self): #cx, cy, tsh return self.settings.c_x, self.settings.c_y, self.settings.block_size // 2 def move_up(self): cx, cy, tsh = self.get_block_collision_vars() cp1 = (cx - tsh + 2, cy - tsh) cp2 = (cx + tsh - 2, cy - tsh) if self.check_on_moveability(cp1[0], cp1[1], 0, self.settings.move_speed) and self.check_on_moveability(cp2[0], cp2[1], 0, self.settings.move_speed): self.change_coords(None, self.y + self.settings.move_speed) def move_down(self): cx, cy, tsh = self.get_block_collision_vars() cp1 = (cx - tsh + 2, cy + tsh) cp2 = (cx + tsh - 2, cy + tsh) if self.check_on_moveability(cp1[0], cp1[1], 0, -self.settings.move_speed) and self.check_on_moveability(cp2[0], cp2[1], 0, -self.settings.move_speed): self.change_coords(None, self.y - self.settings.move_speed) def move_left(self): cx, cy, tsh = self.get_block_collision_vars() cp1 = (cx - tsh, cy - tsh + 2) cp2 = (cx - tsh, cy + tsh - 2) if self.check_on_moveability(cp1[0], cp1[1], self.settings.move_speed, 0) and self.check_on_moveability(cp2[0], cp2[1], -self.settings.move_speed, 0): self.change_coords(self.x + self.settings.move_speed, None) def move_right(self): cx, cy, tsh = self.get_block_collision_vars() cp1 = (cx + tsh, cy - tsh + 2) cp2 = (cx + tsh, cy + tsh - 2) if self.check_on_moveability(cp1[0], cp1[1], -self.settings.move_speed, 0) and self.check_on_moveability(cp2[0], cp2[1], -self.settings.move_speed, 0): self.change_coords(self.x - self.settings.move_speed, None) def check_on_moveability(self, x, y, dx, dy): #print(x, y, dx, dy) #print(self.find_block_on_coords(x + dx, y + dy)) if self.find_block_on_coords(x, y).passable: return True else: return False def find_block_on_coords(self, x, y): block_line = None for line in self.blockmap: if line[0].y <= y and y < line[0].y + self.settings.block_size: block_line = line break if block_line != None: for block in line: if block.x <= x and x < block.x + self.settings.block_size: return block return False def __str__(self): res = "" for line in self.blockmap: for block in line: res += str(block) + "; " res += "\n" return res