Stage.addListener not working in libgdx - input

I am just trying to add a click listener to the stage in libgdx but it is not working here is my code;
stage.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("CLICK", "LISTENER");
parallaxBackground.reverse();
return super.touchDown(event, x, y, pointer, button);
}
});
This is from my main game screen, which inherits from an abstract screen which calls,
Gdx.input.setInputProcessor(stage);
In the abstract class I also call,
stage.act(delta);
I am most definetely calling super.render() as well from the child class
What is causing this!
EDIT
I don't know if it matters but my stage has no actors but I just want to simply acknowledge a click.

Since you added no actors to your stage, your stage has no substance so it cannot be touched.
You can add create an actor that is the same size as the screen and is aligned with the screen to do what you're trying. Something like this (untested):
Actor screenActor = new Actor(){
public void act (float delta) {
super.act(delta);
Viewport viewport = getStage().getViewport();
width = viewport.getScreenWidth();
height = viewport.getScreenHeight();
x = viewport.getScreenX();
y = viewport.getScreenY();
}
};
stage.addActor(screenActor);
You would add this actor first, so other actors get first crack at intercepting touches, and this is the fallback.

Here is how I solved this problem:
In Photoshop I created a 100x100px image and put only one layer in it and set the opacity of that layer to 1%, I also removed the background (This made a totally transparent image) and saved it as .png to use it as texture.
I created an Actor and called it BgActor and drew the texture to it.
Here is the png image that I created
and here is how my Actor looks like:
The BgActor class:
public class BgActor extends Actor {
private float x, y, width, height;
private Texture texture = new Texture(Gdx.files.internal("images/transparent-bg.png"));
public BgActor(float x, float y, float width, float height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
setTouchable(Touchable.enabled);
}
#Override
public void draw(Batch batch, float parentAlpha) {
setBounds(x, y, width, height);
batch.draw(texture, x, y, width, height);
}
public void dispose() {
texture.dispose();
}
}
Implementation (I used your Listener):
BgActor bgActor = new BgActor(0, 0, stage.getWidth(), stage.getHeight);
bgActor.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("CLICK", "LISTENER");
parallaxBackground.reverse();
return super.touchDown(event, x, y, pointer, button);
}
});
......
stage.addActor(bgActor);
And don't forget to dispose the bgActor in your Screen's hide() method.
Good luck ..

Related

Return type for the method is missing processing.js

Hi i'm new to programming, and while i was trying to do an exercise this error poped up, and i have no idea what it means and how to fix it.
it's an example in the processing.js library that after i tried to copy didn't go so well.
Mover mover;
void setup(){
size (600,600);
mover = new Mover();
}
void draw(){
mover.update();
mover.display();
mover.checkEdges();
}
class Mover {
// position, velocity, and acceleration
PVector position;
PVector velocity;
PVector acceleration;
// Mass is tied to size
float mass;
Mover(float m, float x, float y) { //<<<the error occurs here
mass = m;
position = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}
// Newton's 2nd law: F = M * A
// or A = F / M
void applyForce(PVector force) {
// Divide by mass
PVector f = PVector.div(force, mass);
// Accumulate all forces in acceleration
acceleration.add(f);
}
void update() {
// Velocity changes according to acceleration
velocity.add(acceleration);
// position changes by velocity
position.add(velocity);
// We must clear acceleration each frame
acceleration.mult(0);
}
// Draw Mover
void display() {
stroke(255);
strokeWeight(2);
fill(255, 200);
ellipse(position.x, position.y, mass*16, mass*16);
}
// Bounce off bottom of window
void checkEdges() {
if (position.y > height) {
velocity.y *= -0.9; // A little dampening when hitting the bottom
position.y = height;
}
}
}
The only problem I see in your code is that your Mover constructor takes three arguments, but you're not giving it any in this line:
mover = new Mover();
So I'd fix that error before anything else. If you're still having problems, please be much more specific about exactly how you're compiling and running this code. Are you using the Processing editor? Which version? During exactly which step do you get an error?

XNA 4.0 Camera and object handling on screen

