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

2017/5/24

Saving counter value over worlds... again.

OKNEM OKNEM

2017/5/24

#
Hey, it's me again. I have the same problem now as before. My counter value isn't saving over worlds. I've got a NullPointerException at this line:
1
((SpaceCounter)level2a.getObjects(SpaceCounter.class).get(0)).setValue(spacecounter.getValue());
I want the SpaceCounter value from level2 to be saved into level2a, and the value of level2a to be put in level2b. In Rocket :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
private SpaceCounter spacecounter;
 
if(atWorldEdge())
        {
            if(getWorld() instanceof level2)
            {
                level2a level2a = new level2a();
                ((SpaceCounter)level2a.getObjects(SpaceCounter.class).get(0)).setValue(spacecounter.getValue());
                Greenfoot.setWorld(level2a);
            }
            if(getWorld() instanceof level2a)
            {
                level2b level2b = new level2b();
                ((SpaceCounter)level2b.getObjects(SpaceCounter.class).get(0)).setValue(spacecounter.getValue());
                Greenfoot.setWorld(level2b);
            }
            if(getWorld() instanceof level2b)
            {
                marslevel mw = new marslevel();
                Greenfoot.setWorld(mw);
            }
        }
In level2a prepare method:
1
2
3
SpaceCounter spacecounter2 = new SpaceCounter();
        addObject(spacecounter2,57,32);
        spacecounter2.setLocation(56,28);
And in SpaceCounter:
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
87
88
89
90
91
92
93
94
95
96
97
98
99
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
 
 
public class SpaceCounter extends Actor
{
    private static final Color transparent = new Color(0,0,0,0);
    private GreenfootImage background;
    private int value;
    private int target;
private int delay = 60;
    /**
     * Create a new counter, initialised to 0.
     */
    public SpaceCounter()
    {
        background = getImage();  // get image from class
        value = 60;
        target = 60;
        updateImage();
    }
     
    /**
     * Animate the display to count up (or down) to the current target value.
     */
    public void act()
    {
         
         
        if(getWorld() instanceof level2)
        {
            if(delay>0)delay--;
            if(delay==0)
            {
                value--;
                updateImage();
                delay = 60;
            }
        }
        if(getWorld() instanceof level2a)
        {
            if(delay>0)delay--;
            if(delay==0)
            {
                value--;
                updateImage();
                delay = 60;
            }
        }
        if(getWorld() instanceof level2b)
        {
            if(delay>0)delay--;
            if(delay==0)
            {
                value--;
                updateImage();
                delay = 60;
            }
        }
    }
 
    /**
     * Add a new score to the current counter value.
     */
    public void add(int score)
    {
        target += score;
    }
 
    /**
     * Return the current counter value.
     */
    public int getValue()
    {
        return value;
    }
 
    /**
     * Set a new counter value.
     */
    public void setValue(int newValue)
    {
        target = newValue;
        value = newValue;
        updateImage();
    }
 
    /**
     * Update the image on screen to show the current value.
     */
    private void updateImage()
    {
        GreenfootImage image = new GreenfootImage(background);
        GreenfootImage text = new GreenfootImage("" + value, 22, Color.BLACK, transparent);
        image.drawImage(text, (image.getWidth()-text.getWidth())/2,
        (image.getHeight()-text.getHeight())/2);
        setImage(image);
    }
}
I set the default value of SpaceCounter as 60, and I implemented a feature of the first stage that doesn't allow you to pass into level2 without a counter value of 60. I did this as I couldn't get the Counter to save from Myworld3 to level2. Any ideas? Thanks heaps. P.S. Sorry for my indentation issues, I really don't do much about that until the occasional Ctrl-Shift-I.
danpost danpost

2017/5/24

#
You could try out my new ScoreControl class; however, it looks like that would take a lot of work to change the class over. On the other hand, it is quite a hassle passing the value from world to world. The way my new class works, is that the control is static and holds one counter value. It also creates an actor to display the value if needed. The class is located in my Combo Support Class Demo scenario; but, I will show a more generic version of it here (to use GreenfootImage objects instead of TextImage objects):
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
/**
 * CLASS:  ScoreControl
 * AUTHOR: danpost (greenfoot.org username)
 * CREATED: May 11, 2017
 *
 * DESCRIPTION:
 * This class controls the score value and the actor that displays it in such a way that
 * the content is easily accessible by multiple worlds without the need to pass the data
 * between the worlds.
 */
import greenfoot.*;
import java.awt.Color;
  
public final class ScoreControl
{
    private static int score; // the score field
    private static Actor scoreDisplay; // the display actor
     
    // (internal method) updates the image of the display actor; creates a display actor first if needed
    private static void updateDisplay()
    {
        // create actor if needed
        if (scoreDisplay == null) scoreDisplay = new ScoreDisplay();
        // set image of actor
        scoreDisplay.setImage(new GreenfootImage("Score: "+score, 22, Color.BLACK, new Color(0, 0, 0, 0)));
    }
     
    // adds display actor into a given world; can also be used to re-locate actor
    public static void addToWorld(World world, int x, int y)
    {
        updateDisplay();
        removeFromWorld(world);
        world.addObject(scoreDisplay, x, y);
    }
     
    // removes display actor from a given world
    public static void removeFromWorld(World world)
    {
        if (scoreDisplay.getWorld() == world) world.removeObject(scoreDisplay);
    }
     
    // assigns a given value to the score field and updates the image of the display actor
    public static void setScore(int value)
    {
        score = value;
        updateDisplay();
    }
     
    // allows access to the value of the score field
    public static int getScore()
    {
        return score;
    }
     
    // allows a given amount to be added to the score value; updates the display actor image
    public static void add(int amount)
    {
        score += amount;
        updateDisplay();
    }
     
    // (internal class) class for an immovable actor that will display the score value
    private static class ScoreDisplay extends Actor
    {
        public void setLocation(int x, int y) {}
    }
}
Review the public methods within the class. Notice that they are all 'static' in nature. You can call any of these method on the class name -- meaning that any and all classes have access to the methods. Example codes follow:
1
2
3
4
5
6
7
8
9
// in world constructor
ScoreControl.setScore(0); // initialize score (only put in first world)
ScoreControl.addToWorld(this, 100, 20); // add to any given world
 
// when score (regardless of where)
ScoreControl.add(10);
 
// in world act method
if (ScoreControl.getScore() >= 100) Greenfoot.setWorld(new NextLevel());
You need to login to post a reply.