import pygame
import random
import sys

VIRTUAL_WIDTH = 400
VIRTUAL_HEIGHT = 600
FPS = 60
GRAVITY = 0.15
JUMP_STRENGTH = -4
PIPE_SPEED = 2.5
PIPE_SPAWN_TIME = 1500
GAP_SIZE = 160

class Bird:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.velocity = 0
        self.angle = 0
        
        self.original_image = pygame.Surface((40, 30), pygame.SRCALPHA)
        pygame.draw.ellipse(self.original_image, (255, 215, 0), (0, 0, 40, 30))
        pygame.draw.circle(self.original_image, (255, 255, 255), (28, 10), 8)
        pygame.draw.circle(self.original_image, (0, 0, 0), (30, 10), 3)
        pygame.draw.ellipse(self.original_image, (255, 255, 200), (5, 15, 20, 10))
        pygame.draw.polygon(self.original_image, (255, 140, 0), [(32, 18), (40, 22), (32, 26)])
        
        self.image = self.original_image
        self.rect = self.image.get_rect(center=(self.x, self.y))
        
        self.mask = pygame.mask.from_surface(self.image)

    def jump(self):
        self.velocity = JUMP_STRENGTH
        self.angle = 20 

    def move(self):
        self.velocity += GRAVITY
        self.y += self.velocity
        
        if self.velocity < 0:
            self.angle = 25
        else:
            if self.angle > -90:
                self.angle -= 2 

    def draw(self, surface):
        rotated_image = pygame.transform.rotate(self.original_image, self.angle)
        new_rect = rotated_image.get_rect(center=(self.x, int(self.y)))
        
        self.rect = new_rect
        self.mask = pygame.mask.from_surface(rotated_image)
        surface.blit(rotated_image, new_rect.topleft)

class Pipe:
    def __init__(self, x):
        self.x = x
        self.w = 60
        self.cap_h = 30
        self.passed = False
        self.height = random.randint(150, VIRTUAL_HEIGHT - 200)

        self.top_rect = pygame.Rect(self.x, 0, self.w, self.height - GAP_SIZE)
        self.bot_rect = pygame.Rect(self.x, self.height, self.w, VIRTUAL_HEIGHT - self.height)
        
        self.top_surf = pygame.Surface((self.w, self.height - GAP_SIZE), pygame.SRCALPHA)
        self.top_surf.fill((34, 139, 34))
        self.top_mask = pygame.mask.from_surface(self.top_surf)
        
        self.bot_surf = pygame.Surface((self.w, VIRTUAL_HEIGHT - self.height), pygame.SRCALPHA)
        self.bot_surf.fill((34, 139, 34))
        self.bot_mask = pygame.mask.from_surface(self.bot_surf)

    def move(self):
        self.x -= PIPE_SPEED
        self.top_rect.x = int(self.x)
        self.bot_rect.x = int(self.x)

    def draw(self, surface):
        green = (34, 139, 34)
        dark_green = (0, 100, 0)
        
        pygame.draw.rect(surface, green, self.top_rect)
        pygame.draw.rect(surface, dark_green, self.top_rect, 3) 
        cap_rect_top = pygame.Rect(self.x - 4, self.top_rect.bottom - self.cap_h, self.w + 8, self.cap_h)
        pygame.draw.rect(surface, green, cap_rect_top)
        pygame.draw.rect(surface, dark_green, cap_rect_top, 3)

        pygame.draw.rect(surface, green, self.bot_rect)
        pygame.draw.rect(surface, dark_green, self.bot_rect, 3) 
        cap_rect_bot = pygame.Rect(self.x - 4, self.bot_rect.top, self.w + 8, self.cap_h)
        pygame.draw.rect(surface, green, cap_rect_bot)
        pygame.draw.rect(surface, dark_green, cap_rect_bot, 3)

