I tried to make a jump look realistic, while I watched through the Videos:
The Natur of Code - The Coding Train
I got into PVectors. I strongly recomend watching him. But to get to my question, everything seems to work, exept that it draws the rectangle (my PVector) the way I want.
void keyPressed() {
if (keyCode == UP) {
for (int i = 0; i < 16; i++) {
location.sub(velocity);
velocity.sub(acceleration);
h.display();
background(0);
}
velocity.set(0, 15);
}
}
That's the Code, I expect it to "jump", but nothing realy happens. You can see that the rectangle get's drawn again (on the same spot), but there's no movement. It's definitly an issue with the drawing of the background or something, I don't know what exaclty though.
The nature of your question is unclear. You mentioned issues regarding the background interfering with your rectangle after the UP arrow key is pressed. This is likely because background(0) is called immediately after h.display(). I would remove background(0) from your loop if it's a display issue.
Other than that, there seem to be other issues with the loop itself. When the UP key is pressed, h is affected by acceleration only for 16 frames. To make your object more realistic, gravity (or whatever acceleration you choose) should constantly be acting upon the object.
With that in mind, here's a solution for you.
void keyPressed() {
if (keyCode == UP) {
// Make the character 'jump' upwards when the UP arrow is pressed.
// Setting the velocity should be the only thing happening when the key is pressed.
velocity.set(0, -2);
}
}
void draw() {
// Reset the background each frame so rectangles don't overlap.
background(255);
// Always draw the rectangle AFTER resetting the canvas.
h.display();
// Change the object's location by it's velocity.
location.add(velocity);
// And chance the object's velocity by it's acceleration.
// Since acceleration is the acting force of gravity in this situation, acceleration need not be changed.
velocity.add(acceleration);
// Prevent the rectangle from falling through the bottom of the canvas.
if(location.y > height - 5) location.y = height - 5;
}
// You negleteced to define your variables in your code snippet. Here they are.
PVector location = new PVector(0, 0);
PVector velocity = new PVector(0, 0);
PVector acceleration = new PVector(0, 0.1); // Notice that acceleration's y-value is 0.01. This is so you can see the effect of gravity.
// Define your rectangle object.
Object h = new Object();
class Object {
Object() {} // Constructor.
void display() {
// Draw the rectangle at the x- and y-positions of the location vector.
// The '+ width/2' places it at the center of the screen.
rectMode(CENTER);
rect(location.x + width/2, location.y, 10, 10);
}
}
Related
I am creating a model of a solar system in processing, and after removing the background I noticed the planets were leaving a trail of their image behind them. The program runs fine when the background is back in, but I want to add a lot more and I am sure this is inefficient and will bog things down.
I am very new to processing, and I am really not sure how to solve this. Maybe delete previous images after a delay to create a shortened trail?
These are just the parts I think are important cherry picked from the code, this is just the example of one planet. Sorry if the code is clunky, any suggestions are happily accepted.
Planet p1;
void setup() {
mercury = loadImage("mercury.png")
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
//background(0)
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
imageMode(CENTER);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
I realized that this would probably happen, and I am not sure how to stop it.
The behavior you describe is simply the nature of computer graphics; it's how games, operating systems, and hardware displays all work – they clear and redraw everything every frame.
In Processing, graphic objects that are pushed to a buffer remain there indefinitely until the buffer is cleared or something is pushed on top of them (this is why the planets are leaving a trail without calling background() – previous frames remain in the buffer).
You are worried about the background() being inefficient. Don't be, as it's one of the fastest operations (simply sets the value of each pixel, as given by the user).
Processing does provide a clear() function, but this is equivalent to background(0).
If you're are still concerned about efficiency and speed, one way to speed up Processing is to use the FX2D renderer rather than default AWT renderer. Another way is cache drawn objects into PGraphics objects to prevent successive rasterization (since your planets are image files and not drawn with processing, you needn't worry about this).
Your code is simple enough that it doesn't need optimisations at this stage.
As micycle mentions, you are are drawing an image at a translated position, pretty similar to blitting.
In terms of the trails, one common trick you could use is not clear the screen completely, but draw a transparent rectangle as the background. The more transparency, the longer the trails.
Here's a tweaked version of your code:
// planet object
Planet p1;
// planet texture
PImage mercury;
void setup() {
size(300, 300);
// draw image from center
imageMode(CENTER);
// clear to black one
background(0);
// remove strokes (we'll use rect() later)
noStroke();
// set the fill to black but with 9/255 transparency (~3.5% transparent)
fill(0,9);
// init texture
mercury = loadImage("mercury.png");
// init planet
p1 = new Planet(40, random(TWO_PI), 0.05);
}
void draw() {
// draw a transparent rectangle instead of completely clearing the screen
rect(0,0,width,height);
// render planet
translate(width / 2, height / 2);
p1.display1();
p1.orbit();
}
class Planet {
float radius;
float angle;
float distance;
float orbitSpeed;
Planet(float r, float d, float o) {
radius = r;
distance = d;
orbitSpeed = o;
angle = random(TWO_PI);
}
void orbit() {
angle = angle + orbitSpeed;
}
void display1() {
pushMatrix();
rotate(angle);
translate(distance, 0);
image(mercury, radius, radius, 10, 10);
popMatrix();
}
}
It's an efficient quick'n'dirty hack as you won't need to store previous position and redraw multiple times, however it has it limitations in terms of the flexibility of the trails. Hopefully tweaking the fill() alpha parameter will get you the desired effect.
Later on if you're drawing many many many planets it things start running slow have a peak at VisualVM. Profile the CPU and see the methods that take the longest to complete and focus on those. Don't need to optimise everything, just the slowest calls. Remember that Processing have multiple renderers: JAVA2D is the default one, but there's also FX2D and P2D/P3D and they will behave differently. I strongly recommend optimising at the last moment (otherwise code might be less flexible and readable and will slow down development/iteration).
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.
This is the code I have at the moment but I want to put the bat on the y axis and have it move up and down vertically rather than horizontally, and have the ball bounce in a left to right motion rather than up and down. Help is needed quickly. Thanks.
int x=250; // Horizontal position of ball
int direction_x=2; // Change in horizontal position each time draw() executed
int y=150; // Vertical position of ball
int direction_y=2; // Change in horizontal position each time draw() executed
int lives=3;
int score=0;
void setup()
{
size(400,400); // Create a window 400x400 pixels
}
void draw()
{
background(255,255,255); // Clear screen to white
fill(0,255,0); // Set fill colour to blue
rect(mouseY-60,380,120,20); // Position rectangle using mouse
fill(0,0,255);
ellipse(x,y,20,20); // Draw blue disk centered on x,y diameter 20
x=x+direction_x; // Update position
if(x<10) direction_x=-direction_x; // Reverse direction if hit boundary
if(x>(width-10)) direction_x=-direction_x;
y=y+direction_y;
if(y<10) direction_y=-direction_y;
// if(y>(height-10)) direction_y=-direction_y;
if(y>(height-10)) // If ball bits bottom of screen then miss..
{
direction_y=-direction_y; // Bounce
lives--; // Reduce lives by one
if(lives==0) exit(); // If lives is zero then quit
}
if((y>(height-30))&&(abs(mouseX-x)<60)) // If ball has bit paddle then..
{
direction_y=-direction_y; // Bounce
score++; // Increase score by one
}
textSize(32);
fill(0,0,255);
text(score, 10, 30); // Display score
text(lives,width-30, 30); // Display lives
}
Since help is needed quickly, you'll have better luck if you ask a specific "I tried X, expected Y, but got Z instead" type question. It's hard to help with general "how do I do this" type questions, other than to offer general tips.
That being said, there are two main approaches that I can think of:
Option One: Break your problem down into smaller steps. Start with a blank sketch and get just the paddle working how you want it to. Then try adding the ball. After that's working, then try adding game logic. This is the better option here.
Option Two: Since you seem to almost have this working going up and down, you could just rotate everything 90 degrees by using the rotate() function. This is a bit of a hack though.
Thanks Kevin, got it working at last, turns out I just had to change co-ordinates of the paddle from (mouseX,0,0,0) to (0, mouseY,0,0) and needed to add in an additional line of code to change the axis parameters. I was doing my age old trick of over complicating things.
int x=250; // Horizontal position of ball
int direction_x=2; // Change in horizontal position each time draw() executed
int y=150; // Vertical position of ball
int direction_y=2; // Change in horizontal position each time dra) executed
int lives=3;
int score=0;
void setup()
{
size(400,400); // Create a window 400x400 pixels
}
void draw()
{
background(255,255,255); // Clear screen to white
fill(0,255,0); // Set fill colour to blue
rect(0,mouseY-60,20,120); // Position rectangle using mouse
fill(0,0,255);
ellipse(x,y,20,20); // Draw blue disk centered on x,y diameter 20
x=x+direction_x; // Update position
if(x<10) direction_x=-direction_x; // Reverse direction if hit boundary
if(x>(width-10)) direction_x=-direction_x;
y=y+direction_y;
if(y<10) direction_y=-direction_y;
// if(y>(height-10)) direction_y=-direction_y;
if(y>(height-10)) // If ball bits bottom of screen then miss..
{
direction_y=-direction_y; // Bounce
lives--; // Reduce lives by one
if(lives==0) exit(); // If lives is zero then quit
}
if(x<10)
{
direction_x=-direction_x; // Bounce
x=30; // Force x to beyond the paddle on a restart
lives--; // Reduce lives by one
if(lives==0) exit(); // If lives is zero then quit
}
if((x<30)&&(abs(mouseY-y)<60)) // If ball has bit paddle then..
{
direction_x=-direction_x; // Bounce
score++; // Increase score by one
}
textSize(32);
fill(0,0,255);
text(score, 10, 30); // Display score
text(lives,width-30, 30); // Display lives
}
I'm trying to activate different visuals by pressing different keys. For example, when I press "z" or "Z", an ellipse on a specific position flows down, leaving a trace behind. If I wait for it to reach the canvas border, there's no problem but when I press "0" which activates another ellipse on another position to do the same thing, the ellipse of "z"/"Z" stops flowing. It also happens when I press the same key before the ellipse reaches canvas border. How can I fix this? When I started to code this, I didn't know classes and objects, then I learned and tried to solve it by using creating an object but it got worse, ellipses didn't work at all. I want the first ellipse to continue until the border even if I press another key while it's on its way.
Another thing is I wanted them to fade out after a short time, so I drew semi-transparent rectangles on canvas which seems very primitive to me. Would you suggest a different way? This is less important but it would be better to have them completely fade over time rather than leaving a slight trace.
Here's my code, I cleaned irrelevant parts to make it look more understandable:
void setup() {
size(640, 500);
background(bgRenk);
frameRate(60);
colorMode(HSB);
noStroke();
}
int bgRenk = #e7e7e7;
int C3Yer;
int C3Y;
int Fd6Yer;
int Fd6Y;
void draw() {
// This part probably sucks because it's a primitive solution to make ellipses fade out by putting semi-transparent rectangles on the canvas.
fill(bgRenk, 10);
rect(0, 0, 640, 500);
// I basically map x and y positions to hue and opacity.
float C3Renk= map(C3Yer, 0, width, 0, 255);
float C3Opak = map(C3Y, height, 0, 0, 200);
// When z/Z is pressed, an ellipse appears and goes down, leaving trace behind.
if (key == 'z' || key == 'Z') {
C3Yer = 10;
fill(C3Renk, 255, 255, C3Opak);
ellipse(C3Yer, C3Y, 20, 20);
C3Y += 20;
}
if (key == '0') {
// Same mapping and ellipse thing.
float Fd6Renk= map(Fd6Yer, 0, width, 0, 255);
float Fd6Opak = map(Fd6Y, height, 0, 0, 200);
Fd6Yer = 630;
fill(Fd6Renk, 255, 255, Fd6Opak);
ellipse(Fd6Yer, Fd6Y, 20, 20);
Fd6Y += 20;
}
}
void keyPressed() {
if (key == 'z' || key == 'Z') {
// When z/Z is pressed, y position of those ellipses are reset.
C3Y = 10;
}
if (key == '0') {
// Same reset thing.
Fd6Y = 10;
}
}
Thank you for your time.
Problem with creating new ellipse while other is still flowing is with variable key which always contains the value of the most recent key used (for more see). So when you press any key after "z" your ellipse will stop being drawn.
You can avoid this using global variables indicating which ellipses should be drawn.
But I would suggest using creating objects that will have defined state (position, color, opacity) and will be stored inside array or list. It will also help you with fading so find a time and read more about classes and objects. On processing site you can find nice tutorials like this one
But because you sad you already tried creating objects and i don't works I will give you few tips and basic example of such a class:
class Ball {
float x, y; // position of ball
color col = 10; // color of ball
int opac = 255; // opacity of ball
Ball(float _x, float _y) {
x = _x;
y = _y;
}
void move() {
y += 20;
opac -= 10;
}
void display() {
fill(col, 255, 255, opac);
ellipse(x, y, 20, 20);
}
}
Then you can create new ball objects:
void mousePressed() {
//this will create new ball on mouse position
balls.add( new Ball(mouseX, mouseY) );
}
and store them into ArrayList like this:
ArrayList<Ball> balls = new ArrayList();
Last thing that you need to do is display and move all balls within draw method.
for (Ball b : balls) // for each ball in list
{
b.display(); // first display ball
b.move(); // move and change opacity
}
This is very basic example and should be improved but I hope it will help you with understanding of classes.
Hi How do I make bullets to collide with the objects in Processing ?
Bullets are fired and being translated and rotated
but whenever i try to use function dist() it always gives me 0 as the position of the vector
How do i get the correct vector position if i want the bullet to collide with objects using distance and make the the other object disappear ?
Here's the code
void move(){
passed = passed + time;
if (passed > bulletLife) {
alive = false;
}
forward.x = sin(theta);
forward.y = -cos(theta);
float speed = 15.0f;
velocity = PVector.mult(forward, speed);
side.add(forward);
void display(){
pushMatrix();
translate(side.x, side.y);
rotate(theta);
stroke(255);
ellipse(side.x, side.y, 30, 30);
popMatrix();
Thanks
You're getting 0 from dist() because translate() moves the coordinate system! I think, more than your question, you need to reconsider your code overall. You translate to side.x, side.y (which will then be 0,0 until you call popMatrix()) but then you draw the ellipse at side.x, side.y which is offset from its actual position.
In other words: if the position is 100,200, you're actually drawing the object at 200,400!
If you skip the translate() part, you can use this to draw your object:
void display() {
stroke(255);
ellipse(side.x, side.y, 30,30);
}
And this to check collision:
if (dist(side.x, side.y, bullet.x, bullet.y) == 0) {
collision = true;
}
else {
collision = false;
}
You can also see my collision-detection functions for Processing, which have lots of examples that might help.