public void drawLineShapePart( Vector2 center, int verts, float innerPos, float outerPos, float rotation, Color innerCol, Color outerCol) { setType(GL20.GL_TRIANGLE_STRIP); n_verts = (verts + 1) * 2 + 2; checkMaxVerts(n_verts); a.set(CircleLogic.findPos(center, innerPos, 0 * (360f / verts) + rotation, 0f)); // We place the vertex twice at the start and at the end to ensure no crosover from the last // shape putVertex(a.x, a.y, innerCol); putVertex(a.x, a.y, innerCol); for (int i = 0; i < verts + 1; i++) { a.set(CircleLogic.findPos(center, outerPos, i * (360f / verts) + rotation, 0f)); putVertex(a.x, a.y, outerCol); a.set(CircleLogic.findPos(center, innerPos, i * (360f / verts) + rotation, 0f)); putVertex(a.x, a.y, innerCol); } putVertex(a.x, a.y, innerCol); }
public static boolean inLineOfSight(Vector2 p1, Vector2 p2, Polygon polygon, boolean obstacle) { tmp.set(p1); tmp2.set(p2); float verts[] = polygon.getTransformedVertices(); for (int i = 0; i < verts.length; i += 2) { if (lineSegmentsCross( tmp.x, tmp.y, tmp2.x, tmp2.y, verts[i], verts[i + 1], verts[(i + 2) % verts.length], verts[(i + 3) % verts.length])) return false; } tmp.add(tmp2); tmp.x /= 2; tmp.y /= 2; boolean result = PolygonUtils.isPointInside(polygon, tmp.x, tmp.y, !obstacle); return obstacle ? !result : result; }
private void drawCullingRectangles(ShapeRenderer shapeRenderer, Color color) { for (BoundingBox br : boundingBoxes) { Rectangle r = br.rectangle; Rectangle cullingArea = getCullingArea(tmpRectangle, r, angleRad, position, scale); shapeRenderer.set(ShapeRenderer.ShapeType.Filled); Color fillColor = tmpColor.set(color); fillColor.a *= 0.25f; shapeRenderer.setColor(fillColor); shapeRenderer.rect(cullingArea.x, cullingArea.y, cullingArea.width, cullingArea.height); tmp.set(r.x, r.y).rotateRad(angleRad).add(position); tmp1.set(r.x + r.width, r.y).rotateRad(angleRad).add(position); tmp2.set(r.x + r.width, r.y + r.height).rotateRad(angleRad).add(position); tmp3.set(r.x, r.y + r.height).rotateRad(angleRad).add(position); shapeRenderer.set(ShapeRenderer.ShapeType.Line); shapeRenderer.setColor(color); shapeRenderer.line(tmp, tmp1); shapeRenderer.line(tmp1, tmp2); shapeRenderer.line(tmp2, tmp3); shapeRenderer.line(tmp3, tmp); } }
/** * Determine if the requested line could be tacked on to the end of this line with no kinks or * gaps. If it can, the current LineSegment will be extended by the length of the passed * LineSegment. * * @param lineSegment * @return boolean true if line was extended, false if not. */ public boolean extendIfPossible(LineSegment lineSegment) { /** First, let's see if the slopes of the two segments are the same. */ double slope1 = Math.atan2(end.y - start.y, end.x - start.x); double slope2 = Math.atan2( lineSegment.end.y - lineSegment.start.y, lineSegment.end.x - lineSegment.start.x); if (Math.abs(slope1 - slope2) > 1e-9) { return false; } /** * Second, check if either end of this line segment is adjacent to the requested line segment. * So, 1 pixel away up through sqrt(2) away. * * <p>Whichever two points are within the right range will be "merged" so that the two outer * points will describe the line segment. */ if (start.dst(lineSegment.start) <= Math.sqrt(2) + 1e-9) { start.set(lineSegment.end); return true; } else if (end.dst(lineSegment.start) <= Math.sqrt(2) + 1e-9) { end.set(lineSegment.end); return true; } else if (end.dst(lineSegment.end) <= Math.sqrt(2) + 1e-9) { end.set(lineSegment.start); return true; } else if (start.dst(lineSegment.end) <= Math.sqrt(2) + 1e-9) { start.set(lineSegment.start); return true; } return false; }
private TextField findNextTextField( Array<Actor> actors, TextField best, Vector2 bestCoords, Vector2 currentCoords, boolean up) { for (int i = 0, n = actors.size; i < n; i++) { Actor actor = actors.get(i); if (actor == this) continue; if (actor instanceof TextField) { TextField textField = (TextField) actor; if (textField.isDisabled() || !textField.focusTraversal) continue; Vector2 actorCoords = actor.getParent().localToStageCoordinates(tmp3.set(actor.getX(), actor.getY())); if ((actorCoords.y < currentCoords.y || (actorCoords.y == currentCoords.y && actorCoords.x > currentCoords.x)) ^ up) { if (best == null || (actorCoords.y > bestCoords.y || (actorCoords.y == bestCoords.y && actorCoords.x < bestCoords.x)) ^ up) { best = (TextField) actor; bestCoords.set(actorCoords); } } } else if (actor instanceof Group) best = findNextTextField(((Group) actor).getChildren(), best, bestCoords, currentCoords, up); } return best; }
/** * Calculates the culling area of the bounding box after it has scaled, rotated and translates. * This bounding box contains a bunch of vertices. This way i don't have to merge hundreds of * vertices to get a reasonable culling area, just the four of the bounding box. */ private Rectangle getCullingArea( Rectangle cullingArea, Rectangle boundingBox, float rotation, Vector2 translation, float scale) { tmp.set(boundingBox.x, boundingBox.y).scl(scale).rotateRad(rotation).add(translation); cullingArea.set(tmp.x, tmp.y, 0, 0); tmp.set(boundingBox.x + boundingBox.width, boundingBox.y) .scl(scale) .rotateRad(rotation) .add(translation); cullingArea.merge(tmp); tmp.set(boundingBox.x + boundingBox.width, boundingBox.y + boundingBox.height) .scl(scale) .rotateRad(rotation) .add(translation); cullingArea.merge(tmp); tmp.set(boundingBox.x, boundingBox.y + boundingBox.height) .scl(scale) .rotateRad(rotation) .add(translation); cullingArea.merge(tmp); return cullingArea; }
public void actBehavior(float deltaTime) { Random rand = new Random(); switch (state) { case RESTING: if (stateTime > restTime) { state = MOVING; accel.x = rand.nextFloat() * 2 - 1; // -1 to 1 accel.y = rand.nextFloat() * 2 - 1; accel.nor().scl(ACCEL); stateTime = 0.0f; } else { // still resting... } break; case MOVING: if (stateTime > moveTime) { state = RESTING; accel.set(0, 0); velocity.set(0, 0); stateTime = 0.0f; } else { // still moving... // Continue accel'ing in current direction accel.set(velocity.x, velocity.y).nor().scl(ACCEL); } break; default: break; } stateTime += deltaTime; }
private void restart() { for (int i = 0; i < MAX_BALL_COUNT; i++) { float tx = rand.nextFloat() * 1.0f - 0.5f; float ty = WORLD_SIZE.y / 2 + BALL_SIZE.y * 5; float angle = rand.nextFloat() * MathUtils.PI * 2; ballModels[i].setActive(false); ballModels[i].setLinearVelocity(tmpVec.set(0, 0)); ballModels[i].setAngularVelocity(0); ballModels[i].setTransform(tmpVec.set(tx, ty), angle); } if (timer != null) timer.cancel(); timerBallIndex = 0; timer = new Timer(); timer.scheduleAtFixedRate( new TimerTask() { @Override public void run() { if (timerBallIndex < ballModels.length) { ballModels[timerBallIndex].setAwake(true); ballModels[timerBallIndex].setActive(true); timerBallIndex += 1; } else { timer.cancel(); } } }, 100, 100); }
/** * Calculate the bounds of the possible children of the given actor. If actor has no children, * then resultOrigin and resultSize are set to actor's bounds. */ public static void calculateBounds(Actor actor, Vector2 resultOrigin, Vector2 resultSize) { resultOrigin.set(0, 0); resultSize.set(actor.getWidth(), actor.getHeight()); if (actor instanceof Group && ((Group) actor).getChildren().size > 0) { calculateBounds(((Group) actor).getChildren(), resultOrigin, resultSize); } }
@Override public boolean onEnd( final Draggable draggable, final Actor actor, final float stageX, final float stageY) { if (actor == null || actor.getStage() == null) { return CANCEL; } final Actor overActor = actor.getStage().hit(stageX, stageY, true); if (overActor == null || overActor == actor) { return CANCEL; } else if (overActor.isAscendantOf(actor)) { final DragPane dragPane = getDragPane(actor); if (dragPane != null && dragPane.isFloating()) { DRAG_POSITION.set(stageX, stageY); return addToFloatingGroup(draggable, actor, dragPane); } return CANCEL; } DRAG_POSITION.set(stageX, stageY); if (overActor instanceof DragPane) { return addDirectlyToPane(draggable, actor, (DragPane) overActor); } final DragPane dragPane = getDragPane(overActor); if (accept(actor, dragPane)) { return addActor(draggable, actor, overActor, dragPane); } return CANCEL; }
private void respawn() { position.set(spawnLocation); lastFramePosition.set(spawnLocation); velocity.setZero(); jumpState = Enums.JumpState.FALLING; facing = Direction.RIGHT; walkState = Enums.WalkState.NOT_WALKING; }
@Override public RubeImage read(Json json, JsonValue jsonData, Class type) { if (scene.getBodies() == null) return null; RubeImage defaults = RubeDefaults.Image.image; RubeImage image = new RubeImage(); image.angle = json.readValue("angle", float.class, defaults.angle, jsonData); int bodyIndex = json.readValue("body", int.class, jsonData); if (bodyIndex >= 0 && bodyIndex < scene.getBodies().size) image.body = scene.getBodies().get(bodyIndex); image.center.set(json.readValue("center", Vector2.class, defaults.center, jsonData)); RubeVertexArray corners = json.readValue("corners", RubeVertexArray.class, jsonData); if (corners != null) { tmp.set(corners.x[0], corners.y[0]).sub(corners.x[1], corners.y[1]); image.width = tmp.len(); tmp.set(corners.x[1], corners.y[1]).sub(corners.x[2], corners.y[2]); image.height = tmp.len(); } image.file = json.readValue("file", String.class, jsonData); if (stripImageFile) { int fslashIndex = image.file.lastIndexOf('/'); int dotIndex = image.file.lastIndexOf('.'); if (fslashIndex != -1 && dotIndex != -1 && fslashIndex < dotIndex) { image.file = image.file.substring(fslashIndex + 1, dotIndex); } } image.filter = json.readValue("filter", int.class, defaults.filter, jsonData); image.name = json.readValue("name", String.class, jsonData); image.opacity = json.readValue("opacity", float.class, defaults.opacity, jsonData); image.renderOrder = json.readValue("renderOrder", int.class, defaults.renderOrder, jsonData); image.scale = json.readValue("scale", float.class, defaults.scale, jsonData); image.flip = json.readValue("flip", boolean.class, defaults.flip, jsonData); int[] colorArray = json.readValue("colorTint", int[].class, RubeDefaults.Image.colorArray, jsonData); image.color.r = (float) colorArray[0] / 255; image.color.g = (float) colorArray[1] / 255; image.color.b = (float) colorArray[2] / 255; image.color.a = (float) colorArray[3] / 255; RubeCustomProperty customProperty = null; if (json.getSerializer(RubeCustomProperty.class) != null) customProperty = json.readValue("customProperties", RubeCustomProperty.class, jsonData); scene.onAddImage(image, customProperty); return image; }
public void recalculateButtonPositions() { moveLeftCenter.set(Constants.BUTTON_SIZE * 3 / 4, Constants.BUTTON_SIZE); moveRightCenter.set(Constants.BUTTON_SIZE * 2, Constants.BUTTON_SIZE * 3 / 4); shootCenter.set( viewport.getWorldWidth() - Constants.BUTTON_SIZE * 2f, Constants.BUTTON_SIZE * 3 / 4); jumpCenter.set(viewport.getWorldWidth() - Constants.BUTTON_SIZE * 3 / 4, Constants.BUTTON_SIZE); }
@Override public void resize(int width, int height) { screenSize.set(width, height); midpoint.set(width / 2, height / 2); stage2d.getViewport().update(width, height, true); setActiveCamera(); activeCamera.update(true); resizeElements(); }
/** * Adjusts the parent and child bone rotations so the tip of the child is as close to the target * position as possible. The target is specified in the world coordinate system. * * @param child Any descendant bone of the parent. */ public static void apply( Bone parent, Bone child, float targetX, float targetY, int bendDirection, float alpha) { float childRotation = child.rotation, parentRotation = parent.rotation; if (alpha == 0) { child.rotationIK = childRotation; parent.rotationIK = parentRotation; return; } Vector2 position = temp; Bone parentParent = parent.parent; if (parentParent != null) { parentParent.worldToLocal(position.set(targetX, targetY)); targetX = (position.x - parent.x) * parentParent.worldScaleX; targetY = (position.y - parent.y) * parentParent.worldScaleY; } else { targetX -= parent.x; targetY -= parent.y; } if (child.parent == parent) position.set(child.x, child.y); else parent.worldToLocal(child.parent.localToWorld(position.set(child.x, child.y))); float childX = position.x * parent.worldScaleX, childY = position.y * parent.worldScaleY; float offset = (float) Math.atan2(childY, childX); float len1 = (float) Math.sqrt(childX * childX + childY * childY), len2 = child.data.length * child.worldScaleX; // Based on code by Ryan Juckett with permission: Copyright (c) 2008-2009 Ryan Juckett, // http://www.ryanjuckett.com/ float cosDenom = 2 * len1 * len2; if (cosDenom < 0.0001f) { child.rotationIK = childRotation + ((float) Math.atan2(targetY, targetX) * radDeg - parentRotation - childRotation) * alpha; return; } float cos = clamp( (targetX * targetX + targetY * targetY - len1 * len1 - len2 * len2) / cosDenom, -1, 1); float childAngle = (float) Math.acos(cos) * bendDirection; float adjacent = len1 + len2 * cos, opposite = len2 * sin(childAngle); float parentAngle = (float) Math.atan2( targetY * adjacent - targetX * opposite, targetX * adjacent + targetY * opposite); float rotation = (parentAngle - offset) * radDeg - parentRotation; if (rotation > 180) rotation -= 360; else if (rotation < -180) // rotation += 360; parent.rotationIK = parentRotation + rotation * alpha; rotation = (childAngle + offset) * radDeg - childRotation; if (rotation > 180) rotation -= 360; else if (rotation < -180) // rotation += 360; child.rotationIK = childRotation + (rotation + parent.worldRotation - child.parent.worldRotation) * alpha; }
private int generate(Array<Vector2> input, int mult) { int c = tristrip.size; if (endcap <= 0) { tristrip.add(input.get(0)); } else { Vector2 p = input.get(0); Vector2 p2 = input.get(1); perp.set(p).sub(p2).scl(endcap); tristrip.add(new Vector2(p.x + perp.x, p.y + perp.y)); } texcoord.add(new Vector2(0f, 0f)); for (int i = 1; i < input.size - 1; i++) { Vector2 p = input.get(i); Vector2 p2 = input.get(i + 1); // get direction and normalize it perp.set(p).sub(p2).nor(); // get perpendicular perp.set(-perp.y, perp.x); float thick = thickness * (1f - ((i) / (float) (input.size))); // move outward by thickness perp.scl(thick / 2f); // decide on which side we are using perp.scl(mult); // add the tip of perpendicular tristrip.add(new Vector2(p.x + perp.x, p.y + perp.y)); // 0.0 -> end, transparent texcoord.add(new Vector2(0f, 0f)); // add the center point tristrip.add(new Vector2(p.x, p.y)); // 1.0 -> center, opaque texcoord.add(new Vector2(1f, 0f)); } // final point if (endcap <= 0) { tristrip.add(input.get(input.size - 1)); } else { Vector2 p = input.get(input.size - 2); Vector2 p2 = input.get(input.size - 1); perp.set(p2).sub(p).scl(endcap); tristrip.add(new Vector2(p2.x + perp.x, p2.y + perp.y)); } // end cap is transparent texcoord.add(new Vector2(0f, 0f)); return tristrip.size - c; }
public void rayCast(RayCastCallback callback, Vector2 point1, Vector2 point2) { if (point1.dst2(point2) <= ZERO) { Gdx.app.log("World.rayCast", "Called with zero distance"); return; } callback.reset(); callback.result.start.set(toBox(tmp1.set(point1))); callback.result.end.set(toBox(tmp2.set(point2))); world.rayCast(callback, tmp1, tmp2); callback.result.scl(toWorldScale()); }
public void init() { position.set(spawnLocation); lastFramePosition.set(spawnLocation); velocity.setZero(); jumpState = Enums.JumpState.FALLING; facing = Direction.RIGHT; walkState = Enums.WalkState.NOT_WALKING; // TODO: Initialize ammo ammo = Constants.INTIAL_AMMO; }
@Override public Vector2 valueAt(Vector2 out, float t) { int index = getStartIndex(t); Destination start = destinations.get(index); if (index == destinations.size() - 1) { return out.set(start); } Vector2 next = destinations.get(index + 1); return out.set(next).sub(start).scl((t - start.startTime) / start.moveTime).add(start); }
/** * Slack, like weapon recoil on the joint. * * @param attached */ protected void updateSlack(final Attached attached) { float len = vTmp.set(attached.slackX, attached.slackY).len() - world.delta * attached.tension; if (len > 0) { vTmp.nor().scl(len); } else { vTmp.set(0, 0); } attached.slackX = vTmp.x; attached.slackY = vTmp.y; }
/** * Focuses the next TextField. If none is found, the keyboard is hidden. Does nothing if the text * field is not in a stage. * * @param up If true, the TextField with the same or next smallest y coordinate is found, else the * next highest. */ public void next(boolean up) { Stage stage = getStage(); if (stage == null) return; getParent().localToStageCoordinates(tmp1.set(getX(), getY())); TextField textField = findNextTextField(stage.getActors(), null, tmp2, tmp1, up); if (textField == null) { // Try to wrap around. if (up) tmp1.set(Float.MIN_VALUE, Float.MIN_VALUE); else tmp1.set(Float.MAX_VALUE, Float.MAX_VALUE); textField = findNextTextField(getStage().getActors(), null, tmp2, tmp1, up); } if (textField != null) stage.setKeyboardFocus(textField); else Gdx.input.setOnscreenKeyboardVisible(false); }
public void init(float x, float y, float tx, float ty) { position.set(x, y); start.set(position); target.set(tx, ty); effect.reset(); duration = target.dst(position) / 6; active = true; light.setActive(true); light.setPosition(x, y); for (ParticleEmitter emitter : effect.getEmitters()) { emitter.setContinuous(true); } }
protected static Collision AABBvsCircle(AABB A, Circle B) { Vector2 AtoB = B.getPosition().cpy().sub(A.getCenter()); float xe = A.getDimensions().x / 2; float ye = A.getDimensions().y / 2; Vector2 closest = new Vector2(MathUtils.clamp(AtoB.x, -xe, xe), MathUtils.clamp(AtoB.y, -ye, ye)); boolean inside = false; if (AtoB.epsilonEquals(closest, (float) 1e-4)) { inside = true; if (Math.abs(AtoB.x) > Math.abs(AtoB.y)) { if (closest.x > 0.0f) { closest.x = xe; } else { closest.x = -xe; } } else { if (closest.y > 0.0f) { closest.y = ye; } else { closest.y = -ye; } } } Vector2 normal = new Vector2(AtoB).sub(closest); float d = normal.len2(); float r = B.radius; // No collision if (d > r * r && !inside) { return null; } d = (float) Math.sqrt(d); float penetration = r + d; if (inside) { normal.set(AtoB).mul(1.0f).nor(); } else { normal.set(AtoB).mul(-1.0f).nor(); } return new Collision(normal, penetration); }
private void accelerate() { shipRot = (float) (body.getTransform().getRotation() + MathUtils.PI / 2); xSpeed = MathUtils.cos(shipRot); ySpeed = MathUtils.sin(shipRot); movement.set(speed * xSpeed, speed * ySpeed); setExhaustRotation(); }
/** * Applies a mouse moved event to the stage and returns true if an actor in the scene {@link * Event#handle() handled} the event. This event only occurs on the desktop. */ public boolean mouseMoved(int screenX, int screenY) { if (screenX < viewport.getScreenX() || screenX >= viewport.getScreenX() + viewport.getScreenWidth()) return false; if (Gdx.graphics.getHeight() - screenY < viewport.getScreenY() || Gdx.graphics.getHeight() - screenY >= viewport.getScreenY() + viewport.getScreenHeight()) return false; mouseScreenX = screenX; mouseScreenY = screenY; screenToStageCoordinates(tempCoords.set(screenX, screenY)); InputEvent event = Pools.obtain(InputEvent.class); event.setStage(this); event.setType(Type.mouseMoved); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); Actor target = hit(tempCoords.x, tempCoords.y, true); if (target == null) target = root; target.fire(event); boolean handled = event.isHandled(); Pools.free(event); return handled; }
/** * Applies a touch up event to the stage and returns true if an actor in the scene {@link * Event#handle() handled} the event. Only {@link InputListener listeners} that returned true for * touchDown will receive this event. */ public boolean touchUp(int screenX, int screenY, int pointer, int button) { pointerTouched[pointer] = false; pointerScreenX[pointer] = screenX; pointerScreenY[pointer] = screenY; if (touchFocuses.size == 0) return false; screenToStageCoordinates(tempCoords.set(screenX, screenY)); InputEvent event = Pools.obtain(InputEvent.class); event.setType(Type.touchUp); event.setStage(this); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); event.setPointer(pointer); event.setButton(button); SnapshotArray<TouchFocus> touchFocuses = this.touchFocuses; TouchFocus[] focuses = touchFocuses.begin(); for (int i = 0, n = touchFocuses.size; i < n; i++) { TouchFocus focus = focuses[i]; if (focus.pointer != pointer || focus.button != button) continue; if (!touchFocuses.removeValue(focus, true)) continue; // Touch focus already gone. event.setTarget(focus.target); event.setListenerActor(focus.listenerActor); if (focus.listener.handle(event)) event.handle(); Pools.free(focus); } touchFocuses.end(); boolean handled = event.isHandled(); Pools.free(event); return handled; }
/** * Applies a touch down event to the stage and returns true if an actor in the scene {@link * Event#handle() handled} the event. */ public boolean touchDown(int screenX, int screenY, int pointer, int button) { if (screenX < viewport.getScreenX() || screenX >= viewport.getScreenX() + viewport.getScreenWidth()) return false; if (Gdx.graphics.getHeight() - screenY < viewport.getScreenY() || Gdx.graphics.getHeight() - screenY >= viewport.getScreenY() + viewport.getScreenHeight()) return false; pointerTouched[pointer] = true; pointerScreenX[pointer] = screenX; pointerScreenY[pointer] = screenY; screenToStageCoordinates(tempCoords.set(screenX, screenY)); InputEvent event = Pools.obtain(InputEvent.class); event.setType(Type.touchDown); event.setStage(this); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); event.setPointer(pointer); event.setButton(button); Actor target = hit(tempCoords.x, tempCoords.y, true); if (target == null) { if (root.getTouchable() == Touchable.enabled) root.fire(event); } else { target.fire(event); } boolean handled = event.isHandled(); Pools.free(event); return handled; }
private Actor fireEnterAndExit(Actor overLast, int screenX, int screenY, int pointer) { // Find the actor under the point. screenToStageCoordinates(tempCoords.set(screenX, screenY)); Actor over = hit(tempCoords.x, tempCoords.y, true); if (over == overLast) return overLast; // Exit overLast. if (overLast != null) { InputEvent event = Pools.obtain(InputEvent.class); event.setStage(this); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); event.setPointer(pointer); event.setType(InputEvent.Type.exit); event.setRelatedActor(over); overLast.fire(event); Pools.free(event); } // Enter over. if (over != null) { InputEvent event = Pools.obtain(InputEvent.class); event.setStage(this); event.setStageX(tempCoords.x); event.setStageY(tempCoords.y); event.setPointer(pointer); event.setType(InputEvent.Type.enter); event.setRelatedActor(overLast); over.fire(event); Pools.free(event); } return over; }
/** * Clamp the point to the nearest polygon segment * * @param poly The polygon * @param x The original point X * @param y The original point Y * @param dest The clamped point * @return The segment where the clamped point belongs */ public static int getClampedPoint(Polygon poly, float x, float y, Vector2 dest) { float verts[] = poly.getTransformedVertices(); float dTmp; Intersector.nearestSegmentPoint(verts[0], verts[1], verts[2], verts[3], x, y, dest); int nearest = 0; float d = Vector2.dst(x, y, dest.x, dest.y); for (int i = 2; i < verts.length; i += 2) { Intersector.nearestSegmentPoint( verts[i], verts[i + 1], verts[(i + 2) % verts.length], verts[(i + 3) % verts.length], x, y, tmp); dTmp = Vector2.dst(x, y, tmp.x, tmp.y); if (dTmp < d) { d = dTmp; nearest = i; dest.set(tmp); } } return nearest; }
/** * Complete arc * * @param center * @param radInner * @param radOuter * @param segs * @param innerCol * @param outerCol */ public void drawArc( Vector2 center, float radInner, float radOuter, int segs, Color innerCol, Color outerCol) { setType(GL20.GL_TRIANGLE_STRIP); n_verts = (segs + 1) * 2 + 2; checkMaxVerts(n_verts); a.set(CircleLogic.findPos(center, radOuter, 0 * (360f / segs), 0f)); putVertex(a.x, a.y, outerCol); putVertex(a.x, a.y, outerCol); for (int i = 0; i < segs + 1; i++) { a.set(CircleLogic.findPos(center, radOuter, i * (360f / segs), 0f)); putVertex(a.x, a.y, outerCol); a.set(CircleLogic.findPos(center, radInner, i * (360f / segs), 0f)); putVertex(a.x, a.y, innerCol); } putVertex(a.x, a.y, innerCol); }