Implementing a Gamepad Controller in LIBGDX? - java

I'm at a loss as to how to implement the LIBGDX controller support. So here are the details.
Let's say I'm following the tutorial here: http://obviam.net/index.php/getting-started-in-android-game-development-with-libgdx-create-a-working-prototype-in-a-day-tutorial-part-1/
The Git for the tutorial at Part 4 (where i'm trying to implement a gamepad) is here: https://github.com/obviam/star-assault/tree/part4
I've made it to the final step and now it's running and I can interact with the character using the keyboard. I want to now make the character controllable via a controller either with the OUYA or through USB.
I have read the following: http://www.badlogicgames.com/wordpress/?p=2724
I have added the jar files to the main project and have Ordered and Exported.
I have now modified my GameScreen class to look as follows:
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.controllers.Controller;
import com.badlogic.gdx.controllers.PovDirection;
import com.badlogic.gdx.controllers.mappings.Ouya;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.math.Vector3;
public class GameScreen implements Screen, InputProcessor, ControllerListener {
private World world;
private WorldRenderer renderer;
private CharacterController charactercontroller;
private int width, height;
#Override
public void show() {
world = new World();
renderer = new WorldRenderer(world, false);
charactercontroller = new CharacterController(world);
Gdx.input.setInputProcessor(this);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.1f, 0.1f, 0.1f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
charactercontroller.update(delta);
renderer.render();
}
#Override
public void resize(int width, int height) {
renderer.setSize(width, height);
this.width = width;
this.height = height;
}
#Override
public void hide() {
Gdx.input.setInputProcessor(null);
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
Gdx.input.setInputProcessor(null);
}
// * InputProcessor methods ***************************//
#Override
public boolean keyDown(int keycode) {
if (keycode == Keys.LEFT)
charactercontroller.leftPressed();
if (keycode == Keys.RIGHT)
charactercntroller.rightPressed();
if (keycode == Keys.UP)
charactercontroller.jumpPressed();
return true;
}
#Override
public boolean keyUp(int keycode) {
if (keycode == Keys.LEFT)
charactercontroller.leftReleased();
if (keycode == Keys.RIGHT)
charactercontroller.rightReleased();
if (keycode == Keys.UP)
charactercontroller.jumpReleased();
return true;
}
#Override
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
if (!Gdx.app.getType().equals(ApplicationType.Android))
return false;
if (x < width / 2 && y > height / 2) {
charactercontroller.leftPressed();
}
if (x > width / 2 && y > height / 2) {
charactercontroller.rightPressed();
}
return true;
}
#Override
public boolean touchUp(int x, int y, int pointer, int button) {
if (!Gdx.app.getType().equals(ApplicationType.Android))
return false;
if (x < width / 2 && y > height / 2) {
charactercontroller.leftReleased();
}
if (x > width / 2 && y > height / 2) {
charactercontroller.rightReleased();
}
return true;
}
#Override
public boolean touchDragged(int x, int y, int pointer) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean scrolled(int amount) {
// TODO Auto-generated method stub
return false;
}
#Override
public void connected(Controller controller) {
// TODO Auto-generated method stub
}
#Override
public void disconnected(Controller controller) {
// TODO Auto-generated method stub
}
#Override
public boolean buttonDown(Controller controller, int buttonCode) {
if (buttonCode == Ouya.BUTTON_O) {
charactercontroller.jumpPressed();
}
return false;
}
#Override
public boolean buttonUp(Controller controller, int buttonCode) {
if (buttonCode == Ouya.BUTTON_O) {
charactercontroller.jumpReleased();
}
return false;
}
#Override
public boolean axisMoved(Controller controller, int axisCode, float value) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean povMoved(Controller controller, int povCode,
PovDirection value) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean xSliderMoved(Controller controller, int sliderCode,
boolean value) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean ySliderMoved(Controller controller, int sliderCode,
boolean value) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean accelerometerMoved(Controller controller,
int accelerometerCode, Vector3 value) {
// TODO Auto-generated method stub
return false;
}
}
So based on my understand of how this works, right now when I load this on the OUYA the character should Jump when the "O" button is pressed. But nothing happens. I think I'm missing something. Any glaring mistakes in implementation?
Where I'm at with Java is I've been web developing for a number of years and have just recently returned to Java again to play around with games and interactive stuff on micro consoles. I figure starting off with a simple tutorial and experimenting with building on it would be a good idea, right?
Look forward to getting some awesome help!
Thanks,
Phil

Try adding:
Controllers.addListener(this);
right before:
Gdx.input.setInputProcessor(this);
setInputProcessor only registers listeners for the built-in input events (keys, touch events, etc). The controllers are an external library, and it needs to be initialized and loaded separately.
You will need to import com.badlogic.gdx.controllers.Controllers, too.

Related

Player Character Movement Error LibGDX RPG

