Как навсегда изменить переменную в петле игры Python

StackOverflow https://stackoverflow.com/questions/2663763

  •  27-09-2019
  •  | 
  •  

Вопрос

У меня есть этот скрипт в игре, что я делаю. Это будет использоваться в игровом двигателе 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 я изменяю переменную от его первоначального значения на обратную старое значение. Но потому что я объявляю ценность переменной в начале сценария, переменные скоростей не остаются на том, к чему я его меняю.

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

Спасибо!

Это было полезно?

Решение

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

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

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

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

Возможность 2: ObjectProperty а) с Python:

myObject = bge.logic.getCurrentController().owner

myObject['myproperty_named_has_run_before'] = True

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

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

Другие советы

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

Редактировать: Я не знаю, как работает двигатель Blender Game, но в дополнение к сценарию в большой петле, должен быть способ активизировать вещи до начала петли. Действительно, это все, что я могу сказать, учитывая мои ограниченные знания о вашей конкретной ситуации.

Я ищу ответ на тот же вопрос. Есть один из способов ICOULT.U, ДОЛЖЕН НАЖМИТЕ НА КНОПКУ «Добавить свойство» и добавить свойство в Blender ui. Например, OneTime = false.

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

Если OneTime == false: делать события. OneTime = True.

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

Если ваша среда Runtime 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()

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

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

РЕДАКТИРОВАТЬ

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

self.loc_x += self.velocity_x

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top