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

2017/2/25

How do I create an inventory?

1
2
3
4
SallySanban SallySanban

2017/2/25

#
I would like to create an inventory where if a clue is clicked in the scenario, it will be added to the inventory. The inventory should show all the items inside it by pressing 'x' and (if it's not possible to hide the items by pressing x again) hide the items by clicking the inventory object. This is a very rough code I made to create it:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
boolean CaramelApple = true;
     
    public void act()
    {
        inventory();
    }  
     
    public void inventory()
    {    
        if(Greenfoot.isKeyDown("x"))
        {
            if(CaramelApple)
            {
                CaramelApple apple = new CaramelApple();               
                getWorld().addObject(apple, 105, 361);
            }
        }
        if(Greenfoot.mouseClicked(this))
        {
            if(getWorld().getObjectsAt(105, 361, Props.class) != null)
            {            
                getWorld().removeObjects(getWorld().getObjectsAt(105, 361, Props.class));
            }
        }
    }
It doesn't exactly work, and it only shows the object CaramelApple because I've already set it as true. If I were to have another object that I didn't set manually as true, it wouldn't show up. Is there any way I can create a proper inventory?
Super_Hippo Super_Hippo

2017/2/25

#
I think I would handle the inventory from your world class. Create a list and add every found item to the list. The list can contain the objects itself or maybe ints representing the different hints. Then, when x is pressed, an inventory is created with a set number of inventory slots. For every list entry, you add the corresponding item to the slot.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//importing java.util.List and ...ArrayList at the top
 
private List<Actor> collectedObjects = new ArrayList(0); //the hints which were collected and should show up in the inventory
private boolean inventoryShowing = false; //true if the inventory is showing right now
private List<Actor> inventoryObjects = new ArrayList(0); //all actors which are added when x is pressed so they can be removed when x is pressed again
 
//to check if one was clicked:
for (Hint h : getObjects(Hint.class))
{
    if (Greenfoot.mousePressed(h))
    {
        collectedObjects.add(h); //add the hint to the list of collected hints
        removeObject(h); //remove the clicked hint from the world
    }
}
 
//inventory on/off
if (Greenfoot.mousePressed("x"))
{
    toggleInventory();
}
 
 
private void toggleInventory()
{
    if (!inventoryShowing)
    { //create inventory
        Actor background = new Actor() {}; //an actor for the background of the inventory
        GreenfootImage img = new GreenfootImage(160, 160); //size of the inventory
        img.setColor(new Color(100, 0, 0)); //color of the inventory background
        img.fill();
        background.setImage(img);
        addObject(background, getWidth()/2, getHeight()/2); //add it to the middle of the world
        inventoryObjects.add(background);
         
        img = new GreenfootImage(20, 20); //image with the size of each inventory slot
        img.setColor(Color.GRAY); //color of inventory slot
        img.fill();
        int i=0, numItems=collectedObjects.size();
        for (int row=0; row<2; row++) //2 rows of inventory slots
        {
            for (int column=0; column<5; column++) //each row has 5 columns
            {
                Actor slot = new Actor() {}; //alternative: draw the inventory slots on the image of the 'background' object
                slot.setImage(img);
                addObject(slot, getWidth()/2-100+10+column*30, getHeight()/2-100+10+row*30);
                inventoryObjects.add(slot);
                if (i<numItems)
                {
                    Actor item = collectedObjects.get(i);
                    item.setImage(new GreenfootImage(item.getImage()).scale(20, 20));
                    addObject(item, getWidth()/2-100+10+column*30, getHeight()/2-100+10+row*30);
                    inventoryObjects.add(item);
                }
                i++;
            }
        }
        inventoryShowing = true;
    }
    else
    { //remove inventory
        removeObjects(inventoryObjects); //remove all objects relating to the inventory
        inventoryShowing = false;
        inventoryObjects = new ArrayList(0);
    }
}
Well, that is the idea I had. It is not supposed to work (maybe it does), but hopefully you can understand the idea.
SallySanban SallySanban

2017/2/26

#
Thank you! I don't understand toggleInventory() since it's my first time encountering a for loop in Greenfoot. (I'm a 15 year old high school student and this is actually my project in school.) I haven't tried out the code yet mostly because there's a syntax error:
1
2
3
4
5
6
7
if (i<numItems)
    {
         Actor item = collectedObjects.get(i);
         item.setImage(new GreenfootImage(item.getImage()).scale(20, 20)); //20, 20 is underlined in red and it says, 'void' type not allowed here
         addObject(item, getWidth()/2-100+10+column*30, getHeight()/2-100+10+row*30);
         inventoryObjects.add(item);
    }
Could you please explain the toggleInventory() method?
SallySanban SallySanban

2017/2/27

#
I was able to transfer your code into my Inventory class, doing this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;
import java.awt.Color;
import java.util.ArrayList;
 
/**
 * Write a description of class robot here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class Inventory extends Actor
{
    public List<Actor> collectedObjects = new ArrayList(0); //the hints which were collected and should show up in the inventory
    public boolean inventoryShowing = false; //true if the inventory is showing right now
    public List<Actor> inventoryObjects = new ArrayList(0); //all actors which are added when x is pressed so they can be removed when x is pressed again
 
    /**
     * Act - do whatever the robot wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        clue();
        if(Greenfoot.isKeyDown("x"))
        {
            showInventory();
        }
    }
 
    public void clue()
    {
        for(Clues h: getWorld().getObjects(Clues.class))
        {
            if (Greenfoot.mouseClicked(h))
            {
                collectedObjects.add(h); //add the hint to the list of collected hints
                getWorld().removeObject(h); //remove the clicked hint from the world
            }
        }
    }
 
    public void showInventory()
    {
        if(!inventoryShowing)
        {
            Background background = new Background() {}; //an actor for the background of the inventory
            GreenfootImage img = new GreenfootImage(160, 160); //size of the inventory
            img.setColor(new Color(100, 0, 0)); //color of the inventory background
            img.fill();
            background.setImage(img);
            getWorld().addObject(background, getWorld().getWidth()/2, getWorld().getHeight()/2); //add it to the middle of the world
            inventoryObjects.add(background);
 
            img = new GreenfootImage(20, 20); //image with the size of each inventory slot
            img.setColor(Color.GRAY); //color of inventory slot
            img.fill();
            int i=0, numItems=collectedObjects.size();
            for (int row=0; row<2; row++) //2 rows of inventory slots
            {
                for (int column=0; column<5; column++) //each row has 5 columns
                {
                    Slot slot = new Slot() {}; //alternative: draw the inventory slots on the image of the 'background' object
                    slot.setImage(img);
                    getWorld().addObject(slot, getWorld().getWidth()/2-100+10+column*30, getWorld().getHeight()/2-100+10+row*30);
                    inventoryObjects.add(slot);
                    if (i<numItems)
                    {
                        Actor item = collectedObjects.get(i);
                        item.setImage(new GreenfootImage(item.getImage())); //.scale(10, 10));
                        getWorld().addObject(item, getWorld().getWidth()/2-100+10+column*30, getWorld().getHeight()/2-100+10+row*30);
                        inventoryObjects.add(item);
                    }
                    i++;
                }
            }
            inventoryShowing = true;
        }
        else
        { //remove inventory
            getWorld().removeObjects(inventoryObjects); //remove all objects relating to the inventory
            inventoryShowing = false;
            inventoryObjects = new ArrayList(0);
        }
    }
}
It sort of works. When I click on a clue, it disappears and is added to the list. Then, when I press 'x', the inventory shows. The small grey boxes aren't inside the bigger maroon background, though. I also had to remove the scale because there would've been a syntax error if I didn't. When I press x, sometimes the maroon background (with the grey boxes and the clues) shows up, but sometimes it doesn't. When it does show up, it won't always stay shown if I release the key x. I fixed this by letting the maroon background (with the grey boxes and the clues) disappear when I clicked the inventory instead of having the key x pressed twice. Actually, what I had in mind was that the clues would appear beside my Inventory object, which is in the lower left portion of the screen. They would show up without a background or slots, but I want them to show up beside each other when x is pressed after the clues were clicked. Here's what I tried to do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void showInventory()
    {
        if(!inventoryShowing)
        {
            int i = 0, numItems = collectedObjects.size();
 
            for(i = 0; i < 10; i++) //I copied this line from a separate discussion. I don't know what it means.
            {
                if (i < numItems)
                {
                    Actor item = collectedObjects.get(i);
                    item.setImage(new GreenfootImage(item.getImage())); //.scale(10, 10));
                    getWorld().addObject(item, _x_, getY()); //I don't know how to make it so that the next clue goes beside the last
                    inventoryObjects.add(item);
                }
            }
            i++;
        }
        inventoryShowing = true;
    }
How do I make the clues show up to the right of the last clue?
danpost danpost

2017/2/27

#
Line 13: If 'initX' is the x-coordinate of the first clue and 'gap' is how far to the right you want the next clue, then '_x_' would be 'initX+gap*i'. Line 7: This page of the java tutorials explains the 'for' loop.
Super_Hippo Super_Hippo

2017/2/28

#
For the scale problem: Instead of
1
item.setImage(new GreenfootImage(item.getImage()).scale(20, 20));
use
1
2
3
GreenfootImage itemImage = new GreenfootImage(item.getImage());
itemImage.scale(20, 20);
item.setImage(itemImage);
//I don't know how to make it so that the next clue goes beside the last
That's what I tried to do with line 71. Maybe you have to change both of the 100 to 80 (or to img.getWidth()/2 and img.getHeight()/2. Iirc, I gave the inventory a size of 200/200 first and used half size to subtract from the middle of the world (=top left edge of the image). You probably also have to add half of the itemImage size...
1
getWorld().addObject(item, getWorld().getWidth()/2-img.getWidth()+10+column*30+itemImage.getWidth()/2, getWorld().getHeight()/2-img.getHeight()+10+row*30+itemImage.getHeight()/2);
Do the same change with line 65. If you understand this line, then you know what to change to change the position after seeing the result.
danpost danpost

2017/2/28

#
Super_Hippo wrote...
For the scale problem: Instead of
1
item.setImage(new GreenfootImage(item.getImage()).scale(20, 20));
use
1
2
3
GreenfootImage itemImage = new GreenfootImage(item.getImage());
itemImage.scale(20, 20);
item.setImage(itemImage);
More simply, use:
1
item.getImage().scale(20, 20);
SallySanban SallySanban

2017/3/1

#
Hello again! Sorry for the late reply. The clues now go in order once I click on them. Here is what I used:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void showInventory()
    {
        if(!inventoryShowing)
        {
            int i = 0, numItems = collectedObjects.size();
 
            for(i = 0; i < numItems; i++)
            {
                Actor item = collectedObjects.get(i);
                item.setImage(new GreenfootImage(item.getImage())); //.scale(10, 10));
                int xItem = (i + 2) * 60;
                getWorld().addObject(item, xItem, getY());
                inventoryObjects.add(item);
            }
            i++;
        }
        inventoryShowing = true;
    }
However, when I reset the world, the clues are still shown when I press 'x'. Does anyone know how I can fix this?
Super_Hippo Super_Hippo

2017/3/1

#
Did you, for some reason, make the collectedObjects list static?
SallySanban SallySanban

2017/3/2

#
No. It doesn't work whether or not I make the list static.
danpost danpost

2017/3/2

#
SallySanban wrote...
No. It doesn't work whether or not I make the list static.
What exactly is the problem? Are you wanting that the inventory list retain the objects that have been added to it and not that the inventory list be empty when you reset the world?
Nosson1459 Nosson1459

2017/3/2

#
SallySanban wrote...
However, when I reset the world, the clues are still shown when I press 'x'. Does anyone know how I can fix this?
danpost danpost

2017/3/2

#
Nosson1459 wrote...
However, when I reset the world, the clues are still shown when I press 'x'. Does anyone know how I can fix this?
I think my question is related and should be answered before a fix can be recommended.
SallySanban SallySanban

2017/3/2

#
I would like the inventory list to retain the objects as long as the clues were already clicked. When I reset the World, the clues are still in the inventory list as if the game hadn't restarted, and if this happens, it'd be like the clues were already collected without the player clicking on them.
Nosson1459 Nosson1459

2017/3/2

#
danpost wrote...
Nosson1459 wrote...
However, when I reset the world, the clues are still shown when I press 'x'. Does anyone know how I can fix this?
I think my question is related and should be answered before a fix can be recommended.
I answered your question, I didn't recommend a fix.
SallySanban wrote...
However, when I reset the world, the clues are still shown when I press 'x'. Does anyone know how I can fix this?
SallySanban wrote...
I would like the inventory list to retain the objects as long as the clues were already clicked. When I reset the World, the clues are still in the inventory list as if the game hadn't restarted, and if this happens, it'd be like the clues were already collected without the player clicking on them.
Why are they different? I quoted the first one.
There are more replies on the next page.
1
2
3
4