My projects library #4! Gallery Megathread

#46 Simple Mine-Sweeper


(Won, Playing, Lost)

Code
int a = 10; //width and height of grid
int grid[][] = new int[a][a];
int scl = 600/a, m = 10;
boolean show[][] = new boolean[a][a];
boolean flagged[][] = new boolean[a][a];
int RESULT = 0; //-1: lost 0: undecided 1: won
void setup() {
  size(600, 600);
  grid = newGrid(a, m);
  textAlign(3, 3);
  textSize(scl*0.6);
}
void draw() {
  background(0);
  stroke(255, 50);
  for (int i = 1; i < a; i++) {
    line( i*scl, 0, i*scl, height);
    line( 0, i*scl, width, i*scl);
  }
  for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
    if (show[i][j]||RESULT==1) {
      fill(100);
      square(i*scl, j*scl, scl);
      fill(255);
      if (grid[i][j] > 0) text(grid[i][j], (i+0.5)*scl, (j+0.5)*scl);
      else if(grid[i][j]==-1) drawMine(i,j);
    } else {
      if (mouseX>i*scl&&mouseY>j*scl&&mouseX<(i+1)*scl&&mouseY<(j+1)*scl) {
        fill(200);
      } else fill(0);
      square(i*scl, j*scl, scl);
      if (flagged[i][j]) {
        fill(0, 0, 255, 50);
        square(i*scl, j*scl, scl);
      }
    }
    if(RESULT==-1 && grid[i][j]==-1) drawMine(i,j);
  }
  if(RESULT!=0) {
    textSize(100+sin(frameCount*0.05)*scl*0.25);
    if(RESULT==1) {
      //sin -1 1
      //+1= 0 2
      // *0.5 = 0 1
      fill(20,255,20,map( sin(frameCount*0.05), -1,1, 100,255));
      text("YOU WIN!!",width*0.5,height*0.5);
    } else if(RESULT==-1) {
      fill(255,20,20,map( sin(frameCount*0.05), -1,1, 100,255));
      text("YOU LOSE!!",width*0.5,height*0.5);
    }
    textSize(scl*0.6);
  }
}
void drawMine(int x, int y) {
  fill(255,0,0,150);
  circle((x+0.5)*scl,(y+0.5)*scl,scl*0.5);
}

void mousePressed() {
  int mx = mouseX/scl, my = mouseY/scl;
  if (mouseButton==LEFT) {
    if (flagged[mx][my]==false) checkSlot(mx, my);
  } else if (mouseButton==RIGHT && RESULT==0) flagged[mx][my] = !flagged[mx][my];
}
void keyPressed() {
  if(key==' ') println(checkWin());
}
void checkSlot(int x, int y) {
  if (grid[x][y]==-1) {
    println("GAME OVER");
    RESULT=-1;
  } else if (RESULT==0) {
    show[x][y]=true;
    while (spreadVisible(x, y)>0);
    if (checkWin()) {
      RESULT=1;
      println("YOU WIN!");
    }
  }
}
int spreadVisible(int x, int y) {
  int num = 0;
  for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
    if (grid[i][j]==0||i==x&&j==y) {
      for (int k = -1; k < 2; k++) for (int l = -1; l < 2; l++) if (inBounds(i, j, k, l, a)) {
        if (grid[i+k][j+l]!=-1) show[i+k][j+l]=true;
      }
    }
  }
  return num;
}
int[][] newGrid (int na, int nm) {
  int ngrid[][] = new int[na][na];
  if (nm>=na*na) nm = na*na-1; //to prevent infinite loops, the higher the mine:area ratio the longer it takes
  for (int i = 0, rx = (int)random(na), ry = (int)random(na); i < nm; i++, rx = (int)random(na), ry =(int)random(na)) {
    while (!canPlace(ngrid, rx, ry, 0)) {
      rx = (int)random(na); 
      ry = (int)random(na);
    }
    ngrid[rx][ry]=-1;
  }
  for (int i = 0; i < na; i++) for (int j = 0; j < na; j++) if (ngrid[i][j]!=-1) {
    int num = 0;
    for (int k = -1; k < 2; k++) for (int l = -1; l < 2; l++) if (!(k==0&&l==0) && inBounds(i, j, k, l, a)) {
      if (ngrid[i+k][j+l]==-1) num ++;
    }
    ngrid[i][j] = num;
  }
  a = na;
  m = nm;
  return ngrid;
}
boolean inBounds(int x, int y, int px, int py, int w) {
  return(x+px<w&&y+py<w&&x+px>=0&&y+py>=0);
}
boolean canPlace(int mgrid[][], int x, int y, int desired) {
  return(mgrid[x][y]==desired);
}
boolean checkWin() {
  boolean won = true; //first set it to true
  for (int i = 0; i < a; i++) for (int j = 0; j < a; j++) {
    if (!(show[i][j]==true&&grid[i][j]>=0 || show[i][j]==false&&grid[i][j]==-1)) won = false;
  }
  return won;
}

Notable features:

  • flexible grid size and amount of mines
  • flag slots to mark potential mines (cannot uncover unless you unflag)

A game I completed with 20x20 grid & 40 mines.

#47 3n+1 sequence
Outputs it format: [sum] [highest number] [sequence…] […] […] [1]

Code
void setup() {
  printArray(path(1001));
  exit();
}
long[] path(long start) { //0 - sum 1 - max
  ArrayList<Long> values = new ArrayList<Long>();
  long num = start, sum = 0, maxNum=0;
  while(num!=1) {
    if(num%2==0) num*=0.5;
    else num=num*3+1;
    values.add(num);
    sum+=num;
    if(num>maxNum) maxNum=num;
  }
  long output[] = {sum,maxNum};
  output = expand(output,values.size()+2);
  for(int i = 0; i < values.size(); i++) output[i+2]=values.get(i);
  return output;
}

