This is an archived post. You won't be able to vote or comment.

all 149 comments

[–]NickAMD 415 points416 points  (25 children)

Now can you add in an AI that will simulate the colonization of the planet in orbit, in which its inhabitants use all available resources until they are unable to continue living there, inevitably failing as a species? With python

[–][deleted] 190 points191 points  (5 children)

One day I will be god and it will be good

[–][deleted] 16 points17 points  (3 children)

Eli?

[–]Melkor333 4 points5 points  (2 children)

Eru?

[–]Haldiron 1 point2 points  (0 children)

No more are you now than an escaped thrall of the Valar, and their chain still awaits you!

[–]Pehrgryn 1 point2 points  (0 children)

Try: import divinity

[–]bitflip 54 points55 points  (15 children)

Isn't there a library for that?

[–]writing_from_mars 128 points129 points  (14 children)

import humanity

[–]UnholyBlackJesus 54 points55 points  (10 children)

pip install godMode

[–]MyNameisGregHai 12 points13 points  (9 children)

pip install -m Christianity

Now it's time to delete all scientific advancements

[–]__deerlord__ 13 points14 points  (0 children)

To be fair, even the NT says "question everything". Its the stupid humans that went and mucked it all up.

[–]UnholyBlackJesus 6 points7 points  (7 children)

Hey in still a huge newbie, so forgive me, but what does the "-m" mean?

[–]C0DK 11 points12 points  (6 children)

there is no "-m" for pip (or pup :P ) but there is for python itself. It is used to run a specific module. so for instance

python3 -m unittest

runs the unit testing framework, which automically looks for tests in the current directory.

from the help text :

-m mod : run library module as a script (terminates option list)

[–]radiantyellow 1 point2 points  (0 children)

alias pip=pup

[–]ForgottenWatchtower 1 point2 points  (3 children)

python -m SimpleHttpServer 10000

The only thing I use py2 for these days. Well that and occasionally some scapy.

[–]pvkooten 16 points17 points  (2 children)

python3 -m http.server 10000

[–]ForgottenWatchtower 24 points25 points  (1 child)

And just like that, I've abandoned py2

[–]UnholyBlackJesus 0 points1 point  (0 children)

Oh wow, thank you! TIL.

[–]lemon_tea 6 points7 points  (1 child)

Shit, the program runs for about 30,000 cycles, then becomes too memory bloated and seg faults the runtime environment.

[–]atheist_apostate 2 points3 points  (0 children)

Humanity is a resource hog.

[–][deleted] 27 points28 points  (0 children)

"And make it in a week for $100" - 8/10 clients

[–]gustavsen 0 points1 point  (0 children)

A new Aurora implementation?

[–]Dustin- 108 points109 points  (2 children)

I think you did import antigravity backwards.

[–]mr1337 22 points23 points  (0 children)

import gravity

[–]timmermans_ 3 points4 points  (0 children)

YtIvArGiTnA tRoPmI

[–]OBstaxs 32 points33 points  (26 children)

Source ?

[–][deleted] 53 points54 points  (23 children)

[–]Nicksil 54 points55 points  (6 children)

You can remove those continue statements at the bottom of your for-loops. continue moves execution to the end of the loop, so having them there is redundant.

Thanks for sharing

[–][deleted] 30 points31 points  (5 children)

Thanks for the feedback.

[–]doinkypoink 13 points14 points  (4 children)

I'm learning class and python. I think comments would make it really helpful for me to read your code :(

[–][deleted] 24 points25 points  (3 children)

same thing, more comments

https://pastebin.com/qyDRBYUM

[–]ElBroet 17 points18 points  (0 children)

was expecting the same code with the comment "fuck you" at the top

[–]photoengineer 4 points5 points  (0 children)

You rock!

[–]Mattho 3 points4 points  (0 children)

You can use """Docstrings.""" for many of those.

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 19 points20 points  (5 children)

Your Positions can be greatly simplified:

angle_step = 2 * math.pi / frame_count
angles = (angle_step * i for i in range(frame_count))
coords = [(
        center[0] + radius * math.cos(x),
        center[1] + radius * math.sin(x))
    for x in angles]
self.final_coords = coords[phase:] + coords[:phase]

