1

私はPythonを使用して単純な進化シミュレーターを作成しています。

engine.Allユニット/動物と食べ物の両方を保存する、と呼ばれるリストがあります。私はそれを繰り返し、動物に出くわした場合は、もう一度繰り返して、彼が食べ物のいずれかと衝突しているかどうかを確認します。

もしそうなら、私は彼のエネルギーを増やし、食べ物に食べたものとしてフラグを立て、それをtoRemoveリストに追加します。これは後で要素を削除するために使用しengine.Allます。

これはコードですが、冗長なものはすべて削除されています。

def remove(l, who): #This should remove all the elements contained in who from the list l
    offset = 0

    for i in who:
        l.pop(i + offset)
        offset -= 1

    return l


for ob in engine.All:
    if ob.skip:
        continue;

    if ob.drawable:
       ob.draw()

    if isinstance(ob, Flatlander): #If it is an animal
        #Do speed stuff
        ob.energy -= decay #Lower its energy

        for i in range(len(engine.All)): #Iterate through the list again
            if collides(ob.pos, ob.r, engine.All[i].pos, engine.All[i].r) and isinstance(engine.All[i], Food) and ob.energy + engine.All[i].r < ob.r**2*3.14 and not engine.All[i].skip: #If it collides with a food piece, the food piece isn't about to be deleted and it can take the energy in (their maximum is defined by their radiuses)
                ob.energy += engine.All[i].r #Increase the his energy
                toRemove.append(i) #Add the food piece to the toRemove list
                engine.All[i].skip = True #Flag it as skipped

        if ob.energy < 0 and not ob.skip: #If its energy is 0 and if it isn't already about to be deleted
            toRemove.append(engine.All.index(ob)) #Add it to the toRemove list
            ob.skip = True #Flag it as skipped


engine.All = remove(engine.All, toRemove) 

私はこれがうまくいかないこと、そしてこれを行うためのより良い方法があることをほぼ確信しています。私が確信している理由は、画面上で物事が「点滅」しているのを時々目にするからです。突然消えて、再び現れます。また、「幽霊」の動物(コードではフラットランダーと呼ばれます)がいるようですが、食べ物が永久に消えてしまうことがあるので、これを結論付けます。

より効率的な方法をお勧めします。

4

3 に答える 3

4

不要な要素をポップするよりも、ジェネレーター関数としてこれを実行し、必要な結果を生成する方が簡単です。

def valid_engines():
    for ob in engine.All:
        if should_use_engine(ob):
            yield ob

engines_to_use = valid_engines()

もちろん、should_use_engine()は、エンジンを含めるかどうかを決定するために、上記のロジックに置き換えられます。

于 2012-05-10T22:14:30.530 に答える
1

skip属性が削除する必要のあるオブジェクトにのみ設定されている場合は、それを利用してください。

import math
import itertools

for ob in engine.All:
    if isinstance(ob, Flatlander):
        ob.energy -= decay

for pair in itertools.combinations(engine.All, 2):
    fooditems = [x for x in pair if isinstance(x, Food) and not x.skip]
    animals = [x for x in pair if isinstance(x, Flatlander) and not x.skip]
    if not (fooditems and animals):
        continue
    animal = animals[0]
    food = fooditems[0]
    if collides(animal.pos, animal.r, food.pos, food.r):
        # This seems an odd calculation to me but I think it follows your code.
        if animal.energy + food.r < animal.r ** 2 * math.pi:
            # eating is feasible; the animal always eats the food if it can
            food.skip = True
            animal.energy += food.r # Not the area?

for ob in engine.All:
    if isinstance(ob, Flatlander) and ob.energy < 0:
        ob.skip = True # dead

# Remove dead things
engine.All = [ob for ob in engine.All if not ob.skip]

# Draw everything (no dead things remain)
for ob in engine.All:
    if ob.drawable:
      ob.draw()

一般的に、私はおそらく食料品とフラットランダーを別々のリストに入れておきたいと思います。

衝突検出をより効率的に行うためのいくつかの手法があります(たとえば、世界を正方形に分割し、同じまたは周囲の正方形にある動物のみをチェックする)が、動物/食品が数個(たとえば数百個未満)しかない場合これは必要ありません。

于 2012-05-10T22:30:31.520 に答える
0

私は進化ゲームに精通していませんが、ある種の2Dマップ(mb 3D)と、移動して最初に衝突した食料品を食べる動物がいると思いますか?それとも、それは生き物のようなゲームですか?これは基本的に同じです:p

もしそうなら、私は正方形にコンテンツフィールドを追加します。動物が正方形に移動するときは、隣接する正方形を確認し、食料品が存在する場合は、その正方形のコンテンツフィールドをNullに設定するだけです。これは、2Dゲームのすべての要素の位置を保存することに対する一般的な最適化であり、必要に応じて微調整できます。

タイマーフィールドを使用して、削除されたアイテムのリストを追加して、各アイテムをいつ再スポーンするかを指定できます。このリストは、アイテムを再挿入する必要があるかどうかを簡単に検出できるように、リスポーン時間でソートされます。

于 2012-05-10T22:13:53.930 に答える