This site requires JavaScript, please enable it in your browser!
Greenfoot back
protocolUnknown
protocolUnknown wrote ...

2018/1/3

I made a scenario public and I would like help to solve a problem in it

protocolUnknown protocolUnknown

2018/1/3

#
I am trying to make a mechanic where if you walk over to a "LootBox" as I call it in my code (green or brown boxes as they appear in my game), and press Escape to interact with it, it will show you the two health kits that are inside of it at the top right of your screen. This feature works sometimes, and other times it crashes and greenfoot says it is a nullPointerException error. You should be able to download my work on my page, and see what I am talking about. P.S. you must walk right over these boxes to interact with them. P.P.S. I was going to just do a post on this issue, but I just made a scenario for it public so that whoever wants to help me can see it more clearly.
danpost danpost

2018/1/3

#
You have the following in your MyWorld class (starting around line 166 or so):
public void checkItemsInArea()
{
    maxItemsInArea = 0;
    if(p.isTouchingBox())
    {
        lb =  p.objectNearby();
        //showText(Integer.toString(lb.getMaxNumOfItems()), getWidth()/2, getHeight()/2);
        maxItemsInArea = 2;
        for(i = 0; i < maxItemsInArea; i++)
        {
            //holder[i] = new FirstAid();
            //holder[i] = p.objectNearby();
            holder[i] = (FirstAid) p.objectNearby().getContents()[i];
            addObject( (Actor)holder[i], 35, 110 + (40*i) );

        }
        
    }else{
        return;

    }

}
danpost danpost

2018/1/3

#
I am now looking for why the NullPointerException was sometimes thrown. It was caused by line 13 above.
protocolUnknown protocolUnknown

2018/1/3

#
Yes, and what should I fix with this?
protocolUnknown protocolUnknown

2018/1/3

#
I think it might have to do with the casting as I am terrible with that. But it is strange because it sometimes works and then other times it throws that exception. Also as you can see I commented out a lot of stuff to get this thing to work. (btw ignore my above comment as I sent it b4 seeing your other comment)
danpost danpost

2018/1/3

#
Okay. I am quite sure that the FirstAid (and the Item class, for that matter) should NOT be extending the LootBox class. Items contained within a loot box are not loot boxes themselves. A subclass is used to describe a more specific type of object that the class it extends represents. I noticed you have also subclassed Player with the Bullet class. A bullet is NOT a player by any means. An example of proper subclassing (apparently) would be how the Melee and RangedWeapon classes extend the Weapon class. A melee is a specific weapon and a ranged weapon is a more specific type of weapon (but still a bit general in nature, being it could be further subclassed to the specific ranged weapons you might decide to use in the scenario). I did notice another general type of mistake you are making. You are assigning values to some specific type of fields in the declaration statements where it is pointless to do so. The two I saw were like the following:
// case 1
private MouseInfo mouse = Greenfoot.getMouseInfo();

// case 2
private MyWorld world = (MyWorld)getWorld();
These lines assign the fields with the returned value at the the time the object that holds it is created and only then. The 'getWorld' method will always return and set 'world' to a 'null' value as the object needs to be constructed before it can be placed into a world. Getting mouse info during the creation of the world equally makes no sense. Next thing, I noticed you had a boolean setup field in some Actor subclasses, using an 'if (!setup)' block in the act method to "construct" the actors. Use a constructor block for that. For example:
public LootBox()
{
    setImage(rand.nextInt(2) == 0 ? "Dumpster.png" : "CardboardBox.png");
    contents = { new FirstAid(), new FirstAid() };
}
You do not need multiple method or the 'setup' field. You do not even need the 'maxNumberOfItems' field either if it is always '2'.
danpost danpost

2018/1/3

#
Your 'isTouchingBox' method uses a different collision checking method than that which the 'objectNearby' method uses. That is, itTouchingBox can return a true value at the same time that getOneObjectAOffset(0, 0, LootBox.class) can still returns a null value. Either use 'getOneIntersectingObject' in the objectNearby method; or use 'getOneObjectAtOffset(0, 0, LootBox.class) != null' in the isTouchingBox method.
protocolUnknown protocolUnknown

