Shape List - Skylines

Screenshot of using shape list to create a moving skyline
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_skylines
  6"""
  7import random
  8import arcade
  9import time
 10
 11SCREEN_WIDTH = 1200
 12SCREEN_HEIGHT = 600
 13SCREEN_TITLE = "Skyline Using Buffered Shapes"
 14
 15
 16def make_star_field(star_count):
 17    """ Make a bunch of circles for stars. """
 18
 19    shape_list = arcade.ShapeElementList()
 20
 21    for star_no in range(star_count):
 22        x = random.randrange(SCREEN_WIDTH)
 23        y = random.randrange(SCREEN_HEIGHT)
 24        radius = random.randrange(1, 4)
 25        brightness = random.randrange(127, 256)
 26        color = (brightness, brightness, brightness)
 27        shape = arcade.create_rectangle_filled(x, y, radius, radius, color)
 28        shape_list.append(shape)
 29
 30    return shape_list
 31
 32
 33def make_skyline(width, skyline_height, skyline_color,
 34                 gap_chance=0.70, window_chance=0.30, light_on_chance=0.5,
 35                 window_color=(255, 255, 200), window_margin=3, window_gap=2,
 36                 cap_chance=0.20):
 37    """ Make a skyline """
 38
 39    shape_list = arcade.ShapeElementList()
 40
 41    # Add the "base" that we build the buildings on
 42    shape = arcade.create_rectangle_filled(width / 2, skyline_height / 2, width, skyline_height, skyline_color)
 43    shape_list.append(shape)
 44
 45    building_center_x = 0
 46
 47    skyline_point_list = []
 48    color_list = []
 49
 50    while building_center_x < width:
 51
 52        # Is there a gap between the buildings?
 53        if random.random() < gap_chance:
 54            gap_width = random.randrange(10, 50)
 55        else:
 56            gap_width = 0
 57
 58        # Figure out location and size of building
 59        building_width = random.randrange(20, 70)
 60        building_height = random.randrange(40, 150)
 61        building_center_x += gap_width + (building_width / 2)
 62        building_center_y = skyline_height + (building_height / 2)
 63
 64        x1 = building_center_x - building_width / 2
 65        x2 = building_center_x + building_width / 2
 66        y1 = skyline_height
 67        y2 = skyline_height + building_height
 68
 69        skyline_point_list.append([x1, y1])
 70
 71        skyline_point_list.append([x1, y2])
 72
 73        skyline_point_list.append([x2, y2])
 74
 75        skyline_point_list.append([x2, y1])
 76
 77        for i in range(4):
 78            color_list.append([skyline_color[0], skyline_color[1], skyline_color[2]])
 79
 80        if random.random() < cap_chance:
 81            x1 = building_center_x - building_width / 2
 82            x2 = building_center_x + building_width / 2
 83            x3 = building_center_x
 84
 85            y1 = y2 = building_center_y + building_height / 2
 86            y3 = y1 + building_width / 2
 87
 88            shape = arcade.create_polygon([[x1, y1], [x2, y2], [x3, y3]], skyline_color)
 89            shape_list.append(shape)
 90
 91        # See if we should have some windows
 92        if random.random() < window_chance:
 93            # Yes windows! How many windows?
 94            window_rows = random.randrange(10, 15)
 95            window_columns = random.randrange(1, 7)
 96
 97            # Based on that, how big should they be?
 98            window_height = (building_height - window_margin * 2) / window_rows
 99            window_width = (building_width - window_margin * 2 - window_gap * (window_columns - 1)) / window_columns
100
101            # Find the bottom left of the building so we can start adding widows
102            building_base_y = building_center_y - building_height / 2
103            building_left_x = building_center_x - building_width / 2
104
105            # Loop through each window
106            for row in range(window_rows):
107                for column in range(window_columns):
108                    if random.random() < light_on_chance:
109                        x1 = building_left_x + column * (window_width + window_gap) + window_margin
110                        x2 = building_left_x + column * (window_width + window_gap) + window_width + window_margin
111                        y1 = building_base_y + row * window_height
112                        y2 = building_base_y + row * window_height + window_height * .8
113
114                        skyline_point_list.append([x1, y1])
115                        skyline_point_list.append([x1, y2])
116                        skyline_point_list.append([x2, y2])
117                        skyline_point_list.append([x2, y1])
118
119                        for i in range(4):
120                            color_list.append((window_color[0], window_color[1], window_color[2]))
121
122        building_center_x += (building_width / 2)
123
124    shape = arcade.create_rectangles_filled_with_colors(skyline_point_list, color_list)
125    shape_list.append(shape)
126
127    return shape_list
128
129
130class MyGame(arcade.Window):
131    """ Main application class. """
132
133    def __init__(self):
134        """ Initializer """
135        # Call the parent class initializer
136        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE)
137
138        self.stars = make_star_field(150)
139        self.skyline1 = make_skyline(SCREEN_WIDTH * 5, 250, (80, 80, 80))
140        self.skyline2 = make_skyline(SCREEN_WIDTH * 5, 150, (50, 50, 50))
141
142        arcade.set_background_color(arcade.color.BLACK)
143
144    def setup(self):
145        """ Set up the game and initialize the variables. """
146
147    def on_draw(self):
148        """
149        Render the screen.
150        """
151
152        # This command has to happen before we start drawing
153
154        start_time = int(round(time.time() * 1000))
155        arcade.start_render()
156
157        self.stars.draw()
158        self.skyline1.draw()
159        self.skyline2.draw()
160        end_time = int(round(time.time() * 1000))
161        total_time = end_time - start_time
162
163        arcade.draw_text(f"Time: {total_time}", 10, 10, arcade.color.WHITE)
164
165    def on_update(self, delta_time):
166        """ Movement and game logic """
167        self.skyline1.center_x -= 0.5
168        self.skyline2.center_x -= 1
169
170
171def main():
172    window = MyGame()
173    window.setup()
174    arcade.run()
175
176
177if __name__ == "__main__":
178    main()