I am using rajawali library to load obj model in android, for that i use this camera class which contains guesture detector and guesture listener but I need to extra panning operation in this class:
public class ArcballCamera extends Camera
{
private Context mContext;
private ScaleGestureDetector mScaleDetector;
private View.OnTouchListener mGestureListener;
private GestureDetector mDetector;
private View mView;
private boolean mIsRotating;
private boolean mIsScaling;
private Vector3 mCameraStartPos;
private Vector3 mPrevSphereCoord;
private Vector3 mCurrSphereCoord;
private Vector2 mPrevScreenCoord;
private Vector2 mCurrScreenCoord;
private Quaternion mStartOrientation;
private Quaternion mCurrentOrientation;
private Object3D mEmpty;
private Object3D mTarget;
private Matrix4 mScratchMatrix;
private Vector3 mScratchVector;
private double mStartFOV;
public ArcballCamera(Context context, View view) {
this(context, view, null);
}
public ArcballCamera(Context context, View view, Object3D target) {
super();
mContext = context;
mTarget = target;
mView = view;
initialize();
addListeners();
}
private void initialize() {
mStartFOV = mFieldOfView;
mLookAtEnabled = true;
setLookAt(0, 0, 0);
mEmpty = new Object3D();
mScratchMatrix = new Matrix4();
mScratchVector = new Vector3();
mCameraStartPos = new Vector3();
mPrevSphereCoord = new Vector3();
mCurrSphereCoord = new Vector3();
mPrevScreenCoord = new Vector2();
mCurrScreenCoord = new Vector2();
mStartOrientation = new Quaternion();
mCurrentOrientation = new Quaternion();
}
#Override
public void setProjectionMatrix(int width, int height) {
super.setProjectionMatrix(width, height);
}
private void mapToSphere(final float x, final float y, Vector3 out)
{
float lengthSquared = x * x + y * y;
if (lengthSquared > 1)
{
out.setAll(x, y, 0);
out.normalize();
}
else
{
out.setAll(x, y, Math.sqrt(1 - lengthSquared));
}
}
private void mapToScreen(final float x, final float y, Vector2 out)
{
out.setX((2 * x - mLastWidth) / mLastWidth);
out.setY(-(2 * y - mLastHeight) / mLastHeight);
}
private void startRotation(final float x, final float y)
{
mapToScreen(x, y, mPrevScreenCoord);
mCurrScreenCoord.setAll(mPrevScreenCoord.getX(), mPrevScreenCoord.getY());
mIsRotating = true;
}
private void updateRotation(final float x, final float y)
{
mapToScreen(x, y, mCurrScreenCoord);
applyRotation();
}
private void endRotation()
{
mStartOrientation.multiply(mCurrentOrientation);
}
private void applyRotation()
{
if (mIsRotating)
{
mapToSphere((float) mPrevScreenCoord.getX(), (float) mPrevScreenCoord.getY(), mPrevSphereCoord);
mapToSphere((float) mCurrScreenCoord.getX(), (float) mCurrScreenCoord.getY(), mCurrSphereCoord);
Vector3 rotationAxis = mPrevSphereCoord.clone();
rotationAxis.cross(mCurrSphereCoord);
rotationAxis.normalize();
double rotationAngle = Math.acos(Math.min(1, mPrevSphereCoord.dot(mCurrSphereCoord)));
mCurrentOrientation.fromAngleAxis(rotationAxis, MathUtil.radiansToDegrees(rotationAngle));
mCurrentOrientation.normalize();
Quaternion q = new Quaternion(mStartOrientation);
q.multiply(mCurrentOrientation);
mEmpty.setOrientation(q);
}
}
#Override
public Matrix4 getViewMatrix() {
Matrix4 m = super.getViewMatrix();
if(mTarget != null) { mScratchMatrix.identity();
mScratchMatrix.translate(mTarget.getPosition());
m.multiply(mScratchMatrix);
}
mScratchMatrix.identity();
mScratchMatrix.rotate(mEmpty.getOrientation());
m.multiply(mScratchMatrix);
if(mTarget != null) {
mScratchVector.setAll(mTarget.getPosition());
mScratchVector.inverse();
mScratchMatrix.identity();
mScratchMatrix.translate(mScratchVector);
m.multiply(mScratchMatrix);
}
return m;
}
public void setFieldOfView(double fieldOfView) {
synchronized (mFrustumLock) {
mStartFOV = fieldOfView;
super.setFieldOfView(fieldOfView);
}
}
... In this method defined guesture detector and listeners, so i need to have panning here.
so anyone tell me how to use panning here...
private void addListeners() {
((Activity) mContext).runOnUiThread(new Runnable() {
#Override
public void run() {
mDetector = new GestureDetector(mContext, new GestureListener());
mScaleDetector = new ScaleGestureDetector(mContext, new ScaleListener());
mGestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
if (!mIsScaling) {
mDetector.onTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
if (mIsRotating) {
endRotation();
mIsRotating = false;
}
}
}
return true;
}
};
mView.setOnTouchListener(mGestureListener);
}
});
}
public void setTarget(Object3D target) {
mTarget = target;
setLookAt(mTarget.getPosition());
}
public Object3D getTarget() {
return mTarget;
}
private class GestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX, float distanceY) {
if(!mIsRotating) {
startRotation(event2.getX(), event2.getY());
return false;
}
mIsRotating = true;
updateRotation(event2.getX(), event2.getY());
return false;
}
}
private class ScaleListener
extends ScaleGestureDetector.SimpleOnScaleGestureListener
{
#Override
public boolean onScale(ScaleGestureDetector detector) {
double fov = Math.max(30, Math.min(100, mStartFOV * (1.0 / detector.getScaleFactor())));
setFieldOfView(fov);
return true;
}
#Override
public boolean onScaleBegin (ScaleGestureDetector detector) {
mIsScaling = true;
mIsRotating = false;
return super.onScaleBegin(detector);
}
#Override
public void onScaleEnd (ScaleGestureDetector detector) {
mIsRotating = false;
mIsScaling = false;
}
}
}**
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.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I am trying to launch a very basic app - a ball that should bounce on the screen but I am getting an error while trying to launch app on device.
Here's my code, I may have some errors but please explain to me what are they and how could I fix them, I'm new to android development..
public class Ball {
float x;
float y;
boolean movingRight;
boolean movingBottom;
float screenWidth;
float screenHeight;
public Ball(float x, float y, float screenWidth, float screenHeight) {
this.x = x;
this.y = y;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight - 150;
this.movingBottom = false;
this.movingRight = false;
}
public void move() {
if (movingRight)
this.x++;
else
this.x--;
if (movingBottom)
this.y++;
else
this.y--;
if (this.x >= this.screenWidth)
this.movingRight = false;
else if (this.x <= 1)
this.movingRight = true;
if (this.y >= this.screenHeight)
this.movingBottom = false;
else if (this.y <= 1)
this.movingBottom = true;
}
public float getX(){
return this.x;
}
public float getY() {
return this.y;
}
public class MySurfaceView extends SurfaceView{
private Ball ball;
private SurfaceHolder holder;
Paint paint;
public Paint getBallPaint()
{
if(paint == null)
{
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(3);
}
return this.paint;
}
public MySurfaceView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
draw(c);
holder.unlockCanvasAndPost(c);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
#Override
public void draw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawCircle(ball.x,ball.y,15,getBallPaint());
}
}
public class GameLoopThread extends Thread {
private MySurfaceView view;
private boolean running = false;
public GameLoopThread(MySurfaceView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
while (running) {
Canvas c = null;
try {
c = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
view.draw(c);
}
} finally {
if (c != null) {
view.getHolder().unlockCanvasAndPost(c);
}
}
}
}
}
public class MainActivity extends ActionBarActivity {
Ball ball;
MySurfaceView mySurfaceView;
GameLoopThread gameLoopThread;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int screenWidth;
screenWidth = getWindowManager().getDefaultDisplay().getWidth();
int screenHeight;
screenHeight = getWindowManager().getDefaultDisplay().getHeight();
ball = new Ball(screenWidth / 2, screenHeight / 2, screenWidth,screenHeight);
gameLoopThread = new GameLoopThread(mySurfaceView);
gameLoopThread.start();
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
}
I cannot tell if there are other errors but most obvious one is that you are using mySurfaceView before you have created it.
You should change initialization order to:
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
gameLoopThread = new GameLoopThread(mySurfaceView);
gameLoopThread.start();
I am using LWJGL and SlickUtil to make a game, and I made my own GLButton class that you can click. It works fine, but I want to add action listener implementation so I don't have to make a new class for each button that has a different action when it gets clicked. I want it so I can do
GLButton.addActionListener((ActionEvent e) -> {
//do method here
});
Here is the code of the class
public class GLButton {
private boolean alive = false;
private float x1;
private float y1;
private float x2;
private float y2;
private String text;
private final Texture tex;
private final Texture texOver;
private final Texture texPressed;
private Texture currentTexture;
private boolean pressed=false;
public GLButton(float x, float y, float width, float height, String text) {
this.x1=x;
this.y1=y;
this.x2=width;
this.y2=height;
this.text=text;
tex=loadTexture("btn");
texOver=loadTexture("btnOver");
texPressed=loadTexture("btnPressed");
currentTexture = tex;
alive=true;
}
public void draw() {
if(!alive) return;
pollInput();
currentTexture.bind();
glColor3f(1,1,1);
glBegin(GL_QUADS);
glTexCoord2f(0,0);glVertex2f(x1,y1);
glTexCoord2f(0,1);glVertex2f(x1,y1+y2);
glTexCoord2f(1,1);glVertex2f(x1+x2,y1+y2);
glTexCoord2f(1,0);glVertex2f(x1+x2,y1);
glEnd();
}
public void setText(String text) {
this.text=text;
}
public void setLocation(float x, float y) {
this.x1=x;
this.y1=y;
}
public void setSize(float width, float height) {
this.x2=width;
this.y2=height;
}
private Texture loadTexture(String key) {
try {
return TextureLoader.getTexture("PNG", new FileInputStream(
Start.main_dir+"\\res\\textures\\"+key+".png"));
} catch (IOException ex) {
Logger.getLogger(GLButton.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
private void pollInput() {
if(GameWindow.grabbed==true) return;
int mouseY = Math.abs(Mouse.getY()-Display.getHeight());
currentTexture = tex;
if(Mouse.getX()>=(int)x1 && Mouse.getX()<=(int)x1+(int)x2 && mouseY >= (int)y1 && mouseY <= (int)y1+(int)y2) {
currentTexture = texOver;
if(Mouse.isButtonDown(0)&&pressed==false) {
pressed=true;
currentTexture = texPressed;
} else if(!Mouse.isButtonDown(0)) {
pressed=false;
}
}
}
public boolean isAlive() {
return alive;
}
public void destroy() {
alive=false;
}
public float getX() {
return x1;
}
public float getY() {
return y1;
}
public float getWidth() {
return x2;
}
public float getHeight() {
return y2;
}
}
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.
So in my Gameplay screen user has posibillity to click on menu button and then that menu button will pause the game and show the menu.
I tried to impelement menu as a new stage, but that just opens a new screen, sets the graphics of the menu like I want to and leaves the rest of the screen black.
Here's the image so you can see what I'm talking about:
I want this green part to smoothly slide into Gameplay scene and I wan't to get rid of this black part of the screen and instead leave that part transparent (I want it to show only the green part of a Image).
Tried to find some good tutorials about pause menus, but no luck.
Here's the code of my pause screen:
public class Menu implements Screen{
Stage menuStage = null;
private Image menu_bg = null;
private Main game = null;
public Menu(Main gm){
game = gm;
}
#Override
public void show() {
menuStage = new Stage(new StretchViewport(1920, 1080));
Gdx.input.setInputProcessor(menuStage);
menu_bg = new Image(new Texture(Gdx.files.internal("menuProba.png")));
menuStage.addActor(menu_bg);
menuButtons();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
menuStage.draw();
menuStage.act();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
private void menuButtons(){
Table menuButtons = new Table();
menuButtons.setFillParent(true);
final Image resumeGame = new Image(new Texture(Gdx.files.internal("playbutton.png")));
final Image retryGame = new Image(new Texture(Gdx.files.internal("retrybutton.png")));
final Image homeButton = new Image(new Texture(Gdx.files.internal("homebutton.png")));
final Image exitButton = new Image(new Texture(Gdx.files.internal("exitbutton.png")));
resumeGame.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
resumeGame.addAction(Actions.scaleTo(1, 1.1f,.1f));
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
resumeGame.addAction(Actions.scaleTo(1, 1,.1f));
}
});
retryGame.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
retryGame.addAction(Actions.scaleTo(1, 1.1f,.1f));
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
retryGame.addAction(Actions.scaleTo(1, 1,.1f));
}
});
homeButton.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
homeButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
homeButton.addAction(Actions.scaleTo(1, 1,.1f));
game.setScreen(new MainMenu(game));
}
});
exitButton.addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
exitButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
exitButton.addAction(Actions.scaleTo(1, 1,.1f));
}
});
/*HorizontalGroup horizontalGroup = new HorizontalGroup();
horizontalGroup.addActor(resumeGame);
horizontalGroup.addActor(retryGame);
horizontalGroup.addActor(homeButton);
horizontalGroup.addActor(exitButton);
menuButtons.add(horizontalGroup);*/
menuButtons.add(resumeGame).expand().left().padLeft(40);
menuButtons.row();
menuButtons.add(retryGame).expand().left().padLeft(40);
menuButtons.row();
menuButtons.add(homeButton).expand().left().padLeft(40);
menuButtons.row();
menuButtons.add(exitButton).expand().left().padLeft(40);
menuStage.addActor(menuButtons);
}
}
And the Gameplay screen:
public class GameScreen implements Screen, InputProcessor {
boolean menuScreen;
private Texture menuImage = null;
public boolean buttonMenuTouched = false;
public InputMultiplexer multiplexer = null;
BitmapFont font;
//SCORE-------------------------------------
private SpriteBatch batch = null;
private OrthographicCamera mCamera = null;
private BitmapFont scoreFont = null;
private int score = 0;
//--------------------------------------------
Main game = null;
public Texture font_texture;
public GameScreen(Main gm){
game = gm;
}
Stage gameStage = null;
private Image game_bg = null, menu_bg = null;
private GameManager manager = null;
#Override
public void show() {
mCamera = new OrthographicCamera(1920, 1080);
font_texture = new Texture(Gdx.files.internal("font.png"));
font_texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
scoreFont = new BitmapFont(Gdx.files.internal("font.fnt"), new TextureRegion(font_texture), false);
batch = new SpriteBatch();
multiplexer = new InputMultiplexer();
gameStage = new Stage(new StretchViewport(1920, 1080));
multiplexer.addProcessor(this);
multiplexer.addProcessor(gameStage);
Gdx.input.setInputProcessor(multiplexer);
game_bg = new Image(new Texture(Gdx.files.internal("pozadinaGameScreen.png")));
gameStage.addActor(game_bg);
menuImage = new Texture("menuProba.png");
manager = new GameManager(game, this, gameStage);
manager.createPlayer();
manager.createBlueMonster();
manager.createHUDButtons();
manager.createGameOverStage();
gameScreenButtoni();
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
gameStage.draw();
gameStage.act();
manager.checkButtons();
manager.checkCollisions();
batch.setProjectionMatrix(mCamera.combined);
batch.begin();
this.scoreFont.draw(batch, ""+manager.score, Gdx.graphics.getWidth() - 1070, Gdx.graphics.getHeight() - 580);
batch.end();
if (manager.gameOver == true){
manager.gameOverStage.draw();
manager.gameOverStage.act();
Gdx.input.setInputProcessor(manager.gameOverStage);
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
manager.gameOverStage.dispose();
gameStage.dispose();
manager.dispose();
game.setScreen(game.mainMenu);
}
// METODE INPUT PROCESORA
#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 false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
manager.shootBullet();
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;
}
public void gameScreenButtoni(){
//menuImage = new Image(new Texture(Gdx.files.internal("menuProba.png")));
Table buttoni = new Table();
buttoni.setFillParent(true);
final Image menuButton = new Image(new Texture(Gdx.files.internal("menubutton.png")));
menuButton.addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button){
menuButton.addAction(Actions.scaleTo(1, 1.1f,.1f));
buttonMenuTouched = true;
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button){
menuButton.addAction(Actions.scaleTo(1, 1,.1f));
buttonMenuTouched = false;
game.setScreen(new Menu(game));
}
});
final Image scoreText = new Image(new Texture(Gdx.files.internal("score.png")));
buttoni.add(menuButton).expand().top().left().padLeft(20).padTop(20);
buttoni.add(scoreText).expand().top().right().padTop(30).padRight(140);
gameStage.addActor(buttoni);
}
public void menuScreen(){
Stage menu = new Stage(new StretchViewport(400,400));
menu_bg = new Image(new Texture(Gdx.files.internal("logoMali.png")));
menu.addActor(menu_bg);
}
}
I know that I'm doing this wrong, but how should I do it? Draw a rectangle when button is pressed or what?
In my game I make NavigationDrawer in libgdx as you can see:
You can make this with sample code, just follow a few steps:
1- Copy NavigationDrawer class into your project:
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Timer;
import com.badlogic.gdx.utils.Timer.Task;
/**
* Created by Crowni on 10/6/2015.
*/
public class NavigationDrawer {
// this value is suitable
private static final float INTERVAL_SEC = 0.001f;
// Some attributes for {#link NavigationDrawer}
private static float CAM_MAIN_POSITION;
public static float WIDTH;
public static float SPEED;
private static OrthographicCamera camera;
/**
* To ensure the {#link NavigationDrawerListener#onFinish()} called one time
**/
private static boolean isFinish = true;
private static Task task;
private static Timer timer = new Timer();
private static NavigationDrawerListener listener;
public interface NavigationDrawerListener {
public void onStart();
// May be you want to make some Actions here during sliding
public void onRun();
public void onFinish(float camX);
}
public static void initialize(Stage stage, NavigationDrawerListener listener) {
NavigationDrawer.listener = listener;
camera = ((OrthographicCamera) stage.getCamera());
setNavigationDrawerDefault(stage);
initializeTimerTask(false);
}
private static void setNavigationDrawerDefault(Stage stage) {
WIDTH = stage.getWidth() - stage.getWidth() / 3;
CAM_MAIN_POSITION = stage.getWidth() / 2;
SPEED = 2f;
}
private static Task initializeTimerTask(boolean show) {
task = new Task() {
public void run() {
if (!timer.isEmpty()) {
if (show)
camera.position.x -= SPEED;
else
camera.position.x += SPEED;
listener.onRun();
} else if (isFinish) {
listener.onFinish(setDefaultCameraEndPostion(show));
}
}
};
return task;
}
/**
* #param show
* : I passed it here because I know it is correct choice
**/
private static float setDefaultCameraEndPostion(boolean show) {
isFinish = false;
if (show)
return camera.position.x = CAM_MAIN_POSITION - WIDTH;
else
return camera.position.x = CAM_MAIN_POSITION;
}
private static boolean isOpened() {
return camera.position.x != CAM_MAIN_POSITION;
}
public static void show(boolean show) {
if ((isOpened() && !show) || (!isOpened() && show))
startTask(show);
}
private static void startTask(boolean show) {
if (timer.isEmpty()) {
isFinish = true;
listener.onStart();
timer.scheduleTask(initializeTimerTask(show), 0f, INTERVAL_SEC,
((int) (WIDTH / SPEED)));
}
}
}
2- In your Screen write the following:
#Override
public void show() {
stage = new Stage(new StretchViewport(1080, 1920));
// May be you want to make some Actions with NavigationDrawer state
NavigationDrawerListener listener = new NavigationDrawerListener() {
#Override
public void onStart() {
System.out.println("onStart");
}
#Override
public void onRun() {
System.out.println("onRun");
}
#Override
public void onFinish(float camX) {
System.out.println("onFinish: " + camX);
}
};
// You must be initialize NavigationDrawer Firstly
NavigationDrawer.initialize(stage, listener);
// This image is sample to show how navigationDrawer look like on the screen
Image background= new Image(new Texture(Gdx.files.internal("background.jpg")));
background.addListener(new ClickListener() {
private int clicked = 0;
public void clicked(InputEvent event, float x, float y) {
if (clicked % 2 == 0) {
clicked++;
NavigationDrawer.show(true);
} else {
clicked++;
NavigationDrawer.show(false);
}
}
});
background.setFillParent(true);
stage.addActor(background);
Gdx.input.setInputProcessor(stage);
}
3- The result of sample code look like that:
4- Finally you can create images, labels, ... actors in navigation width which their positions into off-screen i.e. with negative positions. Enjoy!
UPDATE
This Navigation Drawer More performance and beauty sliding.