I am making an RPG game, however, I have an error at the moment. The player's character can move in all four cardinal directions, but the player becomes stuck if you move right, up or down.
Also, the error seems to have some logic to it:
if moving down, the character is stuck in a loop moving down
unless the up arrow is pressed, then the player will begin a new infinite loop for up
unless the right arrow is pressed, then the player will begin a new infinite loop for right
So right seems to take precedence over up which takes precedence over down.
Strangely, the leftward movement works perfectly. Even when the character is stuck in an infinite loop, the left arrow key will always cause the player to move left in the correct way.
I don't understand where the error is in my code. I don't know why the leftward movement works while the other three directions do not. I don't understand why there seems to be some sort of priority ordering between the other three directions as well.
I have looked through the program and I don't think I treat leftward movement differently to any other direction. However, I might be wrong, considering this error.
Due to the 30k word limit, I do not have enough space to include all the code here. Therefore, I have included a link to my github, so you can see the code there instead.
https://github.com/davey67/bludbourne
I think these classes are probably the most important classes though:
package com.bludbourne.game.desktop;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Application;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.bludbourne.game.BludBourne;
public class DesktopLauncher {
public static void main (String[] arg) {
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.title="BludBourne";
config.useGL30=false;
config.width =480;
config.height=480;
Application app = new LwjglApplication(new BludBourne(),config);
Gdx.app=app;
Gdx.app.setLogLevel(Application.LOG_DEBUG);
}
}
/
package com.bludbourne.game;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.bludbourne.game.screens.MainGameScreen;
import com.badlogic.gdx.Game;
public class BludBourne extends Game {
public static final MainGameScreen _mainGameScreen = new MainGameScreen();
#Override
public void create () {
setScreen(_mainGameScreen);
}
#Override
public void dispose () {
_mainGameScreen.dispose();
}
}
/
package com.bludbourne.game;
import java.util.HashMap;
import java.util.Map;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.math.Vector3;
public class PlayerController implements InputProcessor
{
private final static String TAG = PlayerController.class.getSimpleName();
enum Keys{
LEFT,RIGHT,UP,DOWN,QUIT
}
enum Mouse{
SELECT,DOACTION
}
private static Map<Keys,Boolean> keys=new HashMap<PlayerController.Keys,Boolean>();
private static Map<Mouse,Boolean> mouseButtons = new HashMap<PlayerController.Mouse,Boolean>();
private Vector3 lastMouseCoordinates;
static {
keys.put(Keys.LEFT,false);
keys.put(Keys.RIGHT,false);
keys.put(Keys.UP,false);
keys.put(Keys.DOWN, false);
keys.put(Keys.QUIT, false);
}
static {
mouseButtons.put(Mouse.SELECT, false);
mouseButtons.put(Mouse.DOACTION, false);
}
private Entity _player;
public PlayerController(Entity player) {
this.lastMouseCoordinates=new Vector3();
this._player=player;
}
#Override
public boolean keyDown(int keycode)
{
if(keycode ==Input.Keys.LEFT||keycode==Input.Keys.A) {
this.leftPressed();
}
if(keycode ==Input.Keys.RIGHT||keycode==Input.Keys.D) {
this.rightPressed();
}
if(keycode ==Input.Keys.UP||keycode==Input.Keys.W) {
this.upPressed();
}
if(keycode ==Input.Keys.DOWN||keycode==Input.Keys.S) {
this.downPressed();
}
if(keycode==Input.Keys.Q) {
this.quitPressed();
}
return true;
}
#Override
public boolean keyUp(int keycode)
{
if(keycode ==Input.Keys.LEFT||keycode==Input.Keys.A) {
this.leftReleased();
}
if(keycode ==Input.Keys.RIGHT||keycode==Input.Keys.D) {
this.rightReleased();
}
if(keycode ==Input.Keys.UP||keycode==Input.Keys.W) {
this.upReleased();
}
if(keycode ==Input.Keys.DOWN||keycode==Input.Keys.S) {
this.downReleased();
}
if(keycode==Input.Keys.Q) {
this.quitReleased();
}
return true;
}
#Override
public boolean keyTyped(char character)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button)
{
if(button==Input.Buttons.LEFT||button==Input.Buttons.RIGHT) {
this.setClickedMouseCoordinates(screenX,screenY);
}
if(button==Input.Buttons.LEFT) {
this.selectMouseButtonPressed(screenX,screenY);
}
if(button==Input.Buttons.RIGHT) {
this.doActionMouseButtonPressed(screenX,screenY);
}
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button)
{
if(button==Input.Buttons.LEFT) {
this.selectMouseButtonReleased(screenX,screenY);
}
if(button==Input.Buttons.RIGHT) {
this.doActionMouseButtonReleased(screenX,screenY);
}
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean mouseMoved(int screenX, int screenY)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean scrolled(int amount)
{
// TODO Auto-generated method stub
return false;
}
public void dispose() {
}
public void leftPressed() {
keys.put(Keys.LEFT,true);
}
public void rightPressed() {
keys.put(Keys.RIGHT,true);
}
public void upPressed() {
keys.put(Keys.UP,true);
}
public void downPressed() {
keys.put(Keys.DOWN,true);
}
public void quitPressed() {
keys.put(Keys.QUIT, true);
}
public void setClickedMouseCoordinates(int x,int y) {
lastMouseCoordinates.set(x,y,0);
}
public void selectMouseButtonPressed(int x,int y) {
mouseButtons.put(Mouse.SELECT,true);
}
public void doActionMouseButtonPressed(int x,int y) {
mouseButtons.put(Mouse.DOACTION, true);
}
public void leftReleased() {
keys.put(Keys.LEFT,false);
}
public void rightReleased() {
keys.put(Keys.RIGHT,true);
}
public void upReleased() {
keys.put(Keys.UP,true);
}
public void downReleased() {
keys.put(Keys.DOWN,true);
}
public void quitReleased() {
keys.put(Keys.QUIT, true);
}
public void selectMouseButtonReleased(int x,int y) {
mouseButtons.put(Mouse.SELECT, false);
}
public void doActionMouseButtonReleased(int x ,int y) {
mouseButtons.put(Mouse.DOACTION, false);
}
public void update(float delta) {
processInput(delta);
}
public static void hide() {
keys.put(Keys.LEFT, false);
keys.put(Keys.RIGHT, false);
keys.put(Keys.UP, false);
keys.put(Keys.DOWN, false);
keys.put(Keys.QUIT, false);
}
private void processInput(float delta) {
if(keys.get(Keys.LEFT)) {
_player.calculateNextPosition(Entity.Direction.LEFT,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.LEFT,delta);
}
else if(keys.get(Keys.RIGHT)) {
_player.calculateNextPosition(Entity.Direction.RIGHT,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.RIGHT,delta);
}
else if(keys.get(Keys.UP)) {
_player.calculateNextPosition(Entity.Direction.UP,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.UP,delta);
}
else if(keys.get(Keys.DOWN)) {
_player.calculateNextPosition(Entity.Direction.DOWN,delta);
_player.setState(Entity.State.WALKING);
_player.setDirection(Entity.Direction.DOWN,delta);
}
else if(keys.get(Keys.QUIT)) {
Gdx.app.exit();
}
else {
_player.setState(Entity.State.IDLE);
}
if(mouseButtons.get(Mouse.SELECT)) {
mouseButtons.put(Mouse.SELECT, false);
}
}
}
/
package com.bludbourne.game;
import java.util.UUID;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Animation;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
public class Entity
{
private static final String TAG = Entity.class.getSimpleName();
private static final String _defaultSpritePath = "sprites/characters/Warrior.png";
private Vector2 _velocity;
private String _entityID;
private Direction _currentDirection = Direction.LEFT;
private Direction _previousDirection = Direction.UP;
private Animation _walkLeftAnimation;
private Animation _walkRightAnimation;
private Animation _walkUpAnimation;
private Animation _walkDownAnimation;
private Array<TextureRegion> _walkLeftFrames;
private Array<TextureRegion> _walkRightFrames;
private Array<TextureRegion> _walkUpFrames;
private Array<TextureRegion> _walkDownFrames;
protected Vector2 _nextPlayerPosition;
protected Vector2 _currentPlayerPosition;
protected State _state = State.IDLE;
protected float _frameTime = 0f;
protected Sprite _frameSprite = null;
protected TextureRegion _currentFrame = null;
public final int FRAME_WIDTH = 16;
public final int FRAME_HEIGHT = 16;
public static Rectangle boundingBox;
public enum State
{
IDLE, WALKING
}
public enum Direction
{
UP, RIGHT, DOWN, LEFT
}
public Entity() {
initEntity();
}
public void initEntity()
{
this._entityID = UUID.randomUUID().toString();
this._nextPlayerPosition = new Vector2();
this._currentPlayerPosition = new Vector2();
this.boundingBox = new Rectangle();
this._velocity = new Vector2(2f, 2f);
Utility.loadTextureAsset(_defaultSpritePath);
loadDefaultSprite();
loadAllAnimations();
}
public void update(float delta)
{
_frameTime = (_frameTime + delta) % 5;
setBoundingBoxSize(0f, 0.5f);
}
public void init(float startX, float startY)
{
this._currentPlayerPosition.x = startX;
this._currentPlayerPosition.y = startY;
this._nextPlayerPosition.x = startX;
this._nextPlayerPosition.y = startY;
}
public void setBoundingBoxSize(float percentageWidthReduced, float percentageHeightReduced)
{
float width;
float height;
float widthReductionAmount = 1.0f - percentageWidthReduced;
float heightReductionAmount = 1.0f - percentageHeightReduced;
if (widthReductionAmount > 0 && widthReductionAmount < 1)
{
width = FRAME_WIDTH * widthReductionAmount;
}
else
{
width = FRAME_WIDTH;
}
if (heightReductionAmount > 0 && heightReductionAmount < 1)
{
height = FRAME_HEIGHT * heightReductionAmount;
}
else
{
height = FRAME_HEIGHT;
}
if (width == 0 || height == 0)
{
Gdx.app.debug(TAG, "Width and Height are 0!! " + width + ":" + height);
}
float minX;
float minY;
if (MapManager.UNIT_SCALE > 0)
{
minX = _nextPlayerPosition.x / MapManager.UNIT_SCALE;
minY = _nextPlayerPosition.y / MapManager.UNIT_SCALE;
}
else
{
minX = _nextPlayerPosition.x;
minY = _nextPlayerPosition.y;
}
boundingBox.set(minX, minY, width, height);
}
private void loadDefaultSprite()
{
Texture texture = Utility.getTextureAsset(_defaultSpritePath);
TextureRegion[][] textureFrames = TextureRegion.split(texture, FRAME_WIDTH, FRAME_HEIGHT);
_frameSprite = new Sprite(textureFrames[0][0].getTexture(), 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
_currentFrame = textureFrames[0][0];
}
public void loadAllAnimations()
{
Texture texture = Utility.getTextureAsset(_defaultSpritePath);
TextureRegion[][] textureFrames = TextureRegion.split(texture, FRAME_WIDTH, FRAME_HEIGHT);
_walkDownFrames = new Array<TextureRegion>(4);
_walkLeftFrames = new Array<TextureRegion>(4);
_walkRightFrames = new Array<TextureRegion>(4);
_walkUpFrames = new Array<TextureRegion>(4);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
TextureRegion region=textureFrames[i][j];
if(region==null) {
Gdx.app.debug(TAG, "Got null animation frame "+i+","+j);
}
switch(i) {
case 0:
_walkDownFrames.insert(j,region);
break;
case 1:
_walkLeftFrames.insert(j,region);
break;
case 2:
_walkRightFrames.insert(j,region);
break;
case 3:
_walkUpFrames.insert(j,region);
break;
}
}
}
_walkDownAnimation = new Animation(0.25f,_walkDownFrames,Animation.PlayMode.LOOP);
_walkLeftAnimation = new Animation(0.25f,_walkLeftFrames,Animation.PlayMode.LOOP);
_walkRightAnimation = new Animation(0.25f,_walkRightFrames,Animation.PlayMode.LOOP);
_walkUpAnimation = new Animation(0.25f,_walkUpFrames,Animation.PlayMode.LOOP);
}
public void dispose() {
Utility.unloadAsset(_defaultSpritePath);
}
public void setState(State state) {
this._state = state;
}
public Sprite getFrameSprite() {
return _frameSprite;
}
public TextureRegion getFrame() {
return _currentFrame;
}
public Vector2 getCurrentPosition() {
return _currentPlayerPosition;
}
public void setCurrentPosition(float currentPositionX,float currentPositionY) {
_frameSprite.setX(currentPositionX);
_frameSprite.setY(currentPositionY);
this._currentPlayerPosition.x=currentPositionX;
this._currentPlayerPosition.y=currentPositionY;
}
public void setDirection(Direction direction,float deltaTime) {
this._previousDirection=this._currentDirection;
this._currentDirection=direction;
switch(_currentDirection) {
//not sure about this
case DOWN:
_currentFrame=(TextureRegion) _walkDownAnimation.getKeyFrame(_frameTime);
break;
case LEFT:
_currentFrame=(TextureRegion) _walkLeftAnimation.getKeyFrame(_frameTime);
break;
case RIGHT:
_currentFrame=(TextureRegion) _walkRightAnimation.getKeyFrame(_frameTime);
break;
case UP:
_currentFrame=(TextureRegion) _walkUpAnimation.getKeyFrame(_frameTime);
break;
default:
break;
}
}
public void setNextPositionToCurrent() {
setCurrentPosition(_nextPlayerPosition.x,_nextPlayerPosition.y);
}
public void calculateNextPosition(Direction currentDirection,float deltaTime) {
float testX=_currentPlayerPosition.x;
float testY=_currentPlayerPosition.y;
_velocity.scl(deltaTime);
switch(currentDirection) {
case LEFT:
testX-=_velocity.x;
break;
case RIGHT:
testX+=_velocity.x;
break;
case UP:
testY+=_velocity.y;
break;
case DOWN:
testY-=_velocity.y;
break;
default:
break;
}
_nextPlayerPosition.x=testX;
_nextPlayerPosition.y=testY;
_velocity.scl(1/deltaTime);
}
}
I feel that I am probably missing something obvious, however, I still cannot see the error. Help is much appreciated. Thank you.
My github also contains the sprite sheet and the three maps, all of which would be stored in the asset folder of my project.
May I draw your attention to these four methods in PlayerInput
public void leftReleased() {
keys.put(Keys.LEFT,false);
}
public void rightReleased() {
keys.put(Keys.RIGHT,true);
}
public void upReleased() {
keys.put(Keys.UP,true);
}
public void downReleased() {
keys.put(Keys.DOWN,true);
}
I believe it should be false, not true when the key is released. I've verified that this prevents the infinite loop.
The priority order of right, up, then down is due to the order in which the keys are checked in processInput.

