Question

I have this script in a game that I am making. This will be used in the Blender game engine. Blender runs scripts over and over from top to bottom continuously, so if I declare a variable at the beginning of the script, it keeps being initialized over and over.

#The current location of the object
loc_x = obj.getPosition()[0]
loc_y = obj.getPosition()[1]

#The velocity of the object
velocity_x = 0.09
velocity_y = 0.03


#If the location of the object is over 5, bounce off.
if loc_x > 5:
    velocity_x = (velocity_x * -1)

if loc_y > 5:
    velocity_y = (velocity_y * -1)

#Every frame set the object's position to the old position plus the velocity
obj.setPosition([(loc_x + velocity_x),(loc_y + velocity_y),0])

Basically, my problem is that in the if loops, I change the variable from its original value to the inverse of its old value. But because I declare the variable's value at the beginning of the script, the velocity variables don't stay on what I change it to.

I need a way to change the variable's value permanently or declare it only once.

Thank you!

Was it helpful?

Solution

To handle the continuous looping through your scripts code you need a value which ist written outside of the code. Otherwise it can't work. How should your script know that it has been run before? Following Code runs with Blender 2.6 and 2.7 series:

Possibility 1: Blenders Global Dictionary. add a Subdictionary (can be empty too):

bge.logic.globalDict['mysubdictionaryName'] = { 'namestring' : False}

you can save values like this: bge.globalDict['mysubdictionaryName'] = myValue.

Possibility 2: Objectproperty a) with python:

myObject = bge.logic.getCurrentController().owner

myObject['myproperty_named_has_run_before'] = True

b) Use Logicbricks and Add Properties inside of the Logic-editor

In your case you should use objectproperties, because the globalDict is used, when multiple objects communicate or if you need to take data to another gamescene.

OTHER TIPS

Put the velocity_x and velocity_y declarations before the loop. If you're using classes, make them attributes of the object and intialize them just once, inside its __init__().

EDIT: I don't know how the Blender game engine works, but in addition to having the script in a big loop, there should be a way to intialize stuff before the loop starts. Really, that's all I can say given my limited knowledge of your specific situation.

im looking for the answer of the same question. there is one way i coould find.u must click on the "add property" button and add a property in blender UI.for example, oneTime=False.

then in the script write:

if oneTime==False: Do events. oneTime=True

this is the only way i could find.

If your python runtime environment is the same every time the script is run try moving your initialization to an exception handler. Like so:

try:
    velocity_x = (velocity_x * -1)
except:
    velocity_x = 0.09

You can also try stuffing the variable into the __main__ module if that doesn't work. Like so:

try:
    __main__.velocity_x = (velocity_x * -1)
except:
    __main__.velocity_x = 0.09

If that doesn't work you'll need something lightweight and built in like the sqlite3 module. I rewrote your entire code snippet:

import sqlite3

#The current location of the object
loc_x = obj.getPosition()[0]
loc_y = obj.getPosition()[1]

c = sqlite3.connect('/tmp/globals.db')
#c = sqlite3.connect('/dev/shm/globals.db')
# Using the commented connection line above instead will be
# faster on Linux. But it will not persist beyond a reboot.
# Both statements create the database if it doesn't exist.

# This will auto commit on exiting this context
with c:
    # Creates table if it doesn't exist
    c.execute('''create table if not exist vectors 
      (vector_name text primary key not null, 
       vector_value float not null,
       unique (vector_name))''')

# Try to retrieve the value from the vectors table.
c.execute('''select * from vectors''')
vector_count = 0
for vector in c:
    vector_count = vector_count + 1
    # sqlite3 always returns unicode strings
    if vector['vector_name'] == u'x':
        vector_x = vector['vector_value']
    elif vector['vector_name'] == u'y':
        vector_y = vector['vector_value']

# This is a shortcut to avoid exception logic
# Change the count to match the number of vectors
if vector_count != 2:
    vector_x = 0.09
    vector_y = 0.03
    # Insert default x vector. Should only have to do this once
    with c:
        c.executemany("""replace into stocks values 
          (?, ?)""", [('x', vector_x), ('y', vector_y)])

#If the location of the object is over 5, bounce off.
if loc_x > 5:
    velocity_x = (velocity_x * -1)
if loc_y > 5:
    velocity_y = (velocity_y * -1)

# Update stored vectors every time through the loop
with c:
    c.executemany("""update or replace stocks set vector_name = ?, 
      vector_value = ?)""", [('x', vector_x), ('y', vector_y)])

#Every frame set the object's position to the old position plus the velocity
obj.setPosition([(loc_x + velocity_x),(loc_y + velocity_y),0])

# We can also close the connection if we are done with it
c.close()

Yes it could be tuned into functions or fancy classes but if that is the extent of what you are doing you don't need much more than that.

An example of using global.

#The velocity of the object
velocity_x = 0.09
velocity_y = 0.03
loc_x = 0
loc_y = 0    

def update_velocity():  
  #If the location of the object is over 5, bounce off.
  global velocity_x, velocity_y
  if loc_x > 5:
    velocity_x = (velocity_x * -1)

  if loc_y > 5:
    velocity_y = (velocity_y * -1)

def update_position():
  global loc_x, loc_y # global allows you to write to global vars
                      # otherwise you're creating locals :)
  loc_x += velocity_x
  loc_y += velocity_y     

#Every frame set the object's position to the old position plus the velocity

while True:
  update_velocity()
  update_position()
  # undoubtedly you do more than this...
  obj.setPosition([loc_x,loc_y,0])

EDIT

I saw an __init__ in some comment. If you're in a class shouldn't you write something like:

self.loc_x += self.velocity_x

and so on, to reference the instance?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top