2018/1/3

#
Yes the extending parts of my code I am still fixing, such as the bullet. Also for maxNumOfItems I initially set it to randomise a number for that, but I thought it might be the cause of the error so I coded it to always be 2 for the sake of testing. Also, I intend of having different objects other than first aid kits in the lootboxes, which is why I set it up as a switch statement so I can later add objects. I will fix a lot of these mistakes right now, thank you. (Btw I code in a very hapazard way, as you can probably tell, and then later try to go back and fix stuff I did wrong)
danpost danpost

2018/1/3

#
I only see a switch statement for setting the image of the LootBox objects. I do not see one that is used to load the LootBox object with different objects. However when you do, you can use something like this:
Item[] objs = { new ObjA(), new ObjB(), new ObjC(), ... }; // one of each type (if possible for multiple of same types, you can duplicate)
for (int i=0; i<maxNumberOfItems; i++)
{
    int j = rand.nextInt(objs.length-i);
    contents[i] = objs[j];
    objs[j] = objs[objs.lengthh-i-1];
}
If all items can be duplicated any number of times, then a switch statement would be best; but only for creating the item:
for (int i=0; i<maxNumberOfItems; i++)
{
    Item item = null; // presuming all loot box contents are from Item subclasses
    switch(rand.nextInt(maxNumberOfContentTypes))
    {
        case 0 : item = new ObjA(); break;
        case 1 : item = new ObjB(); break;
        // etc.
    }
    contents[i] = item;
}
protocolUnknown protocolUnknown

2018/1/3

#
Oh my god it's working. Thank you so much. Like seriously. I am fixing those other things too, but I have another question I'd like to ask. For my pause function I wanted the game to freeze, yet still allow the player to use the menu options, but I could not figure out how to do that, do you have any ideas?
protocolUnknown protocolUnknown

2018/1/3

#
Every time I comment to your reply and send it, you send another reply just moments before and it looks like I am replying to that lol. But I will definitely try and implement that into my code, for when I add more loot, and yes all items in the loot boxes are child of Item class. Also I set Bullet as a child to Item, as I wanted that to be lootable, and I do agree that it is a more suitable place for it rather than under Player.
protocolUnknown protocolUnknown

2018/1/3

#
Wait a minute for your first patch of code that you posted above:
Item[] objs = { new ObjA(), new ObjB(), new ObjC(), ... }; // one of each type (if possible for multiple of same types, you can duplicate)
for (int i=0; i<maxNumberOfItems; i++)
{
    int j = rand.nextInt(objs.length-i);
    contents[i] = objs[j];
    objs[j] = objs[objs.lengthh-i-1];
}
^Is that to maximise randomisation?
danpost danpost

2018/1/3

#
protocolUnknown wrote...
For my pause function I wanted the game to freeze, yet still allow the player to use the menu options
One way is to put a condition on all actions except those you wish to allow when the game is paused. That would be to enclose all your game characters' act methods within the following 'if' block:
if (getWorld().getObjects(PauseSymbol.class).isEmpty())
{
    // current act method codes
}
There is another way, but it is currently not up to date. I have a PauseWorld support class which could be subclassed to provide the menu there However, it is not written for the current version of greenfoot (currently written for greenfoot v2.3.0).
danpost danpost

2018/1/3

#
protocolUnknown wrote...
Wait a minute for your first patch of code that you posted above: < Code Omitted > ^Is that to maximise randomisation?
That segment so that each and every item, including duplicates, listed has an equal chance of being selected. As each item is selected, it is removed from the selectable items before the next choice. Added more documentation below:
Item[] objs = { new ObjA(), new ObjB(), new ObjC(), ... }; // one of each type (if possible for multiple of same types, you can duplicate)
for (int i=0; i<maxNumberOfItems; i++) // for each choice
{
    int j = rand.nextInt(objs.length-i); // pick an item number
    contents[i] = objs[j]; // put item in box
    objs[j] = objs[objs.length-i-1]; // remove from future selections
}
You need to login to post a reply.