2010-04-18 2 views
2

J'ai ce script dans un jeu que je fais. Ceci sera utilisé dans le moteur de jeu de Blender. Blender exécute continuellement des scripts de haut en bas, donc si je déclare une variable au début du script, il continue d'être initialisé encore et encore.Comment changer de façon permanente une variable dans une boucle de jeu Python

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

Au fond, mon problème est que dans le cas des boucles, je change la variable de sa valeur initiale à l'inverse de son ancienne valeur. Mais parce que je déclare la valeur de la variable au début du script, les variables de vélocité ne restent pas sur ce que je le change.

J'ai besoin d'un moyen de changer la valeur de la variable de façon permanente ou de ne le déclarer qu'une seule fois.

Merci!

+3

À côté: "si les boucles" n'existent pas. "Si" s ne boucle pas. – Thomas

+0

Je pense qu'il nous manque une partie de la logique ici. Les valeurs de velocity_x et velocity_y sont certainement différentes à la fin du début. Est-ce que tout est enveloppé dans une fonction? –

+0

Il est impossible de répondre à votre question sans montrer plus de votre code. Comme écrit, votre code fonctionnera bien. Avez-vous des fonctions dans votre code? Utilisez-vous l'instruction 'global'? –

Répondre

0

Pour gérer la boucle continue à travers votre code de scripts, vous avez besoin d'une valeur qui est écrite en dehors du code. Sinon, cela ne peut pas fonctionner. Comment votre script devrait-il savoir qu'il a déjà été exécuté? Le code suivant s'exécute avec les séries Blender 2.6 et 2.7:

Possibilité 1: dictionnaire global Blenders. ajouter un sous-dictionnaire (peut être vide aussi):

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

vous pouvez enregistrer des valeurs comme ceci: bge.globalDict['mysubdictionaryName'] = myValue.

Possibilité 2: OBJECTPROPERTY a) avec python:

myObject = bge.logic.getCurrentController().owner 

myObject['myproperty_named_has_run_before'] = True 

b) Utiliser Logicbricks et ajoutez des propriétés à l'intérieur de la logique éditeur

Dans votre cas, vous devez utiliser ObjectProperties, parce que le globalDict est utilisé lorsque plusieurs objets communiquent ou si vous devez transférer des données vers un autre site de jeux.

+0

Holy cow, c'est une réponse tardive! De toute évidence pas grand chose pour moi maintenant, mais corrigez quand même. Si vous êtes curieux, voici ce que le projet était: http://davidawehr.com/projects/puck.html – Wehrdo

2

Mettez les déclarations velocity_x et velocity_y avant la boucle. Si vous utilisez des classes, créez les attributs de l'objet et initialisez-les une seule fois, à l'intérieur de __init__().

EDIT: Je ne sais pas comment fonctionne le moteur de jeu de Blender, mais en plus d'avoir le script dans une grosse boucle, il devrait y avoir un moyen d'initialiser les choses avant le début de la boucle. Vraiment, c'est tout ce que je peux dire étant donné ma connaissance limitée de votre situation spécifique.

+0

Je ne peux pas les mettre avant les boucles car tout le script est une boucle. Cela fonctionne dans le moteur de jeu de Blender. Donc, pour utiliser l'init je viens d'écrire __init __ (velocity_x = 0.03) – Wehrdo

+0

@Wehrdo: Ajouter plus de code, alors. Nous ne pouvons pas vraiment savoir quoi faire si vous ne le faites pas. – Javier

+0

Si je devais écrire ce qui suit au début du script, est-ce qu'il initialiserait la variable de vélocité une seule fois, même si elle boucle tout le script? __init __ (velocity_x = 0.03) – Wehrdo

0

Un exemple d'utilisation globale.

#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

je vis un __init__ dans certains commentaires. Si vous êtes dans une classe, vous ne devriez pas écrire quelque chose comme:

self.loc_x += self.velocity_x 

et ainsi de suite, pour faire référence à l'instance?

+0

J'aurais dû préciser que loc_x et loc_y sont l'emplacement x et y de l'objet. Ils changent en fonction de l'emplacement de l'objet. Je vais essayer de mettre cette méthode dans le script et voir si ça marche. – Wehrdo

+0

Dans un environnement différent, ce serait un très bon moyen de le faire. Malheureusement, le moteur de jeu de Blender exécute constamment des scripts depuis le début jusqu'à la fin. Puisque vous déclarez velocity_x et velocity_y au début du script, le moteur de jeu continue d'aller en haut et de réinitialiser ces variables. En outre, l'utilisation de l'instruction "while" dans le moteur de jeu de Blender arrête tous les autres processus jusqu'à ce que l'instruction while soit fausse, ce qui dans ce cas ne serait jamais. Cela gèlerait le jeu. – Wehrdo

+0

Pour gérer la boucle continue à travers votre code de scripts, vous avez besoin d'une valeur qui est écrite en dehors du code. Sinon, cela ne peut pas fonctionner. Comment votre script devrait-il savoir qu'il a déjà été exécuté? – GGolem

1

Je cherche la réponse à la même question. Il y a une façon que je pourrais trouver. Vous devez cliquer sur le bouton "Ajouter une propriété" et ajouter une propriété dans l'interface utilisateur de Blender. Par exemple, oneTime = False.

puis dans l'écriture de script:

si Onetime == Faux: Est-ce que les événements. oneTime = True

C'est la seule façon que j'ai pu trouver.

1

Si votre environnement d'exécution python est le même à chaque fois que le script est exécuté, essayez de déplacer votre initialisation vers un gestionnaire d'exceptions. Comme si:

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

Vous pouvez également essayer de bourrer la variable dans le module __main__ si cela ne fonctionne pas. Comme si:

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

Si cela ne fonctionne pas, vous aurez besoin de quelque chose de léger et intégré comme le module sqlite3. Je réécris l'ensemble de votre extrait de code:

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

Oui, il pourrait être accordé en fonctions ou des classes de fantaisie, mais si c'est l'étendue de ce que vous faites vous n'avez pas besoin de beaucoup plus que cela.

+0

Que l'ajout d'une propriété dans le blender ui trick semble plus facile. – freegnu

Questions connexes