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

2019/4/23

Laser Limit

Celesterra Celesterra

2019/4/23

#
I want to make a laser limit in this scenario, but I can't figure out how to get it to work. Here is the code for the laser limit and the rocket. Relevant Rocket Code:
public class Rocket extends Actor
{
    //Variables used later
    private int speed = 3;
    public boolean shooting = false;
    
    LaserLimit limit = new LaserLimit();
    private int lasers = limit.lasers;
    
    public void act() 
    {
        checkKeys();
        cheats();
        
        if(cheatEnabled == true)
        {
            rapidFire();
        }
        
        if(cheatEnabled == false)
        {
            if(lasers > 0)
            {
                shootWithSpace();
            }
            
            if(lasers == 0)
            {
                if(Greenfoot.isKeyDown("space") && !shooting)
                {
                    shooting = true;
                }
            
                if(!Greenfoot.isKeyDown("space"))
                {
                    shooting = true;
                }
            }
        }
    }    
    
    private void shootWithSpace()
    {
        //If the spacebar is pressed, a laser is fired
        if(Greenfoot.isKeyDown("space") && !shooting)
        {
            getWorld().addObject(new Laser(), getX(), getY());
            Greenfoot.playSound("pew.mp3");
            Galaxy world = (Galaxy) getWorld();
            world.updateLimit();
            shooting = true;
        }
        
        //If the space bar isn't pressed, reset the shooting variable to false
        if(!Greenfoot.isKeyDown("space"))
        {
            shooting = false;
        }
    }
LaserLimit Code:
public class LaserLimit extends Actor
{
    //Variables used later
    public int lasers = 30;
    
    public LaserLimit()
    {
        //creates the image of the laser counter
        GreenfootImage img = new GreenfootImage(100, 30);
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: " + lasers, 5, 25);
        setImage(img);
    }
    
    public void lasersLeft() 
    {
        lasers = lasers - 1;
        
        //Recreates the image of the laser counter if there are still lasers
        GreenfootImage img = getImage();
        img.clear();
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: " + lasers, 5, 25);
    }
    
    public void rapidFire()
    {
        //Recreates the image of the laser counter to infinity once the rapid fire cheat is enabled
        GreenfootImage img = getImage();
        img.clear();
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: ∞", 5, 25);
    }
}
The entire code works, I just can't seem to get the lasers to stop firing once the counter reaches 0. I have tried a variety of methods to try and get it to work. Thanks in advance to anyone who can help me!
danpost danpost

2019/4/23

#
You are creating a LaserLimit object in the Rocket class, yet, for some reason, you go to the Galaxy world object to updateLimit. This most probably has something to do with your issue. Maybe you are creating a second LaserLimit object there.
Celesterra Celesterra

2019/4/23

#
I changed the code a bit, so it wouldn't make a new LaserLimit, but I have a java.lang.NullPointerException on my if statement of (limit.lasers > 0) Here is said code:
LaserLimit limit;
    
    public void act() 
    {
        checkKeys();
        cheats();
        
        if(cheatEnabled == true)
        {
            rapidFire();
        }
        
        if(cheatEnabled == false)
        {
            if(limit.lasers > 0)
            {
                shootWithSpace();
            }
            
            if(limit.lasers == 0)
            {
                if(Greenfoot.isKeyDown("space") && !shooting)
                {
                    shooting = true;
                }
            
                if(!Greenfoot.isKeyDown("space"))
                {
                    shooting = true;
                }
            }
        }
    }
LaserLimit is in the variable limit. Now, why is it giving me a NullPointerException?
danpost danpost

2019/4/23

#
Celesterra wrote...
LaserLimit is in the variable limit. Now, why is it giving me a NullPointerException?
You still have to assign your LaserLimit object to the field, limit, in line 1. Currently, all line 1 does is declare the field to hold a LaserLimit object.
Celesterra Celesterra

2019/4/23

#
How would I do that? Sorry, I am fairly new to programming with Greenfoot.
Nosson1459 Nosson1459

2019/4/24

#
I didn't really look over your code but I think what danpost is trying to say is that your 'limit' variable was never initialized, meaning you never did this:
LaserLimit limit=new LaserLimit();
danpost danpost

2019/4/24

#
Nosson1459 wrote...
I didn't really look over your code but I think what danpost is trying to say is that your 'limit' variable was never initialized, meaning you never did this: << Code Omitted >>
The object assigned cannot be a new one. It must be the one created in and added to the world.
Celesterra Celesterra

2019/4/24

#
Ok, I tried to instead make both the Rocket and LaserLimit class to access the same variable from the world (Galaxy). I have looked into early discussions on this and have copied it practically word for word but I STILL get a NullPointerException error. The terminal window is saying that what is typed below is the issue, but I don't see why it is an issue: int lasers = ((Galaxy) getWorld()).lasers
Celesterra Celesterra

2019/4/24

#
And I do have a semicolon (;) after it.
danpost danpost

2019/4/24

#
Celesterra wrote...
I tried to instead make both the Rocket and LaserLimit class to access the same variable from the world (Galaxy). I have looked into early discussions on this and have copied it practically word for word but I STILL get a NullPointerException error. The terminal window is saying that what is typed below is the issue, but I don't see why it is an issue: int lasers = ((Galaxy) getWorld()).lasers
Please show where you have this line. (show the entire class so you can be instructed where it goes if it has to be moved)
Celesterra Celesterra

2019/4/24

#
Rocket:
public class Rocket extends Actor
{
    //Variables used later
    private int speed = 3;
    private boolean cheatEnabled = false;
    private boolean shooting = false;
    int lasers = ((Galaxy) getWorld()).lasers;
    
