Sorry if this sounds quite trivial. I am just not getting it. How can one determine if a particular sprite is already in a layer? Basically, I need to check this before determining whether to add it to the layer or not.
if ( [ myNode.children indexOfObject:sprite ] == NSNotFound ) {
// you can add the code here
}
There's so many ways:
1) try to get child
if (![layer getChild:sprite]) {
// Your code
}
2) try to get child by tag
if (![layer getChildByTag:spriteTag]) {
// Your code
}
3) Check if sprite is on children array (like #oopology answer)
if ([layer.children indexOfObject:sprite] == NSNotFound) {
// Your code
}
Related
I tried this code to get the first visible row in a scrolling Table inside a BorderLayout.CENTER, but it didn't work, seems the points returned do not reflect the visible cells, unless I am missing a sort of calculation,
thank you for your insights,
#Override
protected void onScrollY(int scrollY) {
super.onScrollY(scrollY); //To change body of generated methods, choose Tools | Templates.
Component c=getComponentAt(50, scrollY);
if (c instanceof Table){
System.err.println("table "+getWidth()+" "+getHeight()+" s "+scrollY);
return;
}
Button b=(Button) c;
System.err.println("c: "+b.getText());
}
getComponentAt(x,y) takes absolute (screen) coordinates. The scrollY value is a relative coordinate in that container.
So what you want is something like:
Component c = getComponentAt(getAbsoluteX()+50, getAbsoluteY() + scrollY)
Also worth nothing that getComponentAt(x,y) will only return components that are focusable or have been set to grab pointer events. If you just want to find the first paintable immediate child of this container, and you're using a BoxLayout.Y_AXIS layout, then you might be better to just iterate through the children until you find one where y is at least the scrollY.
e.g.
Component c = null;
for (Component child : this) {
if (child.getY() + child.getHeight() > scrollY) {
c = child;
break;
}
}
....
I am trying to make a program where you are allowed to select between an option of shapes, and then drawing it. To allow for multiple shapes I created a vector of a class which creates shapes (Shapes are set up with the chosen function). My problem is the mouse click is too long, so it assigns it to everything in the vector, so you can't create a new shape. Is there a problem in my logic, or is there a problem in the code?
Here is my attempt:
for (auto& it : onCanvas) {
if (Mouse::isButtonPressed(Mouse::Left)) {
if (mousepointer.getGlobalBounds().intersects(circleOption.getGlobalBounds())) {
it.chosen(circles);
}
if (mousepointer.getGlobalBounds().intersects(rectOption.getGlobalBounds())) {
it.chosen(rectangle);
}
if (mousepointer.getGlobalBounds().intersects(triOption.getGlobalBounds())) {
it.chosen(triangles);
}
if (mousepointer.getGlobalBounds().intersects(it.shape.getGlobalBounds()) || it.dragging) {
it.shape.setPosition(mousepointer.getPosition());
it.dragging = true;
}
}
if (!Mouse::isButtonPressed) {
it.dragging = false;
}
win.draw(it.shape);
}
Your source-code is a bit incomplete (what is onCanvas and mousepointer). But I guess the problem is that this snippet is called multiple times while your mouse is clicked. To avoid that you can do two thing.
In the first solution you use events, so you only add shapes when the state of the mousebutton changes (you can additionally listen to the MouseButtonReleased to simulate a full click):
if (event.type == sf::Event::MouseButtonPressed)
{
if (event.mouseButton.button == sf::Mouse::Left)
{
// Hit Detection
}
}
or second solution you remember the last state of the button (probably do the mouse check once outside of the for loop):
bool mouse_was_up = true;
if (mouse_was_up && Mouse::isButtonPressed(Mouse::Left)) {
mouse_was_up = false;
for (auto& it : onCanvas) {
// Hit Detection
}
}
else if (!Mouse::isButtonPressed(Mouse::Left))
mouse_was_up = true;
I would rather stick to the first solution because when your click is too short and your gameloop is in another part of the game logic, you can miss the click.
I am trying to make my basic loading screen transition over to game level screen. So what i wanted to do is, once the loading screen is active (or has appeared onscreen), I want at this point to start loading my game state. What it is doing at the moment is loading everything at the start, and this does take a while.
So currently my project starts off with a main menu. Then when i press enter, its starts the loading screen. I have my manual state change using keypresses like so:
void Game::update()
{
static bool enterPreviouslyPressed = false;
static bool escapePreviousPressed = false;
const Uint8 *keys = SDL_GetKeyboardState(NULL);
if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(GameState))
{
fsm->setState(menuState);
}
else if (keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
fsm->setState(loadingState);
}
else if ((keys[::SDL_SCANCODE_RETURN] && !enterPreviouslyPressed) && typeid(*fsm->getState()) == typeid(LoadScreenState))
{
fsm->setState(gameState);
}
else if (keys[::SDL_SCANCODE_ESCAPE] && !escapePreviousPressed && typeid(*fsm->getState()) == typeid(MainMenuState))
{
exit(0);
}
enterPreviouslyPressed = keys[::SDL_SCANCODE_RETURN] != 0;
escapePreviousPressed = keys[::SDL_SCANCODE_ESCAPE] != 0;
fsm->update();
}
I did this to initially does this so i could change states manually to check that everything works. I was wondering if there was an easy(ish) way, like boolean flags for example or another simpler way to do this. I wasn't able find any tutorials online so wondering if someone knows the best solution as to how to do this. I did see a question on here, kindda similar but I wasn't sure if it answered my question as the person did this in threads which I am not familiar with how to implement. Apologies if I dont seem to have the logic correct - so please advise otherwise.
Looks fairly standard, except I would simplify it by keeping two keyboard state variables declared as class variables, like:
const Uint8 *curKeys = SDL_GetKeyboardState(NULL), *prevKeys;
// ...
void Game::update() {
prevKeys = curKeys;
curKeys = = SDL_GetKeyboardState(NULL);
//and so then compare curKeys to prevkeys
//and ditch the booleans
// ...
}
I'm currently programming a game using cocos2dx engine and I have a level manager that keeps track of the current level and the scene that needs to be loaded. I want to avoid long if statements, such as this:
Scene* scene;
if (level == 1)
{
scene = Game_Scene1::createScene();
}
else if (level == 2)
{
scene = Game_Scene2::createScene();
}
else if (level == 3)
{
scene = Game_Scene3::createScene();
}
(...)
else if (level == 10)
{
scene = Game_Scene10::createScene();
}
Director::getInstance()->replaceScene(TransitionFade::create(0.5, scene, Color3B(0,0,0)));
The screateScene() method is a static method
static cocos2d::Scene* createScene();
What could I do to "remove" the if statement? So it would look something like this:
Scene* scene = getScene(level, sceneClass::createScene());
and it would take the correct class (that is: Game_Scene1, Game_Scene2 etc.)
Is there a nice solution for such problem? The title says template but I'm not really sure if the solution for this is a template.
One simple solution would be to used a table of pointer functions.
You could declare your table as
typedef cocos2d::Scene *(*PtfCreateScene)();
PtfCreateScene tab[10];
tab[0] = Game_Scene1::create_scene;
tab[1] = Game_Scene2::create_scene; ...
Using this solution you can then call the associated create_scene function using level as an index. Thus avoiding the if branchings .
scene = tab[level - 1]();
You will have to check the correctness of the index to avoid out of memory access.
Hope I answered your question. Don't hesitate to ask if you need more explanation.
Im working on a dialog box in which several rules must be satisfied before the OK button is enabled.
Currently any action on the page such as entering data or selecting an item from a drop down list (amongst other things) calls a single function called ProcessEvent() - this function handles all logic and either enables or disables the OK button.
My problem is I finding it difficult making the rules concise and understandable.
Some of the rules can be negated by another action on the dialog and I have now ended up with if else statements all over the place or which are difficult to read and follow & extend.
The code below is a simplification of the problem but demonstrates it well. How do I handle this problem better (If its Possible)
bool CWorkstation::ProcessEvent(void)
{
UpdateData();
CharCount = GetDlgItemInt(IDC_CharCount, NULL, FALSE); //get latest
if ( IsDlgButtonChecked(IDC_USEDBNAME))
{
if (!IsDlgButtonChecked(IDC_MAXDBNAME))
{
EnableNext(TRUE);
}
}
if (IsDlgButtonChecked(IDC_MAXDBNAME) && CharCount)
{
if (IsDlgButtonChecked(IDC_USEXMLNAME))
{
if ( PrefixName.IsEmpty() )
{
EnableNext(FALSE);
}
else
{
EnableNext(TRUE);
}
}
}
if (IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1)
{
EnableNext(TRUE);
}
if ( IsDlgButtonChecked(IDC_WSAUTONAME) || IsDlgButtonChecked(IDC_RENAMEIFDUP))
{
// TRACE("IDC_WSAUTONAME is Checked\n");
if ( IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1 )
{
if ( IsDlgButtonChecked(IDC_IDC_USESHORTNAME) )
{
EnableNext(TRUE);
}
else if ( IsDlgButtonChecked(IDC_USELONGNAME) )
{
EnableNext(TRUE);
}
else
{
EnableNext(FALSE);
}
}
if ( !IsDlgButtonChecked(IDC_USEPREFIX) )
{
if ( IsDlgButtonChecked(IDC_IDC_USESHORTNAME) || IsDlgButtonChecked(IDC_USELONGNAME) )
{
EnableNext(TRUE);
}
}
return false;
}
}
I would split your if/else statements into multiple functions, and do an &= on the parameter you send to EnableNext. You should be calling EnableNext only once.
So, for example:
// in CWorkStation::ProcessEvent
bool enableNext = true; // start with true
enableNext &= Condition1(); // of course pick better names than Condition1
enableNext &= Condition2(); // this is just for an example
EnableNext(enableNext);
Where Condition1() might be:
bool Condition1()
{
return (IsDlgButtonChecked(IDC_USEDBNAME)
&& !IsDlgButtonChecked(IDC_MAXDBNAME));
}
And so on.
What's happening here is that the enableNext variable starts with true. Then, each &= you do means that if any of the ConditionX() functions returns false, enableNext will end up false. It will only be true at the end if ALL of the conditions are true.
That problem can be solved with the concept of listeners.
You can make each of your GUI components have a isEnabled() method, which checks its conditions based on some conditions. The isEnabled() is called on each GUI component when any action that changes the state of any component is called.
This way you can have the following declarations:
bool CheckBoxComponent::isValid() {
return isNameFilled() && isEmailChecked();
}
bool OkButton::canSend() {
return checkBoxName->isValid() && isEmailChecked();
}
Then, when creating your GUI components you make each of them connect to each other via listener.
This way you have the rules for each component where they belong and you don't have tons of if statements.
It may help to try to formulate the rules as a state-machine, but if that is practical depends on their nature. In that approach, whenever the user fills out some field in the dialog, or checks a checkbox or whatever, you update the state of your sate-machine accordingly. If you have that, you can use Boost.Statechart to implement it.
In cases like that, I tend to make it as simple as possible by (for example) enabling the button by default, and if any other condition is set (or not), disable it; this limit the different cases in "if" conditions with "else".
Restate your condition as a proper boolean statement, properly indent all conditions and add some comments. IMHO, you shouldn't hide the real checks in single-use methods. If you want to comment code, comment it but don't create methods for that purpose, it only obfuscates things and your conditions don't get any simpler:
EnableNext(
// condition 1
IsDlgButtonChecked(IDC_USEDBNAME) && !IsDlgButtonChecked(IDC_MAXDBNAME)
// condition 2
|| IsDlgButtonChecked(IDC_MAXDBNAME) && CharCount
&& IsDlgButtonChecked(IDC_USEXMLNAME) && !PrefixName.IsEmpty()
// condition 3
|| IsDlgButtonChecked(IDC_USEXMLNAME) && PrefixName.GetLength() > 1
// and so on
)
This way it becomes immediately obvious that you seem to check the same condition twice USEXMLNAME && !PrefixName().IsEmpty(). It is also obvious now, that EnableNext is always called.
Though it might be a bit "heavier" of a solution than you'd like, you might want to look at Adobe's Adam and Eve libraries. Eve deals with widget layout, and Adam takes a set of statements about the logic of the widgets and puts them together into a controller that enables and disables widgets based on that logic, as well as handling initialization and putting results into the proper variables (e.g., when the user clicks "Ok").