Reputation: 8 Worker
- Active Posts:
- 42 (0.02 per day)
- 26-April 09
- Profile Views:
- Last Active:
- Nov 14 2013 09:29 AM
- Dream Kudos:
Posts I've Made
Posted 6 Sep 2013To add on to that explanation above, with the code you have posted, your code runs line by line. Once it reaches that function call, it doesn't recognize the function because it did not reach that line where the function is created, which happens after you try to call it. Like this link. If you step through it, you realize what is going on. It would technically work if the call happened after the program had reached that line and created a pointer to location of the function definition, like in this example.
If you have everything in a function, the program will run line by line, but in a different sense. It will go from top to bottom and point to where each function is defined, but will only execute (explore the contents of the function) the function if it is called. In the case of this last example if newFunction() was not called on the last line of the program, the program would just contain pointers to the functions but would not execute anything because none of the functions were called. Then from there, newFunction() calls the other function on line 7.
Posted 2 Sep 2013@baavgai: Thank you for your response. Wish I saw it earlier. You're right though, objects would be better suited for this. I was doing it exactly as the assignment requirements at that time (using functions), but as I realized I needed more functions to do things, I started to wonder if OOP would be better suited for this.
In your 'code sketch' we would have a class that bridges the ball class and square class together. From there, the square objects would still get pushed into a list, and that's what gets passed in the Square class and also in methods like isInsideSquare(), correct?
Since I didn't see your response until now, I managed to get a little further on the ball collision logic. I think it's significantly better now, and if I stopped right now I would feel pretty okay. Sometimes the balls would get pushed out of bounds by the other ball because I created a while loop inside of the collision detection function but couldn't wrap my mind around creating another function to do that check. Then I realized it would be more efficient if I could reuse that hypothetical function for the two if statements in simul() that check for collision at the bounds of the screen. I left the black box thing alone, but figured it was almost the same as the while loop in the hasCollided() function. Then I realized that I would have to consider the balls going out of bounds based on the original direction of the ball relative to the location of the black box and whether it's at a corner. I think I might call it quits, but I wouldn't mind an explanation on what I could have done for the case of screen bound checking + the while loop and the black box (balls still getting stuck and jiggling) OOP or not is fine.
I edited the "if boolVal == True" statement in simul based on the changes I made in the "if (dist <= (r1 + r2)):" statement until the end of that function. I created a function called "isSameSign()" and attempted to do something with another function called "isInBounds()".
from graphics import * from math import * import random W = 300 H = 300 ballList =  squareList =  #---------------------------------------------------------------- def simul(win, ballList): for step in range( 200 ): for i in range(len(ballList)): c, dx, dy = ballList[i] x = c.getCenter().getX() y = c.getCenter().getY() r = c.getRadius() if (x <= 0 + r ) or (x >= W - r): dx = -dx if (y <= 0 + r) or(y >= H - r): dy = -dy # stop the ball's movement if isInSquare(x, y, r): dx = 0 dy = 0 # make it bounce off the black box's bounds if hitBlackBox(x, y, r): dx = -dx dy = -dy (boolVal, ball1, ball2) = hasCollided(ballList) # create a tuple if boolVal == True: # change the dx and dy of each ball that satisfies condition # then reverse the dx, dy of collided balls c1, dx1, dy1 = ball1 c2, dx2, dy2 = ball2 # replace old ballList values with current ballList values for list in ballList: if ball1 in list: list.pop(1) list.insert(1, dx1) list.pop(2) list.insert(2, dy1) if ball2 in list: list.pop(1) list.insert(1, dx2) list.pop(2) list.insert(2, dy2) c1.move(dx1, dy1) c2.move(dx2, dy2) else: c.move(dx, dy) ballList[ i ] = [ c, dx, dy ] # update ball values if allInBoxes(ballList): end(win) def allInBoxes(ballList): counter = 0 for i in range(len(ballList)): c, dx, dy = ballList[i] if (dy == dx == 0): counter += 1 if counter == len(ballList): return True return False def hasCollided(ballList): newBallList =  for i in range(len(ballList)-1): for j in range(i+1, len(ballList)): c1 = ballList[i] c2 = ballList[j] # get the dx1-2, dy1-2 vals dx1 = ballList[i] dy1 = ballList[i] dx2 = ballList[j] dy2 = ballList[j] # get radius of i and j balls r1 = c1.getRadius() r2 = c2.getRadius() # now get the points P1 = Point(c1.getCenter().getX(), c1.getCenter().getY()) P2 = Point(c2.getCenter().getX(), c2.getCenter().getY()) #print "(", P1.getX(), ",",P1.getY(),")", "(" , P2.getX() , ",",P2.getY(),")", "This is P1, P2" dist = distance(P1, P2) if (dist <= (r1 + r2)): if isSameSign(dx1, dx2): # push away one ball if sign's same dx1 = -dx1 elif isSameSign(dy1, dy2): dy1 = -dy1 else: # assume opposing sign, intend to push away each ball dx1 = -dx1 dy1 = -dy1 dx2 = -dx2 dy2 = -dy2 while (dist <= (r1 + r2)): c1.move(dx1, dy1) c2.move(dx2, dy2) P1 = Point(c1.getCenter().getX(), c1.getCenter().getY()) P2 = Point(c2.getCenter().getX(), c2.getCenter().getY()) dist = distance(P1, P2) # call again, get updated points newBallList.append([c1, dx1, dy1]) newBallList.append([c2, dx2, dy2]) return True, newBallList, newBallList return False, 0, 0 def distance(P1, P2): return sqrt( pow( P1.getX() - P2.getX(), 2 ) + pow( P1.getY() - P2.getY(), 2 )) def isSameSign(a, B)/>/>/>/>: # check if both signs are same if ((a < 0) and (b < 0)) or ((a > 0) and (b > 0)): return True # Complete but incomplete concept (not implemented): # This function is to assist the while loop in the collision check # to ensure the balls don't knock each other out of the screen. # I was going to integrate this in the while loop above and # find the ball that is not closest to the bounds and push # that one in the opposite direction, then bounce the other one. # I've been working on this program for a few days, I think it's better # to do something else now, so I'll leave this incomplete. def isInBounds(c1, c2): boundsList =  boundsList.append(c1) boundsList.append(c2) for i in range(len(boundsList)): r = boundsList[i].getRadius() x = boundsList[i].getCenter().getX() y = boundsList[i].getCenter().getY() if ((x <= 0 + r ) or (x >= W - r)) or ((y <= 0 + r) or(y >= H - r)): return False return True def isInSquare(x, y, r): for i in range(len(squareList)-1): # exclude black box sP1 = squareList[i].getP1() # (bOriginX, bOriginY) sP2 = squareList[i].getP2() # (bW, bH) if (sP2.getX() - r >= x >= sP1.getX() + r) and (sP2.getY() - r >= y >= sP1.getY() + r): return True # Another complete but incomplete concept. # I was going to do make the code push out # any balls that are already inside/go inside the black box. # It's pretty much like the while loop, but I think it's better # to move on. On to another project! def hitBlackBox(x, y, r): # get last box blackBox = squareList[-1] sP1 = blackBox.getP1() # (bOriginX, bOriginY) | square P1 sP2 = blackBox.getP2() # (bW, bH) | square P2 if (sP2.getX() + r >= x >= sP1.getX() - r) and (sP2.getY() + r >= y >= sP1.getY() - r): return True def drawSquare(win): for i in range(4): # create 3 white boxes with random coords bOriginX = random.randrange(0, W-50, 51) bOriginY = random.randrange(0, H-100, 51) bW = bOriginX + 50 # you have to include origin + width therefore 100-50 = 50 sBoxW bH = bOriginY + 50 square = Rectangle(Point(bOriginX, bOriginY), Point(bW, bH)) square.draw(win) square.setFill("white") squareList.append(square) squareList[-1].setFill("black") # Fill last square drawn with black # this commented portion can work too, remove the previous line, set loop range(3) ## blackSquare = Rectangle(Point(H-50,W-50), Point((W-50)+50, (H-50)+ 50)) ## blackSquare.draw(win) ## blackSquare.setFill("black") ## squareList.append(blackSquare) # ------------------------------------------- def end(win): waitForClick( win, "Click to End" ) win.close() #---------------------------------------------------------------- def waitForClick( win, message ): """ waitForClick: stops the GUI and displays a message. Returns when the user clicks the window. The message is erased.""" # wait for user to click mouse to start startMsg = Text( Point( win.getWidth()/2, win.getHeight()/2 ), message ) startMsg.draw( win ) # display message win.getMouse() # wait startMsg.undraw() # erase #---------------------------------------------------------------- def main(): win = GraphWin( "moving ball", W, H ) #--- define a ball position and velocity --- drawSquare(win) ballColor = ["red", "blue", "pink", "purple", "green"] for i in range(5): c = Circle( Point( random.randrange( 16, W-15, 20 ), random.randrange( H/3, 2*H/3, 20 ) ), 15 ) c.setFill(ballColor[i%len(ballColor)]) c.draw(win) ballList.append([c, 5 - random.randrange(10), 5 - random.randrange(10)]) for i in range(len(ballList)): # loop: no ball should be 0 dx and 0 dy if ballList[i] == ballList[i] == 0: ballList[i] == 1 waitForClick( win, "Click to Start" ) simul(win, ballList) end(win) main()
@woooee: I think I understand what you're talking about. I would have thought with the same distance formula it wouldn't make a difference unless you mean making the ball move based on its initial direction before the collision call changes the direction to -dx, -dy.
- Member Title:
- New D.I.C Head
- Age Unknown
- Birthday Unknown