How to unbind a sprite in an updating vector? - java

How to unbind an updating vector to a sprite? I am using Libgdx framework. here is my code
public class VectorSample extends GDX_TEST implements InputProcessor {
Texture ball,bullet,guider;
OrthographicCamera camera;
Vector2 vector = new Vector2();
Vector2 vectoralt = new Vector2();
long lastDropTime;
SpriteBatch batch;
Rectangle rect = new Rectangle();
float angle = 0,anglealt = 0;
private ShapeRenderer renderer;
TextureRegion tr;
Sprite sprite,sprite2;
ShapeRenderer sr;
Ship ship;
BallShit shit;
Vector2 nvec;
protected Vector2 center = new Vector2();
Array<Vector2> bullets;
Array<Rectangle> bulletsRect;
Boolean fire = false;
Rectangle tmpRect = new Rectangle();
#Override
public void create() {
renderer = new ShapeRenderer();
ball = new Texture(Gdx.files.internal("data/player.png"));
bullet = new Texture("data/ball_black.png");
tr = new TextureRegion(ball);
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
ship = new Ship(new Vector2(5, 50), 1, 1, 0, 5f);
sr = new ShapeRenderer();
batch = new SpriteBatch();
Gdx.input.setInputProcessor(this);
rect.width = ball.getWidth();
rect.height = ball.getHeight();
vector.add(200,200);
sprite = new Sprite(ball);
vectoralt.add(200 + sprite.getWidth(),200);
shit = new BallShit(new Vector2(10,0),50f,50f);
bullets = new Array<Vector2>();
getCenter();
bulletsRect = new Array<Rectangle>();
fireatwill2();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
{
batch.draw(sprite,vector.x,vector.y,sprite.getWidth()/2,sprite.getHeight()/2,sprite.getWidth(),sprite.getHeight(),1,1,angle);
if(fire == true){
for(Rectangle raindrop: bulletsRect) {
batch.draw(bullet,raindrop.x,raindrop.y);
}
}
}
batch.end();
if(Gdx.input.isKeyPressed(Input.Keys.D)){
vector.add(1,0);
if(vector.x > Gdx.graphics.getWidth()){
Gdx.app.log("x","x");
}
}
if(Gdx.input.isKeyPressed(Input.Keys.A)){
vector.add(-1,0);
if(vector.x < 0){
Gdx.app.log("x","-x");
}
}
float w = camera.frustum.planePoints[1].x - camera.frustum.planePoints[0].x;
float distance = w - (vector.x + sprite.getWidth());
if(distance <=0){
vector.x = w - sprite.getWidth();
}
Gdx.app.log("camera x" , " " + distance);
if(distance >= Gdx.graphics.getWidth() - sprite.getWidth()) {
vector.x = 0;
}
if(Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
fire = true;
if(TimeUtils.nanoTime() - lastDropTime > 100000000) fireatwill2();
}
Iterator<Rectangle> iter = bulletsRect.iterator();
while(iter.hasNext()) {
Rectangle raindrop = iter.next();
double angletry = getAngle() * MathUtils.degreesToRadians;
float speed = 5;
float scale_x = (float)Math.cos(angletry);
float scale_y = (float)Math.sin(angletry);
float velocity_x = (speed* scale_x);
float velocity_y = (speed* scale_y);
raindrop.x += velocity_x;
raindrop.y += velocity_y;
if(raindrop.y < 0) iter.remove();
if(raindrop.y > Gdx.graphics.getHeight() || raindrop.x > Gdx.graphics.getWidth()) iter.remove();
}
//getting the angle
float angle = findAngle(Gdx.input.getX(),
Gdx.graphics.getHeight() - Gdx.input.getY());
this.angle = angle % 360;
}
private float getAngle(){
float angle = findAngle(Gdx.input.getX(),
Gdx.graphics.getHeight() - Gdx.input.getY());
return angle;
}
private void fireatwill2() {
Rectangle raindrop = new Rectangle();
raindrop.x = vector.x + sprite.getWidth() / 2 - (bullet.getWidth() / 2);
raindrop.y = vector.y + sprite.getHeight() / 2 - (bullet.getHeight() / 2);
bulletsRect.add(raindrop);
lastDropTime = TimeUtils.nanoTime();
}
public Vector2 getCenter() {
center.x = vector.x + sprite.getWidth() / 2;
center.y = vector.y + sprite.getHeight() / 2;
return center.cpy();
}
#Override
public void pause() {
super.pause(); //To change body of overridden methods use File | Settings | File Templates.
}
#Override
public void resume() {
super.resume(); //To change body of overridden methods use File | Settings | File Templates.
}
public float findAngle(float x1, float y1) {
Vector2 center = getCenter();
float x0 = center.x;
float y0 = center.y;
float a = MathUtils.atan2(y1 - y0, x1 - x0);
return a * MathUtils.radiansToDegrees;
}
}
and here is the running demo and source is here
I cant explain it well but if you could run the demo u will get what i am saying.
Im really stuck in here.. Thanks.

Related

Libgdx box2d body is being place at the wrong y coordinate

