pretty much i want my texture to move to a random position on the screen when its touched and when its missed i want to system.out("missed"). I cant figure out how to see if its touched. right now i can only get if the screen is touch and it records about 10 touches for every one touch because it renders so fast.
public void render(float delta) {
Gdx.gl.glClearColor(0,1,0,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
if(Gdx.input.isTouched()) {
int randomX2 = (int)MathUtils.random(100,500);
int randomY2 = (int)MathUtils.random(100,500);
game.batch.draw(boxImage, randomX2, randomY2);
}
game.batch.end();
}
If randomX2 and randomY2 are your coordinates for the texture, you can check with this code:
Rectangle bounds = new Rectangle(randomX2, randomY2, boxImage.getWidth(), boxImage.getHeight());
Vector3 tmp = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(tmp);
if (bounds.contains(tmp.x, tmp.y)) {
System.out.println("Is touched");
}
I could solve this without using Vector3.
var upArrowCircle = Circle(randomX, randomY, radius)
if(upArrowCircle.contains(Gdx.input.getX().toFloat(), Gdx.input.getY().toFloat()))
{
Gdx.app.log("upArrow", "contains")
}
For me it works perfectly.
Related
I am trying to bounce a ball in an android project using the libGDX game engine.
ball = new Texture("football.jpg");
batch = new SpriteBatch();
sprite = new Sprite(ball);
render(float delta)
{
batch.begin();
sprite.draw(batch);
batch.end();
stage.draw();
jumpUp(); //here i call the jump function..
}
The jump function looks like this:
public void jumpUp()
{
sprite.setY(sprite.getY()+2);
dem=sprite.getY();
if(dem==100.0f)
{
jumpDown();
}
}
public void jumpDown()
{
sprite.setY(sprite.getY()-1);
}
The ball is actually moving upward but it's not coming down again.
Should I also call jumpDown() in the render() method?
The official wiki libgdx lifecycle states that game logic updates are also done in the render() function. So, yes you should also call jumpDown() there. I would however propose that you keep it simple and only use one function like this:
private Texture ballTexture;
private Sprite ballSprite;
private SpriteBatch batch;
private dirY = 2;
create(){
ballTexture = new Texture("football.jpg");
ballSprite = new Sprite(ballTexture);
batch = new SpriteBatch();
}
render(float delta){
recalculateBallPos(delta);
batch.begin();
sprite.draw(batch);
batch.end();
stage.draw();
}
private void recalculateBallPos(delta){
float curPos = ballSprite.getY();
if(curPos + dirY > 100 || curPos + dirY < 0){
dirY = dirY * -1 //Invert direction
}
ballSprite.setY(curPos+dirY)
}
This still might look a bit choppy but I hope it's a good way to start.
The problem is the following:
Your Ball goes up, until it's y-value is exactly 100.0f. If thats the case, you decrease it by 1, which results in an y-value of 99.0f.
In the next render you call jumpUp again, which results in a y-value of 101.
This time your condition is not met, the jumpDown() is not called.
Even if you change your condition to >= 100.0f, your Ball will always move up by 2 and down by 1, which results in an increasing y-value.
Instead you should call the method something like updateBallPos and store a boolean up.
In updateBallPos you can simply check the boolean up, if it is true, increase the y-value, if it is fales, decrease it.
Also you need to update this boolean up in the updateBallPos method:
if (up && sprite.getY() >= 100.0f)
up = false
else if (!up && sprite.getY() <= 0.0f)
up = true
I'm using a GestureListener to try and create a panning menu, but even though the camera's coordinates are being changed and it's being updated, nothing moves. I think it might be because the stage is drawing relative to the camera but I'm not sure how I would change that.
How I'm going about it:
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
...
gesture = new GestureDetector(this);
InputMultiplexer im = new InputMultiplexer();
im.addProcessor(gesture);
im.addProcessor(stage);
Gdx.input.setInputProcessor(im);
} //end initialization of CustomizeScreen
public void render(float delta) {
Gdx.gl.glClearColor(0.2f, 0.2f, 0.2f, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 60f)); //0, 18, 31 for layer style
stage.draw();
Table.drawDebug(stage);
batch.setProjectionMatrix(camera.combined);
g.batch.begin();
g.font.setScale(2);
g.font.setColor(Color.WHITE);
g.font.draw(g.batch, "Coins: " + Filer.getCoins(), 15, Gdx.graphics.getHeight() - 15);
g.font.draw(g.batch, message, 0, 150);
g.batch.end();
camera.update();
}
...
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "Pan, delta:" + Float.toString(deltaX) +
"," + Float.toString(deltaY);
camera.translate(deltaX, 0, 0);
camera.update();
return false;
}
I've checked for camera coordinates (camera.position.x) in the update method, so I know it's actually changing something. But all my buttons remain the same. They are placed in thirds of the screen width (Gdx.graphics.getWidth() / 3).
Am I missing something, or doing it wrong? I'd think I'm doing it correctly based on everything I'm found on Google.
Thanks :)
The Stage class has different constructors. Some of those constructors take a Viewport, which contains a Camera. If you use a constructor without Viewport, the Stage creates a new Viewport with a new Camera.
In that case it will use the created Viewport (and Camera) for all it's drawing, unless you switch the Viewport by calling setViewport.
As you don't show, how you create the Stage i am not sure if thats the porblem in your case, but if that is the problem, you can solve it by creating a Viewport with your Camera and passing it to the Stage or by changing the Camera of the Viewport (stage.getViewport().setCamera(myCamera)).
Hope it helps.
I have a bug object that I want to move across the screen as soon as the game starts. The bug starts from the bottom left of the screen and is supposed to move to the top right and stop. What I have is the bug never really gets to the top right because the game screen(X and Y) size are not equal. How do I make the bug move to that position?
This is what I have.
public void create() {
spriteBatch = new SpriteBatch();
bug = new Sprite(new Texture("EnemyBug.png"));
bug.setSize(50, 85);
bug.setPosition(0,0);
}
public void render() {
xdeg++;
ydeg++;
Gdx.gl.glClearColor(0.7f, 0.7f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
bug.translate(xdeg, ydeg);
bug.draw(spriteBatch);
spriteBatch.end();
}
I'll assume that you know your window width (W) and height (H). First find the W / H ratio:
float ratio = screenWidth / screenHeight;
Then update your bug position accordingly:
bug.translate(ratio, 1);
This will make the sprite move through the screen diagonal.
I have a player setup with box2d and I am trying to draw a sprite over the player. The player spawns in the middle of the screen, while the sprite spawns in the lower left hand corner of the screen but does move along with the player entity, just starting at a different location.
GameScreen snippet:
#Override
public void render(float delta) {
super.render(delta);
player.update();
world.step(TIMESTEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
}
#Override
public void show() {
player = new Player(world, 0, 0);
}
Player class snippet:
public Player(World world, float x, float y) {
texture = new Texture(Gdx.files.internal("sprites/Player.png"));
sprite = new Sprite(texture);
}
public void update() {
batch = new SpriteBatch();
batch.begin();
sprite.draw();
sprite.setPosition(body.getPosition().x, body.getPosition().y);
batch.end();
body.setLinearVelocity(impulse);
}
I tried setting the position of the sprite in the constructor based on the body's coordinates but it doesn't seem to be working. I have removed body & fixture code. Any push in the right direction is appreciated.
If you enable box2d debug render, you'll probably find that both the texture and the body are starting at the left corner of the screen. Actually, 0, 0 are supposed to be the coordinates for the left bottom corner. In order to set your body in the center of the screen, you should set something like
(SCREEN_WIDTH / 2) / PTM_RATIO, (SCREEN_HEIGHT / 2) / PTM_RATIO
as your body initial position.
I want to make a button clickable, but it isn't working - it seems like I need to use unproject() but I can't figure out how. The code in question is:
Texture playButtonImage;
SpriteBatch batch;
ClickListener clickListener;
Rectangle playButtonRectangle;
Vector2 touchPos;
OrthographicCamera camera;
#Override
public void show() {
playButtonImage = new Texture(Gdx.files.internal("PlayButton.png"));
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
batch = new SpriteBatch();
playButtonRectangle = new Rectangle();
playButtonRectangle.x = 400;
playButtonRectangle.y = 250;
playButtonRectangle.width = 128;
playButtonRectangle.height = 64;
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(playButtonImage, playButtonRectangle.x, playButtonRectangle.y);
batch.end();
if (Gdx.input.isTouched()) {
Vector2 touchPos = new Vector2();
touchPos.set(Gdx.input.getX(), Gdx.input.getY());
if (playButtonRectangle.contains(touchPos)) {
batch.begin();
batch.draw(playButtonImage, 1, 1);
batch.end();
}
}
}
In general you use camera.unproject(Vector) to transform your screen coordinates from a click or touch to your gameworld. This is needed because the origin is not necessarily the same and using the camera you can also zoom in and out, move around, rotate and so on. Unprojecting will take care of all of that and give you your game world coordinate matching the pointers position.
In your example it would go like this:
Vector3 touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
Having this said you should actually not do this UI task manually. Libgdx has also some shipped UI functionality which is called a Stage (see this). There are lots of widgets already available (see this). They use skins (you can get a basic one from here, you need all the uiskin.* files). They automatically forward inputevents to the socalled Actors, e.g. a button, and you just need to implement handling of those events.
with camera.unproject(Vector3); you can translate screen coordinates to game world coordinates.
Vector3 tmpCoords = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(tmpCoords);
tmpCoords.x //is now the touched X coordinate in the game world coordinate system
tmpCoords.y //is now the touched Y coordinate in the game world coordinate system.
In addition to that it is best practice to define a tmpVector as a field an Instantiate a Vector3 object only once. You can then do the same with the .set() method.
tmpCoords.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(tmpCoords);
tmpCoords.x //is now the touched X coordinate in the game world coordinate system
tmpCoords.y //is now the touched Y coordinate in the game world coordinate system.
Therefore you reduce object creation and remove unnecessary GC calls which lead to microlag.
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(playButtonImage, playButtonRectangle.x, playButtonRectangle.y);
batch.end();
if (Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(),0);
camera.unproject(touchPos);
if (playButtonRectangle.contains(touchPos.x, touchPos.y)) {
batch.begin();
batch.draw(playButtonImage, 1, 1);
batch.end();
}
}
}
when ever u need a touch point from user and to convert those touchpoints to camera u need to unproject them to camera coordinates by camera coordinates
camera.unproject(touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0));