OOP player implementation libgdx - java

I would like some suggestions for the implementation object of the player.
the player can have 2 textures that will be chosen depending on the button pressed, for example, the right arrow will display a texture to the left while another texture.
I have implemented the interface inputprocessor in the class of player but I do not know why it does not seem very fair and very dynamic, so I would like some suggestions from you
thank you very much
CODE:
public class Player implements InputProcessor {
private Texture up;
private Texture down;
private Sprite player;
public Player(Texture one,Texture two){
this.up=one;
this.down=two;
player=new Sprite(one);
}
#Override
public boolean keyDown(int keycode) {
// TODO Auto-generated method stub
player.setTexture(this.down);
return false;
}
#Override
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
player.setTexture(this.up);
return false;
}
#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) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#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;
}
}
I implement the player class in this way, but I would like some suggestions for implementing best.

I'd suggest you to subclass very useful Sprite class and use TextureAtlas to contain player textures. here is the stub of implementation:
public class Player extends Sprite {
TextureAtlas textureAtlas;
public Player(TextureAtlas atlas) {
super(atlas.getRegions().get(0));
textureAtlas = atlas;
}
public void setTexture(String textureName) {
setRegion(textureAtlas.findRegion(textureName)));
}
}
Here is a very nice tutorial explaining how to use TextureAtlas.
Also, instead of implementing whole InputProcessor, use InputAdapter which provides an empty implementation of this interface. This will be much more clearer. It can be a field in your Player class:
private InputProcessor inputProcessor = new InputAdapter() {
// Override only methods you need here
};
Of course, don't forget to register this InputProcessor:
Gdx.input.setInputProcessor(inputProcessor);