LibGdx - Where is PanStop in GestureDetector?

I've a Screen class that implements GestureListener, but it doesn't provide the PanStop method (which is mentioned in the LibGdx JavaDocs and Wiki)
Has this method been removed (and the docs out of date), or am I missing something?
If the former, then how does one detect and handle a touch-up or pan-stop?
Thanks.
EDIT: Implementation added....
package com.me.mygdxgame;
import com.badlogic.gdx.Gdx;
import java.util.Random;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.actions.MoveToAction;
import com.badlogic.gdx.utils.Array;
import com.me.mygdxgame.actors.ActorJ;
public class JGameScreen implements Screen, GestureListener {
final MyGdxGame game;
private Stage stage;
private GameGrid gameGrid;
// Constructor & Init Screen
//
public JGameScreen(final MyGdxGame gam) {
game = gam;
stage = new Stage();
stage.setViewport(600, 600, true);
gameGrid = new GameGrid(stage, 10, 10);
}
// GestureListener Events
//
#Override
public void show() {
// TODO Auto-generated method stub
Gdx.input.setInputProcessor(new GestureDetector(this));
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
//chain = gameGrid.getChain();
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
// TODO Auto-generated method stub
vector2 = stage.screenToStageCoordinates(vector2.set(x,y));
gameGrid.get(25).setPosition(vector2.x, vector2.y);
return true;
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public void hide() {
// TODO Auto-generated method stub
Gdx.input.setInputProcessor(null);
}
#Override
public void render(float delta) {
// TODO Auto-generated method stub
Gdx.gl.glClearColor( 0.9f, .04f, 0.2f, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
#Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
stage.setViewport(game.WIDTH, game.HEIGHT, true);
stage.getCamera().translate(-50, -50, 0);
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
#Override
public boolean tap(float x, float y, int count, int button) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean longPress(float x, float y) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean zoom(float initialDistance, float distance) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
// TODO Auto-generated method stub
return false;
}
}
I got the nightly build last week and I can see panStop in GestureListener interface. Odd issue.

Android: Lag in code when using classes

I'm a beginner in Android programming, and I'm working on a small bubble shooter game. However, I face a weird problem which I cannot figure out. I have a piece of code which handles the launcher of the app, if I program the whole code in class, the app runs smooth. However, if I 'cut' the code into different classes there a noticeable lag in the movement of the launcher.
My main question is: what can cause this lag, and what is the best approach to avoid this (now and in the future).
Thanks in advance,
Kind regards,
This is my code when I program everything in one class.
package com.example.bubbleshootergame;
// imports are delete to shorten the post
public class GameThree extends Activity implements OnTouchListener {
OurView v;
Bitmap launcher;
float x, y, rotationAngle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
v = new OurView(this);
v.setOnTouchListener(this);
launcher = BitmapFactory.decodeResource(getResources(),
R.drawable.launcher);
setContentView(v);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
v.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
v.resume();
}
public class OurView extends SurfaceView implements Runnable {
Thread t = null;
SurfaceHolder holder;
boolean bool = false;
public OurView(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
// x & y are the width and height of the usable screen size
x = content.getWidth();
y = content.getHeight();
}
#Override
public void run() {
// TODO Auto-generated method stub
while (bool == true) {
if (!holder.getSurface().isValid()) {
continue;
}
Canvas c = holder.lockCanvas();
Paint Blackline = new Paint();
Blackline.setColor(Color.rgb(0, 0, 0));
Blackline.setStrokeWidth(10);
// background color of canvas
c.drawARGB(255, 255, 255, 255);
c.drawRect(0, (float) 0.85*y, x, (float) 0.84*y, Blackline);
// rotate by angle 'rotationAngle' around point x/2 and y
// this corresponds the middle of the launcher
c.rotate(rotationAngle, x / 2, y - (launcher.getHeight() / 2));
// draw the bitmap (this case the launcher) around the center of
// the width of the launcher and bottom of the launcher
c.drawBitmap(launcher, x / 2 - (launcher.getWidth() / 2), y
- (launcher.getHeight()), null);
holder.unlockCanvasAndPost(c);
}
}
public void pause() {
// TODO Auto-generated method stub
bool = false;
while (true) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
t = null;
}
public void resume() {
// TODO Auto-generated method stub
bool = true;
t = new Thread(this);
t.start();
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
float currentX = event.getX();
float currentY = event.getY();
if (currentY >= 0.85*y ){
}
else
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
double rotationAngleRadians = Math.atan2(currentX - x / 2, y
- currentY);
rotationAngle = (int) Math.toDegrees(rotationAngleRadians);
return true;
}
}
return true;
}
}
Here are the code block when uses different classes:
MainActivity
package com.gabrudar.conquestappgame;
public class MainActivity extends Activity implements OnTouchListener {
GameView view;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
view = new GameView(this);
view.setOnTouchListener(this);
setContentView(view);
}
#Override
protected void onPause() {
super.onPause();
view.pause();
}
#Override
protected void onResume() {
super.onResume();
view.resume();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
view.processTouch(event);
return true;
}
}
GameView:
package com.gabrudar.conquestappgame;
public class GameView extends SurfaceView implements Runnable {
Thread gameThread = null;
SurfaceHolder holder;
boolean continueRunning = false;
Bitmap blob;
Bitmap background;
Sprite sprite;
Rect screenRect;
Bitmap Launcher;
LauncherC launcher;
long startTime;
float deltaTime;
public GameView(Context context) {
super(context);
holder = getHolder();
screenRect = new Rect();
background = BitmapFactory.decodeResource(getResources(), R.drawable.androidbg);
blob = BitmapFactory.decodeResource(getResources(), R.drawable.spritesheet);
Launcher = BitmapFactory.decodeResource(getResources(),
R.drawable.launcher);
launcher = new LauncherC(Launcher);
}
#Override
public void run() {
startTime = System.nanoTime();
while (continueRunning == true){
if (!holder.getSurface().isValid()){
continue;
}
deltaTime = (System.nanoTime() - startTime)/1000000;
startTime = System.nanoTime();
Canvas c = holder.lockCanvas();
onDraw(c);
holder.unlockCanvasAndPost(c);
}
}
public void pause() {
continueRunning = false;
while(true){
try{
gameThread.join();
}catch(InterruptedException e){
e.printStackTrace();
}
break;
}
gameThread = null;
}
public void resume() {
continueRunning = true;
gameThread = new Thread(this);
gameThread.start();
}
protected void update(float dt) {
}
protected void onDraw(Canvas canvas) {
this.getDrawingRect(screenRect);
canvas.drawBitmap(background, null, screenRect, null);
launcher.onDraw(canvas);
}
public void processTouch(MotionEvent me) {
launcher.Toucher(me);
}
}
Launcher:
package com.gabrudar.conquestappgame;
public class LauncherC {
float rotationAngle,x1,y1;
Bitmap L1;
public LauncherC(Bitmap Launcher){
L1 = Launcher;
}
public void onDraw(Canvas c) {
// TODO Auto-generated method stub
Paint Blackline = new Paint();
Blackline.setColor(Color.rgb(0, 0, 0));
Blackline.setStrokeWidth(10);
x1 = c.getWidth();
y1 = c.getHeight();
c.drawRect(0, (float) 0.85 * y1, x1, (float) 0.84 * y1, Blackline);
c.rotate(rotationAngle, x1 / 2, y1 - (L1.getHeight() / 2));
c.drawBitmap(L1, x1 / 2 - (L1.getWidth() / 2), y1
- (L1.getHeight()), null);
}
public void Toucher(MotionEvent event){
// TODO Auto-generated method stub
float currentX = event.getX();
float currentY = event.getY();
if (currentY >= 0.85 * y1) {
} else
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE: {
double rotationAngleRadians = Math.atan2(currentX - x1 / 2, y1
- currentY);
rotationAngle = (int) Math.toDegrees(rotationAngleRadians);
break;
}
}
}
}
Well one glaring difference I see is this in your "separated" code. I don't see it in the original code, and it will definitely induce a lag, since you're sleeping 50ms every time you receive a touch event. That can happen many times per second with a drag-type movement.
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(50);
....

