I have
Main Test Class creating a Stage, Adding an Actor to the stage and setting the Inputprocessor to the stage
extended Group Class with several Actors added. In the Constructor of the Group I have added an InputListener.
The InputListener is not fired . Can someone tell why not and how to do ?
public class Test extends ApplicationAdapter implements ApplicationListener {
public void create() {
stage = new Stage(new ScreenViewport());
specialScene = new SpecialScene();
stage.addActor(specialScene);
Gdx.input.setInputProcessor(stage);
}
}
public class SpecialScene extends com.badlogic.gdx.scenes.scene2d.Group {
public SpecialScene {
<add some actors ...>
addListener(specialListener);
}
private static InputListener specialListener = new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true; //or false
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
}
#Override
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor) {
super.enter(event, x, y, pointer, fromActor);
}
};
}
* UPDATE *
I found the problem. The Listener did not find any region of my Actors.
I have to set explicitely the Region with setBounds().
My Problem is solved, but I am still confused. Why do I have to set the bounds myself. I will forget this with every Actor in the future I am sure, because it is unlogical to me. Is this the way I have to, or do I understand the concept wrong ?
Group is a skeleton class that can be used to develop your own functionality, so it does not presume anything, even the way its child actors contribute to its bounds. (For example, you might have some actors that you don't want to contribute because they are a visual flourish, like particles.) You can extend Group to create your own base class to fit your needs.
So why doesn't LibGDX already include a class like that? In LibGDX, Stage is used primarily for the UI system. Although it was designed to be extensible to all kinds of purposes, it only includes a framework for you to do that, unless you are using the fully baked UI implementation that is based on it. That UI implementation does include a subclass of Group called WidgetGroup, which does what you'd expect with the bounds.
IIRC, the author of Stage wrote a blog post a few years ago on libgdx.com discussing how he tried using Stage for the gameplay of a simple game jam game, and basically concluded that it caused his game to be more convoluted, or at least more time-consuming to code.
I have personally used it for a turn-based game jam game, and it was good for that. I used the Actions system to have nice animated transitions of the game pieces. But I think it would make a real-time game more convoluted than creating your own organization structure that is tailored to your particular game. If you are creating a more complicated game, you might check out the Ashley plugin for LibGDX.
In either case, you definitely should use it for GUI stuff because that is all fully implemented and a huge time-saver.
Related
I want to draw A Sprite when touchDown event occurs and disposed when touchUp occurs. I tried following code:
public class Connect4Screen implements Screen {
SpriteBatch batch;
Connect4Screen(){
batch = new SpriteBatch();
camera = new OrthographicCamera(30, 20);
camera.update();
batch.setProjectionMatrix(camera.combined);
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
drawChip();
}
}
}
public void drawChip(){
batch.begin();
batch.draw(new Texture("Images/yellow.png"), 0, 5, 1.4f,1.4f);
batch.end();
}
}
I scrapped off unnecessary code.
What is wrong here?
If you simply draw something as a one-time event, it will only be visible for 1/60 of a second. Games redraw the screen over and over in a loop, so to cause something to appear and stay on the screen, you need to set a member Boolean that indicates it should be drawn, and then in your render method you draw that item if the Boolean is true.
That's a very simplified explanation. Games tend to have many different items to draw that come and go, and keeping separate Booleans for each of them is impractical. So typically you'll have a list of items to draw, and you can add and remove items from the list based on events in the game. In your render method, you would loop through the list and draw everything in it.
Also, you must not create a new Texture without keeping a member reference to it so you can dispose() it later. Textures use native memory on the GPU and must be disposed of or they will leak memory. In LibGDX, any object that can leak memory implements Disposable, and must be disposed before you lose track of the reference.
I am making a program using the amazing libGDX+scene2d API and I structured it as follows:
I have a single MyGame instance, holding a single PolygonSpriteBatch instance.
There is an abstract MyScreen class, holding a MyStage class (see below)
Then there are lots of different screen classes that inherit from MyScreen, and instantiate each other at will.
(in all cases, removing the "My" gives you the name of the respective library class that it extends)
This model worked fine, until I encountered some problems to perform actions between screens using the Action system. I decided then that it would be a good idea to have a single OmnipresentActor belonging to MyGame that, as the name says, is present in every scene. So I modified MyStage to look more or less like this:
public class MyStage extends Stage {
public MyStage(MyGame g) {
super(new FitViewport(MyGame.WIDTH, MyGame.HEIGHT), g.batch);
addActor(game.omnipresentInvisibleActor);
}
#Override
public void clear() {
unfocusAll();
getRoot().clearActions();
getRoot().clearListeners();
removeActorsButNotListenersNorActions();
}
public void removeActorsButNotListenersNorActions() {
for (Actor a : getActors()) if (a.getClass()!= OmnipresentInvisibleActor.class) a.remove();
}
It followed a painful debugging phase, until I found out the following:
public PresentationScreen(MyGame g) {
// super() call and other irrelevant/already debugged code
System.out.println("PRINT_BEFORE: "+ stage.getActors().toString()); // OmnipresentActor is there
mainMenuScreen = new MainMenuScreen(game);
System.out.println("PRINT_AFTER: "+ stage.getActors().toString()); // OmnipresentActor is not there anymore, but was added to the mainMenuScreen
the "PRINT_BEFORE" statement shows that the stage holds the omnipresentActor. In "PRINT_AFTER" it isn't there anymore, whereas mainMenuScreen is indeed holding it. So my question, now more precise:
does scene2d prevent this to happen, or am I doing something wrong here?
Answers much appreciated! Cheers
An actor can only be a member of one stage: Thanks to #Tenfour04 for confirming that. The explanation is quite clear after doing a little research:
Stage.addActor() looks like this:
(here the github code of Stage.java)
/** Adds an actor to the root of the stage.
* #see Group#addActor(Actor) */
public void addActor (Actor actor) {
root.addActor(actor);
}
whereas root is simply initialized as a group in the Stage constructor: root = new Group();.
And Group.addActor() looks like this:
(here the github code of Group.java)
/** Adds an actor as a child of this group. The actor is first removed from its parent group, if any. */
public void addActor (Actor actor) {
if (actor.parent != null) actor.parent.removeActor(actor, false);
children.add(actor);
actor.setParent(this);
actor.setStage(getStage());
childrenChanged();
}
So in the tree first lines is the answer: when creating the new stage, if the actor to add already has a parent, it is removed from its current parent. So, There are two possible solutions to the problem I enounced:
SOLUTION 1: Override addActor removing the if statement, or any other alteration of the library, which I'm not sure if it would work. I rather think this could be very problematic, for instance it could prevent the stages from disposing correctly
SOLUTION 2: Change the design so you don't need an omnipresent actor, nor changing/reimplementing the libraries. For the moment this is what I've done based on this answer, it isn't very clean but it works so far:
1) In the MyScreen class added the following fields:
private boolean watchingTemp;
private Actor watchActorTemp;
private Action actionTemp;
2) Then added this method:
public void addActionOnStageAfterActorEndsHisActions(Actor actor, Action action) {
watchActorTemp = actor;
actionTemp = action;
watchingTemp = true;
}
3) then in the render method, I added the following:
if (watchingTemp && !watchActorTemp.hasActions()) {
watchingTemp = false;
stage.addAction(actionTemp);
}
4) finally, when wishing to perform an action at a screen transition (and eventually disposing the first one), you can do something like this: I use something similar when clicking on a door between screens
public void movePlayerTHENgotoNewScreen(float xPos, float yPos, whatever else...) {
game.player.walkToAnyPoint(xPos, yPos);
yourFavoriteScreen.addActionOnStageAfterActorEndsHisActions(game.player, gotoNewScreen(wathever else...));
}
Hope it helps!
I am trying to fade an Actor out using the Action FadeOut. However, I've discovered that the no actions work at all for my objects. The hierarchy of my classes are like this:
Actor -> MoveableObject -> Knight
Stage -> KnightGroup (Group) -> Knight
Actions for my Knight actors do not work at all. However, actions for my KnightGroup group works. Here is the code for my Knight:
public class Knight extends Players {
public Knight() {
setWidth(96);
setHeight(96);
setPosition(100, 90);
//Doesn't work
AlphaAction action = new AlphaAction();
action.setAlpha(0f);
action.setDuration(1f);
addAction(action);
//Doesn't work
addAction(fadeOut(1f));
addAction(Actions.scaleBy(1f, 1f));
}
#Override
public void act(float delta){
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.setColor(getColor().r, getColor().g, getColor().b, getColor().a);
batch.draw(animation[currentState], getX(), getY(), getWidth(), getHeight());
}
}
I can't for the life of me figure out what the problem is. Actions in MoveableObject (the parent of Knight) doesn't work either. My best guess is that wrapping actors in a Group will render the actions of those actors invalid. The KnightGroup is a pretty crucial part of my code though and I would have to do a lot of refactoring to take it out. Can someone else shed some light on this issue?
In the Actor class the method act(float delta) calls act(delta) for all registered Actions of this Actor. So you have to make sure, that you call super.act(delta) in every subclass of Actor, so that the act(delta) method in Actor gets called.
I'm trying to create something like the following using c++:
I have a class called particle which will store the position, velocity of each particle. Additionally, a member function will update the particle's position using velocity data.
I'm also trying to write a function that will detect a collision between particles and the boundaries of the box. To do so, this function needs access to each particle's position and velocity. Thus, the function needs to take an entire array of particles as a parameter. However, this function can't exist as a member function of the particle class, because then it won't have access to all the particles.
Question: Where do I include the collision detection function, such that it is an extensible part of the particle class?
I thought about just writing this function inside my main.cpp file, but I haven't the slightest clue whether this adheres to the OOP guidelines. Ideally there might be other functions that also act on an array of particles.
Probably what you want is some sort of "ParticleContainer" object, that holds the array of particles, and performs operations on the particle system as a whole.
(That's also where you would put the code that runs down the array and calls the "Draw" functions.)
I guess that good idea will be to declare a detection function as a friend of class particle: it will have access to all members in class. Then you can fire this function in loop inside of some kind of manager function that will calculate the collision to all particles in array. In this
void CollisionMgr(particleClass *ParticleArrayPtr, int NumOfParticles)
{
while(NumOfParticles)
{
CollisionOfParticle(*ParticleArrayPtr, NumOfParticles);
NumOfParticles--;
}
}
I tend to use a pattern along these lines: Keep all the model state in a single class called Modelor Environment; have a separate class Renderer which knows how to draw the model state; have a System class which ties these together. The following is highly abbreviated, but hopefully gives the idea:
class Box {};
class Location {};
class Particle
{
public:
void updatePosition(double dt);
const Location& getLocation();
};
class Environment
{
public:
void checkForCollisions();
private:
Box box;
std::vector<Particle> particles;
};
class Renderer
{
public:
void render(Environment& environment);
};
class System
{
Environment environment;
Renderer renderer;
};
I am making a game, and I have finally finished the gameplay aspect of it, but now it's time for me to create a menu and a high scores screen. I'm not entirely sure how to do it, the game will be in a different state (MENU_STATE, GAMEPLAY_STATE, SCORESCREEN_STATE) and in each state I want to draw different things to the screen, is it okay for me to do something like this then?
draw function()
{
if MENU_STATE
draw menu
if GAMEPLAY_STATE
draw game
if SCORESCREEN_STATE
draw scores
}
I've been following a strictly no logic in the draw function and it's been good so far, but I really can't figure out a different way to do this.
You could use separate classes for the three states, implementing a common interface, and rather than setting a constant for state, set an instance of one of the classes:
interface IState {
void draw();
}
class Menu implements IState {
void draw() {
// Draw menu
}
}
class Game implements IState {
void draw() {
// Draw game
}
}
void draw() {
state.draw();
}
This still isn't ideal (you don't really want drawing code in your state, you want something a bit more separate), but the abstraction is a common one and could be relevant (and it's hard to advise further without knowing more of your architecture).
You are calling some drawing functions in that routine but that doesn't mean
you have to name it draw.
Perhaps this is more appropriate in your case:
// pseudocode
on_game_state function(state)
{
select (state):
MENU_STATE:
draw menu
GAMEPLAY_STATE:
draw game
SCORESCREEN_STATE:
draw scores
}
Using a statemachine would make this simpler. Each state will have its own set of update and draw functions that are called when it is on top of the state stack. Instead of having one draw function with internal state switches you would have Game_Draw(), Menu_Draw(), HighScoreScreen_Draw() etc. Similarly your update functions could be separated out.
static void StateMachine_DrawTopState()
{
switch(stateMachine_topState)
{
case STATE_GAMEPLAY:
{
Gameplay_Draw();
}
break;
case STATE_MENU:
{
Menu_Draw();
}
break;
}
}
Similar to Andrew Aylett's answer and assuming an object-oriented language, perhaps you could do something like:
Interface IState {
void init();
void update();
void draw();
}
class GameplayScene implements IState {
void init() {
// initialize gameplay
}
void update() {
// update game logic
}
void draw() {
// draw game
}
}
class MenuScene implements IState {
void init() {
// initialize menu
}
void update() {
// update menu logic
}
void draw() {
// draw menu
}
}
class ScoresScene etc...
class TitleScene etc...
// Somewhere else, probably in the Game class
void Main() {
// Init game
Scene currentScene = new TitleScene;
while (Scene != null) {
Scene.init();
Scene.update();
Scene.draw();
}
// Exit game
}
You would also need to think about how to handle transition between scenes. You could have each scene class have a member variable called something like nextScene and the main function queries it at the start of the loop to switch to the proper scene.
If you don't have the luxury of using an object-oriented programming language (like C++, Java, C#, Python, etc.), both Colin's and Nick D's answers might help, although I'd try to have the switch statement in one place (say one big game_update function) to allow adding new states by making a change in one place. Alternatively, you could build on the Colin's state machine design to make something more generic and that doesn't explicitly require a hard-coded switch statement. (although to be honest I can't think of a good way to do it at the moment)
It is absolutely not ok to put game logic in a draw function.
However, if it makes your life easier in this specific case, it's ok anyway.
You can always change it later if it becomes a mess.
Yes it's fine, game programmers are allowed to bend the rules for performance gains. The view and the model of a game world are quite often one and the same thing to avoid latency created by decoupling the view and the model.
There's no reason why you can't make the menu and highscores objects part of your game world, it's been done before in quite a few games.