def next_level_loop(): while True: yield from listen.event("next_level") globs.play_disabled = True yield from listen.wait(0.1) if globs.level_idx + 1 < len(globs.levels): globs.selected_color = 0 globs.level_idx += 1 print("Loading level", globs.level_idx + 1, "of", len(globs.levels)) polys = globs.levels[globs.level_idx]() idxs = list(range(len(polys))) np.random.shuffle(idxs) globs.polygons = [] for i in idxs: yield from listen.wait(2 / len(polys)) globs.polygons.append(polys[i]) globs.polygons = polys # to reset the order globs.play_disabled = False listen.dispatch("update_hud") else: globs.level_idx = -1 listen.dispatch("ending_screen")
def camera_move_loop(): while True: _, dt = yield from listen.event("on_frame") if globs.mode != "play": continue if globs.cam["pos"] == globs.cam["target_pos"]: continue distance = 5 * dt delta = globs.cam["target_pos"] - globs.cam["pos"] length = np.sqrt(dot(delta, delta)) if length < distance: globs.cam["pos"] -= globs.cam["pos"] globs.cam["pos"] += globs.cam["target_pos"] else: globs.cam["pos"] += delta * distance / length
def reset_level_loop(): while True: yield from listen.event("reset_level") globs.play_disabled = True polys = globs.levels[globs.level_idx]() idxs = list(range(len(polys))) np.random.shuffle(idxs) for i in idxs: if globs.polygons[i].color != polys[i].color: yield from listen.wait(2 / len(polys)) globs.polygons[i].color = polys[i].color globs.selected_color = 0 listen.dispatch("update_hud") globs.play_disabled = False
def render_loop(): # Need depth testing for z order glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) # Need blending for text rendering glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) while True: yield from listen.event("on_render") # blue background glClearColor(0.16,0.67,1.0,1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) # Load the quadshader. Load the projection uniform with the camera position. glUseProgram(QuadArray.quadshader) proj = globs.cam["projection"] @ translate(globs.cam["pos"].xy0) # translation based on world position of camera set_uniform_matrix(QuadArray.quadshader, "projection", proj) # draw world for quadarray in globs.quadarrays: quadarray.draw() # HUD setup for drawing HUDproj = globs.cam["projection"] set_uniform_matrix(QuadArray.quadshader, "projection", HUDproj) # draw HUD for quadarray in globs.hud_quadarrays: quadarray.draw() # Load the textbox shader. Text is in pixels, not units, # so need to scale appropriately. Ignore camera position. glUseProgram(TextBox.textshader) s = globs.cam["pixels_per_unit"]*globs.cam["pixel_scale"] tproj = globs.cam["projection"] @ scale(1/s,1/s,1) set_uniform_matrix(TextBox.textshader, "projection", tproj) for textbox in globs.textboxes: textbox.draw() glfw.swap_buffers(globs.window)
def update_hud(): while True: yield from listen.event("update_hud") textbox = TextBox( font_loc + "carbon_bl.ttf", size=30, color=Vec(0.0, 0.0, 0.0), # black pos=Vec(12, 760, -0.2)) globs.textboxes = [textbox] textbox.text = "Moves: " + str(globs.move_count) polycolors = globs.polydata["colors"] count = len(polycolors) nextColor = globs.selected_color moveCounterBkgd = Polygon( polycolors[nextColor], [Vec(0, 6.9), Vec(0, 8), Vec(3, 8)]) moveCounterBorder = Polygon( Vec(0.0, 0.0, 0.0), [Vec(0, 6.8), Vec(0, 8), Vec(3.1, 8)]) paletteBkgd = Polygon( Vec(0.0, 0.0, 0.0), [Vec(2.8, 0), Vec(8.2, 0), Vec(8.2, 2.2)]) palette0 = Polygon( polycolors[nextColor], [Vec(8, 1), Vec(8, 2), Vec(5.5, 1)]) palette1 = Polygon( polycolors[(nextColor + 1) % count], [Vec(8, 1), Vec(5.5, 1), Vec(3, 0)]) palette2 = Polygon( polycolors[(nextColor + 2) % count], [Vec(8, 1), Vec(3, 0), Vec(6, 0)]) palette3 = Polygon( polycolors[(nextColor + 3) % count], [Vec(8, 1), Vec(6, 0), Vec(8, 0)]) globs.hud_polygons = [ moveCounterBkgd, moveCounterBorder, palette0, palette1, palette2, palette3, paletteBkgd ]
def render_loop(): glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) while True: yield from listen.event("on_render") # black background glClearColor(globs.bgcolor.x, globs.bgcolor.y, globs.bgcolor.z, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(Polygon.polygon_shader) for x in range(globs.polydata["nx"]): for y in range(globs.polydata["ny"]): delta = globs.polydata["origin"].xy delta += x * globs.polydata["unit_dx"] delta += y * globs.polydata["unit_dy"] proj = globs.cam["projection"] @ translate(delta.x, delta.y, 0) set_uniform_matrix(Polygon.polygon_shader, "projection", proj) for polygon in globs.polygons: polygon.draw() # HUD proj = globs.cam["projection"] @ translate(0, 0, -0.1) set_uniform_matrix(Polygon.polygon_shader, "projection", proj) for polygon in globs.hud_polygons: polygon.draw() # Load the textbox shader. Text is in pixels, not units, # so need to scale appropriately. Ignore camera position. glUseProgram(TextBox.textshader) s = globs.cam["scale"] tproj = globs.cam["projection"] @ scale(1 / s, 1 / s, 1) set_uniform_matrix(TextBox.textshader, "projection", tproj) for textbox in globs.textboxes: textbox.draw() glfw.swap_buffers(globs.window)
def editor_camera_loop(): # keep track of keys in this dictionary keys = { glfw.KEY_W: False, glfw.KEY_A: False, glfw.KEY_S: False, glfw.KEY_D: False, glfw.KEY_LEFT_SHIFT: False, glfw.KEY_SPACE: False, glfw.KEY_P: False } while True: events = yield from listen.any( key=listen.on_key(globs.window), frame=listen.event("on_frame")) # update dictionary if "key" in events: _, key, _, action, _ = events["key"] if key in keys: if action == glfw.PRESS: keys[key] = True if action == glfw.RELEASE: keys[key] = False # must be in grid_edit mode if globs.mode != "grid_edit": continue # adjust camera position based on key state if "frame" in events: _, dt = events["frame"] v = -10 dx = 0 if keys[glfw.KEY_D]: dx += v if keys[glfw.KEY_A]: dx -= v globs.cam["pos"].x += dt*dx dy = 0 if keys[glfw.KEY_W]: dy += v if keys[glfw.KEY_S]: dy -= v globs.cam["pos"].y += dt*dy
def render_loop(): glEnable(GL_DEPTH_TEST) glDepthFunc(GL_LESS) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) while True: yield from listen.event("on_render") # black background glClearColor(0, 0, 0.0, 1.0) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glUseProgram(Polygon.polygon_shader) set_uniform_matrix(Polygon.polygon_shader, "projection", globs.cam["projection"]) for polygon in globs.polygons: polygon.draw() glfw.swap_buffers(globs.window)
def ending_screen(): while True: yield from listen.event("ending_screen") globs.textboxes = [] polygons = [] polygons.append( Polygon(colors["peru"], [Vec(0, 3), Vec(0, 8), Vec(5, 8)])) polygons.append( Polygon(colors["mistyrose"], [Vec(2, 5), Vec(5, 8), Vec(8, 8), Vec(8, 5)])) polygons.append( Polygon(colors["lightsteelblue"], [Vec(0, 0), Vec(0, 3), Vec(2, 5), Vec(3, 5), Vec(8, 0)])) polygons.append( Polygon(colors["mediumaquamarine"], [Vec(3, 5), Vec(8, 0), Vec(8, 5)])) yield from listen.wait(0.4) globs.hud_polygons = [] for poly in polygons: globs.hud_polygons.append(poly) yield from listen.wait(0.2) thank_you = TextBox(font_loc + "Vitreous-Medium.ttf", size=30, color=Vec(0, 0, 0), pos=Vec(125, 600, -0.2)) thank_you.text = "Thank you for playing" globs.textboxes.append(thank_you) title_box = TextBox(font_loc + "Vitreous-Black.ttf", size=80, color=Vec(0.0, 0.0, 0.0), pos=Vec(120, 525, -0.2)) title_box.text = "Tesseland" globs.textboxes.append(title_box) name_boxes = [ TextBox(font_loc + "Vitreous-Medium.ttf", size=30, color=Vec(0, 0, 0), pos=Vec(150, 325 - 50 * k, -0.2)) for k in range(5) ] name_boxes[0].text = "Special guest level by Billy Rieger" name_boxes[1].text = "Special thanks to our playtesters" name_boxes[2].text = "Levi Walker" name_boxes[3].text = "Jayashree Srinivasan" name_boxes[4].text = "Stella Wang" globs.textboxes += name_boxes globs.bgcolor = Vec(0.0, 0.0, 0) while True: _, button, action, mods = yield from listen.on_mouse_button( globs.window) x, y = glfw.get_cursor_pos(globs.window) pt = mouse_coords(x, y) for poly in globs.hud_polygons: if is_point_in_poly(pt, poly): globs.hud_polygons.remove(poly) break if len(globs.hud_polygons) == 0: globs.textboxes = [] listen.dispatch("next_level") break
def play_loop(): velocities = [Vec(0, 0), Vec(0, 0)] dpad = Vec(0, 0) listen.launch(dpad_loop(dpad)) direction = "right" collision_radius = 3 while True: events = yield from listen.any(frame=listen.event("on_frame"), ) if globs.mode != "play": continue _, dt = events["frame"] for pn in range(len(globs.playerarray.quads)): playerpos = globs.playerarray.quads[pn] velocity = velocities[pn] # is the player touching a wall? touch = { "bot": Vec(0, -1, 0), "left": Vec(-1, 0, 0), "right": Vec(1, 0, 0) } for key in touch: found = False for (x, y) in grid_positions_nearby(playerpos, collision_radius): if squares_intersect(Vec(x, y), playerpos + touch[key] / 16): if globs.grid[(x, y)] == "terrain-top": found = True break touch[key] = found # replace dict entry with boolean print(touch) if touch["bot"]: # if upstream of obstacle, make the vertical velocity 0 velocity.y = 0 else: # otherwise apply downstream current if velocity.y <= 1: velocity.y -= 5 * dt # horizontal movement velocity.x = dpad.x * 3 for (x, y) in grid_positions_nearby(playerpos, collision_radius): if rect_in_rect(Vec(x, y), playerpos, Vec(1, 1), Vec(1, 1)): if globs.grid[(x, y)] == "terrain-side-right": if velocity.x <= 5: velocity.x += 1 * dt if globs.grid[(x, y)] == "terrain-side-left": if velocity.x >= -5: velocity.x -= 1 * dt # bonk on sides if touch["right"] and velocity.x > 0: velocity.x = 0 if touch["left"] and velocity.x < 0: velocity.x = 0 # compute the delta, and apply it with collision detection delta = velocity * dt # move the player. split the delta into lots of tiny nudges # and then apply as many as you can before we collide for nudge in split_delta(delta, 1 / 16): any_collisions = False for (x, y) in globs.grid: if globs.grid[x, y] == "terrain-top": continue if squares_intersect(Vec(x, y), playerpos + nudge.xy0): any_collisions = True break if any_collisions: break playerpos += nudge.xy0 # finalize playerpos globs.playerarray.update() # adjust the player sprite animation # compute the new label newlabel = "idle" if touch["bot"]: if velocity.x != 0: newlabel = "sneak" else: newlabel = "idle" else: newlabel = "move" # compute the direction the player is facing if velocity.x != 0: if velocity.x > 0: direction = "right" else: direction = "left" newlabel += "-" + direction # update the animator if globs.playerarray.asset.label != newlabel: globs.playerarray.asset.clear() globs.playerarray.asset.enqueue(globs.assets["dino-" + newlabel], loop=True, label=newlabel)
def play_loop(): velocity = Vec(0, 0) dpad = Vec(0, 0) listen.launch(dpad_loop(dpad)) direction = "right" while True: events = yield from listen.any(frame=listen.event("on_frame"), ) # only allow play mode if globs.mode != "play": continue _, dt = events["frame"] playerpos = globs.playerarray.quads[0] center_camera(playerpos.x, playerpos.y) # is the player touching something? touch = { "top": Vec(0, 1, 0), "bot": Vec(0, -1, 0), "left": Vec(-1, 0, 0), "right": Vec(1, 0, 0) } for key in touch: found = False for (x, y) in globs.grid: if squares_intersect(Vec(x, y), playerpos + touch[key] / 16): found = True break touch[key] = found # replace dict entry with boolean if touch["bot"]: # if grounded, make the vertical velocity 0 velocity.y = 0 # if the player is pressing up, make them jump if dpad.y == 1: velocity.y = 5 else: # otherwise apply gravity velocity.y -= 5 * dt if (velocity.y < 0): # after peak jump, fall faster velocity.y -= 5 * dt # head bonk if touch["top"] and velocity.y > 0: velocity.y = 0 # horizontal movement velocity.x = dpad.x * 3 # bonk on sides if touch["right"] and velocity.x > 0: velocity.x = 0 if touch["left"] and velocity.x < 0: velocity.x = 0 # compute the delta, and apply it with collision detection delta = velocity * dt # move the player. split the delta into lots of tiny nudges # and then apply as many as you can before we collide for nudge in split_delta(delta, 1 / 16): any_collisions = False for (x, y) in globs.grid: if squares_intersect(Vec(x, y), playerpos + nudge.xy0): any_collisions = True break if any_collisions: break playerpos += nudge.xy0 # finalize playerpos globs.playerarray.update() # adjust the player sprite animation # compute the new label newlabel = "idle" if touch["bot"]: if velocity.x != 0: newlabel = "sneak" else: newlabel = "idle" else: newlabel = "move" # compute the direction the player is facing if velocity.x != 0: if velocity.x > 0: direction = "right" else: direction = "left" newlabel += "-" + direction # update the animator if globs.playerarray.asset.label != newlabel: globs.playerarray.asset.clear() globs.playerarray.asset.enqueue(globs.assets["dino-" + newlabel], loop=True, label=newlabel)
def play_loop(): velocity = Vec(0, 0) dpad = Vec(0, 0) listen.launch(dpad_loop(dpad)) direction = "right" collision_prec = 0.01 collision_radius = 2 playersize = globs.playerarray.asset["size"] gridsize = Vec(1, 1) recent_portal = None while True: events = yield from listen.any(frame=listen.event("on_frame"), ) if globs.mode != "play": continue _, dt = events["frame"] playerpos = globs.playerarray.quads[0] # is the player touching something? touch = { "top": Vec(0, 1, 0), "bot": Vec(0, -1, 0), "left": Vec(-1, 0, 0), "right": Vec(1, 0, 0) } for key in touch: found = False for (x, y) in grid_positions_nearby(playerpos, collision_radius): if "dark" not in globs.grid[x, y]: continue if rects_intersect(Vec(x, y), playerpos + touch[key] * collision_prec, gridsize, playersize): found = True break touch[key] = found # replace dict entry with boolean if touch["bot"]: # if grounded, make the vertical velocity 0 velocity.y = 0 # if the player is pressing up, make them jump if dpad.y == 1: velocity.y = 3 else: # otherwise apply gravity velocity.y -= 3 * dt # horizontal movement velocity.x = dpad.x * 3 # head bonk if touch["top"] and velocity.y > 0: velocity.y = 0 # bonk on sides if touch["right"] and velocity.x > 0: velocity.x = 0 if touch["left"] and velocity.x < 0: velocity.x = 0 # compute the delta, and apply it with collision detection delta = velocity * dt # move the player. split the delta into lots of tiny nudges # and then apply as many as you can before we collide for nudge in split_delta(delta, collision_prec): any_collisions = False for (x, y) in grid_positions_nearby(playerpos, collision_radius): if "dark" not in globs.grid[x, y]: continue if rects_intersect( Vec(x, y), playerpos + nudge.xy0, gridsize, playersize, ): any_collisions = True break if any_collisions: break playerpos += nudge.xy0 # finalize playerpos globs.playerarray.update() globs.circlearray.quads[0] = Vec(0, 0, 0) + playerpos globs.circlearray.quads[0] -= globs.circlearray.asset["size"].xy0 / 2 globs.circlearray.quads[0] += globs.playerarray.asset["size"].xy0 / 2 globs.circlearray.update() for (x, y) in grid_positions_nearby(playerpos, collision_radius): if globs.grid[x, y] != "portal": continue if not rect_in_rect(playerpos, Vec(x, y), playersize, gridsize): continue if (x, y) == recent_portal: continue mode_switch() velocity = Vec(0, 0) recent_portal = (x, y) if recent_portal is not None: if not rects_intersect(playerpos, Vec(*recent_portal), playersize, gridsize): recent_portal = None # adjust the camera if we are not falling if touch["bot"]: globs.cam["target_pos"] = -playerpos.xy + globs.cam["dims"] / 2 # adjust the player sprite animation # compute the new label newlabel = "idle" if touch["bot"]: if velocity.x != 0: newlabel = "sneak" else: newlabel = "idle" else: newlabel = "move" # compute the direction the player is facing if velocity.x != 0: if velocity.x > 0: direction = "right" else: direction = "left" newlabel += "-" + direction # update the animator if globs.playerarray.asset.label != newlabel: globs.playerarray.asset.clear() globs.playerarray.asset.enqueue(globs.assets["dino-" + newlabel], loop=True, label=newlabel)