private void drawFeatheredFullLine( Vector2 a, Vector2 b, float width, float feather, Color color) { checkMaxVerts(3 * 6); // Calculate the normal that defines the center rectangle norm.set(b); norm.sub(a); norm.rotate(90); norm.setLength(width / 2); // Scale to line width // Calculate the normal that defines feathering feath.set(norm); feath.setLength(feather / 2); zeroAlpha.set(color); zeroAlpha.a = 0; // ORDER OF RENDERING // 1 2 // top feather // 3 4 // center // 5 6 // bottom feather // 7 8 // Top feather tL.set(a).add(norm).add(feath); tR.set(b).add(norm).add(feath); bL.set(a).add(norm); bR.set(b).add(norm); // Draw it // Top feather (1-2-3) uncheckedTriangle(tL.x, tL.y, tR.x, tR.y, bL.x, bL.y, zeroAlpha, zeroAlpha, color); uncheckedTriangle(tR.x, tR.y, bL.x, bL.y, bR.x, bR.y, zeroAlpha, color, color); // Center line tL.set(a).add(norm); tR.set(b).add(norm); bL.set(a).sub(norm); bR.set(b).sub(norm); // Draw it uncheckedTriangle(tL.x, tL.y, tR.x, tR.y, bL.x, bL.y, color, color, color); uncheckedTriangle(tR.x, tR.y, bL.x, bL.y, bR.x, bR.y, color, color, color); // Bottom feather tL.set(a).sub(norm); tR.set(b).sub(norm); bL.set(a).sub(norm).sub(feath); bR.set(b).sub(norm).sub(feath); // Draw it uncheckedTriangle(tL.x, tL.y, tR.x, tR.y, bL.x, bL.y, color, color, zeroAlpha); uncheckedTriangle(tR.x, tR.y, bL.x, bL.y, bR.x, bR.y, color, zeroAlpha, zeroAlpha); }
public void drawArrow( Vector2 a, Vector2 b, float width, float feather, float headDist, float headWidth, Color color) { // Firstly, draw the body of the arrow. B is the front. drawLine(a, b, width, feather, color); // Get the direction vector a->b dir.set(a); dir.sub(b); dir.scl(1 / dir.len()); // Get the point down the line that the arrow head lines get to d.set(dir); d.scl(headDist); d.add(b); // Now, move d out to the sides amount.set(dir); amount.rotate(90); amount.scl(headWidth); right.set(d).add(amount); left.set(d).sub(amount); // Draw the arrow heads to not-quite-b to make it prettier c.set(b); c.sub(dir.scl(-width * 0.2f)); drawLine(c, left, width, feather, color); drawLine(c, right, width, feather, color); }
@Override public void update() { if (!isActive()) return; posCpy.set(GameModel.getPlayer().position); diffToPlayer.set(posCpy.sub(position)); float wantedAngle = MathUtils.atan2(diffToPlayer.y, diffToPlayer.x); /* ^ 3,14 <--- |----> 0 */ if (direction == AbstractMap.N && (wantedAngle > MathUtils.PI || wantedAngle < 0)) return; else if (direction == AbstractMap.S && wantedAngle > 0) return; else if (direction == AbstractMap.W && (!(wantedAngle < MathUtils.PI / 2f && wantedAngle > -MathUtils.PI / 2f))) return; else if (direction == AbstractMap.E && (!(wantedAngle > MathUtils.PI / 2f || wantedAngle < -MathUtils.PI / 2f))) return; body.setTransform(position.x, position.y, wantedAngle); if (diffToPlayer.len() < Config.getDimensions().WORLD_WIDTH / 2f) if (MathUtils.random() < (type == CANNON_TYPE.SINGLE ? Config.BULLET_RATE_LOW : Config.BULLET_RATE_MEDIUM)) { float angle = body.getAngle() * MathUtils.radiansToDegrees; origin.set(position).add(diffToPlayer.scl(.1f)); posCpy.set(GameModel.getPlayer().position); if (type == CANNON_TYPE.SINGLE) { weapon.fire1(origin, posCpy.rotate(MathUtils.random(-1, 1))); createGunSmoke(angle); } else if (type == CANNON_TYPE.DOUBLE) { weapon.fire1(origin, posCpy.rotate(MathUtils.random(-1, 1))); weapon.fire2(origin, posCpy.rotate(MathUtils.random(-1, 1))); } } }
public void add(float centreX, float centreY) { positionEmiter.rotate(EndlessMode.delta15 * speed); tmp.x = (centreX - SparklesColorOverTime.HALF_HEIGHT) + positionEmiter.x; tmp.y = centreY + positionEmiter.y; angle = Physic.getAngleWithPlayer(tmp, SparklesColorOverTime.HALF_HEIGHT, 0); angle += 110 - (Player.shield * 10); SparklesColorOverTimeWide.add( (centreX - SparklesColorOverTime.HALF_HEIGHT) + positionEmiter.x, centreY + positionEmiter.y, angle, PrecalculatedParticles.colorsOverTimeBlue, Particles.COLOR_OVER_TIME_FOREGROUND, 1); SparklesColorOverTimeWide.add( (centreX - SparklesColorOverTime.HALF_HEIGHT) - positionEmiter.x, centreY - positionEmiter.y, angle, PrecalculatedParticles.colorsOverTimeYellowToGreen, Particles.COLOR_OVER_TIME_FOREGROUND, 1); if (!EndlessMode.triggerStop) { SparklesColorOverTimeWide.add( (centreX - SparklesColorOverTime.HALF_HEIGHT) + positionEmiter.x * 0.9f, centreY - positionEmiter.y * 0.9f, -angle, PrecalculatedParticles.colorsOverTimeYellowToGreen, Particles.COLOR_OVER_TIME_FOREGROUND, 1); SparklesColorOverTimeWide.add( (centreX - SparklesColorOverTime.HALF_HEIGHT) - positionEmiter.x * 0.9f, centreY + positionEmiter.y * 0.9f, -angle, PrecalculatedParticles.colorsOverTimeBlue, Particles.COLOR_OVER_TIME_FOREGROUND, 1); } }
public void drawLine(Vector2 a, Vector2 b, float width, Color color) { setType(GL20.GL_TRIANGLES); // Calculate the normal that defines the center rectangle norm.set(b); norm.sub(a); norm.rotate(90); norm.setLength(width / 2); // Scale to line width // 1 2 // top feather // 3 4 // Top feather tL.set(a).add(norm); tR.set(b).add(norm); bL.set(a).sub(norm); bR.set(b).sub(norm); uncheckedTriangle(tL.x, tL.y, tR.x, tR.y, bL.x, bL.y, color, color, color); uncheckedTriangle(tR.x, tR.y, bL.x, bL.y, bR.x, bR.y, color, color, color); }
public Beaver(World world, Island island) { this.island = island; float scale = 2.0f; float radius = 1.0f; BodyDef bd = new BodyDef(); bd.type = BodyDef.BodyType.DynamicBody; Vector2 pos = island.physicsBody.getPosition(); ang = island.physicsBody.getAngle(); float islandW = island.getPhysicsWidth(); float islandH = island.getPhysicsHeight(); Vector2 off = new Vector2(islandW * MathUtils.random(0.3f, 0.6f), islandH); off.rotate(MathUtils.radiansToDegrees * ang); bd.position.set(new Vector2(pos.x + off.x, pos.y + off.y)); bd.angle = ang; off.set(islandW * 0.075f, islandH); off.rotate(MathUtils.radiansToDegrees * ang); Vector2 rightEdge = new Vector2(pos.x + off.x, pos.y + off.y).scl(Mane.PTM_RATIO); off.set(islandW * 0.85f, islandH); off.rotate(MathUtils.radiansToDegrees * ang); Vector2 leftEdge = new Vector2(pos.x + off.x, pos.y + off.y).scl(Mane.PTM_RATIO); float speed = MathUtils.random(1.0f, 3.0f); addAction( Actions.delay( MathUtils.random(0.0f, 1.0f), Actions.forever( Actions.sequence( Actions.moveTo(rightEdge.x, rightEdge.y, speed), Actions.moveTo(leftEdge.x, leftEdge.y, speed))))); bd.linearDamping = 0.2f; Body body = world.createBody(bd); FixtureDef fd = new FixtureDef(); fd.density = 1.0f; fd.filter.categoryBits = Collision.BEAVER; fd.filter.maskBits = Collision.SHARK; fd.restitution = 0.0f; fd.friction = 0.0f; fd.isSensor = true; CircleShape cs = new CircleShape(); cs.setRadius(radius); cs.setPosition(new Vector2(radius, radius)); fd.shape = cs; body.createFixture(fd); cs.dispose(); super.initPhysicsBody(body); setSize(scale * Mane.PTM_RATIO, scale * Mane.PTM_RATIO); setOrigin(0.0f, 0.0f); }
/** * Creates an array of PolySpatials based on fixture information from the scene. Note that * fixtures create aligned textures. * * @param scene */ private void createPolySpatialsFromRubeFixtures(RubeScene scene) { Array<Body> bodies = scene.getBodies(); EarClippingTriangulator ect = new EarClippingTriangulator(); if ((bodies != null) && (bodies.size > 0)) { polySpatials = new Array<PolySpatial>(); Vector2 bodyPos = new Vector2(); // for each body in the scene... for (int i = 0; i < bodies.size; i++) { Body body = bodies.get(i); bodyPos.set(body.getPosition()); Array<Fixture> fixtures = body.getFixtureList(); if ((fixtures != null) && (fixtures.size > 0)) { // for each fixture on the body... for (int j = 0; j < fixtures.size; j++) { Fixture fixture = fixtures.get(j); String textureName = (String) scene.getCustom(fixture, "TextureMask", null); if (textureName != null) { String textureFileName = "data/" + textureName; Texture texture = textureMap.get(textureFileName); TextureRegion textureRegion = null; if (texture == null) { texture = new Texture(textureFileName); texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat); textureMap.put(textureFileName, texture); textureRegion = new TextureRegion(texture); textureRegionMap.put(texture, textureRegion); } else { textureRegion = textureRegionMap.get(texture); } // only handle polygons at this point -- no chain, edge, or circle fixtures. if (fixture.getType() == Shape.Type.Polygon) { PolygonShape shape = (PolygonShape) fixture.getShape(); int vertexCount = shape.getVertexCount(); float[] vertices = new float[vertexCount * 2]; // static bodies are texture aligned and do not get drawn based off of the related // body. if (body.getType() == BodyType.StaticBody) { for (int k = 0; k < vertexCount; k++) { shape.getVertex(k, mTmp); mTmp.rotate(body.getAngle() * MathUtils.radiansToDegrees); mTmp.add( bodyPos); // convert local coordinates to world coordinates to that textures // are // aligned vertices[k * 2] = mTmp.x * PolySpatial.PIXELS_PER_METER; vertices[k * 2 + 1] = mTmp.y * PolySpatial.PIXELS_PER_METER; } short[] triangleIndices = ect.computeTriangles(vertices).toArray(); PolygonRegion region = new PolygonRegion(textureRegion, vertices, triangleIndices); PolySpatial spatial = new PolySpatial(region, Color.WHITE); polySpatials.add(spatial); } else { // all other fixtures are aligned based on their associated body. for (int k = 0; k < vertexCount; k++) { shape.getVertex(k, mTmp); vertices[k * 2] = mTmp.x * PolySpatial.PIXELS_PER_METER; vertices[k * 2 + 1] = mTmp.y * PolySpatial.PIXELS_PER_METER; } short[] triangleIndices = ect.computeTriangles(vertices).toArray(); PolygonRegion region = new PolygonRegion(textureRegion, vertices, triangleIndices); PolySpatial spatial = new PolySpatial(region, body, Color.WHITE); polySpatials.add(spatial); } } else if (fixture.getType() == Shape.Type.Circle) { CircleShape shape = (CircleShape) fixture.getShape(); float radius = shape.getRadius(); int vertexCount = (int) (12f * radius); float[] vertices = new float[vertexCount * 2]; System.out.println("SpatialFactory: radius: " + radius); if (body.getType() == BodyType.StaticBody) { mTmp3.set(shape.getPosition()); for (int k = 0; k < vertexCount; k++) { // set the initial position mTmp.set(radius, 0); // rotate it by 1/vertexCount * k mTmp.rotate(360f * k / vertexCount); // add it to the position. mTmp.rotate(body.getAngle() * MathUtils.radiansToDegrees); mTmp.add(mTmp3); mTmp.add( bodyPos); // convert local coordinates to world coordinates to that textures // are aligned vertices[k * 2] = mTmp.x * PolySpatial.PIXELS_PER_METER; vertices[k * 2 + 1] = mTmp.y * PolySpatial.PIXELS_PER_METER; } short[] triangleIndices = ect.computeTriangles(vertices).toArray(); PolygonRegion region = new PolygonRegion(textureRegion, vertices, triangleIndices); PolySpatial spatial = new PolySpatial(region, Color.WHITE); polySpatials.add(spatial); } else { mTmp3.set(shape.getPosition()); for (int k = 0; k < vertexCount; k++) { // set the initial position mTmp.set(radius, 0); // rotate it by 1/vertexCount * k mTmp.rotate(360f * k / vertexCount); // add it to the position. mTmp.add(mTmp3); vertices[k * 2] = mTmp.x * PolySpatial.PIXELS_PER_METER; vertices[k * 2 + 1] = mTmp.y * PolySpatial.PIXELS_PER_METER; } short[] triangleIndices = ect.computeTriangles(vertices).toArray(); PolygonRegion region = new PolygonRegion(textureRegion, vertices, triangleIndices); PolySpatial spatial = new PolySpatial(region, body, Color.WHITE); polySpatials.add(spatial); } } } } } } } }
private Vector2 getLocalPosition() { absolutePosition.set(localPosition.x, localPosition.y); absolutePosition.rotate(parent.getAngle()); absolutePosition.set(absolutePosition.x + parent.getX(), absolutePosition.y + parent.getY()); return absolutePosition; }
@Override public float projectY(float x, float y) { tmp.set(x - getX(), y - getY()); tmp.rotate(-getAngle()); return tmp.y; }
@Override public void update(BaseObject parent) { Vector2f acceleration = ((GameObject) parent).getAcceleration(); acceleration.set(0, 0); if (sys.keyboard.isKeyPressed(ButtonActions.MOVE_UP)) { acceleration.y = ACCELERATION; } if (sys.keyboard.isKeyPressed(ButtonActions.MOVE_DOWN)) { acceleration.y = -ACCELERATION; } if (sys.keyboard.isKeyPressed(ButtonActions.MOVE_LEFT)) { acceleration.x = -ACCELERATION; } if (sys.keyboard.isKeyPressed(ButtonActions.MOVE_RIGHT)) { acceleration.x = ACCELERATION; } if (sys.currentTime - lastTime < fireRate) { return; } // FIXME I really shouldn't be using hardcoded values to figure out where to // shoot the bullets from. // FIXME I also REALLY REALLY need to get my vectors sorted out so that I don't have to // resort to this ugliness. bulletVelocity.set( ((GameObject) parent).getVelocity().x, ((GameObject) parent).getVelocity().x); bulletPosition.set(16f, 0f); if (sys.keyboard.isKeyPressed(ButtonActions.FIRE_LEFT)) { bulletVelocity.x -= BULLET_VELOCITY; bulletPosition.y = 16f; bulletPosition.x = 0f; } if (sys.keyboard.isKeyPressed(ButtonActions.FIRE_RIGHT)) { bulletVelocity.x += BULLET_VELOCITY; bulletPosition.y = 16f; bulletPosition.x = 32f; } if (sys.keyboard.isKeyPressed(ButtonActions.FIRE_UP)) { bulletVelocity.y += BULLET_VELOCITY; bulletPosition.y = 32f; } if (sys.keyboard.isKeyPressed(ButtonActions.FIRE_DOWN)) { bulletVelocity.y -= BULLET_VELOCITY; bulletPosition.y = 0f; } if (bulletVelocity.x != 0f || bulletVelocity.y != 0f) { Vector2f position = ((GameObject) parent).getPosition(); bulletPosition.x += position.x; bulletPosition.y += position.y; GameObject bullet = bulletPool.obtain(); if (bullet != null) { bullet.setPosition(bulletPosition.x, bulletPosition.y); bulletVelocity.rotate(bulletCounter * spreadDegree); bullet.setVelocity(bulletVelocity.x, bulletVelocity.y); sys.manager.add(bullet); if (bulletCounter == spreadCount / 2) { bulletCounter = -bulletCounter; } else { bulletCounter++; } } } lastTime = sys.currentTime; }
public void transformVectorToParent(Vector2 vector) { vector.rotate(this.getRotation()); }
/** Sets position, rotation, scale and origin in actor to meet the 3 given points */ public static void applyTransformation( Actor actor, Vector2 origin, Vector2 tangent, Vector2 normal) { /* * We are going to calculate the affine transformation for the actor to * fit the bounds represented by the handles. The affine transformation * is defined as follows: */ // |a b tx| // |c d ty|=|Translation Matrix| x |Scale Matrix| x |Rotation // Matrix| // |0 0 1 | /* * More info about affine transformations: * https://people.gnome.org/~mathieu * /libart/libart-affine-transformation-matrices.html, To obtain the * matrix, we want to resolve the following equation system: */ // | a b tx| |0| |o.x| // | c d ty|*|0|=|o.y| // | 0 0 1 | |1| | 1 | // // | a b tx| |w| |t.x| // | c d ty|*|0|=|t.y| // | 0 0 1 | |1| | 1 | // // | a b tx| |0| |n.x| // | c d ty|*|h|=|n.y| // | 0 0 1 | |1| | 1 | /* * where o is handles[0] (origin), t is handles[2] (tangent) and n is * handles[6] (normal), w is actor.getWidth() and h is * actor.getHeight(). * * This matrix defines that the 3 points defining actor bounds are * transformed to the 3 points defining modifier bounds. E.g., we want * that actor origin (0,0) is transformed to (handles[0].x, * handles[0].y), and that is expressed in the first equation. * * Resolving these equations is obtained: */ // a = (t.x - o.y) / w // b = (t.y - o.y) / w // c = (n.x - o.x) / h // d = (n.y - o.y) / h /* * Values for translation, scale and rotation contained by the matrix * can be obtained directly making operations over a, b, c and d: */ // tx = o.x // ty = o.y // sx = sqrt(a^2+b^2) // sy = sqrt(c^2+d^2) // rotation = atan(c/d) // or // rotation = atan(-b/a) /* * Rotation can give two different values (this happens when there is * more than one way of obtaining the same transformation). To avoid * that, we ignore the rotation to obtain the final values. */ Vector2 tmp1 = Pools.obtain(Vector2.class); Vector2 tmp2 = Pools.obtain(Vector2.class); Vector2 tmp3 = Pools.obtain(Vector2.class); Vector2 tmp4 = Pools.obtain(Vector2.class); Vector2 tmp5 = Pools.obtain(Vector2.class); Vector2 o = tmp1.set(origin.x, origin.y); Vector2 t = tmp2.set(tangent.x, tangent.y); Vector2 n = tmp3.set(normal.x, normal.y); Vector2 vt = tmp4.set(t).sub(o); Vector2 vn = tmp5.set(n).sub(o); // Ignore rotation float rotation = actor.getRotation(); vt.rotate(-rotation); vn.rotate(-rotation); t.set(vt).add(o); n.set(vn).add(o); Vector2 bottomLeft = Pools.obtain(Vector2.class); Vector2 size = Pools.obtain(Vector2.class); calculateBounds(actor, bottomLeft, size); float a = (t.x - o.x) / size.x; float c = (t.y - o.y) / size.x; float b = (n.x - o.x) / size.y; float d = (n.y - o.y) / size.y; Pools.free(tmp1); Pools.free(tmp2); Pools.free(tmp3); Pools.free(tmp4); Pools.free(tmp5); Pools.free(bottomLeft); Pools.free(size); // Math.sqrt gives a positive value, but it also have a negatives. // The // signum is calculated computing the current rotation float signumX = vt.angle() > 90.0f && vt.angle() < 270.0f ? -1.0f : 1.0f; float signumY = vn.angle() > 180.0f ? -1.0f : 1.0f; float scaleX = (float) Math.sqrt(a * a + b * b) * signumX; float scaleY = (float) Math.sqrt(c * c + d * d) * signumY; actor.setScale(scaleX, scaleY); /* * To obtain the correct translation value we need to subtract the * amount of translation due to the origin. */ tmpMatrix.setToTranslation(actor.getOriginX(), actor.getOriginY()); tmpMatrix.rotate(actor.getRotation()); tmpMatrix.scale(actor.getScaleX(), actor.getScaleY()); tmpMatrix.translate(-actor.getOriginX(), -actor.getOriginY()); /* * Now, the matrix has how much translation is due to the origin * involved in the rotation and scaling operations */ float x = o.x - tmpMatrix.getValues()[Matrix3.M02]; float y = o.y - tmpMatrix.getValues()[Matrix3.M12]; actor.setPosition(x, y); }