draw scores once and set clip
This commit is contained in:
parent
e0b4ed0251
commit
3deb552325
188
NS.py
188
NS.py
|
@ -102,7 +102,7 @@ class NS(Game, Animation):
|
|||
|
||||
def formatted(self):
|
||||
if self.milliseconds is None:
|
||||
return "--:--.-"
|
||||
return "-:--.-"
|
||||
else:
|
||||
minutes, remainder = divmod(int(self.milliseconds), 60000)
|
||||
seconds, fraction = divmod(remainder, 1000)
|
||||
|
@ -194,7 +194,8 @@ class NS(Game, Animation):
|
|||
"display":
|
||||
{
|
||||
"float": "attract-gif-alpha",
|
||||
"bool": ["effects", "alpha-effect-title"]
|
||||
"bool": ["effects", "alpha-effect-title"],
|
||||
"path": "scores-font"
|
||||
},
|
||||
"system":
|
||||
{
|
||||
|
@ -305,13 +306,12 @@ class NS(Game, Animation):
|
|||
self.register(self.close_pop_up)
|
||||
self.reset()
|
||||
self.most_recent_score = None
|
||||
self.pop_up_font = pygame.font.Font(
|
||||
self.get_resource(Dialogue.FONT_PATH), 12)
|
||||
self.pop_up_font = pygame.font.Font(self.get_resource(Dialogue.FONT_PATH), 12)
|
||||
self.pop_up_text = ""
|
||||
|
||||
# Start the score list with all blank scores
|
||||
self.scores = []
|
||||
blank_count = 14
|
||||
blank_count = 25
|
||||
for level_index in range(3):
|
||||
for _ in range(blank_count):
|
||||
self.scores.append(NS.Score.blank_level(level_index))
|
||||
|
@ -1066,13 +1066,18 @@ class Title(Animation):
|
|||
@param parent GameChild object that will connect this GameChild object to the overall tree and root Game object
|
||||
"""
|
||||
Animation.__init__(self, parent)
|
||||
ds = self.get_display_surface()
|
||||
dsr = ds.get_rect()
|
||||
|
||||
# Set up attract mode pop-up
|
||||
self.angle = pi / 8
|
||||
self.video = Video(self, 320)
|
||||
self.video.location.center = 329, 182
|
||||
self.register(self.show_video, self.hide_video)
|
||||
self.show_video()
|
||||
|
||||
# Set up scores
|
||||
font_path = self.get_resource(self.get_configuration("display", "scores-font"))
|
||||
self.heading_font = pygame.font.Font(font_path, 22)
|
||||
self.score_font = pygame.font.Font(font_path, 16)
|
||||
self.score_sprites = []
|
||||
|
||||
def reset(self):
|
||||
|
@ -1112,57 +1117,117 @@ class Title(Animation):
|
|||
else:
|
||||
self.get_game().level_select.launch(0)
|
||||
|
||||
def draw_score_to_column(self, score, column, screen_pos, rank):
|
||||
"""
|
||||
Blit `score` onto `column`, taking positioning and rank into account
|
||||
|
||||
@param score Score to display in top scores
|
||||
@param column Surface for displaying score
|
||||
@param screen_pos absolute screen (x, y) of score topleft
|
||||
@param rank rank of score
|
||||
@return height of the drawn score
|
||||
"""
|
||||
# Parse both strings and score objects
|
||||
if isinstance(score, NS.Score):
|
||||
text = score.formatted()
|
||||
else:
|
||||
text = score
|
||||
|
||||
# The background is based on rank
|
||||
if rank == 0:
|
||||
bg = 255, 215, 0
|
||||
elif rank == 1:
|
||||
bg = 192, 192, 192
|
||||
elif rank == 2:
|
||||
bg = 205, 127, 50
|
||||
else:
|
||||
bg = 255, 255, 255
|
||||
|
||||
# Draw the score
|
||||
score_surface = render_box(self.score_font, text, width=column.get_width(), background=bg)
|
||||
column.blit(score_surface, (0, screen_pos[1]))
|
||||
|
||||
# Create a blink effect for the most recent score
|
||||
if score == self.get_game().most_recent_score:
|
||||
self.score_blanker = BlinkingSprite(self, 500)
|
||||
blank = pygame.surface.Surface(score_surface.get_size())
|
||||
blank.fill(bg)
|
||||
self.score_blanker.add_frame(blank)
|
||||
self.score_blanker.location = screen_pos
|
||||
|
||||
# The height is used to move the draw location
|
||||
return score_surface.get_height()
|
||||
|
||||
def draw_heading_to_column(self, text, column, y):
|
||||
"""
|
||||
Blit `text` on `column` in the heading style
|
||||
|
||||
@param text heading text to blit
|
||||
@param column Surface where heading will be blit
|
||||
@param y top position of text
|
||||
@return height of drawn heading
|
||||
"""
|
||||
heading = render_box(self.heading_font, text, color=(255, 255, 255), background=(0, 0, 0), width=column.get_width())
|
||||
column.blit(heading, (0, y))
|
||||
return heading.get_height()
|
||||
|
||||
def draw_scores(self):
|
||||
"""
|
||||
Draw frames for a sprite object for each score and store the sprite in a list to be drawn each frame.
|
||||
Create two columns, one for each side of the screen. Draw as many scores as can fit along each column, in order from best to worst, separating
|
||||
them evenly into categories: normal, advanced, and expert. Draw the two columns to the display surface, with the expectation that they will be
|
||||
removed from the clip and will not be drawn over. Note that this doesn't support non-level select mode anymore.
|
||||
"""
|
||||
# Create a list of strings in order of which to draw
|
||||
if not self.get_configuration("system", "enable-level-select"):
|
||||
entries = ["BEST"] + sorted([score for score in self.get_game().scores if score.is_full()])[:15]
|
||||
else:
|
||||
entries = ["NORMAL"] + sorted([score for score in self.get_game().scores if score.level_index == 0])[:3] + \
|
||||
["ADVANCED"] + sorted([score for score in self.get_game().scores if score.level_index == 1])[:3] + \
|
||||
["EXPERT"] + sorted([score for score in self.get_game().scores if score.level_index == 2])[:7]
|
||||
|
||||
# Create a sprite object for each score and place on the screen in two columns on the left and right edges the screen
|
||||
step = 56
|
||||
ds = self.get_display_surface()
|
||||
self.score_sprites = []
|
||||
for ii, entry in enumerate(entries):
|
||||
|
||||
# Reset y counter
|
||||
if ii == 0 or ii == 8:
|
||||
y = 20
|
||||
|
||||
font = pygame.font.Font(self.get_resource(Dialogue.FONT_PATH), 18)
|
||||
|
||||
# Parse both strings and score objects
|
||||
if isinstance(entry, NS.Score):
|
||||
text = entry.formatted()
|
||||
self.score_blanker = None
|
||||
heading_width, heading_height = self.heading_font.size("ADVANCED")
|
||||
heading_width += 10
|
||||
score_height = self.score_font.size("0")[1]
|
||||
column_width, column_height = heading_width, ds.get_height()
|
||||
left_score_count = (column_height - heading_height * 2) // score_height
|
||||
right_score_count = (column_height - heading_height) // score_height
|
||||
total_score_count = left_score_count + right_score_count
|
||||
per_category_count, remainder = divmod(total_score_count, 3)
|
||||
left_column_sprite = Sprite(self)
|
||||
left_column = pygame.surface.Surface((column_width, column_height))
|
||||
left_column.fill((255, 255, 255))
|
||||
x, y = 0, 0
|
||||
y += self.draw_heading_to_column("NORMAL", left_column, y)
|
||||
count = per_category_count
|
||||
if remainder:
|
||||
count += 1
|
||||
remainder -= 1
|
||||
for rank, score in enumerate(sorted([score for score in self.get_game().scores if score.level_index == 0])[:count]):
|
||||
y += self.draw_score_to_column(score, left_column, (x, y), rank)
|
||||
left_score_count -= 1
|
||||
y += self.draw_heading_to_column("ADVANCED", left_column, y)
|
||||
count = per_category_count
|
||||
if remainder:
|
||||
count += 1
|
||||
remainder -= 1
|
||||
right_column_sprite = Sprite(self)
|
||||
right_column = pygame.surface.Surface((column_width, column_height))
|
||||
right_column.fill((255, 255, 255))
|
||||
column = left_column
|
||||
for rank, score in enumerate(sorted([score for score in self.get_game().scores if score.level_index == 1])[:count]):
|
||||
y += self.draw_score_to_column(score, column, (x, y), rank)
|
||||
if left_score_count == 1:
|
||||
y = 0
|
||||
x = ds.get_width() - column_width
|
||||
column = right_column
|
||||
left_column_sprite.add_frame(left_column)
|
||||
if left_score_count == 0:
|
||||
right_score_count -= 1
|
||||
else:
|
||||
text = entry
|
||||
|
||||
# Create a surface as a box around the score
|
||||
message = render_box(font, text, True, Color(255, 255, 255), Color(128, 128, 128), Color(0, 0, 0), padding=2)
|
||||
message.set_alpha(230)
|
||||
|
||||
# Store it in a sprite, use a blinking sprite for the most recent score
|
||||
if not entry == self.get_game().most_recent_score:
|
||||
sprite = Sprite(self)
|
||||
else:
|
||||
sprite = BlinkingSprite(self, 500)
|
||||
sprite.add_frame(message)
|
||||
self.score_sprites.append(sprite)
|
||||
|
||||
# Place the sprite along the column
|
||||
sprite.location.top = y
|
||||
if ii < 8:
|
||||
sprite.location.left = -1
|
||||
else:
|
||||
sprite.location.right = ds.get_width() + 1
|
||||
|
||||
# Move to the next sprite location
|
||||
y += step
|
||||
left_score_count -= 1
|
||||
y += self.draw_heading_to_column("EXPERT", right_column, y)
|
||||
count = per_category_count
|
||||
for rank, score in enumerate(sorted([score for score in self.get_game().scores if score.level_index == 2])[:count]):
|
||||
y += self.draw_score_to_column(score, right_column, (x, y), rank)
|
||||
right_column_sprite.add_frame(right_column)
|
||||
right_column_sprite.location.topleft = x, 0
|
||||
self.score_sprites = [left_column_sprite, right_column_sprite]
|
||||
for sprite in self.score_sprites:
|
||||
sprite.update()
|
||||
|
||||
def show_video(self):
|
||||
self.video.unhide()
|
||||
|
@ -1185,7 +1250,13 @@ class Title(Animation):
|
|||
if self.active:
|
||||
ds = self.get_display_surface()
|
||||
dsr = ds.get_rect()
|
||||
|
||||
# Optimize by setting a clip that excludes the area where the scores are drawn
|
||||
ds.set_clip((self.score_sprites[0].location.right, 0, self.score_sprites[1].location.left - self.score_sprites[0].location.right, dsr.height))
|
||||
|
||||
# Draw the background
|
||||
self.get_game().logo.update()
|
||||
|
||||
# Advance through the unlock pattern
|
||||
platform = self.get_game().platform
|
||||
if not self.get_game().wipe.is_playing() and platform.get_edge_pressed() == self.UNLOCK_MOVES[self.unlock_index]:
|
||||
|
@ -1198,6 +1269,7 @@ class Title(Animation):
|
|||
platform.set_glowing(platform.get_buttons_from_edges([self.UNLOCK_MOVES[self.unlock_index]]))
|
||||
self.get_audio().play_sfx("land_0")
|
||||
self.get_game().tony.update()
|
||||
|
||||
# Bounce the GIF around the screen
|
||||
if self.video.location.right > dsr.right or self.video.location.left < dsr.left:
|
||||
self.angle = reflect_angle(self.angle, 0)
|
||||
|
@ -1213,6 +1285,7 @@ class Title(Animation):
|
|||
self.video.move(dy=dsr.top - self.video.location.top)
|
||||
dx, dy = get_delta(self.angle, 5, False)
|
||||
self.video.move(dx, dy)
|
||||
|
||||
# Hide GIFs/attract mode (or keep them hidden) if input is detected. Set a countdown that will turn
|
||||
# attract mode back on if no input is detected before the countdown expires. As long as input keeps
|
||||
# being detected, this block will keep running and restarting the countdown.
|
||||
|
@ -1221,10 +1294,11 @@ class Title(Animation):
|
|||
self.get_game().tony.set_frameset("static")
|
||||
self.halt()
|
||||
self.play(self.show_video, delay=self.get_configuration("time", "attract-reset-countdown"), play_once=True)
|
||||
# self.video.update()
|
||||
# self.draw_scores()
|
||||
for score in self.score_sprites:
|
||||
score.update()
|
||||
|
||||
# Disable clip and draw blanker which creates a blinking affect for a single score
|
||||
ds.set_clip(None)
|
||||
if self.score_blanker:
|
||||
self.score_blanker.update()
|
||||
|
||||
|
||||
class Dialogue(Animation):
|
||||
|
|
1
config
1
config
|
@ -28,6 +28,7 @@ fullscreen = no
|
|||
attract-gif-alpha = 1.0
|
||||
effects = True
|
||||
alpha-effect-title = False
|
||||
scores-font = BPmono.ttf
|
||||
|
||||
[system]
|
||||
# will force set display->effects to off
|
||||
|
|
2
lib/pgfw
2
lib/pgfw
|
@ -1 +1 @@
|
|||
Subproject commit 0954cd768f6fed46bf77436317271865a888c3a1
|
||||
Subproject commit 314b722528a65e6f0053f8be1844c2d8818319f4
|
Binary file not shown.
|
@ -0,0 +1,94 @@
|
|||
48935 0
|
||||
50940 0
|
||||
51245 0
|
||||
51372 0
|
||||
51754 0
|
||||
52110 0
|
||||
52736 0
|
||||
52863 0
|
||||
53242 0
|
||||
53715 0
|
||||
54546 0
|
||||
54603 0
|
||||
55707 0
|
||||
56045 0
|
||||
56636 0
|
||||
56732 0
|
||||
57247 0
|
||||
57299 0
|
||||
57326 0
|
||||
57436 0
|
||||
57670 0
|
||||
57885 0
|
||||
59459 0
|
||||
60290 0
|
||||
60440 0
|
||||
60510 0
|
||||
60751 0
|
||||
60824 0
|
||||
60957 0
|
||||
61433 0
|
||||
61677 0
|
||||
61838 0
|
||||
62269 0
|
||||
62562 0
|
||||
63416 0
|
||||
64223 0
|
||||
64412 0
|
||||
64534 0
|
||||
64577 0
|
||||
65496 0
|
||||
66051 0
|
||||
66635 0
|
||||
67401 0
|
||||
67523 0
|
||||
68302 0
|
||||
68541 0
|
||||
68948 0
|
||||
69290 0
|
||||
69510 0
|
||||
70404 0
|
||||
70528 0
|
||||
71138 0
|
||||
71335 0
|
||||
71495 0
|
||||
71627 0
|
||||
73511 0
|
||||
73848 0
|
||||
74455 0
|
||||
75015 0
|
||||
75387 0
|
||||
75646 0
|
||||
76002 0
|
||||
76945 0
|
||||
77434 0
|
||||
77526 0
|
||||
77701 0
|
||||
79705 0
|
||||
82020 0
|
||||
82777 0
|
||||
87726 0
|
||||
90718 0
|
||||
91883 0
|
||||
80500 1
|
||||
89673 1
|
||||
93372 1
|
||||
93427 1
|
||||
97111 1
|
||||
105880 1
|
||||
107336 1
|
||||
108024 1
|
||||
109913 1
|
||||
111785 1
|
||||
112993 1
|
||||
113387 1
|
||||
114742 1
|
||||
116102 1
|
||||
117369 1
|
||||
117614 1
|
||||
117744 1
|
||||
119812 1
|
||||
120058 1
|
||||
120493 1
|
||||
85743 2
|
||||
103819 2
|
Loading…
Reference in New Issue