6 Replies - 8139 Views - Last Post: 19 January 2014 - 11:54 AM Rate Topic: -----

#1 GavinDser   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 18-January 14

pygame... bricks breaker

Posted 18 January 2014 - 10:09 PM

I having trouble for bouncing the ball back in the opposite direction when it hits certain side of the bricks. i'm totally new to pygame.... can any one please help me ....


here is my code for the bouncing part, where xBall and yBall are the centre point of my ball, yChecking and xChecking are the upper left hand corner of my bricks. my ball is 6 in radius, and my bricks are 30 in length and 13 in height. also, yDir and xDir is all 1, it is use for make the ball go on the opposite direction.
            if xBall in range(xChecking,xChecking+30) and yBall + 6 in range(yChecking, yChecking + 13) or yBall in range(yChecking + 13, yChecking + 26):
                yDir = -yDir
                print "top or bottom"
                
            else:
                xDir = -xDir
                print "left or right"




if you want to read through the whole code.
#Import & initialize the pygame module
import pygame

#pygame.locals contains constants like MOUSEMOTION and MOUSEBUTTONUP and QUIT for events. #It's easier to type MOUSEBUTTONUP instead of pygame.locals.MOUSEBUTTONUP
from pygame.locals import *  

#This will allow us to name the colours to use rather than give a name  eg (255,0,0)
from pygame.color import THECOLORS

pygame.init()  

#Just like python, we will use os and time
import os, time, random


#Set-up the main screen display window and caption  in the 
size = (640, 480)  
screen = pygame.display.set_mode(size) 

#Puts a caption in the bar at the top of the window
pygame.display.set_caption("Bricks Breaker!") 

# Fills the memory screen surface with colour
#screen.fill((255,255,0))  # Or screen.fill(THECOLORS['yellow']
screen.fill(THECOLORS['white'])
#stores font settings to a variable, myfont
myfont=pygame.font.SysFont("Times New Roman",25)

#Update and refresh the display to end this frame
pygame.display.flip() #<-- refresh the display


redBricks = pygame.Surface((30,13)).convert()
redBricks.fill(THECOLORS['white'])
pygame.draw.rect(redBricks,(THECOLORS['red']),(0,0,30,13))
pygame.draw.rect(redBricks,(THECOLORS['black']),(0,0,30,13),3)


blueBricks = pygame.Surface((30,13)).convert()
blueBricks.fill(THECOLORS['white'])
pygame.draw.rect(blueBricks,(THECOLORS['blue']),(0,0,30,13))
pygame.draw.rect(blueBricks,(THECOLORS['black']),(0,0,30,13),3)

yellowBricks = pygame.Surface((30,13)).convert()
yellowBricks.fill(THECOLORS['white'])
pygame.draw.rect(yellowBricks,(THECOLORS['yellow']),(0,0,30,13))
pygame.draw.rect(yellowBricks,(THECOLORS['black']),(0,0,30,13),3)
# creating surface for block



xBall = 100
yBall = 100
yDir = 1
xDir = 1
speed1 = 5
speed2 = 5

x = 50
y = 440
xClear = x
clearLuanching = x + 30
checking = True
ChangingDir = 0
lives = 3

List1 = []

for xBricks in range(200,650,50):
    yBricks = 40
    List1.append((xBricks,yBricks))


#The game loop
clock = pygame.time.Clock() #<-- used to control the frame rate
keepGoing = True 	    #<-- a 'flag' variable for the game loop condition

while keepGoing:
    clock.tick(30) #<-- Set a constant frame rate, argument is frames per second  
    #Handle any events in the current frame

    keys = pygame.key.get_pressed()

    screen.fill(THECOLORS['white'])

    for eachIndex in range(len(List1)):
        xBricks,yBricks = List1[eachIndex]
        screen.blit(redBricks,(xBricks,yBricks))
    
    for everyBlock in range(len(List1)):
        #print List1
    
        xChecking,yChecking = List1[everyBlock]


        if xBall >= xChecking and xBall <= xChecking + 30 and yBall >= yChecking and yBall <= yChecking + 13:
        
            List1.remove(List1[everyBlock])
