Langton’s Ants, For going further…

It exists a lot of things we can do for improving this code : to click for adding an ant, add a user interface with some keys parameters…


I°) One ant, one click

In the first place, let’s add the feature : adding an ant by cliking on the grid. For this, we need a new parameter for stocking the ants.

ArrayList<Ant> ants;

We need to initialize this ArrayList :

void setup() {  
  ants = new ArrayList();  
}

In the draw() part, we need to update each ant, so a for loop is perfect for this :

  // Update position of all the ants, then display it. 
  for (Ant ant : ants) {
    ant.update();
  }

Finally, we need to add the functionality of click itself. The mousePressed() method allow us to do this, in a very simple way. She is launched each time that a button from the mouse is pressed. In this method, we add the new ant to the new parameter we created : ants.

// ***********************
void mousePressed() {
  ants.add(new Ant(mouseX/rows, mouseY/cols, color(random(255), random(255), random(255))));
} 


II°) Results – One ant, one click


III°) GUI – General User Interface

In this part, i will use the librairie controlP5 that i find very easy to use, and pleasant to see.

The goal is to get this :

This image has an empty alt attribute; its file name is image-10.png
GUI – Main parameters

We need the following objects :

  1. One accordeon, which assemble the groups objects together,
  2. One group, which contain the elements we want to use,
  3. Three sliders, two of which with ticks.
  4. Two radioButtons, for Play and Reset.

Let’s start by creating a new class that we will call GUI.
At the begenning, we need some parameters, two actually. the position (X, Y) of the ant on the grid.

 int posX;
 int posY;

  // ****************************************************************************
  //                                   CONSTRUCTOR 
  // ****************************************************************************

  GUI(int posX_, int posY_) {
    posX = posX_;
    posY = posY_;
  }

For creating all the objects we talked previously, we need :

// ************************
  void gui() {
    // Init ControlP5

    cp5.setColorForeground(0xffDC143C);
    cp5.setColorBackground(0xff660000);
    cp5.setColorActive(0xffff0000);


    // ********************************************************************
    //                     GROUPE 1 : Create some controllers
    //                    RadioButton x1, slider x2, button x1
    // ********************************************************************
    // Init Groupe 1
    Group g1 = cp5.addGroup("Langtons Ants - Main parameters")
      .setBackgroundColor(color(0, 90))
      .setBackgroundHeight(380)
      .setBarHeight(50);


    // Init sliders, radioButton and button
    cp5.addSlider("Nbr Cycles")
      .setPosition(10, 20)
      .setSize(400, 45)
      .setRange(100, 1000)
      .setValue(nbrCycle) //10000
      .setDecimalPrecision(0)
      .moveTo(g1);


    cp5.addSlider("Nbr Steps")
      .setPosition(10, 115)
      .setSize(400, 45)
      .setRange(2, 7) // values can range from big to small as well
      .setValue(2)
      .setNumberOfTickMarks(6)
      .setDecimalPrecision(0)
      .setSliderMode(Slider.FLEXIBLE)
      .moveTo(g1);

    cp5.addSlider("Size Grid")
      .setPosition(10, 200)
      .setSize(400, 45)
      .setRange(3, 15) // values can range from big to small as well
      .setValue(15)
      .setNumberOfTickMarks(13)
      .setDecimalPrecision(0)
      .setSliderMode(Slider.FLEXIBLE)
      .moveTo(g1);


    cp5.addRadioButton("PlayButton")
      .setPosition(150, 295)
      .setItemWidth(55)
      .setItemHeight(55)
      .addItem("Play", 0)
      .setColorLabel(color(255))
      .activate(2)
      .moveTo(g1);

    cp5.addRadioButton("ResetButton")
      .setPosition(350, 295)
      .setItemWidth(55)
      .setItemHeight(55)
      .addItem("Reset", 0)
      .setColorLabel(color(255))
      .activate(0)
      .moveTo(g1);






    //// ********************************************************************
    ////    Groupe1 : Load and apply the font and captionlabels's content 
    //// ********************************************************************
    pfont = createFont("Georgia", 45, true); // use true/false for smooth/no-smooth
    font = new ControlFont(pfont, 45);
    cp5.setFont(font);


    // ********************************************************************
    //                               Accordion : 
    //                                 Groupe1
    // ********************************************************************
    // create a new accordion
    // add g1 to the accordion.
    accordion = cp5.addAccordion("acc")
      .setPosition(posX, posY)
      .setWidth(890)
      .addItem(g1)
      .open()
      .disableCollapse();

    //accordion.setCollapseMode(Accordion.SINGLE);
  }