EDIT: there are 3 issues:
1st: the entered number will not show up , so with path(1) you will get the output [0] [0] instead of [1] [1] [1]
2nd: if you enter 0 you will never get the result out
3rd: negative numbers enter an infinite loop. To stop this, just add in the while condition:

EDIT 2:
Version without the above issues (But it is slightly slower)

Version 2
void setup() {
  printArray(path(16));
  exit();
}
long[] path(long start) { //0 - sum 1 - max
  ArrayList<Long> values = new ArrayList<Long>();
  long num = start, sum = 0, maxNum=0;
  values.add(num);
  while(num!=1&&!values.contains(num)) {
    if(num%2==0) num*=0.5;
    else num=num*3+1;
    values.add(num);
    sum+=num;
    if(num>maxNum) maxNum=num;
    println(num);
  }
  long output[] = {sum,maxNum};
  output = expand(output,values.size()+2);
  for(int i = 0; i < values.size(); i++) output[i+2]=values.get(i);
  return output;
}

nice work keep on :wink: :wink: :wink:

1 Like

#48 String sum
Description: can add two integers (in string form) allowing you to have far larger range. Negative numbers are not supported.

The code contains a fibonacci example and limits allowing you to get the 1000 digit number (4781th value in sequence).

Code
String stringSum(String n1, String n2) {
  String output="";
  while(n1.length()!=n2.length()) {
    if(n1.length()>n2.length()) {
      n2 = "0"+n2;
    } else if(n2.length()>n1.length()) {
      n1 = "0"+n1;
    }
  }
  int rem = 0;
  for(int i = n1.length()-1; i >= 0; i--) {
    int sum = n1.charAt(i)+n2.charAt(i)-96+rem;
    rem=0;
    String abc = sum+"";
    output = abc.charAt(abc.length()-1)+output;
    if(abc.length()==2) rem = int(abc.charAt( abc.length()-2 ))-48;
  }
  if(rem>0)output = rem + output;
  return output;
}
void setup() {
  String a = "0";
  String b = "1";
  String c = "1";
  for(int i = 0; i < 4783; i++) {
    c = stringSum(a,b);
    a = b;
    b = c;
    println("["+i+"] L:",a.length(),"NEXT:\n"+a); //using a instead of c so it is aligned with the challenge
  }
}

#49 Wolfram cellular automata
Edges - looped

Code
//wolfram - by timbebender
ArrayList<int[]> grid = new ArrayList<int[]>();
int w = 330, h = 1000, scl = 660/w;
boolean rules[] = new boolean[8];
void setup() {
  size(660, 600);
  genRule();
}
void mousePressed() { 
  genRule();
}
void genRule() {
  grid.clear();
  int startW[] = new int[w];
  startW[floor(w*0.5)] = 1;

  for (int i = 0; i < rules.length; i++) rules[i] = (random(1)>0.5);
  int v = 0;
  for (int i = 0, m = 128; i < 8; i++, m*=0.5) v+=m*((rules[i])? 1 : 0);
  println(v);

  grid.add(startW);
}

void draw() {
  background(0); 
  noStroke();
  for (int j = 0; j < grid.size(); j++) {
    for (int i = 0; i < grid.get(j).length; i++) {
      fill( ((grid.get(j)[i]!=0)? color(255) : color(0) ) );
      square(i*scl, j*scl, scl);
    }
  }
  if (grid.size()*scl<height) {
    grid.add(generate(grid.get(grid.size()-1), rules));
  }
}
int[] generate(int[] prev, boolean[] ruls) {
  int next[] = new int[prev.length];
  next[0] = checkrule(prev[prev.length-1], prev[0], prev[1], ruls);
  next[next.length-1] = checkrule(prev[prev.length-2], prev[prev.length-1], prev[0], ruls); //ENDGES WRAP ARROUND
  for (int i = 1; i < next.length-1; i++) {
    next[i] = checkrule(prev[i-1], prev[i], prev[i+1], ruls);
  }
  return next;
}
int checkrule(int l, int c, int r, boolean[] ruls) {
  int combine = l*4+c*2+r;
  return 1*((ruls[combine])? 1 : 0);
}

#50 Mutated Wolfram cellular automata
(Mutated or modified, whichever : P)
The difference is that it doesn’t have rules for: [left cell, this cell, right cell] but also the 3 cells above them, so it generates the next row based on the previous two. It has 64 different rules (2^6), resulting in 2^64 different combination.

Code
int w = 600, h=600, gens=1;
int grid[][] = new int[h][w];
int rules[] = new int[64]; //2^6 = 64
boolean loop = true;
void setup() {
  size(600, 600);
  genBoard();
}
void draw() {
  background(0);
  loadPixels();
  for (int j = 0; j < gens; j++) for (int i = 0; i < w; i++) {
    int index = i+j*width;
    color clr = ((grid[j][i]==1)? color(255) : color(0) );
    pixels[index] = clr;
  }
  updatePixels();
  if (gens<h-1) {
    grid[gens] = generate(grid[gens-1], grid[gens], rules);
    gens++;
  }
}
void genBoard() {
  grid = new int[h][w];
  for (int i = 0; i < rules.length; i++) rules[i] = round(random(1));
  grid[0] = new int[w];
  grid[1] = new int[w];
  grid[1][300] = 1;
  gens=1;
}
int[] generate(int[] pp, int[] p, int[] rls) {
  int next[] = new int[w];
  if(!loop) for (int i = 1; i < w-1; i++) next[i] = checkRule(pp[i-1], pp[i], pp[i+1], p[i-1], p[i], p[i+1], rls);
  if(loop) for(int i = 0; i < w; i++) next[i] = checkRule(pp[((i-1>0)? i-1 : w-1)], pp[i], pp[(i+1)%w], p[((i-1>0)? i-1 : w-1)], p[i], p[(i+1)%w], rls);
  return next;
}
int checkRule(int pl, int pc, int pr, int cl, int cc, int cr, int[] rls) {
  int v = pl+pc*2+pr*4+cl*8+cc*16+cr*32;
  return rls[v];
}
void mousePressed() {
  genBoard();
}

