Pythonゲームループで変数を永続的に変更する方法
質問
私が作っているゲームにこのスクリプトがあります。これは、ブレンダーゲームエンジンで使用されます。 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ループでは、変数を元の値から古い値の逆に変更することです。しかし、スクリプトの先頭に変数の値を宣言するため、速度変数は私がそれを変更するものにとどまりません。
変数の値を永続的に変更するか、1回だけ宣言する方法が必要です。
ありがとうございました!
解決
スクリプトコードを介して継続的なループを処理するには、コードの外部で記述される値が必要です。それ以外の場合は機能しません。スクリプトが以前に実行されたことをどのように知っておくべきですか?次のコードは、Blender 2.6および2.7シリーズで実行されます。
可能性1:Blenders Global Dictionary。下着項を追加します(空にすることもできます):
bge.logic.globalDict['mysubdictionaryName'] = { 'namestring' : False}
このような値を保存できます:bge.globalDict['mysubdictionaryName'] = myValue
.
可能性2:ObjectProperty a)Pythonで:
myObject = bge.logic.getCurrentController().owner
myObject['myproperty_named_has_run_before'] = True
b)論理ブリックを使用して、論理編集者の内部にプロパティを追加します
あなたの場合、複数のオブジェクトが通信するとき、または別のGameCeneにデータを取得する必要がある場合、GlobalDictが使用されるため、ObjectPropertiesを使用する必要があります。
他のヒント
置く velocity_x
と velocity_y
ループの前の宣言。クラスを使用している場合は、オブジェクトの属性を作成し、その内部で一度にそれらを一度に整数化します __init__()
.
編集:Blenderゲームエンジンがどのように機能するかはわかりませんが、スクリプトを大きなループに置くことに加えて、ループが開始する前に物をintializeする方法があるはずです。本当に、あなたの特定の状況に関する私の限られた知識を考えると、それは私が言うことができるすべてです。
同じ質問の答えを探しています。 「プロパティの追加」ボタンをクリックして、Blender UIのプロパティを追加する必要がある1つの方法があります。たとえば、Onetime = false。
次に、スクリプトで書き込みます:
onetime == falseの場合:イベントを行います。 Onetime = true
これが私が見つけることができる唯一の方法です。
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()
はい、それは関数や派手なクラスに調整される可能性がありますが、それがあなたがしていることの範囲であれば、それ以上は必要ありません。
グローバルの使用例。
#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
など、インスタンスを参照するために?