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

2016/12/26

Help for a school Game

Paswalt Paswalt

2016/12/26

#
Hello everyone! I made a post like this before but I can't find it through my own profile. I will try to sum up my problem because I can show you guys my code now. I have unlimited enemys which are created from my world. They go from the top to the bottom and I want them to: -Disappear when they reach the edge -Disappear when the Player hits them 3 times So I tried out this:
import java.util.*;
import greenfoot.*;
import java.awt.Color;

/**
 * 
 */
public class CopyOfEnemy extends Actor
{
    private int hit = 0;

    /**
     * 
     */
    public CopyOfEnemy()
    {
        this.setRotation(-90);
    }

    /**
     * Act Method
     */
    public void act()
    {
        move(-3);
        treffer();
    }

    /**
     * Destroys the enemy when
     */
    public void treffer()
    {
        if (hit < 3) {
            if (isTouching(Schuss.class)) {
                removeTouching(Schuss.class);
                hit = hit + 1;
            }
        }
        else {
            this.getWorld().removeObject(this);
        }
        if (this.isAtEdge()) {
            getOneIntersectingObject(CopyOfEnemy.class);
            this.getWorld().removeObject(this);
        }
    }
}
Now everytime they reach the edge they'll disappear like I wanted to but if I shoot them I get this 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:711)
I'm not a genius in things like these. I really hope that I can make my game and don't fail the whole thing because we get a grade for it :/ but like I said this is really really hard for me so it would be cool if you guys could lend me a hand!
danpost danpost

2016/12/26

#
You just need to rearrange your code a bit. As it is now, line 43 will fail on any act cycle that the actor is hit a third time because you remove the actor from the world. Its location in the world is meaningless, which 'isAtEdge' is trying to work with. Anyways, it is almost always best to check a condition immediately after a change in any value of that condition. So, instead of asking if 'hit < 3' first, ask if 'hit == 3' immediately after you increase the value of 'hit'. The other thing is that you have two possible situations (or set of conditions) for when a CopyOfEnemy object is removed from the world -- when third hit occurs or when at edge of world. You can combine these conditions into one statement:
if (isTouching(Schuss.class)) {
    removeTouching(Schuss.class);
    hit = hit + 1;
}
if (hit == 3 || isAtEdge()) {
    getWorld().removeObject(this);
}
Paswalt Paswalt

2016/12/26

#
Oh my god thank you really much it worked! My code was kinda messy there I guess... I tried many different things out (commands where I didn't even know the purpose). A small question at the end: is there a way to make a variable that exists in the world and at the same time in the enemy class ? For example the variable "counter" should do +1 when an enemy spawned and -1 if an enemy is destroyed(to limit the amount of enemys). Or is there a way to count all of the enemys that are currently at the world and set a limit directly in the world? Anyway I'm really grateful!
danpost danpost

2016/12/26

#
The World class method 'getObjects(Class)' returns list of objects of the given class. The List class has a 'size' method to get the number of elements in a list. So (in general terms):
if (getObjects(Enemy.class).size() < maxEnemyCount && spawnChance() == true) spawnEnemy();
Paswalt Paswalt

2016/12/27

#
Thanks I worked quite a lot on it now. But now I have to face another problem. I wanted to to a simple score counter somewhere on the world. So I gave the projectile that the player can shoot with space this:
import java.util.*;
import greenfoot.*;
import java.awt.Color;

/**
 * 
 */
public class CopyOfSchuss extends Actor
{
    private static int score = 0;

    /**
     * 
     */
    public CopyOfSchuss()
    {
        setRotation(-90);
    }

    /**
     * Act Methode
     */
    public void act()
    {
        score();
        bewegung();
    }

    /**
     * CopyOfSchuss bewegung(movement)
     */
    public void bewegung()
    {
        this.move(10);
        this.setRotation(-90);
        if (this.isAtEdge()) {
            this.getWorld().removeObject(this);
        }
    }

    /**
     * Erhöht die Punkteanzahl(score goes up)
     */
    public void score()
    {
        this.getWorld().showText("Score " + score, 400, 400);
        if (isTouching(Enemy.class) || isTouching(Enemy2.class)) {
            score = score + 1;
        }
    }
}
Whenever I hit an Enemy the score still remains zero. Is it because both Enemy classes remove the projectile after they are touching?
danpost danpost

2016/12/27

#
Paswalt wrote...
Is it because both Enemy classes remove the projectile after they are touching?
Most probably. Remove the call to 'score' from the act method above and remove the 'score' method as well. Then, add the following methods to the CopyOfSchuss class:
public static int getScore()
{
    return score;
}

public static void adjustScore(int amout)
{
    score = score + amount;
}
Finally, in the Enemy and Enemy2 classes, you can do this when removing the bullet:
CopyOfSchuss.adjustScore(1);
getWorld().showText("Score "+CopyOfSchuss.getScore(), 400, 400);
((CopyOfSchuss)getOneIntersectingObject(CopyOfSchuss.class)).score();
Paswalt Paswalt

2016/12/28

#
Thank you it worked like always! I have a few questions about this. When I want to use a method from another class you can simply write Classname.Method() ? Can I use the score variable in my world like for example the player scores 1000 points and then enemys stop spawning and a boss will spawn. And my last question (probably for a long time) I added a powerup (a rocket). The player can shoot this rocket and if the player hits a normal enemy it should remove all of them from the world. But only from the same type (I have enemy 1,2,3 now).
danpost danpost

2016/12/28

#
Paswalt wrote...
When I want to use a method from another class you can simply write Classname.Method() ?
Only for static (class) field -- not for instance fields. Be aware that class fields only reset when the project is recompiled -- not when it is reset.
Can I use the score variable in my world like for example the player scores 1000 points and then enemys stop spawning and a boss will spawn.
You can use 'CopyOfSchusss.getScore()' from ANY class within the project.
And my last question (probably for a long time) I added a powerup (a rocket). The player can shoot this rocket and if the player hits a normal enemy it should remove all of them from the world. But only from the same type (I have enemy 1,2,3 now).
There is a question about this here? The Actor class 'getWorld' method returns a World object; the World class 'getObjects(Class)' method returns a List object listing the objects in the world of the specified type; The List class 'get(int)' method returns an element from the list returning an Object object. The Object class 'getClass' method returns a Class object specifying the class of the object. You can compare the class of each element in the list with the class of the enemy that was actually hit
You need to login to post a reply.