I will update my answer with examples when i get home in a few hours.
It doesnt seem a good practice to listen for keys in the player class. I implemented a player class in my game some time ago and it was like this:
in the render method of your game class you implement key listeners, that invoke player.up() or player.down() or for example player.jump().
in player class in those methods, for example in jump() you set textures/animations.
I will post code examples.
public class Player {
float x;
float y;
float xSpeed;
float ySpeed;
private Animation playerRun;
private Animation playerJump;
private Animation playerStand;
private Animation current;
private Rectangle bounds;
public Player(){
playerRun = new Animation(1/10f, Assets.atlas.findRegions("run"));
playerRun.setPlayMode(Animation.PlayMode.LOOP);
//set other animations in similar way
current = playerStand;
this.x = Gdx.graphics.getWidth()/2;
this.y = Gdx.graphics.getHeight()/2;
bounds = new Rectangle(x, y, 100, 100);
}
public Rectangle getBounds(){
return bounds;
}
public void setPos(float x, float y){
this.x = x;
this.y = y;
bounds.x = x;
bounds.y = y;
}
public void changePos(float x, float y){
this.x +=x;
this.y +=y;
bounds.x += x;
bounds.y += y;
}
public void move(){
changePos(xSpeed, ySpeed);
}
public Animation animate(){
return current;
}
public void run(){
current = playerRun;
ySpeed = 0;
}
public void jump(){
current = playerJump;
ySpeed = 10;
}
and the render method in my game class was only calling players methods:
if (Gdx.input.isTouched()){
player.jump();
}
oops, forgot the most important part :
batch.draw(player.animate().getKeyFrame(time += delta), player.x, player.y);

Related

Libgdx - How to use "Long Press"?

I have tried finding an answer to solve the problem, but I think that I don't seem to understand how to use the long press in Libgdx.
I want my character to move right when I long press on the right half of the screen and left when I long press on the left half of the screen.
I have searched and tried.
Here is my InputHandler class :
public class InputHandler implements InputProcessor {
private MainCharacter myMainCharacter;
public InputHandler(MainCharacter mainCharacter) {
myMainCharacter = mainCharacter;
}
#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) {
myMainCharacter.onClick();
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;
}
}
And here is my MainCharacter class :
public class MainCharacter {
private Vector2 position;
private Vector2 velocity;
private Vector2 acceleration;
private float rotation;
private int width;
private int height;
public MainCharacter(float x, float y, int width, int height) {
this.width = width;
this.height = height;
position = new Vector2(x, y);
velocity = new Vector2(0, 0);
acceleration = new Vector2(0, 460);
}
public void update(float delta) {
velocity.add(acceleration.cpy().scl(delta));
if (velocity.y > 200) {
velocity.y = 200;
}
position.add(velocity.cpy().scl(delta));
}
public void onClick() {
if (Gdx.input.getX() <= 135) {
Gdx.app.log("TAG", "LEFT");
position.x--;
} else if (Gdx.input.getX() >= 137) {
Gdx.app.log("TAG", "RIGHT");
position.x++;
}
}
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;
}
}
I used onClick() method as a replacement until I find a solution for the problem. It works fine but it doesn't have the same effect as the long press. My character moves left when I click on the left side of the screen and right when I click on the right side of the screen. But of course it doesn't work when I long press.
So how can I use 'Long Press' ?
I would really appreciate your help.
Gokul gives a nice overview of the GestureListener but I do not believe this is what you are looking for. LongPress indeed only registers after some seconds of pressing and you want to have a touch control the character immediately.
There is no out of the box method in the listeners to keep detecting touched but you can create it yourself.
if (Gdx.input.isTouched())
{
//Finger touching the screen
// You can actually start calling onClick here, if those variables and logic you are using there are correct.
if (Gdx.input.getX() >= screenSize / 2)
{
//Right touched
}
else if (Gdx.input.getX() < screenSize / 2)
{
//Left touched
}
}
Just check for this every frame and do your logic.
You can implement the long press by implementing the GestureListner interface.
GestureDetector will let you detect the following gestures:
touchDown: A user touches the screen.
longPress: A user touches the screen for some time.
tap: A user touches the screen and lifts the finger again. The finger must not move outside a specified square area around the initial touch position for a tap to be registered. Multiple consecutive taps will be detected if the user performs taps within a specified time interval.
pan: A user drags a finger across the screen. The detector will report the current touch coordinates as well as the delta between the current and previous touch positions. Useful to implement camera panning in 2D.
panStop: Called when no longer panning.
fling: A user dragged the finger across the screen, then lifted it. Useful to implement swipe gestures.
zoom: A user places two fingers on the screen and moves them together/apart. The detector will report both the initial and current distance between fingers in pixels. Useful to implement camera zooming.
pinch: Similar to zoom. The detector will report the initial and current finger positions instead of the distance. Useful to implement camera zooming and more sophisticated gestures such as rotation.
A GestureDetector is an event handler. To listen for gestures, one must implement the GestureListener interface and pass it to the constructor of the GestureDetector. The detector is then set as an InputProcessor, either on an InputMultiplexeror as the main InputProcessor:
public class MyGestureListener implements GestureListener{
#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 pan(float x, float y, float deltaX, float deltaY) {
return false;
}
#Override
public boolean panStop(float x, float y, int pointer, int button) {
return false;
}
#Override
public boolean zoom (float originalDistance, float currentDistance){
return false;
}
#Override
public boolean pinch (Vector2 initialFirstPointer, Vector2 initialSecondPointer, Vector2 firstPointer, Vector2 secondPointer){
return false;
}
#Override
public void pinchStop () {
}
}
You have to set the GestureDetector that contains your GestureListener as the InputProcessor:
Gdx.input.setInputProcessor(new GestureDetector(new MyGestureListener()));
For more details, check out the link below
https://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/input/GestureDetector.GestureListener.html

How to make a sprite move with keyboard in java(libgdx)

