How to work a method dispite it is not called in libgdx project - libgdx

I am analizing a game code.
A method which name is act() is running despite it is not called.
Its like, there is a secret method somwere but i cant see it.
i follow source of method.i find so code.The some part of codes are as below.
I think parent class send method to child class when a new object execuded.
Is there a name of this approach.
This is LevelScreen class.It does not have act() method but act() method is working.I can see the changes when i change the parametres in act() method in Plane class.
class LevelScreen : BaseScreen(){
plane = Plane(100f, 500f, mainStage)}
This is Plane class which has act() method.
class Plane(x: Float, y: Float, s: Stage) : BaseActor(x, y, s){
override fun act(dt: Float) {
super.act(dt)
// simulate force of gravity
setAcceleration(800f)
accelerateAtAngle(270f)
applyPhysics(dt)
................
.............
}
This is parent class of Plane class
open class BaseActor(x: Float, y: Float, s: Stage) : Group(){
override fun act(dt: Float) {
super.act(dt)
if (!animationPaused)
elapsedTime += dt
}
}
This is a class which is in framework of libGDX
public class Group extends Actor implements Cullable{
public void act (float delta) {
super.act(delta);
Actor[] actors = children.begin();
for (int i = 0, n = children.size; i < n; i++)
actors[i].act(delta);
children.end();
}
}

Look at the main project file where the Stage is created. The main file will have a method called render and this is where the act method is called for the first time. All Actors are added to the Stage and then inside of the render method the act method is called on the Stage, which then calls the act method on all of the Actors that it contains.
This is the section you are looking for (taken from one of my projects):
#Override
public void render (){
Gdx.gl.glClearColor(0.6f, 0.64f, 0.7f, 1.0f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(Gdx.graphics.getRawDeltaTime()); // START OF ACT METHODS
stage.draw();
}

Related

Check collision of 2 objects in libgdx

I am making a game in libgdx, where you shoot aliens with bullets. I have 2 ArrayLists of objects and would like to check if any of objects in bulletArrayList is colliding with any object from alienArrayList. What is the best way to do that? I was thinking of contactListener.
In the screen class I am generating objects like this:
public class PlayScreen implements Screen, InputProcessor,ContactListener {
public ArrayList<Alien> alienArrayList = new ArrayList<Alien>();
public ArrayList<Bullet> bulletArrayList = new ArrayList<Bullet>();
public void generateAlien() {
alien = new Alien();
alienArrayList.add(alien);
}
public void shootBullet(float x, float y) {
//send x,y moving coordiantes
bullet = new Bullet(x,y);
bulletArrayList.add(bullet);
}
}
In object class I have Rectangle box which i am moving like this:
public class Alien {
public Alien() {
bound = new Rectangle( x, y, alienRegion.getRegionWidth(), alienRegion.getRegionHeight());
}
public void update(float delta) {
bound.y -= speed * delta;
}
public void render(SpriteBatch batch, float delta) {
update(delta);
elapsedTime += Gdx.graphics.getDeltaTime();
alienRegion = (TextureRegion) alien.getKeyFrame(elapsedTime, true);
batch.draw(alienRegion, getBound().x, getBound().y);
}
}
Because you are using Rectangles in your Alien class, we can use a class called Intersector which has static methods to check for collision detection.
for(Alien alien1: alienArrayList) {
for(Alien alien2 : bulletArrayList) {
if(Intersector.overlaps(alien1.rect, alien2.rect)) {
// Collision code
}
}
}
First, we iterate through the two lists using a nested special for loop. Then we pass two Rectangles to the Intersector.overlaps(rect1, rect2). This is a static method defined in the Intersector class which will return true if the rectangles are overlapping.
Also, this code can go straight into your render method.
This code is not the most optimized because it will check 2 rects twice however, I will leave the optimization to you.
I hope that this answer was helpful and if you have any further questions please feel free to post a comment below.

Actor in Stage Does Not Update the MoveTo XY Location

I am creating a game wherein an apple is being shot with an arrow. The apple's location is the XY location of the user input and the arrow actor has to move to that location using the code actor.moveto. The problem is the arrow only moves only once to the user input's direction. I know that the moveTo action of the actor is updated many times per second when I called stageArrow.act in the update method so I am wondering why the arrow only moves once. Here's my code:
appleclass.java
public class AppleClass implements Screen {
Arrow arrow;
private final MainApp app;
public Image ShotImage;
public AppleClass(final MainApp app){
this.app = app;
this.stageApple = new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
this.stageArrow =new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
arrow = new ArrowClass(app);
}
#Override
public void show() {
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(stageApple);
inputMultiplexer.addProcessor(stageArrow);
Gdx.input.setInputProcessor(inputMultiplexer);
arrow();
}
public void arrow(){
arrow.isTouchable();
stageArrow.addActor(arrow);
arrow.addAction((moveTo(Gdx.input.getX(),Gdx.input.getY(),0.3f))); //===> only executes once.
arrow.addListener(new InputListener(){
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
if (Gdx.input.isTouched()){
ShotImage.setVisible(true);
}
}
});}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
update(delta);
}
public void update(float deltaTime){
stageApple.draw();
stageArrow.draw();
stageApple.act(deltaTime);
stageArrow.act(deltaTime);
}
ArrowClass.java
public class ArrowClass extends Actor {
MainApp app;
AppleClass appleClass;
public Texture arrowTexture;
public ArrowClass(final MainApp app){
this.app = app;
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
final float delta = Gdx.graphics.getDeltaTime();
this.act(delta);
app.batch.begin();
app.batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
app.batch.end();
}
}
Any help will be highly appreciated. Thanks.
I think the problem is because you are calling this.act(delta) in your ArrowClass' draw method. When you call Stage#act(), it will call the act method on all of its actors for you. Since you're calling it once when you draw and again when you update the stage, it's moving at twice the normal speed and that could be causing it to reach its destination prematurely.
A few other comments about your code, if I may:
First, you probably don't want two separate stages- unless you're using Scene2D.UI, you would normally have a single stage with Arrow and Apple added to it as actors.
Second, when you override Actor#draw(), you should use the batch it passes you to do the rendering instead of using the one from app. You also don't want to call begin() and end() inside your draw method- these are 'expensive' and you only want to call them once per frame. However, if you just use the batch that is passed to draw(), the Stage class will handle beginning and ending for you and you won't need to call them explicitly.
Third, you actually don't need to call super.draw(batch, parentAlpha) because it's an empty method in the Actor class.
Thus, your class could be simplified to the following:
public class ArrowClass extends Actor {
AppleClass appleClass; // You never set this; you may not need it
Texture arrowTexture;
public ArrowClass(MainApp app, arrowWidth, arrowHeight) {
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
}
}

How to apply a method only to a certain sub class of Actor in Stage

My game has a class named Enemy which extends Actor. Additionally, I have an EnemyAffector class which has methods that affect Enemies, roughly like this:
class EnemyAffector {
public void affect(Enemy enemy) { ... }
}
In my Stage, in the act method, I want to iterate over all Enemies and apply an EnemyAffector to them. The obvious way is by casting:
#Override
public void act() {
super.act();
for (Actor actor: getActors()) {
if (actor instanceof Enemy) {
enemyAffector.affect((Enemy)actor);
}
}
...
}
However, legend has it that using instanceof should be avoided. So, I considered keeping an additional Array to which I will add Enemies as they are added to the Stage, i.e., by overloading my Stage with another addActor method:
public void addActor(EnemyProjectile pEnemyProjectile) { // add to Enemy Array }
So now my act method looks like this:
#Override
public void act() {
super.act();
for (Enemy enemy: enemyArray) {
enemyAffector.affect(enemy);
}
...
}
Yay! No instanceof!
However, the problem with this solution is that I will always need to synchronize between the Enemy Array, and the standard Actor Array because Enemies in the Enemy Array may have been removed from the Stage.
My question is, is there a different, cleaner, approach which can I take here?
You could either use the UserObject that you can add to an actor:
public enum ActorType
{
PLAYER, ENEMY, ETC;
}
//...
Enemy enemy = new Enemy();
// Or set this in the constructor
enemy.setUserObject(ActorType.ENEMY);
for (Actor actor : actors)
{
if (actor.getUserObject() == ActorType.ENEMY)
{
// Do stuff...
}
}
Or put your two arrays in an extra class and add methods for adding/removing:
public class ActorManager
{
private Array<Actor> actors = new Array<>();
private Array<Enemy> enemies = new Array<>();
public void add(Actor actor)
{
actors.add(actor);
}
public void add(Enemy enemy)
{
actors.add(enemy);
enemies.add(enemy);
}
public void remove(Actor actor)
{
actors.removeValue(actor, true);
}
public void remove(Enemy enemy)
{
actors.removeValue(enemy, true);
enemies.removeValue(enemy, true);
}
// To make sure our backing arrays are not modified:
public Array<Actor> getAll()
{
return new Array<>(actors);
}
public Array<Actor> getEnemies()
{
return new Array<>(enemies);
}
}
I quickly encountered a similar situation with LibGDX with both the Actor and Stage class. I created my own sub-class extending Actor, which I was going to use as the "base Actor" Object for all my Actors.
That way, you can set up methods which will be called by all your Actors on certain situations.
class MyStage extends Stage
{
public void addActor(MyActor pEnemyProjectile) { // call onAdd }
//override other methods as necessary,
//possibly getActors() to return Actors as MyActors, etc
}
class MyActor extends Actor
{
public void update(double delta)
{
//I find it easiest to have "removal" code happen in the Actor's update method, then I can call onRemove()
//This could happen by finding death conditions or just checking a "isDead" boolean.
}
public void onAdd()
{
//can set up a default behavior, or just override on other subclasses
}
public void onRemove()
{
//call for every Actor that gets removed - can extend and remove Enemies from an Enemy list if desired
}
//maybe it would be better to check if the Object can be Affected here?
//rather than keeping and maintaining a separate list
public boolean isAffected()
{
return false; //return true by Enemies
}
}
class Enemy extends MyActor
{
//implement onRemove, onAdd, etc..
}
If it works better, MyActor could also be created as an interface instead - and then you could just as easily create sub-classes for Label or other LibGdx classes which inherit from Actor.
I personally chose to make it a sub-class, just because I could create helper-methods which were easier to type and call - such as my "movement" and "rotation" code, which don't use the Action classes which LibGdx comes with.
The easiest and in my opinion generating least lines of code is to use UserObject Actor field like:
Actor actor = new Actor(); //or its children ofc
actor.setUserObject("enemy");
//...
if( actor.getUserObject().equals("enemy") )
{
//yup this is enemy
}
Of course it is not the best solution due to OOP and can be not very flexible in some cases but to be honest in a case like this handling additional arrays etc etc only complicates things.
Notice that UserObject is object type so if you want to push there something that Java cannot cast itself you will have to cast it on your own.
However if you would want to be super ok here's another more elegant solution:
You are overriding the Actor class with your own MyActor class with some customAction() method which do nothing. You will be inheriting from this class not from Actor now
In every child class the method do nothing but in your Enemy class you are implementing the funcionality
In a loop you are casting to (MyActor) and calling customAction method
for (Actor actor: getActors()) {
((MyActor)actor).customAction();
}
The customAction method has a logic from EnemyEffector
This would generate some problems if you are inheriting classes that inherits from Actor (like Label class) and also will be a problem if the EnemyEffector logic is using data that Actor instance should not know because they are global for example and shouldn't be redundant (of course you can also pass the information as a parameter of customAction method)

How to use Libgdx gesture detector

I'm new at Libgdx and one aspect that blocks me to continue with my Libgdx learning is the fact that a I don't know how to use the GestureListener. It's seems there's a user with the same doubt if you see in this link LibGdx: Utilizing a Gesture Listener, but it didn't help me much. So my question is: how do I use my own GestureListener class to process my player moviments? I wanna use the pan function to make it jump, but I don't know how to put my player object inside the method. If you see my gesture detector class:
public class GestureHandler implements GestureListener {
// Main Game class
private ClimbUp mainGame;
public GestureHandler(ClimbUp game) {
this.mainGame = game;
}
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
#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;
}
...
Then I followed what they told the user what to do: in the main class I passed the fallowing instruction:
Gdx.input.setInputProcessor(new GestureDetector(new GestureHandler(this)));
Now in my splash screen, I don't know how to use. How to make my GestureHandler object works for all project? I'll be very grateful with an answer!
So, you have some you class which need GestureListener "services" - you want to be informed when some gesture event happens and you want to have information of gesture properties.
Then, as you did, make your class implement GestureListener interface.
After that your IDE (Eclipse or Android Studio or something else) will complain that you didn't implemented all GestureListener methods, but it can also do that for you. If you (in eclipse) hover the error in the code IDE will offer you to create missing methods.
I would say you are at about that step. But now your methods have to do something useful. Like, if you want to do something when player taps the screen add your code inside that method. Do something there. Inside GestureListener methods you have some info available, as method parameters like x & y coordinates, button (left, middle, right) and something like that.
So, when you call that setInputProcessor with object created in you class that implemented G.L. interface libGDX will know to call your methods when some event occurs.
Every method IDE generated has that "todo" mark - that's where you have to put your code instead. The code that will handle that event, move your space ship, fire the bullet or what ever. You don't have to do something for every event, but only for those you are interested in. You can leave other empty, but your class must have them.
Here is some example:
// importing interface
import com.badlogic.gdx.input.GestureDetector.GestureListener;
// defining my class that implements that interface
public class TouchController implements GestureListener{
// constructor - just storing objects passed to it.
public TouchController(Playground pg, Army army, Hud hud){
super();
this.pg = pg;
this.army = army;
this.hud = hud;
initialZoom = pg.zoom;
}
// Adding some action to touchDown method - I'm just calling my hud object's method and passing coords I get
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
hud.pressedAt(x, pg.camera.viewportHeight-y); // opposite Y axis
// TODO Auto-generated method stub
return false;
}
// Similar thing. I unproject coords I get.
#Override
public boolean tap(float x, float y, int count, int button) {
if (!hud.buttonPressed){
Vector3 touchPos = new Vector3();
touchPos.set(x, y, 0);
pg.camera.unproject(touchPos);
army.add(touchPos.x, touchPos.y, SoldierSide.RED);
}else hud.released();
return false;
}
// Again similar stuff, but this pan methods is getting also delta value (difference from last reading x and y values) which can be useful
#Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
if (hud.aimDrag) hud.aimDragged((int)deltaX, (int)deltaY);
else if (hud.sliderDrag) hud.sliderDragged((int)deltaX, (int)deltaY);
else if (!hud.buttonPressed) pg.panned((int)deltaX, (int)deltaY);
return false;
}
...

LibGdx Stage/Actor InputListener (Appropriate Area for InputListener)

I have a class Bubble that extends Actor.
public Bubble(MyGdxGame game,Texture texture){
this.game=game;
setPosition(0,0);
setSize(32,32);
gameObject=new GameObject("","bubble");
direction=new MovementDirection();
sprite=new Sprite(texture);
setTouchable(Touchable.enabled);
setWidth(sprite.getWidth());
setHeight(sprite.getHeight());
setBounds(0,0,sprite.getWidth(),sprite.getHeight());
addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchdown");
return true; // must return true for touchUp event to occur
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchup");
}
});
}
This is in a class that implements Screen
public void show() {
// TODO Auto-generated method stub
super.show();
//2 bubbles test
gameStage=new Stage(MyGdxGame.WIDTH,MyGdxGame.HEIGHT,true);
Gdx.input.setInputProcessor(gameStage);
for (int i=0; i<10; i++){
Bubble b=new Bubble(game,Assets.bubbleTexture);
b.randomize();
gameStage.addActor(b);
}
//if (bubbleList==null)
// createBubbles();
}
Am I going about this the wrong way by adding the listener # the bubble level? (It seems creating an InputListener for every bubble I spawn is a little crazy).
According to : http://libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html
Actor has a touchUp() and touchDown event - but complains when i try to override them (which lead me to believe they dont exist). Overriding these I feel would be a better approach
The docs you linked to are outdated.
Those methods were deprecated and removed in favor of using InputListeners.
In your example if you want to use the same InputListener instance for all instances of your Actor class (Bubble) then you can just implement the InputListener to refer to the Actor class instance using inputEvent.getRelatedActor() and then instantiate one such InputListener as a static member of Bubble and pass it in the constructor to addListener.
class Bubble extends Actor{
private static InputListener bubbleListener= new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Bubble b = (Bubble) event.getRelatedActor();
b.doSomething();
...
return true; //or false
}
}
public Bubble(){
addListener(bubbleListener);
...
}
...
}