How to create Object with mouse click LibGdx - java

Class FirstTower:
public class FirstTower extends Sprite {
private Map map;
private Texture texture;
private float transfer = 1000;
private float hp;
private float radius;
public FirstTower(Map map) {
this.texture = new Texture("square.png");
this.map = map;
this.hp = 100;
radius = 40;
}
#Override
public void render(SpriteBatch batch) {
batch.draw(texture, Gdx.input.getX() - radius, transfer - Gdx.input.getY() - radius);
}
#Override
public void updade(float dt) {
}
}
I need simple to create example of this class (object of FirstTower) with mouse click on gamefield.
How can I do this?
Try to search, but not find anything useful.
Image of object follow with my cursor.
Here is screen when app is running:

You need to set the GDX InputProcessor. This is done by executing the following:
Replace MyClass with the class you wish to create (FirstTower I believe)
Gdx.input.setInputProcessor(new InputProcessor() {
public boolean touchDown(int x, int y, int point, int button) {
if (button == Input.Buttons.LEFT) {
new MyClass();
return true;
}
return false;
}
});
Note: I have excluded the other methods when creating a new InputProcessor to keep this answer tidy, but you will need to implement those methods.

Related

Java game with libGDX: my ship cant move to the right

I'm doing a Java Project that consists of making a "Space Invaders" clone. I'm starting with the ship movement, searching on stackOverflow I found this code:
if(Gdx.input.isKeyPressed(Input.Keys.LEFT) )
x -= Gdx.graphics.getDeltaTime() * PlayerSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) )
x += Gdx.graphics.getDeltaTime() * PlayerSpeed;
I use it to the playerShip(the class below):
public class PlayerShip extends Ship {
private Animator animator;
private float PlayerSpeed = 20.0f;
private int x,y;
public PlayerShip(SpriteBatch batch){
this.animator=new Animator(batch,"ship.png", 5, 2);
}
public void create(){
animator.create();
}
public void render(){
this.animator.render(this.x,this.y);
if(Gdx.input.isKeyPressed(Input.Keys.LEFT) )
x -= Gdx.graphics.getDeltaTime() * PlayerSpeed;
if(Gdx.input.isKeyPressed(Input.Keys.RIGHT) )
x += Gdx.graphics.getDeltaTime() * PlayerSpeed;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
}
Game(main):
public class Game extends ApplicationAdapter {
private SpriteBatch batch;
private BackgroundManagement backgroundManagement;
private BitmapFont font;
private PlayerShip player;
private SmallShip smallShip;
#Override
public void create() {
Gdx.graphics.setWindowedMode(600, 800);
batch = new SpriteBatch();
player = new PlayerShip(batch);
smallShip = new SmallShip(batch);
player.create();
player.setX(300);
player.setY(100);
smallShip.create();
smallShip.setX(200);
smallShip.setY(400);
font = new BitmapFont(Gdx.files.internal("gamefont.fnt"),
Gdx.files.internal("gamefont.png"), false);
backgroundManagement = new BackgroundManagement(batch);
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
backgroundManagement.render();
player.render();
smallShip.render();
batch.end();
}
#Override
public void dispose() {
batch.dispose();
}
}
When trying on my code, the ship didn't move to the right, I had tried various solutions but i didn't found any, Any help is appreciated, thanks!
The position of the ship is an integer. Your increment is a float. You maybe have a decent graphics card which can render a simple game at e.g. 200+ fps continuous render (or more even could be crazy). In 200fps case the increment would be (1/200)*20 = 1/10 float.
integer += .1f
won't change the original integer.
Change your position to a float as well, then cast (or convert) to an integer when you need to actually render so x can increment very small values.

Libgdx - How to use "Long Press"?

I have tried finding an answer to solve the problem, but I think that I don't seem to understand how to use the long press in Libgdx.
I want my character to move right when I long press on the right half of the screen and left when I long press on the left half of the screen.
I have searched and tried.
Here is my InputHandler class :
public class InputHandler implements InputProcessor {
private MainCharacter myMainCharacter;
public InputHandler(MainCharacter mainCharacter) {
myMainCharacter = mainCharacter;
}
#Override
public boolean keyDown(int keycode) {
return false;
}
#Override
public boolean keyUp(int keycode) {
return false;
}
#Override
public boolean keyTyped(char character) {
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
myMainCharacter.onClick();
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
}
And here is my MainCharacter class :
public class MainCharacter {
private Vector2 position;
private Vector2 velocity;
private Vector2 acceleration;
private float rotation;
private int width;
private int height;
public MainCharacter(float x, float y, int width, int height) {
this.width = width;
this.height = height;
position = new Vector2(x, y);
velocity = new Vector2(0, 0);
acceleration = new Vector2(0, 460);
}
public void update(float delta) {
velocity.add(acceleration.cpy().scl(delta));
if (velocity.y > 200) {
velocity.y = 200;
}
position.add(velocity.cpy().scl(delta));
}
public void onClick() {
if (Gdx.input.getX() <= 135) {
Gdx.app.log("TAG", "LEFT");
position.x--;
} else if (Gdx.input.getX() >= 137) {
Gdx.app.log("TAG", "RIGHT");
position.x++;
}
}
public float getX() {
return position.x;
}
public float getY() {
return position.y;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
public float getRotation() {
return rotation;
}
}
I used onClick() method as a replacement until I find a solution for the problem. It works fine but it doesn't have the same effect as the long press. My character moves left when I click on the left side of the screen and right when I click on the right side of the screen. But of course it doesn't work when I long press.
So how can I use 'Long Press' ?
I would really appreciate your help.
Gokul gives a nice overview of the GestureListener but I do not believe this is what you are looking for. LongPress indeed only registers after some seconds of pressing and you want to have a touch control the character immediately.
There is no out of the box method in the listeners to keep detecting touched but you can create it yourself.
if (Gdx.input.isTouched())
{
//Finger touching the screen
// You can actually start calling onClick here, if those variables and logic you are using there are correct.
if (Gdx.input.getX() >= screenSize / 2)
{
//Right touched
}
else if (Gdx.input.getX() < screenSize / 2)
{
//Left touched
}
}
Just check for this every frame and do your logic.
You can implement the long press by implementing the GestureListner interface.
GestureDetector will let you detect the following gestures:
touchDown: A user touches the screen.
longPress: A user touches the screen for some time.
tap: A user touches the screen and lifts the finger again. The finger must not move outside a specified square area around the initial touch position for a tap to be registered. Multiple consecutive taps will be detected if the user performs taps within a specified time interval.
pan: A user drags a finger across the screen. The detector will report the current touch coordinates as well as the delta between the current and previous touch positions. Useful to implement camera panning in 2D.
panStop: Called when no longer panning.
fling: A user dragged the finger across the screen, then lifted it. Useful to implement swipe gestures.
zoom: A user places two fingers on the screen and moves them together/apart. The detector will report both the initial and current distance between fingers in pixels. Useful to implement camera zooming.
pinch: Similar to zoom. The detector will report the initial and current finger positions instead of the distance. Useful to implement camera zooming and more sophisticated gestures such as rotation.
A GestureDetector is an event handler. To listen for gestures, one must implement the GestureListener interface and pass it to the constructor of the GestureDetector. The detector is then set as an InputProcessor, either on an InputMultiplexeror as the main InputProcessor:
public class MyGestureListener implements GestureListener{
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean tap(float x, float y, int count, int button) {
return false;
}
#Override
public boolean longPress(float x, float y) {
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean zoom (float originalDistance, float currentDistance){
return false;
}
#Override
public boolean pinch (Vector2 initialFirstPointer, Vector2 initialSecondPointer, Vector2 firstPointer, Vector2 secondPointer){
return false;
}
#Override
public void pinchStop () {
}
}
You have to set the GestureDetector that contains your GestureListener as the InputProcessor:
Gdx.input.setInputProcessor(new GestureDetector(new MyGestureListener()));
For more details, check out the link below
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/input/GestureDetector.GestureListener.html

libgdx: Why does my custom actor have a memory leak?

I have created the following custom actor to draw lines on libgdx
public class LineWidget extends Actor implements Disposable {
private Position posA;
private Position posB;
public final Vector2 _A;
public final Vector2 _B;
private TextureRegion lineTexture;
private final TextureRegion lineTextureGreen = Assets.instance.Images.lineGreen;
private final TextureRegion lineTextureOrange = Assets.instance.Images.lineOrange;
private final TextureRegion lineTextureRed = Assets.instance.Images.lineRed;
public LineWidget(Position A, Position B) {
this._A = A.getPositionVector();
this._B = B.getPositionVector();
this.posA = A;
this.posB = B;
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
setLineColor(posA, posB);
float xdif = _B.x-_A.x;
float ydif = _B.y-_A.x;
float l2 = xdif*xdif+ydif*ydif;
float invl = (float)(1/Math.sqrt(l2));
//dif is vector with length linewidth from first to second vertex
xdif*=invl*5;
ydif*=invl*5;
float floatBits = batch.getColor().toFloatBits();
//draw quad with width of linewidth*2 through (x1, y1) and (x2, y2)
float[] verts = new float[]{_A.x+ydif, _A.y-xdif, floatBits, lineTexture.getU(), lineTexture.getV(),
_A.x-ydif, _A.y+xdif, floatBits, lineTexture.getU2(), lineTexture.getV(),
_B.x-ydif, _B.y+xdif, floatBits, lineTexture.getU2(), lineTexture.getV2(),
_B.x+ydif, _B.y-xdif, floatBits, lineTexture.getU(), lineTexture.getV2()};
batch.draw(lineTexture.getTexture(), verts, 0, 20);
}
#Override
public void setSize(float width, float height) {
super.setSize(width, height);
}
#Override
public void dispose() {
}
private void setLineColor(Position A, Position B) {
if(A.get_value() != null && B.get_value() != null) {
if(A.get_value() == 1 || B.get_value() == 1) {
lineTexture = lineTextureGreen;
return;
}else {
lineTexture = lineTextureRed;
}
} else {
lineTexture = lineTextureRed;
}
}
}
When I create the actor memory consumption keeps going up but I cannot detect where this leak is happening. How can I fix this actor to stop leaking memory?
EDIT: I am drawing this actor inside another actor which extends Group Actor class. Group actor class does not leak memory and the only thing it is doing for now is draw LineWidget by calling addActor(). This actor is then added to a stage inside a screen. I dont think this information is important but just adding it in case. I have tested all this actors and the memory leak begins when I draw LineWidget Actor.

Moving circle towards touched point

i'm trying to move a circle to the point i touch in my running app. I want to see the circle moving along a path towards this point i touch.
I have three classes:
public class Drawing extends View{
Context ctx;
static Circle c1;
private float circleCenterX = 100;
private float circleCenterY = 100;
private float lerpX;
private float lerpY;
private float time = 25;
private float frames = 100;
public Drawing(Context context) {
super(context);
this.ctx = context;
c1 = new Circle (165, 350, 33);
}
public void update(float x, float y) {
this.circleCenterX = x;
this.circleCenterY = y;
}
protected void onDraw (android.graphics.Canvas canvas){
Paint p = new Paint();
p.setColor(Color.GREEN);
lerpX = (circleCenterX - c1.getX()) * (time / frames) + c1.getX();
lerpY = (circleCenterY - c1.getY()) * (time / frames) + c1.getY();
canvas.drawCircle(lerpX, lerpY, c1.getR(), p);
c1.setX(lerpX);
c1.setY(lerpY);
}
public class Circle {
private float x;
private float y;
private float r;
public Circle(float x, float y, float r) {
super();
this.x = x;
this.y = y;
this.r = r;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public float getR() {
return r;
}
public void setR(float r) {
this.r = r;
}`
public class Game extends Activity implements OnTouchListener {
Drawing d;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
d=new Drawing(this);
setContentView(d);
d.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent me) {
d.update(me.getX(), me.getY());
d.invalidate();
return true;
}
I think i will need something like a while or for loop to increment the x and y coords and or maybe need a speed value?!
Maybe im totally wrong and its a lot of more math to get it.
Thanks for your help
Cheers
Every time onDraw is called you need to move the circle a bit. The easiest way is just to move a certain number of pixels each time it's called.
To be able to do this you need to keep track of:
Where the animation started
Where you want the animation to end
Use linear interpolation to calculate the position of the circle in each onDraw call

ApplyLinearForce to dynamic body causes NullPointerException/ Libgdx box2d

I am developing an Android game using the libgdx box2d library in Eclipse. In the game, there's a ball that falls after touching the start button. But I get a nullpointerexception when the ball contacts the dynamic body.
On contact I want to applyLinearForce to that dynamic body. But I keep getting nullpointerexception on contact of the ball and dynamic body.
ContactHandler class:
public class ContactHandler implements ContactListener {
InputHandler input;
#Override
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData() == "do1" && contact.getFixtureB().getBody().getUserData() == "ball"){
System.out.println("beginContact");
input = new InputHandler();
input.getBody1().applyLinearImpulse(10, 0, 0, 0, true);
}
}
InputHandler class:
public class InputHandler implements InputProcessor {
private OrthographicCamera camera;
private Ball ball;
private DragObject dragObject;
private boolean start = false;
private Vector3 touch = new Vector3();
private Vector3 dragTo = new Vector3();
public InputHandler(){
}
public InputHandler(OrthographicCamera camera, Ball ball,
DragObject dragObject) {
this.camera = camera;
this.ball = ball;
this.dragObject = dragObject;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (!start) {
for (Body body : dragObject.getBody()) {
if (touch.x > body.getPosition().x - dragObject.getWidth() - 1
&& touch.x < body.getPosition().x
+ dragObject.getWidth() + 1) {
if (touch.y > body.getPosition().y - dragObject.getHeight()
- 1
&& touch.y < body.getPosition().y
+ dragObject.getHeight() + 1) {
dragTo.set(screenX, screenY, 0);
camera.unproject(dragTo);
body.setTransform(dragTo.x, dragTo.y, 0);
touch.set(screenX, screenY, 0);
camera.unproject(touch);
}
}
}
}
return false;
}
public Body getBody1(){
return dragObject.getBody().get(0);
}
DragObject class:
public static Array<Body> bodies = new Array<Body>();
public static int count = 0;
public DragObject(){
}
public DragObject(World world, float x, float y, float width, float height) {
this.world = world;
this.width = width;
this.height = height;
initialize();
body1 = world.createBody(bodyDef1);
body1.createFixture(fixtureDef);
body1.setUserData("do1");
bodies.add(body1);
}
public Array<Body> getBody() {
return bodies;
}
Your constructor for the input handler is wrong, these lines should be removed:
public InputHandler(){
}
Because when you call this constructor here:
public void beginContact(Contact contact) {
if(contact.getFixtureA().getBody().getUserData() == "do1" && contact.getFixtureB().getBody().getUserData() == "ball"){
System.out.println("beginContact");
//You are using the wrong contructor, therefore body1 or dragObject is never initialised
input = new InputHandler();
//The null pointer exception is here, no body1 has been initialised yet
input.getBody1().applyLinearImpulse(10, 0, 0, 0, true);
}
You need to make the contructor match and create a new DragObject within the InputHandler class and as a side note it isn't very efficient initialising the class every time the body collides I am sure you can think of a better way to organise it.

Categories

Resources