Как навсегда изменить переменную в игровом цикле Python - PullRequest
2 голосов
/ 19 апреля 2010

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

#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])

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

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

Спасибо!

Ответы [ 5 ]

2 голосов
/ 19 апреля 2010

Поместите объявления velocity_x и velocity_y перед циклом. Если вы используете классы, присвойте им атрибуты объекта и инициализируйте их только один раз, внутри его __init__().

РЕДАКТИРОВАТЬ: Я не знаю, как работает игровой движок Blender, но в дополнение к наличию сценария в большом цикле, должен быть способ инициализировать материал до начала цикла. На самом деле, это все, что я могу сказать, учитывая мои ограниченные знания о вашей конкретной ситуации.

1 голос
/ 30 июня 2010

Если ваша среда выполнения Python одинакова при каждом запуске скрипта, попробуйте переместить инициализацию в обработчик исключений. Вот так:

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

Вы также можете попробовать вставить переменную в модуль __main__, если это не сработает. Вот так:

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

Если это не сработает, вам понадобится что-то более легкое и встроенное, например модуль sqlite3. Я переписал весь ваш фрагмент кода:

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()

Да, это может быть настроено на функции или необычные классы, но если это то, что вы делаете, вам не нужно намного больше, чем это.

1 голос
/ 19 июня 2010

я ищу ответ на тот же вопрос. есть один способ, которым я мог бы найти. Вы должны нажать кнопку «Добавить свойство» и добавить свойство в пользовательском интерфейсе блендера. Например, oneTime = False.

тогда в скрипте напишите:

if oneTime == False: Делать события. Одноразовый = True

это единственный способ найти.

0 голосов
/ 17 января 2015

Для обработки непрерывного цикла в коде вашего скрипта вам нужно значение, которое написано вне кода. В противном случае это не может работать. Как ваш сценарий должен знать, что он запускался раньше? Следующий код работает с Blender 2.6 и 2.7 series:

Возможность 1: Глобальный словарь Blenders. добавить Subdictionary (также может быть пустым):

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

вы можете сохранить такие значения: bge.globalDict['mysubdictionaryName'] = myValue.

Возможность 2: свойство объекта а) с питоном:

myObject = bge.logic.getCurrentController().owner

myObject['myproperty_named_has_run_before'] = True

b) Использовать логические блоки и добавлять свойства внутри логического редактора

В вашем случае вам следует использовать свойства объекта, потому что используется globalDict, когда несколько объектов обмениваются данными или если вам нужно перенести данные в другую игровую сцену.

0 голосов
/ 19 апреля 2010

Пример использования 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

Я видел __init__ в некоторых комментариях. Если вы в классе, не должны ли вы написать что-то вроде:

self.loc_x += self.velocity_x

и так далее, чтобы ссылаться на экземпляр?

...