Bullet trajectory using LIBGDX - libgdx

Im having problems with the bullet trajectory,the bullet is not accurately fire at the mouse cursor on screen when i do clicks.
Here my code:
#Override
public boolean mouseMoved(int screenX, int screenY) {
touchPos = new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
gamecam.unproject(touchPos);
return false;
}
public void shoot() {
bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(x,y);
body = world.createBody(bodyDef);
polygonShape = new PolygonShape();
polygonShape.setAsBox(0.2f / 2.0f, 0.01f /2.0f);
fixtureDef2 = new FixtureDef();
fixtureDef2.shape = polygonShape;
float calc= (float) (Math.atan2(touchPos.y-(body.getPosition().y),touchPos.x-body.getPosition().x));
body.setTransform(body.getWorldCenter(),calc);
body.applyLinearImpulse((touchPos.x-body.getPosition().x)*3, (touchPos.y-body.getPosition().y)*3, 0, 0, true);
}

You're removing the bodies position from the impulse vector which is causing your body to be misaligned with your target.
body2.applyLinearImpulse(touchPos.x, touchPos.y, 0, 0, true);

Related

libgdx: How do i get the result of an orthographic camera through another orthographic camera?

I would like to have a TV screen on my stage. I have a master scene containing the TV screen and some other things (some sprites) and the scene corresponding to what I want to render in the TV.
So I would like to render the TV scene through an OrthographicCamera and then put the result in something like a sprite which can then be rendered through the master orthographic camera, how to do that?
I know that one can use multiple camera in multiple viewports but these are directly rendered on the pixels of my computer screen.
Any advice would be much appreciated
This can be achieved by rendering the scene from the perspective of a screen camera to a FrameBuffer and then taking the TextureRegion from the FrameBuffer and rendering that to screen and then render the scene again.
For example:
In the above example the cyan rect shows what the in-scene camera sees, and this is rendered to the grey box, it is possible to move both the scene camera and the main camera independentely.
By creating and grabbing the TextureRegion from a FrameBuffer
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
all render calls can be made to affect only the screenFrameBuffer by calling screenFrameBuffer.begin(), after screenFrameBuffer.end() is called the next draw call will again affect the actual screen/window.
So in in the render method you can first draw your scene to the FrameBuffer
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
And then draw it again, followed by the "screen" as a sprite:
renderScene(sceneCamera, Color.BLACK);
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
Complete source code for the gif above is:
package com.bornander.sandbox;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.math.RandomXS128;
import com.badlogic.gdx.math.Vector2;
public class MyGdxGame implements ApplicationListener {
public static class Ball {
public Vector2 position = new Vector2();
public Vector2 velocity = new Vector2();
public float size = 1.0f;
public Color color = new Color();
public void render(ShapeRenderer shapeRenderer) {
shapeRenderer.setColor(color);
shapeRenderer.circle(position.x, position.y, size, 16);
}
public void update() {
position.x += velocity.x * Gdx.graphics.getDeltaTime();
position.y += velocity.y * Gdx.graphics.getDeltaTime();
}
}
static RandomXS128 rnd = new RandomXS128();
OrthographicCamera sceneCamera;
OrthographicCamera screenCamera;
ShapeRenderer shapeRenderer;
SpriteBatch batch;
FrameBuffer screenFrameBuffer;
TextureRegion screenTexture;
Ball[] balls;
private static float rnd(float min, float max) {
return min + rnd.nextFloat() * (max - min);
}
#Override
public void create() {
float aspectRatio = (float) Gdx.graphics.getWidth() / (float)Gdx.graphics.getHeight();
sceneCamera = new OrthographicCamera(100.0f, 100.0f / aspectRatio);
screenCamera = new OrthographicCamera(32.0f, 32.0f / aspectRatio);
batch = new SpriteBatch();
screenFrameBuffer = new FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);
screenTexture = new TextureRegion(screenFrameBuffer.getColorBufferTexture());
screenTexture.flip(false, true);
shapeRenderer = new ShapeRenderer();
balls = new Ball[128];
for(int i = 0; i < balls.length; ++i) {
balls[i] = new Ball();
balls[i].position.set(0, 0);
balls[i].velocity.set(rnd(-4, 4), rnd(-4, 4));
balls[i].size = rnd(1, 1);
balls[i].color.set(rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), rnd(0.5f, 1.0f), 1.0f);
}
}
private void renderScene(Camera camera, Color background) {
camera.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(background.r, background.g, background.b, background.a);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shapeRenderer.setProjectionMatrix(camera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
for(int i = 0; i < balls.length; ++i) {
balls[i].render(shapeRenderer);
}
shapeRenderer.end();
}
#Override
public void render() {
float cs = 8.0f;
for(int i = 0; i < balls.length; ++i)
balls[i].update();
if (Gdx.input.isKeyPressed(Input.Keys.LEFT))
sceneCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.RIGHT))
sceneCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.UP))
sceneCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.DOWN))
sceneCamera.position.y += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.A))
screenCamera.position.x -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.D))
screenCamera.position.x += cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.W))
screenCamera.position.y -= cs * Gdx.graphics.getDeltaTime();
if (Gdx.input.isKeyPressed(Input.Keys.S))
screenCamera.position.y += cs * Gdx.graphics.getDeltaTime();
// Render to framebuffer, clear the background to DARK_GRAY
screenFrameBuffer.begin();
renderScene(screenCamera, Color.DARK_GRAY);
screenFrameBuffer.end();
// Render to window/screen, clear backgroun to BLACK
renderScene(sceneCamera, Color.BLACK);
// Draw the framebuffer's texture as a sprite using a normal SpriteBatch
batch.setProjectionMatrix(sceneCamera.combined);
batch.begin();
batch.draw(screenTexture, -sceneCamera.viewportWidth / 2.0f,-sceneCamera.viewportHeight / 2.0f,0,0,screenCamera.viewportWidth,screenCamera.viewportHeight,1.0f, 1.0f, 0.0f);
batch.end();
// This just draws the outline of what the screen camera looks at
shapeRenderer.setProjectionMatrix(sceneCamera.combined);
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
shapeRenderer.setColor(Color.CYAN);
shapeRenderer.rect(
screenCamera.position.x - screenCamera.viewportWidth / 2.0f,
screenCamera.position.y - screenCamera.viewportHeight / 2.0f,
screenCamera.viewportWidth,
screenCamera.viewportHeight
);
shapeRenderer.end();
}
#Override
public void dispose() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}

