How to move a camera left and right in LibGDX - java

I have a camera which I control using WASD, but I'm stuck on moving it left and right. I've been looking all over the internet and it says to find a vector perpendicular to another you change the x and y round and times one of them by -1. I've tried this in the code below:
void camstrafe (String dir) {
Vector3 direction = camera.direction.nor();
Vector3 old = direction;
direction.set(-old.z, 0, old.x);
camera.translate(direction.scl(0.18f));
}
I have moving forwards working fine, and actually turning the camera round, but for some reason this doesn't work, and to be honest I'm not sure what it really does because when I press a or d (they call this function) the camera just goes crazy and starts turning round really quickly and sometimes going forwards or like a million miles sideways. Anyway, does anyone know how I could do this properly? By the way I've also tried getting the forward direction of the camera and using the .rotate() function rotating it 90 degrees right/left then translating it that way but that does the same thing. I'm thinking maybe cameras don't work the same was as other things do when translating them sideways/backwards.

To archive camera movement between 2 vectors use the camera lerp:
public class myclass {
[...]
private OrthographicCamera camera;
public Vector3 posCameraDesired;
[...]
private void processCameraMovement(){
/// make some camera movement
posCameraDesired.x+=100.0f * Gdx.graphics.getDeltaTime();
posCameraDesired.y+=100.0f * Gdx.graphics.getDeltaTime();
}
[...]
//render method
public void draw(){
[...]
processCameraMovement();
camera.position.lerp(posCameraDesired,0.1f);//vector of the camera desired position and smoothness of the movement
[...]
}

First, in your class, you must have an Animations object, lets call it Anim. In your class instanciation, you must create an OrthographicCamera object, that will be your camera instance. You have to give it a value, such as :
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
This camera coordonates can be set up the first time you use it, and you can do it with the method .translate() :
camera.translate(camera.viewportWidth / 2, camera.viewportHeight);
Otherwise the positio will be set at 0;0.
In your render() method, you have to use a method from the camera object called update(), like bellow :
#Override
public void render(float delta) {
anim.load();
camera.update();
....
game();
....
}
This method is always running during the game/app you develop. So every time the method runs, the camera is updated, and its position too.
Then, in your game() method, or in an other method (depending on your architecture), where you are dealing with the inputs of the user, you move the position of the camera, and modify the camera.position in it. like bellow :
public void game() {
if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) { // or A
moveBack(anim); // The method to move back
camera.position.x -= 3; // if conditions are ok, move the camera back.
} else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) { or D
moveForward(anim); // The method to move forward
camera.position.x += 3; // if conditions are ok, move the camera to the front.
}
When the user is moving, the method to move is called, and the camera position is modified. Each time the method render() is called, the camera is updated with its new position.

Related

scrolling never-ending background in Game not working as expected

I am working on my first side-scroller game and am trying to achieve a neverending background effect and it's nearly working as i would expect but there are little glitches.
I have 2 instances of the background (each fills the screen width), with one placed at the bottom left corner of the screen and one off the screen to the right. I am then moving my camera each frame to the right and when the first background instance is completely offscreen to the left i reset its X to the right of the camera so that it is now (relative to the camera) off the right of the screen. this is working a lot of the time, but every now and again it seems the method to reset its x position is getting called a few frames late and results in a gap in the background.
the update code i am using in the main game is -
private void update(float delta){
//update camera and world
camera.position.set(camera.position.x+scrollSpeed, camera.position.y, 0);
camera.update();
world.step(step, velocityIterations, positionIterations);
if(gameInProgress){
//backgrounds (array holds the 2 instances of the background)
for(int i=0; i< bgFillArray.size; i++){
bgFillArray.get(i).update();
}
}
stage.act(delta);
tweenManager.update(delta);
}
the update method in the BgFill class -
public void update(){
float currentXPos = getX();
float leftBoundary = camera.position.x-1200;
float rightOfScreen = camera.position.x+400;
if(active){
//check to see if the camera has gone past this instance. if so then move to right
if(currentXPos <= leftBoundary){
setX(rightOfScreen);
}
}
}
Firstly, is this the usual way (or even close) to do a continuous scrolling background?
if it is, what am I doing wrong?

Find 5 Largest Values In A Linked List in Processing/Java