##            pygame.draw.rect(screen,(THECOLORS['purple']),(50,yBall,3,3))
##            pygame.draw.rect(screen,(THECOLORS['black']),(50,yChecking,3,3),5)
            print "   "
            print xBall,yBall
            print "    "
            print xChecking,yChecking
##            pygame.display.flip()
##            raw_input()

            
            

            if xBall in range(xChecking,xChecking+30) and yBall + 6 in range(yChecking, yChecking + 13) or yBall in range(yChecking + 13, yChecking + 26):
                yDir = -yDir
                print "top or bottom"
                
            else:
                xDir = -xDir
                print "left or right"


##
##            if xBall in range(xChecking,xChecking+30) and yBall + 6 >= yChecking:
##                yDir = -yDir
##                print "top"
##
##            elif xBall in range(xChecking, xChecking+30) and yBall - 6 <= yChecking+13:
##                yDir = -yDir
##                print "bottom"
##
##            elif yBall in range(yChecking, yChecking+13) and xBall + 6 >= xChecking:
##                xDir = -xDir
##                print "left"
##
##            elif yBall in range(yChecking, yChecking+13) and xBall - 6 <= xChecking + 30:
##                xDir = -xDir
##                print "right"


            break
        
    if checking and lives != 0:
        pygame.draw.rect(screen,(THECOLORS['white']),(xClear,y,65,7))
        pygame.draw.rect(screen,(THECOLORS['black']),(x,y,65,7))
        pygame.draw.rect(screen,(THECOLORS['white']),(x+2,y+2,61,3),1)
        xClear = x

        pygame.draw.circle(screen,(THECOLORS['white']),(clearLuanching,y-6),6,3)        
        pygame.draw.circle(screen,(THECOLORS['black']),(x+30,y-6),6,3)
        clearLuanching = x + 30

        if keys[K_SPACE]:
            xBall = x + 30
            yBall = 440
            checking = False
            pygame.draw.circle(screen,(THECOLORS['white']),(clearLuanching,y-6),6,3)
            
             
            
        
    elif checking == False and lives != 0:
        pygame.draw.circle(screen,(THECOLORS['white']),(xBall,yBall),6,3)
        # change the coordinate of the ball
        xBall = xBall + speed1 * xDir
        yBall = yBall + speed2 * yDir
        # display it
        pygame.draw.circle(screen,(THECOLORS['black']),(xBall,yBall),6,3)
        # find the key that the user 
        keys = pygame.key.get_pressed()


        pygame.draw.rect(screen,(THECOLORS['white']),(xClear,y,65,7))
        pygame.draw.rect(screen,(THECOLORS['black']),(x,y,65,7))
        pygame.draw.rect(screen,(THECOLORS['white']),(x+2,y+2,61,3),1)
        xClear = x

    

        
    if keys[K_LEFT] and x >= 5:
        x = x - 8
        
    if keys[K_RIGHT] and x <= 570:
        x = x + 8

    
    if xBall in range(x,x+65) and yBall == 440:
        yDir = -abs(yDir)
 

        if xBall in range(x,x+65/2):
            speed1 = random.randint(-10,-7)
            speed2 = int(abs(speed1 * 0.75))
            xDir = 1

        else:
            speed1 = random.randint(7,10)
            speed2 = int((speed1 * 0.75))
            xDir = 1
            
            
    if yBall >= 474 and lives != 0 and checking == False:
        lives -= 1
        pygame.draw.circle(screen,(THECOLORS['white']),(xBall,yBall),6,3)
        checking = True

    if lives == 0: 
        screen.fill(THECOLORS['white'])
        GameOverFont = pygame.font.SysFont('Times New Roman',80)
        GameOverText = GameOverFont.render("GAME OVER",True,(THECOLORS['black']))
        screen.blit(GameOverText,(70,160))

    

    
    # displays it
    pygame.display.flip()  
    # if it touches the border


    if xBall >= 634 or xBall <= 6:
        xDir = -xDir
        ChangingDir = 0
        
    elif yBall >= 474 or yBall <= 6:
        yDir = -yDir
        ChangingDir = 1

    else:
        ChangingDir = 2


    
    for ev in pygame.event.get(): 
        if ev.type == QUIT: #<-- this special event type happens when the window is closed
            keepGoing = False