I have been working with box2d and am having a problem where my body is not being set to the correct y coordinate when I try to position it at the bottom right of the screen.
I am trying to set the y coordinate to 0 so that the body aligns directly with the bottom of the screen. However, the half of the body is hanging off the screen. Even when I print out the body's location, it says the y is at 0.
I have my pixel per meter set at screenHeight / 80 which comes out to be around 25 PPM for the current devise I am using. I am not sure if my scaling is causing something weird to happen.
Code:
public class GameScreen extends ScreenAdapter {
Controller game;
public World world;
public Body ball;
public Body block;
public Box2DDebugRenderer box2DDebugRenderer;
private Matrix4 cameraBox2D;
public MyGestureListener myGestureListener;
//x-axis length for top/bottom bar
private float goalWidth;
//pixels per meter
public float PPM;
//y-axis height for back bar
private float goalHeight;
private float goalPostThickness;
//Screen height and width
private float screenWidth;
private float screenHeight;
//How far down/up posts are from edge of screen
private float goalPostTopOffset;
private float goalPostBottomOffset;
//Center x,y of cannon
private float cannonOriginX; //Variables used for starting poisition of balls
private float cannonOriginY;
//Center x,y of ball
float ballX;
float ballY;
//Velocity of ball
public float velocity = 50;
public int colorCode = 1;
//Tracks users drag y coord
public float panLocation = 0;
//Velocity of block once the user releases
public float flingVelocity;
//Changes to true when the block is released
public boolean isReleased = false;
public GameScreen (Controller game){
this.game = game;
}
#Override
public void show(){
myGestureListener = new MyGestureListener(game, this);
cameraBox2D = new Matrix4(game.cam.combined);
screenWidth = game.getScreenWidth();
screenHeight = game.getScreenHeight();
//PPM = screenHeight / 80f;
PPM = screenHeight / 80f;
goalPostTopOffset = screenHeight/7;
goalPostBottomOffset = goalPostTopOffset * 3;
goalHeight = screenHeight - (goalPostTopOffset + goalPostBottomOffset);
goalWidth = screenWidth / 6;
goalPostThickness = screenWidth / 75;
cannonOriginX = goalWidth / 2; //Variables used for starting position of balls
cannonOriginY = (goalPostThickness*5) / 2;
ballX = 0 + cannonOriginX;
ballY = (goalPostBottomOffset - (goalPostBottomOffset / 4)) + cannonOriginY;
world = new World(new Vector2(0, 0f), true);
box2DDebugRenderer = new Box2DDebugRenderer();
//Creates animated ball
ball = createBall();
//Sets radius, density, etc.
setBallProperties(ball);
//Creates block that stops balls
block = createBlock();
//Sets properties
setBlockProperties(block);
}
#Override
public void render(float delta){
//Logic
world.step(1/60f, 6, 2);
//Draw
game.cam.update();
Gdx.gl.glClearColor(32/255f, 32/255f, 32/255f, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
box2DDebugRenderer.render(world, game.cam.combined.scl(PPM));
game.shape.setProjectionMatrix(game.cam.combined);
Gdx.input.setInputProcessor(new GestureDetector(myGestureListener));
System.out.println(block.getPosition().y);
System.out.println(block.getPosition().x);
drawNonAnimated();
drawAnimated();
//show()
cameraBox2D = game.cam.combined.cpy(); //Copy the main camera
cameraBox2D.scl(PPM); //Scale the camera projection to the ratio you're using for Box2D
//render()
box2DDebugRenderer.render(world, cameraBox2D);
}
#Override
public void hide(){
}
//draws stationary objects such as goal posts
public void drawNonAnimated(){
//Cannon platform
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM, goalWidth/PPM, (goalPostThickness*2)/PPM);
game.shape.end();
//Cannon
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(0, (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM, cannonOriginX/PPM,
cannonOriginY/PPM, goalWidth/PPM, (goalPostThickness*5)/PPM, 1, 1, 45);
game.shape.end();
}
public void drawAnimated(){
//FOR BALL
velocity--;
ball.setLinearVelocity(new Vector2(35,velocity));
Vector2 pos = ball.getPosition();
if (pos.x >= screenWidth/PPM){
ball.setTransform(new Vector2(ballX/PPM, ballY/PPM), 0);
//Changing color of ball each loop
if (colorCode == 3){
colorCode = 1;
}
else{
colorCode++;
}
//max 75 min 50
velocity = randInt(50, 75);
}
attachCircleShape(pos);
blockerMovement();
}
public void blockerMovement(){
//FOR BLOCKER RECTANGLE ANIMATION
Vector2 pos = block.getPosition();
float boundaryLocation = (goalPostBottomOffset - (goalPostBottomOffset / 4))/PPM;
//attachBlockerShape(pos);
panLocation = myGestureListener.getPanLocation();
if (isReleased == true){
//Get the velocity as the block is released
//to determine the speed it will continue to go after release
block.setLinearVelocity(0, flingVelocity);
flingVelocity -= 3;
}
else if (myGestureListener.getCheckRelease()|| panLocation/PPM >= boundaryLocation && !isReleased) {
flingVelocity = myGestureListener.speed;
isReleased = true;
System.out.println("SPEED: " + flingVelocity);
}
else if (myGestureListener.isPaning) {
block.setTransform(new Vector2((screenWidth - goalPostThickness) / PPM, panLocation / PPM), 0);
}
}
//Creates animated ball
public Body createBall(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set(ballX/PPM,ballY/PPM);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
//Sets radius, density, etc.
public void setBallProperties(Body body){
float gbt = screenWidth / 75; //Goal post thickness
float ballRadius = (gbt * 1.5f) / PPM;
// Create a circle shape and set its radius to 6
CircleShape circle = new CircleShape();
circle.setRadius(ballRadius);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = circle;
fixtureDef.density = 3.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = ball.createFixture(fixtureDef);
circle.dispose();
}
public Body createBlock(){
Body bBody;
BodyDef def = new BodyDef();
def.type = BodyDef.BodyType.DynamicBody;
def.position.set((screenWidth - goalPostThickness)/PPM,0);
def.fixedRotation = true;
bBody = world.createBody(def);
return bBody;
}
//Sets radius, density, etc.
public void setBlockProperties(Body body){
float gbt = screenWidth / 75; //Goal post thickness
// Create a circle shape and set its radius to 6
PolygonShape square = new PolygonShape();
square.setAsBox(goalPostThickness/PPM, (goalWidth/2)/PPM);
// Create a fixture definition to apply our shape to
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = square;
fixtureDef.density = 3.5f;
fixtureDef.friction = 0.4f;
fixtureDef.restitution = 0.6f; // Make it bounce a little bit
// Create our fixture and attach it to the body
Fixture fixture = block.createFixture(fixtureDef);
square.dispose();
}
public static int randInt(int min, int max) {
Random rand = new Random();
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public void attachBlockerShape(Vector2 pos){
game.shape.setColor(1, 1, 1, 1);
game.shape.begin(ShapeRenderer.ShapeType.Filled);
game.shape.rect(pos.x, pos.y, goalPostThickness/PPM, (goalWidth/2)/PPM);
game.shape.end();
}
//Attaching a regular libgdx shape to the position of box2d shape
public void attachCircleShape(Vector2 pos){
//Color of ball changes each loop
if (colorCode == 1){
//Blue
game.circle.setColor(66/255f, 134/255f, 244/255f, 0);
}
else if (colorCode == 2){
//Pink
game.circle.setColor(244/255f, 66/255f, 116/255f, 0);
}
else if (colorCode == 3){
game.circle.setColor(244/255f, 116/255f, 66/255f, 0);
}
game.circle.begin(ShapeRenderer.ShapeType.Filled);
game.circle.circle(pos.x*PPM, pos.y*PPM, goalPostThickness * 1.5f);
game.circle.end();
game.cam.update();
}
#Override public void dispose(){
box2DDebugRenderer.dispose();
world.dispose();
}
}
If you create a Body with Box2d 0,0 is in the center of the Body while libgdx set 0,0 on the bottom left corner.
So if you create a Body with Box2d and you want that 0,0 is in the bottom left corner you must move the Body by half of width on x and half of height on y:
public Body createBody(float x, float y, float width, float height){
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
//Move the body so if x and y are 0 the bottom left corner of the body is on position 0,0
bodyDef.position.x = x + width / 2;
bodyDef.position.y = y + height / 2;
PolygonShape polygonShape = new PolygonShape();
polygonShape.setAsBox(width / 2, height / 2);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = polygonShape;
Body body = world.createBody(bodyDef);
body.createFixture(fixtureDef);
polygonShape.dispose();
return body;
}

Java libGDX different sizes of animation frames

How to deal with different sizes of frames? If I setBounds(0, 0, 100, 100) in constructor then some frames are smaller but if I update it then frames are moved to left and up. How to make that every frame will be in the same place?
mayby you can see it
http://imgur.com/a/AN8Gc
public class Player extends Sprite{
//floats
private float animationTimer;
//box2d variables
public World world;
public Body body;
//enums
public enum State{STANDING, MOVING, SHOOTING, RELOAD, MALEE_ATTACK}
public State currentState;
public State previousState;
//booleans
boolean shoot;
boolean reload;
boolean maleeAttack;
private TextureRegion region;
public PlayScreen playScreen;
public Player(PlayScreen playScreen){
this.playScreen = playScreen;
this.world = playScreen.getWorld();
definePlayer();
animationTimer = 0;
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
setRegion(region);
setBounds(0, 0, getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM);
setPosition(0, 0);
currentState = State.STANDING;
previousState = State.STANDING;
shoot = false;
reload = false;
maleeAttack = false;
}
public void definePlayer(){
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(100 / Constants.PPM, 100 / Constants.PPM);
bodyDef.type = BodyDef.BodyType.DynamicBody;
body = world.createBody(bodyDef);
FixtureDef fixtureDef = new FixtureDef();
CircleShape shape = new CircleShape();
shape.setRadius(50 / Constants.PPM);
fixtureDef.shape = shape;
body.createFixture(fixtureDef).setUserData(this);
body.setLinearDamping(Constants.LINEAR_DAMPING);
}
public void update(float delta){
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
setRegion(getFrame(delta));
moving();
//rotate();
}
public void moving(){
setPosition(body.getPosition().x - getWidth() / 2, body.getPosition(). y - getHeight() / 2);
//setBounds(0, 0, getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM); update bounds
if (input.isKeyPressed(Input.Keys.W) && body.getLinearVelocity().y < 5){
body.applyLinearImpulse(new Vector2(0, 1), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.S) && body.getLinearVelocity().y > -5){
body.applyLinearImpulse(new Vector2(0, -1), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.D) && body.getLinearVelocity().x < 5){
body.applyLinearImpulse(new Vector2(1, 0), body.getWorldCenter(), true);
}
if (input.isKeyPressed(Input.Keys.A) && body.getLinearVelocity().x > -5){
body.applyLinearImpulse(new Vector2(-1, 0), body.getWorldCenter(), true);
}
if (Gdx.input.isKeyPressed(Input.Keys.R)){
reload = true;
}
if (Gdx.input.isKeyPressed(Input.Keys.F)){
maleeAttack = true;
}
if (Gdx.input.isButtonPressed(Input.Buttons.LEFT)){
shoot = true;
}
}
public TextureRegion getFrame(float delta){
TextureRegion region;
currentState = getState();
switch (currentState){
case MOVING:
region = Assets.instance.playerAssets.moveAnimation.getKeyFrame(animationTimer);
break;
case SHOOTING:
maleeAttack = false;
region = Assets.instance.playerAssets.shootAniamtion.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.shootAniamtion.isAnimationFinished(animationTimer)){
shoot = false;
}
break;
case RELOAD:
region = Assets.instance.playerAssets.reloadAnimation.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.reloadAnimation.isAnimationFinished(animationTimer)){
reload = false;
}
break;
case MALEE_ATTACK:
region = Assets.instance.playerAssets.maleeAttackAnimation.getKeyFrame(animationTimer);
if (Assets.instance.playerAssets.maleeAttackAnimation.isAnimationFinished(animationTimer)) {
maleeAttack = false;
}
break;
default:
region = Assets.instance.playerAssets.idleAniamtion.getKeyFrame(animationTimer);
break;
}
animationTimer = currentState == previousState ? animationTimer + delta : 0;
previousState = currentState;
return region;
}
public State getState(){
if ((body.getLinearVelocity().x > 1 || body.getLinearVelocity().x < -1 || body.getLinearVelocity().y > 1 || body.getLinearVelocity().y < - 1) && !reload && !shoot && !maleeAttack){
return State.MOVING;
}
if (shoot && !reload){
return State.SHOOTING;
}
if (reload && !maleeAttack){
return State.RELOAD;
}
if (maleeAttack){
return State.MALEE_ATTACK;
}
else {
return State.STANDING;
}
}
public Vector2 getMousePosition(){
Vector2 mousePosition;
mousePosition = playScreen.getViewport().unproject(new Vector2(Gdx.input.getX(), Gdx.input.getY()));
return mousePosition;
}
public float getMouseAngle(){
float angle = (float) Math.atan2(getMousePosition().y - body.getPosition().y, getMousePosition().x - body.getPosition().x);
return angle;
}
public void rotate(){
setOrigin(getWidth() / 2, getHeight() / 2 );
setRotation((float) (getMouseAngle() * (180/Math.PI)));
body.setTransform(body.getPosition(), getMouseAngle());
}
}
To avoid the resizing of the texture just create a variable size used to set the bounds. The bound needs to set every frame.
public class Player extends Sprite {
private Body body;
private Vector2 size;
public Player(){
this.size = new Vector2( getRegionWidth() / Constants.PPM, getRegionHeight() / Constants.PPM );
}
public void update( float delta ){
Vector2 position = body.getPosition();
setRegion( getFrame( delta ) );
setRotation( MathUtils.radDeg * body.getAngle() );
setBounds( position.x, position.y, size.x, size.y );
setOriginCenter();
}
public void rotate(){
this.body.setTransform( body.getPosition(), getMouseAngle() );
}
}
You need to use the additional data information a TextureAtlas provides as an AtlasRegion.
One complete animation should have the same (width/height) size for each keyframe. Pick a size where the biggest keyfarme fits into. Also be aware of positioning correctly. Have the same pivot point for each keyframe.
To avoid wasting space when packing your TextureAtlas enable "trim" function. Should be supported by any TexturePacker Tool out there.
The texture data file (for libGDX) then has entries like this:
walk_animation
rotate: false
xy: 794, 235
size: 86, 109
orig: 160, 170
offset: 37, 22
index: 5
Use the AtlasRegion to draw things at the correct size and position:
float width = 400; // pick your size here
float height = 300;
float offsetPctX = atlasRegion.offsetX / atlasRegion.originalWidth;
float offsetPctY = atlasRegion.offsetY / atlasRegion.originalHeight;
float scaleWidth = (float) atlasRegion.packedWidth / atlasRegion.originalWidth;
float scaleHeight = (float) atlasRegion.packedHeight / atlasRegion.originalHeight;
float drawWidth = width * scaleWidth;
float drawHeight = height * scaleHeight;
float regionOffsetX = offsetPctX * width;
float regionOffsetY = offsetPctY * height;
float drawScaleX = 1; // adjust to your needs
float drawScaleY = 1;
float drawOriginX = 0; // adjust to tour needs
float drawOriginY = 0;
float drawRotation = false;
float x = 100 + offsetX + regionOffsetX; // adjust to your needs
float y = 100 + offsetY + regionOffsetY;
spriteBatch.draw(atlasRegion, x, y, drawOriginX, drawOriginY, drawWidth, drawHeight, drawScaleX, drawScaleY, drawRotation);