i'm making a game for school motives, i have already made the sprite and the background(tiled map) my problem is how i can make the sprite move left, right, back and down using the keyboard, please guys help me as soon as possible here is my code:
public class LEVEL1 implements ApplicationListener, Screen {
private Music music;
private SpriteBatch batch;
private Texture Sprite;
private Vector2 position;
private TiledMap map;
private OrthogonalTiledMapRenderer renderer;
private OrthographicCamera camera;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
position.y = position.y - 5;
// player Controls
if(position.y < 0){
position.y = 0;
}
//..................................................
// renderer camera and map
camera.update();
renderer.setView(camera);
renderer.render();
//...................................................
//tells the computer when to start drawing textures
batch.begin();
batch.draw(Sprite, position.x, position.y, 50, 50);
batch.end();
//...................................................
camera = new OrthographicCamera();
camera.setToOrtho(true, 2920,950);
}
#Override
public void show() {
Sprite = new Texture("Sprite.png");
batch = new SpriteBatch();
position = new Vector2(650, Gdx.graphics.getHeight());
map = new TmxMapLoader().load("map1.tmx");
renderer = new OrthogonalTiledMapRenderer(map);
camera = new OrthographicCamera();
music = Gdx.audio.newMusic((Gdx.files.internal("GameSound.mp3")));
music.setLooping(false);
music.setVolume(0.5f);
music.play();
}
#Override
public void create() {
}
#Override
public void resize(int width, int height) {
camera.viewportWidth = width;
camera.viewportHeight = height;
camera.position.set(width/2f, height/3f, 0); //by default camera position on (0,0,0)
camera.update();
}
#Override
public void render() {
if(Gdx.input.justTouched())
music.play();
}
#Override
public void dispose() {
map.dispose();
renderer.dispose();
music.dispose();
}
#Override
public void hide() {
// TODO Auto-generated method stub
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
}
Here i make a little example of moving a sprite using keys (up,down, left,right)
you should find more details in libgdx wiki
public class Level1 implements ApplicationListener {
Sprite sprite;
SpriteBatch batch;
float spriteXposition;
float spriteYposition;
#Override
public void render() {
Gdx.gl.glClearColor(1, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
//tells the computer when to start drawing textures
batch.begin();
sprite.setPosition(spriteXposition, spriteYposition);
sprite.draw(batch);
batch.end();
spriteControl();
}
public void spriteControl() {
if(Gdx.input.isKeyPressed(Keys.UP)) {
spriteYposition++;
}
if(Gdx.input.isKeyPressed(Keys.DOWN)) {
spriteYposition--;
}
if(Gdx.input.isKeyPressed(Keys.LEFT)) {
spriteXposition--;
}
if(Gdx.input.isKeyPressed(Keys.RIGHT)) {
spriteXposition++;
}
}
#Override
public void create() {
sprite = new Sprite(new Texture(Gdx.files.internal("sprite.png")));
batch = new SpriteBatch();
}
}
To react on input events you need to implement InputProcessor. It has the methods keyDown (called when a key is pressed) and keyUp (called when a key is released).
Those methods have an argument keyCode, which defines the int code of the pressed/released key.
So you need to override this 2 methods and depending on the keyCode you get, you should do something or not.
To move the player for example, you might keep a member speed, which you set, depending on the pressed/released key. In the render method you then need to update the position depending on the elapsed time (delta) and the speed.
To get the input event, you need to tell libgdx, that your InputProcessor should be the active one. This is done by calling Gdx.input.setInputProcessor(yourInputProcessor).
Also make sure to read the Libgdx wiki, many of your questions will be answered there.
EDIT:
Some code:
public class Level implements ApplicationListener, InputProcessor {
private int speedX; // Speed in x direction
private Vector2 position; // Position
private boolean keyDown(int keyCode) {
boolean result = false;
if (keyCode == Keys.D) {
result = true;
speed += 5;
}
else if (keyCode == Keys.A) {
result = true;
speed -= 5;
}
return result;
}
private boolean keyUp(int keyCode) {
boolean result = false;
if (keyCode == Keys.D) {
result = true;
speed -= 5;
}
else if (keyCode == Keys.A) {
result = true;
speed += 5;
}
return result;
}
public void render(float delta) {
position.x += speed*delta;
// Render here
}
}

Constructing a GestureDetector in libGDX

I have been detecting different kinds of input with the different implemented Gesture Detector methods. I do however want to change some of the preferences of the G.D by changing the parameters of the method below:
public GestureDetector(float halfTapSquareSize,
float tapCountInterval,
float longPressDuration,
float maxFlingDelay,
GestureDetector.GestureListener listener)
I got ^ code of http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/input/GestureDetector.html
I am especially interested in changing the value of "halfTapSquareSize"
How would I go about implementing that into my code below?
public class MyGdxGame extends ApplicationAdapter implements GestureDetector.GestureListener {
#Override
public void create() {
super.create();
//Doing stuff at create
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void render() {
super.render();
//Rendering stuff
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
//disposing stufff
}
#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) {
// Doing stuff at tap
return true;
}
#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 pan(float x, float y, float deltaX, float deltaY) {
//Doing stuff when paning
}
#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;
}
}
Your code only implements the GestureListener. This listener needs to be associated with a GestureDetector, and the GestureDetector then needs to be registered to handle input.
So within your MyGdxGame class, you'll need something like this:-
GestureDetector input = new GestureDetector(this); // 'this' refers to your MyGdxGame instance
Gdx.input.setInputProcessor(input);
Now you can either supply extra arguments to GestureDetector's constructor, as you have mentioned in your post, or use the GestureDetector's relevant methods, like so:
input.setTapSquareSize(someFloatValue);

