247 lines
7.4 KiB
Python
247 lines
7.4 KiB
Python
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
|
|
|
|
|