diff --git a/src/characters.py b/src/characters.py index 4d22d30..af65bc9 100644 --- a/src/characters.py +++ b/src/characters.py @@ -2,7 +2,7 @@ from pymunk import Vec2d -class Bird(): +class Bird: def __init__(self, distance, angle, x, y, space): self.life = 20 mass = 5 @@ -23,7 +23,7 @@ def __init__(self, distance, angle, x, y, space): self.shape = shape -class Pig(): +class Pig: def __init__(self, x, y, space): self.life = 20 mass = 5 diff --git a/src/level.py b/src/level.py index f6912f5..113b5a4 100644 --- a/src/level.py +++ b/src/level.py @@ -2,7 +2,7 @@ from polygon import Polygon -class Level(): +class Level: def __init__(self, pigs, columns, beams, space): self.pigs = pigs self.columns = columns @@ -20,40 +20,40 @@ def open_flat(self, x, y, n): """Create a open flat struture""" y0 = y for i in range(n): - y = y0+100+i*100 + y = y0 + 100 + i * 100 p = (x, y) self.columns.append(Polygon(p, 20, 85, self.space)) - p = (x+60, y) + p = (x + 60, y) self.columns.append(Polygon(p, 20, 85, self.space)) - p = (x+30, y+50) + p = (x + 30, y + 50) self.beams.append(Polygon(p, 85, 20, self.space)) def closed_flat(self, x, y, n): """Create a closed flat struture""" y0 = y for i in range(n): - y = y0+100+i*125 - p = (x+1, y+22) + y = y0 + 100 + i * 125 + p = (x + 1, y + 22) self.columns.append(Polygon(p, 20, 85, self.space)) - p = (x+60, y+22) + p = (x + 60, y + 22) self.columns.append(Polygon(p, 20, 85, self.space)) - p = (x+30, y+70) + p = (x + 30, y + 70) self.beams.append(Polygon(p, 85, 20, self.space)) - p = (x+30, y-30) + p = (x + 30, y - 30) self.beams.append(Polygon(p, 85, 20, self.space)) def horizontal_pile(self, x, y, n): """Create a horizontal pile""" y += 70 for i in range(n): - p = (x, y+i*20) + p = (x, y + i * 20) self.beams.append(Polygon(p, 85, 20, self.space)) def vertical_pile(self, x, y, n): """Create a vertical pile""" y += 10 for i in range(n): - p = (x, y+85+i*85) + p = (x, y + 85 + i * 85) self.columns.append(Polygon(p, 20, 85, self.space)) def build_0(self): @@ -195,10 +195,10 @@ def build_5(self): pig = Pig(1000, 152, self.space) self.pigs.append(pig) for i in range(9): - p = (800, 70+i*21) + p = (800, 70 + i * 21) self.beams.append(Polygon(p, 85, 20, self.space)) for i in range(4): - p = (1000, 70+i*21) + p = (1000, 70 + i * 21) self.beams.append(Polygon(p, 85, 20, self.space)) p = (970, 176) self.columns.append(Polygon(p, 20, 85, self.space)) @@ -325,9 +325,9 @@ def build_11(self): def load_level(self): try: - build_name = "build_"+str(self.number) + build_name = "build_" + str(self.number) getattr(self, build_name)() except AttributeError: self.number = 0 - build_name = "build_"+str(self.number) + build_name = "build_" + str(self.number) getattr(self, build_name)() diff --git a/src/main.py b/src/main.py index 1793f0c..541958d 100644 --- a/src/main.py +++ b/src/main.py @@ -1,33 +1,25 @@ import os -import sys import math import time import pygame + current_path = os.getcwd() import pymunk as pm from characters import Bird from level import Level - pygame.init() screen = pygame.display.set_mode((1200, 650)) -redbird = pygame.image.load( - "../resources/images/red-bird3.png").convert_alpha() -background2 = pygame.image.load( - "../resources/images/background3.png").convert_alpha() -sling_image = pygame.image.load( - "../resources/images/sling-3.png").convert_alpha() -full_sprite = pygame.image.load( - "../resources/images/full-sprite.png").convert_alpha() +redbird = pygame.image.load("../resources/images/red-bird3.png").convert_alpha() +background2 = pygame.image.load("../resources/images/background3.png").convert_alpha() +sling_image = pygame.image.load("../resources/images/sling-3.png").convert_alpha() +full_sprite = pygame.image.load("../resources/images/full-sprite.png").convert_alpha() rect = pygame.Rect(181, 1050, 50, 50) cropped = full_sprite.subsurface(rect).copy() pig_image = pygame.transform.scale(cropped, (30, 30)) -buttons = pygame.image.load( - "../resources/images/selected-buttons.png").convert_alpha() -pig_happy = pygame.image.load( - "../resources/images/pig_failed.png").convert_alpha() -stars = pygame.image.load( - "../resources/images/stars-edited.png").convert_alpha() +buttons = pygame.image.load("../resources/images/selected-buttons.png").convert_alpha() +pig_happy = pygame.image.load("../resources/images/pig_failed.png").convert_alpha() +stars = pygame.image.load("../resources/images/stars-edited.png").convert_alpha() rect = pygame.Rect(0, 0, 200, 200) star1 = stars.subsurface(rect).copy() rect = pygame.Rect(204, 0, 200, 200) @@ -43,7 +35,6 @@ clock = pygame.time.Clock() rect = pygame.Rect(18, 212, 100, 100) play_button = buttons.subsurface(rect).copy() -clock = pygame.time.Clock() running = True # the base of the physics space = pm.Space() @@ -100,7 +91,7 @@ def to_pygame(p): """Convert pymunk to pygame coordinates""" - return int(p.x), int(-p.y+600) + return int(p.x), int(-p.y + 600) def vector(p0, p1): @@ -108,18 +99,18 @@ def vector(p0, p1): p0 = (xo,yo), p1 = (x1,y1)""" a = p1[0] - p0[0] b = p1[1] - p0[1] - return (a, b) + return a, b def unit_vector(v): """Return the unit vector of the points v = (a,b)""" - h = ((v[0]**2)+(v[1]**2))**0.5 + h = ((v[0] ** 2) + (v[1] ** 2)) ** 0.5 if h == 0: h = 0.000000000000001 ua = v[0] / h ub = v[1] / h - return (ua, ub) + return ua, ub def distance(xo, yo, x, y): @@ -150,7 +141,7 @@ def sling_action(): uv1 = uv[0] uv2 = uv[1] mouse_distance = distance(sling_x, sling_y, x_mouse, y_mouse) - pu = (uv1*rope_lenght+sling_x, uv2*rope_lenght+sling_y) + pu = (uv1 * rope_lenght + sling_x, uv2 * rope_lenght + sling_y) bigger_rope = 102 x_redbird = x_mouse - 20 y_redbird = y_mouse - 20 @@ -160,22 +151,19 @@ def sling_action(): puy -= 20 pul = pux, puy screen.blit(redbird, pul) - pu2 = (uv1*bigger_rope+sling_x, uv2*bigger_rope+sling_y) - pygame.draw.line(screen, (0, 0, 0), (sling2_x, sling2_y), pu2, 5) - screen.blit(redbird, pul) - pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y), pu2, 5) + pu = (uv1 * bigger_rope + sling_x, uv2 * bigger_rope + sling_y) else: mouse_distance += 10 - pu3 = (uv1*mouse_distance+sling_x, uv2*mouse_distance+sling_y) - pygame.draw.line(screen, (0, 0, 0), (sling2_x, sling2_y), pu3, 5) - screen.blit(redbird, (x_redbird, y_redbird)) - pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y), pu3, 5) + pu = (uv1 * mouse_distance + sling_x, uv2 * mouse_distance + sling_y) + pygame.draw.line(screen, (0, 0, 0), (sling2_x, sling2_y), pu, 5) + screen.blit(redbird, (x_redbird, y_redbird)) + pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y), pu, 5) # Angle of impulse dy = y_mouse - sling_y dx = x_mouse - sling_x if dx == 0: dx = 0.00000000000001 - angle = math.atan((float(dy))/dx) + angle = math.atan((float(dy)) / dx) def draw_level_cleared(): @@ -187,15 +175,15 @@ def draw_level_cleared(): score_level_cleared = bold_font2.render(str(score), 1, WHITE) if level.number_of_birds >= 0 and len(pigs) == 0: if bonus_score_once: - score += (level.number_of_birds-1) * 10000 + score += (level.number_of_birds - 1) * 10000 bonus_score_once = False game_state = 4 rect = pygame.Rect(300, 0, 600, 800) pygame.draw.rect(screen, BLACK, rect) screen.blit(level_cleared, (450, 90)) - if score >= level.one_star and score <= level.two_star: + if level.one_star <= score <= level.two_star: screen.blit(star1, (310, 190)) - if score >= level.two_star and score <= level.three_star: + if level.two_star <= score <= level.three_star: screen.blit(star1, (310, 190)) screen.blit(star2, (500, 170)) if score >= level.three_star: @@ -248,9 +236,9 @@ def restart(): beams.remove(beam) -def post_solve_bird_pig(arbiter, space, _): +def post_solve_bird_pig(arbiter, space, *args, **kwargs): """Collision between bird and pig""" - surface=screen + surface = screen a, b = arbiter.shapes bird_body = a.body pig_body = b.body @@ -271,7 +259,7 @@ def post_solve_bird_pig(arbiter, space, _): pigs.remove(pig) -def post_solve_bird_wood(arbiter, space, _): +def post_solve_bird_wood(arbiter, space, *args, **kwargs): """Collision between bird and wood""" poly_to_remove = [] if arbiter.total_impulse.length > 1100: @@ -292,7 +280,7 @@ def post_solve_bird_wood(arbiter, space, _): score += 5000 -def post_solve_pig_wood(arbiter, space, _): +def post_solve_pig_wood(arbiter, space, *args, **kwargs): """Collision between pig and wood""" pigs_to_remove = [] if arbiter.total_impulse.length > 700: @@ -309,204 +297,204 @@ def post_solve_pig_wood(arbiter, space, _): pigs.remove(pig) -# bird and pigs -space.add_collision_handler(0, 1).post_solve=post_solve_bird_pig -# bird and wood -space.add_collision_handler(0, 2).post_solve=post_solve_bird_wood -# pig and wood -space.add_collision_handler(1, 2).post_solve=post_solve_pig_wood -load_music() -level = Level(pigs, columns, beams, space) -level.number = 0 -level.load_level() - -while running: - # Input handling - for event in pygame.event.get(): - if event.type == pygame.QUIT: - running = False - elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: - running = False - elif event.type == pygame.KEYDOWN and event.key == pygame.K_w: - # Toggle wall - if wall: - space.remove(static_lines1) - wall = False - else: - space.add(static_lines1) - wall = True - - elif event.type == pygame.KEYDOWN and event.key == pygame.K_s: - space.gravity = (0.0, -10.0) - level.bool_space = True - elif event.type == pygame.KEYDOWN and event.key == pygame.K_n: - space.gravity = (0.0, -700.0) - level.bool_space = False - if (pygame.mouse.get_pressed()[0] and x_mouse > 100 and - x_mouse < 250 and y_mouse > 370 and y_mouse < 550): - mouse_pressed = True - if (event.type == pygame.MOUSEBUTTONUP and - event.button == 1 and mouse_pressed): - # Release new bird - mouse_pressed = False - if level.number_of_birds > 0: - level.number_of_birds -= 1 - t1 = time.time()*1000 - xo = 154 - yo = 156 - if mouse_distance > rope_lenght: - mouse_distance = rope_lenght - if x_mouse < sling_x+5: - bird = Bird(mouse_distance, angle, xo, yo, space) - birds.append(bird) +if __name__ == '__main__': + # bird and pigs + space.add_collision_handler(0, 1).post_solve = post_solve_bird_pig + # bird and wood + space.add_collision_handler(0, 2).post_solve = post_solve_bird_wood + # pig and wood + space.add_collision_handler(1, 2).post_solve = post_solve_pig_wood + load_music() + level = Level(pigs, columns, beams, space) + level.number = 0 + level.load_level() + + while running: + # Input handling + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: + running = False + elif event.type == pygame.KEYDOWN and event.key == pygame.K_w: + # Toggle wall + if wall: + space.remove(static_lines1) + wall = False else: - bird = Bird(-mouse_distance, angle, xo, yo, space) - birds.append(bird) - if level.number_of_birds == 0: - t2 = time.time() - if event.type == pygame.MOUSEBUTTONUP and event.button == 1: - if (x_mouse < 60 and y_mouse < 155 and y_mouse > 90): - game_state = 1 - if game_state == 1: - if x_mouse > 500 and y_mouse > 200 and y_mouse < 300: - # Resume in the paused screen - game_state = 0 - if x_mouse > 500 and y_mouse > 300: - # Restart in the paused screen - restart() - level.load_level() - game_state = 0 - bird_path = [] - if game_state == 3: - # Restart in the failed level screen - if x_mouse > 500 and x_mouse < 620 and y_mouse > 450: - restart() - level.load_level() - game_state = 0 - bird_path = [] - score = 0 - if game_state == 4: - # Build next level - if x_mouse > 610 and y_mouse > 450: - restart() - level.number += 1 - game_state = 0 - level.load_level() - score = 0 - bird_path = [] - bonus_score_once = True - if x_mouse < 610 and x_mouse > 500 and y_mouse > 450: - # Restart in the level cleared screen - restart() - level.load_level() - game_state = 0 - bird_path = [] - score = 0 - x_mouse, y_mouse = pygame.mouse.get_pos() - # Draw background - screen.fill((130, 200, 100)) - screen.blit(background2, (0, -50)) - # Draw first part of the sling - rect = pygame.Rect(50, 0, 70, 220) - screen.blit(sling_image, (138, 420), rect) - # Draw the trail left behind - for point in bird_path: - pygame.draw.circle(screen, WHITE, point, 5, 0) - # Draw the birds in the wait line - if level.number_of_birds > 0: - for i in range(level.number_of_birds-1): - x = 100 - (i*35) - screen.blit(redbird, (x, 508)) - # Draw sling behavior - if mouse_pressed and level.number_of_birds > 0: - sling_action() - else: - if time.time()*1000 - t1 > 300 and level.number_of_birds > 0: - screen.blit(redbird, (130, 426)) + space.add(static_lines1) + wall = True + + elif event.type == pygame.KEYDOWN and event.key == pygame.K_s: + space.gravity = (0.0, -10.0) + level.bool_space = True + elif event.type == pygame.KEYDOWN and event.key == pygame.K_n: + space.gravity = (0.0, -700.0) + level.bool_space = False + if pygame.mouse.get_pressed()[0] and 100 < x_mouse < 250 and 370 < y_mouse < 550: + mouse_pressed = True + if (event.type == pygame.MOUSEBUTTONUP and + event.button == 1 and mouse_pressed): + # Release new bird + mouse_pressed = False + if level.number_of_birds > 0: + level.number_of_birds -= 1 + t1 = time.time() * 1000 + xo = 154 + yo = 156 + if mouse_distance > rope_lenght: + mouse_distance = rope_lenght + if x_mouse < sling_x + 5: + bird = Bird(mouse_distance, angle, xo, yo, space) + birds.append(bird) + else: + bird = Bird(-mouse_distance, angle, xo, yo, space) + birds.append(bird) + if level.number_of_birds == 0: + t2 = time.time() + if event.type == pygame.MOUSEBUTTONUP and event.button == 1: + if x_mouse < 60 and 155 > y_mouse > 90: + game_state = 1 + if game_state == 1: + if x_mouse > 500 and 200 < y_mouse < 300: + # Resume in the paused screen + game_state = 0 + if x_mouse > 500 and y_mouse > 300: + # Restart in the paused screen + restart() + level.load_level() + game_state = 0 + bird_path = [] + if game_state == 3: + # Restart in the failed level screen + if 500 < x_mouse < 620 and y_mouse > 450: + restart() + level.load_level() + game_state = 0 + bird_path = [] + score = 0 + if game_state == 4: + # Build next level + if x_mouse > 610 and y_mouse > 450: + restart() + level.number += 1 + game_state = 0 + level.load_level() + score = 0 + bird_path = [] + bonus_score_once = True + if 610 > x_mouse > 500 and y_mouse > 450: + # Restart in the level cleared screen + restart() + level.load_level() + game_state = 0 + bird_path = [] + score = 0 + x_mouse, y_mouse = pygame.mouse.get_pos() + # Draw background + screen.fill((130, 200, 100)) + screen.blit(background2, (0, -50)) + # Draw first part of the sling + rect = pygame.Rect(50, 0, 70, 220) + screen.blit(sling_image, (138, 420), rect) + # Draw the trail left behind + for point in bird_path: + pygame.draw.circle(screen, WHITE, point, 5, 0) + # Draw the birds in the wait line + if level.number_of_birds > 0: + for i in range(level.number_of_birds - 1): + x = 100 - (i * 35) + screen.blit(redbird, (x, 508)) + # Draw sling behavior + if mouse_pressed and level.number_of_birds > 0: + sling_action() else: - pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y-8), - (sling2_x, sling2_y-7), 5) - birds_to_remove = [] - pigs_to_remove = [] - counter += 1 - # Draw birds - for bird in birds: - if bird.shape.body.position.y < 0: - birds_to_remove.append(bird) - p = to_pygame(bird.shape.body.position) - x, y = p - x -= 22 - y -= 20 - screen.blit(redbird, (x, y)) - pygame.draw.circle(screen, BLUE, - p, int(bird.shape.radius), 2) - if counter >= 3 and time.time() - t1 < 5: - bird_path.append(p) - restart_counter = True - if restart_counter: - counter = 0 - restart_counter = False - # Remove birds and pigs - for bird in birds_to_remove: - space.remove(bird.shape, bird.shape.body) - birds.remove(bird) - for pig in pigs_to_remove: - space.remove(pig.shape, pig.shape.body) - pigs.remove(pig) - # Draw static lines - for line in static_lines: - body = line.body - pv1 = body.position + line.a.rotated(body.angle) - pv2 = body.position + line.b.rotated(body.angle) - p1 = to_pygame(pv1) - p2 = to_pygame(pv2) - pygame.draw.lines(screen, (150, 150, 150), False, [p1, p2]) - i = 0 - # Draw pigs - for pig in pigs: - i += 1 - # print (i,pig.life) - pig = pig.shape - if pig.body.position.y < 0: - pigs_to_remove.append(pig) - - p = to_pygame(pig.body.position) - x, y = p - - angle_degrees = math.degrees(pig.body.angle) - img = pygame.transform.rotate(pig_image, angle_degrees) - w,h = img.get_size() - x -= w*0.5 - y -= h*0.5 - screen.blit(img, (x, y)) - pygame.draw.circle(screen, BLUE, p, int(pig.radius), 2) - # Draw columns and Beams - for column in columns: - column.draw_poly('columns', screen) - for beam in beams: - beam.draw_poly('beams', screen) - # Update physics - dt = 1.0/50.0/2. - for x in range(2): - space.step(dt) # make two updates per frame for better stability - # Drawing second part of the sling - rect = pygame.Rect(0, 0, 60, 200) - screen.blit(sling_image, (120, 420), rect) - # Draw score - score_font = bold_font.render("SCORE", 1, WHITE) - number_font = bold_font.render(str(score), 1, WHITE) - screen.blit(score_font, (1060, 90)) - if score == 0: - screen.blit(number_font, (1100, 130)) - else: - screen.blit(number_font, (1060, 130)) - screen.blit(pause_button, (10, 90)) - # Pause option - if game_state == 1: - screen.blit(play_button, (500, 200)) - screen.blit(replay_button, (500, 300)) - draw_level_cleared() - draw_level_failed() - pygame.display.flip() - clock.tick(50) - pygame.display.set_caption("fps: " + str(clock.get_fps())) + if time.time() * 1000 - t1 > 300 and level.number_of_birds > 0: + screen.blit(redbird, (130, 426)) + else: + pygame.draw.line(screen, (0, 0, 0), (sling_x, sling_y - 8), + (sling2_x, sling2_y - 7), 5) + birds_to_remove = [] + pigs_to_remove = [] + counter += 1 + # Draw birds + for bird in birds: + if bird.shape.body.position.y < 0: + birds_to_remove.append(bird) + p = to_pygame(bird.shape.body.position) + x, y = p + x -= 22 + y -= 20 + screen.blit(redbird, (x, y)) + pygame.draw.circle(screen, BLUE, + p, int(bird.shape.radius), 2) + if counter >= 3 and time.time() - t1 < 5: + bird_path.append(p) + restart_counter = True + if restart_counter: + counter = 0 + restart_counter = False + # Remove birds and pigs + for bird in birds_to_remove: + space.remove(bird.shape, bird.shape.body) + birds.remove(bird) + for pig in pigs_to_remove: + space.remove(pig.shape, pig.shape.body) + pigs.remove(pig) + # Draw static lines + for line in static_lines: + body = line.body + pv1 = body.position + line.a.rotated(body.angle) + pv2 = body.position + line.b.rotated(body.angle) + p1 = to_pygame(pv1) + p2 = to_pygame(pv2) + pygame.draw.lines(screen, (150, 150, 150), False, [p1, p2]) + i = 0 + # Draw pigs + for pig in pigs: + i += 1 + # print (i,pig.life) + pig = pig.shape + if pig.body.position.y < 0: + pigs_to_remove.append(pig) + + p = to_pygame(pig.body.position) + x, y = p + + angle_degrees = math.degrees(pig.body.angle) + img = pygame.transform.rotate(pig_image, angle_degrees) + w, h = img.get_size() + x -= w * 0.5 + y -= h * 0.5 + screen.blit(img, (x, y)) + pygame.draw.circle(screen, BLUE, p, int(pig.radius), 2) + # Draw columns and Beams + for column in columns: + column.draw_poly('columns', screen) + for beam in beams: + beam.draw_poly('beams', screen) + # Update physics + dt = 1.0 / 50.0 / 2. + for x in range(2): + space.step(dt) # make two updates per frame for better stability + # Drawing second part of the sling + rect = pygame.Rect(0, 0, 60, 200) + screen.blit(sling_image, (120, 420), rect) + # Draw score + score_font = bold_font.render("SCORE", 1, WHITE) + number_font = bold_font.render(str(score), 1, WHITE) + screen.blit(score_font, (1060, 90)) + if score == 0: + screen.blit(number_font, (1100, 130)) + else: + screen.blit(number_font, (1060, 130)) + screen.blit(pause_button, (10, 90)) + # Pause option + if game_state == 1: + screen.blit(play_button, (500, 200)) + screen.blit(replay_button, (500, 300)) + draw_level_cleared() + draw_level_failed() + pygame.display.flip() + clock.tick(50) + pygame.display.set_caption("fps: " + str(clock.get_fps())) diff --git a/src/polygon.py b/src/polygon.py index b7e9271..1d0725e 100644 --- a/src/polygon.py +++ b/src/polygon.py @@ -36,23 +36,12 @@ def draw_poly(self, element, screen): ps = list(ps) color = (255, 0, 0) pygame.draw.lines(screen, color, False, ps) - if element == 'beams': - p = poly.body.position - p = Vec2d(self.to_pygame(p)) - angle_degrees = math.degrees(poly.body.angle) + 180 - rotated_logo_img = pygame.transform.rotate(self.beam_image, - angle_degrees) - offset = Vec2d(rotated_logo_img.get_size()) / 2. - p = p - offset - np = p - screen.blit(rotated_logo_img, (np.x, np.y)) - if element == 'columns': - p = poly.body.position - p = Vec2d(self.to_pygame(p)) - angle_degrees = math.degrees(poly.body.angle) + 180 - rotated_logo_img = pygame.transform.rotate(self.column_image, - angle_degrees) - offset = Vec2d(rotated_logo_img.get_size()) / 2. - p = p - offset - np = p - screen.blit(rotated_logo_img, (np.x, np.y)) + p = poly.body.position + p = Vec2d(self.to_pygame(p)) + angle_degrees = math.degrees(poly.body.angle) + 180 + rotated_logo_img = pygame.transform.rotate( + self.beam_image if element == 'beams'else self.column_image, angle_degrees) + offset = Vec2d(rotated_logo_img.get_size()) / 2. + p = p - offset + np = p + screen.blit(rotated_logo_img, (np.x, np.y))