how to make objects interact each other

edited May 2016 in Questions about Code

so, i want to make a game about push box. which when the ellipse touch the box, the box will move. i don't know how to make the ellipse and box interact each other. can anyone please help me? thank you very much

float oX = 250; float oY = 250; PFont font; String time = "030"; int t; int interval = 30;

float speed = 2;

boolean upPressed = false; boolean downPressed = false; boolean leftPressed = false; boolean rightPressed = false; void setup(){ size (400,450); font = createFont("Arial", 10); background(255); fill(0); }

void draw(){

if (upPressed) { oY -= speed; } if (downPressed) { oY += speed; } if (leftPressed) { oX -= speed; } if (rightPressed) { oX += speed; } background(255);

ellipse(oX, oY, 40,40); rect(95,200,50,50); rect(35,255,50,50); rect(200,255,50,50); rect(145,310,50,50);

t = interval-int(millis()/1000);
time = nf(t , 2);
if(t == 0){
  textSize(32);
  text("GAME OVER",10,30);
}

text(time, 100, 100);

strokeWeight(3); line(90,150,150,150); line(150,150,150,250); line(150,250,300,250); line(300,250,300,310); line(300,310,200,310); line(200,310,200,410); line(200,410,140,410); line(140,410,140,310); line(140,310,1,310); line(1,310,1,250); line(1,250,90,250); line(90,250,90,150);

} void keyPressed(KeyEvent e) { if (key == CODED) { if (keyCode == UP) { upPressed = true; } else if (keyCode == DOWN) { downPressed = true; } else if (keyCode == LEFT) { leftPressed = true; } else if (keyCode == RIGHT) { rightPressed = true; } } }

void keyReleased(KeyEvent e) { if (key == CODED) { if (keyCode == UP) { upPressed = false; } else if (keyCode == DOWN) { downPressed = false; } else if (keyCode == LEFT) { leftPressed = false; } else if (keyCode == RIGHT) { rightPressed = false; } } }

«13

