コード例 #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)