Dragging a texture (without jump)

How can I drag a texture (image) without making it jump and centering itself on the mouse cursor (what I have below in my code)?
When I click on the texture, nothing should happen, and when I drag, the mouse cursor should stay in place (relative to the edges of the texture).
Example: https://s31.postimg.org/ojapwbj6j/Untitled_1.jpg
SpriteBatch batch;
Texture texture;
OrthographicCamera camera;
Vector3 spritePosition = new Vector3();
float offsetX, offsetY;
Vector3 input;
#Override
public void create () {
batch = new SpriteBatch();
texture = new Texture("badlogic.jpg");
camera = new OrthographicCamera();
camera.setToOrtho(false);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(texture, spritePosition.x, spritePosition.y);
batch.end();
if (Gdx.input.justTouched()){
int x1 = Gdx.input.getX();
int y1 = Gdx.input.getY();
input = new Vector3(x1, y1, 0);
camera.unproject(input);
offsetX = x1 - spritePosition.x;
offsetY = y1 - spritePosition.y;
}
if (Gdx.input.isTouched()) {
spritePosition.set(Gdx.input.getX() - offsetX, Gdx.input.getY() - offsetY, 0);
}
}
What you need to do is work out the offset of the mouse position relative to your image, and subtract that, rather than half the width / height as you're doing at the moment.
Here's some very rough pseudocode to show what I mean - You'll need to rewrite as Java...
if Gdx.input.justTouched {
get mouse position from Gdx.input
camera.unproject it into cameraX and cameraY
offsetX = cameraX - imageX
offsetY = cameraY - imageY
}
if Gdx.input.isTouched {
spritePisition.set(Gdx.input.getX() - offsetX, Gdx.input.getY - offsetY)
}
Why are you using camera.unproject?
Try this:
Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(texture, spritePosition.x, spritePosition.y);
batch.end();
if (Gdx.input.isTouched()) {
spritePosition.set(Gdx.input.getX() - texture.getWidth() / 2, Gdx.input.getY() + texture.getHeight() / 2, 0);
}
}

lwjgl Update VBO (color, vertices) through JSlider