    public void act() 
    {
        checkKeys();
        cheats();
        
        if(cheatEnabled == true)
        {
            rapidFire();
        }
        
        if(cheatEnabled == false)
        {
            if(lasers > 0)
            {
                shootWithSpace();
            }
            
            if(lasers == 0)
            {
                if(Greenfoot.isKeyDown("space") && !shooting)
                {
                    shooting = true;
                }
            
                if(!Greenfoot.isKeyDown("space"))
                {
                    shooting = true;
                }
            }
        }
    }    
    
    private void checkKeys()
    {
        //If the up arrow key is pressed, the rocket moves up
        if(Greenfoot.isKeyDown("up"))
        {
            setLocation(getX(), getY()-speed);
        }
        
        //if the down arrow key is pressed, the rocket moves down
        if(Greenfoot.isKeyDown("down"))
        {
            setLocation(getX(), getY()+speed);
        }
        
        //If the right arrow key is pressed, the rocket moves forward
        if(Greenfoot.isKeyDown("right"))
        {
            setLocation(getX()+speed, getY());
        }
        
        //if the left arrow key is pressed, the rocket moves backwards
        if(Greenfoot.isKeyDown("left"))
        {
            setLocation(getX()-speed, getY());
        }
    }
    
    private void shootWithSpace()
    {
        //If the spacebar is pressed, a laser is fired
        if(Greenfoot.isKeyDown("space") && !shooting)
        {
            getWorld().addObject(new Laser(), getX(), getY());
            Greenfoot.playSound("pew.mp3");
            Galaxy world = (Galaxy) getWorld();
            world.updateLimit();
            shooting = true;
        }
        
        //If the space bar isn't pressed, reset the shooting variable to false
        if(!Greenfoot.isKeyDown("space"))
        {
            shooting = false;
        }
    }
    
    private void cheats()
    {
        //If rapid is typed into cheat bar (accessed through shift + c), enable rapid fire
        if(Greenfoot.isKeyDown("shift") && Greenfoot.isKeyDown("c") && cheatEnabled == false)
        {
            if("rapid".equals(Greenfoot.ask("Enter cheat code:")))
            {
                cheatEnabled = true;
                Galaxy world = (Galaxy) getWorld();
                world.noLimit();
            }
        }
    }
    
    private void rapidFire()
    {
        //If the rapid fire cheat is enabled, lasers will be fired rapidly
        if(Greenfoot.isKeyDown("space") && !shooting)
        {
            getWorld().addObject(new Laser(), getX(), getY());
            Greenfoot.playSound("pew.mp3");
            shooting = false;
        }
        
        //If the space bar isn't pressed, reset the shooting variable to false
        if(!Greenfoot.isKeyDown("space"))
        {
            shooting = false;
        }
    }
}
LaserLimit:
public class LaserLimit extends Actor
{
    //Variables used later 
    int lasers = ((Galaxy) getWorld()).lasers;
    
    public LaserLimit()
    {
        //creates the image of the laser counter
        GreenfootImage img = new GreenfootImage(100, 30);
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: " + lasers, 5, 25);
        setImage(img);
    }
    
    public void lasersLeft() 
    {
        lasers = lasers - 1;
        
        //Recreates the image of the laser counter if there are still lasers
        GreenfootImage img = getImage();
        img.clear();
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: " + lasers, 5, 25);
    }
    
    public void unlimited()
    {
        //Recreates the image of the laser counter to infinity once the rapid fire cheat is enabled
        GreenfootImage img = getImage();
        img.clear();
        img.setColor(Color.WHITE);
        img.drawString("Lasers Left: ∞", 5, 25);
    }
}
And just in case, the World:
public class Galaxy extends World
{
    //Variables used later
    private Scoreboard sb;
    private Lives life;
    private Rocket rocket;
    private LaserLimit limit;
    public int lasers = 30;
    
