How to create a sine wave in processing? - java

I would like to create a sine wave using vectors (as I am using box2d).
So far I have (in void draw())
Vec2 mov2 = new Vec2(sin(angle)*scalar,0);
for (int j = 0; j <= 10; j++) {
bridge.particles.get(j).body.setLinearVelocity(mov2);
}
where bridge is a chain of particles. However, this makes all the particles move back and forth at the same time whereas I would like to move like a sine wave so that each particle moves just slightly after the previous one.

You need to add some sort of offset between each of the particles inside your loop.
Example:
for( int i=0; i < 360; i++ ){
float x = 1 + i;
float y = (float)(Math.sin( Math.toRadians(i+currentOffset)));
bridge.particles.get(j).setTransform(x, y, 0);
}
currentOffset+=1;

Related

Catmull Rom Spline implementation (LibGDX)

I want to generate a random spline across my screen.
Here is what I have so far:
public class CurvedPath {
Random rn;
CatmullRomSpline<Vector2> curve;
float[] xPts;
float[] yPts;
Vector2[] points;
public CurvedPath(){
points = new Vector2[10];
rn = new Random();
curve = new CatmullRomSpline<Vector2>(points,false);
for(int i = 0 ; i < 10; i++){
xPts[i] = rn.nextFloat()*SampleGame.WIDTH;
yPts[i] = SampleGame.HEIGHT*i/10;
}
}
}
I'm pretty confused on the documentation that has been provided on how to use the CatmullRomSpline object ( https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines )
Basically what I am trying to do here is generate 10 random points equally distributed across the height of my screen, and randomly placed along the width of the screen to create a randomized curved path.
So within the constructor's for loop you can see that I generate the x and y values of each control point for the spline.
How can I give input these points into the spline object and render it on the screen?
-thanks
update
Let me reword my question to be a little more specific..
I have my control points represented by xPts and yPts. Now I want to get the points that fall along the spline, how do I do this using these two vectors? The constructor for a CatmullRomSpline takes a Vector2, not two float[] 's
what you did. Fill with points:
curve = new CatmullRomSpline<Vector2>(points,false);
To get a point on the curve:
Vector2 point = new Vector2();
curve.valueAt(point, 0.5f);
valueAt() Parameter explanation:
1 (point) the point you are looking for is stored in the Vector2 object.
float between 0 and 1, 0 is the first point, 1 the last one. 0.5f is middle. This float represents the hole distance from first to last point.
Getting and render 100 points can look like this:
Vector2 point = new Vector2();
for (int i = 0; i <= 100; i++) {
curve.valueAt(point, i * 0.01f);
// draw using point.x and point.y
}
answer to you edited question:
for(int i = 0 ; i < 10; i++){
points[i].x = rn.nextFloat()*SampleGame.WIDTH;
points[i].y = SampleGame.HEIGHT*i/10;
}
curve = new CatmullRomSpline<Vector2>(points,false);
The process is also detailed here: https://github.com/libgdx/libgdx/wiki/Path-interface-&-Splines
/*members*/
int k = 100; //increase k for more fidelity to the spline
Vector2[] points = new Vector2[k];
/*init()*/
CatmullRomSpline<Vector2> myCatmull = new CatmullRomSpline<Vector2>(dataSet, true);
for(int i = 0; i < k; ++i)
{
points[i] = new Vector2();
myCatmull.valueAt(points[i], ((float)i)/((float)k-1));
}

An error in water ripple effect (Java Open GL)

I'm trying to implement water ripple effect on a polygon model / wireframe. I followed these two guides that are pretty clear: 2D Water and The Water Effect Explained
Following these guides, I ended up with (in this order)
Two arrays of floats, full of zeros after my app launches expect one to start the ripple effect
float[][] heightMapPrev = new float[101][101];
float[][] heightMapCurr = new float[101][101];
// ... filling both arrays with 0.0f ...
heightMapCurr[30][40] = -0.5f; // changing one value to start a water wave
Variable to define damping of waves as they go further
float damping = 0.4f;
The algorithm itself. I loop through all the vertices, count their new y position and smoothening/damping the effect
// Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
for (int i = 1; i < 100; i++) {
for (int j = 1; j < 100; j++) {
// Count new vertical position of each vertex
heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) % 2.0f -
heightMapCurr[i][j];
// Count water vertical velocity
float velocity = -heightMapCurr[i][j];
// Smooth buffers every frame to waves spread out the waves
float smoothed = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) / 4.0f;
// Calculate new height of the water; reduce the effect with *2
heightMapCurr[i][j] = smoothed * 2 + velocity;
// Damp ripples to make them loose energy
heightMapCurr[i][j] *= damping;
}
}
(Re)drawing all the vertices, inside those two for loops
gl.glVertex3f((float)i, heightMapCurr[i][j], (float)j); // for each vertex
Finally, as the guide tells me to, I swap values in both arrays - what was in the waveMapPrev is now in waveMapCurr and vice versa
for (int i = 0; i < 101; i++) {
for (int j = 0; j < 101; j++) {
temp[i][j] = heightMapPrev[i][j];
heightMapPrev[i][j] = heightMapCurr[i][j];
heightMapCurr[i][j] = temp[i][j];
}
}
I though I'm clear about what is happening there but clearly I'm not, because there something wrong in my algorithm. Wave spreads from a certain point into distance, keeping circle shape, that is okay. However, water keeps "bubbling" also in the middle of the circle and once the water ripple reaches borders, everything is "bubbling" and it never stops. The ripple should probably not even hit all the borders.
Can you tell/explain me what I did wrong and how to correct the error? I tried for hours changing values (damping...), operators (% for /, + for -), and smoothening function, I did not succeed, though.
Update://
In the code above, I use modulus operator (%) instead of (/). The reason for this is just because I always get completely wrong heightMap values, the wave starts spreading to all directions including somewhere into the sky, never getting back down - like in the image below.
I think I've found your problem. Replace the modulus operator % with a simple divide /, as both of the links you provide suggest and see what that does.
The solution is even simpler than what the guides propose. I have found it here
This is the the body of the whole algorithm according to the latter guide provided, even simpler than anyone could expect.
// Loop through all the vertices and update their vertical position values according to their surrounding vertices' vertical positions
for (int i = 1; i < 100; i++) {
for (int j = 1; j < 100; j++) {
// Count new vertical position of each vertex
heightMapCurr[i][j] = (heightMapPrev[i+1][j] +
heightMapPrev[i-1][j] +
heightMapPrev[i][j+1] +
heightMapPrev[i][j-1]) / 2.0f -
heightMapCurr[i][j];
// Damp ripples to make them loose energy
heightMapCurr[i][j] -= heightMapCurr[i][j] * damping;
}
}

Collision Detection in Box2D

So I'm using Box2D for collision detection in a game. I have a tilemap that contains information on the terrain: for now it's just a char[][] that has either road or grass. Now, at the start of each level I wanted to create rectangles to describe the different terrains, but I wanted these rectangles to be optimized and apparently that takes quite an algorithm.
My first approach was to create an individual terrain for EVERY tile in the map at the start of the level. The FPS was reduced to 5.
My second idea was to simply create the different rectangles for terrains as the player moved along the map, deleting the rectangles that were out of view. Although it would still be a lot of rectangles, it would be considerably less.
I haven't attempted the second method yet, but I want to know: is there any easy way for me to efficiently perform collision detection against terrain with a large tilemap?
Thanks.
Try combining tiles. For example, if you have 16 rectangular collision volumes for 16 tiles like so...
* * * *
* * * *
* * * *
* * * *
You can obviously combine these tiles into one large rectangle.
Now, things get more difficult if you have tiles in a weird arrangement, maybe like this...
**---
****-
*--**
-*-*-
I just recently solved this problem in my game using a quad tree and sweep and prune. (Sweep and prune isn't strictly necessary, its an optimization.)
Quad tree partitions your square tiles into bigger rectangles, then you iterate over the rectangles the quad tree produces, and combine them if they have the same width, then iterate over them again and combine them by similar heights. Repeat until you can't combine them anymore, then generate your collision volumes.
Here's a link to a question I asked about a more optimal reduction. I probably won't implement this as it sounds difficult, and my current approach is working well.
Some code:
do {
lastCompressSize = currentOutput;
this.runHorizontalCompression(this.output1, this.output2);
this.output1.clear();
this.runVerticalCompression(this.output2, this.output1);
this.output2.clear();
currentOutput = this.output1.size;
iterations += 1;
}while (lastCompressSize > currentOutput);
public void runHorizontalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.xAxisSort);
int x2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
x2 = newRect.x + newRect.width;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (x2 == r2.x && r2.y == newRect.y
&& r2.height == newRect.height) {
newRect.width += r2.width;
x2 = newRect.x + newRect.width;
input.removeIndex(j);
j -= 1;
} else if (x2 < r2.x)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}
public void runVerticalCompression(Array<SimpleRect> input,
Array<SimpleRect> output) {
input.sort(this.yAxisSort);
int y2 = -1;
final SimpleRect newRect = this.rectCache.retreive();
for (int i = 0; i < input.size; i++) {
SimpleRect r1 = input.get(i);
newRect.set(r1);
y2 = newRect.y + newRect.height;
for (int j = i + 1; j < input.size; j++) {
SimpleRect r2 = input.get(j);
if (y2 == r2.y && r2.x == newRect.x
&& r2.width == newRect.width) {
newRect.height += r2.height;
y2 = newRect.y + newRect.height;
input.removeIndex(j);
j -= 1;
} else if (y2 < r2.y)
break;
}
SimpleRect temp = this.rectCache.retreive().set(newRect);
output.add(temp);
}
}

How to get the last value that an integer had before a method were executed

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

Creating a Squircle

I'm a first year programmer. I'm trying to create a squircle. (square with round corners).
So far i have managed to get. I have been given the constants of a,b and r. If anyone could help i would be really thankful. I'm a total noob to this. So be nice :)
package squircle;
import java.awt.*;
import javax.swing.*;
import java.lang.Math;
public class Main extends javax.swing.JApplet {
public void paint(Graphics g){
// (x-a)^4 + (y-b)^4 = r^4
// y = quadroot( r^4 - (x-a)^4 + b)
// x values must fall within a-r < x < a+r
int[] xPoints = new int[200];
int[] yPoints = new int[200];
int[] mypoints = new int[200];
for(int c = 0; c <200; c++){
int a = 100;
int r = 100;
int b = 100;
double x = c ;
double temp = (r*r*r*r);
double temp2 = x-a;
double temp3 = ((temp2)*(temp2)*(temp2)*(temp2));
double temp6 = Math.sqrt(temp-temp3);
double y = (Math.sqrt(temp6) + b );
double z = (y*-1)+300;
mypoints[c]=(int)z;
// if (c>100){
// y = y*1;
// }
// else if(c<100){
// y = y*1;
// }
xPoints[c]=(int)x;
yPoints[c]=(int)y;
// change the equation to find x co-ordinates
// change it to find y co-ordinates.
// r is the minor radius
// (a,b) is the location of the centre
// a = 100
// b = 100
// r = 100
// x value must fall within 0 or 200
}
g.drawPolygon(xPoints, yPoints, xPoints.length);
g.drawPolygon(xPoints, (mypoints), xPoints.length);
}
}
Is it homework or is there some other reason why you're not using Graphics#drawRoundRect()?
If you are submitting this as homework there are some elements of style that may help you. What are the roles of 200, 100 and 300? These are "magic constants" which should be avoided. Are they related or is it just chance that they have these values? Suggest you use symbols such as:
int NPOINTS = 200;
or
double radius = 100.0
That would reveal whether the 300 was actually the value you want. I haven't checked.
Personally I wouldn't write
y*-1
but
-y
as it's too easy to mistype the former.
I would also print out the 200 points as floats and see if you can tell by eye where the error is. It's highly likely that the spurious lines are either drawn at the start or end of the calculation - it's easy to make "end-effect" errors where exactly one point is omitted or calculated twice.
Also it's cheap to experiment. Try iterating c from 0 to 100. or 0 to 10, or 0 to 198 or 1 to 200. Does your spurious line/triangle always occur?
UPDATE Here is what I think is wrong and how to tackle it. You have made a very natural graphics error and a fence-post error (http://en.wikipedia.org/wiki/Off-by-one_error) and it's hard to detect what is wrong because your variable names are poorly chosen.
What is mypoints? I believe it is the bottom half of the squircle - if you had called it bottomHalf then those replying woulod have spotted the problem quicker :-).
Your graphics problem is that you are drawing TWO HALF-squircles. Your are drawing CLOSED curves - when you get to the last point (c==199) the polygon is closed by drawing back to c==0. That makes a D-shape. You have TWO D-shapes, one with the bulge UP and one DOWN. Each has a horizontal line closing the polygon.
Your fence-post error is that you are drawing points from 0 to 199. For the half-squircle you want to draw from 0 to 200. That's 201 points! The loss of one point means that you have a very slightly sloping line. The bottom lines slopes in tghe opposite direction from the top. That gives you a very then wedge shape, which you refer to as a triangle. I'm guessing that your triangle is not actually closed but like a slice from a pie but very then/sharp.
(The code below could be prettier and more compact. However it is often useful to break symmetrical problems into quadrants or octants. It would also be interesting to use an anngle to sweep out the polygon).
You actually want ONE polygon. The code should be something like:
int NQUADRANT = 100;
int NPOINTS = 4*NQUADRANT ; // closed polygon
double[] xpoints = new double[NPOINTS];
double[] ypoints = new double[NPOINTS];
Your squircle is at 100, 100 with radius 100. I have chosen different values here
to emphasize they aren't related. By using symbolic names you can easily vary them.
double xcenter = 500.0;
double ycentre = 200.0;
double radius = 100.;
double deltax = radius/(double) NQUADRANT;
// let's assume squircle is centered on 0,0 and add offsets later
// this code is NOT complete or correct but should show the way
// I might have time later
for (int i = 0; i < NPOINTS; i++) {
if (i < NQUADRANT) {
double x0 = -radius + i* deltax;
double y0 = fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else if (i < 2*NQUADRANT) {
double x0 = (i-NQUADRANT)* deltax;
double y0 = fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else if (i < 3*NQUADRANT) {
double x0 = (i-2*NQUADRANT)* deltax;
double y0 = -fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}else {
double x0 = -radius + (i-3*NQUADRANT)* deltax;
double y0 = -fourthRoot(radius, x0);
x[i] = x0+xcenter;
y[i] = y0+ycenter;
}
}
// draw single polygon
private double fourthRoot(double radius, double x) {
return Math.sqrt(Math.sqrt(radius*radius*radius*radius - x*x*x*x));
}
There is a javascript version here. You can view the source and "compare notes" to potentially see what you are doing wrong.
Ok, upon further investigation here is why you are getting the "triangle intersecting it". When you drawPolygon the points are drawn and the last point connects the first point, closing the points and making the polygon. Since you draw one half it is drawn (then connected to itself) and then the same happens for the other side.
As a test of this change your last couple lines to this:
for( int i = 0; i < yPoints.length; i++ ) {
g.drawString( "*", xPoints[ i ], yPoints[ i ] );
}
for( int i = 0; i < mypoints.length; i++ ) {
g.drawString( "*", xPoints[ i ], mypoints[ i ] );
}
// g.drawPolygon( xPoints, yPoints, xPoints.length );
// g.drawPolygon( xPoints, ( mypoints ), xPoints.length );
It is a little crude, but I think you'll get the point. There are lots of solutions out there, personally I would try using an array of the Point class and then sort it when done, but I don't know the specifics of what you can and can not do.
Wow, are you guys overthinking this, or what! Why not just use drawLine() four times to draw the straight parts of the rectangle and then use drawArc() to draw the rounded corners?

Categories