6
$\begingroup$

I'm new to Blender and new to Python, on my Layer 1 I have a ball named "BallB". Now I want to make a simple bubbling-animation using Python in Blender but I'm unable to make a keyframe. This should happen on Layer 2. I tried many and got many Errors.... all the Snippets I found didn't work and my script allways crashed with Python-Errors like "RuntimeError: Operator bpy.ops.anim.change ... expected an timeline/animation area to be activated" and many more.

Has anybody some hints for me? I'd like to learn scripted animations in Blender so I'm very thankfull for every hint which advances me ;-)

My Code:

import bpy, math, random

d           = 4
anz         = 100
frameAnz    = 10

scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 100


for anz in range (0,anz):

    ball = bpy.data.objects["ballB"]   

    tball = ball.copy()
    xpos = -1 * (d/2) + random.randint(0,(d-1))
    xpos += random.random()
    ypos = -1 * (d/2) + random.randint(0,(d-1))
    ypos += random.random()
    zpos =  random.randint(0,(d-1))
    zpos += random.random()



    bn = str(anz).zfill(5)
    bn = "zz_Ball-" + bn

    tball.name = bn
    tball.location = (xpos, ypos, zpos)
    sz = random.uniform(0.015,0.09)


    tball.scale = (sz,sz,sz)

    #tball.nodes["Emission"].inputs[1].default_value = 200
    tball.select = False
    scene.objects.link(tball)
    #print ("done!")

obj = bpy.context

for actFrame in range(1,frameAnz):
   # scene = bpy.context.scene
#    scene.keyframe_insert(data_path="gravity", frame = actFrame)


    for ob in scene.objects:

        ploc = ob.location
        #print (ploc)
        xpos = ploc[0]
        ypos = ploc[1]
        zpos = ploc[2]

        zpos = zpos + random.random()
        ob.location = (xpos, ypos, zpos)
        #ypos = ball.location[1]
        #zpos = ball.location]2]

        #zpos = zpos - random.random()

        #ball.location = (xpoy, ypos, zpos)
        #obj.keyframe_insert_menu('Location')
        #bpy.context.scene.frame_set(0)
    #scene = bpy.context.scene
    #scene.keyframe_insert(data_path="Location", frame=actFrame)

Actually it looks so: Screenshot Blender

$\endgroup$
4
$\begingroup$

Finally I found a solution which works great for me. I added some commits so others with the same starter problems can use it.

Remember: there must be an named object defined in originName, otherwise the script will crash!

import bpy, math, random


d           = 4           # size of area where the balls spawn (STRG+Q to see what I mean)
anz         = 100           # number of balls
frameAnz    = 100           # number of generated frames
spawnScale = [0.015 , 0.09] # range for random scale during spawnprocess of a new ball
originName = "motherBall"   # name of the origin-object

#prepare scene, keyframes and keyframe-pointer:
scene = bpy.context.scene
scene.frame_start = 0
scene.frame_end   = frameAnz
bpy.ops.screen.frame_jump(end=False)

# first remove all objects from previous script-runs:
# (better than "a", then "x" and then ENTER before restarting this script!)
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()

# "pick" the original ball from layer 1:
oBall = bpy.data.objects[originName]  

# loop for creating (anz)x balls:
for anz in range (0,anz):

    # duplicate the original ball and
    # name the new ball like "zz_Ball-00001"  
    # zz_ is for standing below in the outliner
    newBall = oBall.copy()
    newBallName = str(anz).zfill(5)
    newBallName = "zz_Ball-" + newBallName
    newBall.name = newBallName

    # now generate a random position for the new ball:
    xpos = -1 * (d/2) + random.randint(0,(d-1))
    xpos += random.random()
    ypos = -1 * (d/2) + random.randint(0,(d-1))
    ypos += random.random()
    zpos =  random.randint(0,(d-1))
    zpos += random.random()
    # and place the new ball at this:
    newBall.location = (xpos, ypos, zpos)

    # scaling the new ball to get different sizes of balls:
    sz = random.uniform(spawnScale[0] , spawnScale[1])
    newBall.scale = (sz,sz,sz)

    #finally deselect the ball and link it into the scene:
    newBall.select = False
    scene.objects.link(newBall)

# now lets create frame by frame:
for actFrame in range(1,frameAnz + 1):

    bpy.context.scene.frame_set(actFrame)
    for ob in scene.objects:

        if (ob.name != originName):
            ploc = ob.location
            xpos = ploc[0]
            ypos = ploc[1]
            zpos = ploc[2]

            zpos = zpos + ( random.random() / 8)
            ob.location = (xpos, ypos, zpos)
            ob.keyframe_insert(data_path="location", index=-1)

# job done: now reset the framekeypointer to 0    
bpy.ops.screen.frame_jump(end=False)
$\endgroup$
  • $\begingroup$ not work, how can change originName $\endgroup$ – saded Jan 12 '17 at 18:22
  • $\begingroup$ Look in your outliner for the name of your objects. If its f.e. "foobazbar" then replace "motherBall" for "foobazbar" in line 7. Also enable the python-console by clicking "toggle system console" under the dropdown window - there you can see if any other erros appear. $\endgroup$ – Atari800XL Jan 13 '17 at 5:31
  • $\begingroup$ I change but i have other error in line :oBall = bpy.data.objects[originName] , in console: Foobazbar not founed $\endgroup$ – saded Jan 13 '17 at 9:46
  • $\begingroup$ Here, take my .blend and compare the variable in line 8 to the outliner on the right side, both names must be equal otherwise the script can't copy this origin object. filedropper.com/gravity $\endgroup$ – Atari800XL Jan 14 '17 at 19:08
  • $\begingroup$ Good it work, than you $\endgroup$ – saded Jan 15 '17 at 11:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.