Podział na pliki, jednostki domów i wysypiska, klasa agenta, nowe tilesy
This commit is contained in:
parent
42e9eb9e8b
commit
b1450df77c
27
res/map.txt
27
res/map.txt
@ -1,13 +1,14 @@
|
|||||||
LRRRRRRRRRRRRRRRRR---R---
|
MP------------------------
|
||||||
---R------R------R---RRR-
|
ORRRRRRRRRRRRRRRRRR---R---
|
||||||
---R------R------R---R---
|
SZ--R------R------R---RRR-
|
||||||
RRRR------RRRRRRRRRRRR---
|
----R------R------R---R---
|
||||||
R--R-------------R-------
|
-RRRR------RRRRRRRRRRRR---
|
||||||
R--RRRRRRRRRRRRRRRH------
|
-R--R-------------R-------
|
||||||
R--R---R---R-----R-------
|
-R--RRRRRRRRRRRRRRRH------
|
||||||
R--R---R---R-----RRRRRRR-
|
-R--R---R---RH----R-------
|
||||||
R--R-------------R-------
|
-R--R---R---RH----RRRRRRR-
|
||||||
R--R-----R----R--R-------
|
-R--R-------H-----R-------
|
||||||
R--R-----R----R--R-------
|
-R--R-----R----R--R-------
|
||||||
RRRRRRRRRRRRRRRRRRRRRRR--
|
-R--R-----R----R--R-------
|
||||||
-------------------------
|
-RRRRRRRRRRRRRRRRRRRRRRR--
|
||||||
|
--------------------------
|
BIN
res/tiles.png
BIN
res/tiles.png
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 15 KiB |
6
src/agent.py
Normal file
6
src/agent.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
class Agent:
|
||||||
|
def __init__(self):
|
||||||
|
graph = []
|
||||||
|
|
||||||
|
def inform(self, coordinate_set):
|
||||||
|
pass
|
196
src/main.py
196
src/main.py
@ -1,191 +1,7 @@
|
|||||||
from pathlib import Path
|
from simulation import *
|
||||||
import pygame as pg
|
from agent import *
|
||||||
from random import randint
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
class Entity:
|
agent = Agent()
|
||||||
def __init__(self, state, position, tile):
|
simulation = Interface(agent)
|
||||||
self.state = state
|
simulation.loop()
|
||||||
self.position = position
|
|
||||||
self.tile = tile
|
|
||||||
|
|
||||||
def move(self, move_vector):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
class Agent(Entity):
|
|
||||||
def move(self, move_vector):
|
|
||||||
proposed_pos = self.position + move_vector
|
|
||||||
move_valid = True
|
|
||||||
|
|
||||||
if proposed_pos != self.state.landfill_pos and proposed_pos not in self.state.roads_pos:
|
|
||||||
move_valid = False
|
|
||||||
if proposed_pos.x < 0 or proposed_pos.x >= self.state.world_limits.x:
|
|
||||||
move_valid = False
|
|
||||||
if proposed_pos.y < 0 or proposed_pos.y >= self.state.world_limits.y:
|
|
||||||
move_valid = False
|
|
||||||
|
|
||||||
if move_valid:
|
|
||||||
self.position = proposed_pos
|
|
||||||
|
|
||||||
|
|
||||||
class SimulationState:
|
|
||||||
def __init__(self):
|
|
||||||
self.landfill_pos = []
|
|
||||||
self.roads_pos = []
|
|
||||||
self.houses_pos = []
|
|
||||||
|
|
||||||
map_path = Path("../res/map.txt")
|
|
||||||
with open(map_path, "r") as map_file:
|
|
||||||
map_data = map_file.readlines()
|
|
||||||
max_x = len(map_data[0].replace('\n', ''))
|
|
||||||
max_y = len(map_data)
|
|
||||||
for y in range(0, max_y):
|
|
||||||
for x in range(0, max_x):
|
|
||||||
tile = map_data[y].replace('\n', '')[x]
|
|
||||||
|
|
||||||
if tile == "L":
|
|
||||||
self.landfill_pos.append(pg.Vector2(x, y))
|
|
||||||
if tile == "R":
|
|
||||||
self.roads_pos.append(pg.Vector2(x, y))
|
|
||||||
if tile == "H":
|
|
||||||
self.houses_pos.append(pg.Vector2(x, y))
|
|
||||||
self.world_limits = pg.Vector2(max_x, max_y)
|
|
||||||
|
|
||||||
self.entities = [Agent(self, self.landfill_pos[0], pg.Vector2(2, 0))]
|
|
||||||
|
|
||||||
def update(self, move_agent):
|
|
||||||
for entity in self.entities:
|
|
||||||
entity.move(move_agent)
|
|
||||||
|
|
||||||
|
|
||||||
class Layer:
|
|
||||||
def __init__(self, sim, texture_file):
|
|
||||||
self.sim = sim
|
|
||||||
self.texture_atlas = pg.image.load(texture_file)
|
|
||||||
|
|
||||||
def renderTile(self, surface, position, tile):
|
|
||||||
# pozycja na ekranie
|
|
||||||
sprite_pos = position.elementwise() * self.sim.cell_size
|
|
||||||
|
|
||||||
# tekstura
|
|
||||||
pos_in_atlas = tile.elementwise() * self.sim.cell_size
|
|
||||||
texture = pg.Rect(int(pos_in_atlas.x),
|
|
||||||
int(pos_in_atlas.y),
|
|
||||||
self.sim.cell_size.x,
|
|
||||||
self.sim.cell_size.y)
|
|
||||||
|
|
||||||
# render
|
|
||||||
surface.blit(self.texture_atlas, sprite_pos, texture)
|
|
||||||
|
|
||||||
def render(self, surface):
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
class EntityLayer(Layer):
|
|
||||||
def __init__(self, sim, texture_file, simulation_state, entities):
|
|
||||||
super().__init__(sim, texture_file)
|
|
||||||
self.simulation_state = simulation_state
|
|
||||||
self.entities = entities
|
|
||||||
|
|
||||||
def render(self, surface):
|
|
||||||
for entity in self.entities:
|
|
||||||
self.renderTile(surface, entity.position, entity.tile)
|
|
||||||
|
|
||||||
|
|
||||||
class StructureLayer(Layer):
|
|
||||||
def __init__(self, sim, texture_file, simulation_state, structures_pos, tile):
|
|
||||||
super().__init__(sim, texture_file)
|
|
||||||
self.simulation_state = simulation_state
|
|
||||||
self.structures_pos = structures_pos
|
|
||||||
self.tile = tile
|
|
||||||
|
|
||||||
def render(self, surface):
|
|
||||||
for position in self.structures_pos:
|
|
||||||
self.renderTile(surface, position, self.tile)
|
|
||||||
|
|
||||||
|
|
||||||
class Interface:
|
|
||||||
def __init__(self):
|
|
||||||
pg.init()
|
|
||||||
|
|
||||||
# stan symulacji
|
|
||||||
self.simulation_state = SimulationState()
|
|
||||||
self.move_agent = pg.Vector2(0, 0)
|
|
||||||
|
|
||||||
# rendering
|
|
||||||
self.cell_size = pg.Vector2(64, 64)
|
|
||||||
texture_file = Path("../res/tiles.png")
|
|
||||||
self.layers = [StructureLayer(self, texture_file, self.simulation_state, self.simulation_state.landfill_pos, pg.Vector2(3, 0)),
|
|
||||||
StructureLayer(self, texture_file, self.simulation_state, self.simulation_state.roads_pos, pg.Vector2(0, 0)),
|
|
||||||
StructureLayer(self, texture_file, self.simulation_state, self.simulation_state.houses_pos, pg.Vector2(1, 0)),
|
|
||||||
EntityLayer(self, texture_file, self.simulation_state, self.simulation_state.entities)]
|
|
||||||
|
|
||||||
# okno
|
|
||||||
pg.display.set_caption("Inteligentna śmieciarka")
|
|
||||||
window_size = self.simulation_state.world_limits.elementwise() * self.cell_size
|
|
||||||
self.window = pg.display.set_mode((int(window_size.x), int(window_size.y)))
|
|
||||||
self.simulation_state.world_limits.elementwise() * self.cell_size
|
|
||||||
|
|
||||||
# dla pętli
|
|
||||||
self.clock = pg.time.Clock()
|
|
||||||
self.run_simulation = True
|
|
||||||
|
|
||||||
self.debug_mode = False
|
|
||||||
|
|
||||||
def processUserInput(self):
|
|
||||||
self.move_agent = pg.Vector2(0, 0)
|
|
||||||
|
|
||||||
for event in pg.event.get():
|
|
||||||
if event.type == pg.QUIT:
|
|
||||||
self.run_simulation = False
|
|
||||||
break
|
|
||||||
elif event.type == pg.KEYDOWN:
|
|
||||||
if event.key == pg.K_ESCAPE:
|
|
||||||
self.run_simulation = False
|
|
||||||
break
|
|
||||||
if event.key == pg.K_BACKQUOTE:
|
|
||||||
self.debug_mode = not self.debug_mode
|
|
||||||
|
|
||||||
if self.debug_mode:
|
|
||||||
if event.key == pg.K_RIGHT:
|
|
||||||
self.move_agent.x = 1
|
|
||||||
if event.key == pg.K_LEFT:
|
|
||||||
self.move_agent.x = -1
|
|
||||||
if event.key == pg.K_DOWN:
|
|
||||||
self.move_agent.y = 1
|
|
||||||
if event.key == pg.K_UP:
|
|
||||||
self.move_agent.y = -1
|
|
||||||
|
|
||||||
def processSimulationInput(self):
|
|
||||||
moves = [pg.Vector2(-1, 0), pg.Vector2(1, 0), pg.Vector2(0, -1), pg.Vector2(0, 1)]
|
|
||||||
|
|
||||||
self.move_agent = moves[randint(0,3)]
|
|
||||||
|
|
||||||
def update(self):
|
|
||||||
self.simulation_state.update(self.move_agent)
|
|
||||||
|
|
||||||
def render(self):
|
|
||||||
if not self.debug_mode:
|
|
||||||
self.window.fill((8, 68, 0))
|
|
||||||
else:
|
|
||||||
self.window.fill((68, 8, 0))
|
|
||||||
|
|
||||||
for layer in self.layers:
|
|
||||||
layer.render(self.window)
|
|
||||||
|
|
||||||
pg.display.update()
|
|
||||||
|
|
||||||
def loop(self):
|
|
||||||
while self.run_simulation:
|
|
||||||
self.processUserInput()
|
|
||||||
if not self.debug_mode:
|
|
||||||
self.processSimulationInput()
|
|
||||||
self.update()
|
|
||||||
self.render()
|
|
||||||
self.clock.tick(24)
|
|
||||||
pg.quit()
|
|
||||||
|
|
||||||
|
|
||||||
simulation = Interface()
|
|
||||||
simulation.loop()
|
|
||||||
|
237
src/simulation.py
Normal file
237
src/simulation.py
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
import pygame as pg
|
||||||
|
from random import randint
|
||||||
|
|
||||||
|
ROAD_SPRITE = pg.Vector2(0, 0)
|
||||||
|
|
||||||
|
HOUSE_WITHOUT_TRASH_SPRITE = pg.Vector2(1, 0)
|
||||||
|
HOUSE_WITH_TRASH_SPRITE = pg.Vector2(1, 1)
|
||||||
|
HOUSE_SPRITES = {0: HOUSE_WITHOUT_TRASH_SPRITE,
|
||||||
|
1: HOUSE_WITH_TRASH_SPRITE}
|
||||||
|
|
||||||
|
TRUCK_SPRITE = pg.Vector2(2, 0)
|
||||||
|
|
||||||
|
PAPER_DUMP_SPRITE = pg.Vector2(3, 0)
|
||||||
|
PLASTIC_DUMP_SPRITE = pg.Vector2(3, 1)
|
||||||
|
GLASS_DUMP_SPRITE = pg.Vector2(3, 2)
|
||||||
|
MIXED_DUMP_SPRITE = pg.Vector2(3, 3)
|
||||||
|
DUMP_SPRITES = {'paper': PAPER_DUMP_SPRITE,
|
||||||
|
'glass': GLASS_DUMP_SPRITE,
|
||||||
|
'plastic': PLASTIC_DUMP_SPRITE,
|
||||||
|
'mixed': MIXED_DUMP_SPRITE}
|
||||||
|
|
||||||
|
|
||||||
|
class Entity:
|
||||||
|
def __init__(self, state, position):
|
||||||
|
self.state = state
|
||||||
|
self.position = position
|
||||||
|
|
||||||
|
|
||||||
|
class TruckEntity(Entity):
|
||||||
|
def __init__(self, state, position):
|
||||||
|
super().__init__(state, position)
|
||||||
|
self.tile = TRUCK_SPRITE
|
||||||
|
|
||||||
|
def move(self, move_vector):
|
||||||
|
proposed_pos = self.position + move_vector
|
||||||
|
move_valid = True
|
||||||
|
|
||||||
|
if proposed_pos not in self.state.roads_pos:
|
||||||
|
move_valid = False
|
||||||
|
if proposed_pos.x < 0 or proposed_pos.x >= self.state.world_limits.x:
|
||||||
|
move_valid = False
|
||||||
|
if proposed_pos.y < 0 or proposed_pos.y >= self.state.world_limits.y:
|
||||||
|
move_valid = False
|
||||||
|
|
||||||
|
if move_valid:
|
||||||
|
self.position = proposed_pos
|
||||||
|
|
||||||
|
|
||||||
|
class HouseEntity(Entity):
|
||||||
|
def __init__(self, state, position):
|
||||||
|
super().__init__(state, position)
|
||||||
|
self.tile = HOUSE_SPRITES[0]
|
||||||
|
|
||||||
|
|
||||||
|
class DumpEntity(Entity):
|
||||||
|
def __init__(self, state, position, trash_type):
|
||||||
|
super().__init__(state, position)
|
||||||
|
self.tile = DUMP_SPRITES[trash_type]
|
||||||
|
|
||||||
|
|
||||||
|
class SimulationState:
|
||||||
|
def __init__(self):
|
||||||
|
self.roads_pos = []
|
||||||
|
self.houses_pos = []
|
||||||
|
self.entities = []
|
||||||
|
|
||||||
|
map_path = Path("../res/map.txt")
|
||||||
|
with open(map_path, "r") as map_file:
|
||||||
|
map_data = map_file.readlines()
|
||||||
|
max_x = len(map_data[0].replace('\n', ''))
|
||||||
|
max_y = len(map_data)
|
||||||
|
for y in range(0, max_y):
|
||||||
|
for x in range(0, max_x):
|
||||||
|
tile = map_data[y].replace('\n', '')[x]
|
||||||
|
|
||||||
|
if tile == "O":
|
||||||
|
self.truck_origin = pg.Vector2(x, y)
|
||||||
|
self.entities.append(TruckEntity(self, self.truck_origin))
|
||||||
|
self.roads_pos.append(pg.Vector2(x, y))
|
||||||
|
if tile == "R":
|
||||||
|
self.roads_pos.append(pg.Vector2(x, y))
|
||||||
|
if tile == "H":
|
||||||
|
self.houses_pos.append(pg.Vector2(x, y))
|
||||||
|
self.entities.append(HouseEntity(self, pg.Vector2(x, y)))
|
||||||
|
if tile == "M":
|
||||||
|
self.paper_dump_pos = pg.Vector2(x, y)
|
||||||
|
self.entities.append(DumpEntity(self, pg.Vector2(x, y), 'paper'))
|
||||||
|
if tile == "P":
|
||||||
|
self.plastic_dump_pos = pg.Vector2(x, y)
|
||||||
|
self.entities.append(DumpEntity(self, pg.Vector2(x, y), 'plastic'))
|
||||||
|
if tile == "S":
|
||||||
|
self.glass_dump_pos = pg.Vector2(x, y)
|
||||||
|
self.entities.append(DumpEntity(self, pg.Vector2(x, y), 'glass'))
|
||||||
|
if tile == "Z":
|
||||||
|
self.mixed_dump_pos = pg.Vector2(x, y)
|
||||||
|
self.entities.append(DumpEntity(self, pg.Vector2(x, y), 'mixed'))
|
||||||
|
|
||||||
|
self.world_limits = pg.Vector2(max_x, max_y)
|
||||||
|
|
||||||
|
def update(self, move_agent):
|
||||||
|
for entity in self.entities:
|
||||||
|
if entity.__class__ is TruckEntity:
|
||||||
|
entity.move(move_agent)
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
class Layer:
|
||||||
|
def __init__(self, sim, texture_file):
|
||||||
|
self.sim = sim
|
||||||
|
self.texture_atlas = pg.image.load(texture_file)
|
||||||
|
|
||||||
|
def renderTile(self, surface, position, tile):
|
||||||
|
# pozycja na ekranie
|
||||||
|
sprite_pos = position.elementwise() * self.sim.cell_size
|
||||||
|
|
||||||
|
# tekstura
|
||||||
|
pos_in_atlas = tile.elementwise() * self.sim.cell_size
|
||||||
|
texture = pg.Rect(int(pos_in_atlas.x),
|
||||||
|
int(pos_in_atlas.y),
|
||||||
|
self.sim.cell_size.x,
|
||||||
|
self.sim.cell_size.y)
|
||||||
|
|
||||||
|
# render
|
||||||
|
surface.blit(self.texture_atlas, sprite_pos, texture)
|
||||||
|
|
||||||
|
def render(self, surface):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
class EntityLayer(Layer):
|
||||||
|
def __init__(self, sim, texture_file, simulation_state, entities):
|
||||||
|
super().__init__(sim, texture_file)
|
||||||
|
self.simulation_state = simulation_state
|
||||||
|
self.entities = entities
|
||||||
|
|
||||||
|
def render(self, surface):
|
||||||
|
for entity in self.entities:
|
||||||
|
self.renderTile(surface, entity.position, entity.tile)
|
||||||
|
|
||||||
|
|
||||||
|
class StructureLayer(Layer):
|
||||||
|
def __init__(self, sim, texture_file, simulation_state, structures_pos, tile):
|
||||||
|
super().__init__(sim, texture_file)
|
||||||
|
self.simulation_state = simulation_state
|
||||||
|
self.structures_pos = structures_pos
|
||||||
|
self.tile = tile
|
||||||
|
|
||||||
|
def render(self, surface):
|
||||||
|
for position in self.structures_pos:
|
||||||
|
self.renderTile(surface, position, self.tile)
|
||||||
|
|
||||||
|
|
||||||
|
class Interface:
|
||||||
|
def __init__(self, agent):
|
||||||
|
pg.init()
|
||||||
|
|
||||||
|
# autonomiczny agent
|
||||||
|
self.agent = agent
|
||||||
|
|
||||||
|
# stan symulacji
|
||||||
|
self.simulation_state = SimulationState()
|
||||||
|
self.move_agent = pg.Vector2(0, 0)
|
||||||
|
|
||||||
|
# rendering
|
||||||
|
self.cell_size = pg.Vector2(64, 64)
|
||||||
|
texture_file = Path("../res/tiles.png")
|
||||||
|
self.layers = [StructureLayer(self, texture_file, self.simulation_state,
|
||||||
|
self.simulation_state.roads_pos, ROAD_SPRITE),
|
||||||
|
EntityLayer(self, texture_file, self.simulation_state,
|
||||||
|
self.simulation_state.entities)]
|
||||||
|
|
||||||
|
# okno
|
||||||
|
pg.display.set_caption("Inteligentna śmieciarka")
|
||||||
|
window_size = self.simulation_state.world_limits.elementwise() * self.cell_size
|
||||||
|
self.window = pg.display.set_mode((int(window_size.x), int(window_size.y)))
|
||||||
|
self.simulation_state.world_limits.elementwise() * self.cell_size
|
||||||
|
|
||||||
|
# dla pętli
|
||||||
|
self.clock = pg.time.Clock()
|
||||||
|
self.run_simulation = True
|
||||||
|
|
||||||
|
self.debug_mode = False
|
||||||
|
|
||||||
|
def processUserInput(self):
|
||||||
|
self.move_agent = pg.Vector2(0, 0)
|
||||||
|
|
||||||
|
for event in pg.event.get():
|
||||||
|
if event.type == pg.QUIT:
|
||||||
|
self.run_simulation = False
|
||||||
|
break
|
||||||
|
elif event.type == pg.KEYDOWN:
|
||||||
|
if event.key == pg.K_ESCAPE:
|
||||||
|
self.run_simulation = False
|
||||||
|
break
|
||||||
|
if event.key == pg.K_BACKQUOTE:
|
||||||
|
self.debug_mode = not self.debug_mode
|
||||||
|
|
||||||
|
if self.debug_mode:
|
||||||
|
if event.key == pg.K_RIGHT:
|
||||||
|
self.move_agent.x = 1
|
||||||
|
if event.key == pg.K_LEFT:
|
||||||
|
self.move_agent.x = -1
|
||||||
|
if event.key == pg.K_DOWN:
|
||||||
|
self.move_agent.y = 1
|
||||||
|
if event.key == pg.K_UP:
|
||||||
|
self.move_agent.y = -1
|
||||||
|
|
||||||
|
def processAgentInput(self):
|
||||||
|
moves = [pg.Vector2(-1, 0), pg.Vector2(1, 0), pg.Vector2(0, -1), pg.Vector2(0, 1)]
|
||||||
|
|
||||||
|
self.move_agent = moves[randint(0, 3)]
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
self.simulation_state.update(self.move_agent)
|
||||||
|
|
||||||
|
def render(self):
|
||||||
|
if not self.debug_mode:
|
||||||
|
self.window.fill((89, 183, 53))
|
||||||
|
else:
|
||||||
|
self.window.fill((180, 32, 42))
|
||||||
|
|
||||||
|
for layer in self.layers:
|
||||||
|
layer.render(self.window)
|
||||||
|
|
||||||
|
pg.display.update()
|
||||||
|
|
||||||
|
def loop(self):
|
||||||
|
self.agent.inform(set())
|
||||||
|
while self.run_simulation:
|
||||||
|
self.processUserInput()
|
||||||
|
if not self.debug_mode:
|
||||||
|
self.processAgentInput()
|
||||||
|
self.update()
|
||||||
|
self.render()
|
||||||
|
self.clock.tick(24)
|
||||||
|
pg.quit()
|
Loading…
Reference in New Issue
Block a user