So I'm working in p5.js and my task is when i press my mouse down it needs to draw circles and I've got that working. But the extra thing is that this only can happen in a certain rectangle and I'm a bit lost, does anyone know how I can achieve this?
function setup() {
createCanvas(400, 400);
}
var circles = [];
function draw() {
background(220);
rect(100, 100, 200, 200)
var index = 0;
while(index < circles.length) {
ellipse(circles[index].x, circles[index].y, circles[index].d);
index += 1;
}
if (mouseIsPressed) {
// add a circle where the mouse is
// not this: ellipse(mouseX, mouseY, 10);
circles[circles.length] = { x: mouseX, y: mouseY, d: 30 };
}
}
This is what it needs to look like:
enter image description here
For now your code generates a circle when the mouse is pressed no matter where the mouse is on the screen. What you want is to generate the new circle only when your mouse is in your rectangle, so this is only a matter of adding a condition to make sure your mouse is not outside of the rectangle.
To make this test you first need to know what are the boundaries of your rectangle. You created it with rect(100, 100, 200, 200) which means the top left corner is on position x:100, y:100 and it's width and length are 200 so its bottom right corner is on position x:(100+200)=300, y:(100+200)=300.
So you want to create your circles only is 100 < mouseX < 300 and 100 < mouseY < 300 you would write it this way:
Do to so you code would be changed to this:
if (mouseIsPressed && mouseX > 100 && mouseX < 300 && mouseY > 100 && mouseY < 300 ) {
// add a circle where the mouse is
circles[circles.length] = { x: mouseX, y: mouseY, d: 30 };
}
Now when you click outside of the rectangle no circle is added.
Note that since the circle is centered on the position of the click, your circles (which are of radius 30/2=15) will be drawn out of the rectangle if you click too close from the border of the rectangle.
So maybe you'd rather want a condition like this:
if (mouseIsPressed && mouseX > 100+15 && mouseX < 300-15 && mouseY > 100+15 && mouseY < 300-15 ) {
You can see it working here
Also it would be better to have all these measures (the rectangle position, its width and height, the circle diameter) in variables so that you don't have to hard code the different values, but you'll be able to do that later on when your program works properly.
Related
I've recently built a game of pong for a UNI assignment in Processing, but whenever the ball hits the top, bottom, side of the screen or the 'paddle' it only bounces back once half the ball is off the screen. I just want the edge of the ball to hit first rather than the centre, but am unsure where my code is going wrong. I hope this makes sense, I'm a definite beginner.
Here is my code for reference
//underwater pong
float x, y, speedX, speedY;
float diam = 10;
float rectSize = 200;
float diamHit;
PImage bg;
PImage img;
int z;
void setup() {
size(920, 500);
smooth();
fill(255);
stroke(255);
imageMode(CENTER);
bg = loadImage("underthesea.jpg");
img = loadImage("plastic.png");
reset();
}
void reset() {
x = width/2;
y = height/2;
//allows plastic to bounce
speedX = random(5, 5);
speedY = random(5, 5);
}
void draw() {
background(bg);
image(img, x/2, y);
rect(0, 0, 20, height);
rect(width/2, mouseY-rectSize/2, 50, rectSize);
//allows plastic to bounce
x += speedX;
y += speedY;
// if plastic hits movable bar, invert X direction
if ( x > width-30 && x < width -20 && y > mouseY-rectSize/2 && y < mouseY+rectSize/2 ) {
speedX = speedX * -1;
}
// if plastic hits wall, change direction of X
if (x < 25) {
speedX *= -1.1;
speedY *= 1.1;
x += speedX;
}
// if plastic hits up or down, change direction of Y
if ( y > height || y < 0 ) {
speedY *= -1;
}
}
void mousePressed() {
reset();
}
I wasn't able to run your code because I am missing the background and plastic images, but here's what's probably going wrong. I'm not 100% since I do not know the dimensions of your images either.
You are using imageMode(CENTER). See the documentation for details.
From the docs:
imageMode(CENTER) interprets the second and third parameters of image() as the image's center point. If two additional parameters are specified, they are used to set the image's width and height.
This treats the coordinates you input into the image function as the center of the image.
Your first issue is that you are placing your image at x/2 but doing all your collision checks with x in mind. x does not represent the middle of your image, because you're drawing it at x/2.
Then I'm not sure if you are doing your horizontal collision checks right, as you are checking against hardcoded values. I do know you are doing your vertical collision checks wrong. You are checking if the center of the image is at the top of the canvas, 0, or the bottom of the canvas, height. This means that your image will already have moved out of the screen halfway.
If you want to treat the image coordinates as the center of your image, you need to check the left edge of the image at x - imageWidth / 2, the right edge at X+ imageWidth / 2, the top edge at y - imageWidth / 2 (remember the y coordinates are 0 at the top of the canvas and increase towards the bottom) and the bottom at y - imageWidth / 2. Here's a great website which goes into more detail on 2d collision detection, i'd highly recommend you give it a read. It's an awesome website.
So I managed to make most of the exercise but can't think of a way to make the trail of the moving image. Also, in the video ball moves in the direction of mouse position.
However, when I tried to do that, mouse position is changing every time and the ball is following the mouse while moving. The velocity had to be calculated using the mouse position. Any help would be appreciated.
This is how it should look: https://streamable.com/9jdc3
My code:
PImage ball, bFire;
int xPosB, yPosB, bW, bH, bFW, bFH, velocityX, velocityY;
boolean bMoving;
void setup() {
size(1024, 512);
//loading images
ball = loadImage("ball.png");
bFire = loadImage("ballFire.png");
//resizing images
ball.resize(ball.width/4, ball.height/4);
bFire.resize(bFire.width/4, bFire.height/4);
//starting values
//ball
xPosB = width/2;
yPosB = height/2;
}
void draw() {
background(0);
//draw ball
imageMode(CENTER);
image(ball, xPosB, yPosB);
//draw fire ball
if (bMoving) {
image(bFire, xPosB, yPosB);
xPosB+=velocityX;
yPosB+=velocityY;
}
//colision detection
if (xPosB-bFire.width/2 <= 0 || xPosB+bFire.width/2 >= width) {
velocityX*=-1;
} else if (yPosB-bFire.height/2 <= 0 || yPosB+bFire.height/2 >= height) {
velocityY*=-1;
}
}
void mousePressed() {
if (mouseButton == LEFT) {
bMoving=!bMoving;
velocityX = mouseX/100;
velocityY = mouseY/100;
}
}
I can't repoduce the problem you describe - of the ball following the mouse.
I can tell you that the mousepressed() you use is incorrect.
You assign the velocity, but because mouseX and mouseY will always be positive the ball will always move to the right and down.
Try the code below, it sets the velocity to the difference between the mouse and the current position of the ball. The ball will now always move towards the mouse.
void mousePressed() {
if (mouseButton == LEFT) {
bMoving=!bMoving;
velocityX = (mouseX - xPosB) / 50;
velocityY = (mouseY - yPosB) / 50;
}
Second point: I don't know how your ballFire.png looks, but right now it is drawn at the exact same X/Y location of the ball. This cannot give you a trailing effect, for that you'll have to draw the fireball a little behind the ball.
Try the code below:
//draw fire ball
if (bMoving) {
image(bFire, xPosB-velocityX, yPosB-velocityY);
xPosB+=velocityX;
yPosB+=velocityY;
}
//draw ball
imageMode(CENTER);
image(ball, xPosB, yPosB);
It draws the fireBall behind the ball based on the velocity. So faster means more distance. You can tweak this distance of course. If you want multiple firballs as trailing effect, draw the fireball multiple times with different offsets.
Final note: you'll want to draw the ball last, else the fireball will be drawn half over the normal ball.
I have a question. How do I change the color of a rectangle from white to black step by step, when I move my mouse away? I'm kinda new to this.
I've tried a bit:
void setup () {
size (200,200);
}
void draw () {
background (0);
stroke (255);
line (100,0,100,200);
line (0,100,200,100);
// Fill a black color
noStroke ();
fill (255);
// Depending on the mouse location, a different rectangle is displayed.
if (mouseX < 100 && mouseY < 100) {
rect (0,0,100,100);
} else if (mouseX > 100 && mouseY < 100) {
rect (100,0,100,100);
} else if (mouseX < 100 && mouseY > 100) {
rect (0,100,100,100);
} else if (mouseX > 100 && mouseY > 100) {
rect (100,100,100,100);
}
}
I would appreciate that, if anyone could help me.
Thanks.
The call fill(255); is setting the rectangle color to white. Use fill(0); to set the rectangle to black, or fill(x); for any value x between 0 and 255 for shades of grey.
To make a fade, you'll need to draw multiple rectangles (drawing all of them is easiest) on each draw() call. The current box will be in white, where the mouse is. Others will be fading to black. So you'll need variables for each box indicating its current color.
Here's my version:
int boxColor1;
int boxColor2;
int boxColor3;
int boxColor4;
void setup () {
size (200,200);
boxColor1 = boxColor2 = boxColor3 = boxColor4 = 0;
}
void draw () {
background (0);
// Fill a black color
noStroke ();
// Subtrack 10 from each box color, but don't go below zero
boxColor1 = max( 0, boxColor1-10 );
boxColor2 = max( 0, boxColor2-10 );
boxColor3 = max( 0, boxColor3-10 );
boxColor4 = max( 0, boxColor4-10 );
// Depending on the mouse location, a different rectangle is displayed.
if (mouseX < 100 && mouseY < 100) {
boxColor1 = 255;
} else if (mouseX > 100 && mouseY < 100) {
boxColor2 = 255;
} else if (mouseX < 100 && mouseY > 100) {
boxColor3 = 255;
} else if (mouseX > 100 && mouseY > 100) {
boxColor4 = 255;
}
fill (boxColor1);
rect (0,0,100,100);
fill (boxColor2);
rect (100,0,100,100);
fill (boxColor3);
rect (0,100,100,100);
fill (boxColor4);
rect (100,100,100,100);
// Draw edge lines last, over the top
stroke (255);
line (100,0,100,200);
line (0,100,200,100);
}
If there are a lot of boxes, you should use an array, or some data structure instead of many different variables like boxColor1, boxColor2 etc.
If I understand your question, you want to show a grid of rectangles, and you want a rectangle to turn white and stay white when the mouse exits that rectangle. Is that right?
If so, then you need to keep track of whether each rectangle should be black or white. The simplest approach might be a 2D array of boolean values. Each cell in the array will represent a single square in your grid.
Set the corresponding cell in the array to true when you want that square to turn white. Then loop over the array and draw each square using the values in the array to determine the color.
I started programming this pong game for CS class. I want to have the ball starting off in the center of the field so I used:
ellipse (width/2, height/2, 15, 15);
I want to make the game start once I press the space key. In order to do that I used:
if (keyPressed == true) {ellipse (ballX, ballY, 15, 15); fill (0, 255, 0);}
However it does not work. Can someone please help me figure out what is wrong with my code? Please consider that this is not a JavaScript but a Processing question.
Here is my entire code so far:
float ballX = 15, ballY = 15, dX = 15, dY = 15; // variables for the ball
float paddleX; // variables for the paddles
int mouseY; // variable to make the pong move with the mouse movement
boolean key, keyPressed;
void setup() {
size (1500,1100); // the field is going to be 1500x110px big
paddleX = width - 40;
ballX = 15; ballY = 15;
}
void draw() {
background(0); // black background
ellipse (width/2, height/2, 15, 15); // this is the starting point of the ball
if (keyPressed == true) { ellipse (ballX, ballY, 15, 15); fill (0, 255, 0); } // the game will only start when a key is pressed
if (ballX > width || ballX < 0) { dX = -dX; } // if the ball reaches the right or left wall it will switch directions
if (ballY > height || ballY < 0) { dY = -dY; }// if the ball reaches the upper or lower wall it will switch directions
ballX = ballX + dX; ballY = ballY + dY; // the ball with move with the speed set as dX and dY
rect(paddleX/58, mouseY, 20, 100); fill (255,10,20); // green pong
rect(paddleX, mouseY, 20, 100); fill (60,255,0); // red pong
}
The answer to this question is the same as the answer to your other question: you need to store the state of your sketch in variables, then you need to draw each frame based on that state, and finally you need to change those variables to change the state of your game.
Here's a simple example that only draws an ellipse after you press a key:
boolean playing = false;
void keyPressed() {
playing = true;
}
void draw() {
background(0);
if (playing) {
ellipse(width/2, height/2, 50, 50);
}
}
In this example, the playing variable is my state. I then update that state in the keyPressed() function, and I use that state to determine what I draw in my draw() function. You'll have to extrapolate a bit, but this process of breaking your problem down into a state, changing that state, and drawing that state is the answer to all of your questions.
So, I am creating the game breakout in processing (programming language) but can't quite figure out a function to check for collision against the bat.
So far the section I have written for collision against the bat only collides the ball against the base and returns it in the opposite direction. For now, the game is a never ending phenomenon where the ball just collides with the walls. What I am trying to do is, collide the ball against the bat.
Oh this is my homework, so just please point me in the right direction instead of doing it for me.
Here's the code:
// Basic Breakout game
// Code from Matthre Yee-King
// brick position
float brickX;
float brickY;
// brick width and height
float brickH;
float brickW;
// ball position
float ballX;
float ballY;
// ball diameter
float ballD;
// ball direction
float ballDx;
float ballDy;
// bat position
float batX;
//bat width
float batW;
float batH;
//bat colour
float batB;
void setup() {
size (500, 500, P2D);
// set sizes of game items
brickW = 100;
brickH = 50;
batW = 100;
batH = 25;
ballD = 25;
batB = 255;
// random brick position
brickX = random(0, width - brickW);
brickY = random (0, height / 2);
// bat in the centre
batX = (width/2) - (batW/2);
// ball atop bat
ballX = batX + (batW/2);
ballY = height - batH - (ballD/2);
// ball movement
ballDx = random(-5, 5);
ballDy = -5;
rectMode(CORNER);
ellipseMode(CENTER);
}
void draw() {
// check for ball collision
// with top or sides of bat
checkBallAgainstBat();
// check for ball collision with
// left right and top walls
// and bounce
checkBallAgainstWalls();
// check ball against brick
checkBallAgainstBrick();
// move the ball
ballX += ballDx;
ballY += ballDy;
background(0);
// draw the bat
fill(0, 255, 0);
rect(batX, height - batH, batW, batH);
// draw the brick
fill(0, 0, batB);
batB = (batB + 10) % 255;
rect(brickX, brickY, brickW, brickH);
// draw the ball
fill(255, 0, 0);
ellipse(ballX, ballY, ballD, ballD);
if (keyCode == 37) { // left cursor key
batX -= 10;
// keep it on the screen
if (batX < 0) {
batX = 0;
}
}
if (keyCode == 39) {
batX += 10;
if (batX > (width - batW)) {
batX = width - batW;
}
}
}
// when they let go of the key, reset the keyCode
void keyReleased() {
keyCode = -1;
}
// this function checks if the ball has hit the top or sides of the bat and
// updates its direction as appropriate so the ball bouncs off the bat
void checkBallAgainstBat() {
if (ballY + ballD > height - batH) {
ballDy *= -1;
}
}
// this function checks if the ball has hit the brick. It should bounce off
// the brick and return true if so
boolean checkBallAgainstBrick() {
return false;
}
// this function checks if the ball has hit the top, left or right
// walls and update its
// direction as appropriate so the ball bounces off the walls
void checkBallAgainstWalls() {
if (ballX + ballD > width) {
ballDx *= -1;
}
if (ballX - ballD < 0) {
ballDx *= -1;
}
if (ballY - ballD < 0) {
ballDy *= -1;
}
}
Since the bat in breakout is a fixed width, your collision detection can be quite simple (in pseudo-code):
if (lower_edge(ball) > top_edge(bat)) {
// the ball has entered territory where it might have collided
if ((left_edge(ball) <= right_edge(bat)) && (right_edge(ball) >= left_edge(bat))) {
// the ball's within the horizontal bounds of the bat, so it's a "hit"
... calculate deflection ...
} else {
// oops, ball's gone past the bat and wasn't hit
strike_out();
} else {
// ball's still above the bat somewhere. do nothing
}
In english: If the ball's lower edge has gone past where the top edge of the bat is, we've POSSIBLY got a collision. This is only checking the vertical axis of the play field. You then check if the left or right edges of the ball fall within the horizontal location of the bat. If neither side of the ball overlaps the bat, then you've lost. Otherwise you've collided and you do the collision detection.