For developing a side-scrolling platform 2D game I want to implement a moving camera class, the reason of using the class instead of moving the whole map is that I'll have to use too many objects at once witch will cause a lag. I cannot let that happen.
There's a nice algorithm for handling the camera, when player is moving further than the width of the screen then camera moves on players direction until he is once again in the middle of the screen, I've been working several days for making this algorithm work however there's been no success.
// Main
public class Camera
{
protected float _zoom;
protected Matrix _transform;
protected Matrix _inverseTransform;
//The zoom scalar (1.0f = 100% zoom level)
public float Zoom
{
get { return _zoom; }
set { _zoom = value; }
}
// Camera View Matrix Property
public Matrix Transform
{
get { return _transform; }
set { _transform = value; }
}
// Inverse of the view matrix,
// can be used to get
// objects screen coordinates
// from its object coordinates
public Matrix InverseTransform
{
get { return _inverseTransform; }
}
public Vector2 Pos;
// Constructor
public Camera()
{
_zoom = 2.4f;
Pos = new Vector2(0, 0);
}
// Update
public void Update(GameTime gameTime)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(Pos.X, Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}
}
This is the camera class I made for handling the screen, it's main purpose is to resize the screen, more precisely to zoom in and out whenever I want to change my screen, (Title screen, Playing screen, Game over, and like that.)
Moving the camera is quite simple with keys, like this.
if (keyState.IsKeyDown(Keys.D))
Cam.Pos.X -= 20;
if (keyState.IsKeyDown(Keys.A))
Cam.Pos.X += 20;
if (keyState.IsKeyDown(Keys.S))
Cam.Pos.Y -= 20;
if (keyState.IsKeyDown(Keys.W))
Cam.Pos.Y += 20;
And ofc. the drawing method witch apply the camera.
spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, null, null, null, null, Cam.Transform);
Here comes the part when I stop, so what I want to do is make something like 2 2D rooms. By Room I mean the place where I usually place objects. like this "Vector2(74, 63)" So I want to create a place where I could draw items that would stick to the screen and wouldn't move, and make the screen bounds that would make my algorithm to work, witch will be always on screen and as an addition it will check if one of the borders of the screen "room" reaches the certain coordinates of the map "room".
I think that the reason for that would be obvious because I don't want player to move camera outside the map when he reaches the wall, otherwise the player would already see a part of the next map where he will be transformed.
The reason of drawing both maps next to each other is again to reduce the loading time so player wouldn't have to wait for playing the next map.
Alright, so I've run into more troubles than I expected so I'll add extra information and will start with the player class:
// Main
public class Player
{
public Texture2D AureliusTexture;
public Vector2 position;
public Vector2 velocity;
public Vector2 PosForTheCam; // Variable that holds value for moving the camera
protected Vector2 dimensions;
protected CollisionPath attachedPath;
const float GRAVITY = 18.0f;
const float WALK_VELOCITY = 120f;
const float JUMP_VELOCITY = -425.0f;
// Constructor
public Player()
{
dimensions = new Vector2(23, 46);
position = new Vector2(50, 770);
}
public void Update(float deltaSeconds, List<CollisionPath> collisionPaths)
{
#region Input handling
KeyboardState keyState = Keyboard.GetState();
if (keyState.IsKeyDown(Keys.Left))
{
velocity.X = -WALK_VELOCITY;
}
else if (keyState.IsKeyDown(Keys.Right))
{
velocity.X = WALK_VELOCITY;
}
else
{
velocity.X = 0;
}
if (attachedPath != null && keyState.IsKeyDown(Keys.Space))
{
velocity.Y = JUMP_VELOCITY;
attachedPath = null;
}
velocity.Y += GRAVITY;
#endregion
#region Region of handling the camera based on Player
PosForTheCam.X = velocity.X;
#endregion
#region Collision checking
if (velocity.Y >= 0)
{
if (attachedPath != null)
{
position.X += velocity.X * deltaSeconds;
position.Y = attachedPath.InterpolateY(position.X) - dimensions.Y / 2;
velocity.Y = 0;
if (position.X < attachedPath.MinimumX || position.X > attachedPath.MaximumX)
{
attachedPath = null;
}
}
else
{
Vector2 footPosition = position + new Vector2(0, dimensions.Y / 2);
Vector2 expectedFootPosition = footPosition + velocity * deltaSeconds;
CollisionPath landablePath = null;
float landablePosition = float.MaxValue;
foreach (CollisionPath path in collisionPaths)
{
if (expectedFootPosition.X >= path.MinimumX && expectedFootPosition.X <= path.MaximumX)
{
float pathOldY = path.InterpolateY(footPosition.X);
float pathNewY = path.InterpolateY(expectedFootPosition.X);
if (footPosition.Y <= pathOldY && expectedFootPosition.Y >= pathNewY && pathNewY < landablePosition)
{
landablePath = path;
landablePosition = pathNewY;
}
}
}
if (landablePath != null)
{
velocity.Y = 0;
footPosition.Y = landablePosition;
attachedPath = landablePath;
position.X += velocity.X * deltaSeconds;
position.Y = footPosition.Y - dimensions.Y / 2;
}
else
{
position = position + velocity * deltaSeconds;
}
}
}
else
{
position += velocity * deltaSeconds;
attachedPath = null;
}
#endregion
}
}
So I state it clear that I asked my friend to do most of it because I wanted to handle the gravity and the slopes so we made it work similar like in Unity. And he happened to know how to do that.
And so I'll add the Update method that handles the camera from the Main Class.
MM.Update(gameTime); // Map Managher update function for map handling
Cam.Update(gameTime); // Camera update
Cam.Zoom = 2.4f; // Sets the zoom level for the title screen
// Takes the start position for camera in map and then turns off the update
// so the camera position can be changed. Else it would just keep an infinite
// loop and we couldn't change the camera.
if (StartInNewRoom)
{
Cam.Pos = MM.CameraPosition; // Applys the camera position value from the map manager class
StartInNewRoom = false;
}
I am unsure how to handle the camera, like I used your method and the result often ended up that camera moves by itself or it doesn't move at all.
If you don't want objects to move with the camera like a HUD you need a second spriteBatch.Begin() without your camera matrix which you draw after your actual scene.
To make the camera not move out of the map you could use some kind of collision detection. Just calculate the right border of your camera. It depends where the origin of your camera is.
Is your camera matrix working like this? Because the position should be negative or it will move in the wrong direction.
This is how mine looks like.
return Matrix.CreateTranslation(new Vector3(-camera.position.X, -camera.position.Y, 0)) *
Matrix.CreateRotationZ(Rotation) * Matrix.CreateScale(Zoom) *
Matrix.CreateTranslation(new Vector3(Viewport.Width * 0.5f, Viewport.Height * 0.5f, 0));
Viewport.Width/Height * 0.5 centers you camera.
You can also apply this behind your Pos.X/Y
To Camera follows player
public void Update(Player player)
{
//Clamp zoom value
_zoom = MathHelper.Clamp(_zoom, 0.0f, 10.0f);
//Create view matrix
_transform = Matrix.CreateScale(new Vector3(_zoom, _zoom, 1)) *
Matrix.CreateTranslation(player.Pos.X, player.Pos.Y, 0);
//Update inverse matrix
_inverseTransform = Matrix.Invert(_transform);
}