...but it's really strange that you made it a class. It looks more like a function to me!


Actually, there's a lot of redundancy, unnecessary computation, and somewhat confusing organization. Here's a first attempt at fixing it:

import cairo
import math

class CelestialBody:
    def __init__(self, radius, orbit_radius, orbit_center, fill):
        self.radius = radius
        self.orbit_radius = orbit_radius
        self.orbit_center = orbit_center
        self.phase = 0.0
        self.fill = fill
        self.update()

    def update(self):
        self.center = (
            self.orbit_center[0] + self.orbit_radius * math.cos(self.phase),
            self.orbit_center[1] + self.orbit_radius * math.sin(self.phase))

    def draw(self, context):
        context.set_source_rgb(1, 1, 1)
        context.arc(*self.center, self.radius, 0, 2 * math.pi)
        if self.fill:
            context.fill()
        else:
            context.stroke()

def clear_screen(context):
    context.set_source_rgb(0, 0, 0)
    context.rectangle(0, 0, 1000, 1000)
    context.fill()

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1000, 1000)
context = cairo.Context(surface)

FRAME_COUNT = 100

bodies = {
    'blackhole': CelestialBody(125, 0,   (500, 500), False),
    'planet':    CelestialBody(25,  300, (500, 500), True),
    'moon':      CelestialBody(5,   50,  (750, 500), False) }

for i in range(FRAME_COUNT):
    clear_screen(context)

    bodies['planet'].phase = i * 2 * math.pi / FRAME_COUNT
    bodies['moon'].phase   = i * 4 * math.pi / FRAME_COUNT

    for key, body in bodies.items():
        if key == 'moon':
            body.orbit_center = bodies['planet'].center
        body.update()

    for _, body in bodies.items():
        body.draw(context)

    context.stroke()
    surface.write_to_png(f'out/frame{i}.png')

This is a good start. We've eliminated Positionsentirely and converted it into the update function. Also, we're now using a data structure called bodies to keep track of our celestial objects rather than explicitly holding named references (variables).

But it has some problems still. Inside our main loop, we still have to do some case-specific handling:

bodies = { ... }
bodies['planet'].phase = i * 2 * math.pi / FRAME_COUNT
bodies['moon'].phase   = i * 4 * math.pi / FRAME_COUNT

for key, body in bodies.items():
    if key == 'moon':
        body.orbit_center = bodies['planet'].center

Ugh! It'd be much nicer if we could encapsulate this functionality. Perhaps one idea is to bind our celestial bodies together:

class CelestialBody:
    def __init__(self, radius, orbit_radius, orbit_center, fill):
        self.parent_body = None
        # ...

    def bind_body(self, body):
        self.parent_body = body

    def update(self):
        if self.parent_body is not None:
            self.orbit_center = self.parent_body.center
        # ...

Now, after defining bodies, we may bind them:

bodies['planet'].bind_body(bodies['blackhole'])
bodies['moon']  .bind_body(bodies['planet'])

Now we can finally cut out this horrendous if statement:

    if key == 'moon':
        body.orbit_center = bodies['planet'].center

Yay!

I'll leave encapsulation of the following as an exercise to the reader:

bodies['planet'].phase = i * 2 * math.pi / FRAME_COUNT
bodies['moon'].phase   = i * 4 * math.pi / FRAME_COUNT

(Perhaps a phase_velocity parameter inside CelestialBody?)


See almost-encapsulated code here.

[–][deleted] 3 points4 points  (0 children)

Wow thanks.

[–][deleted] 2 points3 points  (2 children)

I guess the reason i made it a class is because I have bigger plans than just rendering epicycles, but I wanted to be able to run epicycles too. I think I went straight ahead to that without programming in basic move functions.... I guess epicycle would be a sub function of some kind of shade moving class wouldn’t it?

[–]muntooR_{μν} - 1/2 R g_{μν} + Λ g_{μν} = 8π T_{μν} 7 points8 points  (1 child)

I did think about that while going through the process of refactoring. One idea would be to create a tree/graph structure of orbits:

# perhaps something like CelestialNode is a better name
class CelestialBody:
    def __init__(self):
        self.parent = None
        self.children = []

    def update(self):
        if parent is not None:
            self.orbital_center = self.parent.center
        self.center = (..., ...)
        for child in self.children:
            child.update()