Slick button will not work

I am following a video tutorial on a java game ( so I can go off from there ) but one of my buttons will not work (exit button). Please Help. I'm using lwjgl and slick.
main class:
package javagame;
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;
public class Game extends StateBasedGame {
public static final String gamename = "Java Game Alpha 1.0";
public static final int menu = 0;
public static final int play = 1;
public Game(String gamename) {
super(gamename);
this.addState(new Menu(menu));
this.addState(new Play(play));
}
public void initStatesList(GameContainer gc) throws SlickException{
this.getState(menu).init(gc, this);
this.getState(play).init(gc, this);
this.enterState(menu);
}
public static void main(String[] args) {
AppGameContainer appgc;
try{
appgc = new AppGameContainer(new Game(gamename));
appgc.setDisplayMode(1600, 800, false);
appgc.start();
}catch(SlickException e) {
e.printStackTrace();
}
}
}
menu class:
package javagame;
import org.newdawn.slick.*;
import org.newdawn.slick.state.*;
import org.lwjgl.input.Mouse;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.GameState;
import org.newdawn.slick.state.StateBasedGame;
public class Menu implements GameState {
Image PlayNow;
Image exitGame;
public Menu(int state){
}
#Override
public void mouseClicked(int arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void mouseDragged(int arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(int arg0, int arg1, int arg2, int arg3) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(int arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(int arg0, int arg1, int arg2) {
// TODO Auto-generated method stub
}
#Override
public void mouseWheelMoved(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void inputEnded() {
// TODO Auto-generated method stub
}
#Override
public void inputStarted() {
// TODO Auto-generated method stub
}
#Override
public boolean isAcceptingInput() {
// TODO Auto-generated method stub
return false;
}
#Override
public void setInput(Input arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyPressed(int arg0, char arg1) {
// TODO Auto-generated method stub
}
#Override
public void keyReleased(int arg0, char arg1) {
// TODO Auto-generated method stub
}
#Override
public void controllerButtonPressed(int arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void controllerButtonReleased(int arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void controllerDownPressed(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerDownReleased(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerLeftPressed(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerLeftReleased(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerRightPressed(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerRightReleased(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerUpPressed(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void controllerUpReleased(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void enter(GameContainer arg0, StateBasedGame arg1)
throws SlickException {
// TODO Auto-generated method stub
}
#Override
public int getID() {
// TODO Auto-generated method stub
return 0;
}
#Override
public void init(GameContainer gc, StateBasedGame sbg)
throws SlickException {
// TODO Auto-generated method stub
PlayNow = new Image ("res/PlayNow.png");
exitGame = new Image ("res/exitGame.png");
}
#Override
public void leave(GameContainer arg0, StateBasedGame arg1)
throws SlickException {
// TODO Auto-generated method stub
}
#Override
public void render(GameContainer gc, StateBasedGame sbg, Graphics g)
throws SlickException {
// TODO Auto-generated method stub
g.drawString("It's time for an adventure!", 50, 50);
//g.drawRect(730, 320, 70, 80); //x, y, width, height
PlayNow.draw(680, 320, 250, 50);
exitGame.draw(680, 380, 250, 50);
int xpos = Mouse.getX();
int ypos = Mouse.getY();
g.drawString("Mouse Position: " + xpos + " " + ypos, 10, 22);
}
#Override
public void update(GameContainer gc, StateBasedGame sbg, int delta)
throws SlickException {
// TODO Auto-generated method stub
int xpos = Mouse.getX();
int ypos = Mouse.getY();
Input input = gc.getInput();
//play now
if( (xpos > 683) && (xpos < 920) && (ypos > 440) && (ypos < 478) ) {
if(Mouse.isButtonDown(0)) {
sbg.enterState(1);
}
//exit Game
if ( (xpos > 683) && (xpos < 920) && (ypos > 379) && (ypos < 417) ) {
if(Mouse.isButtonDown(0)) {
gc.exit();
}
}
}
}
}
and there is one more class, but it doesn't matter. Please help!
The problem is your second if statement is nested within the first. So, the first statement must be true for the second to exit. Unfortunately, for the first statement to be true, the second can never be true. So the second never executes.
The first if requires ypos>440 && ypos<478. The second if requires ypos>379 && <417. There is no overlap between those 2 ranges, and so the second if can never execute. Here's your code with cleaner formatting.
if( (xpos > 683) && (xpos < 920) && (ypos > 440) && (ypos < 478) ) {
if(Mouse.isButtonDown(0)) {
sbg.enterState(1);
}
//ypos will never be less than 417 because to reach this point it MUST
//be greater than 440 due to first if statement.
if ( (xpos > 683) && (xpos < 920) && (ypos > 379) && (ypos < 417) ) {
if(Mouse.isButtonDown(0)) {
gc.exit();
}
}
}
And here's the solution:
if( (xpos > 683) && (xpos < 920) && (ypos > 440) && (ypos < 478) ) {
if(Mouse.isButtonDown(0)) {
sbg.enterState(1);
}
}
//exit Game
if ( (xpos > 683) && (xpos < 920) && (ypos > 379) && (ypos < 417) ) {
if(Mouse.isButtonDown(0)) {
gc.exit();
}
}
Now the second if is independent of the first.

AndEngine how to make a sprite not jump if jump method is called

So I have this method that when i touch the screen my sprite will jump. Now the problem is when I continuously touch the screen the sprite will jump again and again. What I want to do is if it jumps, the jump method cannot be called unless my sprite hits the ground.
Here is the code.
public class PhyiscsActivity extends BaseGameActivity implements IAccelerometerListener, IOnSceneTouchListener{
private static final int CAMERA_WIDTH = 720;
private static final int CAMERA_HEIGHT = 480;
private Camera mCamera;
private BitmapTextureAtlas mBitmapTextureAtlas;
private TiledTextureRegion mTextureRegion;
private Scene mScene;
private FixtureDef mFixtureDef = PhysicsFactory.createFixtureDef(1,-10f, 0.5f);
private PhysicsWorld mPhysicsWorld;
private Body body;
private AnimatedSprite facebox;
private FixtureDef wallfixture = PhysicsFactory.createFixtureDef(-1,0.5f, 0.5f);
#Override
public Engine onLoadEngine() {
// TODO Auto-generated method stub
this.mCamera = new Camera(0,0,CAMERA_WIDTH, CAMERA_HEIGHT);
final EngineOptions mEngineOptions = new EngineOptions(true, ScreenOrientation.LANDSCAPE, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT),this.mCamera);
mEngineOptions.getTouchOptions().setRunOnUpdateThread(true);
return new Engine(mEngineOptions);
}
#Override
public void onLoadResources() {
// TODO Auto-generated method stub
this.mBitmapTextureAtlas = new BitmapTextureAtlas(128,128, TextureOptions.BILINEAR_PREMULTIPLYALPHA);
this.mTextureRegion = BitmapTextureAtlasTextureRegionFactory.createTiledFromAsset(mBitmapTextureAtlas, this, "gfx/face_box_tiled.png", 0, 0, 2, 1);
this.mEngine.getTextureManager().loadTexture(this.mBitmapTextureAtlas);
}
#Override
public Scene onLoadScene() {
// TODO Auto-generated method stub
this.mEngine.registerUpdateHandler(new FPSLogger());
this.mScene = new Scene();
this.mScene.setBackground(new ColorBackground(1,1,1));
this.mPhysicsWorld = new PhysicsWorld(new Vector2(0,SensorManager.GRAVITY_EARTH),false);
// This is the walls
final Shape roof = new Rectangle(0, 0, CAMERA_WIDTH, 2);
final Shape ground = new Rectangle(0,CAMERA_HEIGHT - 2,CAMERA_WIDTH,2);
final Shape left = new Rectangle(0,0,2,CAMERA_HEIGHT);
final Shape right = new Rectangle(CAMERA_WIDTH -2, 0,2,CAMERA_HEIGHT);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallfixture);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallfixture);
// This is the Sprite
facebox = new AnimatedSprite(30,(CAMERA_HEIGHT - 2) - this.mTextureRegion.getHeight() ,this.mTextureRegion);
body = PhysicsFactory.createBoxBody(this.mPhysicsWorld, facebox, BodyType.DynamicBody, mFixtureDef);
this.mScene.attachChild(facebox);
this.mScene.registerUpdateHandler(this.mPhysicsWorld);
this.mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(facebox,body,true,true));
this.mScene.setOnSceneTouchListener(this);
return this.mScene;
}
#Override
public void onLoadComplete() {
// TODO Auto-generated method stub
}
//Accelerometer
#Override
public void onAccelerometerChanged(AccelerometerData pAccelerometerData) {
// TODO Auto-generated method stub
final Vector2 gravity = Vector2Pool.obtain(pAccelerometerData.getX()* 3, 10);
this.mPhysicsWorld.setGravity(gravity);
Vector2Pool.recycle(gravity);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
this.enableAccelerometerSensor(this);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
this.disableAccelerometerSensor();
}
//This is where i make the sprite jump
#Override
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
pSceneTouchEvent.isActionDown();{
this.jump(facebox);
}
return false;
}
public void jump(AnimatedSprite sprite){
boolean jumping = false;
if(!jumping ){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
}
public void jump(AnimatedSprite sprite){
if(!jumping){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-10));
jumping = true;
}
}
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
jumping = true;
}
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
jumping = false;
}
I don't know why the beginContact and endContact isn't initialzing. are there things that i should do to initialize this? example like updating a handler? contactlistener?
You need to have a method wich tell you if your player is jumping or not.
public void jump(AnimatedSprite sprite){
if( isJumping(sprite)){
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
In this method you should put the way to compute if the player is jumping. Like if he is touching a wall (if player's body (x,y) is in a wall (rectangle))
Ok you are using box2d to make physics =)
You have to create a ContactListener, you have to implement this class and the function ou want to add.
http://code.google.com/p/andenginephysicsbox2dextension/source/browse/src/com/badlogic/gdx/physics/box2d/ContactListener.java?r=1605f6e82f710ef9ebbe07632d6b055239d3b520
public void beginContact (Contact contact);
public void endContact (Contact contact);
The contact object will countain your objects (Fixture) that are touching. You just have to check and set jumping to false when the body is touching and true when you call jump and you can jump, set jumping to true;
Ok?
#Override
public void beginContact(Contact contact) {
// TODO Auto-generated method stub
jumping = true;
}
#Override
public void endContact(Contact contact) {
// TODO Auto-generated method stub
jumping = false;
}
This is false.. I would think of it like that only:
#Override
public void beginContact(Contact contact) {
jumping = false; //you touched ground so you aren't jumping anymore
}
#Override
public void endContact(Contact contact) {
jumping = true; //you leave ground so you're jumping
}
and one jump method (not two):
public void jump(AnimatedSprite sprite){
if(!jumping ){
jumping = true;
body.setLinearVelocity(new Vector2(body.getLinearVelocity().x,-8f));
}
}
You see?;

Categories