Answers

  • edited May 2016 Answer ✓
    float oX = 250; 
    float oY = 250; 
    PFont font; 
    String time = ""; // "030"; 
    int t; 
    int interval = 30;
    
    float speed = 2;
    
    boolean upPressed = false; 
    boolean downPressed = false; 
    boolean leftPressed = false; 
    boolean rightPressed = false;
    
    PVector r1=new PVector(95, 200);
    PVector r2=new PVector(35, 255);
    PVector r3=new PVector(200, 255);
    PVector r4=new PVector(145, 310);
    
    // diameter, so when we need the radius we say ellipseWidth/2 
    int ellipseWidth=40;
    
    // width and height
    int rectWidth=50; 
    
    boolean gameOver=false; 
    int startTime;
    
    void setup() { 
      size (400, 450); 
      font = createFont("Arial", 10); 
      background(255); 
      startTime=millis(); 
      // fill(0);
    }
    
    void draw() {
      background(255);
    
      fill(0); 
      stroke(0); 
    
      rect(r1.x, r1.y, rectWidth, rectWidth); 
      rect(r2.x, r2.y, rectWidth, rectWidth); 
      rect(r3.x, r3.y, rectWidth, rectWidth); 
      rect(r4.x, r4.y, rectWidth, rectWidth);
    
      if (upPressed) { 
        oY -= speed;
      } 
      if (downPressed) { 
        oY += speed;
      } 
      if (leftPressed) { 
        oX -= speed;
      } 
      if (rightPressed) { 
        oX += speed;
      } 
    
      collision(r1);
      collision(r2);
      collision(r3);
      collision(r4);
    
      fill(0, 255, 0);
      noStroke(); 
      ellipse(oX, oY, ellipseWidth, ellipseWidth);
      fill(255, 0, 0);//red
      ellipse(oX, oY, 3, 2);
    
      // if NOT game over yet 
      if (!gameOver) {
        t = interval-int((millis()-startTime)/1000);
        time = nf(t, 2);
        if (t == 0) {
          gameOver=true;
        }
      }
    
      // if game over 
      if (gameOver) {
        textSize(32);
        text("GAME OVER", 10, 30);
      }
    
      // if NOT game over yet
      if (!gameOver) {
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
      }
    
      fill(0); 
      stroke(0); 
      strokeWeight(3); 
      line(90, 150, 150, 150); 
      line(150, 150, 150, 250); 
      line(150, 250, 300, 250); 
      line(300, 250, 300, 310); 
      line(300, 310, 200, 310); 
      line(200, 310, 200, 410); 
      line(200, 410, 140, 410); 
      line(140, 410, 140, 310); 
      line(140, 310, 1, 310); 
      line(1, 310, 1, 250); 
      line(1, 250, 90, 250); 
      line(90, 250, 90, 150);
    } // draw
    
    // ----------------------------------------------
    
    void keyPressed(KeyEvent e) { 
    
      // if NOT game over yet
      if (!gameOver) {
    
        if (key == CODED) { 
          if (keyCode == UP) { 
            upPressed = true;
          } else if (keyCode == DOWN) { 
            downPressed = true;
          } else if (keyCode == LEFT) { 
            leftPressed = true;
          } else if (keyCode == RIGHT) { 
            rightPressed = true;
          }
        }
      } else
      {
        // if game over 
        // space bar 
        if (key==' ') {
          // reset 
          gameOver=false; 
          r1=new PVector(95, 200);
          r2=new PVector(35, 255);
          r3=new PVector(200, 255);
          r4=new PVector(145, 310);
          oX=random(ellipseWidth/2, width-ellipseWidth/2);
          oY=random(ellipseWidth/2, height-ellipseWidth/2);
          time="030";
          t=30; 
          startTime=millis(); 
          textSize(10);
        }
      }
    }
    
    void keyReleased(KeyEvent e) { 
      if (key == CODED) { 
        if (keyCode == UP) { 
          upPressed = false;
        } else if (keyCode == DOWN) { 
          downPressed = false;
        } else if (keyCode == LEFT) { 
          leftPressed = false;
        } else if (keyCode == RIGHT) { 
          rightPressed = false;
        }
      }
    }
    //
    void collision(PVector r1) {
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>r1.y-6 && oY+ellipseWidth/2<r1.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX-ellipseWidth/2<r1.x+rectWidth+5 && oX-ellipseWidth/2>r1.x-rectWidth/4-5 )
        {
          r1.x--;
          return;
        }
      }
    
      // coming from right towards rect
      if (oY-ellipseWidth/2>r1.y-6 && oY+ellipseWidth/2<r1.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<r1.x+13 && oX+ellipseWidth/2>r1.x-2 )
        {
          r1.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<r1.y+rectWidth+5 && oY-ellipseWidth/2>r1.y-rectWidth/4-5 )
        {
          r1.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<r1.y+13 && oY+ellipseWidth/2>r1.y-2 )
        {
          r1.y++; // go
          return;
        }
      }
    }
    
  • edited May 2016 Answer ✓

    you use variables for the position of the ellipse

    you have to do the same with the rects so that you can recalculate the position of the rects when the ball is pushing them

    To achieve this, I use the data type PVector for the 4 rects (see reference)

    the collision is in the part collision which gets all 4 rects as a parameter

    later you want to have them in an array

    game over

    also I introduced the var gameOver and some related code lines to reset the thing with space bar

    grid

    if you had a grid underneath we could let the boxes move like on tracks and stop at the black lines

    we'll come to that later

    Best, Chrisir ;-)

  • Hello Chrisir,

    thank you so much for your kind reply! I really appreciate it as i now understand the use of new codes you showed me! i've made the grid on size 500,500 to be put underneath so we could let the box stay on track and stopping at the black lines. because when i applied grid with my code, there's error about void keyReleased(KeyEvent e). would you like to help? Once again, thank you so much for your help!

    int horizontal = 10; int vertical = 10;

    void setup() { size (500,500); }

    void draw() { background (255); stroke(0);

    float jhorizontal = (float)height/horizontal; float jvertical = (float)width/vertical;

    for(int i = 0; i < horizontal; i++) { line(0, ijhorizontal, width, ijvertical);

    }

    for(int i = 0; i < vertical; i++) { line (ijhorizontal,0,ijvertical, height); } }

  • edited July 2016

    Explanation line 165 to 175

    • 1st we check if on y axis the ellipse is next to the rect with > and <

    • 2nd on x axis if it's next to the box

  • if so we move the box

  • edited July 2016

    We have to say /2 sometimes to convert the diameter to radius

  • edited May 2016

    here's the right code for the grid, i mistakenly type int horizontal = 10; int vertical = 10;

    void setup()
    {
      size (500,500);
    }
    
    void draw()
    {
      background (255);
      stroke(0);
    
      float jarakhorizontal = (float)height/horizontal;
      float jarakvertical = (float)width/vertical;
    
      for(int i = 0; i < horizontal; i++)
      {
        line(0, i*jarakhorizontal, width, i*jarakvertical);
    
      }
    
      for(int i = 0; i < vertical; i++)
      {
        line (i*jarakhorizontal,0,i*jarakvertical, height);
      }
    }
    

    thank you for your explanation !

  • You need to look at arrays

    when you store the data (where is wall, where is a corridor for the box) you can check those data I guess

  • edited July 2016

    Especially when you plan to have multiple levels, we could make a grid that knows the position of the boxes and the position of the walls etc. for every level

  • what is the goal of the game please?

  • // game control
    final int game=0; 
    final int gameOver=1;
    int state=game;
    
    // ellipse 
    float oX = 250; 
    float oY = 250; 
    // diameter, so when we need the radius we say ellipseWidth/2 
    int ellipseWidth=40;
    
    PFont font; 
    
    String time = ""; 
    int t;
    int startTime;
    int interval = 30;
    
    float speed = 2;
    
    boolean upPressed = false; 
    boolean downPressed = false; 
    boolean leftPressed = false; 
    boolean rightPressed = false;
    
    // rects 
    PVector r1=new PVector(95, 200);
    PVector r2=new PVector(35, 255);
    PVector r3=new PVector(200, 255);
    PVector r4=new PVector(145, 310);
    
    // width and height of rect
    int rectWidth=50; 
    
    // mouse: drag and drop 
    boolean hold=false; 
    
    // ------------------------------------------------------
    
    void setup() { 
      size (400, 450); 
      font = createFont("Arial", 10); 
      background(255); 
      startTime=millis();
    }
    
    void draw() {
    
      switch(state) {
    
      case game: 
        // if NOT game over yet
    
        showScene();
    
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
    
        // check collisions 
        collision(r1);
        collision(r2);
        collision(r3);
        collision(r4);
    
        if (upPressed) { 
          oY -= speed;
        } 
        if (downPressed) { 
          oY += speed;
        } 
        if (leftPressed) { 
          oX -= speed;
        } 
        if (rightPressed) { 
          oX += speed;
        } 
    
        if (hold) {
          oX=mouseX;
          oY=mouseY;
        }
    
        t = interval-int((millis()-startTime)/1000);
        time = nf(t, 2);
        if (t == 0) {
          state=gameOver;
        }
    
        break; 
    
      case gameOver: 
        showScene(); 
        textSize(32);
        text("GAME OVER", 50, 30);
        break; 
    
      default:
        println("Error 101, unknown state : "
          + state 
          + ".");
        break;
      }
    } // draw
    
    // -------------------------------------------------------
    
    void showScene() {
      // this is for both state game and state gameOver
      // (no interactive parts here)
    
      background(255);
    
      fill(0); 
      stroke(0); 
      strokeWeight(3); 
      line(90, 150, 150, 150); 
      line(150, 150, 150, 250); 
      line(150, 250, 300, 250); 
      line(300, 250, 300, 310); 
      line(300, 310, 200, 310); 
      line(200, 310, 200, 410); 
      line(200, 410, 140, 410); 
      line(140, 410, 140, 310); 
      line(140, 310, 1, 310); 
      line(1, 310, 1, 250); 
      line(1, 250, 90, 250); 
      line(90, 250, 90, 150);
    
      fill(0); 
      stroke(0); 
      rect(r1.x, r1.y, rectWidth, rectWidth); 
      rect(r2.x, r2.y, rectWidth, rectWidth); 
      rect(r3.x, r3.y, rectWidth, rectWidth); 
      rect(r4.x, r4.y, rectWidth, rectWidth);
    
      // show ellipse
      fill(0, 255, 0);
      noStroke(); 
      ellipse(oX, oY, ellipseWidth, ellipseWidth);
      fill(255, 0, 0);//red
      ellipse(oX, oY, 3, 2);
    }
    
    // ----------------------------------------------
    
    void keyPressed(KeyEvent e) { 
    
      // if NOT game over yet
      if (state==game) {
    
        if (key == CODED) { 
          if (keyCode == UP) { 
            upPressed = true;
          } else if (keyCode == DOWN) { 
            downPressed = true;
          } else if (keyCode == LEFT) { 
            leftPressed = true;
          } else if (keyCode == RIGHT) { 
            rightPressed = true;
          }
        } else {
          if (key=='x') {
            reset();
          }
        } // else
      } else
      {
        // if game over 
        // space bar 
        if (key==' ') {
          // reset 
          reset();
        }
      }
    }
    
    void keyReleased(KeyEvent e) { 
      if (key == CODED) { 
        if (keyCode == UP) { 
          upPressed = false;
        } else if (keyCode == DOWN) { 
          downPressed = false;
        } else if (keyCode == LEFT) { 
          leftPressed = false;
        } else if (keyCode == RIGHT) { 
          rightPressed = false;
        }
      }
    }
    
    void mousePressed() {
      if (state==game) {
        oX=mouseX;
        oY=mouseY;
        hold=true;
      }
    }
    
    void mouseReleased() {
      hold=false;
    }
    
    // ------------------------------------------------------
    // Tools 
    
    void reset() {
    
      state=game;
    
      r1=new PVector(95, 200);
      r2=new PVector(35, 255);
      r3=new PVector(200, 255);
      r4=new PVector(145, 310);
      oX=random(ellipseWidth/2, width-ellipseWidth/2);
      oY=random(ellipseWidth/2, height-ellipseWidth/2);
      time="030";
      t=30; 
      startTime=millis(); 
      textSize(10);
    }
    
    void collision(PVector rLocal) {
    
      // collision
    
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>rLocal.y-6 && 
        oY+ellipseWidth/2<rLocal.y+rectWidth+6 ) { 
    
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
    
        if (oX-ellipseWidth/2 < rLocal.x+rectWidth+2 && 
          oX-ellipseWidth/2 > rLocal.x-rectWidth/4-5 )
        {
          rLocal.x -= (rLocal.x + rectWidth) - (oX-ellipseWidth/2); 
          return;
        }
      }
    
      // coming from right towards rect
      if (oY-ellipseWidth/2>rLocal.y-6 && 
        oY+ellipseWidth/2<rLocal.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<rLocal.x+13 && 
          oX+ellipseWidth/2>rLocal.x-2 )
        {
          rLocal.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>rLocal.x-6 && 
        oX+ellipseWidth/2<rLocal.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<rLocal.y+rectWidth+5 && 
          oY-ellipseWidth/2>rLocal.y-rectWidth/4-5 )
        {
          rLocal.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>rLocal.x-6 && 
        oX+ellipseWidth/2<rLocal.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<rLocal.y+13 && 
          oY+ellipseWidth/2>rLocal.y-2 )
        {
          rLocal.y++; // go
          return;
        }
      }
    }
    //
    
  • // game control
    final int game=0; 
    final int gameOver=1;
    final int gameWon=2;
    int state=game;
    
    // ellipse 
    float oX = 250; 
    float oY = 250; 
    // diameter, so when we need the radius we say ellipseWidth/2 
    int ellipseWidth=40;
    
    PFont font; 
    
    String time = ""; 
    int t;
    int startTime;
    int interval = 30;
    
    float speed = 2;
    
    boolean upPressed = false; 
    boolean downPressed = false; 
    boolean leftPressed = false; 
    boolean rightPressed = false;
    
    // rects 
    PVector r1=new PVector(95, 200);
    PVector r2=new PVector(35, 255);
    PVector r3=new PVector(200, 255);
    PVector r4=new PVector(145, 310);
    // width and height of rect
    int rectWidth=50; 
    
    // mouse: drag and drop 
    boolean hold=false; 
    
    // Player
    Player thePlayer = new Player();
    
    PVector target=new PVector(0, 277);
    
    // bullets
    final float bulletFlySpeed = 4.2;  // how fast bullet flies
    final int fireSpeed=200; // how often you fire / distance between bullets
    int lastFired=millis();  // timer to determine when next bullet starts 
    // ammo not in use 
    int ammoCount = 70; 
    
    // ------------------------------------------------------
    // main functions 
    
    void setup() { 
      size (400, 450); 
      font = createFont("Arial", 10); 
      background(255); 
      startTime=millis();
    }
    
    void draw() {
    
      switch(state) {
    
      case game: 
        // if NOT game over yet
    
        showScene();
    
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
    
        // check collisions 
        collision(r1);
        collision(r2);
        collision(r3);
        collision(r4);
    
        if (upPressed) { 
          oY -= speed;
        } 
        if (downPressed) { 
          oY += speed;
        } 
        if (leftPressed) { 
          oX -= speed;
        } 
        if (rightPressed) { 
          oX += speed;
        } 
    
        if (hold) {
          oX=mouseX;
          oY=mouseY;
        }
    
        thePlayer.fire();
        thePlayer.draw();
    
        t = interval-int((millis()-startTime)/1000);
        time = nf(t, 2);
        if (t == 0) {
          state=gameOver;
        }
        break; 
    
      case gameOver: 
        showScene(); 
        textSize(32);
        fill(255, 2, 2); 
        text("GAME OVER", 50, 30);
        textSize(11);
        textAlign(CENTER);
        text("Hit space to continue", width/2, height-10);
        textAlign(LEFT);
        break; 
    
      case gameWon:
        // win 
        showScene(); 
        textSize(32);
        fill(255, 2, 2); 
        text("You WON", 50, 30);
        textSize(11);
        textAlign(CENTER);
        text("Hit space to continue", width/2, height-10);
        textAlign(LEFT);
        break; 
    
      default:
        println("Error 101, unknown state : "
          + state 
          + ".");
        break;
      }
    } // draw
    
    // ----------------------------------------------
    // input functions 
    
    void keyPressed(KeyEvent e) { 
    
      // if NOT game over yet
      if (state==game) {
    
        keyPressedForStateGame();
      } else
      {
        // if game over 
        // space bar 
        if (key==' ') {
          // reset 
          reset();
        }
      }
    }
    
    void keyPressedForStateGame() {
      if (key == CODED) { 
        if (keyCode == UP) { 
          upPressed = true;
        } else if (keyCode == DOWN) { 
          downPressed = true;
        } else if (keyCode == LEFT) { 
          leftPressed = true;
        } else if (keyCode == RIGHT) { 
          rightPressed = true;
        }
      } else {
        if (key=='x') {
          reset();
        }
      } // else
    }
    
    void keyReleased(KeyEvent e) { 
      if (key == CODED) { 
        if (keyCode == UP) { 
          upPressed = false;
        } else if (keyCode == DOWN) { 
          downPressed = false;
        } else if (keyCode == LEFT) { 
          leftPressed = false;
        } else if (keyCode == RIGHT) { 
          rightPressed = false;
        }
      }
    }
    
    void mousePressed() {
      if (state==game) {
        oX=mouseX;
        oY=mouseY;
        hold=true;
      }
    }
    
    void mouseReleased() {
      hold=false;
    }
    
    // ------------------------------------------------------
    // Tools 
    
    void showScene() {
      // this is for both state game and state gameOver
      // (no interactive parts here)
    
      background(255);
    
      fill(0); 
      stroke(0); 
      strokeWeight(3);
    
      stroke(220, 0, 0); 
      line(90, 150, 150, 150);
    
      stroke(0); 
      line(150, 150, 150, 250); 
      line(150, 250, 300, 250); 
      line(300, 250, 300, 310); 
      line(300, 310, 200, 310); 
      line(200, 310, 200, 410); 
      line(200, 410, 140, 410); 
      line(140, 410, 140, 310); 
      line(140, 310, 1, 310); 
      line(1, 310, 1, 250); 
      line(1, 250, 90, 250); 
      line(90, 250, 90, 150);
    
      fill(0); 
      stroke(0); 
      rect(r1.x, r1.y, rectWidth, rectWidth); 
      rect(r2.x, r2.y, rectWidth, rectWidth); 
      rect(r3.x, r3.y, rectWidth, rectWidth); 
      rect(r4.x, r4.y, rectWidth, rectWidth);
    
      fill(255, 0, 0); 
      noStroke(); 
      rect(target.x, target.y, 4, 4);
    
      // show ellipse
      fill(0, 255, 0);
      noStroke(); 
      ellipse(oX, oY, ellipseWidth, ellipseWidth);
      fill(255, 0, 0);//red
      ellipse(oX, oY, 3, 2);
    }
    
    void reset() {
    
      state=game;
    
      r1=new PVector(95, 200);
      r2=new PVector(35, 255);
      r3=new PVector(200, 255);
      r4=new PVector(145, 310);
      oX=random(ellipseWidth/2, width-ellipseWidth/2);
      oY=random(ellipseWidth/2, height-ellipseWidth/2);
      time="030";
      t=30; 
      startTime=millis(); 
      textSize(10);
    }
    
    void collision(PVector rLocal) {
    
      // collision
    
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>rLocal.y-6 && 
        oY+ellipseWidth/2<rLocal.y+rectWidth+6 ) { 
    
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
    
        if (oX-ellipseWidth/2 < rLocal.x+rectWidth+2 && 
          oX-ellipseWidth/2 > rLocal.x-rectWidth/4-5 )
        {
          rLocal.x -= (rLocal.x + rectWidth) - (oX-ellipseWidth/2); 
          return;
        }
      }
    
      // coming from right towards rect
      if (oY-ellipseWidth/2>rLocal.y-6 && 
        oY+ellipseWidth/2<rLocal.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<rLocal.x+13 && 
          oX+ellipseWidth/2>rLocal.x-2 )
        {
          rLocal.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>rLocal.x-6 && 
        oX+ellipseWidth/2<rLocal.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<rLocal.y+rectWidth+5 && 
          oY-ellipseWidth/2>rLocal.y-rectWidth/4-5 )
        {
          rLocal.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>rLocal.x-6 && 
        oX+ellipseWidth/2<rLocal.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(rLocal.x, rLocal.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<rLocal.y+13 && 
          oY+ellipseWidth/2>rLocal.y-2 )
        {
          rLocal.y++; // go
          return;
        }
      }
    }
    
    // ================================================================
    // classes
    
    class Player {
    
      ArrayList<Bullet> bullets;   
      PVector position, velocity; // contains x and y...
    
      Player() {
        bullets  = new ArrayList();   
        position = new PVector(297, 277);
        velocity = new PVector();
        velocity.x = 0;
        velocity.y = 0;
      }
    
      void fire() {     // new2
        if (fireSpeed<=millis()-lastFired) {
          if (ammoCount>0) {
            // ammoCount--;
            lastFired=millis();
    
            float xSpeed ;
            float ySpeed ; 
            float angle = PI; //update(mouseX, mouseY);
            xSpeed = cos(angle);
            ySpeed = sin(angle);
            xSpeed*= bulletFlySpeed;
            ySpeed*= bulletFlySpeed;
            if (ySpeed>0)
              ySpeed=0;
            bullets.add ( new Bullet( 
              position.x, position.y+2, 
              xSpeed, ySpeed, 
              5 ));
          } // if
        } // if
      } // method 
    
      float update(int mx, int my) {
        //determines angle to mouse
        float angle = atan2(float(my)-(position.y-14), float(mx)-(position.x+12));
        return angle;
      }
    
      void draw() {
        // draw player & bullets
        //
        // draw player 
        pushMatrix();
        translate(position.x, position.y);
        noStroke();
        fill(255, 3, 3);
        rect (0, 0, 6, 6);
        popMatrix(); // undoes all
    
        // draw bullets
        for (Bullet currentBullet : bullets ) {     // new1 
          // println ("************************");
          currentBullet.move();
          currentBullet.display();
        }
    
        // With an array, we say length, with an ArrayList, we say size()
        // The length of an ArrayList is dynamic
        // Notice how we are looping through the ArrayList backwards
        // This is because we are deleting elements from the list  
        for (int i = bullets.size()-1; i >= 0; i--) { 
          // An ArrayList 
          Bullet currentBullet = bullets.get(i);
          if (currentBullet.finished()) {
            // Items can be deleted with remove()
            bullets.remove(i);
          }
        }
      }
    }
    //
    class Bullet {
    
      // Bullet - Simple class for bullets
      // http://www.processing.org/learning/topics/arraylistclass.html
    
      float x;
      float y;
      float speedX ;  
      float speedY;
      float w;
      float life = 255;
    
      Bullet(float tempX, float tempY, // new2
        float tempSpeedX, float tempSpeedY, 
        float tempW) {
        x = tempX;
        y = tempY;
        w = tempW;
        speedX = tempSpeedX; // 4.2; // new2 
        speedY = tempSpeedY; // 0;
      }
    
      void move() {
        // Add speed to location
        x = x + speedX; 
        y = y + speedY;
        //
        // kill bullet when outside screen
        if (x<4) 
          life=-1;
        if (y<4) 
          life=-1;
        if (x>width-4) 
          life=-1;
        if (y>width-4) 
          life=-1;
    
        // check collisions 
        killWhenInRect(r1);
        killWhenInRect(r2);
        killWhenInRect(r3);
        killWhenInRect(r4);
    
        // target -> winning
        if (x>=target.x && y>=target.y && 
          x<=target.x+4 && y<=target.y+4)   
          state=gameWon;
    
        //
        if (life==-1) {
          explode () ;
        }
      } // method 
    
      void killWhenInRect(PVector rLocal) {
        if (x>=rLocal.x && y>=rLocal.y && 
          x<=rLocal.x+rectWidth && y<=rLocal.y+rectWidth)   
          life=-1;
      }
    
      void explode () {
        // explode!
        int maxMissiles= int(random(4, 222));
        for (int i=0; i<maxMissiles; i+=1) {   
          // this is where explode missile/shrapnel object is created
          // and added to the missiles arrayList.
          // It is small (4) and life decrease is .72 (how fast it dies),
          // no Line (false).
          //missiles.add( new Explosion(
          //  random(x-3, x+3), random(y+9, y+12), 
          //  random(-1.3, 1.3), random(-2.7, .6), 
          //  4, .72, false)); //
        }
      } // method
    
      boolean finished() {
        // bullet dead?
        if (life < 0) {
          return true;
        } else {
          return false;
        }
      }
    
      void display() {
        // Display the circle
        fill(244, 2, 2);
        noStroke();
        //stroke(0,life);
        ellipse(x, y, w, w);
        // image( ammo_fired, x, y );
      }
    } // class 
    //
    
  • I thought of a way to win.

    there is a small weapon shooting (or lamp emitting light)

    when the light / laser beams / bullets reach the target on the left, you win.

    Now you need to move the boxes out of the way between laser and target

    ;-)

  • hello chris, sorry for late reply and thanks for your helped :> :> . so the goal is to move the boxes in the proper place, there's a red ellipse in each corner (right place). then you will go to the next level. my question is how to make a border, so the ball and the box can't cross the line. i already made the line like maze. and how to stop the timer when you already achieved the quest.

     float oX = 170;
    float oY = 275;
    
    PFont font;
    String time = "030";
    int t;
    int interval = 30;
    
    float speed = 2;
    boolean gameOver = false;
    int startTime;
    boolean upPressed = false;
    boolean downPressed = false;
    boolean leftPressed = false;
    boolean rightPressed = false;
    
    PVector r1 = new PVector (95,200);
    PVector r2 = new PVector (35,255);
    PVector r3 = new PVector (200,255);
    PVector r4 = new PVector (145,310);
    int rectWidth = 50;
    int ellipseWidth = 40;
    void setup(){
    size (400,450);
    
    
     font = createFont("Arial", 10);
      background(255);
      fill(0);
    }
    
    
    
    void draw(){
    
    
    
    
      if (upPressed) {
        oY -= speed;
      }
      if (downPressed) {
        oY += speed;
      }
      if (leftPressed) {
        oX -= speed;
      }
      if (rightPressed) {
        oX += speed;
     }
    
     collision(r1);
      collision(r2);
      collision(r3);
      collision(r4);
      background(255);
    
      ellipse(oX, oY, ellipseWidth ,ellipseWidth);
      //box
      fill(0);
      rect(r1.x,r1.y,rectWidth,rectWidth);
      rect(r2.x,r2.y,rectWidth,rectWidth);
      rect(r3.x,r3.y,rectWidth,rectWidth);
      rect(r4.x,r4.y,rectWidth,rectWidth);
    
     if(r1.y <=160 && r2.x <=20 && r3.x >= 230 && r4.y >= 330){
       textSize(35);
       text ("Next Level" , 150,150);
     }
    if(!gameOver){
    
        t = interval-int((millis()-startTime)/1000);
        time = nf(t , 2);
        if(t == 0){
          gameOver = true;
        }
    }
          //if game over
    if (gameOver){
          textSize(32);
          text("GAME OVER",10,30);
        }
        // if NOT game over yet
      if (!gameOver) {
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
      }
      textSize(32);
    text ("Level 1", 200,30);
        //maze
        strokeWeight(3);
    
      line(90,150,150,150);
      line(150,150,150,250);
      line(150,250,300,250);
      line(300,250,300,310);
      line(300,310,200,310);
      line(200,310,200,410);
      line(200,410,140,410);
      line(140,410,140,310);
     line(140,310,1,310);
     line(1,310,1,250);
     line(1,250,90,250);
     line(90,250,90,150);
    
       text(time, 100, 100);
       //target
    
      fill(224,27,44);
      ellipse(120,170,20,20);
      ellipse(20,280,20,20);
      ellipse(280,280,20,20);
      ellipse(170,380,20,20);
    
      }
    
    void keyPressed(KeyEvent e) {
      if(!gameOver){
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = true;
        }
        else if (keyCode == DOWN) {
          downPressed = true;
        }
        else if (keyCode == LEFT) {
          leftPressed = true;
        }
        else if (keyCode == RIGHT) {
          rightPressed = true;
        }
      }
    } else{
      if (key==' ') {
          // reset 
          gameOver=false; 
          oX=random(ellipseWidth, width);
          oY=random(ellipseWidth, height);
    
    
      }
    }
    }
    void keyReleased(KeyEvent e) {
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = false;
        }
        else if (keyCode == DOWN) {
          downPressed = false;
        }
        else if (keyCode == LEFT) {
          leftPressed = false;
        }
        else if (keyCode == RIGHT) {
          rightPressed = false;
        }
      }
    }
    
    void collision(PVector r1) {
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>r1.y -6 && oY+ellipseWidth/2<r1.y+rectWidth-6) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX-ellipseWidth/2<r1.x+rectWidth+10&& oX-ellipseWidth/2>r1.x-rectWidth/10 )
        {
          r1.x--;
          return;
        }
      }
     // coming from right towards rect
      if (oY-ellipseWidth/2>r1.y-6 && oY+ellipseWidth/2<r1.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<r1.x+13 && oX+ellipseWidth/2>r1.x-2 )
        {
          r1.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<r1.y+rectWidth+5 && oY-ellipseWidth/2>r1.y-rectWidth/4-5 )
        {
          r1.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<r1.y+13 && oY+ellipseWidth/2>r1.y-2 )
        {
          r1.y++; // go
          return;
        }
      }
    
    }
    
  • edited July 2016

    first, you can use ctrl-t in processing to auto-format your code.

    This is especially useful for indents.

    second, I asked quark about your "box need to stay inside the lines"-issue and here is what he wrote:

    I suggest a list vertices (anti-clockwise order) for the enclosing space then when attempting to move the box you calculate the new position (but don't move the box) check for intersection with the enclosing space walls defined by the vertices. Only move the box IF there is no intersection.

    Although it might seem cumbersome to do all the maths but the computer will eat it. My AI library does thousands of these calculations every frame and still get 60fps.

    My geometry cookbook page 5 ( http://lagers.org.uk/how-to/ht-geom-01/index.html } provides the maths for a line-box intersection test.

    I also suggest that the drawn box size is slightly smaller than the box size used for testing intersections. It will give a nice clear border round the box without any additional work.

    third, you wrote:

    how to stop the timer when you already achieved the quest.

    I recommend a new var questAchieved similar to gameOver

    don't increase the timer when questAchieved == true

  • edited July 2016

    since I haven't understood quarks idea, I made a full new version, based on a grid

    Now, what do I mean with a grid?

    I don't mean single lines that look like a grid.

    I mean a grid of data. The grid is like a chess board.

    Each field / cell / Tile of it has a position and a size (size is the same for all).

    This grid gives us our level.

    So instead of drawing the lines and the blocks and the targets, we draw the grid. Each cell in the grid shows itself as a target or a wall or so. It's a huge different.

    The grid knows for each of it's field whether it holds a

    • corridor

    • a wall

    • a target

    • a block (moveable)

    • an ellipse (we move it with cursor keys)

    Now, when we move the ellipse, we in fact just copy it to the next field in the grid (up, down, left or right) and delete the ellipse from the field it was before (meaning we set the field back to be a corridor). We change the grid holding the data (wall, ellipse...).

    Now, in a program, the grid (chess board) is a 2D array (there is a tutorial on that). Each cell / Tile is an object from the class Tile (object oriented programming is another concept. There is a tutorial for that too. It means, we can make a package of data, like a package of data for a tile).

    A Tile in turn has a lot of properties, position, size and type (which is target, wall etc. )

    Now, I invented a list of strings to define our level :

    String[] map = { 
      "wwtwww", 
      "wwbwww", 
      "tbcebt", 
      "wwwbww", 
      "wwwtww"
    };
    

    we read that string and copy each letter into our tiles as its type.

    You can recognize your level when you see, w is wall, t is target, b is block, e is ellipse... c corridor

    it is a simple trick to store data about the level as a map.

    I hope this helps you a bit.

    Best, Chrisir ;-)

    P.S.

    stuff to work on: you can't currently make a level where the ellipse is initially on a target field. Bad.

    you can crash the sketch when you push a block over the edge. We could just surround the field with walls to avoid this.

    Tile[] [] grid;
    int unit = 50; // size of one tile 
    int wideCount ;
    int highCount ;
    
    String[] map = { 
      "wwtwww", 
      "wwbwww", 
      "tbcebt", 
      "wwwbww", 
      "wwwtww"
    };
    
    // counter for the targets 
    int targetCounter  = 0; 
    int targetCounterMax = 0;
    
    PFont font;
    String time = "";
    int t=0;
    int interval = 30;
    
    //float speed = 2;
    boolean gameOver = false;
    int startTime;
    
    boolean upPressed = false;
    boolean downPressed = false;
    boolean leftPressed = false;
    boolean rightPressed = false;
    
    //int rectWidth = 50;
    int ellipseWidth = 40;
    
    // --------------------------------------------------------
    
    void setup() {
      size (400, 450);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      // int count;
      wideCount = map[1].length(); // the length of one String/line in the array
      highCount = map.length; 
      //count = wideCount * highCount;  
      grid = new Tile[wideCount][highCount];
      // int index = 0;
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
          // all strings in the map must be of the same length
          if (map[y].length() != wideCount) {
            println("wrong length of a String in map: error # 59; with y (line + in map) being: "
              + y 
              + "; text in map was "
              + map[y]);
            exit();
          }
    
    
          char type = map[y].charAt(x);
    
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
            targetCounter++;
          }
    
    
          //start creating objects
          grid[x][y] = new Tile (x*unit+70, y*unit+130, 
            unit, 
            type );
        }
      }//for
    
      if (!ellipseFound) {
        println("Error in map. No ellipse (e) found. Error 60");
        exit();
      }
    
      if (!targetFound) {
        println("Error in map. No target (t) found. Error 60");
        exit();
      }
    
      targetCounterMax=targetCounter;
      targetCounter=0;
    }
    
    
    
    void draw() {
    
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
        for (int x=0; x< wideCount; x++) {
          for (int y=0; y< highCount; y++) {
            grid[x][y].display();
          }
        }
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
      } else {
    
        fill(0); 
        textSize(12); 
        text("You found "
          + targetCounter 
          + " of "
          + targetCounterMax 
          + " targets.", 
          21, height-12); 
    
        //if (upPressed) {
        //  oY -= speed;
        //}
        //if (downPressed) {
        //  oY += speed;
        //}
        //if (leftPressed) {
        //  oX -= speed;
        //}
        //if (rightPressed) {
        //  oX += speed;
        //}
    
        //collision(r1);
        //collision(r2);
        //collision(r3);
        //collision(r4);
    
    
        for (int x=0; x< wideCount; x++) {
          for (int y=0; y< highCount; y++) {
            grid[x][y].display();
          }
        }
    
    
        //if (r1.y <=160 && r2.x <=20 && r3.x >= 230 && r4.y >= 330) {
        //  textSize(35);
        //  text ("Next Level", 150, 150);
        //}
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
        }
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
        // if NOT game over yet
        if (!gameOver) {
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
        }
        textSize(32);
        text ("Level 1", 200, 30);
        //maze
        strokeWeight(3);
    
        //line(90, 150, 150, 150);
        //line(150, 150, 150, 250);
        //line(150, 250, 300, 250);
        //line(300, 250, 300, 310);
        //line(300, 310, 200, 310);
        //line(200, 310, 200, 410);
        //line(200, 410, 140, 410);
        //line(140, 410, 140, 310);
        //line(140, 310, 1, 310);
        //line(1, 310, 1, 250);
        //line(1, 250, 90, 250);
        //line(90, 250, 90, 150);
    
        // text(time, 100, 100);
        //target
    
        //fill(224, 27, 44);
        //ellipse(120, 170, 20, 20);
        //ellipse(20, 280, 20, 20);
        //ellipse(280, 280, 20, 20);
        //ellipse(170, 380, 20, 20);
      }
    }
    
    void keyPressed(KeyEvent e) {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
            upPressed = true;
    
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if  (  grid[x][y].type=='e' && 
                  y>0 && 
                  "ctb".indexOf(grid[x][y-1].type)  > -1 )
                {
                  grid[x][y].type='c';
                  if (grid[x][y-1].type=='b') {
                    // check target and move block 
                    if (grid[x][y-2].type=='t') 
                      targetCounter++;
                    grid[x][y-2].type='b';
                  }
                  grid[x][y-1].type='e';
                  return;
                }
              }
            }
          } else if (keyCode == DOWN) {
            downPressed = true;
    
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if (x<5 && 
                  grid[x][y].type=='e' && 
                  "ctb".indexOf(grid[x][y+1].type)  > -1 )
                {
                  grid[x][y].type='c';// where we left with the ellipse
                  if (grid[x][y+1].type=='b') {
                    // check target and move block 
                    if (grid[x][y+2].type=='t') 
                      targetCounter++;
                    grid[x][y+2].type='b';
                  }
                  grid[x][y+1].type='e';// new pos for ellipse 
                  return;
                }
              }
            }
          } else if (keyCode == LEFT) {
            leftPressed = true;
            println("1");
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                println("2");
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if  (x>0  &&   grid[x][y].type=='e' && 
                  x>0 && 
                  "ctb".indexOf(grid[x-1][y].type)  > -1 )
                {
                  println("2");
                  if (grid[x-1][y].type=='b') {
                    // check target and move block 
                    if (grid[x-2][y].type=='t') 
                      targetCounter++;
                    grid[x-2][y].type='b';
                  }
                  grid[x][y].type='c';
                  grid[x-1][y].type='e';
                  return;
                }
              }
            }
          } else if (keyCode == RIGHT) {
            rightPressed = true;
    
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if (x<5 && 
                  grid[x][y].type=='e' && 
                  "ctb".indexOf(grid[x+1][y].type)  > -1 )
                {
                  grid[x][y].type='c';// where we left with the ellipse
                  if (grid[x+1][y].type=='b') {
                    // check target and move block 
                    if (grid[x+2][y].type=='t') 
                      targetCounter++;
                    grid[x+2][y].type='b';
                  }
                  grid[x+1][y].type='e';// new pos for ellipse 
                  return;
                }
              }
            }
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false; 
          //oX=random(ellipseWidth, width);
          //oY=random(ellipseWidth, height);
        }
      }
    }
    void keyReleased(KeyEvent e) {
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = false;
        } else if (keyCode == DOWN) {
          downPressed = false;
        } else if (keyCode == LEFT) {
          leftPressed = false;
        } else if (keyCode == RIGHT) {
          rightPressed = false;
        }
      }
    }
    
    // ==========================================================
    
    
    class Tile {
    
      float x, y;
      float side;
      //  int col;
      char type;
    
      Tile (float tempX, float tempY, float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        //
        float fate = random(2);
        type=tempType;
      }
    
      void display() {
        //     if (mouseX>x&&mouseX<x+side&&mouseY>y&&mouseY<y+side)
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, ellipseWidth-6, ellipseWidth-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 4, 4);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
        default:
          println("unknown type: error # 295: with char: "+ type);
          exit();
          break; 
          //
        }//switch
      }// func
    
      void corridor() {
        // corridor
        fill(255);  // white 
        //stroke(0);
        stroke(255);
        // noStroke(); 
        rect (x, y, side, side);
      }//func
    }//class
    // 
    
  • // the grid
    Tile[] [] grid; // grid 
    int unit = 50;  // size of one tile 
    int wideCount ; // how many
    int highCount ; // how many
    
    // the coding: 
    // i =invisble wall 
    // w =wall
    // t =target 
    // e =ellipse (we steer it with cursor)
    // b =block, moveable
    // c =corridor, empty
    // u =unknown type
    String[] map = {
      "iiiiiiii", 
      "iwwtwwwi", 
      "iwwbwwwi", 
      "itbcebti", 
      "iwwwbwwi", 
      "iwwwtwwi", 
      "iiiiiiii"
    };
    
    // counter for the targets 
    int targetCounter    = 0; // current  
    int targetCounterMax = 0; // number of all targets in the level
    
    // font
    PFont font;
    
    // timer 
    String time = "";
    int t=0;
    int interval = 30;
    int startTime;
    
    // game over? 
    boolean gameOver = false;
    
    // --------------------------------------------------------
    
    void setup() {
      size (900, 550);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      buildTheGrid();
    }
    
    void draw() {
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
    
        generalScreenDesign();
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
      } else {
        // normal game 
    
        generalScreenDesign(); 
    
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
    
          textSize(32);
          text ("Level 1", 200, 30);
          strokeWeight(3);
        }
    
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
      }// else
    }//func 
    
    void buildTheGrid() {
      // int count;
      wideCount = map[1].length(); // the length of one String/line in the array
      highCount = map.length; 
    
      grid = new Tile[wideCount][highCount];
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
          // detect possible error: 
          // all strings in the map must be of the same length
          if (map[y].length() != wideCount) {
            println("Wrong length of a String in map: error #59; with y (line + in map) being: "
              + y 
              + "; text in map was "
              + map[y]);
            exit();
          }
    
          // get type from map 
          char type = map[y].charAt(x);
    
          // to detect some errors, we monitor if we found ellipse and target 
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
            targetCounterMax++;
          }
    
          //start creating objects
          grid[x][y] = new Tile (x*unit+10, y*unit+130, 
            unit, 
            type );
        }//for
      }//for
    
      // detect some errors 
      if (!ellipseFound) {
        println("Error in map. No ellipse (e) found. Error 60");
        exit();
      }
    
      if (!targetFound) {
        println("Error in map. No target (t) found. Error 61");
        exit();
      }
    }//func
    
    void generalScreenDesign() {
    
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          grid[x][y].display();
        }
      }
    
      fill(0); 
      textSize(12); 
      text("You found "
        + targetCounter 
        + " of "
        + targetCounterMax 
        + " targets.", 
        21, height-12);
    
      // frame around grid 
      noFill(); 
      stroke(0);
      rect (grid[1][1].x, 
        grid[1][1].y, 
        grid[wideCount-2][highCount-2].x-grid[0][0].x, 
        grid[wideCount-2][highCount-2].y-grid[0][0].y);
    }
    
    void keyPressed() {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
    
            PVector pvE=ellipsePosition();
            if (pvE==null) {
              exit();
            }
            int x=int(pvE.x);
            int y=int(pvE.y);
            // test: must be an ellipse 
            if (grid[x][y].type!='e') {
              exit();
            }
    
            // test: is not allowed on the border and target tile must be c, b or t 
            if  (y>0 && grid[x][y-1].allowedTileForEllipse()  )
            {
              if (grid[x][y-1].type=='b') {
                if (grid[x][y-2].type!='w' && grid[x][y-2].type!='i' && y-2>=0) {
                  // check target and move block
                  grid[x][y].type='c';
                  if (grid[x][y-2].type=='t') 
                    targetCounter++;
                  grid[x][y-2].type='b';//move block by 1
                  grid[x][y-1].type='e';//move ellipse by 1
                  return;
                }
              } else {
                grid[x][y].type='c';
                grid[x][y-1].previousType = grid[x][y-1].type;  
                grid[x][y-1].type='e';
                return;
              }
            }
          } else if (keyCode == DOWN) {
    
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if (x<5 && 
                  grid[x][y].type=='e' && 
                  grid[x][y+1].allowedTileForEllipse()  )
                {
                  grid[x][y].type='c';// where we left with the ellipse
                  if (grid[x][y+1].type=='b') {
                    // check target and move block 
                    if (grid[x][y+2].type=='t') 
                      targetCounter++;
                    grid[x][y+2].type='b';
                  }
                  grid[x][y+1].type='e';// new pos for ellipse 
                  return;
                }
              }
            }
          } else if (keyCode == LEFT) {
    
            println("1");
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                println("2");
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if  (x>0  &&   grid[x][y].type=='e' && 
                  x>0 && 
                  grid[x-1][y].allowedTileForEllipse()  )
                {
                  println("2");
                  if (grid[x-1][y].type=='b') {
                    // check target and move block 
                    if (grid[x-2][y].type=='t') 
                      targetCounter++;
                    grid[x-2][y].type='b';
                  }
                  grid[x][y].type='c';
                  grid[x-1][y].type='e';
                  return;
                }
              }
            }
          } else if (keyCode == RIGHT) {
    
    
            for (int x=0; x< wideCount; x++) {
              for (int y=0; y< highCount; y++) {
    
                // test: must be an ellipse and not on the border and target tile must be c, b, or t 
                if (x<5 && 
                  grid[x][y].type=='e' && 
                  grid[x+1][y].allowedTileForEllipse()  )
                {
                  grid[x][y].type='c';// where we left with the ellipse
                  if (grid[x+1][y].type=='b') {
                    // check target and move block 
                    if (grid[x+2][y].type=='t') 
                      targetCounter++;
                    grid[x+2][y].type='b';
                  }
                  grid[x+1][y].type='e';// new pos for ellipse 
                  return;
                }
              }
            }
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false;
        }
      }
    }
    
    PVector ellipsePosition() {
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          if (  grid[x][y].type=='e' ) {
            return new PVector(x, y);
          }// if
        }
      }
    
      println("no ellipse found, error 297"); 
      return null;
    }
    
    // ==========================================================
    
    class Tile {
    
      float x, y;
      float side;
    
      char type='u';
      char previousType='u'; 
    
      Tile (float tempX, float tempY, 
        float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        type=tempType;
      }
    
      void display() {
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, side-6, side-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 4, 4);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
        case 'i':
          // Invisible wall            
          break;
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
        default:
          println("unknown type: error # 295: with char: "
            + type);
          exit();
          break; 
          //
        }//switch
      }// func
    
      void corridor() {
        // corridor
        fill(255);  // white 
        stroke(255);
        rect (x, y, side, side);
      }//func
    
      boolean allowedTileForEllipse() {
        // tile must be c, b or t
        // so that the ellipse is allowed to go there 
        return "ctb".indexOf(type)  > -1;
      }// func
    }//class
    // 
    
  • small improvements

    key UP is now better than the others

  • Answer ✓
    // the grid (a 2D-Array) 
    Tile[] [] grid; // grid 
    int unit = 50;  // size of one tile 
    int wideCount ; // how many
    int highCount ; // how many
    
    // the coding: 
    // i =invisble wall (not in use)
    // w =wall
    // t =target 
    // e =ellipse (we steer it with cursor)
    // b =block, moveable 
    // c =corridor, empty
    // u =unknown type (don't use this here)
    String[] map22222222222222222 = {
      "wwtwww", 
      "wwbwww", 
      "tbcebt", 
      "wwwbww", 
      "wwwtww"
    };
    
    String[] map = {
      "cwtccc", 
      "wwcwcc", 
      "tbcecc", 
      "wcwbcc", 
      "cccccc"
    };
    
    // counter for the targets 
    int targetCounter    = 0; // current  
    int targetCounterMax = 0; // number of all targets in the level
    
    // font
    PFont font;
    
    // timer 
    String time = "";
    int t=0;
    int interval = 30;
    int startTime;
    
    // game over? 
    boolean gameOver = false;
    
    // --------------------------------------------------------
    
    void setup() {
      size (900, 550);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      buildTheGrid();
    }
    
    void draw() {
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
    
        generalScreenDesign();
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
      } else {
        // normal game 
    
        generalScreenDesign(); 
    
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
    
          textSize(32);
          text ("Level 1", 200, 30);
          strokeWeight(3);
        }
    
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
      }// else
    }//func 
    
    // ----------------------------------------------------------
    
    void buildTheGrid() {
    
      wideCount = map[1].length(); // the length of one String/line in the array map
      highCount = map.length;  // how many lines in the array map       
    
      grid = new Tile[wideCount][highCount];
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      // double for-loop for a 2D-Array 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
          // detect possible error: 
          // all strings in the map must be of the same length
          if (map[y].length() != wideCount) {
            println("Wrong length of a String in map: error #59; with y (line + in map) being: "
              + y 
              + "; text in map was "
              + map[y]);
            exit();
            return;
          }
    
          // get type from map (line number y, character number = x)
          char type = map[y].charAt(x);
    
          // to detect some errors, we monitor if we found ellipse and target 
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
            targetCounterMax++; // count targets
          }
    
          // create object
          grid[x][y] = new Tile (x*unit+210, y*unit+130, 
            unit, 
            type );
        }//for
      }//for
    
      // detect some errors 
      if (!ellipseFound) {
        println("Error in map. No ellipse (e) found. Error 60");
        exit();
        return;
      }
    
      if (!targetFound) {
        println("Error in map. No target (t) found. Error 61");
        exit();
        return;
      }
    }//func
    
    void generalScreenDesign() {
    
      // show grid 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          grid[x][y].display();
        }
      }
    
      // show status message 
      fill(0); 
      textSize(12); 
      text("You found "
        + targetCounter 
        + " of "
        + targetCounterMax 
        + " targets.", 
        21, height-12);
    
      // frame around grid 
      noFill(); 
      stroke(0);
      rect (grid[0][0].x, 
        grid[0][0].y, 
        grid[wideCount-1][highCount-1].x-grid[0][0].x+grid[0][0].side, 
        grid[wideCount-1][highCount-1].y-grid[0][0].y+grid[0][0].side);
    }
    
    void keyPressed() {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
            // push Ellipse up (y = -1)
            pushEllipse(0, -1);
          } else if (keyCode == DOWN) {
            // push Ellipse down (y = 1)
            pushEllipse(0, 1);
          } else if (keyCode == LEFT) {
            // push Ellipse left (x = -1)
            pushEllipse(-1, 0);
          } else if (keyCode == RIGHT) {
            // push Ellipse right (x = 1)
            pushEllipse(1, 0);
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false;
          startTime=millis();
        }
      }
    }
    
    void pushEllipse( int xAdd, int yAdd ) {
    
      // push Ellipse in a direction given by xAdd and yAdd
    
      // get the position of the ellipse 
      PVector pvE=ellipsePosition();
      if (pvE==null) {
        // error 
        println("no ellipse found, error 297."); 
        exit();
      }
      int x=int(pvE.x);
      int y=int(pvE.y);
      // test: must be an ellipse 
      if (grid[x][y].type!='e') {
        // error 
        println("no ellipse found in grid, error 298."); 
        exit();
      }
    
      // -----------------------------------------------------------
    
      // test: target field (where the Ellipse goes to)
      // must be inside 
      if (x+xAdd<0||y+yAdd<0||
        x+xAdd>wideCount-1||y+yAdd>highCount-1) 
        return; 
    
      // test: target tile must be c, b or t 
      if (!grid[x+xAdd][y+yAdd].allowedTileForEllipse())
        return; 
    
      if (grid[x+xAdd][y+yAdd].type=='b') {
    
        // special move with a box
    
        // test: target field of the block (where the block goes to)
        // must be inside 
        if (x+xAdd+xAdd<0||y+yAdd+yAdd<0||
          x+xAdd+xAdd>=wideCount||y+yAdd+yAdd>=highCount) 
          return; 
    
        // no wall is allowed behind the block
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='w' || grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='i') 
          return; 
    
        // check target 
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='t') 
          targetCounter++;
    
        // move ellipse and block 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor   
        grid[x+xAdd][y+yAdd].type='e'; // ellipse
        grid[x+xAdd+xAdd][y+yAdd+yAdd].type='b'; //move block by 1
        return;
      } else {
        // normal move 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor       
        grid[x+xAdd][y+yAdd].previousType = grid[x+xAdd][y+yAdd].type;  
        grid[x+xAdd][y+yAdd].type='e';
        return;
      }
    }// func 
    
    PVector ellipsePosition() {
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          if ( grid[x][y].type=='e' ) {
            return new PVector(x, y);
          }// if
        }
      }
    
      // error 
      return null;
    }
    
    // ==========================================================
    
    class Tile {
    
      float x, y;
      float side;
    
      char type='u';
      char previousType='u'; 
    
      Tile (float tempX, float tempY, 
        float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        type=tempType;
      }
    
      void display() {
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, side-6, side-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 4, 4);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
        case 'i':
          // Invisible wall            
          break;
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
        default:
          println("unknown type: error # 295: with char: "
            + type);
          exit();
          break; 
          //
        }//switch
      }// func
    
      void corridor() {
        // draw corridor
        // (also as background for block and target etc.)
        fill(255);  // white 
        stroke(255);
        rect (x, y, side, side);
      }//func
    
      boolean allowedTileForEllipse() {
        // tile must be c, b or t
        // so that the ellipse is allowed to go there 
        return "ctb".indexOf(type)  > -1;
      }// func
    }//class
    // 
    
  • new version with a new level and some improvements in the code

  • i try to understand your code, but i can't get it espescially in the void build thegrid :((. is it possible to make a multilevel? if it's possible can you teach me ? like when the boxes already in the proper place, then we will go to the next level.

    this is level 1 float oX = 170; float oY = 275;

    PFont font;
    String time = "030";
    int t;
    int interval = 30;
    
    float speed = 2;
    boolean gameOver = false;
    int startTime;
    boolean upPressed = false;
    boolean downPressed = false;
    boolean leftPressed = false;
    boolean rightPressed = false;
    
    PVector r1 = new PVector (95,200);
    PVector r2 = new PVector (35,255);
    PVector r3 = new PVector (200,255);
    PVector r4 = new PVector (145,310);
    int rectWidth = 50;
    int ellipseWidth = 40;
    void setup(){
    size (400,450);
    
    
     font = createFont("Arial", 10);
      background(255);
      fill(0);
    }
    
    
    
    void draw(){
    
    
    
    
      if (upPressed) {
        oY -= speed;
      }
      if (downPressed) {
        oY += speed;
      }
      if (leftPressed) {
        oX -= speed;
      }
      if (rightPressed) {
        oX += speed;
     }
    
     collision(r1);
      collision(r2);
      collision(r3);
      collision(r4);
      background(255);
    
      ellipse(oX, oY, ellipseWidth ,ellipseWidth);
      //box
      fill(0);
      rect(r1.x,r1.y,rectWidth,rectWidth);
      rect(r2.x,r2.y,rectWidth,rectWidth);
      rect(r3.x,r3.y,rectWidth,rectWidth);
      rect(r4.x,r4.y,rectWidth,rectWidth);
    
     if(r1.y <=160 && r2.x <=20 && r3.x >= 230 && r4.y >= 330){
       textSize(35);
       text ("Next Level" , 150,150);
     }
    if(!gameOver){
    
        t = interval-int((millis()-startTime)/1000);
        time = nf(t , 2);
        if(t == 0){
          gameOver = true;
        }
    }
          //if game over
    if (gameOver){
          textSize(32);
          text("GAME OVER",10,30);
        }
        // if NOT game over yet
      if (!gameOver) {
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
      }
      textSize(32);
    text ("Level 1", 200,30);
        //maze
        strokeWeight(3);
    
      line(90,150,150,150);
      line(150,150,150,250);
      line(150,250,300,250);
      line(300,250,300,310);
      line(300,310,200,310);
      line(200,310,200,410);
      line(200,410,140,410);
      line(140,410,140,310);
     line(140,310,1,310);
     line(1,310,1,250);
     line(1,250,90,250);
     line(90,250,90,150);
    
       text(time, 100, 100);
       //target
    
      fill(224,27,44);
      ellipse(120,170,20,20);
      ellipse(20,280,20,20);
      ellipse(280,280,20,20);
      ellipse(170,380,20,20);
    
      }
    
    void keyPressed(KeyEvent e) {
      if(!gameOver){
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = true;
        }
        else if (keyCode == DOWN) {
          downPressed = true;
        }
        else if (keyCode == LEFT) {
          leftPressed = true;
        }
        else if (keyCode == RIGHT) {
          rightPressed = true;
        }
      }
    } else{
      if (key==' ') {
          // reset 
          gameOver=false; 
          oX=random(ellipseWidth, width);
          oY=random(ellipseWidth, height);
    
    
      }
    }
    }
    void keyReleased(KeyEvent e) {
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = false;
        }
        else if (keyCode == DOWN) {
          downPressed = false;
        }
        else if (keyCode == LEFT) {
          leftPressed = false;
        }
        else if (keyCode == RIGHT) {
          rightPressed = false;
        }
      }
    }
    
    void collision(PVector r1) {
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>r1.y -6 && oY+ellipseWidth/2<r1.y+rectWidth-6) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX-ellipseWidth/2<r1.x+rectWidth+10&& oX-ellipseWidth/2>r1.x-rectWidth/10 )
        {
          r1.x--;
          return;
        }
      }
     // coming from right towards rect
      if (oY-ellipseWidth/2>r1.y-6 && oY+ellipseWidth/2<r1.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<r1.x+13 && oX+ellipseWidth/2>r1.x-2 )
        {
          r1.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<r1.y+rectWidth+5 && oY-ellipseWidth/2>r1.y-rectWidth/4-5 )
        {
          r1.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<r1.y+13 && oY+ellipseWidth/2>r1.y-2 )
        {
          r1.y++; // go
          return;
        }
      }
    
    }
    

    and this is level 2

    float oX = 170;
    float oY = 120;
    PFont font;
    String time = "030";
    int t;
    int interval = 30;
    float speed = 2;
    boolean gameOver = false;
    int startTime;
    boolean upPressed = false;
    boolean downPressed = false;
    boolean leftPressed = false;
    boolean rightPressed = false;
    PVector r1 = new PVector(150,150);
    PVector r2 = new PVector(260,210);
    int rectWidth = 50;
    int ellipseWidth = 40;
    
    void setup() {
      size(500, 500);
      font = createFont("arial",10);
      background(255);
      fill(0);
    
    }
    
    void draw() {
    
      if (upPressed) {
        oY -= speed;
      }
      if (downPressed) {
       oY += speed;
      }
      if (leftPressed) {
        oX -= speed;
      }
      if (rightPressed) {
        oX += speed;
      }
    collision(r1);
      collision(r2);
    
    
      background(255);
      ellipse(oX, oY,ellipseWidth, ellipseWidth);
    
      //box 
      fill(0);
      rect(r1.x , r1.y, rectWidth, rectWidth);
      rect(r2.x, r2.y, rectWidth, rectWidth);
    
      if(r1.y >= 210 && r1.y <=230 && r2.x <= 220 && r2.y <= 110){
        textSize(32);
        text("Next Level", 250,250);
      }
    if(!gameOver){
    
        t = interval-int((millis()-startTime)/1000);
        time = nf(t , 2);
        if(t == 0){
          gameOver = true;
        }
    }
          //if game over
    if (gameOver){
          textSize(32);
          text("GAME OVER",10,30);
        }
        // if NOT game over yet
      if (!gameOver) {
        fill(0); 
        stroke(0); 
        text(time, 100, 100);
      }
      textSize(32);
    text ("Level 2", 200,30);
        //maze
        strokeWeight(3);
    
    
      line (140,100,260,100);
      line(260,100,260,210);
      line(260,210,370,210);
      line(370,210,370,320);
      line(370,320,340,320);
      line(340,320,230,320);
      line(230,320,230,380);
      line(230,380,140,380);
      line(140,380,140,100);
    text(time, 100, 100);  
    
      //target
      fill(224,27,44);
      ellipse(230,120,20,20);
      ellipse(170,250,20,20);
    } 
    
    void keyPressed(KeyEvent e) {
      if(!gameOver){
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = true;
        }
        else if (keyCode == DOWN) {
          downPressed = true;
        }
        else if (keyCode == LEFT) {
          leftPressed = true;
        }
        else if (keyCode == RIGHT) {
          rightPressed = true;
        }
      }
    } else{
      if (key==' ') {
          // reset 
          gameOver=false; 
          oX=random(ellipseWidth, width);
          oY=random(ellipseWidth, height);
    
    
      }
    }
    }
    void keyReleased(KeyEvent e) {
      if (key == CODED) {
        if (keyCode == UP) {
          upPressed = false;
        }
        else if (keyCode == DOWN) {
          downPressed = false;
        }
        else if (keyCode == LEFT) {
          leftPressed = false;
        }
        else if (keyCode == RIGHT) {
          rightPressed = false;
        }
      }
    }
    void collision(PVector r1) {
      // coming from left towards rect (pushing the box right)
      // first check: is the y-pos of the elippse inside the rect? 
      if (oY-ellipseWidth/2>r1.y -6 && oY+ellipseWidth/2<r1.y+rectWidth-6) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX-ellipseWidth/2<r1.x+rectWidth+10&& oX-ellipseWidth/2>r1.x-rectWidth/10 )
        {
          r1.x--;
          return;
        }
      }
     // coming from right towards rect
      if (oY-ellipseWidth/2>r1.y-6 && oY+ellipseWidth/2<r1.y+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oX+ellipseWidth/2<r1.x+13 && oX+ellipseWidth/2>r1.x-2 )
        {
          r1.x++; // go right
          return;
        }
      }
    
      //-----
    
      // coming from bottom towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY-ellipseWidth/2<r1.y+rectWidth+5 && oY-ellipseWidth/2>r1.y-rectWidth/4-5 )
        {
          r1.y--;
          return;
        }
      }
    
      // coming from top towards rect
      if (oX-ellipseWidth/2>r1.x-6 && oX+ellipseWidth/2<r1.x+rectWidth+6 ) { 
        fill(255, 0, 0);//red
        rect(r1.x, r1.y, rectWidth, rectWidth);
        if (oY+ellipseWidth/2<r1.y+13 && oY+ellipseWidth/2>r1.y-2 )
        {
          r1.y++; // go
          return;
        }
      }
    
    }
    

    im so sorry if i asked you too much questions :((

  • do you interact with the lines? the walls I mean?

  • i have to , but i will think another way, like if the ball cross the line then the timer will reduce for 7 seconds. because if i built the grid like you teach me, it just too deep for me and i can't understand :( i think if i reduce the timer it will make the code more simple.

  • quark told you... but his way is hard.....

    see, you need a counter that tells you in which level you are. depending on this, draw the lines. And do the text() about the level number.

    but you draw the lines but they are not in data, so they are hard to interact with.

    the grid is better solution

  • I can explain the grid later

    A new idea would be that you

    send out test beams from the block to detect lines.

    Let me explain. When you push the block left it sends out 2 beams from the 2 left corners to the left. With get() the beams grab the color. If it's black, stop (or set a var tell it to stop).

    The beam is of course invisible it's just a for-loop with i and the get is like

    Color colGet = get(r1.x-i, r1.y);

    etc.

  • The grid....

    now imagine a chess board

    In build grid we define each field of it.

    That's the line with new.

    Here we also give the new tile a Position and size and type.

    The Double for loop in build grid is there to cover the entire chessboard, basically rows and columns.

    with grid[][] we can access a single field by passing column number and row number to it

  • i already get what you tried to explain in this code

    // the grid (a 2D-Array) 
    Tile[] [] grid; // grid 
    int unit = 50;  // size of one tile 
    int wideCount  ; // how many
    int highCount  ; // how many
    
    // the coding: 
    
    // w =wall
    // t =target 
    // e =ellipse (we steer it with cursor)
    // b =block, moveable 
    // c =corridor, empty
    // u =unknown type (don't use this here)
    
    
    String[] map = {
      "cwtccc", 
      "wwcwcc", 
      "tbcecc", 
      "wcwbcc", 
      "cccccc"
    };
    
    // counter for the targets 
    int targetCounter    = 0; // current  
    int targetCounterMax = 0; // number of all targets in the level
    
    // font
    PFont font;
    
    // timer 
    String time = "";
    int t=0;
    int interval = 30;
    int startTime;
    
    // game over? 
    boolean gameOver = false;
    
    // --------------------------------------------------------
    
    void setup() {
      size (900, 550);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      buildTheGrid();
    }
    
    void draw() {
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
    
        generalScreenDesign();
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
      } else {
        // normal game 
    
        generalScreenDesign(); 
    
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
    
          textSize(32);
          text ("Level 1", 200, 30);
          strokeWeight(3);
        }
    
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
      }// else
    }//func 
    
    // ----------------------------------------------------------
    
    void buildTheGrid() {
    
      wideCount = map[1].length(); // the length of one String/line in the array map
      highCount = map.length;  // how many lines in the array map       
    
      grid = new Tile[wideCount][highCount];
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      // double for-loop for a 2D-Array 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
    
    
          // get type from map (line number y, character number = x)
          char type = map[y].charAt(x);
    
          // to detect some errors, we monitor if we found ellipse and target 
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
            targetCounterMax++; // count targets
          }
    
          // create object
          grid[x][y] = new Tile (x*unit+210, y*unit+130, 
            unit, 
            type );
        }//for
      }//for
    
    
      }
    
    
    void generalScreenDesign() {
    
      // show grid 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          grid[x][y].display();
        }
      }
    
    
    
    
      // frame around grid 
      noFill(); 
      stroke(0);
      rect (grid[0][0].x, 
        grid[0][0].y, 
        grid[wideCount-1][highCount-1].x-grid[0][0].x+grid[1][0].side, 
        grid[wideCount-1][highCount-1].y-grid[0][0].y+grid[0][0].side);
    }
    
    void keyPressed() {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
            // push Ellipse up (y = -1)
            pushEllipse(0, -1);
          } else if (keyCode == DOWN) {
            // push Ellipse down (y = 1)
            pushEllipse(0, 1);
          } else if (keyCode == LEFT) {
            // push Ellipse left (x = -1)
            pushEllipse(-1, 0);
          } else if (keyCode == RIGHT) {
            // push Ellipse right (x = 1)
            pushEllipse(1, 0);
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false;
          startTime=millis();
        }
      }
    }
    
    void pushEllipse( int xAdd, int yAdd ) {
    
      // push Ellipse in a direction given by xAdd and yAdd
    
      // get the position of the ellipse 
      PVector pvE=ellipsePosition();
    
      int x=int(pvE.x);
      int y=int(pvE.y);
      // test: must be an ellipse 
    
    
      // -----------------------------------------------------------
    
     //
      if (x+xAdd<0||y+yAdd<0||
        x+xAdd>wideCount-1||y+yAdd>highCount-1) 
        return; 
    
      // test: target tile must be c, b or t 
      if (!grid[x+xAdd][y+yAdd].allowedTileForEllipse())
        return; 
    
      if (grid[x+xAdd][y+yAdd].type=='b') {
    
        // special move with a box
    
        // test: target field of the block (where the block goes to)
        // must be inside 
        if (x+xAdd+xAdd<0||y+yAdd+yAdd<0||
          x+xAdd+xAdd>=wideCount||y+yAdd+yAdd>=highCount) 
          return; 
    
        // no wall is allowed behind the block
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='w' || grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='i') 
          return; 
    
        // check target 
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='t') 
          targetCounter++;
    
        // move ellipse and block 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor   
        grid[x+xAdd][y+yAdd].type='e'; // ellipse
        grid[x+xAdd+xAdd][y+yAdd+yAdd].type='b'; //move block by 1
        return;
      } else {
        // normal move 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor       
        grid[x+xAdd][y+yAdd].previousType = grid[x+xAdd][y+yAdd].type;  
        grid[x+xAdd][y+yAdd].type='e';
        return;
      }
    }// func 
    
    PVector ellipsePosition() {
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          if ( grid[x][y].type=='e' ) {
            return new PVector(x, y);
          }// if
        }
      }
    
      // error 
      return null;
    }
    
    // ==========================================================
    
    class Tile {
    
      float x, y;
      float side;
    
      char type='u';
      char previousType='u'; 
    
      Tile (float tempX, float tempY, 
        float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        type=tempType;
      }
    
      void display() {
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, side-6, side-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 3, 3);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
    
        }//switch
      }// func
    
      void corridor() {
        // draw corridor
        // (also as background for block and target etc.)
        fill(255);  // white 
        stroke(255);
        rect (x, y, side, side);
      }//func
    
      boolean allowedTileForEllipse() {
        // tile must be c, b or t
        // so that the ellipse is allowed to go there 
        return "ctb".indexOf(type)  > -1;
      }// func
    }//class
    // 
    

    i wanna ask about the function of tempside in here. and what the meaning o fchar previous type ?

    float x, y; float side;

    char type='u'; char previousType='u';

    Tile (float tempX, float tempY, float tempSide, char tempType) { x = tempX; y = tempY; side = tempSide; type=tempType;

  • look! now i can build my own maze. thanks to you ! ;) // the grid (a 2D-Array) Tile[] [] grid; // grid int unit = 50; // size of one tile int wideCount = 150 ; // how many int highCount=150 ; // how many

    // the coding:

    // w =wall // t =target // e =ellipse (we steer it with cursor) // b =block, moveable // c =corridor, empty // u =unknown type (don't use this here)

    String[] map = { "iiwtwii", "iiwcwww", "wwwbcbt", "wtcbeww", "wwwwbwi", "iiiwtwi",

    };

    // counter for the targets int targetCounter = 0; // current
    int targetCounterMax = 4; // number of all targets in the level

    // font PFont font;

    // timer String time = ""; int t=0; int interval = 30; int startTime;

    // game over? boolean gameOver = false;

    // --------------------------------------------------------

    void setup() { size (900, 550); background(255);

    font = createFont("Arial", 10); fill(0);

    buildTheGrid(); }

    void draw() {

    background(255);

    if (targetCounter==targetCounterMax) { // Win !!!

    generalScreenDesign();
    
    textSize(32);
    fill(255, 2, 2);
    text("You WON", 50, 50);
    

    } else { // normal game

    generalScreenDesign(); 
    
    if (!gameOver) {
    
      t = interval-int((millis()-startTime)/1000);
      time = nf(t, 2);
      if (t == 0) {
        gameOver = true;
      }
      fill(0); 
      stroke(0); 
      textSize(32);
      text(time, 100, 100);
    
      textSize(32);
      text ("Level 1", 200, 30);
      strokeWeight(3);
    }
    
    //if game over
    if (gameOver) {
      textSize(32);
      text("GAME OVER", 10, 30);
    }
    

    }// else }//func

    // ----------------------------------------------------------

    void buildTheGrid() {

    wideCount = map[1].length(); // the length of one String/line in the array map highCount = map.length; // how many lines in the array map

    grid = new Tile[wideCount][highCount];

    boolean ellipseFound=false; boolean targetFound=false;

    // double for-loop for a 2D-Array for (int x=0; x< wideCount; x++) { for (int y=0; y< highCount; y++) {

      // get type from map (line number y, character number = x)
      char type = map[y].charAt(x);
    
      // to detect some errors, we monitor if we found ellipse and target 
      if (type=='e') {
        ellipseFound=true;
      }
      if (type=='t') {  
        targetFound=true;
    
      }
    
      // create object
      grid[x][y] = new Tile (x*unit+200, y*unit+130, 
        unit, 
        type );
    }//for
    

    }//for

    }

    void generalScreenDesign() {

    // show grid for (int x=0; x< wideCount; x++) { for (int y=0; y< highCount; y++) { grid[x][y].display(); } }

    // frame around grid noFill(); stroke(0); rect (grid[0][0].x, grid[0][0].y, 350,300); }

    void keyPressed() { if (!gameOver&& targetCounter<targetCounterMax) { if (key == CODED) { if (keyCode == UP) { // push Ellipse up (y = -1) pushEllipse(0, -1); } else if (keyCode == DOWN) { // push Ellipse down (y = 1) pushEllipse(0, 1); } else if (keyCode == LEFT) { // push Ellipse left (x = -1) pushEllipse(-1, 0); } else if (keyCode == RIGHT) { // push Ellipse right (x = 1) pushEllipse(1, 0); } } } else { if (key==' ') { // reset gameOver=false; startTime=millis(); } } }

    void pushEllipse( int xAdd, int yAdd ) {

    // push Ellipse in a direction given by xAdd and yAdd

    // get the position of the ellipse PVector pvE=ellipsePosition();

    int x=int(pvE.x); int y=int(pvE.y); // test: must be an ellipse

    // -----------------------------------------------------------

    // if (x+xAdd<0||y+yAdd<0|| x+xAdd>wideCount-1||y+yAdd>highCount-1) return;

    // test: target tile must be c, b or t if (!grid[x+xAdd][y+yAdd].allowedTileForEllipse()) return;

    if (grid[x+xAdd][y+yAdd].type=='b') {

    // special move with a box
    
    // test: target field of the block (where the block goes to)
    // must be inside 
    if (x+xAdd+xAdd<0||y+yAdd+yAdd<0||
      x+xAdd+xAdd>=wideCount||y+yAdd+yAdd>=highCount) 
      return; 
    
    // no wall is allowed behind the block
    if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='w' || grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='i') 
      return; 
    
    // check target 
    if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='t') 
      targetCounter++;
    
    // move ellipse and block 
    if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
      grid[x][y].type=grid[x][y].previousType;
    else grid[x][y].type='c'; // corridor   
    grid[x+xAdd][y+yAdd].type='e'; // ellipse
    grid[x+xAdd+xAdd][y+yAdd+yAdd].type='b'; //move block by 1
    return;
    

    } else { // normal move if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b') grid[x][y].type=grid[x][y].previousType; else grid[x][y].type='c'; // corridor
    grid[x+xAdd][y+yAdd].previousType = grid[x+xAdd][y+yAdd].type;
    grid[x+xAdd][y+yAdd].type='e'; return; } }// func

    PVector ellipsePosition() { for (int x=0; x< wideCount; x++) { for (int y=0; y< highCount; y++) { if ( grid[x][y].type=='e' ) { return new PVector(x, y); }// if } }

    // error return null; }

    // ==========================================================

    class Tile {

    float x, y; float side;

    char type='u'; char previousType='u';

    Tile (float tempX, float tempY, float tempSide, char tempType) { x = tempX; y = tempY; side = tempSide; type=tempType; }

    void display() {

    switch (type) {
    
    case 'e':
      // ellipse (our player)
      corridor();
      stroke(0); 
      fill(255, 0, 0); // red
      ellipse(x+side/2, y+side/2, side-6, side-6);
      break;
    
    case 't':
      // target
      corridor(); 
      noStroke();
      fill(255, 0, 0); // red
      ellipse(x+side/2, y+side/2, 3, 3);
      break;
    
    case 'w':
      // wall
      fill(0);  //  
      stroke(0);
      rect (x, y, side, side);      
      break;
    
    
    case 'c':
      corridor(); 
      break;
    
    case 'b':
      // moveable block
      corridor();
      fill(0, 255, 0);  // green 
      stroke(0); 
      rect (x+2, y+2, side-6, side-6);
      break;
    
    
    }//switch
    

    }// func

    void corridor() { // draw corridor // (also as background for block and target etc.) fill(255); // white stroke(255); rect (x, y, side, side); }//func

    boolean allowedTileForEllipse() {

    return "ctb".indexOf(type)  > -1;
    

    }// func }//class //

    i still have one questin. how to make a next level when i already put the boxes i the rght place?

  • // the grid (a 2D-Array) 
    Tile[] [] grid; // grid 
    int unit = 50;  // size of one tile 
    int wideCount = 150 ; // how many
    int highCount=150  ; // how many
    
    // the coding: 
    
    // w =wall
    // t =target 
    // e =ellipse (we steer it with cursor)
    // b =block, moveable 
    // c =corridor, empty
    // u =unknown type (don't use this here)
    
    
    String[] map = {
      "iiwtwii", 
      "iiwcwww", 
      "wwwbcbt", 
      "wtcbeww", 
      "wwwwbwi",
      "iiiwtwi",
    
    
    };
    
    // counter for the targets 
    int targetCounter    = 0; // current  
    int targetCounterMax = 4; // number of all targets in the level
    
    // font
    PFont font;
    
    // timer 
    String time = "";
    int t=0;
    int interval = 30;
    int startTime;
    
    // game over? 
    boolean gameOver = false;
    
    // --------------------------------------------------------
    
    void setup() {
      size (900, 550);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      buildTheGrid();
    }
    
    void draw() {
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
    
        generalScreenDesign();
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
      } else {
        // normal game 
    
        generalScreenDesign(); 
    
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
    
          textSize(32);
          text ("Level 1", 200, 30);
          strokeWeight(3);
        }
    
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
      }// else
    }//func 
    
    // ----------------------------------------------------------
    
    void buildTheGrid() {
    
      wideCount = map[1].length(); // the length of one String/line in the array map
      highCount = map.length;  // how many lines in the array map       
    
      grid = new Tile[wideCount][highCount];
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      // double for-loop for a 2D-Array 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
    
    
          // get type from map (line number y, character number = x)
          char type = map[y].charAt(x);
    
          // to detect some errors, we monitor if we found ellipse and target 
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
    
          }
    
          // create object
          grid[x][y] = new Tile (x*unit+200, y*unit+130, 
            unit, 
            type );
        }//for
      }//for
    
    
      }
    
    
    void generalScreenDesign() {
    
      // show grid 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          grid[x][y].display();
        }
      }
    
    
      // frame around grid 
      noFill(); 
      stroke(0);
      rect (grid[0][0].x, 
        grid[0][0].y, 
        350,300);
    }
    
    void keyPressed() {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
            // push Ellipse up (y = -1)
            pushEllipse(0, -1);
          } else if (keyCode == DOWN) {
            // push Ellipse down (y = 1)
            pushEllipse(0, 1);
          } else if (keyCode == LEFT) {
            // push Ellipse left (x = -1)
            pushEllipse(-1, 0);
          } else if (keyCode == RIGHT) {
            // push Ellipse right (x = 1)
            pushEllipse(1, 0);
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false;
          startTime=millis();
        }
      }
    }
    
    void pushEllipse( int xAdd, int yAdd ) {
    
      // push Ellipse in a direction given by xAdd and yAdd
    
      // get the position of the ellipse 
      PVector pvE=ellipsePosition();
    
      int x=int(pvE.x);
      int y=int(pvE.y);
      // test: must be an ellipse 
    
    
      // -----------------------------------------------------------
    
     //
      if (x+xAdd<0||y+yAdd<0||
        x+xAdd>wideCount-1||y+yAdd>highCount-1) 
        return; 
    
      // test: target tile must be c, b or t 
      if (!grid[x+xAdd][y+yAdd].allowedTileForEllipse())
        return; 
    
      if (grid[x+xAdd][y+yAdd].type=='b') {
    
        // special move with a box
    
        // test: target field of the block (where the block goes to)
        // must be inside 
        if (x+xAdd+xAdd<0||y+yAdd+yAdd<0||
          x+xAdd+xAdd>=wideCount||y+yAdd+yAdd>=highCount) 
          return; 
    
        // no wall is allowed behind the block
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='w' || grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='i') 
          return; 
    
        // check target 
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='t') 
          targetCounter++;
    
        // move ellipse and block 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor   
        grid[x+xAdd][y+yAdd].type='e'; // ellipse
        grid[x+xAdd+xAdd][y+yAdd+yAdd].type='b'; //move block by 1
        return;
      } else {
        // normal move 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor       
        grid[x+xAdd][y+yAdd].previousType = grid[x+xAdd][y+yAdd].type;  
        grid[x+xAdd][y+yAdd].type='e';
        return;
      }
    }// func 
    
    PVector ellipsePosition() {
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          if ( grid[x][y].type=='e' ) {
            return new PVector(x, y);
          }// if
        }
      }
    
      // error 
      return null;
    }
    
    // ==========================================================
    
    class Tile {
    
      float x, y;
      float side;
    
      char type='u';
      char previousType='u'; 
    
      Tile (float tempX, float tempY, 
        float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        type=tempType;
      }
    
      void display() {
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, side-6, side-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 3, 3);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
    
        }//switch
      }// func
    
      void corridor() {
        // draw corridor
        // (also as background for block and target etc.)
        fill(255);  // white 
        stroke(255);
        rect (x, y, side, side);
      }//func
    
      boolean allowedTileForEllipse() {
    
        return "ctb".indexOf(type)  > -1;
      }// func
    }//class
    // 
    
  • You are making great progress!

  • edited July 2016

    This is were you win

      if (targetCounter==targetCounterMax) {
    

    Now here you need to wait for key press: space bar

    Then say levelNumber ++;

    and reset all : target counter , target max, timer,

    define new grid with new map (wwcwwt......)

  • edited May 2016

    Look at states also, when you want to see a concept how to treat the different states within a program

    state being game / gameover / newlevel / win etc. - all with different messages / screens

    Btw you need a way go say give up, when you Can't solve it anymore you can restart level

  • Try search state here in the forum

  • Is this homework?

    When do you have to hand it in?

  • do you mean i have to write final int stategame = 0; case stategame: like this? is it ok if i wrote final int stategame, because i have read that if we use 'final' then it will be our final. yes, i have to hand it every thursday to explain my progress with this game :)

  • edited July 2016

    int state = 0;

    and then 1 and 2 ...

    but then use switch(state) { in draw()

    you can give the states names and then use the names instead of 0,1,2....:

    final int stateGame=0;
    
    final int stateGameOver =1; 
    
    final int stateNewLevelScreen = 2;
    

    etc.

    then you can use those constants in

    switch(state) { 
    
        case stateGame: 
        // 
        break; 
    
        case stateGameOver: 
        //
        break; 
    
        case stateNewLevelScreen: 
        // 
        break; 
    
    }
    

    also use an indexLevel or so to monitor the level number

  • Answer ✓

    this is a typical (empty) sketch with states

    //
    // states
    final int stateGame  = 0;  // consts
    final int statePause = 1;
    int state = statePause;    // current state
    
    // ---------------------------------------------------------------
    
    void setup()
    {
      // init (runs only once)
      size(800, 600);
    } // func 
    
    void draw() 
    { 
      // draw() runs on and on 
    
      switch (state) {
    
      case stateGame: 
        // Game
        handleStateGame();
        break; 
    
      case statePause:
        // Pause
        handleStatePause(); 
        break;
    
      default:
        // error
        println("Error number 939; unknown state : " 
          + state 
          + ".");
        exit();
        break;
      } // switch
      //
    } // func 
    
    // ------------------------------------------------------------
    
    // functions for states - called from draw() 
    
    void handleStateGame() {
      // Game
      background(11);
      fill(244, 3, 3); // red 
      text ("Game....", 210, 313);
      signHome(10, 100);
    } // func 
    
    void handleStatePause() {
      // Pause
      background(255);
      fill(244, 3, 3); // red 
      text ("Pause.... ", 210, 313);
      text ("Hit p to start ", 210, 385);
      signHome(width-70, 100);
    } // func 
    
    // ----------------------------------------
    // keyboard input 
    
    void keyPressed() {
    
      switch (state) {
    
      case stateGame: 
        // Game
        keyPressedForStateGame();
        break; 
    
      case statePause:
        // Pause
        keyPressedForStatePause(); 
        break;
    
      default:
        // error
        println("Error number 1039; unknown state : "
          + state 
          + ".");
        exit();
        break;
      } // switch
    } // func 
    
    // ----
    
    void keyPressedForStateGame() { 
      if (key == CODED) 
      {
        if (keyCode == UP) {
          //
        } else if (keyCode == DOWN) {
          //
        }
    
        if (keyCode == LEFT) {
          //
        } else if (keyCode == RIGHT) {
          //
        } else {
          // do nothing
        } // else
      } //  if (key == CODED) {
      else 
      {
        // not CODED ---------------------- 
        if (key == 'p') {
          // Pause 
          state = statePause;
        } else {
          // do nothing
        } // else
      } // else not CODED
    } // func
    
    void keyPressedForStatePause() { 
      if (key == CODED) 
      {
        if (keyCode == UP) {
          //
        } else if (keyCode == DOWN) {
          // none
        }
    
        if (keyCode == LEFT) {
          //
        } else if (keyCode == RIGHT) {
          //
        } else {
          // do nothing
        } // else
      } //  if (key == CODED) {
      else 
      {
        // not CODED ---------------------- 
        if (key == 'p') {
          //
          state = stateGame;
        } else {
          // do nothing
        } // else
      } // else not CODED
    } // func
    
    // -------------------------------------------------------
    // Mouse input
    
    void mousePressed() {
      //
      switch (state) {
    
      case stateGame: 
        // Game
        mousePressedForStateGame();
        break; 
    
      case statePause:
        // Pause
        mousePressedForStatePause(); 
        break;
    
      default:
        // error
        println("Error number 1139; unknown state : " + state+".");
        exit();
        break;
      } // switch
    } // func 
    
    void mousePressedForStateGame() {
      if (dist(mouseX, mouseY, 10, 100) < 30 ) { 
        println ("Hit Game.");
      }
    } // func 
    
    void mousePressedForStatePause() {
      if (dist(mouseX, mouseY, width-70, 100) < 30 ) { 
        println ("Hit Pause.");
      }
    } // func 
    
    // -------------------------------------------------------
    // Misc
    
    void signHome(int x, int y) {
      // gives a sign for a house / home sign
    
      final int width1=6;
      final int height1=8;
    
      fill( 2, 255, 0 );
      strokeWeight(1);
      stroke ( 2, 255, 0 );
      noFill();
      x+=21;
      y+=14;
      triangle ( x-width1, y, 
        x, y-height1, 
        x+width1, y );
      rect(x-width1/2, y, width1, width1);
      rect(x-width1/4+1, y+height1/4+1, width1/4, width1/3);
      strokeWeight(1);
    }
    
    // =================================================
    
  • Answer ✓

    actually you don't need states - just concentrate on the different levels

  • I did it! Finished!

  • so i don't need states? function of states just for pause, start and other things right? so where i have to put my new grid (level 2) in the code?

  • You can go on without states

    You have map={......

    here you could say map1 ......

    And map2........

    And map3.....

    Now in buildTheGrid depending on your levelNumber choose one switch(levelNumber){ ....

  • i already made like you said, but it wont work. in void built the grid

    // the grid (a 2D-Array) 
    Tile[] [] grid; // grid 
    int unit = 50;  // size of one tile 
    int wideCount = 150 ; // how many
    int highCount=150  ; // how many
    
    // the coding: 
    
    // w =wall
    // t =target 
    // e =ellipse (we steer it with cursor)
    // b =block, moveable 
    // c =corridor, empty
    // u =unknown type (don't use this here)
    
    
    String[] map1= {
      "iiwtwii", 
      "iiwcwww", 
      "wwwbcbt", 
      "wtcbeww", 
      "wwwwbwi",
      "iiiwtwi",
    
    
    
    };
    
     String[] map2 = {
    "iiwtwii",
    "iiwcwww",
    "wwwbcbt",
    "wtcbeww",
    "wwwwbwi",
    "iiiwtwi",
     };
    // counter for the targets 
    int targetCounter    = 0; // current  
    int targetCounterMax = 0; // number of all targets in the level
    
    // font
    PFont font;
    
    // timer 
    String time = "";
    int t=0;
    int interval = 30;
    int startTime;
    
    // game over? 
    boolean gameOver = false;
    
    // --------------------------------------------------------
    
    void setup() {
      size (900, 550);
      background(255);
    
      font = createFont("Arial", 10);
      fill(0);
    
      buildTheGrid();
    }
    
    void draw() {
    
      background(255);
    
      if (targetCounter==targetCounterMax) {
        // Win !!!
    
        generalScreenDesign();
    
        textSize(32);
        fill(255, 2, 2);
        text("You WON", 50, 50);
    
      } else {
        // normal game 
    
        generalScreenDesign(); 
    
        if (!gameOver) {
    
          t = interval-int((millis()-startTime)/1000);
          time = nf(t, 2);
          if (t == 0) {
            gameOver = true;
          }
          fill(0); 
          stroke(0); 
          textSize(32);
          text(time, 100, 100);
    
    
        }
    
        //if game over
        if (gameOver) {
          textSize(32);
          text("GAME OVER", 10, 30);
        }
      }// else
    }//func 
    
    // ----------------------------------------------------------
    
    void buildTheGrid() {
     switch (level1){
      wideCount = map[1].length(); // the length of one String/line in the array map
      highCount = map.length;  // how many lines in the array map       
     }
      grid = new Tile[wideCount][highCount];
    
      boolean ellipseFound=false; 
      boolean targetFound=false; 
    
      // double for-loop for a 2D-Array 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
    
    
    
          // get type from map (line number y, character number = x)
          char type = map[y].charAt(x);
    
          // to detect some errors, we monitor if we found ellipse and target 
          if (type=='e') {
            ellipseFound=true;
          }
          if (type=='t') {  
            targetFound=true;
    
          }
    
          // create object
          grid[x][y] = new Tile (x*unit+200, y*unit+130, 
            unit, 
            type );
        }//for
      }//for
    
    
      }
    
    
    void generalScreenDesign() {
    
      // show grid 
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          grid[x][y].display();
        }
      }
    
    
      // frame around grid 
      noFill(); 
      stroke(0);
      rect (grid[0][0].x, 
        grid[0][0].y, 
        350,300);
    }
    
    void keyPressed() {
      if (!gameOver&&
        targetCounter<targetCounterMax) {
        if (key == CODED) {
          if (keyCode == UP) {
            // push Ellipse up (y = -1)
            pushEllipse(0, -1);
          } else if (keyCode == DOWN) {
            // push Ellipse down (y = 1)
            pushEllipse(0, 1);
          } else if (keyCode == LEFT) {
            // push Ellipse left (x = -1)
            pushEllipse(-1, 0);
          } else if (keyCode == RIGHT) {
            // push Ellipse right (x = 1)
            pushEllipse(1, 0);
          }
        }
      } else {
        if (key==' ') {
          // reset 
          gameOver=false;
          startTime=millis();
        }
      }
    }
    
    void pushEllipse( int xAdd, int yAdd ) {
    
      // push Ellipse in a direction given by xAdd and yAdd
    
      // get the position of the ellipse 
      PVector pvE=ellipsePosition();
    
      int x=int(pvE.x);
      int y=int(pvE.y);
      // test: must be an ellipse 
    
    
      // -----------------------------------------------------------
    
     //
      if (x+xAdd<0||y+yAdd<0||
        x+xAdd>wideCount-1||y+yAdd>highCount-1) 
        return; 
    
      // test: target tile must be c, b or t 
      if (!grid[x+xAdd][y+yAdd].allowedTileForEllipse())
        return; 
    
      if (grid[x+xAdd][y+yAdd].type=='b') {
    
        // special move with a box
    
        // test: target field of the block (where the block goes to)
        // must be inside 
        if (x+xAdd+xAdd<0||y+yAdd+yAdd<0||
          x+xAdd+xAdd>=wideCount||y+yAdd+yAdd>=highCount) 
          return; 
    
        // no wall is allowed behind the block
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='w' || grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='i') 
          return; 
    
        // check target 
        if (grid[x+xAdd+xAdd][y+yAdd+yAdd].type=='t') 
          targetCounter++;
    
        // move ellipse and block 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor   
        grid[x+xAdd][y+yAdd].type='e'; // ellipse
        grid[x+xAdd+xAdd][y+yAdd+yAdd].type='b'; //move block by 1
        return;
      } else {
        // normal move 
        if (grid[x][y].previousType!='u'&&grid[x][y].previousType!='b')
          grid[x][y].type=grid[x][y].previousType;
        else grid[x][y].type='c'; // corridor       
        grid[x+xAdd][y+yAdd].previousType = grid[x+xAdd][y+yAdd].type;  
        grid[x+xAdd][y+yAdd].type='e';
        return;
      }
    }// func 
    
    PVector ellipsePosition() {
      for (int x=0; x< wideCount; x++) {
        for (int y=0; y< highCount; y++) {
          if ( grid[x][y].type=='e' ) {
            return new PVector(x, y);
          }// if
        }
      }
    
      // error 
      return null;
    }
    
    // ==========================================================
    
    class Tile {
    
      float x, y;
      float side;
    
      char type='u';
      char previousType='u'; 
    
      Tile (float tempX, float tempY, 
        float tempSide, 
        char tempType) {
        x = tempX;
        y = tempY;
        side = tempSide;
        type=tempType;
      }
    
      void display() {
    
        switch (type) {
    
        case 'e':
          // ellipse (our player)
          corridor();
          stroke(0); 
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, side-6, side-6);
          break;
    
        case 't':
          // target
          corridor(); 
          noStroke();
          fill(255, 0, 0); // red
          ellipse(x+side/2, y+side/2, 3, 3);
          break;
    
        case 'w':
          // wall
          fill(0);  //  
          stroke(0);
          rect (x, y, side, side);      
          break;
    
    
        case 'c':
          corridor(); 
          break;
    
        case 'b':
          // moveable block
          corridor();
          fill(0, 255, 0);  // green 
          stroke(0); 
          rect (x+2, y+2, side-6, side-6);
          break;
    
    
        }//switch
      }// func
    
      void corridor() {
        // draw corridor
        // (also as background for block and target etc.)
        fill(255);  // white 
        stroke(255);
        rect (x, y, side, side);
      }//func
    
      boolean allowedTileForEllipse() {
    
        return "ctb".indexOf(type)  > -1;
      }// func
    }//class
    // 
    
  • In line 125 you need that switch(levelNumber

  • like this? switch (level1){ char type = map[y].charAt(x); }

  • Read the reference for switch

    case 0:

    char......

    break;

    case 1:

    char.....

    break;

    level1 is not a good name; it is levelNumber which you will increase after each level

  • switch (levelnumber){
     case 0:
    
          char type = map1[y].charAt(x);
          break;
    
      case 1:
      char type = map2[y].charAt(x);
      break;
    }
    

    is it right? but in widecount = map[1].length() wont resolve, under builtthegrid(){

  • The switch looks correct

    Where do you increase levelnumber ?

    There are 2 kinds of length - the one you got there is without ()

  • Sorry, the () is correct there, since we are using length on a String I think

    but where you define the map iiiwtwi", }

    the last comma is wrong (before the } )

  • how to increase levelnumber?

    still cant resolve the
    wideCount = map[1].length(); // the length of one String/line in the array map. it says "map cannot resolved to a variable" when i add switch (levelnumber){ case 0:

          char type = map1[y].charAt(x);
          break;
    
      case 1:
      char type = map2[y].charAt(x);
      break;
    }
    
  • It's map1 or map2, not map

    to increase just say levelNumber ++;

    but where in the code?

Sign In or Register to comment.