Libgdx InputListener touchUp

I've added InputListener to my actor and now I want to check if touchUp event is inside the actor.
Simple example: I'm starting draging mouse inside my actor and i'm finishing outside my actor.
I though that touchUp event will start only if mouse is inside my actor but it also start outside my actor (when touchDown event start inside my actor).
How to check if touchUp event is inside my actor only?
I see two solutions here:
To use some flag to check if the pointer is inside the actor and handle it with exit method:
image.addListener(new InputListener(){
boolean touched = false;
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button)
{
touched = true;
System.out.println("TOUCH DOWN");
return true;
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
if(touched)
{
touched = false;
System.out.println("TOUCH UP");
}
}
#Override
public void exit(InputEvent event, float x, float y, int pointer, Actor toActor)
{
touched = false;
}
});
To check if pointer is inside the actor inside touchUp
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button)
{
Stage stage = event.getTarget().getStage();
Vector2 mouse = stage.screenToStageCoordinates( new Vector2(Gdx.input.getX(), Gdx.input.getY()) );
if(stage.hit(mouse.x, mouse.y, true) == event.getTarget())
{
System.out.println("TOUCH UP");
}
}
Both solutions need some extra code but both should be working fine.
Sorry miss read your question noticed when you changed it.
Still, I would add a listener and simply check coordinates of actor. The x and y given with a clicklistener just return local coordinates of the actor so a simple check vs width and height is enough.
ClickListener cl = new ClickListener()
{
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
if (x > 0 && y > 0 && x < getWidth() && y < getHeight())
{
System.out.println("Released within actor");
}
}
};
actor.addListener(cl);

cameras in libgdx and box2d

I develop 2D game using libGDX and box2D. Camera is following with body.I want to scroll background (png 3200X48) too. Now the camera works fine in box2D world but background is not moving. I searched and tried many solutions but didn't help. What is the best solution for it? Maybe makes two cameras one for physics world and second for libgdx scene? Has someone got the similar problem? Thanks for help.
Here are a parts of my code
float w = 320;
float h = 480;
#Override
public void show() {
camera = new OrthographicCamera();
camera.setToOrtho(false, w/2, h/2);
world = new World(new Vector2(0, -20), true);
box2DDebugRenderer = new Box2DDebugRenderer();
background = new Texture(Gdx.files.internal("gfx/forklift/background.png"));
bg = new Sprite(background);
......}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1f, 1f, 1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
moveCamera(dynamicBody.getPosition().x);
moveBody();
batch.begin();
batch.draw(background, 0, 0, 3200, 480);
batch.end();
Gdx.app.log("", ""+dynamicBody.getPosition());
world.step(1/60f, 6, 2);
box2DDebugRenderer.render(world, camera.combined);}
public void moveCamera(float x){
camera.position.set(x, dynamicBody.getPosition().y, 0);
camera.update();
}
#Override
public void resize(int w, int h) {
camera = new OrthographicCamera(w, h);
camera.translate(h/2, w/2, 0);
super.resize(w, h);
}
use batch.setProjectionmatrix(camera.combined)
before batch.begin()