sorry for my bad english.
I have a problem upadting a VBO through a JSlider and the stateChanged-Event. In general i want to figure it out by myself but i am stuck at the moment. so my first question is how to manipulate (update) the vbo when the following code was given:
public void update(){
farbe = (float)slider_c.getValue()/100f;
// x = (float)slider_x.getValue()/100f;
// y = (float)slider_y.getValue()/100f;
}
public float[] getPosition()
{
return new float[]{x,y};
}
/* Run Methode: window is started here
* Definition of frame loop
*/
public void run() {
try{
initWindow();
GL.createCapabilities();
initBuffers();
initShaders();
// Game Loop
while (glfwWindowShouldClose(window) == GL_FALSE) {
// initBuffers();
frame();
glfwSwapBuffers(window);
glfwPollEvents();
}
}
finally {
// Clean up
glfwTerminate();
errorCallback.release();
glDeleteProgram(program);
System.exit(0);
}
}
private void frame() {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
private void initBuffers() {
// from the secound one
if (vao > -1) {
glDeleteBuffers(vao);
glDeleteVertexArrays(vboPosition);
glDeleteVertexArrays(vboColor);
}
vao = glGenVertexArrays();
glBindVertexArray(vao);
vboPosition = glGenBuffers();
// x y z w
float[] positions2 = new float[]{
0.5f, 0.0f, 0.0f, 1.0f, // 1. Point
0.0f, 0.5f, 0.0f, 1.0f, // 2. Point
0.0f, 0.0f, 0.5f, 1.0f
};
FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(positions2.length);
dataBuffer.put(positions2);
dataBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, vboPosition);
// alloctate memory on the graphics card and upload bytes to it
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
GLUtil.checkGLError();
glEnableVertexAttribArray(0); // Position is index 0
glVertexAttribPointer(0, 4, GL_FLOAT, false, 0, 0L);
GLUtil.checkGLError();
vboColor = glGenBuffers();
// x y z w
float[] colors = new float[]{
1f, 0f, 0f, 1f, // P1 = red
0f, 1f, 0f, 1f, // green
0f, 0f, 1f, 1f, // blue
};
dataBuffer = BufferUtils.createFloatBuffer(colors.length);
dataBuffer.put(colors);
dataBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, vboColor);
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
GLUtil.checkGLError();
glEnableVertexAttribArray(1); // COLOR is index 1
glVertexAttribPointer(1, 4, GL_FLOAT, false, 0, 0L);
GLUtil.checkGLError();
}
private void initWindow() {
System.out.println("LWJGL version: " + Version.getVersion());
glfwSetErrorCallback(errorCallback = GLFWErrorCallback
.createPrint(System.err));
if (glfwInit() != GL_TRUE)
throw new IllegalStateException("Unable to initialize GLFW");
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
window = glfwCreateWindow(WIDTH, HEIGHT, "Demo", NULL, NULL);
if (window == NULL)
throw new RuntimeException("Failed to create the GLFW window");
glfwMakeContextCurrent(window);
glfwSwapInterval(1);
glfwShowWindow(window);
}
I hope someone can help me out with that. if you need more information - i am keeping an eye on this post and will reply immediately.
best regards
private void updateColors() {
float[] newColors = new float[]{
newColor, 0f, 0f, 1f, // P1 = red
0f, 1f, 0f, 1f, // green
0f, 0f, 1f, 1f, // blue
};
FloatBuffer dataBuffer = BufferUtils.createFloatBuffer(newColors.length);
dataBuffer.put(newColors);
dataBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, vboColor);
// alloctate memory on the graphics card and upload bytes to it
glBufferData(GL_ARRAY_BUFFER, dataBuffer, GL_STATIC_DRAW);
glEnableVertexAttribArray(1); // Color at index 1
}
I solved it by using the method seen above within the while loop (the frame loop).

Box2d Body to follow mouse movement

