0
votes

So I am pretty new to Pygame, and I am stuck on how to show the collision between the bird and the Bamboo in the flappy bird game and how to keep running it if it hasn't collided with the bamboo. I haven't written the whole code yet, so please tell me what to write for showing collision(with steps and why is it used? In pygame) and also a source code to display after the collision the screen shows GAME OVER.(optional) (Thanks in advance:)

import pygame
pygame.init()

WINDOWWIDTH = 820
WINDOWHEIGHT = 480
win = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
pygame.display.set_caption("The Flappy Bird Game")

birdload = [pygame.image.load('C:/Users/Vinod/Desktop/Flappy Bird/flapbird.png')]

bgimg = pygame.image.load('C:/Users/Vinod/Desktop/Flappy Bird/bg.jpg')

clock=pygame.time.Clock()

UP = 'up'
DOWN ='down'
LEFT ='left'
RIGHT = 'right'

WHITE =(255, 255, 255)
BLACK = (0, 0 ,0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
DARKGREEN = (0, 155,0)
DARKGRAY = (40, 40, 40)
YELLOW = (255, 255, 0)
ORANGE = (255, 165, 0)
BGCOLOR = BLACK
BROWN = (90, 39, 41)

score = 0



def showstartscreen():
    global BASICFONT, FPS
    FPS = 15
    BASICFONT = pygame.font.Font('freesansbold.ttf', 18)
    titleFont = pygame.font.Font('freesansbold.ttf', 100)
    titleSurf1 = titleFont.render('The Flappy Bird!', True, WHITE, YELLOW)
    titleSurf2 = titleFont.render('The Flappy Bird!', True, ORANGE)
    degrees1 = 0
    degrees2 = 0
    while True:
        win.fill(BGCOLOR)
        rotatedSurf1= pygame.transform.rotate(titleSurf1, degrees1)
        rotatedRect1 = rotatedSurf1.get_rect()
        rotatedRect1.center= (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
        win.blit(rotatedSurf1, rotatedRect1)
        
        rotatedSurf2 = pygame.transform.rotate(titleSurf2, degrees2)
        rotatedRect2 = rotatedSurf2.get_rect()
        rotatedRect2.center = (WINDOWWIDTH / 2, WINDOWHEIGHT / 2)
        win.blit(rotatedSurf2,rotatedRect2)
        
        drawPressKeyMsg()
        
        pygame.display.update()
        clock.tick(FPS)
        degrees1 += 3 #rotate 3 degrees each frame
        degrees2 += 7 #rotate by 7 degrees per frame
        
def drawPressKeyMsg():
    pressKeySurf = BASICFONT.render('Press a key to play.', True, DARKGRAY)
    pressKeyRect = pressKeySurf.get_rect()
    pressKeyRect.topleft = (WINDOWWIDTH - 200, WINDOWHEIGHT - 30)
    win.blit(pressKeySurf, pressKeyRect)
    

def terminate():
    pygame.quit()
    
class bird(object):
    def __init__(self, x, y, width, height, end):
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.end = end
        self.path = [self.x, self.end]
        self.flyCount = 0
        self.vel = 3
        self.hitbox = (self.x + 17, self.y + 2, 31, 57)
        self.visible = True
        
    def draw(self, win):
        if self.flyCount + 1 >= 27:
            self.flyCount = 0

        if not(self.standing):
            win.blit(birdload[self.flyCount//3], (self.x,self.y))
            self.flyCount +=1
        else:
            win.blit(birdload[0], (self.x, self.y))
        self.hitbox = (self.x + 17, self.y + 11, 29, 52)
        #pygame.draw.rect(win, (255,0,0), self.hitbox,2)
        
    def hit(self):
        self.isJump = False
        self.jumpCount = 10
        self.x = 100
        self.y = 410
        self.flyCount = 0
        font1 = pygame.font.SysFont('comicsans', 100)
        text = font1.render('-5', 1, (255,0,0))
        win.blit(text, (250 - (text.get_width()/2),200))
        pygame.display.update()
        i = 0
        while i < 200:
            pygame.time.delay(10)
            i += 1
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    i = 201
                    pygame.quit()
                    
    def fly(self):
        if self.vel > 0:
            if self.x + self.vel < self.path[1]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.flyCount = 0
        else:
            if self.x - self.vel > self.path[0]:
                self.x += self.vel
            else:
                self.vel = self.vel * -1
                self.flyCount = 0
                    
    
def bamboo():
    bamb0 = pygame.draw.rect(win, BROWN,(310, 0, 28, 140))#left, top, width, height
    pygame.display.flip()
    bamb1 = pygame.draw.rect(win, BROWN, (310, 230 , 28, 250))
    pygame.display.flip()
    bamb2 = pygame.draw.rect(win, BROWN,(410, 0, 28, 100))#left, top, width, height
    pygame.display.flip()
    bamb3 = pygame.draw.rect(win, BROWN,(410, 160, 28,320))#left, top, width, height
    pygame.display.flip()
    bamb4 = pygame.draw.rect(win, BROWN,(510, 0, 28,110))#left, top, width, height
    pygame.display.flip()
    bamb5 = pygame.draw.rect(win, BROWN,(510, 180, 28,300))#left, top, width, height
    pygame.display.flip()
    bamb6 = pygame.draw.rect(win, BROWN,(600, 0, 28,240))#left, top, width, height
    pygame.display.flip()
    bamb7 = pygame.draw.rect(win, BROWN,(600, 320, 28,160))#left, top, width, height
    pygame.display.flip()
    bamb8 = pygame.draw.rect(win, BROWN,(700, 0, 28,120))#left, top, width, height
    pygame.display.flip()
    bamb9 = pygame.draw.rect(win, BROWN,(700, 200, 28,280))#left, top, width, height
    pygame.display.flip()
    bamb10 = pygame.draw.rect(win, BROWN,(770, 0, 28,190))#left, top, width, height
    pygame.display.flip()
    bamb11 = pygame.draw.rect(win, BROWN,(770, 250, 28,230))#left, top, width, height
    pygame.display.flip()
    
    
class sticks(object):
    bamboo()
    
    
    def collision():
        if bird.x == sticks.x and bird.y == sticks.y:
            print("Game Over")
            gameover()
            while True:
                if checkForKeyPress():
                    pygame.event.get() # clear event queue
                    return
        else:
            True()

Please refer to the 'def collision' in the 'class sticks' in the last, i know the code i've added is probably wrong... please answer for this part only... Regards, Nishita Thakur.

1
Please answer it as soon as possible.Nishita Thakur
You should only call pygame.display.flip once.user12291970

1 Answers

1
votes

When an object is designed, typically it's for a single object, say "Tree", not "Forest", because a forest is a group of trees. You're going the right direction already with the sticks class, but then use a function named bamboo() to know their locations, and draw all of them.

What would make your code easier to use, is to combine these two together, so that a single object is responsible for the location, drawing and collision of each stick of bamboo. Multiple objects are grouped together for easy access in a Python "container" data structure, say a list.

First let's make a new Bamboo:

class Bamboo:

    def __init__( self, x, y, width, height ):
        self.image  = pygame.Surface( ( width, height ) )
        self.rect   = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y
        # currently the image is a brown rectangle
        self.image.fill( BROWN )
        
    def draw( self, surface ):
        surface.blit( self.image, self.rect )
        
    def move( self, dx, dy ):
        self.rect.move_ip( dx, dy )
        
    def collidesWith( self, other_rect ):
        result = self.rect.colliderect( other_rect )
        return result

Here everything about a Bamboo entity is contained within the Bamboo object. Because this object knows everything about itself (and nothing else), it's easy to implement the collidesWith() function, the drawing, etc.

But how do we create all these sticks of bamboo - a loop filling a list.

### Create the list of Bamboo            
all_bamboo = []     # list to hold the final objects

# List of initial locations and sizes
initial_locs = [ (310, 0, 28, 140),  (310, 230 , 28, 250), (410, 0, 28, 100),
                 (410, 160, 28,320), (510, 0, 28,110),     (510, 180, 28,300),
                 (600, 0, 28,240),   (600, 320, 28,160),   (700, 0, 28,120),
                 (700, 200, 28,280), (770, 0, 28,190),     (770, 250, 28,230) ]
                 
# loop through the locations, making Bamboo, appending to list                 
for location in initial_locs:
    x, y, width, height = location                  # unpack location
    new_bamboo = Bamboo( x, y, width, height )      # create a Bamboo
    all_bamboo.append( new_bamboo )                 # move to list

So now you have all your Bamboo objects created, and moved into a list named all_bamboo. With everything in a list it makes it trivial to draw, move and check collisions.

You don't show your main loop function in the question, so I'll make my own:

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            pass   # TODO - handle mouse-clicks
        elif ( event.type == pygame.KEYUP ):
            pass   # TODO - handle player-input

    ### Update the window
    window.fill( WHITE )         # fill the background

    # draw the sprites
    player_bird.draw( window )   # draw player

    for bamboo in all_bamboo:    # draw all bamboo
        bamboo.draw( screen )

    pygame.display.flip()        # send the updates to the screen

    ### Check for collisions & move bamboo
    bird_rect = pygame.Rect( bird.hitbox )        # location of bird
    for bamboo in all_bamboo:                     # for each stick of bamboo
        if ( bamboo.collidesWith( bird_rect ) ):  # does it collide?
            # Bird hit bamboo, now what?
            bird.hit()                            # ouch!
        
        # move the bamboo 1 pixel left
        # so it looks like the bird moves forward
        bamboo.move( -1, 0 )

    clock.tick(60)

pygame.quit()

Any time you find yourself needing a group of items, (clouds maybe) think of a single object representing a single entity, and then container data structure to hold them all.

So when you find yourself adding code to the object that isn't really part of it's core, say for example: adding a "game over" clause to the collidesWith() function, you can ask yourself "Is drawing a Game Over screen really the responsibility of a stick of bamboo?!" These thoughts can hold to a good design. This helps prevent spaghetti-code with poorly positioned logic in irrelevant locations.

NOTE: the above is not tested, debugged code. Errors and omissions should be expected.