Change fill color of cell when clicked in Processing - arrays

I've managed to print the co-ordinates of a cell when it's clicked.
Now I'm looking for help and advice to use the this data in order to change the cell colour to red - unless the cell selected is a base cell, I want those to remain as a constant. Here's the code I'm working with:
Tile[][] tileArray = new Tile[10][10];
int rows = 10;
int cols = 10;
int[] base = { 4,4, 4,5, 4,6, 4,7 };
void setup() {
size(500, 500);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
tileArray[i][j] = new Tile(i*50, j*50);
}
}
}
void draw() {
for (int i=0; i<base.length; i+=2) {
fill(0, 0, 255);
rect(base[i]*50, base[i+1]*50, 50, 50);
}
}
void mousePressed() {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
println (mouseX/50 +"," + mouseY/50);
}
}
}
class Tile {
Tile(int x, int y) {
fill(255);
stroke(0);
rect(x, y, 50, 50);
}
}
EDIT:
I've added the functionality which I am looking for, but I assume that I have not stored my base cell data correctly. As you can still click on the base cell and an active cell is drawing underneath. Here is the new code:
Tile[][] tiles;
int gridSize = 10;
int tileSize = 50;
void setup() {
size (450, 400);
generateGrid();
}
void draw() {
background (255);
display();
}
public void generateGrid() {
tiles = new Tile[gridSize][gridSize];
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
tiles[i][j] = new Tile((i*50), (j*50), tileSize, tileSize);
}
}
}
public void display() {
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
tiles[i][j].display();
}
}
}
void mousePressed() {
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridSize; j++) {
println (mouseX/50 +"," + mouseY/50);
}
}
int mx = mouseX/50;
int my = mouseY/50;
tiles[mx][my].active = !tiles[mx][my].active;
// tiles[mx][my].base = !tiles[mx][my].base;
println(tiles[mx][my].active);
}
class Tile {
int tx, ty, tw, th;
int[] baseCell = { 4, 2, 4, 3, 4, 4, 4, 5 };
color col_default = color(255);
color col_base = color(0, 0, 255);
color col_active = color(255, 100, 50);
boolean active = false;
boolean base = false;
Tile (int itx, int ity, int itw, int ith) {
tx = itx;
ty = ity;
tw = itw;
th = ith;
}
void display() {
stroke(0);
fill(col_default);
if ( active ) fill (col_active);
rect(tx, ty, tw, th);
for (int i=0; i<baseCell.length; i+=2) {
fill(col_base);
rect(baseCell[i]*50, baseCell[i+1]*50, 50, 50);
}
}
}

Your Tile class doesn't really make sense right now. It doesn't really make sense to draw to the screen from a constructor. Instead, move that logic into a draw() function inside the Tile class.
Your Tile class also has to keep track of its state: whether it's a base cell or not, or any other kind of cell it can be. You might do this with an enum, or an int, or a set of booleans. That part is completely up to you.
Then in your Tile.draw() function, you should check that state to decide what color to draw. From the sketch's draw() function, simply loop over each Tile and tell it to draw itself.
Finally, when you click, simply set the state of the Tile that you clicked on.

Related

Looping a mouse movement in Processing