I am trying a box2d body to rotate following the mouse. Here's an image to clarify what I mean.
The red and blue circles are current point of the mouse and the body (of corresponding color) moving/rotating to follow it. Basically the rectangle should rotate with its one end pointed towards where the mouse pointer is.
Here's my code so far,
World world;
Body body, bullet;
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
#Override
public void create() {
world = new World(new Vector2(0, 0f), true);
debugRenderer = new Box2DDebugRenderer();
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(10, 10);
body = world.createBody(bodyDef);
PolygonShape shape = new PolygonShape();
shape.setAsBox(2, 5);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
Fixture fixture = body.createFixture(fixtureDef);
shape.dispose();
Gdx.input.setInputProcessor(this);
camera = new OrthographicCamera(200, 100 * (h / w));
camera.position.set(camera.viewportWidth / 2f, camera.viewportHeight / 2f, 0);
camera.update();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
camera.update();
debugRenderer.render(world, camera.combined);
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
int mouseX = screenX;
int mouseY = Gdx.graphics.getHeight() - screenY;
float rotateAngle = MathUtils.radiansToDegrees * MathUtils.atan2((float) mouseY - (float) body.getPosition().y, (float) mouseX - (float) body.getPosition().x);
body.setTransform(body.getPosition(), rotateAngle / 57.2957795f);
return true;
}
And here's a gif of how it appears now.
as you can see the body gets skewed and also doesn't rotate properly. What am I missing?
The skew looks like a problem with aspect correction, try,
camera = OrthographicCamera(200, 100 * (w / h));
or even,
camera = OrthographicCamera(200, 100);
To get the end of the box to follow the mouse as in the picture just redefine the box,
shape.setAsBox(5, 2, Vector2(offset, 0), 0);

libgdx - group transformation

I'm new in LibGDX.
I created group with actors in show method and add listener (where i calculate rotation matrix) and want to rotate all actors from group with batch.setTransformMatrix(matrixResult); but nothing happens. How can I force to rotate all actors of group?
#Override
public void show() {
camera = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(0f, 0f, - 120);
camera.lookAt(0,0,0);
camera.near = 0.1f;
camera.far = 300f;
camera.update();
stage = new Stage();
shader = new ShaderProgram(vertexShader, fragmentShader);
myBatch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
sphere = BuildSphere(5, 100);
group = new Group(){
#Override
public void draw(Batch batch, float parentAlpha) {
batch.setTransformMatrix(matrixResult);
super.draw(batch, parentAlpha);
}
};
group.setTouchable(Touchable.enabled);
group.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button) {
Gdx.app.log("MOUSE_X_BEG", Float.toString(x));
Gdx.app.log("MOUSE_Y_BEG", Float.toString(y));
begX = x;
begY = y;
return true;
}
#Override
public void touchDragged(InputEvent event, float x, float y,
int pointer) {
endX = x;
endY = y;
//isRotate = true;
float translationX = endX-begX;
float translationY = begY-endY;
float length = (float)Math.sqrt(Math.pow(translationX,2) + Math.pow(translationY,2));
Vector3 axis = new Vector3(0, 0, 0);
if(length>0){
if(begX-endX == 0){
axis.x = 1;
}else{
float angle = (float) (Math.atan(translationY/translationX) + Math.PI/2.0*(translationX <0 ? -1 : 1));
axis.z = 1;
axis.x = (float) Math.cos(angle);
axis.y = (float) Math.sin(angle);
}
}
quaternion = new Quaternion(axis, 0.02f*length);
Matrix4 rotation = new Matrix4(quaternion);
matrixResult = rotation.mul(matrixRotationOld);
matrixRotationOld = matrixResult;
}
});
//group.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
for (CenterCoordinate cenCoordinate : sphere.getPolygonCenterCoordinates()) {
Vector3 vector = cenCoordinate.getCartesianCenter();
Polygon polygon = new Polygon(1, cenCoordinate.getType().getCode(), cenCoordinate.getRadius(), cenCoordinate.getPsi(),
cenCoordinate.getKsi(), vector, cenCoordinate.getRotation());
group.addActor(polygon);
}
stage.addActor(group);
Gdx.input.setInputProcessor(stage);
}
Polygon extends Actor draw method :
#Override
public void draw(Batch batch, float parentAlpha) {
translation.setToTranslation(vertex.x, vertex.y, vertex.z);
matrix.mul(translation);
shader.begin();
shader.setUniformMatrix("u_worldView", matrix);
mesh.render(shader, GL20.GL_LINE_LOOP, 1, mesh.getNumVertices()-1);
shader.end();
matrix.idt();
}
Rotating the batch will not rotate the group. If you want to rotate everything i would suggest to rotate the camera of the Stage and set the Stages SpriteBatchs ProjectionMatrix to cam.combined. But to rotate only the Group use the rotateBy(degrees) or setRotation(degrees) method.
Rotating the SpriteBatch or the camera is actually only a change of the view, but rotating the Actor (in your case the Group) changes the logic of them.
In the draw() method you then will need to take care about this rotation and then you will have the result you want.