class Ground:
    def __init__(self):
        self.x = 0
        self.height = 100
        self.y = VIRTUAL_HEIGHT - self.height
        self.image = pygame.Surface((VIRTUAL_WIDTH + 50, self.height))
        self.image.fill((222, 184, 135)) 
        for i in range(0, VIRTUAL_WIDTH + 50, 20):
            pygame.draw.line(self.image, (100, 200, 100), (i, 0), (i+10, 20), 3)
            
    def move(self):
        self.x -= PIPE_SPEED
        if self.x <= -20:
            self.x = 0
            
    def draw(self, surface):
        surface.blit(self.image, (self.x, self.y))
        pygame.draw.line(surface, (0,100,0), (0, self.y), (VIRTUAL_WIDTH, self.y), 4)

class RealisticGame:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((VIRTUAL_WIDTH, VIRTUAL_HEIGHT), pygame.RESIZABLE)
        pygame.display.set_caption("Realistic Flappy Bird")
        self.virtual_surface = pygame.Surface((VIRTUAL_WIDTH, VIRTUAL_HEIGHT))
        self.clock = pygame.time.Clock()
        self.font = pygame.font.SysFont('Arial Black', 24)
        self.reset_game()

    def reset_game(self):
        self.bird = Bird(60, VIRTUAL_HEIGHT // 2)
        self.pipes = []
        self.ground = Ground()
        self.score = 0
        self.last_pipe_time = pygame.time.get_ticks()
        self.active = True

    def run(self):
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit(); sys.exit()
                if event.type == pygame.VIDEORESIZE:
                    self.screen = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
                
                if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                    if self.active:
                        self.bird.jump()
                    else:
                        self.reset_game()

            if self.active:
                self.bird.move()
                self.ground.move()
                
                if pygame.time.get_ticks() - self.last_pipe_time > PIPE_SPAWN_TIME:
                    self.pipes.append(Pipe(VIRTUAL_WIDTH + 20))
                    self.last_pipe_time = pygame.time.get_ticks()

                for pipe in self.pipes:
                    pipe.move()
                    
                    top_offset = (pipe.top_rect.x - self.bird.rect.x, pipe.top_rect.y - self.bird.rect.y)
                    bot_offset = (pipe.bot_rect.x - self.bird.rect.x, pipe.bot_rect.y - self.bird.rect.y)
                    
                    if self.bird.mask.overlap(pipe.top_mask, top_offset) or \
                       self.bird.mask.overlap(pipe.bot_mask, bot_offset):
                        self.active = False
                    
                    if not pipe.passed and pipe.x < self.bird.x:
                        self.score += 1
                        pipe.passed = True
                
                if self.bird.y >= VIRTUAL_HEIGHT - 100:
                    self.active = False
                
                self.pipes = [p for p in self.pipes if p.x > -100]

            self.virtual_surface.fill((135, 206, 235)) 
            
            for pipe in self.pipes:
                pipe.draw(self.virtual_surface)
            
            self.ground.draw(self.virtual_surface)
            self.bird.draw(self.virtual_surface)
            
            score_surf = self.font.render(f"{self.score}", True, (255, 255, 255))
            shadow_surf = self.font.render(f"{self.score}", True, (0, 0, 0))
            self.virtual_surface.blit(shadow_surf, (17, 17))
            self.virtual_surface.blit(score_surf, (15, 15))

            if not self.active:
                msg1 = self.font.render("CRASHED!", True, (255, 50, 50))
                msg2 = self.font.render("PRESS SPACE TO RESTART", True, (255, 50, 50))
                rect1 = msg1.get_rect(center=(VIRTUAL_WIDTH//2, VIRTUAL_HEIGHT//2 - 20))
                rect2 = msg2.get_rect(center=(VIRTUAL_WIDTH//2, VIRTUAL_HEIGHT//2 + 20))
                self.virtual_surface.blit(msg1, rect1)
                self.virtual_surface.blit(msg2, rect2)

            scaled = pygame.transform.scale(self.virtual_surface, self.screen.get_size())
            self.screen.blit(scaled, (0, 0))
            pygame.display.flip()
            self.clock.tick(FPS)
RealisticGame().run()