2009-12-29 5 views
0

Je dessine une simulation d'automate cellulaire sur une toile Flex. Je calcule alternativement l'état de l'automate avec la mise à jour des graphismes sur le Panel. Cependant, la mise à jour du Panel ne semble pas "suivre" la mise à jour de l'état de CA. Je me demande si je fais quelque chose de mal avec ma manipulation du code graphique. Le code est ci-dessous. Désolé, c'est trop long, mais je ne pense pas que le problème se produira avec quelque chose de plus simple (eh bien, ce sera probablement le cas, mais je ne suis pas certain de vouloir prendre le temps de le trouver).Panneau Flex non mis à jour

<?xml version="1.0" encoding="utf-8"?> 
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init();"> 
    <mx:Script> 
     <![CDATA[ 
     private static const universeRadius:uint = 8; 

     private var universes:Array = new Array(); 
     private var currentUniverse:uint = 0; 
     private var squareHeight:uint; 
     private var squareWidth:uint; 

     private function init():void { 
      squareHeight = myCanvas.height/universeRadius; 
      squareWidth = myCanvas.width/universeRadius; 
      initUniverses(); 

      while (true) { 
       trace("Calling draw()"); 
       draw(); 
       trace("Calling updateUniverse()"); 
       updateUniverse(); 
      } 
     } 

     private function initUniverses():void { 
      var universe0:Array = new Array(); 
      var universe1:Array = new Array(); 

      var i:int; 
      for (i = 0; i < universeRadius; i++) { 
       var universe0Row:Array = new Array(); 
       var universe1Row:Array = new Array(); 
       var j:int; 
       for (j = 0; j < universeRadius; j++) { 
        if (Math.random() < 0.5) { 
         universe0Row[j] = 0; 
        } else { 
         universe0Row[j] = 1; 
        } 
        universe1Row[j] = 0; 
       } 
       universe0[i] = universe0Row; 
       universe1[i] = universe1Row; 
      } 

      universes[0] = universe0; 
      universes[1] = universe1; 
     } 

     private function normalize(pos:int):int { 
      return (pos + universeRadius) % universeRadius; 
     } 

     private function updateUniverse():void { 
      var newUniverse:int = 1 - currentUniverse; 
      var i:int; 
      for (i = 0; i < universeRadius; i++) { 
       var j:int; 
       for (j = 0; j < universeRadius; j++) { 
        var dx:int; 
        var dy:int; 
        var count:int = 0; 
        for (dx = -1; dx <= 1; dx++) { 
         var neighborX:int = normalize(i + dx); 
         for (dy = -1; dy <= 1; dy++) { 
          var neighborY:int = normalize(j + dy); 
          if ((dx != 0 || dy != 0) && 
           universes[currentUniverse][neighborX][neighborY] == 1) { 
            count++; 
           } 
         } 
        } 
        var currentCell:int = universes[currentUniverse][i][j]; 
        if (currentCell == 1) { 
         // 1. Any live cell with fewer than two live neighbours 
         // dies, as if caused by underpopulation. 
         if (count < 2) { 
          universes[newUniverse][i][j] = 0; 
         } 
         // 2. Any live cell with more than three live neighbours 
         // dies, as if by overcrowding. 
         else if (count > 3) { 
          universes[newUniverse][i][j] = 0; 
         } 
         // 3. Any live cell with two or three live neighbours 
         // lives on to the next generation. 
         else { 
          universes[newUniverse][i][j] = 1; 
         } 
        } else { 
         // 4. Any dead cell with exactly three live neighbours 
         // becomes a live cell. 
         if (count == 3) { 
          universes[newUniverse][i][j] = 1; 
         } else { 
          universes[newUniverse][i][j] = 0; 
         } 
        } 
       } 
      } 

      currentUniverse = newUniverse; 
     } 

     private function draw():void { 
      myCanvas.graphics.clear(); 
      myCanvas.graphics.beginFill(0xFFFFFF, 1.0); 
      myCanvas.graphics.drawRect(0, 0, myCanvas.width, myCanvas.height); 
      var i:int; 
      for (i = 0; i < universeRadius; i++) { 
       var j:int; 
       for (j = 0; j < universeRadius; j++) { 
        if (universes[currentUniverse][i][j] == "1") { 
         myCanvas.graphics.beginFill(0x000000, 1.0); 
         myCanvas.graphics.drawRect(
          j * squareWidth, i * squareHeight, squareWidth, squareHeight) 
        } 
       } 
      } 
      myCanvas.graphics.endFill(); 
     } 
     ]]> 
    </mx:Script> 
    <mx:Panel title="Life" height="95%" width="95%" 
     paddingTop="5" paddingLeft="5" paddingRight="5" paddingBottom="5"> 

     <mx:Canvas id="myCanvas" borderStyle="solid" height="100%" width="100%"> 
     </mx:Canvas> 
    </mx:Panel> 
</mx:Application> 

Répondre

1

Effrayant:

while (true) { 

Flex est mono-thread, donc je pense que vous ne jamais donner les UIComponents une chance de mettre à jour pleinement. Les alternatives consisteraient à exécuter les méthodes draw et update sur un temporisateur ou à les exécuter sur l'événement ENTER_FRAME. Chacune de ces laisseraient les mises à jour de la liste d'affichage se produisent entre votre

private function cycleUniverse(event:Event):void { 
    updateUniverse(); 
    draw(); 
} 

puis l'une des

private var t:Timer; 

private function init():void { 
    t = new Timer(500); // every 500 ms 
    t.addEventListener(TimerEvent.Timer, cycleUniverse); 
    t.start(); 
} 

ou

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" enterFrame="cycleUniverse(event)"> 
+0

J'ai fini par mettre les mises à jour sur un événement de minuterie et fonctionne bien. Je sais que "while (true)" est effrayant, mais c'est une ancienne version du code et j'ai prévu de le changer plus tard. Merci! –

+0

Seulement effrayant à cause du filetage unique de Flex. Ailleurs, alors que (vrai) loin. –