Flappy Cappy game

Flappy is a capybara with a plan to fly south for the winter. In her way lie all manner of obstacles, from cities to space aliens. Will she ever reach those warmer climes?



We'll be using the P5 library to provide a graphical interface for the game, and we'll use the Strivemath IDE so that you can save your progress online


Download the instructions here.

We can draw some of the game objects directly in the code, but we'll use pre-prepared images for some of them (have you ever tried making a convincing capybara out of rectangles, triangles and ellipses?). You can download these from here - right-click each image and save it to your desktop.




View the code




# Week 2 # Import libraries import random # Set constants SCREEN = [600, 400] CAPPY_START = [50, 200] CAPPY_W = CAPPY_H = 64 CLOUD_SPEED = 0.3 GRAVITY = 0.1 level = 1 score = 0 lives = 3 cappy = [] cappy_index = 0 frame_count = 0 y_speed = 0 x_speed = 1 buildinglist = [] next_building = 0 assets = "https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/d9ea3bf8-b645-47a5-b0e8-4fc65f7df8c0/" def setup(): createCanvas(SCREEN[0], SCREEN[1]) frameRate(60) # Declare and set globals global cloudpic, cloudlist, x, y # Add the first cloud to the cloudlist array cloudpic = loadImage(assets+"cloud.png") cloudlist = [[random.randint(0, 600), random.randint(100, 380)]] # Load the image frames that make the Cappy animation for i in range(4): cappy.append(loadImage(assets + "cappy_"+str(i)+".png")) x = CAPPY_START[0] y = CAPPY_START[1] def draw(): global cappy_index, frame_count, x, y, x_speed, y_speed # Draw background and clouds background("#99ddff") drawTickAxes() chance = random.randint(1,300) if chance == 1: cloudlist.append ([500, random.randint(100, 380)]) for cloud in cloudlist: image(cloudpic, cloud[0], cloud[1]) cloud[0]-= CLOUD_SPEED if cloud[0] < 0-cloudpic.width: cloudlist.remove(cloud) if level == 1: buildings(100, (200, 200, 200)) # Draw Cappy image(cappy[cappy_index], x, y) # Advance frame every 6 draw calls (~10 fps at 60 fps) frame_count += 1 if frame_count % 6 == 0: cappy_index = (cappy_index + 1) % len(cappy) # Adjust y_speed y_speed = y_speed + GRAVITY if (y < 20 ): y_speed = 0 elif y > 350: y_speed = 1 y -= y_speed else: y -= y_speed def buildings(max_height, colour): def addBuilding(colour): global next_building height = random.randint(20, max_height) buildinglist.append([600, 100, height, colour]) next_building = next_building + random.randint(20, 80) + 100 if frame_count > next_building: addBuilding(colour) last_building = frame_count # Loop through the buildings for building in buildinglist: building[0]-= x_speed if building[0] < 0-building[1]: buildinglist.remove(building) else: fill(building[3]) rect(building[0], 0, building[1], building[2]) # Draw the windows window_y = building[2] - 30 fill( "yellow") while window_y > 0: rect(building[0]+20, window_y, 15, 20) rect(building[0]+60, window_y, 15, 20) window_y -= 40 # Loop through the buildings def mousePressed(): global y_speed, y if y<20: y += 10 y_speed -= 3 # Import libraries import random # Set constants SCREEN = [600, 400] CAPPY_START = [50, 200] CAPPY_W = CAPPY_H = 64 CLOUD_SPEED = 0.3 GRAVITY = 0.1 level = 1 score = 0 lives = 3 cappy = [] cappy_index = 0 frame_count = 0 y_speed = 0 x_speed = 1 buildinglist = [] next_building = 0 planelist = [] plane_counter = 0 assets = "https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/95989e3b-e181-4582-98e6-675f333abe01/" def setup(): createCanvas(SCREEN[0], SCREEN[1]) frameRate(60) # Declare and set globals global cloudpic, cloudlist, x, y, game_state, boom, font, aircraft game_state = "over" # Add the first cloud to the cloudlist array cloudpic = loadImage(assets+"cloud.png") cloudlist = [[random.randint(0, 600), random.randint(100, 380)]] # Load the image frames that make the Cappy animation for i in range(4): cappy.append(loadImage(assets + "cappy_"+str(i)+".png")) # Load the 'BOOM' pic boom = loadImage(assets+"boom.png") # Load the plane pic aircraft = loadImage(assets+"plane.png") # Load font font = loadFont("https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/global/Orbitron-Bold.ttf"); x = CAPPY_START[0] y = CAPPY_START[1] def draw(): global cappy_index, frame_count, x, y, x_speed, y_speed, game_state global lives, score, level if game_state == 'crashed': if lives == 0: game_state = 'over' else: crashed() elif game_state == 'over': over() elif game_state == 'play': # Draw background and clouds background("#99ddff") chance = random.randint(1,300) if chance == 1: cloudlist.append ([500, random.randint(100, 380)]) for cloud in cloudlist: image(cloudpic, cloud[0], cloud[1]) cloud[0]-= CLOUD_SPEED if cloud[0] < 0-cloudpic.width: cloudlist.remove(cloud) if level == 1: game_state = buildings(100, (200, 200, 200)) if level == 2: game_state = buildings(200, (200, 160, 100)) if level == 3: game_state = buildings(300, (200, 100, 60)) if level == 4: game_state = buildings(180, (200, 160, 160)) game_state = plane() # Draw Cappy image(cappy[cappy_index], x, y) # Advance frame every 6 draw calls (~10 fps at 60 fps) frame_count += 1 if frame_count % 6 == 0: cappy_index = (cappy_index + 1) % len(cappy) # Adjust y_speed y_speed = y_speed + GRAVITY if (y < 20 ): y_speed = 0 elif y > 350: y_speed = 1 y -= y_speed else: y -= y_speed if game_state == "crashed": image(boom, x-25, y-30) lives -= 1 if frame_count % 60 == 0: score += 1 if frame_count % 1000 == 0: level += 1 write_score(score, level, lives) def buildings(max_height, colour): status = game_state crash_building = False def addBuilding(colour): global next_building height = random.randint(20, max_height) buildinglist.append([600, 100, height, colour]) next_building = next_building + random.randint(20, 80) + 100 if frame_count > next_building: addBuilding(colour) last_building = frame_count # Loop through the buildings for building in buildinglist: building[0]-= x_speed if building[0] < 0-building[1]: buildinglist.remove(building) else: fill(building[3]) rect(building[0], 0, building[1], building[2]) # Draw the windows window_y = building[2] - 30 fill( "yellow") while window_y > 0: rect(building[0]+20, window_y, 15, 20) rect(building[0]+60, window_y, 15, 20) window_y -= 40 # Loop through the buildings # Check for collisions if x + CAPPY_W > building[0] and x < building[0]+building[1] and y < building[2]: status = "crashed" crash_building = building if crash_building: buildinglist.remove(crash_building) return status def plane(): global planelist, plane_counter status = game_state crash_plane = False def add_plane(): global plane_counter y = random.randint(260,400-aircraft.height) planelist.append([SCREEN[0], y]) plane_counter = 100 chance = random.randint(1,200) if plane_counter <= 0 and chance == 1: add_plane() for plane in planelist: image(aircraft, plane[0], plane[1]) plane[0] -= 2 # Check for collisions if x+CAPPY_W > plane[0] and x < plane[0]+aircraft.width and y+CAPPY_H > plane[1] and y < plane[1]+aircraft.height: status = "crashed" crash_plane = plane if crash_plane: #pass planelist.remove(crash_plane) plane_counter -= 1 return status def write_score(score, level, lives): fill(255, 100, 0); noStroke(); textFont(font) textSize(22); text("Score: "+str(int(score)), 40, 370) text("Level: "+str(level), 260, 370) text("Lives: "+str(lives), 480, 370) def crashed(): global x, y, y_speed x = CAPPY_START[0] y = CAPPY_START[1] y_speed = 0 fill(255, 255, 0) stroke(0) textFont(font) textSize(40) text("Crashed!", 220, 260) text("Click To Resume", 140, 200) def over(): global x, y, y_speed, score, lives, level global buildinglist, frame_count, next_building x = CAPPY_START[0] y = CAPPY_START[1] y_speed = 0 score = 0 level = 1 lives = 3 buildinglist = [] next_building = 0 frame_count = 0 fill(255, 0, 0) stroke(0) textFont(font) textSize(40) text("Game Over", 220, 260) text("Click To Start", 180, 200) def mousePressed(): global game_state if game_state == 'over' or game_state == 'crashed': game_state = 'play' elif game_state == 'play': global y_speed, y if y<20: y += 10 y_speed -= 3 # Import libraries import random import math # Set constants SCREEN = [600, 400] CAPPY_START = [50, 200] CAPPY_W = CAPPY_H = 64 CLOUD_SPEED = 0.3 GRAVITY = 0.1 level = 1 score = 0 lives = 3 cappy = [] cappy_index = 0 frame_count = 0 y_speed = 0 x_speed = 1 buildinglist = [] next_building = 0 egglist = [] planelist = [] plane_counter = 0 ufolist = [] assets = "https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/95989e3b-e181-4582-98e6-675f333abe01/" def setup(): createCanvas(SCREEN[0], SCREEN[1]) frameRate(60) # Declare and set globals global cloudpic, cloudlist, x, y, game_state, boom, font, aircraft, pop game_state = "over" # Add the first cloud to the cloudlist array cloudpic = loadImage(assets+"cloud.png") cloudlist = [[random.randint(0, 600), random.randint(100, 380)]] # Load the image frames that make the Cappy animation for i in range(4): cappy.append(loadImage(assets + "cappy_"+str(i)+".png")) # Load the 'BOOM' pic boom = loadImage(assets+"boom.png") # Load the plane pic aircraft = loadImage(assets+"plane.png") # Load font font = loadFont("https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/global/Orbitron-Bold.ttf"); # Load a sound pop = loadSound("https://ezpwmmfaodhpebjbmury.supabase.co/storage/v1/object/public/assets/global/pop.mp3") x = CAPPY_START[0] y = CAPPY_START[1] def draw(): global cappy_index, frame_count, x, y, x_speed, y_speed, game_state global lives, score, level if game_state == 'crashed': if lives == 0: game_state = 'over' else: crashed() elif game_state == 'over': over() elif game_state == 'play': # Draw background and clouds background("#99ddff") chance = random.randint(1,300) if chance == 1: cloudlist.append ([500, random.randint(100, 380)]) for cloud in cloudlist: image(cloudpic, cloud[0], cloud[1]) cloud[0]-= CLOUD_SPEED if cloud[0] < 0-cloudpic.width: cloudlist.remove(cloud) if level == 1: game_state = buildings(100, (200, 200, 200)) if level == 2: game_state = buildings(200, (200, 160, 100)) game_state = plane() if level == 3: game_state = buildings(100, (200, 160, 100)) game_state = plane() if level == 4: game_state = buildings(140, (200, 100, 60)) game_state = ufo(300) if level == 5: game_state = buildings(180, (200, 160, 160)) game_state = ufo(300) if level >= 6: game_state = buildings(180, (200, 100, 160)) game_state = plane() game_state = ufo(300) # Draw Cappy image(cappy[cappy_index], x, y) # Advance frame every 6 draw calls (~10 fps at 60 fps) frame_count += 1 if frame_count % 6 == 0: cappy_index = (cappy_index + 1) % len(cappy) # Adjust y_speed y_speed = y_speed + GRAVITY if (y < 20 ): y_speed = 0 elif y > 350: y_speed = 1 y -= y_speed else: y -= y_speed if game_state == "crashed": image(boom, x-25, y-30) lives -= 1 if frame_count % 60 == 0: score += 1 if frame_count % 1000 == 0: level += 1 write_score(score, level, lives) def buildings(max_height, colour): global score status = game_state crash_building = False def addBuilding(colour): global next_building height = random.randint(20, max_height) buildinglist.append([600, 100, height, colour]) chance = random.randint(1, 3) if chance == 1: egglist.append([650, height+20, 30, 40]) next_building = next_building + random.randint(20, 80) + 100 if frame_count > next_building: addBuilding(colour) last_building = frame_count # Loop through the buildings for building in buildinglist: building[0]-= x_speed if building[0] < 0-building[1]: buildinglist.remove(building) else: stroke(0) fill(building[3]) rect(building[0], 0, building[1], building[2]) # Draw the windows window_y = building[2] - 30 fill( "yellow") while window_y > 0: rect(building[0]+20, window_y, 15, 20) rect(building[0]+60, window_y, 15, 20) window_y -= 40 # Check for collisions if x + CAPPY_W > building[0] and x < building[0]+building[1] and y < building[2]: status = "crashed" crash_building = building for egg in egglist: if egg[0] < -10: egglist.remove(egg) else: # Draw an egg fill(255) egg[0]-= x_speed ellipse(egg[0], egg[1], egg[2], egg[3]) # Check for egg capture if x + CAPPY_W > egg[0] and x < egg[0]+egg[2] and y < egg[1]+egg[2]: score += 20 egglist.remove(egg) play(pop) if crash_building: buildinglist.remove(crash_building) return status def plane(): global planelist, plane_counter status = game_state crash_plane = False def add_plane(): global plane_counter y = random.randint(260,400-aircraft.height) planelist.append([SCREEN[0], y]) plane_counter = 100 chance = random.randint(1,200) if plane_counter <= 0 and chance == 1: add_plane() for plane in planelist: image(aircraft, plane[0], plane[1]) plane[0] -= 2 # Check for collisions if x+CAPPY_W > plane[0] and x < plane[0]+aircraft.width and y+CAPPY_H > plane[1] and y < plane[1]+aircraft.height: status = "crashed" crash_plane = plane if crash_plane: #pass planelist.remove(crash_plane) plane_counter -= 1 return status def ufo(rarity): status = game_state crash_ufo = False chance = random.randint(1, rarity) if chance == 1: direction = random.randint(0, 6) y_pos = random.randint(250, 300) ufolist.append([644, y_pos, direction]) def draw_ufo(ufo_x, ufo_y): fill(0, 200, 200); ellipse(ufo_x-22, ufo_y+6, 5, 5) triangle(ufo_x-22, ufo_y, ufo_x-24, ufo_y-10, ufo_x-14, ufo_y) triangle(ufo_x+22, ufo_y, ufo_x+24, ufo_y-10, ufo_x+14, ufo_y) ellipse(ufo_x+22, ufo_y+6, 5, 5) fill(0, 100, 155); ellipse(ufo_x, ufo_y, 50, 20) fill(0, 200, 200) for win_x in range(ufo_x-20, ufo_x+20, 6): rect(win_x, ufo_y-3, 3, 6) for ufo in ufolist: if ufo[0] < -22: ufolist.remove(ufo) else: ufo[0] -= 1 ufo[2] += 0.03 ufo_speed = math.sin(ufo[2]) ufo[1] += ufo_speed draw_ufo(ufo[0], ufo[1]) # Check for collisions if x+CAPPY_W > ufo[0]-22 and x < ufo[0]+22 and y+CAPPY_H > ufo[1]-6 and y < ufo[1]+6: status = "crashed" crash_ufo = ufo if crash_ufo: ufolist.remove(crash_ufo) return status def write_score(score, level, lives): fill(255, 100, 0); noStroke(); textFont(font) textSize(22); text("Score: "+str(int(score)), 40, 370) text("Level: "+str(level), 260, 370) text("Lives: "+str(lives), 480, 370) def crashed(): global x, y, y_speed x = CAPPY_START[0] y = CAPPY_START[1] y_speed = 0 fill(255, 255, 0) stroke(0) textFont(font) textSize(40) text("Crashed!", 220, 260) text("Click To Resume", 140, 200) def over(): global x, y, y_speed, score, lives, level global buildinglist, frame_count, next_building x = CAPPY_START[0] y = CAPPY_START[1] y_speed = 0 score = 0 level = 1 lives = 3 buildinglist = [] next_building = 0 frame_count = 0 fill(255, 0, 0) stroke(0) textFont(font) textSize(40) text("Game Over", 220, 260) text("Click To Start", 180, 200) def mousePressed(): global game_state if game_state == 'over' or game_state == 'crashed': game_state = 'play' elif game_state == 'play': global y_speed, y if y<20: y += 10 y_speed -= 3