I am trying to de-pixellate an image over time, which is working. However when this has finished, I want the mouse to go back to its original point and start again, forever. I have tried loop commands with no luck.
I can only get this code to work in version 2.2.1
import java.awt.Robot;
PImage img;
int pixls = 0;
int x, y, yinc;
int XOffset = 0;
int YOffset = 30;
int counter = YOffset;
Robot robot;
void setup() {
size(900, 900);
//noCursor();
noStroke();
img = loadImage("p.jpg");
img.resize(900, 900);
//surface.setLocation(XOffset, YOffset);
}
void draw() {
loadPixels();
frameRate(14);
pixls = (int)map(mouseY, height, 20, 250, 20); //pixellation
for (int i = 0; i < pixls; i++) {
for (int j = 0; j < pixls; j++) {
float r = red(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
float g = green(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
float b = blue(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
fill(r, g, b);
rect((width/pixls)*i, (height/pixls)*j, width/pixls, height/pixls);
yinc = (height/pixls)*j;
}
}
try {
robot = new Robot();
robot.mouseMove(XOffset*2, counter); //counter is start of mouse
if (counter > height + YOffset)
{
counter = YOffset + 30; // +30 for menubar
}
}
catch (Exception e) {
//println("error = ", e);
}
counter++;
}
The following should work in Processing 2.2.1. It uses an old method for finding the XOffset and YOffset of the app's window.
/*
Will work in Processing 2.2.1
*/
import java.awt.Robot;
Robot robot;
PImage img;
int pixls = 0;
int x, y, yinc;
int XOffset = 0;
int YOffset = 0;
int counter = 0;
void setup() {
size(710, 710);
// noCursor();
noStroke();
img = loadImage("myImage.jpg");
img.resize(710, 710);
}
void draw() {
int XOffset = frame.getLocationOnScreen().x;
int YOffset = frame.getLocationOnScreen().y;
pixls = (int)map(mouseY, 0, height, 5, 350);
for (int i = 0; i < pixls; i++) {
for (int j = 0; j < pixls; j++) {
float r = red(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
float g = green(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
float b = blue(img.pixels[(height/pixls)*j*width+(width/pixls)*i]);
fill(r, g, b);
rect((width/pixls)*i, (height/pixls)*j, width/pixls, height/pixls);
yinc = (height/pixls)*j;
}
}
try {
robot = new Robot();
robot.mouseMove(XOffset + 10, counter);
if (counter > height + YOffset + 30) {
counter = YOffset + 30; // + 30 for menubar
}
} catch (Exception e) {
println("error = ", e);
}
counter++;
}

Setting up a Timeline with a for loop in JavaFX

I'm trying to write an animated sort for a class I'm in. My goal is to have the sort displayed as vertical white bars that will be rendered on the canvas I've created.
I've attempted to accomplish this using a Timeline and Keyframes, but the output I get is a blank white canvas that after a few moments outputs the finished and sorted array.
I've resorted to just shuffling around code with no success, and can't find any helpful examples online. I'm hoping someone with some more experience with JavaFX animation can help me learn more about how to properly set this up!
Note that in the code below the array created with the random method is commented out because when used it makes the program hang for long time. The code will output in a reasonable time with a smaller array.
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class Project06 extends Application
{
final int SCALE = 16;
final int WIDTH = 64;
final int HEIGHT = 32;
int[][] pixels;
Timeline sortLoop;
int[] myArray = {32,28,22,20,16,13,10,9,5,3};
#Override
public void start(Stage primaryStage) throws Exception
{
pixels = new int[WIDTH][HEIGHT];
int[] myArray = new int[WIDTH];
/*
Random rand = new Random();
for (int i = 0; i < WIDTH; i++)
{
myArray[i] = rand.nextInt((HEIGHT) + 1);
}
*/
Canvas display = new Canvas (WIDTH*SCALE, HEIGHT*SCALE);
GraphicsContext gc = display.getGraphicsContext2D();
GridPane grid = new GridPane();
grid.add(display, 0, 0);
primaryStage.setTitle("Sort");
primaryStage.setScene(new Scene(grid, WIDTH*SCALE, HEIGHT*SCALE));
primaryStage.show();
sortLoop = new Timeline();
sortLoop.setCycleCount(Timeline.INDEFINITE);
// Sort array
for (int i = 0; i < myArray.length - 1; i++)
{
if (myArray[i] > myArray[i + 1])
{
int swap = myArray[i];
myArray[i] = myArray[i + 1];
myArray[i + 1] = swap;
i = -1;
}
// Clear screen by zeroing out pixel array
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
pixels[k][j] = 0;
}
}
// Draw array with vertical bars (assign values to canvas array)
for (int k = 0; k < myArray.length; k++)
{
for (int j = (HEIGHT - 1); j > ((HEIGHT - myArray[k]) - 1); j--)
{
pixels[k][j] = 1;
}
}
KeyFrame kf = new KeyFrame(Duration.seconds(1), actionEvent -> {
// Render canvas
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (pixels[k][j] == 1)
{
gc.setFill(Color.WHITE);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
else
{
gc.setFill(Color.BLACK);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
}
}
});
sortLoop.getKeyFrames().add(kf);
sortLoop.play();
}
}
public static void main(String[] args)
{
launch(args);
}
}
First, you are setting the timepoint for all your key frames to the same value (one second), so they all happen simultaneously. You need each key frame to have a different timepoint, so they happen sequentially.
Second, you sort the array, and then the event handlers for the keyframes reference the array. Since the event handlers for the keyframes are executed later, they only see the sorted array. You need to actually manipulate the array in the event handlers for the key frames.
Third, you play the timeline multiple times. You only need to play it once. Additionally, you set the cycle count to INDEFINITE: I think you only need to animate the sort once. (If you actually want it to repeat, you would need to set the array back to its original order at the beginning of the timeline.)
Finally, you have some issues in the implementation of the actual sort algorithm. This is why your application hangs when you randomly populate the array. I won't address those issues here, because the question is about how to perform the animation.
The following code performs a step-by-step animation. It's probably not the correctly-implemented sort, so you won't see the animation you necessarily expect, but it at least repaints the effect of the swaps in an animation:
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color;
public class AnimatedSort extends Application
{
final int SCALE = 16;
final int WIDTH = 64;
final int HEIGHT = 32;
int[][] pixels;
Timeline sortLoop;
int[] myArray = {32,28,22,20,16,13,10,9,5,3};
#Override
public void start(Stage primaryStage) throws Exception
{
pixels = new int[WIDTH][HEIGHT];
// int[] myArray = new int[WIDTH];
//
//
// Random rand = new Random();
// for (int i = 0; i < WIDTH; i++)
// {
// myArray[i] = rand.nextInt((HEIGHT) + 1);
// }
Canvas display = new Canvas (WIDTH*SCALE, HEIGHT*SCALE);
GraphicsContext gc = display.getGraphicsContext2D();
GridPane grid = new GridPane();
grid.add(display, 0, 0);
primaryStage.setTitle("Sort");
primaryStage.setScene(new Scene(grid, WIDTH*SCALE, HEIGHT*SCALE));
primaryStage.show();
sortLoop = new Timeline();
// sortLoop.setCycleCount(Timeline.INDEFINITE);
// Sort array
for (int index = 0; index < myArray.length - 1; index++)
{
final int i = index ;
KeyFrame kf = new KeyFrame(Duration.seconds(i+1), actionEvent -> {
if (myArray[i] > myArray[i + 1])
{
int swap = myArray[i];
myArray[i] = myArray[i + 1];
myArray[i + 1] = swap;
// i = -1;
}
// Clear screen by zeroing out pixel array
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
pixels[k][j] = 0;
}
}
// Draw array with vertical bars (assign values to canvas array)
for (int k = 0; k < myArray.length; k++)
{
for (int j = (HEIGHT - 1); j > ((HEIGHT - myArray[k]) - 1); j--)
{
pixels[k][j] = 1;
}
}
// Render canvas
for (int k = 0; k < WIDTH; k++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (pixels[k][j] == 1)
{
gc.setFill(Color.WHITE);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
else
{
gc.setFill(Color.BLACK);
gc.fillRect((k*SCALE), (j*SCALE), SCALE, SCALE);
}
}
}
});
sortLoop.getKeyFrames().add(kf);
}
sortLoop.play();
}
public static void main(String[] args)
{
launch(args);
}
}
The time property of KeyFrame denotes the time since the start of the animation, not the time since the previously added KeyFrame. You need to position. You need to pass different times to the KeyFrame constructor.
Furthermore you "sort" a fresh array instead of using the field. Also your pixels array contains the last value from the start.
Better save the swaps to a data structure and use a Timeline to render the changes step by step:
final int SCALE = 16;
final int WIDTH = 64;
final int HEIGHT = 32;
Timeline sortLoop;
int[] myArray = {32, 28, 22, 20, 16, 13, 10, 9, 5, 3};
private void renderBar(GraphicsContext gc, int barIndex, double canvasHeight, int barHeight) {
double rectHeight = barHeight * SCALE;
gc.fillRect(SCALE * barIndex, canvasHeight - rectHeight, SCALE, rectHeight);
}
#Override
public void start(Stage primaryStage) throws Exception {
int[] myArray = this.myArray.clone(); // copy field (you may also simply delete this declaration, if you never reuse the initial array)
class Swap {
final int lowerIndex, value1, value2;
public Swap(int lowerIndex, int value1, int value2) {
this.lowerIndex = lowerIndex;
this.value1 = value1;
this.value2 = value2;
}
}
final double canvasHeight = HEIGHT * SCALE;
Canvas display = new Canvas(WIDTH * SCALE, canvasHeight);
GraphicsContext gc = display.getGraphicsContext2D();
primaryStage.setTitle("Sort");
primaryStage.setScene(new Scene(new Group(display)));
primaryStage.show();
// render initial state
gc.setFill(Color.WHITE);
gc.fillRect(0, 0, display.getWidth(), canvasHeight);
gc.setFill(Color.BLACK);
for (int i = 0; i < myArray.length; i++) {
renderBar(gc, i, canvasHeight, myArray[i]);
}
// Sort array & save changes
List<Swap> swaps = new ArrayList<>();
for (int i = 0; i < myArray.length - 1; i++) {
if (myArray[i] > myArray[i + 1]) {
int swap = myArray[i];
myArray[i] = myArray[i + 1];
myArray[i + 1] = swap;
swaps.add(new Swap(i, myArray[i], swap));
i = -1;
} else {
// no change
swaps.add(null);
}
}
sortLoop = new Timeline();
sortLoop.setCycleCount(swaps.size());
final Iterator<Swap> iter = swaps.iterator();
sortLoop.getKeyFrames().add(new KeyFrame(Duration.seconds(1), evt -> {
Swap swap = iter.next();
if (swap != null) {
// clear old area
gc.setFill(Color.WHITE);
gc.fillRect(SCALE * swap.lowerIndex, 0, SCALE * 2, canvasHeight);
// draw new bars
gc.setFill(Color.BLACK);
renderBar(gc, swap.lowerIndex, canvasHeight, swap.value1);
renderBar(gc, swap.lowerIndex+1, canvasHeight, swap.value2);
}
}));
sortLoop.play();
}

Wpf How to fill a grid with label?

I need your help for filling my grid with a label in WPF.
Imagine a grid 3x3.
My code is like that :
MainWindow.xaml.cs
private void CreationDeLaCarte()
{
Label CaseForet = new Label();
CaseForet.Background = Brushes.Black;
Grille.Children.Add(CaseForet);
}
private void CreerLesCases()
{
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 10; j++)
{
CreationDeLaCarte();
}
}
}
The result : Just one cell in the grid is blacked. And not the all grid that i wanted. How can i improve this ?
Thank you for your replies ! :)
You should set Grid.Row and Grid.Column properties in your loop:
private void CreationDeLaCarte(int i, int j)
{
Label CaseForet = new Label();
CaseForet.Background = Brushes.Black;
Grille.Children.Add(CaseForet);
Grid.SetRow(CaseForet, i);
Grid.SetColumn(CaseForet, j);
}
and your loop should look like:
for (int i = 0; i < 8; i++)
{
for(int j = 0; j <10; j++)
{
CreationDeLaCarte(i,j);
}
}
Make sure the maximum number of columns and rows are consistent with your Grid.
I succeeded.
I have to put some parameters like :
private void CreationDeLaCarte(**int i, int j**)
{Label CaseForet = new Label();
CaseForet.Background = Brushes.Black;
Grille.Children.Add(CaseForet);
**Grid.SetColumn(CaseForet, i);
Grid.SetRow(CaseForet, j);**

How do I make my object disappear when it hits my character in my game? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm trying to make a game where my character (Homer Simpson) has to collect falling objects (donuts) and avoid falling toxic-tanks. Right now my score increments every time he gets a donut, but I wish to make the donut disappear afterwards. Can anyone help me with that?
This is my code so far:
PImage bg2; //background image
PImage homer; //image of homer
homer homer1;
int numberOfToxic = 3; //number of falling toxic tanks
int numberOfDonut = 3; //number of falling donuts
int score; //the score
Toxic[] toxic; //array for the toxic that will fall
PImage t;
Donut[] donut; //array for the donuts that will fall
PImage d;
void setup() {
size(600,500); //size of the window
bg2 = loadImage("bg2.jpg"); //uploading the background image
homer = loadImage("homer.gif"); //uploading the character image
t = loadImage("toxictank.png");
d = loadImage("donut.png");
PFont louiseFont;
louiseFont = loadFont("chalk.vlw"); //loading the font I've chosen
textFont(louiseFont); //the current font being used in the game
toxic = new Toxic[numberOfToxic];
for (int i = 0; i < numberOfToxic; i++) {
toxic[i] = new Toxic();
}
donut = new Donut[numberOfDonut];
for(int i = 0; i < numberOfDonut; i++) {
donut[i] = new Donut();
}
score = 0; //the score starts at 0
}
void draw() {
background(bg2);
homer1 = new homer(mouseX-70, 350, 140, 150, homer); //mouseX makes the hero move on the x axis and 350 defines where it is on the y axis. -70 center the mouse on the image/hero
homer1.drawHomer(); //call the function homer(hero)
//Making the taxictanks fall
for(int i = 0; i < toxic.length; i++) {
toxic[i].update();
toxic[i].drawToxic();
if(toxic[i].position.y > 500) {
toxic[i].reset();
}
}
//Making the donuts fall
for(int i = 0; i < donut.length; i++) {
donut[i].update2();
donut[i].drawDonut();
if(donut[i].position2.y > 500) {
donut[i].reset2();
}
//Collecting points if Homer eats donuts
if(abs(donut[i].position2.y - homer1.y) <= 2 && abs(donut[i].position2.x-40 - homer1.x)<=40) {
score ++;
println("ok");
}
}
fill(#0D128B); //color of text
textSize(20); //size of text
text("SCORE: " + nf(score, 1), 20, 40); //score points - tells how to use the text in the game
}
//class with height, width x, y positions and the hero image
class homer {
int x;
int y;
int hWidth;
int hHeight;
PImage homer;
homer(int x, int y, int hWidth, int hHeight, PImage homer) {
this.x = x;
this.y = y;
this.hWidth = hWidth;
this.hHeight = hHeight;
this.homer = homer;
}
void drawHomer() {
image(this.homer, this.x, this.y, this.hWidth, this.hHeight);
}
}
class Toxic { //all the variables for toxic
PImage t;
PVector position;
float speed;
float size;
//constructor of toxic
Toxic() {
t = loadImage("toxictank.png");
position = new PVector(random(width), random(height));
speed = 4;
size = 20;
}
void update() {
position.y += speed;
}
void drawToxic() {
for(int i = 1; i < 3; i++) {
image(t, position.x, position.y);
}
}
void reset() {
position.x = random(width);
position.y = 0 - 50;
speed = 4;
size = 20;
}
}
class Donut { //all variables for donut
PImage d;
PVector position2;
float speed2;
float size2;
boolean falling;
int timeToDisplay;
int fallingSpeed;
Donut() { //constructor of donut
d = loadImage("donut.png");
position2 = new PVector(random(width), random(height));
speed2 = 4;
size2 = 40;
falling = false;
timeToDisplay = (int)random(2.60);
fallingSpeed = (int)random(2.5);
}
void update2() {
position2.y += speed2;
}
void drawDonut() {
for(int i = 1; i < 3; i++) {
image(d, position2.x, position2.y);
}
}
void reset2() {
position2.x = random(width);
position2.y = 0 - 50;
speed2 = 4;
size2 = 20;
}
}
Just set the variables in the instance of Donut so that it goes back to the top of the screen, or isn't drawn at all. You already have a reset2() function that does that. Something like this:
if(abs(donut[i].position2.y - homer1.y) <= 2 && abs(donut[i].position2.x-40 - homer1.x)<=40) {
score ++;
donut[i].reset2();
println("ok");
}

flipped 2D array not filling properly

My 2D array will not fill properly I want the original array to stay unmodified, which it does, but then the next array to be flipped. For example 111, 222, 333 should be 333, 222, 111. If anyone could help it would be appreciated.
import java.util.Scanner;
public class Main
{
public static void main(String args[])
{
int rows = 0, cols = 0;
System.out.println("Please enter the size or your rows first and then columns:");
Scanner input = new Scanner (System.in);
rows = input.nextInt();
cols = input.nextInt();
int [][] my2DArray = new int [rows][cols];
System.out.print("Now fill the array with the numbers you would like: ");
for(int i = 0; i < my2DArray.length; i++)
{
for(int j = 0; j < my2DArray[i].length; j++)
{
my2DArray[i][j] = input.nextInt();
}
System.out.println("");
}
System.out.println("Here is the origional unmodified array.");
for(int i = 0; i < my2DArray.length; i++)
{
for(int j = 0; j < my2DArray[i].length; j++)
{
System.out.print(my2DArray[i][j] + " ");
}
System.out.println("");
}
flipMy2DArray(my2DArray);
}
public static int[][] flipMy2DArray(int[][] inMy2DArray)
{
int [][] flipMy2DArray = new int [inMy2DArray.length][inMy2DArray.length];
for(int row = flipMy2DArray.length-1; row > 0; row--)
{
for(int cols = 0; cols < flipMy2DArray[row].length; cols++)
{
flipMy2DArray[row][cols] = inMy2DArray[row][cols];
}
System.out.println("");
}
for(int row = 0; row < flipMy2DArray.length; row ++)
{
for(int cols = 0; cols < flipMy2DArray[row].length; cols++)
{
System.out.print(flipMy2DArray[row][cols]+ " ");
}
System.out.println("");
}
return flipMy2DArray;
}
}

Resources