简体   繁体   English

如何在Python游戏循环中永久更改变量

[英]How to permanently change a variable in a Python game loop

I have this script in a game that I am making. 我正在制作的游戏中有此脚本。 This will be used in the Blender game engine. 这将在Blender游戏引擎中使用。 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. 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])

Basically, my problem is that in the if loops, I change the variable from its original value to the inverse of its old value. 基本上,我的问题是在if循环中,我将变量从其原始值更改为其旧值的倒数。 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! 谢谢!

Put the velocity_x and velocity_y declarations before the loop. velocity_xvelocity_y声明放在循环之前。 If you're using classes, make them attributes of the object and intialize them just once, inside its __init__() . 如果使用的是类,则使它们成为对象的属性,并在其__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. 编辑:我不知道Blender游戏引擎如何工作,但是除了使脚本处于较大的循环之外,还应该有一种在循环开始之前初始化内容的方法。 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. 我有一种方法可以find.u必须单击“添加属性”按钮,然后在搅拌机UI中添加属性。例如,oneTime = False。

then in the script write: 然后在脚本中编写:

if oneTime==False: Do events. 如果oneTime == False:执行事件。 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. 如果每次运行脚本时python运行时环境都相同,请尝试将初始化移至异常处理程序。 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. 您也可以尝试将变量填充到__main__模块中,如果这样做不起作用。 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. 如果那不起作用,您将需要像sqlite3模块这样的轻量级内置产品。 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. 我在一些评论中看到了__init__ 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? 等等,以引用实例?

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: 以下代码在Blender 2.6和2.7系列中运行:

Possibility 1: Blenders Global Dictionary. 可能性1:Blenders全球词典。 add a Subdictionary (can be empty too): 添加一个Subdictionary(也可以为空):

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

you can save values like this: bge.globalDict['mysubdictionaryName'] = myValue . 您可以这样保存值: bge.globalDict['mysubdictionaryName'] = myValue

Possibility 2: Objectproperty a) with python: 可能性2:使用python的对象属性 a):

myObject = bge.logic.getCurrentController().owner

myObject['myproperty_named_has_run_before'] = True

b) Use Logicbricks and Add Properties inside of the Logic-editor b)在逻辑编辑器中使用Logicbricks和Add Properties

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. 在您的情况下,应该使用objectproperties,因为使用了globalDict,当多个对象进行通信时,或者您需要将数据带到另一个游戏场景时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM