Changing color of sphere with time (processing) - java

I am a new coder on processing, because of this reason please be gentle.
Normally my code is more longer and complex but I wrote a simple code for you, which I can adapt on my code:
int speed = 1;
int x, z = 50;
void setup() {
size(400, 400, P3D);
}
void draw() {
background(0);
noStroke();
lights();
translate(x, height/2, z);
fill(255,0,0);
sphere(25);
if (x > width -50)
noLoop();
x += speed;
}
So, like you see, sphere starts with color of red and it reaches end of the window. I want to change it's color from red to white and it should take 30 sec. to reach end of the window. However I don't know how. If you help me I will be happy.
Note: I tried lerpColor function but didn't help me.

Math is the secret. Is often is.
There are a couple things you'll need to keep track of to accomplish this: the time it takes to cross the screen (you said 30 seconds), the speed of the sphere, the speed at which the color changes.
Before we start, I suggest that you use float for your variables which are positions and speeds. Integers will do the job, but at some point when you want precision you may regret not using floats or a similar type.
There are 2 ways to deal with changes over time: you can calculate time and draw what needs to be drawn where it's supposed to be, or calculate how many frames will be drawn in a certain amount of time and move things accordingly. The first technique has the advantage of being able to draw things where they are supposed to be even if the system is laggy (Processing will lower the framerate if it's not able to respect it), while the second is often easier to work with. We'll go with the framerate technique, as this is not supposed to be complicated and because most programs won't need so much resource that it'll lower the framerate.
The framerate, in Processing, is also the rate at which the main loop (the draw() loop) run. So we'll choose a framerate which will let us calculate the speed of the sphere and the speed at which the color change. The rest is just watching it move.
Here's your example, but modified so it works approximately as you told:
float speed;
float x, z = 50;
float greenBlueStrength = 0;
float colorFadeRate = 1;
int fadeTimeInFrames;
void setup() {
size(400, 400, P3D);
frameRate(60); // 60 is the default framerate per second
// so 30 seconds == (30*60) == 1800 frames
// so you must have the speed to match
fadeTimeInFrames = 60 * 30;
speed = (width - 50) / (float)fadeTimeInFrames;
colorFadeRate = 255 / (float)fadeTimeInFrames;
println(colorFadeRate);
}
void draw() {
background(0);
textSize(30);
text((millis()/1000) + " s. // color: " + (int)greenBlueStrength, 20, 50);
// this is just to keep track of changes while they happen
noStroke();
lights();
translate(x, height/2, z);
fill(255, greenBlueStrength, greenBlueStrength);
sphere(25);
if (x > width -50) {
noLoop();
} // no actual change, but use brackets anyway, it's easier to read
// updating what needs to be updated
x += speed;
greenBlueStrength += colorFadeRate;
}
I'll hang around so don't hesitate if you have questions.
Have fun!

I think something like that would work:
int r=255,b=255,g=255;
...
void draw(){
...
int percent=x/width*100;
fill(r,b*percent,g*percent)
sphere(25)
...
}
so the sphere would be red only on the left of the screen and white on the right

Related

How do I adjust Processing/Minim waveform scale?

I'm a total beginner so forgive me if this is probably silly or improper of me to ask.
I'm trying to make my own virtual oscillograph in processing. I don't really know how to explain it, but I want to "zoom out" from where I am getting the peaks in waveforms, which is the window size. I'm not sure what I'm doing wrong here or what's wrong with my code. I've tried changing the buffer size, and changing the multiplier for x/y. My sketch is adapted from a minim example Sketch.
All Help is greatly appreciated.
import ddf.minim.*;
Minim minim;
AudioInput in;
int frames;
int refresh = 7;
float fade = 32;
void setup()
{
size(800, 800, P3D);
minim = new Minim(this);
ellipseMode(RADIUS);
// use the getLineIn method of the Minim object to get an AudioInput
in = minim.getLineIn(Minim.STEREO);
println (in.bufferSize());
//in.enableMonitoring();
frameRate(1000);
background(0);
}
void draw()
{
frames++; //same saying frames = frames+1
if (frames%refresh == 0){
fill (0, 32, 0, fade);
rect (0, 0, width, height);
}
float x;
float y;
stroke (0, 0);
fill (0,255,0);
// draw the waveforms so we can see what we are monitoring
for(int i = 0; i < in.bufferSize() - 1; i++)
{
x = width/2 + in.left.get(i) * height/2;
y = height/2- in.right.get(i) * height/2;
ellipse(x, y, .5, .5);
}
}
Thanks
Edit: you don't need push and pop matrix here. Guess my understanding of it is lacking too. You can just use translate.
You can use matrices to create a camera object, there is tons of material out there that you can read up on to understand the math behind this and implement it anywhere.
However, there might be an easier solution here. You can use pushMatrix and popMatrix in combination with translate. Push and popping the matrix will manipulate the matrix stack - you create a new "frame" where you can play around with translations, then pop back the original frame (so you don't get lost by applying new translations on each frame).
push the matrix, translate the z coordinate once before drawing everything you want zoomed out, pop the matrix. You can set up a variable for the translation so that you can control this with your mouse.
Here's a crude example (I don't have all those libraries so couldn't add it to your code):
float scroll = 0;
float scroll_multiplier = 10;
void setup()
{
size(800, 800, P3D);
frameRate(1000);
background(0);
}
void draw()
{
background(0);
//draw HUD - things that don't zoom.
fill(255,0,0);
rect(400,300,100,100);
//We don't want to mess up our coordinate system, we push a new "frame" on the matrix stack
pushMatrix();
//We can now safely translate the Y axis, creating a zoom effect. In reality, whatever we pass to translate gets added to the coordinates of draw calls.
translate(0,0,scroll);
//Draw zoomed elements
fill(0,255,0);
rect(400,400,100,100);
//Pop the matrix - if we don't push and pop around our translation, the translation will be applied every frame, making our drawables dissapear in the distance.
popMatrix();
}
void mouseWheel(MouseEvent event) {
scroll += scroll_multiplier * event.getCount();
}

What's the best way to implement a color cycling background?

What's the best way to cycle the color of a background smoothly (as well as other things) using cos or sin in java, without using more than one file? I've tried using randomness and increasing each individual r, g, and b value separately to make this look kind of normal, but it's jittery, not smooth, and the colors are horrid. Right now, it's just plain white. I included only the necessary code, and I am using Processing 3.
//background
int bg1 = 255; //r
int bg2 = 255; //g
int bg3 = 255; //b
void draw() {
fill(bg1,bg2,bg3);
}
You've got the general idea down. It's a three-step process:
Step 1: Declare variables at the top of your sketch.
Step 2: Use those variables to draw your scene.
Step 3: Change those variables over time.
This is the basic approach to create any animation in Processing. Here is a tutorial with more information.
Here is a small example that shows a window that cycles between white and black:
float c = 0;
float cChange = 1;
void draw(){
background(c);
c += cChange;
if(c < 0 || c > 255){
cChange *= -1;
}
}
You would need to do something similar, but with 3 color values instead of 1. Note that I'm only changing the color by a small amount each time, which makes it appear smooth instead of jittery.
If you're still having trouble, please post an updated MCVE in a new question and we'll go from there. Good luck.
If you specifically want to use a sine wave as input rather than the sawtooth wave then you need to map your input (e.g. time) to some color range. For example:
every 2000 milliseconds value increases from 0 to 2.0
value ranges from -1 to 1.
the output of sin(value) ranges from -1 to 1.
map the output to a color range.
map() works well for mapping values, but you can also use colorMode() for mapping color ranges -- so rather than moving your sine output values around, just make your output 0-2.0 and set the max RGB or HSB value to 2.0 rather than 255.
Here are some examples, all running simultaneously in one sketch:
float val;
float out;
void draw() {
background(0);
val = TWO_PI * (millis()%2000)/2000.0; // every 2000 milliseconds value increases from 0 to 2PI
out = sin(val);
// white-black (256-0)
pushStyle();
fill(128 + 128*out);
rect(0,0,50,50);
popStyle();
// red-black (255-0)
pushStyle();
colorMode(RGB, 255);
fill(255*(out+1), 0, 0);
rect(50,0,50,50);
popStyle();
// hue rainbow (0-2)
pushStyle();
colorMode(HSB, 2.0);
fill(out+1, 2, 2);
rect(0,50,50,50);
popStyle();
// hue blue-green (3 to 5 / 9)
pushStyle();
colorMode(HSB, 9);
fill(out+4, 9, 9);
rect(50,50,50,50);
popStyle();
translate(width/2,height/2 - out * height/2);
ellipse(0,0,10,10);
}
Don't understand what you mean by cos and sin in relation to background color. But maybe something like this is what you want?
void draw(){
int H = frameCount%1536;
background(color(abs(H-765)-256,512-abs(H-512),512-abs(H-1024)));
}

Box2D move bodies at same rate regardless of FPS

Sorry, I couldn't word my title properly but I will explain my problem with more clarity here.
I am using libgdx.
When I want to move a Texture so that it covers the same distance with all FPS I will do this:
//...define Player class with x property up here.
Player player = new Player();
int SPEED = 100
public void render() {
player.x += SPEED * Gdx.graphics.getDeltaTime();
}
Now I want to know how to do this to have the same affect on a body in box2d. Here is an example(the render method of a class that extends ApplicationAdapter):
public void render() {
//clear screen, ... do other stuff up here.
playerBody.applyForce(new Vector2(0.5f / PIXEL_PER_METER, 0.0f), playerBody.getWorldCenter(), true);
//PIXEL_PER_METER -> applied to scale everything down
//update all bodies
world.step(1/60f, 6, 2);
}
This applies a force on the playerBody so that it's acceleration increases. How do I make shore, just like with my first example, that how fast the body is travelling stays constant across at 30fps, 10fps, 60fps, etc. I know the timeStep parameter of the world.step is the amount of time to simulate but this value shouldn't vary.
Thankyou in advance.
You can update all bodies with delta (not 1/60 fixed delta)
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
EDIT:
As #Tenfour04 mentioned, in order to prevent high delta values (causes huge jumps), we mostly set a cap for delta.
world.step(Math.min(Gdx.graphics.getDeltaTime(), 0.15f), 6, 2);
I wouldn't use a variable timestep - this is the approach I've used:
private float time = 0;
private final float timestep = 1 / 60f;
public void updateMethod(float delta) {
for(time += delta; time >= timestep; time -= timestep)
world.step(timestep, 6, 2);
}
Basically a variable-ish timestep, but uniformly updating.
If you run your game at very low FPS, or if you force it to with the application configuration (e.g. for testing) this will keep updating at roughly the same speed as a normal 60 FPS instance.
Take a look at Fix your timestep!

Bring Ball To A Stop

I have the following methods in my program which keep a ball continuously bouncing. I have tried modifying but can't seem to get the ball to stop at the bottom of my GUI. My main goal is to have the methods simulate as if you were bouncing a real ball.
private void updateDelta() {
final int minimumMovement = 5;
final int maxExtra = 10;
deltaY = minimumMovement + (int) (Math.random() * maxExtra);
}
public void verticalBounce(Container container) {
// controls vertical ball motion
if (upDown) {
y += deltaY;
if (y >= getHeight()) {
upDown = false;
updateDelta();
}
} else {
y += -deltaY;
if (y <= 0) {
upDown = true;
updateDelta();
}
}
}
UPDATE:
Ball bounces and stops at the bottom of the gui.
public void verticalBounce(Container container) {
deltaY = deltaY - gravity;
y = y + deltaY;
if (y > getHeight()) {
y = getHeight(); // reset location
deltaY = (int) (deltaY * -0.9); // slows down ball
}
}
None of that code looks correct. You need to implement the equation(s) of rectilinear motion:
http://en.wikipedia.org/wiki/Linear_motion
The one you need is s = ut + 0.5 * a * t * t, where
s = distance
u = an initial velocity - regard as the speed at which it hits the ground
a = acceleration due to gravity (you can probably have this pretty arbitrary)
t = time
You reverse the sign of a on the way up.
To simulate lossy bouncing, reduce u by taking a certain factor of energy E out of the system:
new_u * new_u = (1 - E)u * u.
(This comes from the formula for the kinetic energy of a moving body).
I can see from your question that you are capable of implementing this, so I won't provide code; just the physics.
First, a bouncing ball doesn't have a random element in it. Its all determined by the forces acting on the ball and the speed and direction of the ball. If you add a little randomness, it may make it look a little more realistic because of things like wind and unbalance in the ball but its very little.
To program it, assume the ball gets shot up from the ground at some speed. You need to store:
Y = location in units above the ground. Start at 0.
deltaY = speed in units per time interval. Negative is down. Positive is up. Start at 10.
gravity = acceleration in units of change per time interval. Gravity is always negative and constant. Start with -2 and try some values.
Unless you want the ball to disappear off the screen as it reaches the top of the bounce, you will need to select a ceiling height. Say 100. (Which is best chosen to match your graphics area's height, though.)
So for every time interval/tick/loop you do the following:
Adjust for gravity by subtracting gravity from deltaY. (If the ball is moving down it will move faster. If its moving up, it will move slower.)
Move the ball by adding deltaY to Y.
Then you have to check: Did the ball hit the ground or the ceiling? Is Y greater than the ceiling value or less than the ground one (0).
If so, you have to bounce it by:
Move Y such that if it was X past the boundary (ground/ceiling) it becomes X within the boundary. (If Y = 110 and ceiling = 100, set Y to 90. If Y = -5, set it to +5.)
Negate deltaY. In a bounce the direction reverses. (deltaY = -deltaY)
Reduce deltaY by a percentage. Some energy is lost in the bounce so speed is slower after a bounce. (deltaY = deltaY * 0.90 or some other amount) #Bathsheba calls that removing energy from the system.
That's all there is to it. You have to fiddle with the numbers to make it take off at a reasonable speed. You have to adjust the time interval. You don't have to match real life. Just do what looks good.
As time goes by, the speed will reduce to 0.
(And despite what I said before, adding or subtracting a small random amount actually looks kind of cool.)
Your ball is bouncing randomly instead of slowly decreasing in velocity. You need to lower your velocity every bounce until the velocity is under minimumMovement then make the velocity 0 and stop bouncing.

Creating "stick controls" for android game?

I'm trying to create a simple Android game, a 2D action shooter which has 2 control sticks (circles) on the screen, the left one is movement control and the right one weapon control. Direction is being controlled by the position of your thumb relative to the circle’s center.
I've been following a tutorial on this site: http://www.kilobolt.com/day-7-creating-an-android-game-from-start-to-finish.html but it only gave me the base to work on. I have no programming experience so I'm quite lost now.
I got the movement working only on TOUCH_DOWN event, the hero moves to about where it should but to change direction I have to lift my thumb and touch the circle again. TOUCH_DRAGGED (or ACTION_MOVE) is broken because if I drag my finger across the circle the character moves really fast. I guess the problem is too many touch events are being handled, but I have no idea how to fix it.
How can I change this so that I can drag my thumb around the circle and the hero will change its direction instantly, and keep its speed constant all the time? Also the speed should be the same no matter how close or far from the center of the circle you touch.
private void updateRunning(List<TouchEvent> touchEvents, float deltaTime) {
int len = touchEvents.size();
for (int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if (event.type == TouchEvent.TOUCH_DOWN || event.type == TouchEvent.TOUCH_DRAGGED) {
if (inBounds(event, 50, 300, 150, 150, 'c')) {
ctrl.setX(event.x);
ctrl.setY(event.y);
ctrl.direction();
hero.move(ctrl.getDirX(), ctrl.getDirY());
}
}
if (event.type == TouchEvent.TOUCH_UP) {
if (inBounds(event, 0, 0, 35, 35,'r')) {
pause();
}
hero.stopMove();
}
}
hero.update();
The movement: hero's speedX and speedY are added to hero's centerX and centerY on every hero.update() call.
public void move(float x, float y) {
speedX += x * MOVESPEED;
speedY += y * MOVESPEED;
}
This method that handles the x & y speed. Found it here at stackoverflow, and because touch_down event is working ok, I guess it's doing it's job. Although I feel it's not exactly how it's supposed to be. L_STICK_C is a constant with values of 100 and 350 (center of the circle).
public void direction() {
dir.x = x - L_STICK_C.x;
dir.y = y - L_STICK_C.y;
double hyp = Math.sqrt(dir.x * dir.x + dir.y * dir.y);
dir.x = (float) (dir.x / hyp);
dir.y = (float) (dir.y / hyp);
}
I suggest you look into some game programming tutorials. You usually would not move the character directly from the touch input. You'd set a game state variable once a game loop which would correspond to the position of your thumb inputs. Then you'd only update the hero once per game loop based on those inputs. This lets allows you to keep the game input control code, and hero code separate, and makes it re-usable for other parts of your game.
EDIT:
Based on your code, every time you drag your finger, you generate a bunch of dragged events. So you are adding onto your characters speed for each event. You should probably just be looking at the distance to center and x / y of the input on the last touch event, not all of them.

Categories