pygame.quit()  # Keep this IDLE friendly


please if any one can help me... this problem get me stuck for the whole week..

This post has been edited by modi123_1: 18 January 2014 - 10:16 PM
Reason for edit:: please use code tags


Is This A Good Question/Topic? 0
  • +

Replies To: pygame... bricks breaker

#2 andrewsw   User is online

  • Unprocessable Entity
  • member icon

Reputation: 6594
  • View blog
  • Posts: 26,833
  • Joined: 12-December 12

Re: pygame... bricks breaker

Posted 18 January 2014 - 10:20 PM

It is late for me so I will just suggest for the moment that you put brackets around (yBall + 6).
Was This Post Helpful? 0
  • +
  • -

#3 GavinDser   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 18-January 14

Re: pygame... bricks breaker

Posted 18 January 2014 - 10:42 PM

um... it still didn't really work...
Was This Post Helpful? 0
  • +
  • -

#4 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 437
  • View blog
  • Posts: 1,410
  • Joined: 27-December 13

Re: pygame... bricks breaker

Posted 19 January 2014 - 03:30 AM

I intruduced two set of brackets in the line 96:

        if xBall >= xChecking and xBall <= (xChecking + 30) and yBall >= yChecking and yBall <= (yChecking + 13):



To me it seems that the code run well.
You should consider controlling the 'bat' by the mouse rather than by right/left arrows - makes the game more involving.

Another issue: I noticed that the ball from time to time gets stuck on the sides of the screen. This is because you first move the ball (ending up outside the screen) and then check for direction change. If you check first and only move the ball to the inside of your screen - this wall-hanging is avoided.
Or check if the ball is outside the screen and move it inside before change of direction. This will create a small graphic inaccuracy - but most people will not notice.
Was This Post Helpful? 1
  • +
  • -

#5 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 437
  • View blog
  • Posts: 1,410
  • Joined: 27-December 13

Re: pygame... bricks breaker

Posted 19 January 2014 - 04:14 AM

Sorry, I ran your code again, and see the problem now.
I'm pretty sure it is the logic in line 111 - missing a set of brackets:

<xxx> and (<yyy> or <zzz>)

or in real code:

            if xBall in range(xChecking,xChecking+30) and (yBall + 6 in range(yChecking, yChecking + 13) or yBall in range(yChecking + 13, yChecking + 26)):



I have checked, and don't see the 'odd' bounce on the bricks anymore.
Was This Post Helpful? 1
  • +
  • -

#6 DK3250   User is offline

  • Pythonian
  • member icon

Reputation: 437
  • View blog
  • Posts: 1,410
  • Joined: 27-December 13

Re: pygame... bricks breaker

Posted 19 January 2014 - 04:55 AM

OK, final correction from me.

You detect collision with brick by checking if ball is inside the brick - but then the code do not know if the hit was from x or y direction.

In the code below, I calculate the distance to all edges of the brick and assume that the lowest value is the entering direction. There is still a risk that a hit very close to a brick corner will give wrong bouncing.

        if xBall >= xChecking and xBall <= (xChecking + 30) and yBall >= yChecking and yBall <= (yChecking + 13):
        
            List1.remove(List1[everyBlock])
            
            dy1 = yBall - yChecking
            dy2 = yChecking + 13 -yBall
            dx1 = xBall - xChecking
            dx2 = xChecking + 30 -xBall

            if min(dy1, dy2, dx1, dx2) in [dy1, dy2]:
                yDir = -yDir
                print "top or bottom"
                
            else:
                xDir = -xDir
                print "left or right"



Sorry for the two wrong postings above - still early Sunday morning in my time zone.
Was This Post Helpful? 2
  • +
  • -

#7 GavinDser   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 7
  • Joined: 18-January 14

Re: pygame... bricks breaker

Posted 19 January 2014 - 11:54 AM

thank you so much!!!!!!!!!!!! it help a lot!!!!!!!!!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1