Randomize image when mouse pressed - Processing - processing

I'm trying to make a grid where each individual cell contains one random image from my data folder.
So far, I've accomplished having a different image in every cell, but it doesn't randomize
instead of randomly picking one from the 600+ from the folder, it places every image in order 1 to 27.
Apart from that, I want it to randomize every time I click with the mouse instead of just randomizing when its closed and played again. The code:
PImage img[];
int nPics;
int w;
int h;
int rand;
void setup(){
size(1500,500);
nPics=27;
img = new PImage[nPics];
w=width/9;
h=height/3;
for (int i = 0; i <nPics; i++) {
img[i] = loadImage("img_" +nf(i,3)+ ".jpg");
imageMode(CORNERS);
}
//rand = int(random(0,687));
//img[0]=loadImage("img_" + nf(rand,3)+ ".jpg");
}
void draw(){
background(0);
for(int i=0;i<nPics;i=i+3){
int col = i/3;
for(int row=0;row<3;row++)
image(img[i+row],col*w,row*h,(col+1)*w,(row+1)*h);
}
}

When you are loading your images you are using i instead of rand. In order to randomize the images when you click the mouse, you can use the mousePressed() to reload different images into your array.
This should work:
PImage img[];
int nPics;
int w, h;
void loadImages(){
for (int i = 0; i < nPics; i++) {
img[i] = loadImage("img_"+ nf(int(random(0, 687)), 3) + ".jpg");
imageMode(CORNERS);
}
}
void setup() {
size(1500, 500);
nPics=27;
img = new PImage[nPics];
w=width/9;
h=height/3;
loadImages();
}
void mousePressed(){
loadImages();
}
void draw() {
background(0);
for (int i=0; i<nPics; i=i+3) {
int col = i/3;
for (int row=0; row<3; row++)
image(img[i+row], col*w, row*h, (col+1)*w, (row+1)*h);
}
}

Related

Processing String splitting and loops to form a facade

I have tried many methods, and can't seem to grasp the idea of extracting an index from my array of strings to help me generate my desired number of building with a desired height, please help, here is my example
edit: Hi, i saw your feedback and posted my code below, hopefully it helps with the idea overall, as much as it is just creating rects, its more complicated as i need to involve arrays and string splitting along with loops. i more or less got that covered but i as i said above, i cannot extract the values from my array of string and create my facades at my own desired number and height
String buffer = " ";
String bh = "9,4,6,8,12,2";
int[] b = int(split(bh, ","));
int buildingheight = b.length;
void setup () {
size(1200, 800);
background(0);
}
void draw () {
}
void Textbox() {
textSize(30);
text(buffer, 5, height-10);
}
void keyTyped() {
if (key == BACKSPACE) {
if (buffer.length() > 0) {
buffer = buffer.substring(0, buffer.length() - 1);
}
} else if (key == ENTER) {
background(0);
stroke(0);
GenerateFacade();
println(buffer);
}
else {
buffer = buffer + key;
Textbox();
}
}
void GenerateFacade() {
fill(128);
for (int i = 0; i < b.length; i++) {
for (int j = 0; j < b.length; j++) {
if (int(b[j]) > buildingheight) {
buildingheight = int(b[j]);
}
}
rect(i*width/b.length, height - (int(b[i])*height/buildingheight), width/b.length, int(b[i])*height/buildingheight);
}
}
For the next time it would be great if you provide us with some code so we know what you tried and maybe can point you to the problem you have.
You need just the keyPressed function and some variables
int x = 0;
int buildingWidth = 50;
int buildingHeight = height / 6;
void setup(){
size(1000, 500);
background(255);
}
void draw(){
}
void keyPressed(){
if(key >= '0' && key <= '9'){
int numberPressed = key - '0' ;
fill(0);
rect(x, height - buildingHeight * numberPressed,
buildingWidth, buildingHeight * numberPressed);
x += buildingWidth;
}
}
This is my result

How to swap images in a tile on a grid board upon user click?

