33import logging
44from typing import TYPE_CHECKING , Protocol
55
6+ import pygame
7+
68if TYPE_CHECKING :
79 from collections .abc import Iterable
810
@@ -47,7 +49,11 @@ def redraw_all(
4749 buffer_surface : Surface ,
4850 ) -> None : ...
4951
50- def clear_region (self , surface : Surface , area : RectLike | None = None ) -> None : ...
52+ def clear_region (
53+ self ,
54+ surface : Surface ,
55+ area : RectLike | None = None ,
56+ ) -> None : ...
5157
5258
5359class TileRenderer (TileRendererProtocol ):
@@ -58,7 +64,6 @@ def __init__(
5864 alpha : bool = False ,
5965 ):
6066 self .data = data
61-
6267 self ._clear_color : ColorRGB | ColorRGBA | None
6368
6469 if colorkey and alpha :
@@ -79,19 +84,19 @@ def clear_color(self) -> ColorRGB | ColorRGBA | None:
7984 return self ._clear_color
8085
8186 def queue_edge_tiles (
82- self , tile_view : Rect , dx : int , dy : int , buffer_surface : Surface
87+ self ,
88+ tile_view : Rect ,
89+ dx : int ,
90+ dy : int ,
91+ buffer_surface : Surface ,
8392 ) -> list [tuple [int , int , int , Surface ]]:
84- # Early exit: no movement
8593 if dx == 0 and dy == 0 :
8694 return []
8795
8896 tw , th = self .data .tile_size
89- v_left = tile_view .left
90- v_top = tile_view .top
91- v_right = tile_view .right
92- v_bottom = tile_view .bottom
93- v_width = tile_view .width
94- v_height = tile_view .height
97+ v_left , v_top = tile_view .left , tile_view .top
98+ v_right , v_bottom = tile_view .right , tile_view .bottom
99+ v_width , v_height = tile_view .width , tile_view .height
95100
96101 get_images = self .data .get_tile_images_by_rect
97102 clear_region = self .clear_region
@@ -103,42 +108,35 @@ def queue_edge_tiles(
103108 rect = (v_right - 1 , v_top , dx , v_height )
104109 queue .extend (get_images (rect ))
105110 if buffer_surface is not None :
106- px = (rect [0 ] - v_left ) * tw
107- py = 0
108- pw = rect [2 ] * tw
109- ph = v_height * th
110- clear_region (buffer_surface , (px , py , pw , ph ))
111+ clear_region (
112+ buffer_surface ,
113+ ((rect [0 ] - v_left ) * tw , 0 , rect [2 ] * tw , v_height * th ),
114+ )
111115
112116 elif dx < 0 :
113117 rect = (v_left , v_top , - dx , v_height )
114118 queue .extend (get_images (rect ))
115119 if buffer_surface is not None :
116- px = 0
117- py = 0
118- pw = rect [2 ] * tw
119- ph = v_height * th
120- clear_region (buffer_surface , (px , py , pw , ph ))
120+ clear_region (buffer_surface , (0 , 0 , rect [2 ] * tw , v_height * th ))
121121
122122 # Vertical movement
123123 if dy > 0 :
124- rect = (v_left , v_bottom - 1 , v_width , dy )
124+ rect = (v_left , v_bottom - 1 , v_width , 1 )
125125 queue .extend (get_images (rect ))
126126 if buffer_surface is not None :
127- px = 0
128- py = (rect [1 ] - v_top ) * th
129- pw = v_width * tw
130- ph = rect [3 ] * th
131- clear_region (buffer_surface , (px , py , pw , ph ))
127+ clear_region (
128+ buffer_surface ,
129+ (0 , (rect [1 ] - v_top ) * th , v_width * tw , rect [3 ] * th ),
130+ )
132131
133132 elif dy < 0 :
134- rect = (v_left , v_top , v_width , - dy )
133+ rect = (v_left , v_top , v_width , 1 )
135134 queue .extend (get_images (rect ))
136135 if buffer_surface is not None :
137- px = 0
138- py = 0
139- pw = v_width * tw
140- ph = rect [3 ] * th
141- clear_region (buffer_surface , (px , py , pw , ph ))
136+ clear_region (
137+ buffer_surface ,
138+ (0 , 0 , v_width * tw , rect [3 ] * th ),
139+ )
142140
143141 return queue
144142
@@ -154,23 +152,33 @@ def flush_tile_queue(
154152
155153 self .data .prepare_tiles (tile_view )
156154
157- # Precompute generator outside the C call
158- blit_items = (
155+ blit_items = [
159156 (image , (x * tw - ltw , y * th - tth )) for x , y , layer , image in tile_queue
160- )
157+ ]
161158
162159 buffer_surface .blits (blit_items , doreturn = False )
163160
164- def redraw_all (self , tile_view : Rect , buffer_surface : Surface ) -> None :
161+ def redraw_all (
162+ self ,
163+ tile_view : Rect ,
164+ buffer_surface : Surface ,
165+ ) -> None :
165166 tile_queue = self .data .get_tile_images_by_rect (tile_view )
166167 self .flush_tile_queue (tile_queue , tile_view , buffer_surface )
167168
168- def clear_region (self , surface : Surface , area : RectLike | None = None ) -> None :
169+ def clear_region (
170+ self ,
171+ surface : Surface ,
172+ area : RectLike | None = None ,
173+ ) -> None :
169174 if self ._clear_color is not None :
170175 clear_color = self ._clear_color
171176 else :
172- has_alpha = surface .get_masks ()[3 ] != 0
173- clear_color = self ._rgba_clear_color if has_alpha else self ._rgb_clear_color
177+ clear_color = (
178+ self ._rgba_clear_color
179+ if (surface .get_flags () & pygame .SRCALPHA )
180+ else self ._rgb_clear_color
181+ )
174182
175183 surface .fill (clear_color , area )
176184
@@ -184,13 +192,11 @@ def __init__(
184192 ):
185193 self .data = data
186194
187- self ._clear_color : ColorRGB | ColorRGBA | None
188-
189195 if colorkey and alpha :
190196 raise ValueError ("cannot select both colorkey and alpha" )
191197
192198 if colorkey :
193- self ._clear_color = colorkey
199+ self ._clear_color : ColorRGB | ColorRGBA | None = colorkey
194200 elif alpha :
195201 self ._clear_color = (0 , 0 , 0 , 0 )
196202 else :
@@ -201,7 +207,11 @@ def clear_color(self) -> ColorRGB | ColorRGBA | None:
201207 return self ._clear_color
202208
203209 def queue_edge_tiles (
204- self , tile_view : Rect , dx : int , dy : int , buffer_surface : Surface
210+ self ,
211+ tile_view : Rect ,
212+ dx : int ,
213+ dy : int ,
214+ buffer_surface : Surface ,
205215 ) -> list [tuple [int , int , int , Surface ]]:
206216 return []
207217
@@ -213,31 +223,45 @@ def flush_tile_queue(
213223 ) -> None :
214224 return
215225
216- def redraw_all (self , tile_view : Rect , buffer_surface : Surface ) -> None :
226+ def redraw_all (
227+ self ,
228+ tile_view : Rect ,
229+ buffer_surface : Surface ,
230+ ) -> None :
217231 if self ._clear_color is not None :
218232 buffer_surface .fill (self ._clear_color )
219233
220234 tw , th = self .data .tile_size
221235 twh = tw // 2
222236 thh = th // 2
223237
224- blit = buffer_surface .blit
238+ visible_layers = self .data .visible_tile_layers
239+ get_tile_image = self .data .get_tile_image
240+
241+ blit_items : list [tuple [Surface , tuple [int , int ]]] = []
225242
226243 for x in range (tile_view .left , tile_view .right ):
244+ lx = x - tile_view .left
227245 for y in range (tile_view .top , tile_view .bottom ):
228- lx = x - tile_view .left
229246 ly = y - tile_view .top
230247
231248 iso_x = (lx - ly ) * twh
232249 iso_y = (lx + ly ) * thh
233250
234- for layer in self . data . visible_tile_layers :
235- tile = self . data . get_tile_image (x , y , layer )
251+ for layer in visible_layers :
252+ tile = get_tile_image (x , y , layer )
236253 if tile :
237- blit ( tile , (iso_x , iso_y ))
254+ blit_items . append (( tile , (iso_x , iso_y ) ))
238255
239- def clear_region (self , surface : Surface , area : RectLike | None = None ) -> None :
256+ if blit_items :
257+ buffer_surface .blits (blit_items , doreturn = False )
258+
259+ def clear_region (
260+ self ,
261+ surface : Surface ,
262+ area : RectLike | None = None ,
263+ ) -> None :
240264 clear_color = (
241265 self ._clear_color if self ._clear_color is not None else (0 , 0 , 0 , 0 )
242266 )
243- surface .fill (clear_color )
267+ surface .fill (clear_color , area )
0 commit comments