Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Создаем симулятор ясной системы

Anna | 16.06.2014 | нет комментариев
Вступление
Нерушимая тяга к новому подтолкнула к постижению такого восхитительного языка программирования, как Питон. Как это Зачастую бывает, неимение идеи, на реализацию которой не ничтожно потратить свое время, крепко тормозило процесс.

Свободою судьбы на глаза попался восхитительный цикл статей о создании игры-платформера на Питоне
здесь и здесь.
Я решил взяться за один ветхий план. За симулятор движения тел под действием сил гравитации.

Что из этого вышло читайте дальше. 

Часть первая. Теоритическая

Дабы решить задачу, необходимо вначале Отчетливо себе ее представить.
Представим, всеми правдами и выдумками нам удалось заполучить двумерный участок безвоздушного пространства с находящимися в нем телами. Все тела перемещаются под действием сил гравитации. Внешнего воздействия нет.
Необходимо возвести процесс их движения касательно друг друга. Простота реализации и красочность финального итога послужат толчком и наградой. Освоение Питона будет отличной инвестицией в грядущее.

Введем систему координат.

Пускай наша система состоит из 2-х тел:
1. громоздкой звезды массой М и центром (x0, y0)
2. легкой планеты массой m, с центром в точке (x, y), скоростью v = (vx, vy) и убыстрением a = (ax, ay).

Когда нам удастся разобрать данный случай, мы легко перейдем к трудным системам со взаимным влиянием звезд и планет друг на друга. Теперь же речь пойдет о самом простом.

Позже несложных манипуляций со вторым законом Ньютона, законом глобального стремления и сходственными треугольниками, я обнаружил, что:

ax = G * M * (x0-x) / r^3
ay = G * M * (y0-y) / r^3

Это разрешает составить алгорифм перемещения планеты в поле гравитации звезды:

1. Перед началом задаем исходное расположение планеты (x, y) и исходную скорость (vx, vy)
2. На всяком шаге вычисляем новое убыстрение по формуле выше, позже этого пересчитываем скорость и координаты:

vx := vx T * ax
vy := vy T * ax

x := x T * vx
y := y T * yx

Осталось разобраться с константами G и T. Положим G = 1. Для нашей задачи это не так значимо. Параметр T влияет на точность и скорость вычислений. Тоже положим 1 для начала.

Часть вторая. Утилитарная

Выходит, моя первая программа на Питоне. При этом еще раз хочется поблагодарить Velese за фактическое начальство.

import pygame, math
from pygame import *
from math import *

WIN_WIDTH = 800
WIN_HEIGHT = 640
PLANET_WIDTH = 20
PLANET_HEIGHT = 20
DISPLAY = (WIN_WIDTH, WIN_HEIGHT)
SPACE_COLOR = "#000022"
SUN_COLOR = "yellow"
PLANET_COLOR = "blue"

#Sun position
X0 = WIN_WIDTH // 2
Y0 = WIN_HEIGHT // 2
#Sun mass
M0 = 5000
#Stop conditions
CRASH_DIST = 10
OUT_DIST = 1000

def main():
    #PyGame init
    pygame.init()
    screen = pygame.display.set_mode(DISPLAY)
    pygame.display.set_caption("Solar Mechanics v0.1")

    #Space init
    bg = Surface((WIN_WIDTH,WIN_HEIGHT))
    bg.fill(Color(SPACE_COLOR))     
    draw.circle (bg, Color(SUN_COLOR), (X0, Y0), 10)

    #Timer init                     
    timer = pygame.time.Clock()

    #Planet init
    planet = Surface((PLANET_WIDTH, PLANET_HEIGHT))
    planet.fill(Color(SPACE_COLOR))
    draw.circle (planet,
        Color(PLANET_COLOR),
        (PLANET_WIDTH // 2, PLANET_HEIGHT // 2),
        5)

    #Planet to Sun distance
    r = 0.0
    #Initial planet pos, speed and accel
    x = 100.0
    y = 290.0
    vx = 0.1
    vy = 1.5
    ax = 0.0
    ay = 0.0

    done = False
    while not done:
        timer.tick(50)
        for e in pygame.event.get():
            if e.type == QUIT:
                done = True
                break        

        r = sqrt((x - X0)**2   (y - Y0)**2)

        ax = M0 * (X0 - x) / r**3
        ay = M0 * (Y0 - y) / r**3

        #New spped based on accel
        vx  = ax
        vy  = ay

        #New pos based on speed
        x  = vx
        y  = vy

        screen.blit(bg, (0, 0))      
        screen.blit(planet, (int(x), int(y)))
        pygame.display.update()     

        if r < CRASH_DIST:
            done = True
            print("Crashed")
            break
        if r > OUT_DIST:
            done = True
            print("Out of system")
            break

    #Farewell
    print (":-)")

if __name__ == "__main__":
    main()

Так выглядит наша система позже некоторого времени симуляции

Пока писалась эта заметка, симулятор разросся новой функциональностью: число объектов в звездной системе не ограничевается, учитывается взаимное их воздействие друг на друга, расчетная часть вынесена в свой класс, конфигурация системы задается в отдельном файле и добавлена вероятность выбора систем.

Теперь я занимаюсь поиском увлекательных сценариев системы и небольшими совершенствованиями интерфейса.

Вот пример того, что на данный момент в разработке:

Если эта заметка встретит правильные отзывы, обещаю продолжить рассказ о больше новой версии.

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB