Rotating multiple sprites as one ( around same origin ) - java

I have array of sprites forming T shape, and I want to ratate them around the same origin, in my case box2D body origin, like this:
my shape is defined in matrix like this:
int array[][]= {{0,1,1,1,0},
{0,0,1,0,0},
{0,0,1,0,0},
{0,0,0,0,0},
{0,0,0,0,0}};
this is how I create the body:
public void setBody(int[][] blocks){
BodyDef def = new BodyDef();
def.type = BodyType.DynamicBody;
def.position.set(new Vector2(0 * WORLD_TO_BOX, 0 * WORLD_TO_BOX));
Body body = world.createBody(def);
body.setTransform(130*WORLD_TO_BOX, 200*WORLD_TO_BOX, -90*MathUtils.degreesToRadians);
for (int x = 0; x < 5; x++) { // HARDCODED 5
for (int y = 0; y < 5; y++) { // HARDCODED 5
if(blocks[x][y] == 1){
PolygonShape poly = new PolygonShape();
Vector2 v = new Vector2((x*size/BOX_TO_WORLD),(y*size/BOX_TO_WORLD));
poly.setAsBox(size/2 * WORLD_TO_BOX, size/2 * WORLD_TO_BOX, v, 0);
Sprite sprite = new Sprite(new Texture(Gdx.files.internal("data/block.png")));
sprite.setSize(size, size);
sprites.add(sprite);
orig.add(v);
body.createFixture(poly, 1);
poly.dispose();
}
}
}
this.body = body;
}
this is my render method:
public void draw(SpriteBatch batch){
for (int i = 0;i< this.body.getFixtureList().size;i++) {
Vector2 pos = this.body.getFixtureList().get(i).getBody().getPosition();
Sprite sprite = sprites.get(i);
sprite.setOrigin(this.body.getWorldCenter().x,this.body.getWorldCenter().y);
sprite.setPosition(pos.x*BOX_TO_WORLD+orig.get(i).x*32-16, pos.y*BOX_TO_WORLD+orig.get(i).y*32-16);
sprite.setRotation(this.body.getAngle()*MathUtils.radiansToDegrees);
sprite.draw(batch);
}
}

As you can see in your 'right' example in the diagram, the position of the sprites depends on the angle of the body, which you are not accounting for.
b2Vec2 pos = ...; // center of the sprite relative to body (local coords)
float ang = ...; // angle of the sprite relative to body (probably zero)
//need to rotate image local center by body angle
b2Rot rot( body->GetAngle() );
pos = b2Mul(rot, pos) + body->GetPosition();
ang += -body->GetAngle();
sprite.setRotation( ang * RADTODEG ); // RADTODEG = 57.295779513082320876f
sprite.setPosition( PTM * pos.x, PTM * -pos.y);
Prior to that, I have also done:
sf::FloatRect rect = sprite.getLocalBounds();
sprite.setOrigin( 0.5 * rect.width, 0.5 * rect.height );

The easiest way to do this is to create all the fixtures, remembering what their relative position is to the body. Create a sprite for each fixture and update them using the body->GetWorldPosition(fixture center) each time the physics updates. Finally, the rotation of the sprites is the same as the rotation of the body (excepting it is the negative of the angle).
For example, to create the body:
void MainScene::CreateBody()
{
Vec2 position(0,0);
// Create the body.
b2BodyDef bodyDef;
bodyDef.position = position;
bodyDef.type = b2_dynamicBody;
_body = _world->CreateBody(&bodyDef);
assert(_body != NULL);
// Now attach fixtures to the body.
FixtureDef fixtureDef;
PolygonShape polyShape;
vector<Vec2> vertices;
const float32 VERT_SCALE = .5;
fixtureDef.shape = &polyShape;
fixtureDef.density = 1.0;
fixtureDef.friction = 1.0;
fixtureDef.isSensor = false;
// Main Box
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// Down one
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,-3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,-3*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// Up One
vertices.clear();
vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// T Left Top
vertices.clear();
vertices.push_back(Vec2(-1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-3*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(-3*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(-1*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
// T Right Top
vertices.clear();
vertices.push_back(Vec2(3*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,3*VERT_SCALE));
vertices.push_back(Vec2(1*VERT_SCALE,1*VERT_SCALE));
vertices.push_back(Vec2(3*VERT_SCALE,1*VERT_SCALE));
polyShape.Set(&vertices[0],vertices.size());
_body->CreateFixture(&fixtureDef);
_fixturePositions.push_back(CalculateAverage(vertices));
_body->SetAngularVelocity(M_PI/8);
}
NOTE The CalculateAverage(...) function just finds the average of the vertices. For squares, it will be the center. I could manually set the centers, but I didn't want to make a simple math oopsie so I wrote a quick function to handle it.
Then create the sprites:
void MainScene::CreateSprites()
{
Viewport& vp = Viewport::Instance();
for(int idx = 0; idx < _fixturePositions.size(); idx++)
{
CCSprite* sprite = CCSprite::create("arrow.png");
sprite->setScale(1.0*vp.GetPTMRatio()/128);
_fixtureSprites.push_back(sprite);
addChild(sprite);
}
}
Then update the sprites after each physics update:
void MainScene::UpdateSprites()
{
for(int idx = 0; idx < _fixturePositions.size(); idx++)
{
CCPoint spritePosition = Viewport::Instance().Convert(_body->GetWorldPoint(_fixturePositions[idx]));
_fixtureSprites[idx]->setPosition(spritePosition);
float32 bodyAngle = _body->GetAngle();
bodyAngle = MathUtilities::AdjustAngle(bodyAngle);
_fixtureSprites[idx]->setRotation(-CC_RADIANS_TO_DEGREES(bodyAngle));
}
}
NOTE The viewport has a function Convert(..) that takes a Vec2 and converts it to a pixel position on the screen. AdjustAngle just puts the angle back in the range of [-pi,pi). All the rest should be fairly straightforward, but feel free to ask.
I have posted a solution on git hub here for Cocos2d-x (C++). Check out the code in MainScene.cpp.
And this is what it looks like on my simulator:
(Hopefully) Final Note: The implementation here uses a "Viewport" class to map between the Box2d world (meters) and the screen coordinates (pixels). One very useful consequence of this is that you can automatically adjust the sizes of sprites based on the size you want the bodies to be in meters and the size of the graphic in pixels. This is part of a larger set of components that I often use. You can find more information about them in this post.
Was this helpful?

Related

In ARCore, how do I best place a triangle in my world near a Pose, that I can use for ray intersection?

I'm working with ARCore in Android Studio using java and am trying to implement ray intersection with an object.
I started with Google's provided sample (as found here: https://developers.google.com/ar/develop/java/getting-started).
Upon touching the screen, a ray gets projected and when this ray touches a Plane, a PlaneAttachment (with an Anchor/a Pose) is created in the intersection point.
I would then like to put a 3D triangle in the world attached to this Pose.
At the moment I create my Triangle based on the Pose's translation, like this:
In HelloArActivity, during onDrawFrame(...)
//Code from sample, determining the hits on planes
MotionEvent tap = mQueuedSingleTaps.poll();
if (tap != null && frame.getTrackingState() == TrackingState.TRACKING) {
for (HitResult hit : frame.hitTest(tap)) {
// Check if any plane was hit, and if it was hit inside the plane polygon.
if (hit instanceof PlaneHitResult && ((PlaneHitResult) hit).isHitInPolygon()) {
mTouches.add(new PlaneAttachment(
((PlaneHitResult) hit).getPlane(),
mSession.addAnchor(hit.getHitPose())));
//creating a triangle in the world
Pose hitPose = hit.getHitPose();
float[] poseCoords = new float[3];
hitPose.getTranslation(poseCoords, 0);
mTriangle = new Triangle(poseCoords);
}
}
}
Note: I am aware that the triangle's coordinates should be updated every time the Pose's coordinates get updated. I left this out as it is not part of my issue.
Triangle class
public class Triangle {
public float[] v0;
public float[] v1;
public float[] v2;
//create triangle around a given coordinate
public Triangle(float[] poseCoords){
float x = poseCoords[0], y = poseCoords[1], z = poseCoords[2];
this.v0 = new float[]{x+0.0001f, y-0.0001f, z};
this.v1 = new float[]{x, y+ 0.0001f, z-0.0001f};
this.v2 = new float[]{x-0.0001f, y, z+ 0.0001f};
}
After this, upon tapping the screen again I create a ray projected from the tapped (x,y) part of the screen, using Ian M his code sample provided in the answer to this question: how to check ray intersection with object in ARCore
Ray Creation, in HelloArActivity
/**
* Returns a world coordinate frame ray for a screen point. The ray is
* defined using a 6-element float array containing the head location
* followed by a normalized direction vector.
*/
float[] screenPointToWorldRay(float xPx, float yPx, Frame frame) {
float[] points = new float[12]; // {clip query, camera query, camera origin}
// Set up the clip-space coordinates of our query point
// +x is right:
points[0] = 2.0f * xPx / mSurfaceView.getMeasuredWidth() - 1.0f;
// +y is up (android UI Y is down):
points[1] = 1.0f - 2.0f * yPx / mSurfaceView.getMeasuredHeight();
points[2] = 1.0f; // +z is forwards (remember clip, not camera)
points[3] = 1.0f; // w (homogenous coordinates)
float[] matrices = new float[32]; // {proj, inverse proj}
// If you'll be calling this several times per frame factor out
// the next two lines to run when Frame.isDisplayRotationChanged().
mSession.getProjectionMatrix(matrices, 0, 1.0f, 100.0f);
Matrix.invertM(matrices, 16, matrices, 0);
// Transform clip-space point to camera-space.
Matrix.multiplyMV(points, 4, matrices, 16, points, 0);
// points[4,5,6] is now a camera-space vector. Transform to world space to get a point
// along the ray.
float[] out = new float[6];
frame.getPose().transformPoint(points, 4, out, 3);
// use points[8,9,10] as a zero vector to get the ray head position in world space.
frame.getPose().transformPoint(points, 8, out, 0);
// normalize the direction vector:
float dx = out[3] - out[0];
float dy = out[4] - out[1];
float dz = out[5] - out[2];
float scale = 1.0f / (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
out[3] = dx * scale;
out[4] = dy * scale;
out[5] = dz * scale;
return out;
}
The result of this however is that, no matter where I tap the screen, it always counts as a hit (regardless of how much distance I add between the points, in Triangle's constructor).
I suspect this has to do with how a Pose is located in the world, and using the Pose's translation coordinates as a reference point for my triangle is not the way to go, so I'm looking for the correct way to do this, but any remarks regarding other parts of my method are welcome!
Also I have tested my method for ray-triangle intersection and I don't think it is the problem, but I'll include it here for completeness:
public Point3f intersectRayTriangle(CustomRay R, Triangle T) {
Point3f I = new Point3f();
Vector3f u, v, n;
Vector3f dir, w0, w;
float r, a, b;
u = new Vector3f(T.V1);
u.sub(new Point3f(T.V0));
v = new Vector3f(T.V2);
v.sub(new Point3f(T.V0));
n = new Vector3f(); // cross product
n.cross(u, v);
if (n.length() == 0) {
return null;
}
dir = new Vector3f(R.direction);
w0 = new Vector3f(R.origin);
w0.sub(new Point3f(T.V0));
a = -(new Vector3f(n).dot(w0));
b = new Vector3f(n).dot(dir);
if ((float)Math.abs(b) < SMALL_NUM) {
return null;
}
r = a / b;
if (r < 0.0) {
return null;
}
I = new Point3f(R.origin);
I.x += r * dir.x;
I.y += r * dir.y;
I.z += r * dir.z;
return I;
}
Thanks in advance!

Different Box2D bodies act differently and unexpectedly with same mass

I have a box2d body which is simply a rectangle (the spaceship).
This ship flies around, affected by the gravity of planets (static circle bodies) just fine.
I have tried changing the ship fixture shape to both (1) a triangle fixture and also (2) two rectangular fixtures put together. Both of these body configurations are causing problems.
Given the change in volume, to make up for the difference in mass I calculated the necessary new densities so that these bodies have the same mass as the original rectangle body. However when launching the ship with the same linear impulse as before, the triangular body and multi-rectangular body both act differently than the original body and shoot forward much faster.
I have tried further tweaking the ship density as well as the linear impulse and also the planet gravity to return the ship to a normal pace of movement,
however when doing that the ship starts to act weird and will do things like suddenly switch direction in mid-air even though there's no collision. This collision-looking event does not happen when the density/gravity/linear impulse are all the same as before, however in that situation the ship is moving too fast for my needs.
Basically I don't know why these bodies are acting differently when there is no change in mass or anything besides shape and size. There's no linear damping or collisions happening. I don't know what else could possibly be affecting the ship.
Any help or ideas is greatly appreciated.
Here is the code that I believe is relevant:
public void createShipBody() {
density = 0.05f; //normal rectangle
//density = 0.06666667f; //density for the two rectangles together
restitution = 1.0f;
bodyDef.type = BodyDef.BodyType.DynamicBody;
setBodyDefPosition(bodyDef);
body = GameCore.world.createBody(bodyDef);
setShipShapeAndFixture();
}
// For with the original rectangle
private void setShipShapeAndFixture() {
PolygonShape shape = new PolygonShape();
shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 2));
createFixtureDef(shape);
shape.dispose();
}
// For with triangle fixture
private void setShipShapeAndFixture() {
Vector2[] vertices = new Vector2[3];
vertices[0] = new Vector2(0, 0);
vertices[1] = new Vector2(Utility.pixelsToMeters(bodyWidth), 0);
vertices[2] = new Vector2(Utility.pixelsToMeters(bodyWidth/2), Utility.pixelsToMeters(bodyHeight));
shape.set(vertices);
createFixtureDef(shape);
shape.dispose();
}
// For multi-rectangle body
private void setShipShapeAndFixture() {
PolygonShape shape = new PolygonShape();
shape.setAsBox(Utility.pixelsToMeters(bodyWidth / 2), Utility.pixelsToMeters(bodyHeight / 4));
PolygonShape shape2 = new PolygonShape();
shape2.setAsBox(Utility.pixelsToMeters(bodyWidth / 4), Utility.pixelsToMeters(bodyHeight / 4), new Vector2(0, Utility.pixelsToMeters(bodyHeight/2)), 0);
createShipMultiFixtureDef(shape, shape2);
shape.dispose();
shape2.dispose();
}
private void createFixtureDef(PolygonShape shape) {
FixtureDef polygonFixtureDef = new FixtureDef();
polygonFixtureDef.shape = shape;
polygonFixtureDef.density = density;
polygonFixtureDef.restitution = restitution;
body.createFixture(polygonFixtureDef);
}
private void createShipMultiFixtureDef(PolygonShape shape, PolygonShape shape2) {
FixtureDef polygonFixtureDef = new FixtureDef();
polygonFixtureDef.shape = shape;
polygonFixtureDef.density = density;
polygonFixtureDef.restitution = restitution;
FixtureDef polygonFixtureDef2 = new FixtureDef();
polygonFixtureDef2.shape = shape2;
polygonFixtureDef2.density = density;
polygonFixtureDef2.restitution = restitution;
body.createFixture(polygonFixtureDef);
body.createFixture(polygonFixtureDef2);
}
/**
* This is inside the Ship class
* #param x From world center of release
* #param y From world center of release
* #param distance The capped distance of release from shipCenter, to determine force of impulse
*/
protected void applyLinearImpulse(float x, float y, float distance, float maxDistance) {
float deltaX = x - getXinPixels();
float deltaY = y - getYinPixels();
float scale = 0.8f; // Have tried playing around with this with different bodies
float force = scale * (distance/maxDistance);
float angle = (float) Math.atan2(deltaY, deltaX);
bodyWrapper.body.applyLinearImpulse(new Vector2((float) Math.cos(angle) * force,
(float) Math.sin(angle) * force), getWorldCenter(), true);
}
// This is called on each planet every game update
protected void applyGravity() {
for (SpaceObject spaceObject:spaceObjects) {
float scalar = 2.334f;
if(spaceObject instanceof Ship) {
if (gameCore.shipInMotion) {
scalar = 2f; //Have tried playng with this for different bodies
}
else {
continue; //No gravity to ship until it's launched
}
}
Vector2 objectWorldCenter = spaceObject.getWorldCenter();
Vector2 planetWorldCenter = getWorldCenter();
float planetDiameter = Utility.pixelsToMeters(getWidth());
float distance = Utility.distance(planetWorldCenter.x, planetWorldCenter.y, objectWorldCenter.x, objectWorldCenter.y);
float xDistance = planetWorldCenter.x - objectWorldCenter.x;
float yDistance = planetWorldCenter.y - objectWorldCenter.y;
float x = (float) ((xDistance * planetDiameter * scalar) / (distance*distance));
float y = (float) ((yDistance * planetDiameter * scalar) / (distance*distance));
Vector2 gravity = new Vector2(x, y);
spaceObject.bodyWrapper.body.applyForceToCenter(gravity, true);
}
}

How to construct and draw a nice rope with box2d

I created a rope in box2d with RevoluteJoint and a RopeJoint but I have several problems with it:
From time to time, the last segment rotates and it looks like it was disconnected from the rope.
How to draw this thing? I create a texture with the size of each link. If the rope isn't moving it looks good, but as soon as the rope moves and the different links start to rotate slightly, you see gaps between the links.
Code:
private void createChain(World world, Body anchorBody) {
Body previousBody = anchorBody;
FixtureDef fixtureDef = new FixtureDef();
PolygonShape robeLinkShape = new PolygonShape();
robeLinkShape.setAsBox(4 / PPM, 8 / PPM);
fixtureDef.shape = robeLinkShape;
fixtureDef.density = 0.1f;
// fixtureDef.friction = 1.0f;
fixtureDef.restitution = 0.1f;
fixtureDef.filter.maskBits = Box2DConst.BIT_PLAYER;
fixtureDef.filter.categoryBits = Box2DConst.BIT_GROUND;
float mapX = anchorBody.getPosition().x * PPM;
float mapY = anchorBody.getPosition().y * PPM;
BodyDef bodyDef = new BodyDef();
bodyDef.angularDamping = 1.0f;
bodyDef.linearDamping = 1.0f;
//create rope
for (int i = 0; i < 10; i++) {
Float robeX = mapX / PPM;
Float robeY = (mapY - (i * 16)) / PPM;
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(robeX, robeY);
final Body link = world.createBody(bodyDef);
link.createFixture(fixtureDef);
RevoluteJointDef jointDef = new RevoluteJointDef();
jointDef.initialize(previousBody, link, new Vector2(robeX, robeY));
//don't need the rope to collide itself
jointDef.collideConnected = false;
jointDef.enableLimit = false;
// because we don't collide with other bodies in the rope, limit rotation to keep the rope bodies from rotating too much.
jointDef.lowerAngle = -5.0f * MathUtils.degreesToRadians;
jointDef.upperAngle = 5.0f * MathUtils.degreesToRadians;
world.createJoint(jointDef);
links.add(link);
previousBody = link;
}
RopeJointDef ropeJointDef = new RopeJointDef();
ropeJointDef.localAnchorB.set(0, 0);
ropeJointDef.maxLength = 90.0f;
ropeJointDef.bodyB = previousBody;
ropeJointDef.bodyA = links.get(0);
ropeJointDef.collideConnected = false;
world.createJoint(ropeJointDef);
}
public void draw(final SpriteBatch batch) {
Texture texture = FipiGame.res.get("rope");
batch.begin();
for (Body link : links) {
float x = (link.getPosition().x * PPM) - 4;
float y = (link.getPosition().y * PPM) - 8;
float angleDeg = MathUtils.radiansToDegrees * link.getAngle();
batch.draw(texture, x, y, 0, 0, texture.getWidth(), texture.getHeight(), 1f, 1f, angleDeg, 0, 0,
texture.getWidth(), texture.getHeight(), false, false);
}
batch.end();
}
Instead of drawing based on body positions and rotations: Create a set of points by looping through the revolute joint positions (midpoint of anchorA and anchorB in world space). Then draw your sprites so they connect those positions. This will be somewhat inaccurate in that it won't perfectly line up with the positions of the rigid bodies, but it should look all right.

How do I initiate particles to grow from anywhere on stage upon mouseClick?

I want to be able to create new particles from wherever I click on stage. I'm just stuck on adding the mouse portion and I've tried to add/pass parameters and I always get errors while I try setting the parameters. Any suggestions?
This is my current code:
float parSpeed = 1; //speed of particles
int nParticles = 1000; //# of particles
Particle[] particles;
void setup() {
size(700,700); //size of image (8.5 x 11 # 300px) is 3300,2550)
frameRate(60); //framerate of stage
background(0); //color of background
particles = new Particle[nParticles];
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i] = new Particle();
}
}
void draw() {
fill(0,0,0,5); //5 is Alpha
rect(0,0,width,height); //color of rectangle on top?
translate(width/2, height/2); //starting point of particles
//start particle array
for(int i=0; i<nParticles; i++) {
particles[i].update();
particles[i].show();
}
}
//Particle Class
class Particle {
PVector pos; //position
float angle; //angle
float dRange; //diameter range
float dAngle; //beginning angle?
color c; //color
Particle() {
pos = new PVector(0,0);//new position for the particles.
angle = 1; //controls randomization of direction in position when multiplied
dRange = 0.01; // how big of a circle shold the particles rotate on
dAngle = 0.15; // -- maximum angle when starting
c = color(0,0,random(100, 255)); //set color to random blue
}
void update() {
float cor = .25*dRange*atan(angle)/PI;
float randNum = (random(2)-1)*dRange-cor; //Random number from (-dRange, dRange)
dAngle+=randNum; //We don't change the angle directly
//but its differential - source of the smoothness!
angle+=dAngle; //new angle is angle+dAngle -- change angle each frame
pos.x+=parSpeed*cos(angle);//random direction for X axis multiplied by speed
pos.y+=parSpeed*sin(angle);//rabdin durectuib for y axis multiplied by speed
}
void show() {
fill(c); //fill in the random color
noStroke(); //no stroke
ellipse(pos.x,pos.y,10,10); //make the shape
smooth(); //smooth out the animation
}
}
void keyPressed() {
print("pressed " + int(key) + " " + keyCode);
if (key == 's' || key == 'S'){
saveFrame("image-##.png");
}
}
void mouseReleased() {
print("mouse has been clicked!");
}
Overwrite the mouseReleased() method:
In there you'll need to:
capture the position of the mouse
create the new particle
update the position of the newly created particle.
add it to the array (the particle system)
This may look simple but you'll have to keep in mind an array cannot change sizes. I would advise that you create a ParticleSystem class that takes care of adding and removing particles from the system.
Edit: You might want to consider using an ArrayList instead of an Array of Particles. Have a look at this
In pseudo code this would look like this:
void mouseReleased() {
int particleX = mouseX;
int particleY = mouseY;
Particle P = new Particle();
P.setPos ( new PVector ( particleX, particleY ) ); // this needs to be implemented
ParticleSystem.add ( P ); // this needs to be implemented
}
I hope this will be a good start.
AH

Flipping a polygon that contains many polygons to create an upside down mirror of everything

I have created a polygon with 6 vertices. Lets call this one, outside polygon. Inside the outside polygon I created smaller polygons. I want to flip all of it vertically one point at the time.
I know the vertices of the outside polygon and I have an ArrayList<Polygon> for the inner polygons. I was able to flip the outside polygon. but how do I flipped the inner polygons keeping their relative positions in the new one? I know the center of the outside polygon and the flipped version.
correction: I needed to flip horizontal.
I flipped the outer polygon (triangle shape), and I was able to move the inner polygons. but the distance is incorrect. this is a picture of what I have done,
(https://docs.google.com/drawings/d/1cPYJqxTWVu5gSHFQyHxHWSTysNzxJvNuJIwsgCQInfc/edit) https://docs.google.com/drawings/d/1cPYJqxTWVu5gSHFQyHxHWSTysNzxJvNuJIwsgCQInfc/edit
I tried this:
for (Polygon p : polygonList) {
Polygon tempP = new Polygon(p.xpoints, p.ypoints, p.npoints);
firstPointinPolygon = new Point(p.xpoints[0], p.ypoints[0]);
// find frist point in the polygon
float adjacent = (float) firstPointinPolygon.getX() - 400;
float opposite = (float) firstPointinPolygon.getY() - 400;
float hypotenuse = (float) Math.sqrt(opposite * opposite + adjacent * adjacent);
float cosine = adjacent / hypotenuse;
float sine = opposite / hypotenuse;
float endX = 400 * cosine;
float endY = 400 * sine;
float endXDelta =400-endX;
float endYDelta=400-endY;
Polygon pM = move(tempP, endX, endY);
polygonListMirror.add(pM);
tempP = new Polygon();
}
public Polygon move(Polygon p, double xMove, double yMove) {
// Change the values of the points for the Polygon
for (int i = 0; i < p.xpoints.length; i++) {
p.xpoints[i] += xMove;
p.ypoints[i] += yMove;
}
return p;
}
But did not get the result, I expected. What am I doing wrong? The end result should be like the picture in this link:
(https://docs.google.com/drawings/d/1vYdWkCelWW1_NUypNhtmckBYfEMzCf6bMVtoB-AyPkw/edit) https://docs.google.com/drawings/d/1vYdWkCelWW1_NUypNhtmckBYfEMzCf6bMVtoB-AyPkw/edit
I think something like this will do it:
Polygon outerPolygon, oldOuterPolygon;
ArrayList<Polygon> innerPolygons;
// set up objects
for (Polygon polygon: innerPolygons)
{
for (int i = 0; i < polygon.ypoints.length; i++)
{
polygon.ypoints[i] = center(outerPolygon) - polygon.ypoints[i] + center(oldOuterPolygon);
}
}
If you just to flip it vertically where it stands, such that the y-coordinate of top-most and bottom-most points just switch around, center for both should be the same (thus you can just say 2*center).
I'm pretty sure you can replace center(outerPolygon) and center(oldOuterPolygon) with any point from the applicable Polygon, as long as both use the same point.

Categories

Resources