I got this code that gets x,y positions from a motion sensor tracking a hand. The app draws a circle in the middle of the screen and then detects whether the hand is outside the circle. While the hand is outside the circle, a function checks the distance of the hand from the center of the circle. I'm attempting to store the distance data while the hand is outside of the circle in a linked list.
I need to get both the top 5 largest values and the duration for each time the hand is outside the circle.
Here's my code thus far; I've left out a bunch of the code for setting up the motion sensor just for simplicity, so this is semi-pseudo code. In any case, my main issue is getting the values I need from the list. I have the circle class included as well. I do the outside of the circle calculation and how far outside of calculation inside of my circle class.
Please let me know if this makes sense! The motion sensor is reading in data at 200 fps, so efficiency is factor here. On top of that, I am only expecting the hand, going back and forth, to be outside of the circle for a few seconds at a time.
import java.util.*;
LinkedList<Integer> values;
public void setup()
{
size(800, 300);
values = new LinkedList<Integer>();
HandPosition = new PVector(0, 0); //This is getting x,y values from motion sensor
aCircle = new Circle(); //my class just draws a circle to center of screen
aCircle.draw();
}
public void draw()
{
if (aCircle.isOut(HandPosition)) /* detects if movement is outside of circle. Would it make more sense for this to be a while loop? I also need to start a timer as soon as this happens but that shouldn't be hard */
{
values.add(aCircle.GetDistance(HandPosition)); //gets how far the hand is from center of circle and adds it to linked list. Allegedly at least, I think this will work.
/*So I need to get the 5 largest value from inside of my linked list here.
I also need to start a timer*/
}
}
class Circle {
PVector mCenter;
int mRadius;
Circle()
{
// initialize the center position vector
mCenter = new PVector(0,0);
mRadius = 150;
mCenter.set((width/2),(height/2));
}
boolean isOut(PVector Position) //detects if hand position is outside of circle
{
return mCenter.dist(Position) <= mRadius;
}
float GetDistance(PVector Position) //detects how far the hand is from the center of circle
{
return mCenter.dist(Position);
}
void draw() {
ellipse(mCenter.x, mCenter.y, mRadius, mRadius);
}
}
I'm new to Processing as well so don't hold back if any of this works.
You can use Collections.sort(List); here, then take last five element from the list.
Collection.Sort()

libgdx coordinate system differences between rendering and touch input

I have a screen (BaseScreen implements the Screen interface) that renders a PNG image. On click of the screen, it moves the character to the position touched (for testing purposes).
public class DrawingSpriteScreen extends BaseScreen {
private Texture _sourceTexture = null;
float x = 0, y = 0;
#Override
public void create() {
_sourceTexture = new Texture(Gdx.files.internal("data/character.png"));
}
.
.
}
During rendering of the screen, if the user touched the screen, I grab the coordinates of the touch, and then use these to render the character image.
#Override
public void render(float delta) {
if (Gdx.input.justTouched()) {
x = Gdx.input.getX();
y = Gdx.input.getY();
}
super.getGame().batch.draw(_sourceTexture, x, y);
}
The issue is the coordinates for drawing the image start from the bottom left position (as noted in the LibGDX Wiki) and the coordinates for the touch input starts from the upper left corner. So the issue I'm having is that I click on the bottom right, it moves the image to the top right. My coordinates may be X 675 Y 13, which on touch would be near the top of the screen. But the character shows at the bottom, since the coordinates start from the bottom left.
Why is what? Why are the coordinate systems reversed? Am I using the wrong objects to determine this?
To detect collision I use camera.unproject(vector3). I set vector3 as:
x = Gdx.input.getX();
y = Gdx.input.getY();
z=0;
Now I pass this vector in camera.unproject(vector3). Use x and y of this vector to draw your character.
You're doing it right. Libgdx generally provides coordinate systems in their "native" format (in this case the native touch screen coordinates, and the default OpenGL coordinates). This doesn't create any consistency but it does mean the library doesn't have to get in between you and everything else. Most OpenGL games use a camera that maps relatively arbitrary "world" coordinates onto the screen, so the world/game coordinates are often very different from screen coordinates (so consistency is impossible). See Changing the Coordinate System in LibGDX (Java)
There are two ways you can work around this. One is transform your touch coordinates. The other is to use a different camera (a different projection).
To fix the touch coordinates, just subtract the y from the screen height. That's a bit of a hack. More generally you want to "unproject" from the screen into the world (see the
Camera.unproject() variations). This is probably the easiest.
Alternatively, to fix the camera see "Changing the Coordinate System in LibGDX (Java)", or this post on the libgdx forum. Basically you define a custom camera, and then set the SpriteBatch to use that instead of the default.:
// Create a full-screen camera:
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Set it to an orthographic projection with "y down" (the first boolean parameter)
camera.setToOrtho(true, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.update();
// Create a full screen sprite renderer and use the above camera
batch = new SpriteBatch(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(camera.combined);
While fixing the camera works, it is "swimming upstream" a bit. You'll run into other renderers (ShapeRenderer, the font renderers, etc) that will also default to the "wrong" camera and need to be fixed up.
I had same problem , i simply did this.
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenY = (int) (gheight - screenY);
return true;
}
and every time you want to take input from user dont use Gdx.input.getY();
instead use (Gdx.graphics.getHeight()-Gdx.input.getY())
that worked for me.
The link below discusses this problem.
Projects the given coords in world space to screen coordinates.
You need to use the method project(Vector3 worldCoords) in class com.badlogic.gdx.graphics.Camera.
private Camera camera;
............
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Create an instance of the vector and initialize it with the coordinates of the input event handler.
Vector3 worldCoors = new Vector3(screenX, screenY, 0);
Projects the worldCoors given in world space to screen coordinates.
camera.project(worldCoors);
Use projected coordinates.
world.hitPoint((int) worldCoors.x, (int) worldCoors.y);
OnTouch();
return true;
}

