Shape List - Skylines

shape_list_demo_skylines.py
1"""
2City Scape Generator
3
4If Python and Arcade are installed, this example can be run from the command line with:
5python -m arcade.examples.shape_list_demo_skylines
6"""
7import random
8import arcade
9from arcade.shape_list import (
10 ShapeElementList,
11 create_rectangle_filled,
12 create_polygon,
13 create_rectangles_filled_with_colors,
14)
15
16WINDOW_WIDTH = 1200
17WINDOW_HEIGHT = 600
18WINDOW_TITLE = "Skyline Using Buffered Shapes"
19
20
21def make_star_field(star_count):
22 """Make a bunch of circles for stars"""
23 shape_list = ShapeElementList()
24
25 for _ in range(star_count):
26 x = random.randrange(WINDOW_WIDTH)
27 y = random.randrange(WINDOW_HEIGHT)
28 radius = random.randrange(1, 4)
29 brightness = random.randrange(127, 256)
30 color = (brightness, brightness, brightness)
31 shape = create_rectangle_filled(x, y, radius, radius, color)
32 shape_list.append(shape)
33
34 return shape_list
35
36
37def make_skyline(width, skyline_height, skyline_color,
38 gap_chance=0.70, window_chance=0.30, light_on_chance=0.5,
39 window_color=(255, 255, 200), window_margin=3, window_gap=2,
40 cap_chance=0.20):
41 """Make a skyline of buildings"""
42 shape_list = ShapeElementList()
43
44 # Add the "base" that we build the buildings on
45 shape = create_rectangle_filled(
46 center_x=width / 2,
47 center_y=skyline_height / 2,
48 width=width,
49 height=skyline_height,
50 color=skyline_color,
51 )
52 shape_list.append(shape)
53
54 building_center_x = 0
55
56 skyline_point_list = []
57 color_list = []
58
59 while building_center_x < width:
60
61 # Is there a gap between the buildings?
62 if random.random() < gap_chance:
63 gap_width = random.randrange(10, 50)
64 else:
65 gap_width = 0
66
67 # Figure out location and size of building
68 building_width = random.randrange(20, 70)
69 building_height = random.randrange(40, 150)
70 building_center_x += gap_width + (building_width / 2)
71 building_center_y = skyline_height + (building_height / 2)
72
73 x1 = building_center_x - building_width / 2
74 x2 = building_center_x + building_width / 2
75 y1 = skyline_height
76 y2 = skyline_height + building_height
77
78 skyline_point_list.append([x1, y1])
79 skyline_point_list.append([x1, y2])
80 skyline_point_list.append([x2, y2])
81 skyline_point_list.append([x2, y1])
82
83 for i in range(4):
84 color_list.append([skyline_color[0], skyline_color[1], skyline_color[2]])
85
86 if random.random() < cap_chance:
87 x1 = building_center_x - building_width / 2
88 x2 = building_center_x + building_width / 2
89 x3 = building_center_x
90
91 y1 = y2 = building_center_y + building_height / 2
92 y3 = y1 + building_width / 2
93
94 # Roof
95 shape = create_polygon([[x1, y1], [x2, y2], [x3, y3]], skyline_color)
96 shape_list.append(shape)
97
98 # See if we should have some windows
99 if random.random() < window_chance:
100 # Yes windows! How many windows?
101 window_rows = random.randrange(10, 15)
102 window_columns = random.randrange(1, 7)
103
104 # Based on that, how big should they be?
105 window_height = (building_height - window_margin * 2) / window_rows
106 window_width = (
107 (building_width - window_margin * 2 - window_gap * (window_columns - 1))
108 / window_columns
109 )
110
111 # Find the bottom left of the building so we can start adding widows
112 building_base_y = building_center_y - building_height / 2
113 building_left_x = building_center_x - building_width / 2
114
115 # Loop through each window
116 for row in range(window_rows):
117 for column in range(window_columns):
118 if random.random() > light_on_chance:
119 continue
120
121 x1 = (
122 building_left_x
123 + column * (window_width + window_gap)
124 + window_margin
125 )
126 x2 = (
127 building_left_x
128 + column * (window_width + window_gap)
129 + window_width
130 + window_margin
131 )
132 y1 = building_base_y + row * window_height
133 y2 = building_base_y + row * window_height + window_height * .8
134
135 skyline_point_list.append([x1, y1])
136 skyline_point_list.append([x1, y2])
137 skyline_point_list.append([x2, y2])
138 skyline_point_list.append([x2, y1])
139
140 for i in range(4):
141 color_list.append((
142 window_color[0],
143 window_color[1],
144 window_color[2],
145 ))
146
147 building_center_x += (building_width / 2)
148
149 shape = create_rectangles_filled_with_colors(skyline_point_list, color_list)
150 shape_list.append(shape)
151
152 return shape_list
153
154
155class GameView(arcade.View):
156 """ Main application class. """
157
158 def __init__(self):
159 """ Initializer """
160 # Call the parent class initializer
161 super().__init__()
162 # Enable vertical sync to make scrolling smoother
163 self.window.set_vsync(True)
164
165 self.stars = make_star_field(150)
166 self.skyline1 = make_skyline(WINDOW_WIDTH * 5, 250, (80, 80, 80))
167 self.skyline2 = make_skyline(WINDOW_WIDTH * 5, 150, (50, 50, 50))
168
169 self.background_color = arcade.color.BLACK
170
171 def on_draw(self):
172 """Draw to screen"""
173 self.clear()
174
175 self.stars.draw()
176 self.skyline1.draw()
177 self.skyline2.draw()
178
179 def on_update(self, delta_time):
180 """Per frame update logic"""
181 # Scroll each shape list with a slight offset to give a parallax effect
182 self.skyline1.center_x -= 0.5 * 60 * delta_time
183 self.skyline2.center_x -= 1 * 60 * delta_time
184
185 def on_mouse_drag(self, x: int, y: int, dx: int, dy: int, buttons: int, modifiers: int):
186 """Make it possible scroll the scene around by dragging the mouse"""
187 self.skyline1.center_x += dx
188 self.skyline1.center_y += dy
189
190 self.skyline2.center_x += dx
191 self.skyline2.center_y += dy
192
193
194def main():
195 """ Main function """
196 # Create a window class. This is what actually shows up on screen
197 window = arcade.Window(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE)
198
199 # Create the GameView
200 game = GameView()
201
202 # Show GameView on screen
203 window.show_view(game)
204
205 # Start the arcade game loop
206 arcade.run()
207
208
209if __name__ == "__main__":
210 main()