I'm following a course in programming in the Java-based environment "Processing". One assignment is to write a program that displays 3 buttons (black). When the button is clicked, that button should change to another colour (grey). We are required to use a boolean[] array. My code is as follows:
boolean[] button = new boolean[3];
void setup(){
size(300,300);
button[0] = false;
button[1] = false;
button[2] = false;
}
void draw(){
int x = (width/(button.length+1));
int y = height/2;
int ellipseSize = 50;
int radius = ellipseSize/2;
background(255);
noStroke();
fill(0);
for(int i = 1; i <= button.length; i++){
ellipse(i*x, y, ellipseSize, ellipseSize);
}
}
//shifting array values upon mouse pressing
void mousePressed(){
int x = (width/(button.length+1));
int y = height/2;
int ellipseSize = 50;
int radius = ellipseSize/2;
for(int i = 1; i <= button.length; i++){
button[i] = !button[i];
if (mouseX > i*x-radius && mouseX < i*x+radius && mouseY > y-radius && mouseY < y+radius){
if (button[i]){
fill(150);
}
}
else {
fill(0);
}
ellipse(i*x, y, ellipseSize, ellipseSize);
}
}
I get an error saying "ArrayIndexOutOfBoundsException: 3". Can someone help?
You get the error ArrayIndexOutOfBoundsException: 3 because you have tried to access to an illegal index. In Java and in most programming languages arrays start at 0.
So, in your for loop you need to change i <= button.length to i < button.length
As few people mentioned arrays in most programming languages start at index 0 and last index is at button.length - 1 so you need to change for loop or button[i] call.
But to finish your buttons you will need to understand more about processing. Your draw function is called repeatedly (depending on you fps) and you always clear the sketch with background function. Then you set fill color to black and draw three circles. If you change fill inside mouse event it might sometimes work (if you click at the same moment as circle is drawn) but it is very bad approach.
You will need to set fill according to your button array within draw function:
for(int i = 1; i <= button.length; i++){ //good boundaries for drawing but not for array
if(button[i-1]) { //for array you need correct index
fill(0);
}else{
fill(150);
}
ellipse(i*x, y, ellipseSize, ellipseSize);
}
And of course change the mouse event to just check if button was clicked and store this information inside button array for next drwing.
for(int i = 1; i <= button.length; i++){ //your old boundaries
if (mouseX > i*x-radius && mouseX < i*x+radius && mouseY > y-radius && mouseY < y+radius){
button[i-1] = !button[i-1]; //updated index
}
}
Change
i <= button.length
to
i < button.length
If the length of the array is 3 then button[2] is the last element.
Related
I am working on a school project in Processing (Java Mode). We have a picture of how the game should look like.
So the task is to create a grid out of squares. Random squares should light up in red. If a red square is clicked, it should change colors to green and stay green.
What my code looks like at the moment:
Square[][] grid;
int cols = 20;
int rows = 20;
void setup() {
size(400, 400);
grid = new Square[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j] = new Square(i*20, j*20, 20, 20);
}
}
}
void draw() {
background(0);
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j].display();
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
color col = color(0,204,0);
grid[i][j].update(col);
}
}
}
}
Class for squares:
class Square {
float x, y;
float w, h;
color c;
Square(float tempX, float tempY, float tempW, float tempH) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
c = color(0);
}
void display() {
stroke(0);
fill(c);
rect(x, y, w, h);
}
void update(color c) {
this.c = c;
}
}
So at the moment, every square you click turns green. I am not sure how to write the code, so that random squares change color to red and shuffle every 5 seconds.
Do you have any tips on how to proceed with the code or which thinking steps to take to be able to solve this task?
First, take your task:
So the task is to create a grid out of squares. Random squares should light up in red. If a red square is clicked, it should change colors to green and stay green.
and break it down:
create a grid out of squares: nicely done already !
Random squares should light up in red
If a red square is clicked
change colors to green and stay green
How do you use random numbers in Processing ?
The simplest method is using the random() method: you can pass two values and you'll get back a random number between those values.
Let's say you want to flip a coin so there's a (roughly) 50-50 change you get heads or tails. You could so something like:
if(random(0, 100) > 50){
println("head");
}else{
println("tails");
}
Could even be random(0.0, 1.0) > 0.5 for example, the idea is the same.
You could think of throwing a dice or a number of dices, etc.
Remember these are pseudo-random and in your own time can explore other pseudo random related methods such as randomGauss() and noise().
random() may be good enough for now, part 2 done :)
You're almost done with part 3:
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
but you need to also check if the clicked square is red.
Would nice to have some red squares to begin with. Let's assume color(204, 0, 0) is your red, you could simply add an additional check:
if(grid[i][j].c == color(204, 0, 0)){
println("red block clicked");
grid[i][j].c = color(0, 204, 0);
}
Which roughly turns your sketch into:
Square[][] grid;
int cols = 20;
int rows = 20;
final color RED = color(204, 0, 0);
final color GREEN = color(0, 204, 0);
void setup() {
size(400, 400);
grid = new Square[cols][rows];
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j] = new Square(i*20, j*20, 20, 20);
// roughly 50 - 50 % change a grid square will be red
if (random(0, 100) > 50) {
grid[i][j].update(RED);
}
}
}
}
void draw() {
background(0);
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
grid[i][j].display();
if (grid[i][j].x<mouseX && mouseX < grid[i][j].x + grid[i][j].w && grid[i][j].y<mouseY && mouseY < grid[i][j].y + grid[i][j].h && mousePressed) {
// if the square is red
if (grid[i][j].c == RED) {
// change colour to GREEN
grid[i][j].update(GREEN);
}
}
}
}
}
class Square {
float x, y;
float w, h;
color c;
Square(float tempX, float tempY, float tempW, float tempH) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
c = color(0);
}
void display() {
stroke(0);
fill(c);
rect(x, y, w, h);
}
void update(color c) {
this.c = c;
}
}
In terms of shuffling colours every 5 seconds I recommend:
for every 5 seconds you could use millis()
above there is an example of shuffling done in setup() though you might want to encapsulate a nested loop like that with the random condition in a void shuffle() function for example which you could easily call every 5 seconds.
note that this approach will reset green blocks to red, you might want an else in that condition to reset blocks to black (otherwise, with time, most will turn red), etc.
Have fun!
P.S. I tend to separate state data from representation. For example I would add a variable to keep track of each square state (e.g. OFF, INTERACTIVE, ACTIVATED), update a basic finite state machine, then render colours accordingly. What you have above is a tight coupling between the colour of a Square and it's state. For the homework you've got that's ok, but in the future, for more complex projects you might want to consider data flows through your program and how you represent it.
ive been working on this side project trying to make a battle ship game from some time now. I have come across a few things I do not know how to do. I was wondering if anyone knew how I could make each of the five ships with their appropriate lengths and then randomize their location on the boards.
I draw the two boards like this in my void setup()
//drawing grid
for(int i = 0; i < 10; i++){
for(int j = 0; j <10; j++){
squares.add(new ObjGame( 20+50*i,75+50*j));
squares.add(new ObjGame( 580+50*i,75+50*j));
}
}
here is where I create the matrix for the ships and the hit icons. I do it in their own class in order to try and keep my main kinda clean
ObjGame(int xi, int yi){
ship = random(5)<.5;
x = xi;
y = yi;
}
void draw(){
pushMatrix();
translate(x,y);
fill(25,200,222);
stroke(c1,c2,c3);
rect(0,0,50,50);
if(!ship && clicked){
fill(255); //white circle for miss);
ellipse(25,25,30,30);
}
else if(ship && clicked){
fill(255,0,0); //red circle for hit
ellipse(25,25,30,30);
}
else{
fill(25,200,222);
rect(0,0,50,50);
}
popMatrix();
}
void attacked(){
if(mouseX <= 500){
if(mouseX> x && mouseX< x+ 50 && mouseY > y && mouseY < y+50){
clicked = true;
println(x+" "+y);
}
}
i am also trying to print out their coordinates but I want them to print out 0 - 9 instead of their actual x and y coordinates, is there an easy way to fix that or should I just be switching them?
I have been working on a 2D game, kind of like Terraria, and i have got to the stage where i am ready to do collision detection. I tried it myself, but it... well, its very strange. I was wondering if anybody could help me with this. I store all of my blocks in a 2D array:
Block[][] map = new Block[mw][mh];
where mw is map width and mh is map height (in terms of number of blocks). Each Block is an image that is displayed as 16x16 pixels. Here is what i attempted, i know that it is wrong but i dont really know what i need to do.
private void checkCollision() {
for(int x = -1; x <= 1; x++){
for(int y = -1; y <= 2; y++){
Rectangle obj = new Rectangle((int)Block.getXOnScreen(xblock+x), (int)Block.getYOnScreen(yblock+y), 16, 16);
try{
if(main.map[(int) (xblock+x)][(int) (yblock+y)].solid && obj.intersects(bounds()){
if(y <= -1 && velY > 0){
velY = 0;
System.out.println("Collision below");
onground = true;
}else if(y >= 2 && velY < 0){
velY = 0;
System.out.println("Collision above");
}
if(x <= -1 && velX < 0){
velX = 0;
System.out.println("Collision left");
}else if(x >= 1 && velX > 0){
velX = 0;
System.out.println("Collision right");
}
}
}catch(Exception e){}
}
}
}
I call this method every tick like so, but it doesn't collide with anything so the player just falls.
public void tick(){
xblock += velX;
yblock += velY;
velY += gravity;
checkCollision();
}
If anyone knows how to do collision detection efficiently please can you share this with me. Thanks! :)
Based on the few JavaFX/Swing applications that I once wrote, the way you want to detect collision is by always keeping track of where the object is, and when it moves check to see that it is new location (old + movement count) is not exceeding the limits of the map. If it does, you want to reset its position to be right on limit so that it can go in all other directions that are valid. If you keep trying to move outside of the limits then it should keep resetting your position.
So say the limit of the page is 500 pixels wide, you are in position 495, and each move is 10, next time you move you would in position 505, so that's clearly out of range. Thus you run a check if(currentPosition > limit) {reset position to limit} thus your currentPosition will be set to 500 which is right on the border, and within the limits.
I have two squares that moves around on the screen, both of the squares are from the same class (it's the same square that was drawn two times). I have already figured out how to do the collision detection between them so thats not a problem. The problem is that the squares can go through each other so I was thinking that I could make it so that when the squares hit each other they will teleport to the latest x and y position they were on before they collided. I have tried some things but non of them works. In my thread I have this code for now.
for(int i = 0; i < rectangles.size(); i++){
Rectangle rect = (Rectangle) rectangles.get(i);
x = rect.getXPos();
y = rect.getYPos();
checkRectCollisionAndMovement();
for(int j = i + 1; j < rectangles.size(); j++){
Rectangle rect2 = (Rectangle) rectangles.get(j);
Rectangle r1 = rect.getBounds();
Rectangle r2 = rect2.getBounds();
if(r1.intersects(r2)){
rect.setXPos(x);
rect.setYPos(y);
}
}
}
How would I make it so that it gets the x and y position before they colided and not the one they had while they were colliding?
This is the checkCollisionAndMovement method
public void checkRectCollisionAndMovement(){
for(int i = 0; i < rectangles.size(); i++){
Rectangle rect = (Rectangle) rectangles.get(i);
if(rect.getYPos() > 500){
rect.setYPos(rect.getYPos() - .1);
}
if(rect.getYPos() < 500){
rect.setYPos(rect.getYPos() + .1);
}
if(rect.getXPos() > 500){
rect.setXPos(rect.getXPos() - .1);
}
if(rect.getXPos() < 500){
rect.setXPos(rect.getXPos() + .1);
}
if(rect.isVisibe()){
rect.move();
}else{
rect.remove(i);
}
}
}
You can either store all previous x,y positions in a list and traceback one step when there is a collision or Store only last co-ordinates in temporary variables.
But as Duncan has mentioned I feel your new path should reflect along the axis orthogonal to the impact
So I am making a snake game, but if I move from one direction to the other really fast then it says I made a collision with the body and ends the game (for example, if I am going left and I hit down and then left again really fast or down and right really fast, etc.)
I've tried a few things already. I changed the way that it checked for a collision by making it a .intersects rather than checking if (x == body[i][0] && y = body[i][1]). I also did a few System.out.println()'s to see if maybe something was going wrong there. I noticed that sometimes one of the values repeats (either x or y depending on the direction), but I can't figure out why... I figure that the repeating is why it messes up the collision, but I can't find the spot where it would be making it repeat.
x and y are being changed by a thread.
Here is the "Drawing" portion of my code. If you need any other snippets of code please let me know.
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (numOfFood == 1) {//Checks wether there is food on the GUI
g.setColor(Color.BLUE);
g.fillRect(foodX,foodY,12,12);
}
else {
foodX = random.nextInt(103)*12; //Both this and the below line get a random x or y value to put on GUI for food placement
foodY = random.nextInt(57)*12;
numOfFood = 1;
}
Rectangle headRect = new Rectangle( x, y, 12, 12 ); //Actual rectangle of the head
Rectangle foodRect = new Rectangle(foodX, foodY, 12, 12); //Food rectangle
g.setColor(Color.RED);
g.fillRect(x,y,12,12); //Draws head of Snake
g.setColor(Color.WHITE);
g.fillRect(x+2,y+2,8,8); //Draws a white square in the head of the snake
for (int i = 0; i < n; ++i) { //Collision Checker
Rectangle bodyRect = new Rectangle(body[i][0],body[i][1],12,12);
if ( headRect.intersects(bodyRect)) {
for (int j = 0; j < n; ++j) {
body[j][0] = -1;
body[j][1] = -1;
}
numOfFood = 1;
n = 0;
x = 624;
y = 348;
endGame = true;
}
}
g.setColor(Color.RED);
if (n > 0) { //Puts the snakes body behind the head
for (int i = 0;i < n; ++i) {
g.fillRect(body[i][0],body[i][1],12,12);
}
}
for (int i = n-1;i >= 0; --i) { //Inserts the head at the first part of the array so that the body moves
if (body[i][0] != -1 && body[i][1] != -1) {
body[i+1][0] = body[i][0];
body[i+1][1] = body[i][1];
}
if (i == 0) {
body[i][0] = x;
body[i][1] = y;
}
}
if (headRect.intersects(foodRect)) { //If the food rectangle and the head rectangle intersect then the snake got the food.
numOfFood = 0;
n++;
}
}
When do you call paintComponent? I suspect that you have one method that continuously moves the snake forward in regular intervals, but paintComponent is responsible for making the snake longer.
You should move collision and moving the snake into the same method that is responsible for moving the head in the direction the snake is moving.
Otherwise, paintComponent might be called many times on one move update, and this is responsible for duplicates of x and y in your array.