Android Mic Volume Meter

I'm writing an app that requires getting the mic level to create a sound meter. I have found this: Android Media Player Decibel Reading. I still need to create a meter to display the current level, out of 100% kind of deal. So a bar that the higher it gets it gets redder for example. Just getting the code to display the level is great.
In the link above there is a method for getting the current decibel reading, however it appears to be something that I would need to possibly run in a separate thread and update it constantly. I was reading into a VU meter but have no clue where to start.
Thanks in advance!
Okay I'm assuming your working with the code you linked to in your question.
So this meter will have to change its size and colour on the fly depending on the value of amplitude.
To draw the shape extend the View class and override the onDraw method as shown below
float x,y; //CONSTANTS FOR WHERE YOU WANT YOUR BAR TO BE
float baseWidth; // This is the width of one block.
//Number of blocks together will be your rectangle
float nwidth; //This is the number of blocks varying according to amplitude
float height; //CONSTANT HEIGHT
Paint color=new Paint();
//For drawing meter
public void onDraw(Canvas c){
changeColorAndSize();
Rect rect = new Rect(x, y, x + (baseWidth*nwidth), y + height);
shapeDrawable.setBounds(rect);
shapeDrawable.getPaint().set(paint);
shapeDrawable.draw(canvas);
}
public void changeColorAndSize(){
double amp=getAmplitude();
nWidth=amp;
paint.setARGB (a, r*(Integer.parseInt(amp)), g, b);
//This will change the redness of the bar. a,g and b will have to be set by you
}
public double getAmplitude() {
if (mRecorder != null)
return (mRecorder.getMaxAmplitude());
else
return 0;
}
To make the meter change every 'x' seconds you will have to call postInvalidate() repeatedly
OR
Use an Animation, and call startAnimation() on it from your View.

MouseJointDef libgdx - draw a trajectory line like Angry Birds

in libgdx game
I want to touchDown and then drag somewhere and then on the release (touchUp) apply a directional force based on the distance and direction from the target body. When you touchdown the target body stays still and then on touchup the force is applied along the desired trajectory.
(very similar to Angry birds - where you get to see the trajectory in dotted lines for the target body when you hold hack the slingshot - I want to do the same)
So I guess that this might not be the hardest thing to do but given a few options Im leaning towards using a MouseJointDef but its an immediate force applied (i.e. the target moves immediately - I want it to stay still and then once the touchup event happens then apply the force)
Whats the easiest way to draw the trajectory also? Im using Box2D also.
Create a class that inherits InputAdapter class, then create an instance of it and register it to listen the touch inputs.
Gdx.input.setInputProcessor(inputAdapter);
There are 3 methods to handle the touch events touch_down, touch_dragged and touch_up that you have to override.
In touch_down, check the touching position to whether is in the birds area or not. If it is, make a boolean flag true.
In touch_dragged, check the flag above and if it was true, calculate the distance of the touch position relative to the bird shooting center and the shooting angle.
In touch_up, you can order to shoot with the calculated amounts by calling
body2shoot.applyLinearImpulse(impulse, body2shoot.getWorldCenter());
There is no need to MouseJointDef to move the body2shoot. Just set the transform of body2shoot in touching position to be dragged in each cycle of render.
For calculating the trajectory I wrote a class like this:
public class ProjectileEquation
{
public float gravity;
public Vector2 startVelocity = new Vector2();
public Vector2 startPoint = new Vector2();
public ProjectileEquation()
{ }
public float getX(float t)
{
return startVelocity.x*t + startPoint.x;
}
public float getY(float t)
{
return 0.5f*gravity*t*t + startVelocity.y*t + startPoint.y;
}
}
and for drawing it just I set the startPoint and startVelocity and then in a loop I give a t (time) incrementally and call getX(t) and getY(t).

Categories