I am trying to create a simple app which allows you to load 3d model from .obj and zoom/rotate it by touching the screen.
I managed to write code which loads 3d model from file and detect gestures but now I am not sure what to do to enable zoom/rotate features by touching the screen.
Here is my code for now:
public class RenderObjApp implements ApplicationListener, GestureDetector.GestureListener {
public static int SCREEN_WIDTH = 800;
public static int SCREEN_HEIGHT = 600;
private static final String TAG = RenderObjApp.class.getSimpleName();
private Mesh model;
private PerspectiveCamera camera;
private float scale = 1f;
#Override
public void create() {
model = ObjLoader.loadObj(Gdx.files.internal("data/cessna.obj").read(), true);
Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
Gdx.input.setInputProcessor(new GestureDetector(this));
}
#Override
public void dispose() {
}
#Override
public void pause() {
}
#Override
public void render() {
Gdx.gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
camera.update();
camera.apply(Gdx.gl10);
model.render(GL10.GL_TRIANGLES);
}
#Override
public void resize(int arg0, int arg1) {
float aspectRatio = (float) arg0 / (float) arg1;
camera = new PerspectiveCamera(75, 2f * aspectRatio, 2f);
camera.near = 0.1f;
camera.translate(0, 0, 0);
}
#Override
public void resume() {
}
#Override
public boolean touchDown(float x, float y, int pointer) {
Gdx.app.log(TAG, "touchDown: ");
return false;
}
#Override
public boolean tap(float x, float y, int count, int pointer, int button) {
Gdx.app.log(TAG, "tap: ");
return false;
}
#Override
public boolean longPress(float x, float y) {
Gdx.app.log(TAG, "zoom: ");
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int pointer, int button) {
Gdx.app.log(TAG, "fling: ");
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
Gdx.app.log(TAG, "pan: ");
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
Gdx.app.log(TAG, "zoom: initialDistance=" + initialDistance + ", distance=" + distance);
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2) {
Gdx.app.log(TAG, "pinch: ");
return false;
}
}
So I am looking how to rotate the PerspectiveCamera and Mesh itself.
I have been working on a "Blender-style" camera that has pinch-to-zoom capability as well as (on desktop) most of the functionality you get with Blender's camera. It is a work in progress — it doesn't perfectly imitate the behavior of Blender's camera (yet). I think this will get you pointed in the right direction. Some things you should know:
You may have to translate your model so it sits on the origin. The camera remains pointed at the origin unless you translate it. (You can only translate on desktop and not on android so far);
I got most of the pinch-to-zoom handling code here: https://code.google.com/p/libgdx-users/wiki/PinchToZoom.
Sorry for the magic numbers. I will make those constants in the future.
If you or anyone else improves this code, I would love if you shared a copy with me.
The Abstract class:
/* Author: Christopher Grabowski, yourchristopher6334 gmail.com */
package ...;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Vector2;
abstract public class ControllableCamera extends PerspectiveCamera implements InputProcessor{
abstract public void resize(int width, int height);
abstract public void render();
public ControllableCamera(int fieldOfView, int width, int height) {
super(fieldOfView, width, height);
}
#Override
public boolean keyDown(int keyCode) {
return false;
}
#Override
public boolean keyTyped(char arg0) {
return false;
}
#Override
public boolean keyUp(int arg0) {
return false;
}
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
return false;
}
#Override
public boolean touchUp(int x, int y, int pointer, int button) {
return false;
}
#Override
public boolean mouseMoved(int arg0, int arg1) {
return false;
}
#Override
public boolean scrolled(int direction) {
return false;
}
}
The concrete class:
/* Author: Christopher Grabowski, yourchristopher6334 gmail.com */
package ...;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.Vector3;
/*
* the pause, resize, and render methods must be called within their corresponding
* methods in the ApplicationListener
*/
public class BlenderStyleCamera extends ControllableCamera {
public static final Vector3 ORIGIN = new Vector3(0, 0, 0);
private static boolean shiftIsPressed = false, controlIsPressed = false,
isScrollingUp = false, isScrollingDown = false,
isSingleTouched = false, justSingleTouched = false;
private float aspectRatio;
private int x = -1, y = -1;
private float dx = 0.0f, dy = 0.0f;
private final Vector3 tmp = new Vector3();
// fields related to pinch-to-zoom
private int numberOfFingers = 0;
private int fingerOnePointer;
private int fingerTwoPointer;
private float lastDistance = 0;
private final Vector3 fingerOne = new Vector3();
private final Vector3 fingerTwo = new Vector3();
public BlenderStyleCamera(int fieldOfView, int width, int height) {
super(fieldOfView, width, height);
aspectRatio = viewportHeight / viewportWidth;
Gdx.input.setInputProcessor(this);
up.set(0.0f, 1.0f, 0.0f);
position.set(0.0f, 0.0f, 30.0f);
far = 300.0f;
lookAt(0, 0, 0);
translate(0.0f, 0.0f, 2.1f);
lookAt(0, 0, 0);
update();
}
public void pause() {
numberOfFingers = 0;
}
#Override
public void resize(int width, int height) {
viewportWidth = width;
viewportHeight = height;
aspectRatio = viewportHeight / viewportWidth;
update();
}
#Override
public void render() {
if (isSingleTouched) {
// This gets the change in touch position and
// compensates for the aspect ratio.
if (x == -1 || y == -1 || justSingleTouched) {
x = Gdx.input.getX();
y = Gdx.input.getY();
} else {
dx = (x - Gdx.input.getX());
dy = (y - Gdx.input.getY()) / aspectRatio;
}
// This zooms when control is pressed.
if (controlIsPressed && dy > 0) {
scrollIn();
} else if (controlIsPressed && dy < 0) {
scrollOut();
}
// This translates the camera blender-style
// if shift is pressed.
// Note that this will look weird with a
// perspective camera.
else if (shiftIsPressed) {
translateTangentially();
}
// Default is to rotate the object
// (actually rotate the camera about a sphere
// that surrounds the object).
else {
travelAround();
}
x = Gdx.input.getX();
y = Gdx.input.getY();
justSingleTouched = false;
}
// this zooms when the mouse wheel is rotated
if (isScrollingUp) {
scrollIn();
isScrollingUp = false;
} else if (isScrollingDown) {
scrollOut();
isScrollingDown = false;
}
// Some key controls
if (Gdx.input.isKeyPressed(Keys.LEFT) || Gdx.input.isKeyPressed(Keys.A)) {
translateTangentially(1, 0);
} else if (Gdx.input.isKeyPressed(Keys.RIGHT)
|| Gdx.input.isKeyPressed(Keys.D)) {
translateTangentially(-1, 0);
}
if (Gdx.input.isKeyPressed(Keys.UP) || Gdx.input.isKeyPressed(Keys.W)) {
translateTangentially(0, 1);
} else if (Gdx.input.isKeyPressed(Keys.DOWN)
|| Gdx.input.isKeyPressed(Keys.S)) {
translateTangentially(0, -1);
}
update();
}
// These methods create the pinch zoom
// and set some flags for logic in render method.
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
// for pinch-to-zoom
numberOfFingers++;
if (numberOfFingers == 1) {
isSingleTouched = true;
justSingleTouched = true;
fingerOnePointer = pointer;
fingerOne.set(x, y, 0);
} else if (numberOfFingers == 2) {
isSingleTouched = false;
fingerTwoPointer = pointer;
fingerTwo.set(x, y, 0);
float distance = fingerOne.dst(fingerTwo);
lastDistance = distance;
}
return true;
}
#Override
public boolean touchDragged(int x, int y, int pointer) {
if (numberOfFingers > 1) {
if (pointer == fingerOnePointer) {
fingerOne.set(x, y, 0);
}
if (pointer == fingerTwoPointer) {
fingerTwo.set(x, y, 0);
}
float distance = fingerOne.dst(fingerTwo);
if (lastDistance > distance) {
scrollOut();
} else if (lastDistance < distance) {
scrollIn();
}
lastDistance = distance;
update();
}
return true;
}
#Override
public boolean touchUp(int x, int y, int pointer, int button) {
isSingleTouched = false;
if (numberOfFingers == 1) {
Vector3 touchPoint = new Vector3(x, y, 0);
unproject(touchPoint);
}
numberOfFingers--;
// just some error prevention... clamping number of fingers (ouch! :-)
if (numberOfFingers < 0) {
numberOfFingers = 0;
}
lastDistance = 0;
return false;
}
// These methods set flags for logic in render method.
#Override
public boolean keyDown(int keycode) {
switch (keycode) {
case (Keys.SHIFT_LEFT):
case (Keys.SHIFT_RIGHT):
shiftIsPressed = true;
break;
case (Keys.CONTROL_LEFT):
case (Keys.CONTROL_RIGHT):
controlIsPressed = true;
break;
case (Keys.O):
this.up.set(0.0f, 1.0f, 0.0f);
this.position.set(0.0f, 0.0f, 30.0f);
this.lookAt(0, 0, 0);
this.update();
}
return true;
}
#Override
public boolean keyUp(int arg0) {
shiftIsPressed = controlIsPressed = false;
return true;
}
#Override
public boolean scrolled(int direction) {
if (direction == -1) {
isScrollingUp = true;
} else if (direction == 1) {
isScrollingDown = true;
}
return true;
}
// The rest of the methods translate the camera.
public void scrollIn() {
float magnitude = 1.0f;
scrollIn(magnitude);
}
public void scrollIn(float magnitude) {
if (position.dst2(ORIGIN) > 2.0f) {
tmp.set(position);
tmp.nor();
this.translate(-tmp.x * magnitude, -tmp.y * magnitude, -tmp.z
* magnitude);
update();
}
}
public void scrollOut() {
float magnitude = 1.0f;
scrollOut(magnitude);
}
public void scrollOut(float magnitude) {
tmp.set(position);
tmp.nor();
this.translate(tmp.x * magnitude, tmp.y * magnitude, tmp.z * magnitude);
update();
}
private void travelAround() {
tmp.set(up);
rotateAround(ORIGIN, tmp, dx);
tmp.crs(position).nor();
rotateAround(ORIGIN, tmp, dy);
}
private void translateTangentially() {
translateTangentially(dx, dy);
}
private void translateTangentially(float dx, float dy) {
tmp.set(up);
tmp.crs(position);
if (dx > 0) {
translate(tmp.x / 15.0f, tmp.y / 15.0f, tmp.z / 15.0f);
} else if (dx < 0) {
translate(-tmp.x / 15.0f, -tmp.y / 15.0f, -tmp.z / 15.0f);
}
if (dy > 0) {
translate(-up.x, -up.y, -up.z);
} else if (dy < 0) {
translate(up);
}
}
}
Please take a look at this: Mesh rendering issue libgdx.
Method render contains the code you need.
You either need to rotate the camera, or rotate the model.
I believe the libGDX Camera.rotateAround method does what you need. Leave the "point" as the center of your model and set the "axis" parameter based on which way the user is flinging/panning. The "angle" can either be a fixed value, or relative to the intensity of the fling/pan.
Related
I'm new in Libgdx and I'm trying to make a map that can be explored using Camera. Fo that I implements GestureListener in my own Map class.
public class Map extends Stage implements GestureListener {
public String mapName;
private Sprite background;
public LocationPoint points[];
private OrthographicCamera camera;
private Batch batch;
public Music anbientSound;
public int numOfPoints;
public int locationsX[];
public int locationsY[];
public Map(Sprite background) {
this.background = background;
}
public Sprite getBackground() {
return background;
}
public void activate() {
InputMultiplexer inputChain = new InputMultiplexer();
if(points==null) {
points = new LocationPoint[numOfPoints];
for(int i = 0; i < numOfPoints; i++) {
points[i] = new LocationPoint(locationsX[i], locationsY[i]);
addActor(points[i]);
}
}
batch = GameUtils.batch;
camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(camera.viewportWidth/2, camera.viewportHeight/2, 0);
camera.update();
Music music = GameUtils.addMusic(anbientSound);
music.setLooping(true);
music.play();
inputChain.addProcessor(this);
inputChain.addProcessor(new GestureDetector(this));
Gdx.input.setInputProcessor(inputChain);
}
public void draw() {
Gdx.gl20.glClearColor(0, 0, 0, 1);
Gdx.gl20.glClear(Gdx.gl20.GL_COLOR_BUFFER_BIT);
Batch batch = this.batch;
batch.setProjectionMatrix(camera.combined);
batch.begin();
background.draw(batch);
batch.end();
batch.begin();
for(int i = 0; i < numOfPoints; i++) {
points[i].draw(batch, 1);
addActor(points[i]);
}
batch.end();
}
public void dispose() {
GameUtils.stopMusic();
background.getTexture().dispose();
anbientSound.dispose();
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
camera.translate(-deltaX, deltaY);
float initialX = camera.viewportWidth / 2;
float initialY = camera.viewportHeight / 2;
GameUtils.limitBound(camera, initialX, initialY, background.getWidth(), background.getHeight());
camera.update();
return true;
}
#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 panStop(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
return false;
}
#Override
public void pinchStop() {}
}
The method activate() is used to activate the resources of the Map class. The class Map also have a ImageButtons called LocationPoints.
public class LocationPoint extends ImageButton {
private Monster monster;
private Trap trap;
public boolean occuped;
public boolean isTrap;
public int f = 20;
public int k = 20;
public LocationPoint(float x, float y) {
super(GameUtils.getLocationDrawable());
this.setSize(46, 46);
setPosition(x, y);
addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
setPosition(f, k);
f += 10;
k += 10;
return super.touchDown(event, x, y, pointer, button);
}
});
}
public void occup(Monster monster) {
this.monster = monster;
occuped = true;
if(isTrap)
captured();
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
}
public void empty() {
monster = null;
occuped = false;
}
public void captured() {
monster.capture();
}
public Monster getMonster() {
return monster;
}
}
In LocationPoint class I add a InputListener to make a thing when that LocationPoint is touched.
When a play the game on android both LocationPoints event and the Map pan event. But after I move the camera, when I touch on LocationPoint it don't fires that point event.
But when I return the camera to initial position the LocationPoints events works fine! Can you help me? (And sorry for my broken english...)
Actor is already a child so remove redundant call from draw() method.
for(int i = 0; i < numOfPoints; i++) {
points[i].draw(batch, 1);
addActor(points[i]); // <-- Not Should be in draw() call
}
Stage having own SpriteBatch that created by default constructor, use that one or pass own batch in Stage constructor.
Use getBatch() method of Stage if you want to draw something by yourself.
Creating camera in Map class also redundant, use getViewport().getCamera() that return camera of stage, you can typecast to OrthographicCamera
call super.dispose(); inside your dispose() method
Drawing all your Actor by yourself ? If you're not doing something beyond the scope, no need to override draw() method of Stage.
I have a sprite that collides with obstacle, but i have a problem with the score in the top of my screen.
In the update of my class, The collisions are specified by an array, but when it collides with an object, the score is still growing and I can not stop it. this is my code:
private Array<Polen> polen;
private Score score;
public PlayState(GameStateManager gsm) {
super(gsm);
score = new Score(110, 310);
polen = new Array<Polen>();
for(int i = 1; i <= COUNT; i++){
polen.add(new Polen(i * (Polen.WIDTH)));
}
}
#Override
public void update(float dt) {
handleInput();
for(int i = 0; i < polen.size; i++){
Polen pol= polen.get(i);
if(pol.collides(aliado.getBounds())) {
pol.changeExplosion();
flagScore = 1;
}
if (pol.collides(aliado.getBounds())==false){
flagScore = 0;
}
}
if (flagScore == 1){
Score.count++;
flagScore=0;
//auxCount = Score.count +1;
}
score.update(dt);
updateGround();
cam.update();
}
Score Class:
public class Score {
private static final int MOVEMENT = 70;
private Vector3 position;
private Vector3 velocity;
private Rectangle bounds;
private Texture texture;
public Score(int x, int y){
position = new Vector3(x, y, 0);
velocity = new Vector3(0, 0, 0);
texture = new Texture("score0.png");
bounds = new Rectangle(x, y, ((texture.getWidth())), texture.getHeight());
}
public void update(float dt){//code for move the score for top of screen:
if(position.y > 0)
velocity.add(0, 0, 0);
velocity.scl(dt);
position.add(MOVEMENT * dt, velocity.y, 0);
if(position.y < 0)
position.y = 0;
velocity.scl(1/dt);
bounds.setPosition(position.x, position.y);
}
public Vector3 getPosition() {
return position;
}
public Texture getTexture() {
return texture;
}
public void setTexture(Texture texture) {
this.texture = texture;
}
public Vector3 getVelocity() {
return velocity;
}
public void setVelocity(Vector3 velocity) {
this.velocity = velocity;
}
public Rectangle getBounds(){
return bounds;
}
public void setBounds(Rectangle bounds) {
this.bounds = bounds;
}
public void dispose(){
texture.dispose();
}
}
In pol.changeExplosion() you should add a boolean to mark the object as done.
public class Polen {
private boolean exploded = false;
public void changeExplosion() {
// ...
exploded = true;
// ...
}
public boolean isExploded() {
return exploded;
}
}
Then, in your update function you can use this flag to determine if the score should stop being incremented.
for(int i = 0; i < polen.size; i++) {
Polen pol= polen.get(i);
if(pol.collides(aliado.getBounds()) && !pol.isExploded()) {
pol.changeExplosion();
flagScore = 1;
}
else if (!pol.collides(aliado.getBounds())) {
flagScore = 0;
}
}
I would like to add a zoom and pan mechanic to my game but everything I have looked up on the web has been complete and utter failure.
If you could give me a good example of implementing these functions that would be sweet.
Here is the class I'm trying to get it to work in.
package com.adam.finis.screens;
import com.adam.finis.Main;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputMultiplexer;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.viewport.FitViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Play extends ApplicationAdapter implements Screen, GestureListener, ApplicationListener{
//Core Variables
private Main game;
public static InputMultiplexer inputMultiPlex;
//Texture Variables
Texture Title;
private TmxMapLoader mapLoader;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
//Sprite Variables
public static boolean spawnSprite = false;
//Font
private BitmapFont font;
//Window Variables
private OrthographicCamera gameCam;
private Viewport gamePort;
private PlayHud hudPlay;
private int mapX = 1952;
private int mapY = 1952;
private int mapHalfX = mapX / 2;
private int mapHalfY = mapY / 2;
public static boolean GAME_PAUSED = false;
//Random Variables
private Vector2 dragOld, dragNew;
public static Vector2 worldSize;
//DEBUG
private String message;
private Texture debugTexture;
private Sprite debugSprite;
public Play(Main game){
this.game = game;
gameCam = new OrthographicCamera();
gameCam.setToOrtho(false, Main.V_WIDTH, Main.V_HEIGHT);
gamePort = new FitViewport(Main.V_WIDTH, Main.V_HEIGHT, gameCam);
hudPlay = new PlayHud(game.sb);
mapLoader = new TmxMapLoader();
map = mapLoader.load("images/level1.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
gameCam.position.set(mapHalfX, mapHalfY, 0);
GestureDetector gd = new GestureDetector(this);
inputMultiPlex = new InputMultiplexer();
inputMultiPlex.addProcessor(hudPlay.stage);
inputMultiPlex.addProcessor(hudPlay.debugStage);
inputMultiPlex.addProcessor(gd);
Gdx.input.setInputProcessor(gd);
debugTexture = new Texture(Gdx.files.internal("images/house.png"));
debugSprite = new Sprite(debugTexture);
worldSize = new Vector2(mapX, mapY);
font = new BitmapFont(Gdx.files.internal("fonts/lemonMilk.fnt"),false);
font.setColor(Color.RED);
}
#Override
public void show() {
}
public void handleInput(float dt){
//Keyboard Settings
if (Gdx.input.isKeyPressed(Input.Keys.W)) {
gameCam.position.y += 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.A)) {
gameCam.position.x -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.S)) {
gameCam.position.y -= 350 * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.D)) {
gameCam.position.x += 350 * dt;
}
//ZOOM
if (Gdx.input.isKeyPressed(Input.Keys.O)) {
gameCam.zoom += 1.5f * dt;
}
if (Gdx.input.isKeyPressed(Input.Keys.P)) {
gameCam.zoom -= 1.5f * dt;
}
//CAMERA BOUNDS
gameCam.zoom = MathUtils.clamp(gameCam.zoom, 0.1f, mapX / gameCam.viewportWidth);
//|
float camX = gameCam.position.x;
float camY = gameCam.position.y;
//|
Vector2 camMin = new Vector2(gameCam.viewportWidth, gameCam.viewportHeight);
Vector2 camMax = new Vector2(1952, 1952);
//|
camMin.scl(gameCam.zoom/2);
camMax.sub(camMin);
//|
camX = Math.min(camMax.x, Math.max(camX, camMin.x));
camY = Math.min(camMax.y, Math.max(camY, camMin.y));
gameCam.position.set(camX, camY, gameCam.position.z);
//------------------------------------------------------------------------------------
//Touch Settings
if (Gdx.input.justTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
dragOld = dragNew;
}
if (Gdx.input.isTouched()){
dragNew = new Vector2(Gdx.input.getX(), Gdx.input.getY());
if (!dragNew.equals(dragOld)){
gameCam.translate(dragOld.x - dragNew.x, dragNew.y - dragOld.y);
dragOld = dragNew;
}
}
}
public void update(float dt){
handleInput(dt);
gameCam.update();
renderer.setView(gameCam);
}
#Override
public void render(float delta) {
if(GAME_PAUSED == false){
update(delta);
//CLEAR SCREEN - BLACK
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//INIT ALL INPUT
Gdx.input.setInputProcessor(inputMultiPlex);
//RENDER MAP
renderer.setView(gameCam);
renderer.render();
//DRAW
if(spawnSprite == true){
game.sb.begin();
game.sb.draw(debugSprite, 1500, 500);
game.sb.end();
}
//DRAW HUD
hudPlay.stage.getViewport().apply();
hudPlay.stage.act();
hudPlay.stage.draw();
//debug DRAW HUD
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
//PROJECTION
game.sb.setProjectionMatrix(gameCam.combined);
game.hudSb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
game.hudSb.setProjectionMatrix(hudPlay.stage.getCamera().combined);
if(Main.zoomOut == true){
gameCam.zoom += 1.5f * delta;
}
if(Main.zoomIn == true){
gameCam.zoom -= 1.5f * delta;
}
}
if(GAME_PAUSED == true){
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
Gdx.input.setInputProcessor(inputMultiPlex);
game.sb.setProjectionMatrix(hudPlay.debugStage.getCamera().combined);
hudPlay.debugStage.getViewport().apply();
hudPlay.debugStage.act();
hudPlay.debugStage.draw();
}
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
gameCam.viewportWidth = width/5f; //We will see width/32f units!
gameCam.viewportHeight = gameCam.viewportWidth * height/width;
hudPlay.stage.getViewport().update(width, height, true);
hudPlay.debugStage.getViewport().update(width, height, true);
}
#Override
public void pause() {}
#Override
public void resume() {}
#Override
public void hide() {}
#Override
public void dispose() {
game.sb.dispose();
renderer.dispose();
hudPlay.dispose();
font.dispose();
}
#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) {
message = "TAP";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean longPress(float x, float y) {
message = "LONG PRESS";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
message = "Pinch performed";
Gdx.app.log("INFO", message);
return true;
}
}
Your own answer is right, but here is an improved version where zooming a second time is performed upon the previous zoom.
Also, camera translation speed is proportional to the current camera zoom.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX * currentZoom,deltaY * currentZoom);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * currentZoom;
gameCam.update();
return true;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
Gdx.app.log("INFO", "panStop");
currentZoom = gameCam.zoom;
return false;
}
I fixed the issue sorry im new to all of this and its making me think a little too much.
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
message = "PAN";
Gdx.app.log("INFO", message);
gameCam.translate(-deltaX, deltaY);
gameCam.update();
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
message = "Zoom performed";
Gdx.app.log("INFO", message);
gameCam.zoom = (initialDistance / distance) * ZOOM;
gameCam.update();
return true;
}
Please help me. I want that when pressing the left part of the screen the model moved to the left, and when pressing the right part of the screen, model moved to the right.
InputHandler class
public class InputHandler implements InputProcessor {
private Bird myBird;
//
public InputHandler(Bird bird) {
// myBird and bird
myBird = bird;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
myBird.onClick();
return true;
}
#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 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;
}
Bird class
public class Bird {
private Vector2 position;
private Vector2 velocity;
private Vector2 acceleration;
private float rotation; // For handling bird rotation
private int width;
private int height;
public Bird(float x, float y, int width, int height) {
this.width = width;
this.height = height;
position = new Vector2(230, 650);
velocity = new Vector2(0, 0);
acceleration = new Vector2(200, 0);
}
public void update(float delta) {
velocity.add(acceleration.cpy().scl(delta));
if (velocity.x > 200) {
velocity.x = 200;
}
position.add(velocity.cpy().scl(delta));
// Turn
/*if (velocity.y < 0) {
rotation -= 600 * delta;
if (rotation < -20) {
rotation = -20;
}
}*/
/* Turn
if (isFalling()) {
rotation += 480 * delta;
if (rotation > 90) {
rotation = 90;
}
}*/
}
/*public boolean isFalling() {
return velocity.y > 110;
}*/
public void onClick() {
velocity.x = -140;
}
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;
}
Change your touchDown code to this and remove the comment tags
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
if (screenX < WIDTH_OF_SCREEN / 2) {
myBird.setLeftMove(true);
} else {
myBird.setRightMove(true);
}
return true;
}
and then change your touchUp code to this
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
myBird.setLeftMove(false);
myBird.setRightMove(false);
return true;
}
You will need to replace the WIDTH_OF_SCREEN with the width of your screen. What this will do is it will check to see where the screen was pressed, the left being less than half the screen and the right being more than half the screen. When the finger is lifted it will stop moving them to the left and right.
What the title says basically.
The jump worked perfectly until I decided to make my game more object-oriented by adding a GameObject class. The sprite should jump whenever you tap the screen (added a print statement in jump() to verify that this method DOES get called). Can anyone spot the mistake?
The way I've coded the jump:
player is constantly decelerating until he reaches the ground
if the screen is tapped, the players ySpeed is increased by accelerationJump, then decreased slowly by g while he's in the air
Player:
public class Player extends GameObject implements InputProcessor {
private float g;
private float accelerationJump = 9f;
private boolean allowJump = true;
public Player(Sprite spr) {
super(spr);
setxPos(0);
setyPos(getHeight() / 6);
setxSpeed(5.5f);
setySpeed(0);
spr.setX(getxPos());
spr.setY(getyPos());
g = 0.2f;
accelerationX = 0.02f;
}
public void update() {
setySpeed(-g);
//have the sprite constantly moving
moveBy(getxSpeed(), getySpeed());
//if sprite reaches end of screen, move it to the start of the screen again
if (getxPos() > getWidth()) {
setxPos(0);
}
if (getyPos() < getHeight() / 6) {
moveTo(getSprite().getX(), getHeight() / 6);
}
//the player can only jump if he is on the ground. once player is on the ground, he must stop decelerating
if (onGround()) {
allowJump = true;
setySpeed(0);
}
}
public void jump() {
System.out.println("dasdasddadsdasd");
setySpeed(getySpeed() + accelerationJump);
}
// checks whether or not player is on the ground
public boolean onGround() {
return (getSprite().getY() == getHeight() / 6);
}
#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) {
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
//if (allowJump && isDragged == false) {
//System.out.println("dsdasdasd");
if(allowJump){
allowJump = false;
jump();
}
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
/*if (isDragged == false) {
isDragged = true;
}*/
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
return false;
}
#Override
public boolean scrolled(int amount) {
return false;
}
}
GameObject
public abstract class GameObject {
private Sprite spr;
private float xSpeed;
private float ySpeed;
public GameObject(Sprite spr) {
this.spr=spr;
}
public void moveTo(float xPos2, float yPos2) {
setxPos(xPos2);
setyPos(yPos2);
}
public void moveBy(float dx, float dy) {
spr.setY(spr.getY() + dy);
spr.setX(spr.getX() + dx);
}
public float getxPos() {
return spr.getX();
}
public float getyPos() {
return spr.getY();
}
public void setxPos(float xPos2) {
spr.setX(xPos2);
}
public void setyPos(float yPos) {
spr.setY(yPos);
}
public float getxSpeed() {
return xSpeed;
}
public float getySpeed() {
return ySpeed;
}
public void setxSpeed(float xSpeed2) {
xSpeed = xSpeed2;
}
public void setySpeed(float ySpeed2) {
ySpeed = ySpeed2;
}
public int getWidth() {
return Gdx.graphics.getWidth();
}
public int getHeight() {
return Gdx.graphics.getHeight();
}
public void draw(SpriteBatch batch) {
spr.draw(batch);
}
public Sprite getSprite() {
return spr;
}
}
Any help is HIGHLY appreciated.
You are setting ySpeed to -g every update()