def main(): pygame.init() SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCALE = 80 # pixels per meter WIDTH = SCREEN_WIDTH/SCALE HEIGHT = SCREEN_HEIGHT/SCALE SCREEN_CENTRE = Point(WIDTH/2, HEIGHT/2) CENTRE = SCREEN_CENTRE/SCALE DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) CLOCK = pygame.time.Clock() totalTime = 0 GRAVITY = 9.81 helper = Helper(DISPLAY, SCALE, WIDTH, HEIGHT) drawPos = helper.drawPos worldPos = helper.worldPos drawVector = helper.drawVector personImage = pygame.image.load(os.getcwd()+"/person.jpg") personRect = personImage.get_rect() personImage = pygame.transform.scale(personImage, (int(personRect.width*(int(1.8*SCALE)/personRect.height)), int(1.8*SCALE))) moveData = { "lastPos": Point(), "currentPos": Point(CENTRE.x, 0), "lastScreenMousePos": Point(), "mouseHeld": False, "lastVelocity": Vector() } mouseVelocity = Vector() mouseBall = Ball() mouseBall.moveable = False tickerPoints = [] MAX_TICKER_POINTS = 100 TICKER_PERIOD = 0.02 timeSinceLastTicker = 0 ball = Ball() ball.setPos(Point(WIDTH/2, HEIGHT/2)) string = String() string.setConnections(mouseBall, ball) string.active = False while True: DISPLAY.fill(WHITE) deltaT = CLOCK.get_time()/1000 totalTime += deltaT moveData["lastPos"] = Point(moveData["currentPos"]) if not moveData["lastScreenMousePos"] == Point(pygame.mouse.get_pos()): moveData["currentPos"] = Point(worldPos(Point(pygame.mouse.get_pos()))) moveData["lastScreenMousePos"] = Point(pygame.mouse.get_pos()) heldKeys = pygame.key.get_pressed() for e in pygame.event.get(): if e.type == pygame.QUIT: pygame.quit() elif e.type == pygame.KEYDOWN: heldKeys = pygame.key.get_pressed() if (heldKeys[pygame.K_RCTRL] or heldKeys[pygame.K_LCTRL]) and\ (heldKeys[pygame.K_w] or heldKeys[pygame.K_q]): pygame.quit() if (heldKeys[pygame.K_SPACE]): mouseBallDist = moveData["currentPos"].distance(ball.pos) if mouseBallDist > 0: string.toggle() string.length = mouseBallDist elif e.type == pygame.MOUSEBUTTONDOWN: if e.button == 1: moveData["mouseHeld"] = True elif e.type == pygame.MOUSEBUTTONUP: if e.button == 1: moveData["mouseHeld"] = False keyboardMoveSpeed = 1 if heldKeys[pygame.K_a]: moveData["currentPos"] = moveData["currentPos"] - Point(keyboardMoveSpeed*deltaT, 0) elif heldKeys[pygame.K_d]: moveData["currentPos"] = moveData["currentPos"] + Point(keyboardMoveSpeed*deltaT, 0) if heldKeys[pygame.K_w]: moveData["currentPos"] = moveData["currentPos"] + Point(0, keyboardMoveSpeed*deltaT) elif heldKeys[pygame.K_s]: moveData["currentPos"] = moveData["currentPos"] - Point(0, keyboardMoveSpeed*deltaT) if deltaT > 0: moveData["lastVelocity"] = Vector(mouseBall.velocity) mouseVelocity = Vector(((moveData["currentPos"]-moveData["lastPos"])/deltaT).pos()) mouseAcceleration = (mouseVelocity - moveData["lastVelocity"])/deltaT else: mouseVelocity = Vector() mouseAcceleration = Vector() mouseBall.setPos(moveData["currentPos"]) mouseBall.setVelocity(mouseVelocity) #gravity adjustment if heldKeys[pygame.K_i]: GRAVITY = min(30.0,GRAVITY+0.1) elif heldKeys[pygame.K_k]: GRAVITY = max(0.0,GRAVITY-0.1) #ball radius if heldKeys[pygame.K_o]: ball.radius = min(4.0,ball.radius+0.01) elif heldKeys[pygame.K_l]: ball.radius = max(0.1,ball.radius-0.01) #string length if heldKeys[pygame.K_u]: string.length = min(8.0,string.length+0.01) elif heldKeys[pygame.K_j]: string.length = max(0.01,string.length-0.01) #reset all if heldKeys[pygame.K_r]: GRAVITY = 9.81 ball.radius = 0.1 string.length = 2.0 if ball.bottom <= 0: if ball.velocity.y < 0: ball.accelerate(Vector((0, -ball.velocity.y-ball.velocity.y*ball.cor))) else: ball.accelerate(Vector((0, -GRAVITY))*deltaT) #print(ball.velocity) if ball.left <= 0: if ball.velocity.x < 0: ball.accelerate(Vector((-ball.velocity.x-ball.velocity.x*ball.cor, 0))) if ball.right >= WIDTH: if ball.velocity.x > 0: ball.accelerate(Vector((-ball.velocity.x-ball.velocity.x*ball.cor, 0))) string.applyTension(deltaT) if moveData["mouseHeld"]: ball.setPos(moveData["currentPos"]) ball.setVelocity(mouseBall.velocity) ball.setInEquilibrium() else: ball.move(deltaT) string.correctPositions() # === DRAW # draw person DISPLAY.blit(personImage, (-(1/3)*personImage.get_rect().width, SCREEN_HEIGHT-personImage.get_rect().height)) # draw ticker tape if not moveData["mouseHeld"]: timeSinceLastTicker += deltaT if timeSinceLastTicker >= TICKER_PERIOD: tickerPoints.append(Point(ball.pos)) if len(tickerPoints) > MAX_TICKER_POINTS: del tickerPoints[0] timeSinceLastTicker = 0 else: tickerPoints = [] for p in tickerPoints: pygame.draw.circle(DISPLAY, BLUE, drawPos(p), 2, 2) # draw mouse velocity vector drawVector(mouseBall.velocity, moveData["currentPos"], 20, False, BLUE) # velocity vector is scaled so it can be more easily comprehended drawVector(ball.velocity, ball.pos, 10, False, GREEN, 1) # draw ball pygame.draw.circle(DISPLAY, RED, drawPos(ball.pos), int(ball.radius*SCALE), 1) if string.active: pygame.draw.line(DISPLAY, GREEN, drawPos(ball.pos), drawPos(moveData["currentPos"]), 1) font = pygame.font.SysFont("monospace", 15) # render text fps = font.render("{}fps".format(int(CLOCK.get_fps())), 1, BLACK) DISPLAY.blit(fps, (10, 10)) ballVelLabel = font.render("Ball velocity: {:.2f}ms-1".format(ball.velocity.mag), 1, BLACK) DISPLAY.blit(ballVelLabel, (10, 30)) mouseVelLabel = font.render("Mouse velocity: {:.2f}ms-1".format(mouseBall.velocity.mag), 1, BLACK) DISPLAY.blit(mouseVelLabel, (10, 50)) gravityVelLabel = font.render("Gravity: {:.2f}ms-2".format(GRAVITY), 1, BLACK) DISPLAY.blit(gravityVelLabel, (10, 70)) diameterVelLabel = font.render("Ball diameter: {:.2f}m".format(ball.radius*2), 1, BLACK) DISPLAY.blit(diameterVelLabel, (10, 90)) stringVelLabel = font.render("String length: {:.2f}m".format(string.length), 1, BLACK) DISPLAY.blit(stringVelLabel, (10, 110)) #control prompts stringConnect = font.render("Connect string: SPACE", 1, BLACK) DISPLAY.blit(stringConnect, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 10)) stringControl = font.render("String length +/-: U/J", 1, BLACK) DISPLAY.blit(stringControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 30)) gravityControl = font.render("Gravity +/-: I/K", 1, BLACK) DISPLAY.blit(gravityControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 50)) diameterControl = font.render("Ball diameter +/-: O/L", 1, BLACK) DISPLAY.blit(diameterControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 70)) resetAllControl = font.render("Reset all: R", 1, BLACK) DISPLAY.blit(resetAllControl, (SCREEN_WIDTH-stringConnect.get_rect().width-10, 90)) pygame.display.update() CLOCK.tick(120)
def main(): pygame.init() SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 SCALE = 80 # pixels per meter WIDTH = SCREEN_WIDTH / SCALE HEIGHT = SCREEN_HEIGHT / SCALE SCREEN_CENTRE = Point(WIDTH / 2, HEIGHT / 2) CENTRE = SCREEN_CENTRE / SCALE DISPLAY = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) CLOCK = pygame.time.Clock() totalTime = 0 GRAVITY = 9.81 helper = Helper(DISPLAY, SCALE, WIDTH, HEIGHT) drawPos = helper.drawPos worldPos = helper.worldPos drawVector = helper.drawVector personImage = pygame.image.load(os.getcwd() + "/person.jpg") personRect = personImage.get_rect() personImage = pygame.transform.scale( personImage, (int(personRect.width * (int(1.8 * SCALE) / personRect.height)), int(1.8 * SCALE))) moveData = { "lastPos": Point(), "currentPos": Point(CENTRE.x, 0), "lastScreenMousePos": Point(), "mouseHeld": False, "lastVelocity": Vector() } mouseVelocity = Vector() tickerPoints = [] MAX_TICKER_POINTS = 100 TICKER_PERIOD = 0.02 timeSinceLastTicker = 0 mouseBall = Ball() mouseBall.moveable = False ball = Ball() ball.setPos(Point(WIDTH / 2, HEIGHT / 2)) balls = [ball] ballMouseString = String() ballMouseString.setConnections(mouseBall, ball) ballMouseString.active = True size = 1 ballMouseString.length = size strings = [ballMouseString] for i in range(1): a = Ball() a.setPos(Point(WIDTH / 2, HEIGHT / 4)) balls.append(a) st = String() st.setConnections(balls[i], balls[i + 1]) st.length = size st.active = True strings.append(st) drawBalls = True print(len(balls)) print(len(strings)) '''ball2 = Ball() ball2.setPos(Point(WIDTH/2, HEIGHT/4)) #ball2.mass = 0.5 balls.append(ball2) ball3 = Ball() ball3.setPos(Point(WIDTH/2, HEIGHT/4)) #ball3.mass = 1 balls.append(ball3)''' '''ballString1 = String() ballString1.setConnections(ball, ball2) ballString1.length = 1 ballString1.active = True ballString2 = String() ballString2.setConnections(ball2, ball3) ballString2.length = 1 ballString2.active = True strings = [ballMouseString, ballString1, ballString2]''' while True: DISPLAY.fill(WHITE) deltaT = CLOCK.get_time() / 1000 totalTime += deltaT moveData["lastPos"] = Point(moveData["currentPos"]) if not moveData["lastScreenMousePos"] == Point(pygame.mouse.get_pos()): moveData["currentPos"] = Point( worldPos(Point(pygame.mouse.get_pos()))) moveData["lastScreenMousePos"] = Point(pygame.mouse.get_pos()) heldKeys = pygame.key.get_pressed() for e in pygame.event.get(): if e.type == pygame.QUIT: pygame.quit() elif e.type == pygame.KEYDOWN: heldKeys = pygame.key.get_pressed() if (heldKeys[pygame.K_RCTRL] or heldKeys[pygame.K_LCTRL]) and\ (heldKeys[pygame.K_w] or heldKeys[pygame.K_q]): pygame.quit() if (heldKeys[pygame.K_SPACE]): mouseBallDist = moveData["currentPos"].distance( balls[0].pos) if mouseBallDist > 0: strings[0].length = mouseBallDist strings[0].toggle() elif e.type == pygame.MOUSEBUTTONDOWN: if e.button == 1: moveData["mouseHeld"] = True elif e.type == pygame.MOUSEBUTTONUP: if e.button == 1: moveData["mouseHeld"] = False keyboardMoveSpeed = 1 if heldKeys[pygame.K_a]: moveData["currentPos"] = moveData["currentPos"] - Point( keyboardMoveSpeed * deltaT, 0) elif heldKeys[pygame.K_d]: moveData["currentPos"] = moveData["currentPos"] + Point( keyboardMoveSpeed * deltaT, 0) if heldKeys[pygame.K_w]: moveData["currentPos"] = moveData["currentPos"] + Point( 0, keyboardMoveSpeed * deltaT) elif heldKeys[pygame.K_s]: moveData["currentPos"] = moveData["currentPos"] - Point( 0, keyboardMoveSpeed * deltaT) if deltaT > 0: moveData["lastVelocity"] = Vector(mouseVelocity) mouseVelocity = Vector( ((moveData["currentPos"] - moveData["lastPos"]) / deltaT).pos()) mouseAcceleration = (mouseVelocity - moveData["lastVelocity"]) / deltaT else: mouseVelocity = Vector() mouseAcceleration = Vector() mouseBall.setVelocity(mouseVelocity) mouseBall.setPos(moveData["currentPos"]) for i in range(len(balls)): b = balls[i] if b.bottom <= 0: if b.velocity.y < 0: b.accelerate( Vector((0, -b.velocity.y - b.velocity.y * b.cor))) else: b.accelerate(Vector((0, -GRAVITY)) * deltaT) if b.left <= 0: if b.velocity.x < 0: ball.accelerate( Vector((-b.velocity.x - b.velocity.x * b.cor, 0))) if b.right >= WIDTH: if b.velocity.x > 0: ball.accelerate( Vector((-b.velocity.x - b.velocity.x * b.cor, 0))) for s in strings: s.applyTension(deltaT) #drawVector(s.applyTension(), s.connections[1].pos, 1) if moveData["mouseHeld"]: balls[0].setPos(mouseBall.pos) balls[0].setVelocity(mouseBall.velocity) balls[0].setInEquilibrium() balls[0].moveable = False else: balls[0].moveable = True for i in range(len(balls)): if i == 0 and moveData["mouseHeld"]: continue b = balls[i] b.move(deltaT) if b.velocity.mag > 10000: b.velocity = Vector() for s in strings: s.correctPositions() # === DRAW # draw person DISPLAY.blit(personImage, (-(1 / 3) * personImage.get_rect().width, SCREEN_HEIGHT - personImage.get_rect().height)) # draw ticker tape if not moveData["mouseHeld"] and False: timeSinceLastTicker += deltaT if timeSinceLastTicker >= TICKER_PERIOD: tickerPoints.append(Point(ball.pos)) if len(tickerPoints) > MAX_TICKER_POINTS: del tickerPoints[0] timeSinceLastTicker = 0 else: tickerPoints = [] for p in tickerPoints: pygame.draw.circle(DISPLAY, BLUE, drawPos(p), 2, 2) # draw mouse velocity vector drawVector(mouseBall.velocity, mouseBall.pos, 20, False, BLUE) # velocity vector is scaled so it can be more easily comprehended for b in balls: if not drawBalls: break drawVector(b.velocity, b.pos, 10, False, GREEN, 1) # draw ball for b in balls: if not drawBalls: break pygame.draw.circle(DISPLAY, RED, drawPos(b.pos), int(ball.radius * SCALE), 1) for s in strings: if s.active: pygame.draw.line(DISPLAY, GREEN, drawPos(s.connections[0].pos), drawPos(s.connections[1].pos), 1) font = pygame.font.SysFont("monospace", 15) # render text fps = font.render("{}fps".format(int(CLOCK.get_fps())), 1, BLACK) DISPLAY.blit(fps, (10, 10)) ballVelLabel = font.render( "Ball velocity: {:.2f}ms-1".format(ball.velocity.mag), 1, BLACK) DISPLAY.blit(ballVelLabel, (10, 30)) mouseVelLabel = font.render( "Mouse velocity: {:.2f}ms-1".format(mouseVelocity.mag), 1, BLACK) DISPLAY.blit(mouseVelLabel, (10, 50)) pygame.display.update() CLOCK.tick(120)