public static void showHs(boolean remove){
if(remove){
table.getCell(hsLabel).getActor().setVisible(true);
table.getCell(hsLabel).getActor().setWidth(labelsWidth);
}else {
table.getCell(hsLabel).getActor().setVisible(false);
table.getCell(hsLabel).getActor().setWidth(0);
}
}
setVisible() doesn't remove actor - it still takes the cell, if I use remove() works, but permanently, can't bring actor at the same place.
Is there any methods like Visibility.GONE ? I searched and ended by being here.
public static void showHs(boolean remove){
if(remove){
table.getCell(hsLabel).getActor().setVisible(true);
table.getCell(hsLabel).getActor().setWidth(labelsWidth);
table.getCell(hsLabel).expandX();
}else {
table.getCell(hsLabel).getActor().setVisible(false);
table.getCell(hsLabel).getActor().setWidth(0);
table.getCell(hsLabel).width(0);
}
}
Worked out by setting 0 width to cell, but maybe there is a proper way
Here is a simple approach on how to make your actors inside your table set the visibility. You don't have to set the actor's width to zero to make it "disappear".
The second parameter in contains is Identity, If true, == comparison will be used. If false, .equals() comparison will be used.
true if an array contains a value, false if it doesn't.
public static void showHs(boolean visible,Actor yourActor){
if(table.getChildren().contains(actor,true){
actor.setVisible(visible);
}
}
Related
Hope everyone knows the basic Libgdx game in this link:
https://github.com/libgdx/libgdx/wiki/A-simple-game
In the simple game,rain drops are falling randomly from the top,that is of one type.
In my case,I want to implement the same thing,as drops.The difference is that,there are four type of drops.When it collides with another object,four should show four different characteristics.
In short,I created a Drop class with its object and array and can spawn drop objects too.
Drop drop=new Drop();
private Array<Drop> drops=new Array<Drop>();
But what if I want to define individual attributes for drops in this case?
I want the drop object to be categorized of four types. For example have different colors yellow,red,green and blue.Also four kind of drops should fall randomly from top.
In which way,and how I should implement such a concept?
It would be very helpful if I get some idea on this.
Edit:
I have an abstract class Drop and .I am not passing texture and rectangle in the constructor.Because graphics are not available for the project right now.I am planning to assign it in a later stage.As of now,everything I am doing it with shaperenderer.
I have create() method for three distinct colored drops in my objectFactory class where I used to create all objects:
public YellowDrop createYellow(){
YellowDrop yellow = new YellowDrop();
yellow.setSize(100f,100f);
yellow.setPosition(MathUtils.random(0, 800),1280);
return yellow;
}
public RedDrop createRed(){
RedDrop red = new RedDrop();
red.setSize(100f,100f);
red.setPosition(MathUtils.random(0, 800),1280);
return red;
}
public GreenDrop createGreen(){
GreenDrop green = new GreenDrop();
green.setSize(100f,100f);
green.setPosition(MathUtils.random(0, 800),1280);
return green;
}
And I written createRandomDrop() code like this(For me,your code is confusing though.How can I use that colon symbol there in a method?I never used it.)
private Block createRandomDrop() {
switch (MathUtils.random(0, 3)) {
case 0 :
System.out.println("000000");
return objectFactory.createYellow();
case 1 :
return objectFactory.createGreen();
case 2 : return objectFactory.createRed();
default:
return objectFactory.createGreen();
}
}
Here I am confused about how to return the individual drop object.
Even though I have written the call like this:
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) {
drops.add(createRandomDrop());
}
private void updateBlocks(float delta) {
Iterator<Drop> iter = drops.iterator();
while(iter.hasNext()) {
Drop b = iter.next();
b.update(delta);//moving drop from top to bottom in update()
if(b.getY()<0) iter.remove();
}
// System.out.println(drops.size);
}
At last I am drawing the shaperenderer for all array elements:
for (Drop b : drops) {
b.drawDebug(shapeRenderer);}
This drawdebug() is in Drop class and I am overriding it
public void drawDebug(ShapeRenderer shapeRenderer) {
shapeRenderer.setColor(Color.YELLOW);
shapeRenderer.rect(collisionRectangle.x, collisionRectangle.y,
collisionRectangle.width,
collisionRectangle.height);
}
problem is that,too many drops are getting created and overlapping.May be the switch case creates the problem.
What is your problem? This is simple.
Create 4 children of Drop class. yellowDrop, greenDrop, etc... And create collide() method in Drop class which will implement same functionality for all children.
Something like this:
abstract class Drop {
abstract Texture tex;
abstract Rectangle rect;
Drop(Texture tex, Rectangle rect){
// initialize values here
}
void showCollideAnimation(){ // example. here you can create your own void to show different characteristics.
tex.blabla()
}
void collide(){
showCollideAnimation();
}
// also draw, update methods etc... Hope you got that they should do functionality same for all children
}
And then create child that will override showCollideAnimation method.
class GreenDrop extends Drop {
#override
void showCollideAnimation(){
.... // here you pass effect for Green child
}
}
To chose random child you can just create function that returns Drop
Drop createRandomDrop(Rectangle rect): Drop {
switch (MathUtils.random(0, 3)) {
case 0 : return new YellowDrop(Texture("pathToYellowTexture"), rect) break;
case 1 : return new GreenDrop(Texture("pathToGreenTexture"), rect) break;
// etc.
}
}
Now you can fill ArrayList of Drops.
private ArrayList<Drop> drops = new ArrayList<Drop>();
in render method:
if(TimeUtils.nanoTime() - lastDropTime > 1000000000) {
drops.add(createRandomDrop(Texture(""), Rectangle())); // specify texture and rectangle yourself
}
I have a component which consists of two children component A and B. However, the visibility of showing either A or B can only be determined after the page rendering started. I tried to do this but got back the following error:
Cannot modify component hierarchy after render phase has started
So, is there any way to change the visibility of the children components in my case?
I'm not exactly sure if I understand your problem.
I assume that you have 2 containers and want to display only one of them. If that is the case you can simply extend the onConfigure() method and change the visibility the way you want it to. This method will be called once during each rendering and is therefore preferred over extending the isVisible() method (which is called multiple times during each request).
private IModel<Boolean> switchModel = Model.of(Boolean.FALSE);
#Override
protected void onInitialize() {
super.onInitialize();
WebMarkupContainer container1 = new WebMarkupContainer("container1") {
#Override
protected void onConfigure() {
super.onConfigure();
setVisible(Boolean.TRUE.equals(switchModel.getModelObject()));
}
};
add(container1);
WebMarkupContainer container2 = new WebMarkupContainer("container2") {
#Override
protected void onConfigure() {
super.onConfigure();
setVisible(Boolean.FALSE.equals(switchModel.getModelObject()));
}
};
add(container2);
}
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!
Variant 1:
public static function set setWidth(w:int):void
{
width += (w); //not working
}
.
public function Caller()
{
ProgressLine.setWidth = -20;
}
.
Variant 2
public function set setWidth(w:int):void
{
width += (w);
}
.
public function Caller()
{
progress = new ProgressLine;
progress.setWidth = -20;
}
.
My first function (setter) is in class ProgressLine
My second function is in class Caller
How to change the width of Class ProgressLine by using static setter function (Variant 1)?
I don't want to use non-static function (Variant 2) because every time I use Variant 2 the width is back to normal. If the normal width is 200 every time I call the ProgressLine class the width is back to 200 (it renew the initial width).
Basically I want to pass the value from Caller to ProgressLine that is going to change the ProgressLine width. The problem is that I don't want to initialize the ProgressLine class every time I send the value.
Thanks you for your help in advance
You can't access a non-static property from a static method in the same class. Maybe you have to implement a Singleton pattern on the class if you will only have one instance of ProgressLine.
Firstly can some one please explain what is meant by Object and Function in a profiling environment.
Secondly, why does the Object and Function count increase when I repeatedly set the text property of a textfield:
override public function setLanguage(id:String):void
{
if (id == "en")
{
ui.title.text = _data.text.title.en;
ui.title.direction = Direction.LTR;
}
else if (id == "ae")
{
ui.title.text = _data.text.title.en;
ui.title.direction = Direction.RTL;
}
}
From Laurent:
Internally, TextField::text is most likely a getter/setter (since it needs to set a flag to update the text field display, also possibly update the HTML content, etc.) so when you set it you are effectively calling a function.
This means that TextField.text is implemented as a property getter and setter, so if you had to code it, you would see something like
private var _text:String="";
public function get text():String {
return _text;
}
public function set text(value:String):void {
_text=value;
}
Your Object count increases every time you reference (looking for a better word, don't kill me about this :P) an object (I trust you know what objects are), and your Function count increases every time you invoke a function.
So when you do something like
myTextField.text="Hello World";
you are referencing object myTextField and invoking its function set text(String);, causing your counts to increase by 1 each.
Internally, TextField::text is most likely a getter/setter (since it needs to set a flag to update the text field display, also possibly update the HTML content, etc.) so when you set it you are effectively calling a function.
What is it you don't understand about the difference between a Function and an Object? Could you be more specific?