コード例 #1
0
ファイル: main.py プロジェクト: jthistle/physics-sim
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)
コード例 #2
0
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)