Processing draw a rect and keep it for some time - java

So i've made a simple program that have as its objective to draw a rect on the screen when a button is clicked on the mouse, if its the left button it make a rect on the left half of the screen, and if it the right it make a rect in the right half of the screen.
The problem is that i used a for loop to make the rect get drew for some time continuously, but it just does not happen.
Here is my code:
int bab = 0;
void setup() {
size(500, 500);
frameRate(24);
background(255);
int b = 0;
}
void draw() {
background(255);
println(bab);
bab++;
if(mousePressed == true && mouseButton == LEFT) {
fill(100, 0, 0);
for(int i = 0; i <= 20000; i++) {
fill(100, 0, 0);
rect(0, 200, width/2, 50);
println("The value is: " + i);
}
background(255);
}else if(mousePressed == true && mouseButton == RIGHT) {
fill(255, 255, 0);
for(int i = 0; i <= 200; i++) {
rect(width/2, 0, width/2, height);
}
}
}

Try this code:
long leftOn = 0;
long rightOn = 0;
void draw() {
// clear window buffer (white color)
background(255);
if (mousePressed == true && mouseButton == LEFT) {
// remember timestamp when left button was pressed in variable leftOn
leftOn = millis();
rightOn = 0;
} else if (mousePressed == true && mouseButton == RIGHT) {
// remember timestamp when right button was pressed
rightOn = millis();
leftOn = 0;
}
// now is current timestamp
long now = millis();
/*
* if now - last left click distance is lower than 1000 ms - draw left rect
* else if now - right left click distance is lower than 1000 ms - draw right rect
*/
if (now - leftOn <= 1000*1) {
fill(0,255,0);
rect(0,0,width/2,height);
} else if (now - rightOn <= 1000*1) {
fill(255,255,0);
rect(width/2, 0, width/2, height);
}
// else - nothing is drawn in this frame, so window will be empty in this frame
}
Looping is done by Processing - I mean when you set frame rate to 20 it means that Processing will call method draw() every 50 ms (20 times in 1 second).
So, you have to implement how 1 single frame should be drawn. You dont need looping to make things last longer.
In above code left rect will appear and last for 1 second from last left button was pressed. And right rect for 1 second from right button.
The millis() method returns the number of milliseconds that elapsed from startup. You can then remember in leftOn when left button was pressed. And you draw left rect if time difference between now and last leftOn is less then 1000 ms - for example.

Your for loop uses i as it's control / to represent each iteration through the loop. You also have the drawing happening in this loop, so that each iteration should draw something.
However, nowhere in your loop do you use the i variable -- you only print it to the console.
for(int i = 0; i <= 20000; i++) {
fill(100, 0, 0); // does not use i
rect(0, 200, width/2, 50); // does not use i
println("O valor é: " + i);
}
So what you have really is a loop that draws the exact same thing, 20000 times. So to you it looks like nothing is happening, but it is, it's just the same thing is happening repeatedly.
Maybe you wanted something more like:
for(int i = 0; i <= 20000; i++) {
fill(100, 0 + i, 0 + i);
rect(0 + i, 200, width/2, 50 + i);
println("O valor é: " + i);
}
^ I really have no idea if that makese sense... But you need to use the loop control variable i somewhere in your drawing code, or else yes, you will draw the same thing repeatedly.

Related

Make my rectangle randomly fall down from my screen?