Looping around the edges can be disabled.
If you press the mouse, another pattern will be generated

#51 Simple pong game

Code
int w = 400, h = 400;
int scoreA = 0, scoreB = 0; //LEFT - A, RIGHT - B
float speed=5, barSpeed=3, ballS = 20, ballX = w, ballY = h*0.5, xS = ((random(1)>=0.5)? 1 : -1), yS = ((random(1)>=0.5)? 1 : -1) * random(1,0.7);
float barX=0.1, barH = 32, barA = h*0.5, barB = h*0.5;
int mA = 0, mB = 0;
void keyPressed() {
  if (keyCode==UP) mB=-1;
  if (keyCode==DOWN) mB=1;
  if (key=='w') mA=-1;
  else if (key=='s') mA=1;
}
void keyReleased() {
  if (mB==-1 && keyCode==UP ||mB==1 && keyCode==DOWN) mB=0;
  if (mA==-1 && key=='w' ||mA==1 && key=='s') mA=0;
}


void setup() {
  size(800, 400);
  textSize(50);
}
void draw() {
  background(0);
  stroke(255);
  fill(255);
  line(w, 0, w, height);
  float sw1 = textWidth(scoreA+"");
  text(scoreA, w-sw1-5, textAscent());
  text(scoreB, w+5, textAscent());

  //bar movements
  barA=constrain(barA+mA*barSpeed, barH, h-barH);
  barB=constrain(barB+mB*barSpeed, barH, h-barH);
  line( w*barX, barA-barH, w*barX, barA+barH);
  line( w*(2-barX), barB-barH, w*(2-barX), barB+barH);


  //puck movement
  ballX+=speed*xS;
  ballY+=speed*yS;
  if (ballY>h-ballS*0.5||ballY<ballS*0.5) { //puck bounce of walls
    ballY = ((ballY>h*0.5)? h-ballS*0.5 : ballS*0.5 );
    yS*=-1;
  }
  //puck deflection
  if (ballX>(2-barX)*w-ballS*0.5&&ballX<(2-barX)*w+ballS*0.5 && ballY>barB-barH-ballS*0.5&&ballY<barB+barH+ballS*0.5) {
    ballX=(2-barX)*w-ballS*0.5;
    xS*=-1;
  }
  if (ballX>barX*w-ballS*0.5&&ballX<(barX)*w+ballS*0.5) {
    ballX=(barX)*w+ballS*0.5;
    xS*=-1;
  }

  //drawing the puck
  square(ballX-ballS*0.5, ballY-ballS*0.5, ballS);
  //scoring system
  if (ballX>w*2) scoreA++;
  if (ballX<0) scoreB++;
  else if (ballX<-ballS) scoreB++;
  if (ballX>w*2||ballX<0) {
    ballX=w;
    ballY=h*0.5;
    xS=((random(1)>=0.5)? 1 : -1);
  }
}

There is a bug where the puck bounces off empty air. Not sure what’s wrong but yeah. Besides that, I didn’t implement ignore-case-controlls, so playing with capslock is impossible. Good luck playing!

#52 SnakePVP

Code
int w = 20, h = 20, scl=30;
int grid[][] = new int[w][h];
color clr1 = color(255, 0, 0), clr2 = color(0, 0, 255);
color trail1 = color(50, 0, 0), trail2 = color(0, 0, 50);
int x1=5, y1=5, x2=15, y2=15;
float d1 = 0, d2 = 2;
int RESULT = 0;
void setup() {
  size(660, 660);
  textAlign(3, 3);
}
void keyPressed() {
  d1 = ((keyCode==RIGHT)? 0 : ((keyCode==DOWN)? 1 : ((keyCode==LEFT)? 2 : ((keyCode==UP)? 3 : d1)))); 
  char pressed = ((key+"").toLowerCase()).charAt(0);
  d2 = ((pressed=='d')? 0 : ((pressed=='s')? 1 : ((pressed=='a')? 2 : ((pressed=='w')? 3 : d2))));
}

void draw() {
  background(50, 255, 50);
  fill(0); 
  noStroke();
  square(scl, scl, scl*w);  
  int cx1 = round(cos(d1*HALF_PI)), cy1 = round(sin(d1*HALF_PI)), cx2 = round(cos(d2*HALF_PI)), cy2 = round(sin(d2*HALF_PI));
  if (grid[x1][y1]==0) grid[x1][y1] = 1;
  else RESULT = 2; //P1 LOSES
  if (grid[x2][y2]==0) grid[x2][y2] = 2;
  else RESULT = 1; //P2 LOSES
  if (RESULT==0) {
    x1+= cx1;
    y1+= cy1;
    x2+= cx2;
    y2+= cy2;
  }
  if(x1>=w||x1<0||y1>=h||y1<0) RESULT = 2;
  if(x2>=w||x2<0||y2>=h||y2<0) RESULT = 1;
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) if (grid[i][j]!=0) {
    fill( ((grid[i][j]==1)? trail1 : trail2) );
    square((i+1)*scl, (j+1)*scl, scl);
  }

  fill(clr1);
  square((x1+1)*scl, (y1+1)*scl, scl);
  fill(clr2);
  square((x2+1)*scl, (y2+1)*scl, scl);
  if (RESULT!=0) {
    textSize(50);
    if (RESULT==1) {
      println("Player 1 wins!");
      fill(clr1, 150);
      text("PLAYER 1 WINS", width*0.5, height*0.5);
    } else if (RESULT == 2) {
      println("Player 2 wins!");
      fill(clr2, 150);
      text("PLAYER 2 WINS", width*0.5, height*0.5);
    }
    noLoop();
  }
  delay(300);
}