Strange PolyBatch Positioning in libGDX

Excuse the basic question, just getting into the guts of LibGDX
I'm creating a radial bar to show my countdown timer
I've found some code that does what I need it to, the problem is the radial sprite's positioning. I can't seem to get it to center in the Image object (Since it seems to be ignoring the Image's local coordinates and is defaulting to the stage's) so 0,0 places it close to the bottom left of my screen.
I've tried using a localtoStage and vice versa to calculate the correct positions, but that doesn't seem to give me the right values either.
Please advise
package com.goplayplay.klpoker.CSS.Classes;
import com.badlogic.gdx.graphics.g2d.*;
import com.badlogic.gdx.math.EarClippingTriangulator;
import com.badlogic.gdx.math.Intersector;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.utils.ShortArray;
public class ProgressCircle extends Image {
TextureRegion texture;
PolygonSpriteBatch polyBatch;
Vector2 center;
Vector2 centerTop;
Vector2 leftTop;
Vector2 leftBottom;
Vector2 rightBottom;
Vector2 rightTop;
Vector2 progressPoint;
float[] fv;
IntersectAt intersectAt;
public ProgressCircle(TextureRegion region, PolygonSpriteBatch polyBatch) {
super(region);
this.texture = region;
this.polyBatch = polyBatch;
center = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
centerTop = new Vector2(this.getWidth() / 2, this.getHeight());
leftTop = new Vector2(0, this.getHeight());
leftBottom = new Vector2(0, 0);
rightBottom = new Vector2(this.getWidth(), 0);
rightTop = new Vector2(this.getWidth(), this.getHeight());
progressPoint = new Vector2(this.getWidth() / 2, this.getHeight() / 2);
setPercentage(0);
}
private Vector2 IntersectPoint(Vector2 line) {
Vector2 v = new Vector2();
boolean isIntersect;
//check top
isIntersect = Intersector.intersectSegments(leftTop, rightTop, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.TOP;
return v;
} else isIntersect = Intersector.intersectSegments(leftBottom, rightBottom, center, line, v);
//check left
if (isIntersect) {
intersectAt = IntersectAt.BOTTOM;
return v;
} else isIntersect = Intersector.intersectSegments(leftTop, leftBottom, center, line, v);
//check bottom
if (isIntersect) {
intersectAt = IntersectAt.LEFT;
return v;
} else isIntersect = Intersector.intersectSegments(rightTop, rightBottom, center, line, v);
if (isIntersect) {
intersectAt = IntersectAt.RIGHT;
return v;
} else {
intersectAt = IntersectAt.NONE;
return null;
}
}
public void setPercentage(float percent) {
//100 % = 360 degree
//==> percent % => (percent * 360 / 100) degree
float angle = convertToRadians(90); //percent = 0 => angle = -90
angle -= convertToRadians(percent * 360 / 100);
float len = this.getWidth() > this.getHeight() ? this.getWidth() : this.getHeight();
float dy = (float) (Math.sin(angle) * len);
float dx = (float) (Math.cos(angle) * len);
Vector2 line = new Vector2(center.x + dx, center.y + dy);
Vector2 v = IntersectPoint(line);
if (intersectAt == IntersectAt.TOP) {
if (v.x >= this.getWidth() / 2)
{
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
rightTop.x,
rightTop.y,
v.x,
v.y
};
} else {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
v.x,
v.y
};
}
} else if (intersectAt == IntersectAt.BOTTOM) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.LEFT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
v.x,
v.y
};
} else if (intersectAt == IntersectAt.RIGHT) {
fv = new float[]{
center.x,
center.y,
centerTop.x,
centerTop.y,
leftTop.x,
leftTop.y,
leftBottom.x,
leftBottom.y,
rightBottom.x,
rightBottom.y,
v.x,
v.y
};
} else // if (intersectAt == IntersectAt.NONE)
{
fv = null;
}
}
//
#Override
public void draw(Batch batch, float parentAlpha) {
// super.draw(batch, parentAlpha);
if (fv == null) return;
batch.end();
drawMe();
batch.begin();
}
public void drawMe() {
Vector2 acc = new Vector2();
acc.set(getWidth() / 2, getHeight() / 2);
localToStageCoordinates(acc);
EarClippingTriangulator e = new EarClippingTriangulator();
ShortArray sv = e.computeTriangles(fv);
PolygonRegion polyReg = new PolygonRegion(texture, fv, sv.toArray());
PolygonSprite poly = new PolygonSprite(polyReg);
poly.setOrigin(this.getOriginX(), this.getOriginY());
poly.setPosition(this.getX(), this.getY());
// poly.setPosition(acc.x, acc.y); //Attempting to calculate correct positioning - Doesnt work
poly.setRotation(this.getRotation());
poly.setColor(this.getColor());
polyBatch.begin();
poly.draw(polyBatch);
polyBatch.end();
}
float convertToDegrees(float angleInRadians) {
float angleInDegrees = angleInRadians * 57.2957795f;
return angleInDegrees;
}
//-----------------------------------------------------------------
float convertToRadians(float angleInDegrees) {
float angleInRadians = angleInDegrees * 0.0174532925f;
return angleInRadians;
}
public enum IntersectAt {
NONE, TOP, BOTTOM, LEFT, RIGHT
}
}
You forgot to set the camera's projection matrix on the polygon batch. You can get a copy of it from the Batch that's passed in:
public void draw(Batch batch, float parentAlpha) {
// super.draw(batch, parentAlpha);
if (fv == null) return;
batch.end();
drawMe(batch.getProjectionMatrix());
batch.begin();
}
public void drawMe(Matrix4 projection) {
polyBatch.setProjectionMatrix(projection);
//...
}
Or more simply, you can use a PolygonBatch as your Stage's batch, so you don't have to be swapping batches:
stage = new Stage(myViewport, new PolygonBatch());
//...
public void draw(Batch batch, float parentAlpha) {
// super.draw(batch, parentAlpha);
if (fv == null) return;
//don't need to call begin and end on the batch
drawMe((PolygonBatch)batch);
}
public void drawMe(PolygonBatch polyBatch) {
//...
//don't need to call begin or end on the batch
}
By the way, your drawMe method instantiates quite a few objects, some large. You should avoid this if you have more than a few actors that do this, or you'll get stutters from the GC. Try to instantiate objects only once in the constructor and reuse them.