    public Galaxy()
    {
        // Create a new world with 800x600 cells with a cell size of 1x1 pixels.
        super(800, 600, 1);
        prepare();
    }
    
    private void prepare()
    {
        // Creates the black background of the galaxy
        GreenfootImage bg = new GreenfootImage(800, 600);
        bg.fill();
        setBackground(bg);
        
        //Spawns in the stars of the Galaxy
        addStars(800);
        
        //Spawns in the rocket 
        addObject(new Rocket(), 75, getHeight()/2);
        
        //Spawns lasers underneath the rocket
        setPaintOrder(Rocket.class, Laser.class);
        
        //Prevents delay of animation
        Explosion.initializeImages();
        
        //Spawns in the scoreboard
        sb = new Scoreboard();
        addObject(sb, 70, 570);
        
        //Spawns in the life counter
        life = new Lives();
        addObject(life, 140, 570);
        
        //Spawns in the laser counter
        limit = new LaserLimit();
        addObject(limit, 210, 570);
    }
    
    public void updateScore()
    {
        sb.changeScore();
    }
    
    public void updateLives()
    {
        //Changes the life counter and spawns in a new rocket
        life.changeLives();
        addObject(new Rocket(), 75, getHeight()/2);
    }
    
    public void updateLimit()
    {
        limit.lasersLeft();
    }
    
    public void noLimit()
    {
        limit.unlimited();
    }
    
    private void addStars(int n)
    {
        //Loop to add stars to the galaxy
        for(int s=0; s<n; s++)
        {
            int x = Greenfoot.getRandomNumber(getWidth());
            int y = Greenfoot.getRandomNumber(getHeight());
            addObject(new Star(), x, y);
        }
    }
    
    public void act()
    {
        //Spawns in asteroids at 0.5% of the time
        if(Greenfoot.getRandomNumber(1000) < 5)
        {
            addObject(new Asteroid(), getWidth()-5, Greenfoot.getRandomNumber(getHeight()));
        }
    }
}
danpost danpost

2019/4/24

#
You cannot use getWorld to access the world until the actor is in the world. Line 7 in Rocket and line 4 in LaserLimit should only declare the field. No assignment is possible at the time these actors are being created. These line should only be:
int lasers;
You could assign their values after the prepare method has completed by inserting the following at line 15 in your Galaxy class:
limit.lasers = this.lasers;
rocket.lasers = this.lasers;
However, it is never wise to have more than one field for any changing value as changing one will not change the others. Best would be to remove line 7 from Rocket and line 4 from LaserLimit and use the one in the world only. The actor classes can acquire its value at the time they need it. For example, you can use the following for line 21 in your Rocket class:
if (((Galaxy)getWorld()).lasers > 0)
Your LaserLimit class doing a lot of stuff that would be much more easily done in your world. Really all the class is doing is showing how many lasers remain. You could use a simple actor and let the world supply its image when needed (a method in your Galaxy class could acccomplish this:
public void updateLaserCounter()
{
    GreenfootImage img = new GreenfootImage(100, 30);
    img.setColor(Color.WHITE);
    img.drawString("Lasers left: "+(lasers == Integer.MAX_VALUE ? "∞" : lasers), 5, 25);
    limit.setImage(img);
}
Then:
public void noLimit()
{
    lasers = Integer.MAX_VALUE;
    updateLaserCounter();
}
should work. The class for the laser counter actor could simply be this:
public class SimpleActor extends greenfoot.Actor {}
created (in Galaxy) at line 45 with:
limit = new SimpleActor();
followed by a call to updateLaserCounter. and
public void updateLimit()
{
    if (lasers == Integer.MAX_VALUE) return;
    lasers--;
    updateLaserCounter();
}
should work for when a laser is fired. It might help if you check out my Value Display Tutorial scenario.
Celesterra Celesterra

2019/4/28

#
I got the laser limit to work! However, I have a minor issue. When the program starts, it just has a green foot as the image until the space bar is pressed (then it turns to the image it should be). How do I fix this?
danpost danpost

2019/4/28

#
Celesterra wrote...
I got the laser limit to work! However, I have a minor issue. When the program starts, it just has a green foot as the image until the space bar is pressed (then it turns to the image it should be). How do I fix this?
You just need to call updateLaserCounter from the Galaxy class constructor or prepare method.
Celesterra Celesterra

2019/4/28

#
Thank you very much!
You need to login to post a reply.