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

2016/3/6

How can one actor do something, wait a second and then do something else?

TheTimon TheTimon

2016/3/6

#
Hey, I'm writing a game "Mr.Oops" like and want to have arrows popping up, being there for a second or so and then disappearing and creating another object, a cannon ball. I have no idea how to do that. The delay method delays the whole execution and with a timer I don't see a way of doing this. I think the code is written quite poorly, but I hope it is still possible. Thank you for your time.
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
public class Arrowup extends Object
{
    private SimpleTimer timer = new SimpleTimer();
    private GreenfootImage bildup = new GreenfootImage("Arrowup.png");
    private GreenfootImage bilddown = new GreenfootImage("Arrowdown.png");
    private GreenfootImage bildleft = new GreenfootImage("Arrowleft.png");
    private GreenfootImage bildright = new GreenfootImage("Arrowright.png");
    public void act()
    {
         
        if (Greenfoot.getRandomNumber(50)==7)Arrow(); // I don't want the method to be executed with every act
    
     public void Arrow()
    {
        //if (Greenfoot.getRandomNumber(20)==7) { ignore this
        int i=Greenfoot.getRandomNumber(4);
        int j=Greenfoot.getRandomNumber(10);
        int k=Greenfoot.getRandomNumber(6);
         
        if(i==0) //on which side the arrow shall appear
        {
             
            World OopsWorld=getWorld();
            Arrowup arrowdown = new Arrowup();
            OopsWorld.addObject(arrowdown,(j*60+30) ,30);
            arrowdown.setImage(bilddown);
            getWorld().removeObject(this);
            //if (timer.millisElapsed() > 1000
            Rocket rocket = new Rocket();
            OopsWorld.addObject(rocket, j*60+30, 30);
            rocket.setRotation(90);
             
        }
        if(i==1)
        {
             
            World OopsWorld=getWorld();
            Arrowup arrowup = new Arrowup();
            OopsWorld.addObject(arrowup,(j*60+30) ,570);
            arrowup.setImage(bildup);
            //timer.mark();
            //if (timer.millisElapsed() > 1000)
            getWorld().removeObject(this);
            Rocket rocket = new Rocket();
            OopsWorld.addObject(rocket, j*60+30, 570);
            rocket.setRotation(270);
        }
        if(i==2)
        {
             
            World OopsWorld=getWorld();
            Arrowup arrowright = new Arrowup();
            OopsWorld.addObject(arrowright,30 ,(j*60+30));
            arrowright.setImage(bildright);
            //timer.mark();
            //if (timer.millisElapsed() > 1000)
            getWorld().removeObject(this);
            Rocket rocket = new Rocket();
            OopsWorld.addObject(rocket, 30, j*60+30);
             
        }
         
        if(i==3)
        {
             
            World OopsWorld=getWorld();
            Arrowup arrowleft = new Arrowup();
            OopsWorld.addObject(arrowleft,570 ,(j*60+30));
            arrowleft.setImage(bildleft);
           //timer.mark();
            //if (timer.millisElapsed() > 1000)
            getWorld().removeObject(this);
           Rocket rocket = new Rocket();
            OopsWorld.addObject(rocket, 570, j*60+30);
            rocket.setRotation(180);
        }
     
}
Super_Hippo Super_Hippo

2016/3/6

#
You should not create new 'Arrowup's from the 'Arrowup' class.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// in the world class
public void act()
{
    if (r(50) == 0) addArrow();
}
 
public void addArrow()
{
    switch(r(4))
    {
        case 0: addObject(new Arrow(0), r(10)*60+30, 30); break;
        case 1: addObject(new Arrow(1), r(10)*60+30, 570); break;
        case 2: addObject(new Arrow(2), 30, r(10)*60+30); break;
        case 3: addObject(new Arrow(3), 570, r(10)*60+30); break;
    }
}
 
//so it is not needed to write the long method name all the time
private int r(final int s)
{
    return Greenfoot.getRandomNumber(s);
}
Then you have something like this in the Arrow class
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
private int timer = 60;
private int direction;
private static GreenfooImage images[] = new GreenfootImage[]
{
    new GreenfootImage("Arrowdown.png"),
    new GreenfootImage("Arrowup.png"),
    new GreenfootImage("Arrowright.png"),
    new GreenfootImage("Arrowleft.png")
};
 
public Arrow(int dir)
{
    direction = dir;
    setImage(images[direction]);
}
 
public void act()
{
    timer--;
    if (timer == 0)
    {
        Actor rocket = new Rocket();
        getWorld().addObject(rocket, getX(), getY());
        rocket.setRotation(((direction*2+1)%5)*90); //would be easier if i = 0..3 would be clockwise or counterclockwise
        getWorld().removeObject(this);
    }
}
Isn't it possible to use just one arrow image and turn the actor?
TheTimon TheTimon

2016/3/6

#
Thank you, this looks much better, however I get this error now: "constructer Arrow in class Arrow cannot be applied to given types; required: no arguments fount: int reason: actual and formal arguments lists differ in length" And I have another problem, where my rocket doesn't correctly removes my person (the player), because of this error message: java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:695) at greenfoot.Actor.getOneObjectAtOffset(Actor.java:897) at Object.destroy(Object.java:45) at Rocket.tryToDestroyPerson(Rocket.java:24) at Rocket.act(Rocket.java:19) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205) The code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Rocket extends Object
{
    /**
     * Act - do whatever the Rocket wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        move(10);
        if (atWorldEdge() == true) getWorld().removeObject(this);
        tryToDestroyPerson();
        // Add your action code here.
    }
   void tryToDestroyPerson() {
        
       destroy (Person.class);
    }
}
And I suppose I could turn the actor but if it works..
TheTimon TheTimon

2016/3/6

#
Okay so now I have split the Arrow class up in 4 individual classes, where I assign everyone of the the direction and their image, this works now.
Super_Hippo Super_Hippo

2016/3/6

#
You really don't have to split them up. For the first problem, you need to use 'new Arrow(a number)' instead of 'new Arrow()' to create a new arrow. For the second problem, call the 'tryToDestroyPerson' method before line 10. You can also change the name of the method to 'removeTouching(Person.class)' and remove the other method if it does the same.
TheTimon TheTimon

2016/3/6

#
Alright it works, thank you very much. Now I want to do a different level, where instead of rocket lasers are fired and in a way, that in an instant a whole row is filled up and if the person is in that row then the person dies. Is this possible and if it is possible, how?
danpost danpost

2016/3/6

#
TheTimon wrote...
Alright it works, thank you very much. Now I want to do a different level, where instead of rocket lasers are fired and in a way, that in an instant a whole row is filled up and if the person is in that row then the person dies. Is this possible and if it is possible, how?
Of course, it is possible. Just create a subclass of Actor called Laser and add the implementation to it (put code in the class to have it do what you want).
You need to login to post a reply.