I have a sprite that moves from the bottom left of the screen to the top right. What I want to know is how would i make it turn around and go in the opposite direction, and continue this loop.
I tried negating the direction of the vector but that doesnt work.
This what i have right now:
public void create() {
// Game Initialization
v = new Vector2(Gdx.graphics.getWidth() - 0, Gdx.graphics.getHeight() - 0);
v.nor();
v.scl(100);
spriteBatch = new SpriteBatch();
bug = new Sprite(new Texture("EnemyBug.png"));
bug.setSize(50, 85);
bug.setOrigin(0,0);//Gdx.graphics.getHeight() / 5, Gdx.graphics.getHeight() / 5);
bug.setPosition(1,1);//Gdx.graphics.getWidth() - 50, Gdx.graphics.getHeight() - 50);
bug.rotate(v.angle());
rotDeg = 5;
}
#Override
public void render() {
// Game Loop
Gdx.gl.glClearColor(0.7f, 0.7f, 0.2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
spriteBatch.begin();
if(bug.getX() >= (int)(Gdx.graphics.getWidth() - 100) && bug.getY() >= (int)(Gdx.graphics.getHeight() - 100)){
turn = !turn;
}
else if(bug.getX() <= 50 && bug.getY() <= 50){
turn = !turn;
}
if(!turn){
bug.translate(v.x * Gdx.graphics.getDeltaTime(), v.y * Gdx.graphics.getDeltaTime());
}
else{
bug.translate(-(v.x * Gdx.graphics.getDeltaTime()), -(v.y * Gdx.graphics.getDeltaTime()));
}
bug.translate(v.x * Gdx.graphics.getDeltaTime(), v.y * Gdx.graphics.getDeltaTime());
bug.draw(spriteBatch);
spriteBatch.end();
}
You are translating the sprite twice per frame:
if(!turn){
bug.translate(v.x * Gdx.graphics.getDeltaTime(), v.y * Gdx.graphics.getDeltaTime());
}
else{
bug.translate(-(v.x * Gdx.graphics.getDeltaTime()), -(v.y * Gdx.graphics.getDeltaTime()));
}
//REMOVE THIS LINE
bug.translate(v.x * Gdx.graphics.getDeltaTime(), v.y * Gdx.graphics.getDeltaTime());
That extra line may be causing your problem, nullifying your negative translation and doubling the positive one.
Related
I have defined a camera that rotates around the scene's origin, with a Rotate X axis, and a Rotate Y axis.
I would like that the X axis defines the "height" of my Y axis camera so that it revolves around the given latitude on the sphere.
I have defined the rotates as such:
_cameraTranslate = new Translate(0, 0, -10);
_cameraRotateX = new MyRotate(0, 0, 0, 10, Rotate.X_AXIS);
_cameraRotateY = new MyRotate(0, 0, 0, 10, Rotate.Y_AXIS);
_camera.getTransforms().addAll(_cameraTranslate, _cameraRotateX, _cameraRotateY);
And rotate them as such:
private void onMouseDragged(MouseEvent e) {
_cameraRotateX.setAngle360(_cameraRotateX.getAngle() - (-e.getSceneY() + _mouseOldY));
_cameraRotateY.setAngle360(_cameraRotateY.getAngle() - (e.getSceneX() - _mouseOldX));
_mouseOldX = e.getSceneX();
_mouseOldY = e.getSceneY();
}
This is what it does when I rotate around, shifting the world instead of keeping the X axis lines parallel to the frame if it makes sense.
I realized I have to modify the axis of the X camera (the one going up and down). As the camera rotates around the Y axis, the X and Z axes move so the rotation needs to be adapted accordingly.
Instead, I added a Point3D that I modify every time the Y camera is moved:
_cameraRotateXAxis = new Point3D(1, 0, 0);
_cameraRotateX = new MyRotate(0, 0, 0, 10, _cameraRotateXAxis);
And in the mouseDragged method:
private void onMouseDragged(MouseEvent e) {
_cameraRotateX.setAngle360(_cameraRotateX.getAngle() - (-e.getSceneY() + _mouseOldY));
_cameraRotateY.setAngle360(_cameraRotateY.getAngle() - (e.getSceneX() - _mouseOldX));
_cameraRotateXAxis = _cameraRotateXAxis.add(-_cameraRotateXAxis.getX(), -_cameraRotateXAxis.getY(), -_cameraRotateXAxis.getZ());
double angle = _cameraRotateY.getAngle();
double newDelta = _cameraRotateY.getAngle()%90 / 90d;
if (angle >= 0 && angle < 90) {
_cameraRotateXAxis = _cameraRotateXAxis.add(-(1 - newDelta), 0, newDelta);
}
else if (angle >= 90 && angle < 180) {
_cameraRotateXAxis = _cameraRotateXAxis.add(newDelta, 0, 1 -newDelta);
}
else if (angle >= 180 && angle < 270) {
_cameraRotateXAxis = _cameraRotateXAxis.add(1 - newDelta, 0, -newDelta);
}
else {
_cameraRotateXAxis = _cameraRotateXAxis.add(-newDelta, 0, -(1 - newDelta));
}
_mouseOldX = e.getSceneX();
_mouseOldY = e.getSceneY();
}
In LibGDX I'm trying to have my OrthographicCamera follow the playersprite when I move it around. Currently, the playersprite gets updated first and then in the next frame the camera updates to the position of the playersprite in the previous frame. Here is an example:
https://i.imgur.com/wxJUizU.gifv
I have tried moving gameMap.render(cam) to the bottom of the method, but not only does it not solve my problem, it also places the map textures above the playersprite, so you won't be able to see the playersprite anymore when it moves under the map.
Here is the code for rendering the playersprite and camera:
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.viewportHeight = Gdx.graphics.getHeight() / 3;
cam.viewportWidth = Gdx.graphics.getWidth() / 3;
gameMap.render(cam);
gameMap.getTiledMapRenderer().getBatch().begin();
player.draw(gameMap.getTiledMapRenderer().getBatch());
gameMap.getTiledMapRenderer().getBatch().end();
cam.position.x = player.getX() + (player.getWidth() / 2);
cam.position.y = player.getY() + (player.getHeight() / 2);
cam.update();
}
Typically, you want to break your logic into two sections:
Update
Render
So, before each frame you want to perform any pertinent calculations.
Your camera is currently updating late, because it isn't performing logic until after the gameMap has been updated.
For example:
// Perform logic and update the state
public void Update () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
cam.viewportHeight = Gdx.graphics.getHeight() / 3;
cam.viewportWidth = Gdx.graphics.getWidth() / 3;
gameMap.getTiledMapRenderer().getBatch().begin();
cam.position.x = player.getX() + (player.getWidth() / 2);
cam.position.y = player.getY() + (player.getHeight() / 2);
}
// Draw map
public void Render () {
gameMap.render(cam);
player.draw(gameMap.getTiledMapRenderer().getBatch());
gameMap.getTiledMapRenderer().getBatch().end();
cam.update();
}
I'm not familiar with the framework you're using, so I can't tell if this would run or not, but when working with frames in any game development situation, this is how you want to handle things.
Like Bradley says you should split your logic into two parts: update and render
Create a udpate() method where you place all your things to update and call this method first in the render() method:
public void update(){
//Update camera position
cam.position.x = player.getX() + (player.getWidth() / 2);
cam.position.y = player.getY() + (player.getHeight() / 2);
//apply all updates to the camera before this the changed position won't apply to the camera
cam.update();
}
#Override
public void render() {
//First call the update method we created
update();
//Clear the Screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//Render
gameMap.render(cam);
gameMap.getTiledMapRenderer().getBatch().begin();
player.draw(gameMap.getTiledMapRenderer().getBatch());
gameMap.getTiledMapRenderer().getBatch().end();
}
You don't need to call:
cam.viewportHeight = Gdx.graphics.getHeight() / 3;
cam.viewportWidth = Gdx.graphics.getWidth() / 3;
every frame. It's enough to call it ones in the create() method
I am creating a game in LibGDX. I have taken the tiles used in Pixel Dungeon and created a tile map using Tiled.
The main character's class is a subclass of Actor, and because the character is animated, I am using this code to draw the sprite:
if (direction.isEastwards() || direction.isNorthwards()) {
Vector3 projectedPosition = getLocation().getCamera().project(
new Vector3(16 * getX() + 1, Gdx.graphics.getHeight()
- (16 * getY()) - 15, 0));
batch.draw(current.getKeyFrame(
animTime += Gdx.graphics.getDeltaTime(), true),
projectedPosition.x, projectedPosition.y);
} else {
Vector3 projectedPosition = getLocation().getCamera().project(
new Vector3(16 * getX() + 13, Gdx.graphics.getHeight()
- (16 * getY()) - 15, 0));
batch.draw(current.getKeyFrame(
animTime += Gdx.graphics.getDeltaTime(), true),
projectedPosition.x, projectedPosition.y);
}
When I launch the game in Eclipse, the sprite initially appears in the correct location. However, if I resize the screen, the sprite ceases to be in the correct location and eventually will disappear off the map.
The same thing happened before I started using projection, and I figured the problem was related to projection. As this is an area I have not explored before I decided after an hour of being able to solve this to ask for help.
The animation flips depending on which direction the character faces, which is why the if/else clause is there.
Addendum: The stage is created with new Stage(new ExtendViewport(800,600),batch);, the resize method updates the camera, and the batch is set to the projection matrix.
Here is more relevant code:
Camera and map initialisation:
camera=new OrthographicCamera();
camera.setToOrtho(false,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
mapRenderer=new OrthogonalTiledMapRenderer(map,batch);
Render method:
camera.update();
batch.setProjectionMatrix(camera.combined);
mapRenderer.setView(camera);
mapRenderer.render();
stage.act();
stage.draw();
Resize method:
camera.viewportWidth=width;
camera.viewportHeight=height;
camera.update();
Actor draw method:
#Override
public void draw(Batch batch, float parentAlpha) {
Color color = getColor();
batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
if (direction.isEastwards() || direction.isNorthwards()) {
Vector3 projectedPosition = getLocation().getCamera().project(
new Vector3(16 * getX() + 1, Gdx.graphics.getHeight()
- (16 * getY()) - 15, 0));
batch.draw(current.getKeyFrame(
animTime += Gdx.graphics.getDeltaTime(), true),
projectedPosition.x, projectedPosition.y);
} else {
Vector3 projectedPosition = getLocation().getCamera().project(
new Vector3(16 * getX() + 13, Gdx.graphics.getHeight()
- (16 * getY()) - 15, 0));
batch.draw(current.getKeyFrame(
animTime += Gdx.graphics.getDeltaTime(), true),
projectedPosition.x, projectedPosition.y);
}
// Walk animation displays for 0.2 seconds
if (current == walk && animTime >= 0.2) {
current = idle;
animTime = 0;
}
}
I think the problem it caused because you dont combine the sprite with camera projection. set your spriteBatch like this :
spriteBatch.setProjectionMatrix(camera.combined);
And dont miss update viewport in resize method :
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.update();
}
With that, you can resize or zoomin zoomout, the spriteBatch it scalled to the camera projection.
I am trying to move a triangle in the direction of the top vertex.
Depending on the rotation angle.
This is my code:
private static void render() {
// Clear the pixels on the screen and clear the contents of the depth buffer (3D contents of the scene)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset any translations the camera made last frame update
glLoadIdentity();
// Apply the camera position and orientation to the scene
//camera.applyTranslations();
glTranslated(0,0,-5);
glPushMatrix();
glRotated(f.get_direction(),0,0,1);
glTranslated(x,y,0);
f.draw();
glPopMatrix();
x+=(f.get_speed()/30)*cos(f.get_direction()+90);
y+=(f.get_speed()/30)*sin(f.get_direction()+90);
}
The point is that no matter what is the rotation angle that is the direction,
i want to move the triangle according to it.
Did you try to translate according to direction vector but there is simple problem cos and sin arguments is in radians glRotate in degrees:
so we must create static function
static double degToRad(double x)
{
return (x / 180.0) * Math.PI;
}
than use it
glLoadIdenity();
x += Math.cos(degToRad(getDirection() + 90)) * getSpeed();
y += Math.sin(degToRad(getDirection() + 90)) * getSpeed();
glTranslatef(x, y, 0);
glRotatef(getDirection(), 0, 0, 1);
drawObject();
you can also invert direction of movement just subsctacting current angle from 360:
glLoadIdenity();
x += Math.cos(degToRad(360 - getDirection() + 90)) * getSpeed();
y += Math.sin(degToRad(360 - getDirection() + 90)) * getSpeed();
glTranslatef(x, y, 0);
glRotatef(getDirection(), 0, 0, 1);
drawObject();
I am making a game in Libgdx, in which I want to fall a ball from up word to down word and move background towards up word and update camera according to it. My code is given below...
public WorldRenderer(SpriteBatch spriteBatch, World world){
this.world = world;
this.camera = new OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
this.camera.position.set(FRUSTUM_WIDTH/2, FRUSTUM_HEIGHT/2, 0);
this.spriteBatch = spriteBatch;
positionBGY1 = 0;
positionBGY2 = 0;
}
public void render(World world, float deltaTime){
if(world.ball.position.y > - camera.position.y){
camera.position.y = world.ball.position.y;
}
if(camera.position.y<0)
camera.position.y=world.ball.position.y;
camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
renderBackground();
renderObjects(world, deltaTime);
}
private void calculateBGPosition(){
positionBGY2 = positionBGY1 + (int)FRUSTUM_HEIGHT;
if(camera.position.y >= positionBGY2){
positionBGY1 = positionBGY2;
}
}
private void renderBackground() {
spriteBatch.disableBlending();
spriteBatch.begin();
spriteBatch.draw(Assets.gamebackgroundRegion, camera.position.x - FRUSTUM_WIDTH / 2, positionBGY1 - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH, 1.5f * FRUSTUM_HEIGHT);
spriteBatch.draw(Assets.gamebackgroundRegion2, camera.position.x - FRUSTUM_WIDTH / 2, positionBGY2 - FRUSTUM_HEIGHT / 2, FRUSTUM_WIDTH, 1.5f * FRUSTUM_HEIGHT);
calculateBGPosition();
spriteBatch.end();
}
Problem with my code is background screen is not moving and camera is not updated with ball movement and ball fall down out of screen.
Well, first thing you need to do is change one of the bg variables, so in render somehwere do something like:
float speed = 1;
positionBGY1+=deltaTime*speed;
positionBGY2+=deltaTime*speed;
As far as the camera moving with the ball I would just do this:
camera.position.y = Math.min(ball.y,0);
And I would in turn omit all of this:
if(world.ball.position.y > - camera.position.y){
camera.position.y = world.ball.position.y;
}
if(camera.position.y<0)
camera.position.y=world.ball.position.y;
Best way to achieve this is using ParrallaxLayer and ParrallaxBackground classes
it optimised the background operation so that u dont have to worry about the performance