A PVP game for two players

#53 Artistic Connect-n (4)


A program that allows you to play connect-n in a w * h size grid. It allows you to resize the grid and the win requirement. There is no win message.

Code
int w = 7, h = 6, inRow = 4, turn = 1, mx=0;
int grid[][] = new int[w][h];
float scl = 70, rm = 0.85;
color clr[] = {#FF001C, #75A2BF, #FFFF00};
int bottomBuffer=5, x=floor(700*0.5-w*scl*0.5), y=600-bottomBuffer-int(h*scl), sideW=25;
float coinX = y+scl*w/2, coinY = y - scl*0.6;
int RESULT = 0;
int wx1, wy1, wx2=4, wy2=4;
void setup() {
  size(700, 600);
}
void draw() {
  mx = (int)constrain(map(mouseX, x, x+w*scl, 0, w), 0, w-1);
  noStroke();
  strokeWeight(1);
  noFill();
  background(0);
  displayBoard();
  if (RESULT!=0) { 
    displayWin(wx1, wy1, wx2, wy2);
  }
}
int checkWin() { //0-none, -1: yellow 1: red 2: out of space
  //checking for outofspace
  boolean outOfSpace=true;
  for (int i = 0; i < w && outOfSpace==true; i++)for (int j = 0; j < h && outOfSpace==true; j++) if (grid[i][j]==0) outOfSpace=false;
  if (outOfSpace) return 2;
  //check for horizontal win
  for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) if (grid[i][j] != 0) for (int k = 0; k < 4; k++) {
    //HOR, VER, RDIG, LDIG
    int cx = ((k==0 || k == 2)? 1 : ((k==1)? 0 : -1)), cy = ((k==0)? 0 : 1);
    boolean win=true;
    int nx = i, ny = j, target = grid[i][j], row = 0;
    while (inBounds(nx, ny) && grid[nx][ny] == target) {
      row++;
      nx+=cx;
      ny+=cy;
    }
    if (row>=inRow) {
      wx1 = i;
      wy1 = j;
      wx2 = nx-cx;
      wy2 = ny-cy;
      return target;
    }
  }

  return 0;
}
boolean inBounds(int x, int y) {
  return(x>=0&&x<w&&y>=0&&y<h);
}
void displayWin(int x1, int y1, int x2, int y2) {
  stroke(0, 255, 0); 
  strokeWeight(3);
  boolean t = true, f = false;
  float nx1 = x+(x1+0.5)*scl, ny1 = y+(y1+0.5)*scl, nx2 = x+(x2+0.5)*scl, ny2 = y+(y2+0.5)*scl;
  float dir = atan2(y2-y1, x2-x1);
  float cx = move(0, dir+HALF_PI, scl*0.5, t), cy  = move(0, dir+HALF_PI, scl*0.5, f);
  line(nx1-cx, ny1-cy, nx2-cx, ny2-cy);
  line(nx1+cx, ny1+cy, nx2+cx, ny2+cy);
  noFill();
  arc(nx1, ny1, scl, scl, dir+HALF_PI, dir+3*HALF_PI);
  arc(nx2, ny2, scl, scl, dir-HALF_PI, dir+HALF_PI);
}
float move(float p, float dir, float dist, boolean x_) {
  if (x_) return p+cos(dir)*dist;
  else return p+sin(dir)*dist;
}
void displayBoard() {
  fill(#001540);
  rect(x-sideW, y, w*scl+2*sideW, h*scl+bottomBuffer, sideW, sideW, 0, 0);

  fill(#003366);
  rect(x, y, w*scl, h*scl);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    fill( clr[grid[i][j]+1]);
    circle((i+0.5)*scl+x, (j+0.5)*scl+y, scl*rm);
  }
  fill(#001540);
  rect(x, y, w*scl, scl*(1-rm)*0.25);

  fill(255, 20);
  rect(x+mx*scl, y, scl, scl*h);
  if(RESULT==0) coinX = constrain(lerp(coinX, x+(mx+0.5)*scl, 0.05), x+scl*0.5, x+(w-0.5)*scl);

  fill(clr[turn+1]);
  circle(coinX, coinY, scl*(0.5+rm*0.5));
}
void mousePressed() {
  if (RESULT==0) {
    int y = h-1;
    while (grid[mx][constrain(y, 0, h)]!=0 && y>=0) y--;
    if (y>=0) { 
      grid[mx][y] = turn;
      turn*=-1;
      RESULT = checkWin();
    }
  }
}

set inRow to >3, since everything less is not interesting. To resize the grid change w and h.

Nice and good working keep on that

1 Like

#53-2 Artistic Connect-n V2


Changes:

  • added win message
  • more than one win can be displayed (look at picture)
  • minor changes
Code
int w = 7, h = 6, inRow =4, turn = 1, mx=0, wUsed = 0; //wUsed - wins used
int grid[][] = new int[w][h];
float scl = 70, rm = 0.85; //rm - radius multiplier
color clr[] = {#FF001C, #75A2BF, #FFFF00}; //red-empty-yellow
int bottomBuffer=5, x=floor(700*0.5-w*scl*0.5), y=600-bottomBuffer-int(h*scl), sideW=25, RESULT = 0;
float coinX = y+scl*w/2, coinY = y - scl*0.6;
PVector w1[] = new PVector[4], w2[] = new PVector[4];
void setup() {
  size(700, 600);
  textAlign(3,3);
}
void draw() {
  mx = (int)constrain(map(mouseX, x, x+w*scl, 0, w), 0, w-1);
  noStroke();
  strokeWeight(1);
  noFill();
  background(0);
  displayBoard();
  if (RESULT!=0) for(int i = 0; i < wUsed; i++) displayWin((int)w1[i].x,(int)w1[i].y,(int)w2[i].x,(int)w2[i].y);
  if (RESULT==2) displayWin(100,100,100,100);
}
int checkWin() { //0-none, -1: yellow 1: red 2: out of space
  boolean outOfSpace=true; //checking for outofspace
  int output = 0;
  for (int i = 0; i < w && outOfSpace==true; i++)for (int j = 0; j < h && outOfSpace==true; j++) if (grid[i][j]==0) outOfSpace=false;
  if (outOfSpace) return 2;
  //check connecting
  for (int j = 0; j < h; j++) for (int i = 0; i < w; i++) if (grid[i][j] != 0) for (int k = 0; k < 4; k++) {
    //HOR, VER, RDIG, LDIG
    int cx = ((k==0 || k == 2)? 1 : ((k==1)? 0 : -1)), cy = ((k==0)? 0 : 1);
    int nx = i, ny = j, target = grid[i][j], row = 0;
    while (inBounds(nx, ny) && grid[nx][ny] == target) {
      row++;
      nx+=cx;
      ny+=cy;
    }
    if (row>=inRow) {
      w1[wUsed] = new PVector(i,j);
      w2[wUsed] = new PVector(nx-cx,ny-cy);
      wUsed++;
      output = target;
    }
  }

  return output;
}
boolean inBounds(int x, int y) {
  return(x>=0&&x<w&&y>=0&&y<h);
}
void displayWin(int x1, int y1, int x2, int y2) {
  stroke(0, 255, 0); 
  strokeWeight(3);
  boolean t = true, f = false;
  float nx1 = x+(x1+0.5)*scl, ny1 = y+(y1+0.5)*scl, nx2 = x+(x2+0.5)*scl, ny2 = y+(y2+0.5)*scl;
  float dir = atan2(y2-y1, x2-x1);
  float cx = move(0, dir+HALF_PI, scl*0.5, t), cy  = move(0, dir+HALF_PI, scl*0.5, f);
  line(nx1-cx, ny1-cy, nx2-cx, ny2-cy);
  line(nx1+cx, ny1+cy, nx2+cx, ny2+cy);
  noFill();
  arc(nx1, ny1, scl, scl, dir+HALF_PI, dir+3*HALF_PI);
  arc(nx2, ny2, scl, scl, dir-HALF_PI, dir+HALF_PI);
  textSize(scl);
  if(RESULT==-1||RESULT==1) {
    fill(clr[RESULT+1]);
    text( ((RESULT==1)? "YELLOW" : "RED") + " WINS!", x+w*scl*0.5, y-scl);
  }
  if(RESULT==2) {
    fill(0,200,0);
    text( "OUT OF SPACE", x+w*scl*0.5, y-scl);
  }
}
float move(float p, float dir, float dist, boolean x_) {
  if (x_) return p+cos(dir)*dist;
  else return p+sin(dir)*dist;
}
void displayBoard() {
  fill(#001540);
  rect(x-sideW, y, w*scl+2*sideW, h*scl+bottomBuffer, sideW, sideW, 0, 0);

  fill(#003366);
  rect(x, y, w*scl, h*scl);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    fill( clr[grid[i][j]+1]);
    circle((i+0.5)*scl+x, (j+0.5)*scl+y, scl*rm);
  }
  fill(#001540);
  rect(x, y, w*scl, scl*(1-rm)*0.25);

  fill(255, 20);
  rect(x+mx*scl, y, scl, scl*h);
  if(RESULT==0) coinX = constrain(lerp(coinX, x+(mx+0.5)*scl, 0.05), x+scl*0.5, x+(w-0.5)*scl);

  fill(clr[turn+1]);
  circle(coinX, coinY, scl*(0.5+rm*0.5));
}
void mousePressed() {
  if (RESULT==0) {
    int y = h-1;
    while (grid[mx][constrain(y, 0, h)]!=0 && y>=0) y--;
    if (y>=0) { 
      grid[mx][y] = turn;
      turn*=-1;
      RESULT = checkWin();
    }
  }
}

#54 2D simple collisions demo 1

This is a simple demo for a 2D collision detection with rectangles. The only square that can move is the player. If you find any bugs, do tell!

Code
int px = 10, py = 10, a = 20;
int cx = 0, cy = 0, speed = 1;
obstacle o = new obstacle(275, 275, 50, 50);
void setup() {
  size(600, 600);
}
void draw() {
  background(0);
  movePlayer();
  fill(255);
  square(px, py, a);
  o.display();
}
void movePlayer() {
  for (int i = 0; i < speed; i++) {
    int nx = px+cx, ny = py+cy;
    if(collision(nx,py,a,a, o.x,o.y,o.s,o.s2) == false) px = nx;
    if(collision(px,ny,a,a, o.x,o.y,o.s,o.s2) == false) py = ny;
  }
}
void keyPressed() {
  char ky = (key+"").toLowerCase().charAt(0);
  if (ky == 'a') cx = -1;
  if (ky == 'd') cx = 1;
  if (ky == 'w') cy = -1;
  if (ky == 's') cy = 1;
}
void keyReleased() {
  char ky = (key+"").toLowerCase().charAt(0);
  if (ky == 'a' && cx == -1) cx = 0;
  if (ky == 'd' && cx == 1) cx = 0;
  if (ky == 'w' && cy == -1) cy = 0;
  if (ky == 's' && cy == 1) cy = 0;
}
boolean collision(int x1, int y1, int s1, int s12, int x2, int y2, int s2, int s22) {
  if (x1>x2-s1&&y1>y2-s12&& x1<x2+s2 && y1<y2+s22) return true; //x2-s1, y2-s12, x2+s2, y2+s22
  return false;
}
class obstacle {
  int x, y, s, s2;
  obstacle(int x_, int y_, int s_, int s2_) {
    x = x_;
    y = y_;
    s = s_;
    s2 = s2_;
  }
  void display() {
    fill(0, 0, 255);
    rect(x, y, s, s2);
  }
}

#55 Simple posterization filter

Posterization filter sets the maximum amount of colors used. All colors on the screen get converted into those. explanation by josephh

Code
int clrs = 3; //end has clrs^3 colors, (1-1, 2-8, 3-27, 4-64, 5-125, 6-216,...)
color clr[];
PImage img;
void setup() {
  size(640,642);
  clr = generateColors(clrs);
  img = loadImage("house2.jpg");
  println(img.width,img.height);
}
void draw() {
  image(img,0,0); noLoop();
  loadPixels();
  for(int i = 0; i < width; i++) for(int j = 0; j < height*0.5; j++) {
    int in = i+j*width, off = floor(width*height*0.5);
    color base = pixels[in], chan = closest(base);
    pixels[in+off] = chan;
  }
  updatePixels();
}
color closest(color input) {
  int id=0;
  float d = -1;
  for(int i = 0; i < clr.length; i++) {
    float dis = dist(red(input),green(input),blue(input),red(clr[i]),green(clr[i]),blue(clr[i]));
    if(dis < d || d == -1) {
      id = i;
      d = dis;
    }
  }
  return clr[id];
}

color[] generateColors(int c) {
  float a = 255/c;
  color nclr[] = new color[c*c*c];
  for(int i = 0; i < c; i++) for(int j = 0; j < c; j++) for(int k = 0; k < c; k++) {
    nclr[i+j*c+k*c*c] = color(i*a, j*a, k*a);
  }
  return nclr;
}

It is a simple project (if you are using the simple color cube solution). It can be upgraded at any time by changing the generateColors() function.

#56 Color channels reduction


(random image I found on the web used as source)

Code
int clrs = 4; //end has clrs^3 colors, (1-1, 2-8, 3-27, 4-64, 5-125, 6-216,...)
PImage img;
void setup() {
  size(640,642);
  img = loadImage("house2.jpg");
}
void draw() {
  image(img,0,0); noLoop();
  loadPixels();
  for(int i = 0; i < width; i++) for(int j = 0; j < height*0.5; j++) {
    int in = i+j*width, off = floor(width*height*0.5);
    color base = pixels[in], chan = closest(base,clrs);
    pixels[in+off] = chan;
  }
  updatePixels();
}
color closest(color input, int colorChannels) {
  float r = round(map(red(input)  ,0,255,0,colorChannels));
  float g = round(map(green(input),0,255,0,colorChannels));
  float b = round(map(blue(input) ,0,255,0,colorChannels));
  float m = 255/colorChannels;
  return color(floor(r*m),floor(g*m),floor(b*m));
}

It is similar to #55, but it runs far faster. Instead of finding the closest color, it just maps the color to the closest one.

#57 Fractal animation

Code
int n = 3; //starting to show with a line; if line intercepts circle, it is shown
float r = 150, rm = 0.5, rot=0;
ArrayList<c> cs = new ArrayList<c>();
float lY = 0, lS = 1;
boolean lActive = false;
void setup() {
  size(600, 600);
  cs.add(new c(300, 300, r));
  for (int j = 0; j < 5; j++) for (int i = 0, m = cs.size(); i < m; i++) cs.get(i).dupe();
}
void draw() {
  background(0);
  rot = atan2(mouseX-300, mouseY-300);
  for (int i = 0; i < cs.size(); i++) cs.get(i).display();
  if(lActive) {
    lY+=lS;
    line(0,lY,width,lY);
    if(lY>height) lActive = false;
  }
}
void keyPressed() {
  if (key== ' ') {
    lActive = true;
    lY = 0;
  }
}

class c {
  float x, y, r;
  boolean canDupe = true;
  c(float x_, float y_, float r_) {
    x = x_; 
    y = y_; 
    r = r_;
  }
  void dupe() {
    if (canDupe) for (float i = 0, a = TWO_PI/n; i < n; i++) cs.add(new c(x+cos(a*i)*r, y+sin(a*i)*r, r*rm));
    canDupe = false;
  }
  void display() {
    stroke(255); 
    noFill();
    if (lActive == false || lY>y-r) circle(x, y, r*2);
  }
}

This is a slight modification to a previous project (can’t remember which one), but the main difference is that you can trigger an event, where a line will move down the screen. All of the circles that are ‘above’ the line (even if just the outline), it will display it.

1 Like

#58 Twin spinners (bad name : P)

Code
float x1=200, y1=200, rad=50, dir = 0, dr = 10;
float s = PI*0.03;
boolean o = false;
ArrayList<PVector> p1 = new ArrayList<PVector>(), p2 = new ArrayList<PVector>();
void setup() {
  size(600,600);
}
void draw() {
  background(0); stroke(255);
  //for(int i = 0; i < p1.size()-1; i++) line(p1.get(i).x,p1.get(i).y,p1.get(i+1).x,p1.get(i+1).y);
  for(int i = 0; i < p2.size()-1; i++) line(p2.get(i).x,p2.get(i).y,p2.get(i+1).x,p2.get(i+1).y);
  
  dir+=s*(o? 1:-1);
  float px = x1+cos(dir)*rad;
  float py = y1+sin(dir)*rad;
  line(x1,y1,px,py);
  noStroke();
  fill((o? color(255,0,0) : color(0,255,0)));
  circle(x1,y1,dr*2);
  fill((!o? color(255,0,0) : color(0,255,0)));
  circle(px, py,dr*2);
  //if(o||!o) p1.add(new PVector(x1,y1));
  //else 
  p2.add(new PVector(px,py));
}

void mousePressed() {
  o=!o;
  float px = x1+cos(dir)*rad;
  float py = y1+sin(dir)*rad;
  float d = atan2(y1-py,x1-px);
  x1 = px;
  y1 = py;
  dir = d;
}
1 Like

#59 Simple memory card game
Alternative names: Mix-n-match, Concentration, Memory, Matching cards,…

Code
int w = 4, h = 4, scl = 150, buffer=5;
card c[][] = new card[w][h];
int s1 = -1, s2 = -1, state = 0;
void setup() {
  size(600, 600);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    c[i][j] = new card(i, j, floor((i+j*w)/2));
  }
  shuffleBoard(1000);
}
void draw() {
  background(0);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    c[i][j].display( (s1==i+j*w || s2==i+j*w), (s1 == i+j*w? #00FF00 : (s2 == i+j*w? #0000FF : #FFFFFF)) );
  }
}
void mousePressed() {
  int p = -1;
  for (int i = 0; i < w && i >= 0; i++) for (int j = 0; j < h && i >= 0; j++) {
    if (c[i][j].pressed(mouseX, mouseY)) {
      p = i+j*w;
      i = -2;
    }
  }
  if (state == 0 && p>=0) {
    s1 = p;
    s2 = -1;
    state++;
  } else if (state == 1) {
    if (p != s1) {
      s2 = p;
      state++;
    }
  } else if (state == 2) {
    state = 0;
    if (c[s1%w][floor(s1/w)].value == c[s2%w][floor(s2/w)].value) {
      c[s1%w][floor(s1/w)].active = false;
      c[s2%w][floor(s2/w)].active = false;
    } else {
      s1 = -1;
      s2 = -1;
    }
  }
}
void shuffleBoard(int times) {
  int temp;
  for (int i = 0; i < times; i++) {
    int x1=(int)random(w), y1=(int)random(h), x2=(int)random(w), y2=(int)random(h);
    temp = c[x1][y1].value;
    c[x1][y1].value = c[x2][y2].value;
    c[x2][y2].value = temp;
  }
}
class card {
  int x, y, value;
  boolean active;
  card(int X, int Y, int Value) {
    x = X;
    y = Y;
    value = Value;
    active = true;
  }
  void display(boolean show, color cl) {
    if (active) {
      fill(cl);
      square(x*scl+buffer, y*scl+buffer, scl-buffer*2);
      if (show) {
        fill(0);
        text(value, (x+0.5)*scl, (y+0.5)*scl);
      }
    }
  }
  boolean pressed(int mx, int my) {
    return(active && mx>x*scl+buffer && my>y*scl+buffer&&mx<(x+1)*scl-buffer&&my<(y+1)*scl-buffer);
  }
}

VERSION 2

Summary
int w = 4, h = 4, scl = 150, buffer=5;
card c[][] = new card[w][h];
int s1 = -1, s2 = -1, state = 0;
void setup() {
  size(600, 600);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    c[i][j] = new card(i, j, floor((i+j*w)/2));
  }
  colorMode(HSB);
  textSize(scl*0.5);
  textAlign(3,3);
  shuffleBoard(1000);
}
void draw() {
  background(0);
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
    c[i][j].display( (s1==i+j*w || s2==i+j*w));
  }
}
void mousePressed() {
  int p = -1;
  for (int i = 0; i < w && i >= 0; i++) for (int j = 0; j < h && i >= 0; j++) {
    if (c[i][j].pressed(mouseX, mouseY)) {
      p = i+j*w;
      i = -2;
    }
  }
  if (state == 0 && p>=0) {
    s1 = p;
    s2 = -1;
    state++;
  } else if (state == 1) {
    if (p != s1 && p != -1) {
      s2 = p;
      state++;
    }
  } else if (state == 2) {
    state = 0;
    if (c[s1%w][floor(s1/w)].value == c[s2%w][floor(s2/w)].value) {
      c[s1%w][floor(s1/w)].active = false;
      c[s2%w][floor(s2/w)].active = false;
    } else {
      s1 = -1;
      s2 = -1;
    }
  }
}
void shuffleBoard(int times) {
  int temp;
  for (int i = 0; i < times; i++) {
    int x1=(int)random(w), y1=(int)random(h), x2=(int)random(w), y2=(int)random(h);
    temp = c[x1][y1].value;
    c[x1][y1].value = c[x2][y2].value;
    c[x2][y2].value = temp;
  }
}
class card {
  int x, y, value;
  boolean active;
  card(int X, int Y, int Value) {
    x = X;
    y = Y;
    value = Value;
    active = true;
  }
  void display(boolean show) {
    if (active) {
      fill((show? color(getColor(value,w*h*0.5),255,255) : #FFFFFF));
      square(x*scl+buffer, y*scl+buffer, scl-buffer*2);
      if (show) {
        fill(0);
        text(value, (x+0.5)*scl, (y+0.45)*scl);
      }
    }
  }
  boolean pressed(int mx, int my) {
    return(active && mx>x*scl+buffer && my>y*scl+buffer&&mx<(x+1)*scl-buffer&&my<(y+1)*scl-buffer);
  }
}
float getColor(int c, float max) {
  return map(c,0,max,0,255);
}
void keyPressed() { //RESET
  if (key == ' ') {
    c = new card[w][h];
    s1 = -1;
    s2 = -1;
    for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
      c[i][j] = new card(i, j, floor((i+j*w)/2));
    }
    shuffleBoard(1000);
  }
}

#60 Simple blur
Set the pixel value to the average of all pixels in a*2 by a*2 range. All pixels have the weight of 1.

Change blur by increasing / decreasing ‘a’ variable. Set to 1 to remove blur.

Code
PImage bg;
int a = 32, v = 0;
void settings() {
  bg = loadImage("bg.jpg"); 
  size(bg.width*2, bg.height);
  println(width, height);
}
void draw() {
  loadPixels();
  boolean cont = true;
  for (int i = 0; i < bg.width*5; i++) {
    v+=1;
    int x = v%bg.width, y = floor(v/bg.width);
    if(y>=bg.height-1 && x>=bg.width-2) {noLoop(); cont = false;} 
    if(cont) pixels[x+(y*2+1)*bg.width] = avg(bg, x-a, y-a, a*2, a*2);
  }
  updatePixels();
  if(frameCount<2) image(bg,0,0);
}
color avg(PImage img, int x, int y, float w, float h) {
  int r=0, g=0, b=0;
  float p=0;
  if (x < img.width && y < img.height && x > -w && y > -h) {
    img.loadPixels();
    for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) {
      int xp = x+i, yp = y+j;
      if (xp >= 0 && yp >= 0) {
        p++;
        color pxl = img.pixels[constrain(xp+yp*img.width, 0, bg.width*bg.height-1)];
        r+=red(pxl);
        g+=green(pxl);
        b+=blue(pxl);
      }
    }
  }
  float er = (float)r/p, eg = (float)g/p, eb = (float)b/p;
  return color(er, eg, eb);
}

Original image

#61 THE MANDELBROT SET!!!

It took me a lot of tries to complete. I didn’t want to watch the tutorials, since I wouldn’t understand the process. So after watching tons of youtube videos explaining the mandelbrot set, I had finally done it!

Thank you to Crystalize on discord, for showing me a neat way to create complex numbers in processing.
I made all the basic functions I needed with them and commented out the rest. So right now, there are:
addition, subtraction, multiplication ( C * C or C * R ), division ( C / C or C / R), squaring and z^2+c. If you want to use them, feel free!

Code
complex c = new complex(0, 0);
float scale = 150;
int iter = 1000;
float cx = 300, cy = 300;
color clr[] = new color[iter];
color bg = #FF0000;
void setup() {
  size(600, 600);
  colorMode(HSB);
  noStroke();

  float m = 0.95;
  float v = 1;

  for (int i = 0; i < iter; i++) { //can be replaced with: 255 * pow(m,i) and shorten to a single row
    clr[i] = color((v)*255, 255, 255);
    v*=m;
  }
  clr[iter-1] = #000000; //mandelbrot set is black in the center
}

void draw() {
  loadPixels();
  for (float i = 0; i < width; i ++) for (float j = 0; j < height; j++) {
    if (dist(i, j, width*0.5, height*0.5)<scale*2) {
      complex c = new complex( (i-300.0)/scale, (j-300.0)/scale); //og
      complex d = new complex( (i-300.0)/scale, (j-300.0)/scale); //changes

      int it;
      for (it = 0; it < iter-1 && inBounds(d) == true; it++) {
        complex nw = d.z2pc(d, c);
        d.setValueC( nw );
      }
      pixels[(int)i+(int)j*width] = clr[it];
    } else pixels[(int)i+(int)j*width] = bg;
  }
  updatePixels();
  //if(mousePressed) {
  //  println(((float)mouseX-300.0)/scale, ((float)mouseY-300.0)/scale);
  //}
  noLoop();
}

class complex {
  float re, im;
  complex(float re, float im) {
    this.re = re;
    this.im = im;
  }
  void setValue(float re, float im) {
    this.re = re;
    this.im = im;
  }
  void setValueC(complex c) {
    re = c.re;
    im = c.im;
  }
  complex add(complex z) {
    return new complex(re+z.re, im+z.im);
  }
  //complex sub(complex z) {
  //  return new complex(re-z.re, im-z.im);
  //}
  complex multC(complex z) {
    return new complex(re*z.re - im*z.im, re*z.im + z.re * im);
  }
  //complex multR(float z) {
  //  return new complex(re*z, im*z);
  //}
  complex devC(complex z) {
    return new complex( (re*z.re + im*z.im)/(z.re*z.re+z.im*z.im), (im * z.re - re * z.im)/(z.re*z.re+z.im*z.im) );
  }
  complex squ() {
    return multC(this);
  }
  complex z2pc(complex z, complex c) { //f(z) = z^2 + c
    return z.squ().add(c);
  }
}
void printComplex(complex ccc) {
  println("=" + ccc.re + " + " + ccc.im + "i");
}
boolean inBounds(complex c) {
  return(abs(c.re)<2&&abs(c.im)<2);
}

1 Like

The separate thread about the mandelbrot set I created. It has a few new features and as seen from the title, it has functioning zoom option.