I am trying to make a game and am almost done with the code. But I can't make my rectangle randomly fall down from my screen.
I am coding a car game that is supposed to dodge the other cars. But is not working. can someone help me?
int carx = 200;
int cary = 0;
float speedx = 0;
float speedy = 0;
float accy = 0.1;
color rod = color(255, 0, 0);
color vit = color(255);
final int START_STATE = 1;
final int PLAY_STATE = 2;
final int GAMEOVER_STATE = 3;
final int RESTART = 4;
int state = START_STATE;
void setup() {
size(400, 700);
}
void draw() {
switch (state) {
case START_STATE:
drawStart();
break;
case PLAY_STATE:
drawPlay();
break;
case GAMEOVER_STATE:
drawGameOver();
case RESTART:
drawrestart();
}
}
void init() {
carx = 200;
cary = 0;
speedx = 0;
speedy = 0;
accy = 0.1;
}
void drawStart() {
background(0);
textAlign(CENTER, CENTER);
textSize(16);
text("Click the mouse button to start the game", width / 2, height / 2);
if (mousePressed) {
state = PLAY_STATE;
}
}
void drawGameOver() {
textAlign(CENTER, CENTER);
textSize(20);
text("you have crashed your car", width / 2, height / 2);
if (mousePressed) {
state = PLAY_STATE;
init();
}
}
void drawrestart() {
textAlign(CENTER, CENTER);
textSize(15);
text("press mouse to restart", 200, 400);
if (keyPressed) {
state = RESTART;
}
}
void drawPlay() {
background(0);
if (get(carx, cary) == vit) {
speedy = -1 * speedy;
}
fill(rod);
rect(carx, cary, 50, 30);
if (get(mouseX, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
fill(#FFFFFF);
rect(mouseX, 600, 30, 50);
carx += speedx;
cary += speedy;
speedy += accy;
}
The code you have at the moment only has one rectangle fall down from the top for each 'round' of the game. I'm not sure if you wanted to have multiple blocks falling; I think that would be a good next step.
For now, here's a simple hack which will cause the block to fall from a random position each time, like you requested.
At the very start of your code, outside of the functions, place:
boolean randomise;
Then, within void init() you should add:
randomise = true;
Finally, add this section into drawPlay(), right at the start of the function:
if (randomise){
carx = int(random(width-50));
randomise = false;
}
Note that a new random x co-ordinate will only generate every time you set the boolean 'randomise' to true again. So if you generate a new iteration with more than one block falling inside the drawPlay() function, you should bear this in mind and adjust the code accordingly.
------- [EDIT] -------
Hi, glad that this helped.
I've actually noticed another little issue which I will help you fix.
Currently, you are checking at mouseX to see whether there has been a collision. This works (mostly), but if the right side of the player's white car drives through the left edge of a red falling block, then the game continues as though nothing has happened. What should occur is that the game is over because a collision is detected. You want to find out if any part of the two shapes have overlapped.
To do this, you should alter the code like so. In drawPlay(), replace:
if (get(mouseX, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
with:
if (get(mouseX, 600) == color(255, 0, 0) || get(mouseX + 30, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
This is an OR statement - checking whether either side of the player's car has collided. This way, every time they bump into each other, the game will end.
Now for your question: how to add multiple cars?
There are a few ways you could go about this, but I'll show you the most straightforward.
In drawPlay(), you want to add this little if statement:
if (cary > height){
init();
}
Basically what we're doing here is checking if the previous red block/car has fallen off the bottom of the sketch. If it has, i.e. if the red block's y co-ordinate is larger than the height of the whole sketch, we call init() again. This will reset everything, including making randomise true. Once randomise is true, the previous code you added will select a random start point for the block, and it will fall all over again.
I hope you've understood everything I explained - whilst my code will fix your problem, the best way to learn is to try to solve things by yourself. Check out Dan Shiffman's videos on YouTube. These are a great starting place to get to grips with Processing - hopefully you'll be more confident writing your own code after following along with his examples :)
Use random to generate a random x coordinate:
carx = (int)random(0, width-50);
Reset the position and the speed of the care, once the car reached to bottom of the window:
void drawPlay() {
if (cary > height) {
carx = (int)random(0, width-50);
cary = 0;
speedy = 0;
}
// [...]

Matrixes and for loops becoming inconsistent?

This is a follow-up post to my previous question, here. I got a remarkable response to instead of using array data tracking, to use matrixes. Now, the code here works just as planned (as in, the rectangles somewhat most of the time get filled in properly with white), but it's very inconsistent. When holding the left or right mouse button the colors phase over each other in a battle of randomness, and I don't know nearly that much about why this is happening. Just for reference, I'm using Java in Processing 3.
This is a result that I made with the project. As you can see, it looks fine.
Except for that jitter when hovering over a rect, and that more than not the rectangles are not being filled in half the time. And plus, the hover color is cycling almost randomly.
int cols, rows;
int scl = 20;
boolean[][] matrix = new boolean[scl+1][scl+1];
void setup() {
size(400, 400);
int w = 400;
int h = 400;
cols = w / scl;
rows = h / scl;
}
void draw() {
background(255);
for (int x = 0; x < cols; x++) {
for (int y = 0; y < rows; y++) {
int xpos = x*scl;
int ypos = y*scl;
stroke(55);
if ((mouseX >= xpos && mouseX <= xpos+scl) &&
(mouseY >= ypos && mouseY <= ypos+scl)) {
fill(75);
if (mousePressed == true) {
println("Clicked at: " + xpos + " and " + ypos);
if (!matrix[xpos/scl][ypos/scl]) {
matrix[xpos/scl][ypos/scl] = true;
} else {
matrix[xpos/scl][ypos/scl] = false;
}
fill(100);
//here is the desired location for the fill to remain constant even
//after unclicking and leaving hover
}
println("Mouse at: " + xpos + " and " + ypos);
} else {
fill(50);
}
if (matrix[x][y]) {
//fill(204, 102, 0);
fill(240);
rect(xpos, ypos, scl, scl);
}
rect(xpos, ypos, scl, scl);
}
}
}
Remeber that Processing fires the draw() function 60 times per second.
So your check for whether the mouse is pressed is happening 60 times per second. That means you're toggling the state of whatever cell the mouse is in 60 times per second.
To fix that problem, you might switch to using the event functions like mousePressed() instead of constantly polling every frame.
From the reference:
int value = 0;
void draw() {
fill(value);
rect(25, 25, 50, 50);
}
void mousePressed() {
if (value == 0) {
value = 255;
} else {
value = 0;
}
}
As for certain cells being skipped over, that's because when you move the mouse, it doesn't actually go through every pixel. It "jumps" from frame to frame. Those jumps are usually small enough that humans don't notice it, but they're large enough that it's skipping over cells.
One solution to this is to use the pmouseX and pmouseY variables to calculate a line from the previous mouse position to the current mouse position, and fill in any cells that would have been hit along the way.

Ball in Brick Breaker game destroys whole lines without touching them(Java)

I have been making a brick breaker game for fun, but I came across an odd error in the execution of the program. When the game is started, the ball is set in motion away from the bricks. However, it starts destroying them almost immediately, starting from the brick furthest to the right on the upper row and continuing to break them all from right to left. Then it goes to the second row and destroys them from left to right. This whole time, on the screen, the ball is away from any bricks.
I think I pinpointed the problem to the following piece of code. Here I create a rectangle around the ball and a rectangle around the brick and if they were to intersect, I call the method setBrickValue inside another class called Map Generator, which sets the value of the brick to 0, meaning, it doesn't exist.
Here's the method:
public void actionPerformed(ActionEvent arg0) {
timer.start();
//makes sure the ball collides with the paddle
if(play){
if( new Rectangle( ballPositionX, ballPositionY, 20, 20)
.intersects( new Rectangle( player, 550, 100, 8 ) ) ){
ballDirY = - ballDirY;
}
// beginning of the code with an error in it, the rectangle around the ball
//is intersecting incorrectly the rectangle of the brick
A:for(int i = 0; i < MGobj.map.length; i++){
for(int j = 0; j < MGobj.map[0].length; j++){
if(MGobj.map [i] [j] > 0){
int brickX = i * MGobj.brickWidth + 80;
int brickY = j * MGobj.brickHeight + 50;
int brickWidth = MGobj.brickWidth;
int brickHeight = MGobj.brickHeight;
//create the rectangle around the brick
Rectangle rect = new Rectangle( brickX, brickY,
brickWidth, brickHeight );
//create the rectangle around the ball, so we can detect the intersection
Rectangle ballRect = new Rectangle( ballPositionX, ballPositionY, 20, 20 );
Rectangle brickRect = rect;
//when intersecting, delete the brick off the map
if( ballRect.intersects( brickRect )){
MGobj.setBrickValue( 0, i, j );
totalBricks--;
score += 5;
//
if( ballPositionX + 19 >= brickRect.x ||
ballPositionX + 1 <= brickRect.x + brickRect.width ){
ballDirX = - ballDirX;
}else{
ballDirY = - ballDirY;
}
//creates a label that says when this code executes, get out of the
//outer loop
break A;
}
}
}
}
//end of the code with an error in it
//makes sure the ball is moving
ballPositionX += ballDirX;
ballPositionY += ballDirY;
//makes sure the ball isn't going beyond the borders
if(ballPositionX < 0){
ballDirX = -ballDirX;
}
if(ballPositionY < 0){
ballDirY = -ballDirY;
}
//think this code doesn't work
if(ballPositionX > 670){
ballDirX = -ballDirX;
}
}
repaint();
}
Here's the setBrickValue method:
public void setBrickValue(int value, int row, int col){
map [row] [col] = value;
}
All help is appreciated. Thank you in advance.
PS: If anybody would like to see the whole code (400ish lines), just tell me and I would upload it.

Drawing the position indicator on the image

so, here is the question, i need to draw the position indicator corresponding to my hand position and then perform some manipulations on an image
here is the screen capture:
the left half of the screen is the image, and the right half of the screen is my camera,
the program will draw the position indicator corresponding to my hand position,
my problem is that the cursor cannot be disappeared and it will draw many times!
here is the code:
import gab.opencv.*;
import processing.video.*;
import java.awt.*;
PImage img;
PImage select;
PImage cur;
OpenCV opencv;
Capture cam;
int prevPositionX, prevPositionY, currPositionX, currPositionY;
int mode = -1; //mode 1 = s (select) mode 2 = c (copy) mode 3 = d (draw)
int select_ind = -1;
//store every dectected things
Rectangle[] hand;
//store the biggest hand
Rectangle bhand;
void setup() {
size(1280, 480);
img = loadImage("test.jpg");
cur = loadImage("cursor.png");
stroke(255,10,0);
opencv = new OpenCV(this, 640, 480);
opencv.loadCascade("aGest.xml");
cam = new Capture(this, 640, 480);
cam.start();
image(img, 0, 0, img.width, img.height);
}
void draw(){
if (cam.available()==true) {
cam.read();
}
opencv.loadImage(cam);
hand = opencv.detect();
pushMatrix();
scale(-1.0, 1.0);
image(cam, -1280, 0);
popMatrix();
int handcount = -1;
int handsize = -1;
//calculate the biggest hand
for( int i=0; i < hand.length; i++ ) {
if(handsize < (hand[i].width * hand[i].height)){
handsize = hand[i].width * hand[i].height;
handcount = 1;
bhand = hand[i];
}
}
if(handcount > 0){
rect(1280 - bhand.x, bhand.y, -bhand.width, bhand.height);
noFill();
//draw the position indicator
image(cur, 480 - bhand.x, bhand.y, 16, 16);
prevPositionX = currPositionX;
prevPositionY = currPositionY;
currPositionX = 480 - bhand.x + 4;
currPositionY = bhand.y;
//select mode
if (mode == 1){
}
//copy mode
else if (mode == 2){
}
//draw mode
else if (mode == 3){
line(prevPositionX,prevPositionY,currPositionX,currPositionY);
}
}
}
void keyPressed(){
if(key=='s'||key=='S')
mode = 1;
else if(key=='c'||key=='C')
mode = 2;
else if(key=='d'||key=='D')
mode = 3;
else if(key=='i'||key=='I')
image(img, 0, 0, img.width, img.height);
}
void keyReleased(){
if(select_ind > -1 && mode == 2){
//to be done
}
mode = -1;
}
i am working with the drawing mode which is to draw a line on the image,
and i know the problem but i do not know how to solve it,
i need to add this : image(img, 0, 0, img.width, img.height); to the first
of draw() function, but the line will also be deleted. i want to keep
the line like the screen capture.
Please give me a hand and sorry for the bad english. Thanks
If you need to persist just part of the draw, you need to redraw it every frame, while still "clearing" the background using image(img, 0, 0, img.width, img.height). This means store coordinates of lines and redraw it every time, also note that you can hide the cursor... SomeThing like this:
// YOU GOT ADD (CLICK) AT LEAST 2 POINTS TO SEE IT WORKING ;)
ArrayList<PVector> positions = new ArrayList<PVector>();
void setup(){
size(600, 600);
//if you don't want to see the cursor...
noCursor();
}
void draw(){
//clear screen
background(255);
//always draw at mousePosition
//a "custom cursor"
//that will not persist as screen is beeing cleared
fill(200,80,220);
noStroke();
ellipse(mouseX, mouseY, 20, 20);
stroke(80);
PVector prevP = null;
for (PVector p:positions) {
if(prevP != null) {
line(prevP.x, prevP.y, p.x, p.y);
}
prevP = p.get();
}
}
void mouseClicked() {
positions.add(new PVector(mouseX, mouseY));
}
EDIT:
Also you can use PGraphics as layers to persist just part of the drawing without redrawing all the stuff over and over... :)

Drawing mountains using 1px swing rectangles

I'm trying to draw mountains background using 1-width rectangles (something like integrals). I randomize the first point to the very left of the screen, randomize binary number and draw the first rectangle.
If binary number is 0, the next rectangle will be 1px lower. Else higher. And so on in the for loop.
There's a 95% chance that in the next loop the direction won't change and it will keep going higher/lower. And 5% chance the direction will change. For this I'm using randomized number from 1 to 1000.
public Landscape(Graphics g)
{
Graphics2D g2d = (Graphics2D)g;
Random rand = new Random();
int first = rand.nextInt((800 - 200) + 1) + 200;
g2d.fillRect(0, 800 - first, 1, first);
int d = first % 2;
for(int i = 1; i <= 800; i++) {
int choose = rand.nextInt((1000 - 1) + 1) + 1;
if(choose > 950) {
d = -(d);
}
if(d == -1) {
first += 1;
} else {
first -= 1;
}
g2d.fillRect(i, 800 - first, 1, first);
}
}
That's the effect I get in like half cases. Sometimes however I get something like this:
How is this possible? What's wrong here?
Here:
int d = first % 2;
d is either 1 or 0. If d is assigned 0, then if(d == -1) { is always false, and thus your graph will go monotonically downwards.
You are looking for a two state solution to decide whether the mountain goes up or down, so use a boolean. Perhaps something like:
boolean direction = rand.nextBoolean();
// 1 in 20 chance, same as 5 in 100, same as 50 in 1000 chance
if (rand.nextInt(20) == 0) {
direction = !direction;
}
if (direction) {
// ...
} else {
// ...
}
Myself, I'd look into using fractals.

Categories

Resources