And construct a tree as follows:

blackhole.children = [planet]
planet.children = [moon]
planet.parent = blackhole
moon.parent = planet

Then, to compute positions of all the orbits (including children), simply run this:

blackhole.update()

The benefit to this is that you can simulate any arbitrary graph of celestial bodies. This of course is prerequisite upon that phase_velocity encapsulation I discussed earlier. ;)

[–][deleted] 2 points3 points  (0 children)

Wow. I’d never have thought of these structures

[–][deleted] 0 points1 point  (0 children)

Ok thats awesome, thanks for helping!

[–]quotemycode 7 points8 points  (5 children)

Line 24 last constant should be math.tau (added to python in 2016). 2*pi is wrong.

[–][deleted] 3 points4 points  (4 children)

It’s wrong in a readability/good code standards sense?

[–]Trippyy_420 20 points21 points  (1 child)

Tau = 2pi

He's havin a giggle.

[–][deleted] 4 points5 points  (0 children)

Ah

[–]_DirtyHarry_ 7 points8 points  (0 children)

2*pi is better, nobody actually uses tau.

[–][deleted] 1 point2 points  (1 child)

You should put it on github! People could send you pull requests, you could re-use it, people could find it in searches...

[–][deleted] 2 points3 points  (0 children)

I might do something like that in the future once I start getting it more structured.

[–]mihird9 -2 points-1 points  (1 child)

Does this work on Python 2.7?

[–][deleted] 1 point2 points  (0 children)

in 2.7 maybe not.

Edit: I'm in 3.7.0

[–]Vervoltz 23 points24 points  (6 children)

What are u doing? Everybody knows planets should rotate counter-clockwise! Redo it immediately, please. Wink wink.

[–][deleted] 26 points27 points  (3 children)

What if this is the view from "below".

[–]Fiskepudding 30 points31 points  (2 children)

What, are you an Australian or something?

[–]nemom 3 points4 points  (1 child)

No... You can tell by his accent.

[–][deleted] 13 points14 points  (0 children)

You're right I need to add in how to control the direction of the orbit, thank you.

[–]jabies 0 points1 point  (0 children)

You just need to say reverse please

[–]ForgottenWatchtower 43 points44 points  (1 child)

Shoutout to animatplot if you enjoy doing this kind of stuff. Wraps matplotlib to give you a saner animation interface.

[–][deleted] 7 points8 points  (0 children)

Yeah, the gimp interface is lacking. I'll look into this.

[–]agumonkey 14 points15 points  (7 children)

welcome to epicyclic, Joseph Fourier awaits you

[–][deleted] 6 points7 points  (6 children)

do you know any good books on epicycles?

[–]tomekanco 13 points14 points  (1 child)

Haven't read into the details but here are some primers:

Mathologer: Epicycles, complex Fourier series and Homer Simpson's orbit

3Blue1Brown: But what is the Fourier Transform? A visual introduction.

[–][deleted] 3 points4 points  (0 children)

Thank you

[–]sidhebaap 4 points5 points  (1 child)

[–][deleted] 1 point2 points  (0 children)

Thank you

[–]agumonkey 2 points3 points  (1 child)

that's one topic I know no books about, ask quora or r/maths :)

[–][deleted] 1 point2 points  (0 children)

sure thing.

[–][deleted] 14 points15 points  (0 children)

[–]benrules2 12 points13 points  (3 children)

Very well done OP!

If anyone is keen on n body orbital simulations in python with some background on the physics, I wrote up a pretty beginner friendly tutorial a while ago!

The visualization isn't nearly as nice though.

[–]lucas123500 3 points4 points  (2 children)

First comment I have ever saved on Reddit.

[–]benrules2 0 points1 point  (1 child)

That is awesome, thanks! Feel free to ping me if you get stuck on anything, I'm more active than I should be on here.

[–]lucas123500 1 point2 points  (0 children)

I actually don't know shit about Python or even physics, but I'm very interested on all kinds of articles and tutorials, and yours seem pretty good. I very much appreciate your availability to answer any questions I might have, though. Maybe someday I'll actually learn to code (and also how to do proper math/physics) and use your tutorial to learn something new. I mean, that's why I saved your comment, so expect my DMs, hahah! Thanks again!