I'm making a game that flips a tile in a grid board to flip between images and the user wins when all the tiles become the same image. My current issue is in mousepressed() with the if statement that swaps the tiles around based on what tile the user clicked. I get an error complaining about incompatible types and I am not sure how to work around this error. I will add the images I used for the tiles.
final int NUM_TILES = 4;
PImage image1, image2;
PImage [][] imageShown;
PImage [][] board;
int sqSide;
float randValue = random(1,2);
void setup(){
size(500, 500);
sqSide = width/NUM_TILES;
imageShown = new PImage[NUM_TILES][NUM_TILES];
board = new PImage[NUM_TILES][NUM_TILES];
image1 = loadImage("helloseal.jpg");
image2 = loadImage("very-rotund.jpg");
displayPuzzle();
}
void draw(){
}
void displayPuzzle(){
for(int i=0; i<NUM_TILES; i++){
for(int j=0; j<NUM_TILES; j++){
image(board[i][j], j*sqSide, i*sqSide);
}
}
}
int clickedRow, clickedCol;
void mousePressed(){
clickedRow = int(mouseY/sqSide);
clickedCol = int(mouseX/sqSide);
if(board[clickedRow][clickedCol] == 1){
board[clickedRow][clickedCol] = 2;
image(image2, clickedCol*sqSide, clickedRow*sqSide);
}else if(board[clickedRow][clickedCol] == 2){
board[clickedRow][clickedCol] = 1;
}
if (checkGameOver() == true){
System.exit(0);
}
}
boolean checkGameOver(){
for(int row=0; row<NUM_TILES; row++){
for(int col=0; col<NUM_TILES; col++){
int randValue = int(random(1,2));
if( randValue == 1){
imageShown[row][col] = 1;
return false;
}
}
return true;
}
}
Looks like you're trying to compare a PImage to an integer, replacing the 1 and 2 with "image1" and "image2" should fix it.

Fixing a nullpointer exception when using image(); in processing

I am trying to draw a board using 2 images for a game but I receive a null pointer exception when I call the function that creates it.
final int NUM_TILES = 4;
PImage image1, image2;
PImage [][] imageShown;
PImage [][] board;
int sqSide;
float randValue = random(1,2);
void setup(){
size(500, 500);
sqSide = width/NUM_TILES;
imageShown = new PImage[NUM_TILES][NUM_TILES];
board = new PImage[NUM_TILES][NUM_TILES];
image1 = loadImage("helloseal.jpg");
image2 = loadImage("very-rotund.jpg");
displayPuzzle();
}
void draw(){
}
void displayPuzzle(){
for(int i=0; i<NUM_TILES; i++){
for(int j=0; j<NUM_TILES; j++){
image(board[i][j], j*sqSide, i*sqSide);
}
}
}
You have to initialize the elements board. In the beginning all the elements are null. Assign an image to each element in a nested loop. For instance:
void setup(){
size(500, 500);
sqSide = width/NUM_TILES;
imageShown = new PImage[NUM_TILES][NUM_TILES];
board = new PImage[NUM_TILES][NUM_TILES];
image1 = loadImage("helloseal.jpg");
image2 = loadImage("very-rotund.jpg");
for(int i=0; i<NUM_TILES; i++){
for(int j=0; j<NUM_TILES; j++){
board[i][j] = image;
}
}
}
displayPuzzle has to be called in draw rather than in setup:
void draw(){
displayPuzzle();
}

Processing: How to fix timer display and how to display time score at end of game?