Trying to get an array of images to work on Onclick

I don't know what I'm doing wrong here
//This is the Bullet Class. Here All I need is the Y position (because the Bullet is going only Y. The image which is in my drawable hdpi folder contains the image of my bullet.
public class Bulletbun extends GameObject {
private int deltaY;
private android.media.Image img;
public Bulletbun(final int xPos, final int yPos, final Image img){
this.img= img;
this.xPos=xPos;
this.yPos=yPos;
}
public Bulletbun(float f, int i, int j, String string) {
// TODO Auto-generated constructor stub
}
#Override
public void draw(Graphics g){
g.drawImage (img, xPos, yPos, null);
}
#Override
void update() {
// TODO Auto-generated method stub
}
}
}
}
// Trying to make it fire from here... This is my OnClick. What I want is When I touch the button I made, an Image would shoot out on the Y position of the screen. Also If I were to hit it multiple time it would shoot more than one (5). But also destroy the ones that are off-screen to save memory.
#Override
public void onClick(View v) { //+sound
// TODO Auto-generated method stub //+sound
Bulletbun Bulletbunny= new Bulletbun(bunbutt.getX()+20, 4,4, "images/air_bunny.png");
if (barrelblast != 0)
sp.play(barrelblast, 1, 1, 0, 0, 1); //+sound
Vibrator vibe = (Vibrator)getSystemService(Context.VIBRATOR_SERVICE);
vibe.vibrate(90);
smoke.setVisibility(View.VISIBLE);
Handler delayedAction = new Handler();
delayedAction.postDelayed(new Runnable() {
public void run() {
smoke.setVisibility(View.INVISIBLE);
//This is my GameObject Class
package com.ramy.fallingbarrels;
import com.badlogic.gdx.Graphics;
import android.media.Image;
public abstract class GameObject {
protected Image img;
protected int xPos;
protected int yPos;
abstract void draw (Graphics g);
abstract void update();
public Image getImg() {
return img;
}
public void setImg(Image img) {
this.img = img;
}
public int getxPos() {
return xPos;
}
public void setxPos(int xPos) {
this.xPos = xPos;
}
public int getYpos() {
return yPos;
}
public void setYpos(int ypos) {
this.yPos = ypos;
}
//I was trying to follow a tutorial. If I'm doing something wrong here please tell me. Also if there's a better way to do what I described please tell me.

Get Coordinates before and after touch released

I am trying to make slingshot type thing(like in angry birds) using LIBGDX(currently learning). So, how do I get the coordinates of the point where user touched the screen and dragged finger to other point n released . I want both co-ordinates initial and released point.
I also want to know how to achieve the above in Android SDK/NDK.
I have not tested this but this should be around about what you need
#Override
Public boolean onTouchEvent (MotionEvent event) {
int downx;
int downy;
int upx;
int upy;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downy = (int)event.gety();
downx = (int)event.getx();
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
upy = (int)event.gety();
upx = (int)event.getx();
}
return false;
}
public class TempScreen extends Screen
{
Game game; // the class which is implementing the InputProcessor
SpriteBatch batcher;
Vector3 touchPoint;
OrthographicCamera cam;
InputMultiplexer multiplexer;
GestureListener listener=new GestureListener()
{
#Override
public boolean zoom(float initialDistance, float distance)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean touchDown(float x, float y, int pointer, int button)
{
cam.unproject(touchPoint.set(x, y, 0));
System.out.println(touchPoint);
return false;
}
#Override
public boolean tap(float x, float y, int count, int button)
{
// 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;
}
#Override
public boolean panStop(float x, float y, int pointer, int button)
{
// TODO Auto-generated method stub
return false;
}
#Override
public boolean pan(float x, float y, float deltaX, float deltaY)
{
// 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 fling(float velocityX, float velocityY, int button)
{
// TODO Auto-generated method stub
return false;
}
};
GestureDetector detector=new GestureDetector(listener)
{
public boolean touchUp(float x, float y, int pointer, int button)
{
cam.unproject(touchPoint.set(x, y, 0));
System.out.println(touchPoint);
return false;
}
};
public TempScreen(Game game,SpriteBatch batcher)
{
super(game);
this.batcher=batcher;
this.game=game;
touchPoint = new Vector3();
cam = new OrthographicCamera(GameConstants.CAMERA_WIDTH,GameConstants.CAMERA_HEIGHT);
cam.position.set(GameConstants.CAMERA_WIDTH / 2,GameConstants.CAMERA_HEIGHT / 2, 0);
multiplexer = new InputMultiplexer();
multiplexer.addProcessor(game);
multiplexer.addProcessor(detector);
Gdx.input.setInputProcessor(multiplexer);
}
#Override
public void render(float deltaTime)
{
update(deltaTime);
GLCommon gl = Gdx.gl;
gl.glClearColor(0, 0f, 1f, 0.1f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
cam.update();
batcher.setProjectionMatrix(cam.combined);
batcher.enableBlending();
batcher.begin();
draw(deltaTime);
batcher.end();
}
#Override
public void draw(float deltaTime)
{
// TODO Auto-generated method stub
}
#Override
public void update(float deltaTime)
{
// TODO Auto-generated method stub
}
#Override
public void backKeyPressed()
{
// TODO Auto-generated method stub
}
}
Make an InputProcessor and a Vector3:
MyInputprocessor myInputprocessor;
Vector3 touchPoint = new Vector3();
Define the InputProcessor like this:
public class MyInputprocessor implements InputProcessor{
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button){
guicam.unproject(touchPoint.set(screenX, screenY, 0)); //Initial point coordinates
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer){
guicam.unproject(touchPoint.set(screenX, screenY, 0)); //current point coordinates (when you are dragging it)
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button){
guicam.unproject(touchPoint.set(screenX, screenY, 0)); //final/release point coordinates
return false;
}
#Override public boolean keyTyped(char character){return false;}
#Override public boolean mouseMoved(int screenX, int screenY){return false;}
#Override public boolean scrolled(int amount){return false;}
#Override public boolean keyDown(int keycode){return false;}
#Override public boolean keyUp(int keycode){return false;}
}
Create it and set it in your ini code:
myInputprocessor = new MyInputprocessor();
Gdx.input.setInputProcessor(myInputprocessor);

Categories

Resources