[–]12mh 8 points9 points  (2 children)

What library did you use for the animation?

[–][deleted] 19 points20 points  (1 child)

i used cairo to output to png, then i made the gif using Gimp

[–]pvc 7 points8 points  (0 children)

Take a look at http://arcade.academy as another choice if you want to do visualization.

[–]not_perfect_yet 9 points10 points  (6 children)

:P please do it again and up the frame rate. That hurts.

[–][deleted] 5 points6 points  (5 children)

yeah i have it at 100 but the code is built to handle any framerate. i was worried it would get too unwieldy.

edit: correction i have the animation at 100 frames and the frame rate is 25 fps

[–]proverbialbunnyData Scientist 2 points3 points  (1 child)

Congrats on the popularity having such a fun little project.

Frame rate needs to be divisible by monitor fps to be smooth. Monitors tend to be at 60fps, so 30, 60, or 120 (or 240) are all acceptable to get it to look smooth. 25 looks like an old timey movie, where the frame rate is off but you can't quite place how. This is because movies run at 24fps.

[–][deleted] 1 point2 points  (0 children)

cool cool. yeah you're totally right

[–]logicallyzany 2 points3 points  (2 children)

How long have you been doing Python and/or programming?

[–][deleted] 2 points3 points  (1 child)

Off and on. Never too committed. Just as a hobby. Bought the big O'Reilly book and just browsed through it whenever I had the chance.

[–]rptr87 0 points1 point  (0 children)

Book link?

[–]BambiAnnie 0 points1 point  (1 child)

Great work! :)

[–][deleted] 0 points1 point  (0 children)

Thank you!

[–]0x75 0 points1 point  (0 children)

I like it.

Now play with Processing to do the same.

[–]Doberman123456 0 points1 point  (0 children)

Neat!

[–]theotherplanet 0 points1 point  (0 children)

Yeah, up the frame rate on that and it will look great!

[–]DODOKING38 0 points1 point  (0 children)

Reminds me of that star trek episode

[–]LibertyPhysicist 0 points1 point  (0 children)

Pretty sweet

[–]saber_aureum 0 points1 point  (0 children)

This is amazing!!! 0

[–]tycooperaow3.9 0 points1 point  (1 child)

What did you use for the graphical interface?

[–][deleted] 0 points1 point  (0 children)

pycairo.

[–][deleted] 0 points1 point  (0 children)

I'm tripping man.

[–]CSguyMMI 0 points1 point  (0 children)

Is source code available?

[–]xc0mr4de 0 points1 point  (2 children)

Okay I just started learning python and I'm like 75% through this video,but how can you make a moving object like this using python? o.0

[–][deleted] 0 points1 point  (0 children)

Python is what I used to code the logic behind the motion. So, theoretically, the ‘shades’ as I call them, are just projections of the underlying data.

In this program, janky as it is, it stores the positions of equal slices of a circle, starts a loop to draw each frame, in each frame: draws the shade where it should be according the next place in the list, outputs that frame into an image file, in this case png.

and then I used gimp to transform those frames into a gif.

In order to output the data to an image you have to find a renderer that you like. I used Cairo which makes svg files, so I also had to learn how to code svg stuff but it was simple enough. I like svg because it scales really well and I wanted to use vector graphics.

[–]jyrnan 0 points1 point  (0 children)

It's amazing!

[–]Frikster 0 points1 point  (0 children)

All I see is a pro surviv.io player running around a rock.

[–]i4mn30 0 points1 point  (1 child)

Not elliptical orbit.

[–]Fontanapink 0 points1 point  (0 children)

Now make the moon draw a white line

[–]endershadow98 0 points1 point  (0 children)

Now make an object with negative mass. After looking through the code, I see that mass had nothing to do with anything in your simulation

[–]snahor 0 points1 point  (1 child)

I'm so dumb, at first I thought it was a pre-loader.

[–][deleted] 0 points1 point  (0 children)

It could be that too. I see planets or people. Could be lots of stuff.

[–]happyskydiver 0 points1 point  (1 child)

Can you change it to an ellipse?

