Coverage for src/gncpy/game_engine/rendering2d.py: 0%

58 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-13 06:15 +0000

1"""Handles low level calls to 2D graphics libraries.""" 

2import os 

3import numpy as np 

4from sys import exit 

5from warnings import warn 

6 

7os.environ["PYGAME_HIDE_SUPPORT_PROMPT"] = "hide" 

8import pygame # noqa 

9 

10import gncpy.game_engine.components as gcomp # noqa 

11 

12 

13class Shape2dParams: 

14 """Parameters of a 2d shape object. 

15 

16 The types defined in this class determine what type the parser uses. 

17 

18 Attributes 

19 ---------- 

20 type : string 

21 Pygame object type to create, see :class:`.components.CShape` for options. 

22 width : int 

23 Width in real units of the shape. 

24 height : int 

25 Height in real units of the shape. 

26 color : tuple 

27 RGB triplet of the shape, in range [0, 255]. 

28 file : string 

29 Full file path to image if needed. 

30 """ 

31 

32 def __init__(self): 

33 super().__init__() 

34 self.type = "" 

35 self.width = 0 

36 self.height = 0 

37 self.color = () 

38 self.file = "" 

39 

40 

41def init_rendering_system(): 

42 """Initialize the rendering system. 

43 

44 Returns 

45 ------- 

46 pygame clock 

47 pygame clock instance 

48 """ 

49 pygame.init() 

50 clock = pygame.time.Clock() 

51 

52 return clock 

53 

54 

55def init_window(render_mode, width, height): 

56 """Initialize the main window. 

57 

58 Parameters 

59 ---------- 

60 render_mode : string 

61 Render mode to use, if :code:`'human'` is given then the window will be 

62 shown. All other values are ignored. 

63 width : int 

64 Window width in pixels. 

65 height : int 

66 Window height in pixels. 

67 

68 Returns 

69 ------- 

70 window : pygame window 

71 Main window object for drawing. 

72 """ 

73 extra = {} 

74 if render_mode != "human": 

75 extra["flags"] = pygame.HIDDEN 

76 

77 window = pygame.display.set_mode((int(width), int(height)), **extra) 

78 return window 

79 

80 

81def get_drawable_entities(entities): 

82 """Get all the drawable entities. 

83 

84 Parameters 

85 ---------- 

86 entities : list 

87 List of all entities from the :class:`.entities.EntityManager` class. 

88 

89 Returns 

90 ------- 

91 list 

92 list of all entities that can be drawn. 

93 """ 

94 

95 def _can_draw(_e): 

96 return ( 

97 _e.active 

98 and _e.has_component(gcomp.CShape) 

99 and _e.has_component(gcomp.CTransform) 

100 ) 

101 

102 drawable = list(filter(_can_draw, entities)) 

103 drawable.sort(key=lambda _e: _e.get_component(gcomp.CShape).zorder) 

104 

105 return drawable 

106 

107 

108def render(drawable, window, clock, mode, fps): 

109 """Draw all entities to the window. 

110 

111 Parameters 

112 ---------- 

113 drawable : list 

114 List of drawable entities. 

115 window : pygame window 

116 Window to draw to. 

117 clock : pygame clock 

118 main clock for the game. 

119 mode : string 

120 Rendering mode, if :code:`'human'` then the screen is updated and events 

121 are checked for the close button. 

122 fps : int 

123 Frame rate to render at. 

124 

125 Returns 

126 ------- 

127 numpy array 

128 pixel values of the window in HxWx3 order. 

129 """ 

130 window.fill((255, 255, 255)) 

131 offset = window.get_size()[1] 

132 for e in drawable: 

133 e_shape = e.get_component(gcomp.CShape) 

134 e_trans = e.get_component(gcomp.CTransform) 

135 

136 if np.any(np.isnan(e_trans.pos)) or np.any(np.isinf(e_trans.pos)): 

137 continue 

138 

139 # flip in the vertical direction 

140 c_pos = (e_trans.pos[0].item(), offset - e_trans.pos[1].item()) 

141 # e_shape.shape.centerx = e_trans.pos[0].item() 

142 # # flip in the vertical direction 

143 # e_shape.shape.centery = offset - e_trans.pos[1].item() 

144 

145 if e_shape.type == "rect": 

146 e_shape.shape.centerx = c_pos[0] 

147 e_shape.shape.centery = c_pos[1] 

148 pygame.draw.rect(window, e_shape.color, e_shape.shape) 

149 

150 elif e_shape.type == "sprite": 

151 window.blit(e_shape.shape, e_shape.shape.get_rect(center=c_pos)) 

152 

153 else: 

154 warn("No rendering method for this shape") 

155 

156 if mode == "human": 

157 for event in pygame.event.get(): 

158 if event.type == pygame.QUIT: 

159 shutdown(window) 

160 exit() 

161 clock.tick(fps) 

162 pygame.display.update() 

163 

164 return np.transpose( 

165 np.array(pygame.surfarray.pixels3d(window), dtype=np.uint8), axes=(1, 0, 2) 

166 ) 

167 

168 

169def shutdown(window): 

170 """Nicely close pygame if window was initialized. 

171 

172 Parameters 

173 ---------- 

174 window : pygame window 

175 Main window object. 

176 """ 

177 if window is not None: 

178 pygame.quit()