How to draw new circle on touch and remove previous circle

I can create circle on touch but can not remove the previous one. I have manage to remove the very first circle but the code is poor and it does not really work as I want. I like to draw circle every time I touch the screen and remove the previous circle . So the screen starts with a circle and as I will touch a new position the previous should be removed and there will be a new one.So how to do that part?
Here is my work:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
Display display = new Display(this);
display.init();
display.backPaint.setColor(Color.WHITE);
setContentView(display);
}
static class Display extends View {
ArrayList<Point> points = new ArrayList();
int touch1_x=700;
int touch1_y=700;
Paint backPaint;
Paint circlePaint;
Paint circlePaint2;
Display(Context context) {
super(context);
}
void init() {
backPaint = new Paint();
backPaint.setColor(Color.WHITE);
backPaint.setStyle(Paint.Style.FILL);
circlePaint = new Paint();
circlePaint.setColor(Color.YELLOW);
circlePaint2 = new Paint();
circlePaint2.setColor(Color.WHITE);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getActionMasked()) {
// if (event.getX(event.getActionIndex()) > 100 && event.getX(event.getActionIndex()) < 200) {
touch1_x = (int) event.getX(event.getActionIndex());
touch1_y = (int) event.getY(event.getActionIndex());
// }
System.out.println("touch1_x ===" + touch1_x);
points.add(new Point(touch1_x, touch1_y));
points.add(new Point(touch1_x, touch1_y));
return true;
}
return false;
}
});
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawRect(0, 0, getWidth(), getHeight(), backPaint);
canvas.drawCircle(touch1_x, touch1_y, 50, circlePaint);
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50, circlePaint);
}
for(Point p: points){
canvas.drawCircle(p.x, p.y, 50,circlePaint2 );
}
invalidate();
}
}
}
relevant question
You could erase canvas before drawing the next circle, using
canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);
import turtle
t=turtle.Turtle()
wn=turtle.Screen()
for count in range(360):
t.fd(3)
t.rt(1)
wn.exitonclick()
I have a customised view for photo annotate, you can use this to do your job.
1: Create a file AnnotationView.java and copy the following code
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
/**
* #author Bob Gao
* http://bobgao.net
*/
public class AnnotationView extends ImageView implements OnTouchListener {
private static final float KEY_STROKE_WIDTH = 4;
private List<Annotation> annotations = new ArrayList<Annotation>();
private Annotation mAnnotation;
private Canvas mCanvas;
private Paint mPaint;
// private Rect mOutRect;
public AnnotationView(Context context) {
super(context);
setOnTouchListener(this);
setDrawingCacheEnabled(true);
setScaleType(ScaleType.FIT_XY);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.mCanvas = canvas;
for (Annotation annotation : annotations) {
mPaint.setColor(annotation.getColor());
switch (annotation.getShape()) {
case Annotation.KEY_SHAPE_CIRCLE:
drawCircle(annotation.getX(), annotation.getY(), annotation.getRadius());
break;
case Annotation.KEY_SHAPE_ARROW:
drawAL((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
case Annotation.KEY_SHAPE_SQUARES:
drawRect((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius());
break;
case Annotation.KEY_SHAPE_TRIANGLE:
drawTriangle((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
}
}
}
/**
* Draw a triangle
*
* #param x
* #param y
* #param r
*/
public void drawTriangle(int x, int y, int r, float degree) {
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x - 2 * r, y + 2 * r);
path.lineTo(x + 2 * r, y + 2 * r);
path.lineTo(x, y);
path.close();
rotatePath(path, degree);
mCanvas.drawPath(path, mPaint);
}
public void drawRect(int x, int y, int r) {
int lenght = 4 * r;
int left = x - lenght / 2;
int top = y - lenght / 2;
int right = x + lenght / 2;
int bottom = y + lenght / 2;
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
path.lineTo(right, bottom);
path.lineTo(left, bottom);
path.lineTo(left, top);
path.close();
mCanvas.drawPath(path, mPaint);
}
public void drawCircle(float x, float y, float r) {
mCanvas.drawCircle(x, y, r, mPaint);
}
/**
* Draw arrow
*
* #param sx
* #param sy
* #param ex
* #param ey
*/
public void drawAL(int sx, int sy, int r, float degree) {
int ex = (int) (sx + 2 * r);
int ey = (int) (sy + 2 * r);
switch (new Float(degree).intValue()) {
case 90:
ex = (int) (sx - 2 * r);
ey = (int) (sy + 2 * r);
break;
case 180:
ex = (int) (sx - 2 * r);
ey = (int) (sy - 2 * r);
break;
case 270:
ex = (int) (sx + 2 * r);
ey = (int) (sy - 2 * r);
break;
}
double H = 8; // the height of arrow
double L = 3.5; // half of bottom line
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // the rotation of arrow
double arraow_len = Math.sqrt(L * L + H * H); // the length of arrow
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3) the first point
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4) the second point
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// draw line
mCanvas.drawLine(sx, sy, ex, ey, mPaint);
Path triangle = new Path();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.close();
mCanvas.drawPath(triangle, mPaint);
}
// Calculate
public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (mAnnotation != null) {
float minX = 0;
float minY = 0;
float maxX = 0;
float maxY = 0;
switch (mAnnotation.getShape()) {
case Annotation.KEY_SHAPE_ARROW:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
case Annotation.KEY_SHAPE_SQUARES:
minX = getLeft() + mAnnotation.getRadius() / 2;
minY = getTop() + mAnnotation.getRadius() / 2;
maxX = getLeft() + getWidth() - mAnnotation.getRadius() / 2;
maxY = getTop() + getHeight() - mAnnotation.getRadius() / 2;
break;
case Annotation.KEY_SHAPE_CIRCLE:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
case Annotation.KEY_SHAPE_TRIANGLE:
minX = getLeft() + mAnnotation.getRadius();
minY = getTop() + mAnnotation.getRadius();
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
}
if (x > minX && x < maxX && y > minY && y < maxY) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
case MotionEvent.ACTION_MOVE:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
break;
}
}
return true;
}
return false;
}
public void startAnnotate(String pathName) {
mAnnotation = new Annotation();
mAnnotation.setMaxRadius(getWidth() / 2);
mAnnotation.setColor(Color.RED);
mAnnotation.setX(getWidth() / 2);
mAnnotation.setY(getHeight() / 2);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
annotations.add(mAnnotation);
postInvalidate();
}
public void stopAnnotate() {
if (annotations.isEmpty()) {
mPaint = null;
mAnnotation = null;
} else {
annotations.remove(annotations.size() - 1);
if (annotations.isEmpty()) {
mAnnotation = null;
mPaint = null;
} else {
mAnnotation = annotations.get(annotations.size() - 1);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mAnnotation.getColor());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
}
}
postInvalidate();
}
public void plus() {
if (mAnnotation != null) {
mAnnotation.plus();
postInvalidate();
}
}
public void sub() {
if (mAnnotation != null) {
mAnnotation.sub();
postInvalidate();
}
}
public void rotateRight() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() >= 360) {
mAnnotation.setDegree(0);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() + 90);
}
postInvalidate();
}
}
public void rotateLeft() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() <= 0) {
mAnnotation.setDegree(270);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() - 90);
}
postInvalidate();
}
}
public void changeColor(int color) {
if (mAnnotation != null) {
mAnnotation.setColor(color);
mPaint.setColor(color);
}
postInvalidate();
}
/**
* Change the shape
*
* #param id
*/
public void changeShape(int id) {
if (mAnnotation != null) {
mAnnotation.setShape(id);
postInvalidate();
}
}
/**
* Draw line
*
* #param fromX
* start point x
* #param fromY
* start point y
* #param toX
* end point x
* #param toY
* end point y
*/
public void drawLine(float fromX, float fromY, float toX, float toY) {
Path linePath = new Path();
linePath.moveTo(fromX, fromY);
linePath.lineTo(toX, toY);
linePath.close();
mCanvas.drawPath(linePath, mPaint);
invalidate();
}
public List<Annotation> getAnnotations() {
return annotations;
}
private void rotatePath(Path path, float degree) {
Matrix mMatrix = new Matrix();
RectF bounds = new RectF();
path.computeBounds(bounds, true);
mMatrix.postRotate(degree, (bounds.right + bounds.left) / 2, (bounds.bottom + bounds.top) / 2);
path.transform(mMatrix);
}
}
2. In your activity, create the AnnotationView and assign your image to it, then append this view to your root view.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AnnotationView mPreview = (FrameLayout) findViewById(R.id.camera_preview);
AnnotationView mAnnotationView = new AnnotationView(this);
Bitmap bitmap;
try {
bitmap = CBitmapUtil.decode(mPictureFile); // Get your image as a bitmap
mAnnotationView.setImageBitmap(bitmap);
mPreview.addView(mAnnotationView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Photo cannot be saved, please try again later.", Toast.LENGTH_SHORT).show();
}
}

