使用 Cocos2d 模拟 N 体问题

最近学习了一下 Cocos2d,它是一个基于 Python 的用于创建 2D 游戏、演示以及其它图像/交互应用的框架。

这个框架总体来说,还是很简单清晰的。我用它把之前写的网页版的 N 体问题模拟重新实现了一遍。效果如下:

只模拟万有引力,没有做碰撞检测。代码比较简单:

# -*- coding: utf-8 -*-
#
# N 体问题模拟
# https://oldj.net/
#

import cocos
from cocos.director import director
from cocos.sprite import Sprite
from cocos.actions import *
from cocos import draw
import pyglet

import random
import os
import math

G = 0.001 # 万有引力常数

class Planet(Sprite):

	def __init__(self, x, y, r):

		super(Planet, self).__init__(
				"0.png",
				rotation = 90,
				position = (x, y),
				scale = r * 0.1,
			)

		self.r = r
		self.m = math.pi * self.r * self.r
		self.vx = 0
		self.vy = 0

	def beAttracted(self, planets):

		for planet in planets:
			if planet != self:
				self.beAttractedBy(planet)

	def beAttractedBy(self, planet):

		distance = math.sqrt(pow(self.x - planet.x, 2) + pow(self.y - planet.y, 2))
		f = G * self.m * planet.m / (distance + 0.0000001)

		if self.x != planet.x:
			a = math.atan((planet.y - self.y) / (planet.x - self.x))
			vx = f * math.cos(a) / self.m
			vy = f * math.sin(a) / self.m
			if planet.x > self.x:
				self.vx += vx
				self.vy += vy
			else:
				self.vx -= vx
				self.vy -= vy

		else:
			self.vy += f if self.y < planet.y else -f

	def move(self):

		self.x += self.vx
		self.y += self.vy


class SpaceLayer(cocos.layer.Layer):

	def __init__(self):

		super(SpaceLayer, self).__init__()
		# self.schedule(lambda x: 0)
		self.mkPlanets(50)

		self.schedule(self.timer)

	def mkPlanets(self, n = 10):

		self.planets = []
		ri = random.randint
		w, h = director.get_window_size()

		for i in range(n):
			planet = Planet(ri(0, w), ri(0, h), ri(1, 10))
			self.planets.append(planet)
			self.add(planet)

	def timer(self, x):

		self.attract()


	def attract(self):

		for planet in self.planets:
			planet.beAttracted(self.planets)

		for planet in self.planets:
			planet.move()


if __name__ == "__main__":
	director.init(
			# resizable = True,
			# width = 800,
			# height = 600,
			caption = u"N 体问题模拟",
		)
	space_layer = SpaceLayer()
	main_scene = cocos.scene.Scene(space_layer)
	director.run(main_scene)

其中需要一个图像文件,点击这儿可以下载完整的源文件。

分类:编程标签:物理Python

相关文章:

评论:

暂无评论

发表评论: