WIP: display events on the map
28
game/game.py
@ -100,21 +100,11 @@ class Game:
|
|||||||
self.enemy = enemy_name
|
self.enemy = enemy_name
|
||||||
|
|
||||||
def _roll(self, prob, mult):
|
def _roll(self, prob, mult):
|
||||||
return random.randint(1, 100) <= prob * mult
|
if self.settings.version == "dev":
|
||||||
|
# always generate all events for dev
|
||||||
def _generate_globalinterceptions(self):
|
return 100
|
||||||
global_count = len([x for x in self.theater.player_points() if x.is_global])
|
else:
|
||||||
for from_cp in [x for x in self.theater.player_points() if x.is_global]:
|
return random.randint(1, 100) <= prob * mult
|
||||||
probability_base = max(PLAYER_INTERCEPT_GLOBAL_PROBABILITY_BASE / global_count, 1)
|
|
||||||
probability = probability_base * math.log(len(self.theater.player_points()) + 1, PLAYER_INTERCEPT_GLOBAL_PROBABILITY_LOG)
|
|
||||||
if self._roll(probability, from_cp.base.strength):
|
|
||||||
to_cp = random.choice([x for x in self.theater.enemy_points() if x not in self.theater.conflicts()])
|
|
||||||
self.events.append(InterceptEvent(attacker_name=self.player,
|
|
||||||
defender_name=self.enemy,
|
|
||||||
from_cp=from_cp,
|
|
||||||
to_cp=to_cp,
|
|
||||||
game=self))
|
|
||||||
break
|
|
||||||
|
|
||||||
def _generate_player_event(self, event_class, player_cp, enemy_cp):
|
def _generate_player_event(self, event_class, player_cp, enemy_cp):
|
||||||
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
|
if event_class == NavalInterceptEvent and enemy_cp.radials == LAND:
|
||||||
@ -173,20 +163,12 @@ class Game:
|
|||||||
|
|
||||||
def _generate_events(self):
|
def _generate_events(self):
|
||||||
for player_cp, enemy_cp in self.theater.conflicts(True):
|
for player_cp, enemy_cp in self.theater.conflicts(True):
|
||||||
if enemy_cp.is_global:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
|
for event_class, (player_probability, enemy_probability) in EVENT_PROBABILITIES.items():
|
||||||
if event_class in [FrontlineAttackEvent, FrontlinePatrolEvent, InfantryTransportEvent]:
|
if event_class in [FrontlineAttackEvent, FrontlinePatrolEvent, InfantryTransportEvent]:
|
||||||
# skip events requiring frontline
|
# skip events requiring frontline
|
||||||
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
if not Conflict.has_frontline_between(player_cp, enemy_cp):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if player_cp.is_global:
|
|
||||||
# skip events requiring ground CP
|
|
||||||
if event_class not in [InterceptEvent, StrikeEvent, NavalInterceptEvent]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if player_probability == 100 or self._roll(player_probability, player_cp.base.strength):
|
if player_probability == 100 or self._roll(player_probability, player_cp.base.strength):
|
||||||
self._generate_player_event(event_class, player_cp, enemy_cp)
|
self._generate_player_event(event_class, player_cp, enemy_cp)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 229 B |
|
Before Width: | Height: | Size: 197 B |
|
Before Width: | Height: | Size: 315 B |
|
Before Width: | Height: | Size: 196 B |
|
Before Width: | Height: | Size: 220 B |
|
Before Width: | Height: | Size: 253 B |
|
Before Width: | Height: | Size: 213 B |
|
Before Width: | Height: | Size: 224 B |
|
Before Width: | Height: | Size: 227 B |
|
Before Width: | Height: | Size: 235 B |
|
Before Width: | Height: | Size: 230 B |
|
Before Width: | Height: | Size: 232 B |
@ -72,7 +72,7 @@ def generate_groundobjects(theater: ConflictTheater):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
group_id = 0
|
group_id = 0
|
||||||
for cp in theater.enemy_points():
|
for cp in theater.controlpoints:
|
||||||
for _ in range(0, random.randrange(2, 4)):
|
for _ in range(0, random.randrange(2, 4)):
|
||||||
available_categories = list(tpls) + ["aa", "aa"]
|
available_categories = list(tpls) + ["aa", "aa"]
|
||||||
tpl_category = random.choice(available_categories)
|
tpl_category = random.choice(available_categories)
|
||||||
|
|||||||
@ -32,6 +32,8 @@ class OverviewCanvas:
|
|||||||
HEIGHT = 600
|
HEIGHT = 600
|
||||||
|
|
||||||
started = None
|
started = None
|
||||||
|
ground_assets_icons = None # type: typing.Dict[str, pygame.Surface]
|
||||||
|
event_icons = None # type: typing.Dict[typing.Type, pygame.Surface]
|
||||||
selected_event_info = None # type: typing.Tuple[Event, typing.Tuple[int, int]]
|
selected_event_info = None # type: typing.Tuple[Event, typing.Tuple[int, int]]
|
||||||
frontline_vector_cache = None # type: typing.Dict[str, typing.Tuple[Point, int, int]]
|
frontline_vector_cache = None # type: typing.Dict[str, typing.Tuple[Point, int, int]]
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ class OverviewCanvas:
|
|||||||
pygame.font.init()
|
pygame.font.init()
|
||||||
self.font: pygame.font.SysFont = pygame.font.SysFont("arial", 15)
|
self.font: pygame.font.SysFont = pygame.font.SysFont("arial", 15)
|
||||||
self.fontsmall: pygame.font.SysFont = pygame.font.SysFont("arial", 10)
|
self.fontsmall: pygame.font.SysFont = pygame.font.SysFont("arial", 10)
|
||||||
self.icons = {}
|
self.ground_assets_icons = {}
|
||||||
|
|
||||||
# Frontline are too heavy on performance to compute in realtime, so keep them in a cache
|
# Frontline are too heavy on performance to compute in realtime, so keep them in a cache
|
||||||
self.frontline_vector_cache = {}
|
self.frontline_vector_cache = {}
|
||||||
@ -144,14 +146,23 @@ class OverviewCanvas:
|
|||||||
self.screen.fill(pygame.Color(*self.BLACK))
|
self.screen.fill(pygame.Color(*self.BLACK))
|
||||||
|
|
||||||
# Load icons resources
|
# Load icons resources
|
||||||
self.icons = {}
|
self.ground_assets_icons = {}
|
||||||
self.icons["target"] = pygame.image.load(os.path.join("resources", "ui", "target.png"))
|
self.ground_assets_icons["target"] = pygame.image.load(os.path.join("resources", "ui", "ground_assets", "target.png"))
|
||||||
self.icons["cleared"] = pygame.image.load(os.path.join("resources", "ui", "cleared.png"))
|
self.ground_assets_icons["cleared"] = pygame.image.load(os.path.join("resources", "ui", "ground_assets", "cleared.png"))
|
||||||
for category in CATEGORY_MAP.keys():
|
for category in CATEGORY_MAP.keys():
|
||||||
try:
|
self.ground_assets_icons[category] = pygame.image.load(os.path.join("resources", "ui", "ground_assets", category + ".png"))
|
||||||
self.icons[category] = pygame.image.load(os.path.join("resources", "ui", category + ".png"))
|
|
||||||
except:
|
self.event_icons = {}
|
||||||
print("Couldn't load icon for : " + category)
|
for category, image in {BaseAttackEvent: "capture",
|
||||||
|
FrontlinePatrolEvent: "attack",
|
||||||
|
FrontlineAttackEvent: "attack",
|
||||||
|
InfantryTransportEvent: "infantry",
|
||||||
|
InsurgentAttackEvent: "insurgent_attack",
|
||||||
|
InterceptEvent: "air_intercept",
|
||||||
|
NavalInterceptEvent: "naval_intercept",
|
||||||
|
StrikeEvent: "strike"}.items():
|
||||||
|
self.event_icons[category] = pygame.image.load(os.path.join("resources", "ui", "events", image + ".png"))
|
||||||
|
|
||||||
|
|
||||||
# Load the map image
|
# Load the map image
|
||||||
self.map = pygame.image.load(os.path.join("resources", self.game.theater.overview_image)).convert()
|
self.map = pygame.image.load(os.path.join("resources", self.game.theater.overview_image)).convert()
|
||||||
@ -409,12 +420,12 @@ class OverviewCanvas:
|
|||||||
rect = pygame.Rect(x, y, 16, 16)
|
rect = pygame.Rect(x, y, 16, 16)
|
||||||
|
|
||||||
if ground_object.is_dead:
|
if ground_object.is_dead:
|
||||||
surface.blit(self.icons["cleared"], (x, y))
|
surface.blit(self.ground_assets_icons["cleared"], (x, y))
|
||||||
else:
|
else:
|
||||||
if ground_object.category in self.icons.keys():
|
if ground_object.category in self.ground_assets_icons.keys():
|
||||||
icon = self.icons[ground_object.category]
|
icon = self.ground_assets_icons[ground_object.category]
|
||||||
else:
|
else:
|
||||||
icon = self.icons["target"]
|
icon = self.ground_assets_icons["target"]
|
||||||
surface.blit(icon, (x, y))
|
surface.blit(icon, (x, y))
|
||||||
|
|
||||||
if rect.collidepoint(*mouse_pos):
|
if rect.collidepoint(*mouse_pos):
|
||||||
@ -425,36 +436,46 @@ class OverviewCanvas:
|
|||||||
surface.blit(lb, (pos[0] + 18, pos[1]))
|
surface.blit(lb, (pos[0] + 18, pos[1]))
|
||||||
|
|
||||||
def draw_events(self, surface: pygame.Surface, mouse_pos, mouse_down):
|
def draw_events(self, surface: pygame.Surface, mouse_pos, mouse_down):
|
||||||
location_point_counters = {}
|
occupied_rects = [pygame.Rect(*self._transform_point(x.position), 32, 32) for x in self.game.theater.controlpoints]
|
||||||
|
|
||||||
def _location_to_point(location: Point) -> typing.Tuple[int, int]:
|
|
||||||
nonlocal location_point_counters
|
|
||||||
key = str(location.x) + str(location.y)
|
|
||||||
|
|
||||||
|
def _location_to_rect(location: Point) -> pygame.Rect:
|
||||||
|
nonlocal occupied_rects
|
||||||
point = self._transform_point(location)
|
point = self._transform_point(location)
|
||||||
point = point[0], point[1] + location_point_counters.get(key, 0) * 40
|
rect = pygame.Rect(*point, 32, 32)
|
||||||
|
i = 0
|
||||||
|
for occupied_rect in occupied_rects:
|
||||||
|
if rect.colliderect(occupied_rect):
|
||||||
|
i += 1
|
||||||
|
if i % 2:
|
||||||
|
rect.y = occupied_rect.y + occupied_rect.height + 3
|
||||||
|
else:
|
||||||
|
rect.x = occupied_rect.x + occupied_rect.width + 3
|
||||||
|
|
||||||
location_point_counters[key] = location_point_counters.get(key, 0) + 1
|
occupied_rects.append(rect)
|
||||||
return point
|
return rect
|
||||||
|
|
||||||
|
label_to_draw = None
|
||||||
for event in self.game.events:
|
for event in self.game.events:
|
||||||
location = event.location
|
location = event.location
|
||||||
if isinstance(event, FrontlinePatrolEvent) or isinstance(event, FrontlineAttackEvent):
|
if isinstance(event, FrontlinePatrolEvent) or isinstance(event, FrontlineAttackEvent):
|
||||||
location = self._frontline_center(event.from_cp, event.to_cp)
|
location = self._frontline_center(event.from_cp, event.to_cp)
|
||||||
|
|
||||||
point = _location_to_point(location)
|
rect = _location_to_rect(location)
|
||||||
rect = pygame.Rect(*point, 30, 30)
|
pygame.draw.rect(surface, self.RED, rect)
|
||||||
pygame.draw.rect(surface, self.BLACK, rect)
|
self.surface.blit(self.event_icons[event.__class__], rect.topleft)
|
||||||
|
|
||||||
if rect.collidepoint(*mouse_pos) or self.selected_event_info == (event, point):
|
if rect.collidepoint(*mouse_pos) or self.selected_event_info == (event, rect.center):
|
||||||
line = self.font.render(str(event), self.ANTIALIASING, self.WHITE, self.BLACK)
|
if not label_to_draw:
|
||||||
surface.blit(line, rect.center)
|
label_to_draw = self.font.render(str(event), self.ANTIALIASING, self.WHITE, self.BLACK), rect.center
|
||||||
|
|
||||||
if rect.collidepoint(*mouse_pos):
|
if rect.collidepoint(*mouse_pos):
|
||||||
if mouse_down[0]:
|
if mouse_down[0]:
|
||||||
self.selected_event_info = event, point
|
self.selected_event_info = event, rect.center
|
||||||
mouse_down[0] = False
|
mouse_down[0] = False
|
||||||
|
|
||||||
|
if label_to_draw:
|
||||||
|
surface.blit(*label_to_draw)
|
||||||
|
|
||||||
return mouse_down
|
return mouse_down
|
||||||
|
|
||||||
def _selected_cp(self, cp):
|
def _selected_cp(self, cp):
|
||||||
|
|||||||