I am working on an ascending order puzzle that records the time it takes the user to complete the puzzle and once the puzzle is completed it takes the user to a game over screen that shows the user their time. My issue is that the time that is being displayed is overlapping and not updating as it should be. I am also unsure how to save the time that the user took to complete the puzzle.
final int NUM_SQUARES = 4;
int[][] board = new int[NUM_SQUARES][NUM_SQUARES];
int sqSide;
Timer startTimer;
void setup(){
size(500, 500);
setupGame();
sqSide = width/NUM_SQUARES;
}
void setupGame(){
sqSide = width/NUM_SQUARES;
startTimer = new Timer(0);
//populate the board
//generate random number
//check if we have it already inside the array
//if we have, then go on to generate another random number
//if we do not have it, then we can store inside array
for(int row=0; row<NUM_SQUARES; row++){
for(int col=0; col<NUM_SQUARES; col++){
int randVal;
do{
randVal = int(random(1, NUM_SQUARES*NUM_SQUARES+1) );
}while( searchFor(randVal) );
board[row][col] = randVal;
}
}
//visual representation of the board
for(int row=0; row<NUM_SQUARES; row++){
for(int col=0; col<NUM_SQUARES; col++){
fill(random(0,255), random(0,255), random(0,255));
rect(col*sqSide, row*sqSide, sqSide, sqSide);
fill(0);
textSize(30);
text(board[row][col], (col+0.5)*sqSide, (row+0.5)*sqSide);
}
}
}
class Timer{
float Time;
Timer(float set){
Time = set;
}
float getTime(){
return(Time);
}
void setTime(float set){
Time = set;
}
void countUP(){
Time += 1/frameRate;
}
}
boolean searchFor(int itemToBeSearched){
for(int i=0; i<NUM_SQUARES; i++){
for(int j=0; j<NUM_SQUARES; j++){
if(itemToBeSearched == board[i][j]){
return true;
}
}
}
return false;
}
void draw(){
startTimer.countUP();
fill(0);
text(startTimer.getTime(), 20,20);
}
int clickedRow, clickedCol, releasedRow, releasedCol;
void mousePressed(){
clickedRow = int(mouseY/sqSide);
clickedCol = int(mouseX/sqSide);
}
void mouseReleased(){
releasedRow = int(mouseY/sqSide);
releasedCol = int(mouseX/sqSide);
//swap
int buffer = board[clickedRow][clickedCol];
board[clickedRow][clickedCol] = board[releasedRow][releasedCol];
board[releasedRow][releasedCol] = buffer;
//visual representation - finish up
//show what is inside board[clickedRow][clikedCol]
//then show what is inside board[releasedRow][releasedCol]
//where the child pressed
fill(random(0,255), random(0,255), random(0,255));
rect(clickedCol*sqSide, clickedRow*sqSide, sqSide, sqSide);
fill(0);
text(board[clickedRow][clickedCol],(clickedCol+0.5)*sqSide, (clickedRow+0.5)*sqSide) ;
//where the child released
fill(random(0,255), random(0,255), random(0,255));
rect(releasedCol*sqSide, releasedRow*sqSide, sqSide, sqSide);
fill(0);
text(board[releasedRow][releasedCol],(releasedCol+0.5)*sqSide, (releasedRow+0.5)*sqSide);
if(gameOver()==true){ //calling function gameOver
background(255);
String s = "Congratulations!";
String d = "Click to start again!";
fill(0);
text(s, 125, 225);
text(d, 125, 250);
if(mousePressed == true){
setupGame();
}
}
}
//definition of gameOver
boolean gameOver(){
int counter=1;
for(int row=0; row<NUM_SQUARES; row++){
for(int col=0; col<NUM_SQUARES; col++){
if(board[row][col] !=counter){
return false;
}
counter++;
}
}
return true;
}
There's plenty of good work there, especially when it comes to managing the board / swapping elements / etc. It takes focus to keep it in check.
It also looks like there's a bit of confusion regarding drawing.
You can draw elements once and in draw(); render overlapping elements on top as you are doing now, however you need to pay attention to what needs to be rendered once or multiple times.
The timer text is leaving trails because the background is never cleared, but the board is only drawn once. You will want to redraw the background/board to fix the text, but some bits of code will need to move or need to be handled differently.
For example:
fill(random(0,255), random(0,255), random(0,255));
If you call that in draw() the colours will change continuously you don't want.
You could however generate the colours once in setup() then re-use them in draw() without resetting the values.
There seems to be also some confusion with mouse events and when or in which state should resets happen.
Here's a re-organised version of your code taking into account the notes above:
final int NUM_SQUARES = 4;
int[][] board = new int[NUM_SQUARES][NUM_SQUARES];
// also remember the colours set once in setup() to re-use in draw()
int[][] boardColors = new int[NUM_SQUARES][NUM_SQUARES];
int sqSide;
Timer startTimer;
int clickedRow, clickedCol, releasedRow, releasedCol;
// this will store the result of gameOver() once so it can be re-used
boolean isGameOver;
void setup(){
size(500, 500);
setupGame();
}
void setupGame(){
sqSide = width/NUM_SQUARES;
startTimer = new Timer(0);
clearBoard();
//populate the board
//generate random number
//check if we have it already inside the array
//if we have, then go on to generate another random number
//if we do not have it, then we can store inside array
shuffleBoard();
}
void clearBoard(){
for(int row = 0; row < NUM_SQUARES; row++){
for(int col = 0; col < NUM_SQUARES; col++){
board[row][col] = 0;
}
}
}
void shuffleBoard(){
for(int row = 0; row < NUM_SQUARES; row++){
for(int col = 0; col < NUM_SQUARES; col++){
int randVal;
do{
randVal = int(random(1, NUM_SQUARES*NUM_SQUARES+1) );
}while( searchFor(randVal) );
board[row][col] = randVal;
boardColors[row][col] = color(random(0,255), random(0,255), random(0,255));
}
}
}
void drawBoard(){
//visual representation of the board
for(int row = 0; row < NUM_SQUARES; row++){
for(int col = 0; col < NUM_SQUARES; col++){
fill(boardColors[row][col]);
rect(col * sqSide, row * sqSide, sqSide, sqSide);
fill(255);
textSize(30);
text(board[row][col], (col + 0.5) * sqSide, (row + 0.5) * sqSide);
}
}
}
boolean searchFor(int itemToBeSearched){
for(int i = 0; i < NUM_SQUARES; i++){
for(int j = 0; j < NUM_SQUARES; j++){
if(itemToBeSearched == board[i][j]){
return true;
}
}
}
return false;
}
void draw(){
background(255);
// draw based on state
if(gameOver()){
// render game over state
String s = "Congratulations!";
String d = "Click to start again!";
fill(0);
text(s, 125, 225);
text(d, 125, 250);
// reset game only if clicking in game over state
if(mousePressed == true){
setupGame();
}
}else{
// render game state
startTimer.countUp();
// re-render board
drawBoard();
// render text on top
fill(0);
text(startTimer.getTime(), 20, 30);
}
}
void mousePressed(){
clickedRow = int(mouseY/sqSide);
clickedCol = int(mouseX/sqSide);
}
void mouseReleased(){
releasedRow = int(mouseY/sqSide);
releasedCol = int(mouseX/sqSide);
//swap
int buffer = board[clickedRow][clickedCol];
board[clickedRow][clickedCol] = board[releasedRow][releasedCol];
board[releasedRow][releasedCol] = buffer;
}
//definition of gameOver
boolean gameOver(){
int counter=1;
for(int row=0; row<NUM_SQUARES; row++){
for(int col=0; col<NUM_SQUARES; col++){
if(board[row][col] !=counter){
return false;
}
counter++;
}
}
return true;
}
class Timer{
float time;
Timer(float set){
time = set;
}
float getTime(){
return(time);
}
void setTime(float set){
time = set;
}
void countUp(){
time += 1 / frameRate;
}
}
It might make it easier to organise a basic finite state machine(FSM).
It sounds more complicated than it is: the basic idea is to isolate functionality per state and tightly handle transitions between states which allow you to reset/update data accordingly. For example a game play state will only have to deal with gameplay related data until the state completes. Similarly the game over state only deals with it's data until it completes (when a user clicks). There are many ways you can write this.
Here's a suggestion organised around how a Processing sketch runs:
setup() is where things get set up once at the start
draw() is where things get updated/rendered
mouse / key / etc. events handle user input
You're already using a class (Timer) this will be very similar:
// the two states
StateDisplay playState;
StateDisplay gameOverState;
// a reference to the current state
StateDisplay currentState;
void setup(){
size(500, 500);
textAlign(CENTER);
// setup each state
playState = new PlayState();
gameOverState = new GameOverState();
// set the reference to the 1st state
currentState = playState;
}
// forward events to the current state: doesn't matter if it's play or game over, they're can all handle it
void draw(){
currentState.draw();
}
void mousePressed(){
currentState.mousePressed();
}
void mouseReleased(){
currentState.mouseReleased();
}
// global function to be called by each state as it exits
// this does the state switch: reset state data as required
void onStateExit(StateDisplay exitingState){
// game play state to game over state
if(exitingState == playState){
// cast each state to access specialised variables
// in this case store the last timer value to display on the game over screen
((GameOverState)gameOverState).timerValue = ((PlayState)playState).startTimer.getTimeFormatted();
// set the state
currentState = gameOverState;
}
// game over state to game play state
if(exitingState == gameOverState){
// reset game
playState.setup();
// set the state
currentState = playState;
}
}
class Timer{
float time;
Timer(float set){
time = set;
}
float getTime(){
return time;
}
String getTimeFormatted(){
return nfc(time, 2);
}
void setTime(float set){
time = set;
}
void countUp(){
time += 1 / frameRate;
}
}
// "parent" state class that all other states will extend
// and inherit functionality from
class StateDisplay{
StateDisplay(){
// as soon as the constructor is called, set up this state
this.setup();
}
void setup(){
// to be overriden by subclass
}
void draw(){
// to be overriden by subclass
}
void mousePressed(){
// to be overriden by subclass
}
void mouseReleased(){
// to be overriden by subclass
}
}
class PlayState extends StateDisplay{
final int NUM_SQUARES = 4;
int[][] board;
int[][] boardColors;
int sqSide;
Timer startTimer;
int clickedRow, clickedCol, releasedRow, releasedCol;
void setup(){
setupGame();
}
void setupGame(){
this.board = new int[NUM_SQUARES][NUM_SQUARES];
this.boardColors = new int[NUM_SQUARES][NUM_SQUARES];
sqSide = width/NUM_SQUARES;
startTimer = new Timer(0);
//populate the board
//generate random number
//check if we have it already inside the array
//if we have, then go on to generate another random number
//if we do not have it, then we can store inside array
for(int row = 0; row < NUM_SQUARES; row++){
for(int col = 0; col < NUM_SQUARES; col++){
int randVal;
do{
randVal = int(random(1, NUM_SQUARES*NUM_SQUARES+1) );
}while( searchFor(randVal) );
board[row][col] = randVal;
boardColors[row][col] = color(random(0,255), random(0,255), random(0,255));
}
}
}
boolean searchFor(int itemToBeSearched){
for(int i = 0; i < NUM_SQUARES; i++){
for(int j = 0; j < NUM_SQUARES; j++){
if(itemToBeSearched == board[i][j]){
return true;
}
}
}
return false;
}
//definition of gameOver
boolean gameOver(){
int counter=1;
for(int row=0; row<NUM_SQUARES; row++){
for(int col=0; col<NUM_SQUARES; col++){
if(board[row][col] !=counter){
return false;
}
counter++;
}
}
return true;
}
void drawBoard(){
//visual representation of the board
for(int row = 0; row < NUM_SQUARES; row++){
for(int col = 0; col < NUM_SQUARES; col++){
fill(boardColors[row][col]);
rect(col * sqSide, row*sqSide, sqSide, sqSide);
fill(255);
textSize(30);
text(board[row][col], (col+0.5) * sqSide, (row + 0.5) * sqSide);
}
}
}
void draw(){
// clear screen
background(255);
// redraw board
drawBoard();
// optional: drag and drop visual cue
if(mousePressed){
fill(255, 192);
text(board[clickedRow][clickedCol], mouseX, mouseY);
}
startTimer.countUp();
fill(255);
text(startTimer.getTimeFormatted()+"s", width * 0.5, 30);
}
void mousePressed(){
clickedRow = int(mouseY/sqSide);
clickedCol = int(mouseX/sqSide);
}
void mouseReleased(){
releasedRow = int(mouseY/sqSide);
releasedCol = int(mouseX/sqSide);
//swap
int buffer = board[clickedRow][clickedCol];
board[clickedRow][clickedCol] = board[releasedRow][releasedCol];
board[releasedRow][releasedCol] = buffer;
if(gameOver()){
onStateExit(this);
}
}
}
class GameOverState extends StateDisplay{
// time taken to solve
String timerValue = "";
void draw(){
String s = "Congratulations!\n" +
"Solved in " + timerValue + "s\n" +
"Click to start again!";
background(255);
fill(0);
text(s, width * 0.5, 225);
}
void mouseReleased(){
onStateExit(this);
}
}
The code may look verbose but essentially most of the work that's doing is grouping functionality per state: as if you're running mini-sketches and swapping between them.
The things that may be new are:
extending a class: the class that extends (subclass) will inherit properties/methods from the parent class (superclass)
polymorphism: relying on what subclasses have in common with the superclass to treat them as if they are the same (though internally the implementation for each is different). (e.g. all states have draw(), but each state renders something else)
casting: in this particular case allowing subclass to behave as itself (with all it's extra properties/methods), not just what's shared from the superclass. More specifically in the code above the timer data is passed from game play state to the game over state to display.
Even though it's a bit more work to set up this way it may be worth doing to keep states isolated and easily add more states using the same logic (e.g. a high scores stable, a start / game menu screen / etc.). With each state as a min-sketch you can also keep it organised with tabs, saving time having scroll up and down all the time:

How can I create points, display them and store them in some sort of Array

I want to create points and then store them in an array. I'm doing this to put a linear regression through my data points afterwards. So I need to be able to cycle through all my points.
I could not find anything like that on the web for processing and as I was not really able to do it, I need your help. Here is my approach, but it doesn't seem to work:
ArrayList<dataPoint> dataPoints = new ArrayList<dataPoint>();
void setup(){
size(1000, 1000);
background(255);
}
void draw(){
for (int i = 1; i == dataPoints.size(); i++) {
// An ArrayList doesn't know what it is storing so we have to cast the object coming out
dataPoint Point = dataPoints.get(i);
Point.display();
}
}
void mousePressed() {
dataPoints.add(new dataPoint(mouseX, mouseY));
}
class dataPoint {
float x;
float y;
dataPoint(int tempX, int tempY) {
x = tempX;
y = tempY;
}
void display() {
strokeWeight(10);
stroke(255,0,0);
point(x,y);
}
}
I would like to have a program to create points and store them in an array (or something similar, that you can cycle through).
Most of your code makes sense, there are only two gotchas I could spot that may prevent you from cycling through all your points and visualising them:
your condition is will go to an array index out of bounds: try for (int i = 0; i < dataPoints.size(); i++)
remember to clear the frame, otherwise you're drawing on top of the same dots over and over again
Remember array indices start at 0 in Processing/Java (and likewise the last index will not be the size() of your array, but the 1 less, hence the < in the for condition)
Here is your code with the above tweaks:
ArrayList<dataPoint> dataPoints = new ArrayList<dataPoint>();
void setup(){
size(1000, 1000);
}
void draw(){
background(255);
for (int i = 0; i < dataPoints.size(); i++) {
// An ArrayList doesn't know what it is storing so we have to cast the object coming out
dataPoint Point = dataPoints.get(i);
Point.display();
}
}
void mousePressed() {
dataPoints.add(new dataPoint(mouseX, mouseY));
}
class dataPoint {
float x;
float y;
dataPoint(int tempX, int tempY) {
x = tempX;
y = tempY;
}
void display() {
strokeWeight(10);
stroke(255,0,0);
point(x,y);
}
}
Note that Processing has a handy PVector class (which has x,y properties) so you could do something like this:
ArrayList<PVector> dataPoints = new ArrayList<PVector>();
void setup(){
size(1000, 1000);
strokeWeight(10);
stroke(255,0,0);
noFill();
}
void draw(){
background(255);
beginShape();
for (int i = 0; i < dataPoints.size(); i++) {
PVector point = dataPoints.get(i);
vertex(point.x,point.y);
}
endShape();
}
void mousePressed() {
dataPoints.add(new PVector(mouseX, mouseY));
}
This a bit of a detail, but I recommend to following Java Naming Convention to keep the code consistent. (For example: renaming the dataPoint class to DataPoint and renaming the Point instance to point)

Resources