How to make sprite bounce of the sides of the screen

I'm using libgdx in java android studio. i have just started. i'm working on android phone. i not using any cameras. all i want is a sprite bounce of all four sides of the screen without tapping. i tried many codes i thought would work but nope. i hope u guys can help me. I'm expecting an answer soon as possible. Thanks
this is what i have:
SpriteBatch batch;
Texture background;
Sprite backgroundsprite;
Sprite ballsprite;
Texture line;
Texture ballimg;
BitmapFont credits;
BitmapFont input;
BitmapFont play;
float dt;
String string = "";
float ballx;
float bally;
float speedx;
float speedy;
Rectangle screenrect;
Rectangle ballrect;
float screenLeft ;
float screenBottom ;
float screenTop ;
float screenRight ;
#Override
public void create() {
batch = new SpriteBatch();
speedx = 5f * dt;
speedy = 5f * dt;
createsprite();
createbackground();
createtext();
ballx = ballsprite.getX();
bally = ballsprite.getY();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
dt = Gdx.graphics.getDeltaTime();
ballsprite.setPosition(ballx + speedx,ballsprite.getY());
ballsprite.translateX(speedx);
float left = ballrect.getX();
float bottom = ballrect.getY();
float top = bottom + ballrect.getHeight();
float right = left + ballrect.getWidth();
if(left < screenLeft) {
string = "left";
speedx = 5f*dt;
}
if(right > screenRight)
{
string = "right";
speedx = -5f*dt;
}
if(bottom < screenBottom)
{
string = "bottom";
}
if(top > screenTop)
{
string = "top";
}
batch.begin();
backgroundsprite.draw(batch);
ballsprite.draw(batch);
rendertext();
batch.end();
}
public void createbackground() {
background = new Texture("images/BackgroundGodwin.jpg");
backgroundsprite = new Sprite(background);
backgroundsprite.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
screenrect = new Rectangle(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
screenLeft = screenrect.getX();
screenBottom = screenrect.getY();
screenTop = screenBottom + screenrect.getHeight();
screenRight = screenLeft + screenrect.getWidth();
}
public void createsprite() {
ballimg = new Texture("images/SpriteGodwin.png");
ballsprite = new Sprite(ballimg);
ballsprite.setScale(0.65f);
ballsprite.setPosition(Gdx.graphics.getWidth()/3,Gdx.graphics.getHeight()/2);
ballrect = new Rectangle(ballsprite.getBoundingRectangle());
}
#Override
public void dispose() {
batch.dispose();
ballimg.dispose();
background.dispose();
credits.dispose();
play.dispose();
input.dispose();
line.dispose();
}
public void createtext(){
play = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
play.setColor(com.badlogic.gdx.graphics.Color.GOLD);
credits = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
credits.setColor(com.badlogic.gdx.graphics.Color.GOLD);
input = new BitmapFont(Gdx.files.internal("fonts/realfont.fnt"));
input.setColor(com.badlogic.gdx.graphics.Color.OLIVE);
}
public void rendertext() {
credits.draw(batch, "Maded", Gdx.graphics.getWidth() / 7 - 50, Gdx.graphics.getHeight() / 9);
play.draw(batch, "Touch the Screen to play!!", Gdx.graphics.getWidth() / 2 - 175, Gdx.graphics.getHeight() - 80);
input.draw(batch, string, Gdx.graphics.getWidth() / 2 - 160, Gdx.graphics.getHeight() - 120);
}
}
I made a very simple version of what you want:
public class BouncyGame extends ApplicationAdapter {
SpriteBatch batch;
Texture ball;
float speedX = 3f;
float speedY = 3f;
int x;
int y;
#Override
public void create () {
batch = new SpriteBatch();
ball = new Texture("ball.png");
x = Gdx.graphics.getWidth()/2;
y = Gdx.graphics.getHeight()/2;
}
#Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//When the ball's x position is on either side of the screen.
//The width of the sprite is taken into account.
if (x > Gdx.graphics.getWidth() - ball.getWidth()/2 || x < 0 + ball.getWidth()/2) {
//Here we flip the speed, so it bonces the other way.
speedX = -speedX;
}
//Same as above, but with on the y-axis.
if (y > Gdx.graphics.getHeight() - ball.getHeight()/2 || y < 0 + ball.getHeight()/2) {
speedY = -speedY;
}
//Move the ball according to the speed.
x += speedX;
y += speedY;
batch.begin();
//Draw the ball so the center is at x and y. Normally it would be drawn from the lower left corner.
batch.draw(ball, x - ball.getWidth()/2, y - ball.getHeight()/2);
batch.end();
}
}
It will result in the following:
http://gfycat.com/TatteredCarefreeHapuku
There are numerous ways to improve this code, you could for example use vectors, and I wouldn't recommend using it in your final product, but it might help you figure out how to do something like this for your own project.

Categories