Now that the interface is created, and that each parameters is linked to the good object, we need to make this interface interactive. For this, in the main part, we need to know at every instant the state of the buttons Start and Reset, and also the state of the sliders.

The code for main part is :

import controlP5.*;
import java.util.*;


// ****************************************************************************
//                                 PARAMETERS
// ****************************************************************************

// Grid parameter
int w, h;
int rows = 10; // rows size of one square from the grid
int cols = 10; // cols size of one square from the grid
int[][] grid;

// Nbr of mouvement a n ant is allow to do during one frame. 
int nbrCycle = 100;

// Ant's parameters
ArrayList<Ant> ants;

// GUI parameters
ControlP5 cp5;
GUI gui;
Accordion accordion;
PFont pfont;
ControlFont font;
float play = 0;
boolean play_b = false;
float reset = 0;
boolean reset_b = false;
int nbrStep = 2;



// ****************************************************************************
//                                   SETUP
// ****************************************************************************
void setup() {
  //size(800, 800);
  fullScreen();
  //orientation(LANDSCAPE);
  orientation(PORTRAIT);


  // Grid init
  w = width/rows;
  h = height/cols;
  grid = new int[w][h];

  // ants init
  ants = new ArrayList();  

  // GUI init
  cp5 = new ControlP5(this);
  gui = new GUI(20, 20);
  //pfont = createFont("Georgia", 45, true); // use true/false for smooth/no-smooth
  //textFont(pfont);
  gui.gui( );
}



// ****************************************************************************
//                                   DRAW
// ****************************************************************************
void draw() {
  background(255);

  nbrCycle = (int)(cp5.getController("Nbr Cycles").getValue());
  if (reset_b) {
    nbrStep = (int)(cp5.getController("Nbr Steps").getValue());

    rows = (int)(cp5.getController("Size Grid").getValue());
    cols = rows;

    // Grid init
    w = width/rows;
    h = height/cols;
    grid = new int[w][h];
  }


  play = cp5.getController("Play").getValue();
  if (play == 0) play_b = true;
  if (play == 1) play_b = false;

  reset = cp5.getController("Reset").getValue();
  if (reset == 0) reset_b = false;
  if (reset == 1) reset_b = true;


  // **************************************************************
  //                    RESET button is pressed
  // **************************************************************
  if (reset_b) { // IF we push reset button
    reset();
  }

  if (!play_b) {
    // Update position of all the ants, then display it. 
    for (Ant ant : ants) {
      ant.update(false);
    }
  }


  //All ants share a common "2D universe". Their interactions got
  //the same actions on this universe. A commun display is necessary. 
  displayAntActions();
}



// ****************************************************************************
//                                FUNCTIONS
// ****************************************************************************
// Add new ant each time we clicked
void mousePressed() {
  if (!play_b) {
    ants.add(new Ant(mouseX/rows, mouseY/cols, color(random(255), random(255), random(255))));
  }
}




void displayAntActions() {
  //All ants share a common "2D universe". Their interactions got
  //the same actions on this universe. A commun display is necessary. 
  for (int i =0; i < w; i++) {
    for (int j =0; j < h; j++) {
      if (grid[i][j] == 1) {
        fill(139, 0, 0);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
      if (grid[i][j] == 2) {
        fill(255, 160, 122);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
      if (grid[i][j] == 3) {
        fill(220, 20, 60);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
      if (grid[i][j] == 4) {
        fill(240, 128, 128);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
      if (grid[i][j] == 5) {
        fill(178, 34, 34);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
      if (grid[i][j] == 6) {
        fill(219, 112, 147);
        ellipse(i*rows + rows/2, j*cols + cols/2, rows, cols);
      }
    }
  }
}



// ****************************************************************************
// Reset...
void reset() {
  for (int i=0; i < ants.size(); i++) {      
    ants.remove(ants.get(0));
  }
  for (int i =0; i < w; i++) {
    for (int j =0; j < h; j++) {
      grid[i][j] = 0;
    }
  }
}


IV°) Results – GUI

Leave a comment

Design a site like this with WordPress.com
Get started
search previous next tag category expand menu location phone mail time cart zoom edit close