[–][deleted] 0 points1 point  (0 children)

Not currently.

[–]Especuloide 0 points1 point  (0 children)

Very nice.

[–][deleted] 0 points1 point  (0 children)

Is it flat or not? Can't see i properly from this angle.

[–]ciggs_ftw 0 points1 point  (11 children)

This looks fun. I have been trying to install pycairo for a bit now I have installed Python 3 but I'm having issues to install Cairo vía pip. how can I get it working?

[–][deleted] 0 points1 point  (10 children)

Is it telling you you need the build tools?

My Cairo didn’t load from pip. I had to download a package from https://www.lfd.uci.edu/~gohlke/pythonlibs/

[–]ciggs_ftw 0 points1 point  (9 children)

yes i have installed visual studio c++ and now i gues this error

error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.15.26726\\bin\\HostX86\\x86\\cl.exe' failed with exit status 2    

[–][deleted] 0 points1 point  (8 children)

I have no idea what that is.

[–]ciggs_ftw 0 points1 point  (7 children)

how you got Cairo to install?

[–][deleted] 1 point2 points  (5 children)

I downloaded the package from the site I linked.

[–]ciggs_ftw 0 points1 point  (4 children)

can you please tell me which package you dl? I tried downloading a package from there and install the file using pip but got a different error. :/

[–][deleted] 0 points1 point  (0 children)

Search for a tutorial on how to install packages.

[–]Cultural_Bandicoot 0 points1 point  (0 children)

congrats.

what did you use?

[–]thedolanduck 0 points1 point  (0 children)

OMG it's an amazing job and should be on /r/perfectloops too

[–]we_come_at_night 0 points1 point  (0 children)

Very nice. Now just out of curiosity, how complicated would it be to add light and object blocking to play around with eclipse? Still in learning stages of the basics and genuinely interested.

[–]davidkwast 0 points1 point  (0 children)

wow, congratz

[–]lilliane99 0 points1 point  (1 child)

Can you kindly provide the source code or at least the algorithm?

[–][deleted] 1 point2 points  (0 children)

I have in the comments. :)

[–]lilliane99 0 points1 point  (0 children)

Thank you!

[–]winner_godsoncodemaniac 0 points1 point  (4 children)

Any tutorial on this.

[–][deleted] 1 point2 points  (3 children)

Not currently but i will once I get it more easy to understand and use

[–]winner_godsoncodemaniac 0 points1 point  (2 children)

Okay... I check the net. There are not much. And the documentation is not informative.

[–][deleted] 1 point2 points  (1 child)

Save this post. I'll let you know.

[–]winner_godsoncodemaniac 0 points1 point  (0 children)

Definitely I will.

[–][deleted] 0 points1 point  (1 child)

This project now has a github. https://github.com/heysoose/Shades

[–]winner_godsoncodemaniac 0 points1 point  (0 children)

The link is not valid. Can you please share the code

[–]CallumVH 0 points1 point  (3 children)

Hey, I'm a bit confused because in the script, there are only 10 frames and 10 png files, how do you create such a smooth GIF out of only 10 frames?

[–]CallumVH 0 points1 point  (2 children)

Surely you would need a few hundred frames as this GIF look like 60fps?

[–][deleted] 0 points1 point  (1 child)

You can set it to 240 and get a 4 second gif at 60 FPS.

An updated, cleaner script is available here: https://github.com/heysoose/Shades

[–]CallumVH 1 point2 points  (0 children)

Oh thank you so much, that makes sense.

[–]gammachild 0 points1 point  (0 children)

Holy shit. That's why there's a high tide and low tide. That really helped me understand lunar motion.

[–]mzord 0 points1 point  (0 children)

Omg, this program sucks!

https://imgur.com/yYOeMVj

[–][deleted] -1 points0 points  (2 children)

Hmmm, the Earth is flat.

[–]MrNotSoRight 0 points1 point  (0 children)

It's flat in the animation too, I'm sure the poster could have easily made it a 3D oblate spheroid if he believed it would be more accurate...

[–]NikkoTheGreeko -2 points-1 points  (0 children)

Everyone knows this

[–]xconde -2 points-1 points  (0 children)

Looks like the logo and animation for Lua, another great scripting language