كيفية تغيير متغير بشكل دائم في حلقة لعبة 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: قاموس الخلاطات العالمي.أضف الفرز الفرعي (يمكن أن يكون فارغًا أيضًا):

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

يمكنك حفظ قيم مثل هذا:bge.globalDict['mysubdictionaryName'] = myValue.

احتمال 2: ObjectProperty أ) مع بيثون:

myObject = bge.logic.getCurrentController().owner

myObject['myproperty_named_has_run_before'] = True

ب) استخدم Brickbricks وأضف خصائص داخل محرر المنطق

في حالتك ، يجب عليك استخدام ObjectProperties ، لأن Globaldict يتم استخدامها ، عندما تتواصل كائنات متعددة أو إذا كنت بحاجة إلى أخذ البيانات إلى GamesCene أخرى.

نصائح أخرى

ضع ال velocity_x و velocity_y إعلانات قبل الحلقة. إذا كنت تستخدم الفصول ، اجعلها سمات للكائن وتثبيتها مرة واحدة فقط ، داخلها __init__().

تحرير: لا أعرف كيف يعمل محرك لعبة Blender ، ولكن بالإضافة إلى وجود البرنامج النصي في حلقة كبيرة ، يجب أن تكون هناك وسيلة لإعداد الأشياء قبل بدء الحلقة. حقًا ، هذا كل ما يمكنني قوله بالنظر إلى معرفتي المحدودة بموقفك المحدد.

أنا أبحث عن إجابة السؤال نفسه. هناك طريقة واحدة لأجدها. يجب النقر فوق الزر "إضافة خاصية" وإضافة خاصية في Blender ui.fore على سبيل المثال ، OneTime = false.

ثم في البرنامج النصي: اكتب:

إذا onet -reet == false: افعل الأحداث. onet -reet = 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

وهلم جرا ، للإشارة إلى المثيل؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top