GeoTools DirectLayer Class Issues

I'm working with DirectLayer to try and create a tool that I can use to draw boxes on a map that will be used to highlight features.
I'm looking for a way to make features that will resize and move with zoom and pan operations and not cause issues with other layers when they are created.
Right now the biggest issue is that when the DirectLayer draw function is called other layers in my map will render incorrectly or not render at all.
public class drawer extends DirectLayer{
private int x,y,w,h;
private Point center;
private boolean oval;
private Color main;
private Color shade;
private float diameter;
/**
* Empty constructor because there should be no persistent information to this class
* Defaults to a circle with diameter 20 and blue outline and shade
*/
public drawer()
{
diameter = 20;
shade = Color.BLUE;
main = Color.BLUE;
}
/**
* The actual drawing function, should not call this from the client, but has to be public to extend DirectLayer
*/
#Override
public void draw(Graphics2D graphics, MapContent map, MapViewport vp) {
graphics.setColor(main);
if(center == null)
{
if(!oval)
{
graphics.drawRect(x, y, w,h);
graphics.setColor(shade);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float) .5));
graphics.fillRect(x, y, w,h);
}
else
{
graphics.drawOval(x, y, w, h);
graphics.setColor(shade);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float) .5));
graphics.fillOval(x, y, w,h);
}
}
else
{
Shape theCircle = new Ellipse2D.Double(center.x - diameter/2, center.y - diameter/2, diameter, diameter);
graphics.draw(theCircle);
graphics.setColor(shade);
graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,(float) .5));
graphics.fill(theCircle);
}
map.addLayer(this);
}
/**
* Draws a circle on the given map using the given graphics option
* #param graphics - graphics object from parentComponent
* #param center - center of circle (diameter is set using setDiameter)
* #param map - map to draw circle on
*/
public void drawCircle(Graphics2D graphics,Point center, MapContent map)
{
this.center = center;
draw(graphics,map,map.getViewport());
}
/**
* Draws a rectangle on the map with the given x and y coordinates and the given width and height on the Map
* #param graphics - graphics object from the parentcomponent
* #param x - Upper left x coordinate
* #param y - upper left y coordinate
* #param w - width
* #param h - height
* #param map - Map to draw on
*/
public void drawRectangle(Graphics2D graphics,int x, int y, int w, int h, MapContent map)
{
center = null;
oval = false;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
draw(graphics,map,map.getViewport());
}
/**
* Draws an oval on the map with the given x and y coordinates and the given width and height on the Map
* #param graphics - graphics object from the parentcomponent
* #param x - Upper left x coordinate
* #param y - upper left y coordinate
* #param w - width
* #param h - height
* #param map - Map to draw on
*/
public void drawOval(Graphics2D graphics,int x, int y, int w, int h, MapContent map)
{
oval = true;
center = null;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
draw(graphics,map,map.getViewport());
}
/**
* used to set outline color for shapes
* #param color - color to outline
*/
public void setGraphicsColor(Color color)
{
main = color;
}
/**
* Used to set color of shading
* #param color - color to shade
*/
public void setShaderColor(Color color)
{
shade = color;
}
/**
* Sets diameter of circles that are drawn using the drawCircle Method
* #param d - Diameter
*/
public void setDiameter(float d)
{
diameter = d;
}
/**
* removes all drawn shapes from the given map
* #param map - the map to remove shapes from
*/
public static void removeDrawings(MapContent map)
{
for(Layer l : map.layers())
{
if(l instanceof drawer)
{
l.preDispose();
map.removeLayer(l);
}
}
}
#Override
public ReferencedEnvelope getBounds() {
// TODO Auto-generated method stub
return null;
}
}
The issue here is that when I call DrawREctangle, when the rectangle is drawn on the screen other layers render incorrectly on the repaint. Also the rectangle does not zoom or pan with the screen as it has no featuresource.
I'm wondering what can I do about these two issues? Is DirectLayer actually what I am looking for or should I be trying to make a Drawable version of FeatureLayer, which just feels like the wrong way to go about this.