Reputation: 43
Hey i got a lot of entities drawn with curses, they move dynamically and after i changed some code to async (for movement speed functionality) entities sometimes are flickering. What could be the potential issue? I will try to provide most important code snippets (imo), but you can also take a look at the source code on github.
def main(stdscr) -> None:
win = stdscr
width = win.getmaxyx()[1]
height = win.getmaxyx()[0]
ov = Overworld(win, width, height)
system = System(ov, sysinfo)
return asyncio.run(system.run())
if __name__ == "__main__":
stdscr = setup_stdscr()
main(stdscr)
async def refresh_overworld(self):
while self._running:
self.overworld.draw(force_static=self._static_update_iter % REFRESH_STATIC_AFTER == 0)
await asyncio.sleep(0.3)
async def update_system_info(self):
while self._running:
self.system_info.draw()
await asyncio.sleep(0.1)
async def refresh_stdscr(self):
while self._running:
self.overworld.stdscr.refresh()
await asyncio.sleep(0.1)
async def run(self) -> None:
self.overworld.spawn_entities()
self.overworld.stdscr.nodelay(True)
update_task = asyncio.create_task(self.overworld.update())
refresh_task = asyncio.create_task(self.refresh_overworld())
refresh_stdscr = asyncio.create_task(self.refresh_stdscr())
try:
while self._running:
self._static_update_iter += 1
await asyncio.sleep(MINUTE_LENGTH)
finally:
refresh_stdscr.cancel()
update_task.cancel()
refresh_task.cancel()
key_listener_task.cancel()
self.overworld.stdscr.nodelay(False)
self.overworld.stdscr.clear()
self.overworld.stdscr.refresh()
curses.endwin()
```
# overworld
```python
def _draw_entity(self, entity: Entity, position: Position):
biome = self.biome.get_biome_by_coords(position.x, position.y)
biome_color = self.biome.get_biome_color(biome)
char = entity.representation
try:
self.stdscr.addstr(position.y, position.x, char, biome_color)
except curses.error:
pass
def draw(self, force_static: bool = False):
"""
Draw all the existing entities on the board.
"""
logging.debug("Drawing entities in the overworld.")
if not self._static_drawn or force_static:
self.biome.draw()
static_entities = [entity for entity in self.entities if not entity.dynamic]
for entity in static_entities:
self._draw_entity(entity, entity.position)
self._static_drawn = True
dynamic_entities = [entity for entity in self.entities if entity.dynamic]
for entity in dynamic_entities:
self._draw_entity(entity, entity.position)
logging.debug("Entities drawn.")
def end(self):
"""
End the overworld 😲.
"""
logging.debug("Ending the overworld. Clearing screen.")
self.stdscr.clear()
def get_entity_at_position(
self, position: Position, dynamic_only: bool = True, range: int = 2
):
entities = [
entity for entity in self.entities if not dynamic_only or entity.dynamic
]
for entity in entities:
if entity.position.is_within_range(position, range):
return entity
return None
def get_nearby_entities(self, entity: Entity, perception_range: int):
nearby_entities = []
for other_entity in self.entities:
if entity.position.is_within_range(other_entity.position, perception_range):
nearby_entities.append(entity)
return nearby_entities
def is_occupied(self, position: Position):
return position in [entity.position for entity in self.entities]
async def update_entity(self, entity):
while True:
await entity.update(self, self.biome)
await asyncio.sleep(MINUTE_LENGTH / entity.properties.movement_speed)
async def update(self):
"""
Update all the entities in the overworld.
"""
logging.debug("Updating entities in the overworld.")
update_tasks = [asyncio.create_task(self.update_entity(entity)) for entity in self.entities if entity.dynamic]
await asyncio.gather(*update_tasks)
logging.info("Entities updated.")
def _spawn_entities(self):
for entity_class in ENTITIES:
cap = self._calculate_entity_cap(entity_class.frequency)
for _ in range(round(cap)):
self.spawn_entity(entity_class)
def spawn_entity(self, entity: Entity, position: Position = None):
"""
Create new entity and add it to the overworld.
Attributes:
entity: the entity to add to the overworld
position: the position to add the entity to
"""
if not position:
position = self._calculate_position()
biome = self.biome.get_biome_by_coords(position.x, position.y)
else:
biome = self.biome.get_biome_by_coords(position.x, position.y)
spawn_rate = self._get_spawn_rate(entity, biome)
if random.random() < spawn_rate:
entity = entity.create(position, biome)
self.entities.append(entity)
vid: https://streamable.com/6xid97 entire code: https://github.com/style77/EcoSphere
Upvotes: 0
Views: 62