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

2019/1/10

Subtracting a value from a variable

CosmicCaleb CosmicCaleb

2019/1/10

#
Here is my code for a helicopter. The main method I'm worried about is heliDie(). In here, my idea was to make it so that the helicopter would die after 2 shots. But, instead of dying after 2 shots, it might be 3, or 7, or 8 shots.
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Helicopter here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Helicopter extends Actor
{
    boolean kill = true;
    public int heliHealth = 2;
    private int timer;
    boolean time = false;

    private int shoot;
    private int imageNumber = 1;
    private int count;
    GreenfootImage image = new GreenfootImage("r1.png");
    /**
     * Act - do whatever the Helicopter wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        setLocation(getX() -2, getY());
        setImage();
        shootBullet();
        heliDie();
        if (kill)
        {
            if (isAtEdge())
            {
                getWorld().removeObject(this);
            }
        }
    }  

    public void setImage()
    {
        image = new GreenfootImage("r" + imageNumber + ".png");

        if (count % 10 == 0)
            imageNumber++;
        if (imageNumber == 4)
        {
            imageNumber = 1;
        }
        {
            setImage(image);
        }
        count++;
    }

    public void shootBullet()
    {
        shoot++;
        if (shoot == 100)
        {
            getWorld().addObject(new Bullet(), getX() -100, getY());
            Greenfoot.playSound("Gunshot.wav");
            shoot = 0;
        }
    }

    public void heliDie()
    {
        if (kill)
        {
            if (isTouching(Tracking_Missile.class))
            {
                heliHealth-=1;
                kill = false;
                time = true;
                MyWorld world = (MyWorld)getWorld();
                //world.addScore(3);
                removeTouching(Tracking_Missile.class);
            }
        }
        if (time)
        {
            timer++;
        }
        if (timer == 5)
        {
            kill = true;
            time = false;
        }
        if (heliHealth == 0)
        {
            getWorld().addObject(new Death(), getX(), getY());
            getWorld().removeObject(this);
        }
    }
}
Zamoht Zamoht

2019/1/10

#
The code from this class seems to me like it should work. Is it possible to change heliHealth to a private variable? If not there may be other places in your program, where you change the value.
danpost danpost

2019/1/10

#
You are working with too many variables. Keep it simple. If you can find a way to reduce the number, do so. I doubt you need both kill and time (are they not always opposite each other -- when one is true, the other is false?). Also, I doubt you need both imageNumber and count (you can use mod arithmetic to combine them into one value). Then, I am wondering about the logic, checking for zero health would be better placed immediately after losing health. Also, in your setImage method, you unnecessarily create an image every act cycle whether you need to change it or not. Here is the simplified version:
import greenfoot.*;

public class Helicopter extends Actor
{
    private int shotTimer;
    private int imgTimer;
    private int hitTimer;
    private int health = 2;
    
    public Helicopter()
    {
        setImage("r1.png");
    }
    
    public void act()
    {
        // moving
        setLocation(getX()-2, getY());

        // setting image
        imgTimer = (imgTimer+1)%40;
        if (imgTimer%10 == 0) setImage("r"+(1+imgTimer/10)+".png");
        
        // shooting
        shotTimer = (shotTimer+1)%100;
        if (shotTimer == 0)
        {
            getWorld().addObject(new Bullet(), getX()-100, getY());
            Greenfoot.playSound("Gunshot.wav");
        }
        
        // hitting edge and getting hit
        if (isAtEdge()) getWorld().removeObject(this);
        else
        {
            if (hitTimer == 0)
            {
                if (isTouching(Tracking_Missile.class))
                {
                    removeTouching(Tracking_Missile.class);
                    if (--health == 0)
                    {
                        getWorld().addObject(new Death(), getX(), getY());
                        getWorld().removeObject(this);
                    }
                    else hitTimer = 5;
                }
            }
            else hitTimer--;
        }
    }
}
CosmicCaleb CosmicCaleb

2019/1/10

#
Zahmot, making the variable private didn't fix it. Danpost, while you have made my code concise, the problem is still not fixed. It takes a totally random amount of shots to kill the helicopter. Here is the code of the weapon that kills the helicopter, if it helps.
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Missile here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Tracking_Missile extends Actor
{
    boolean kill = true;
    private int imageNumber = 1;
    private int count;
    GreenfootImage image = new GreenfootImage("m1.png");
    /**
     * Act - do whatever the Missile wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        setLocation(getX() +15, getY());
        setImage();
        killActors();
        if (kill)
        {
            if(isAtEdge())
            {
                getWorld().removeObject(this);
            }
        }
    }  

    public void killActors()
    {
        if (kill)
        {
            if (isTouching(Bowser.class))
            {
                kill = false;
                getWorld().removeObject(this);
            }
        }
        if (kill)
        {
            if (isTouching(Helicopter.class))
            {
                kill = false;
                getWorld().removeObject(this);
            }
        }
        if (kill)
        {
            if (isTouching(Dino.class))
            {
                kill = false;
                removeTouching(Dino.class);
                MyWorld world = (MyWorld)getWorld();
                world.addObject(new Death(), getX(), getY());
                world.addScore(+3);
                Greenfoot.playSound("Death.wav");
                getWorld().removeObject(this);
            }
        }
        if (kill)
        {
            if (isTouching(Tank.class))
            {
                kill = false;
                removeTouching(Tank.class);
                MyWorld world = (MyWorld)getWorld();
                world.addObject(new Death(), getX(), getY());
                world.addScore(+3);
                Greenfoot.playSound("Death.wav");
                getWorld().removeObject(this);
            }
        }
    }

    public void setImage()
    {
        image = new GreenfootImage("m" + imageNumber + ".png");

        if (count % 10 == 0)
            imageNumber++;
        if (imageNumber == 5)
        {
            imageNumber = 1;
        }
        {
            setImage(image);
        }
        count++;
    }
}
CosmicCaleb CosmicCaleb

2019/1/10

#
Btw, danpost, how did you fix the problem where you get an error if you are removing an actor, but also at some point in your code, remove yourself. I had to fix it with my long boolean kill thing, but you didn't need that. How did you do it?
danpost danpost

2019/1/10

#
CosmicCaleb wrote...
Btw, danpost, how did you fix the problem where you get an error if you are removing an actor, but also at some point in your code, remove yourself. I had to fix it with my long boolean kill thing, but you didn't need that. How did you do it?
The key word that did it was "else" (line 34). There are other ways to prevent that error. One is by checking if the actor is still in the world:
if (getWorld() != null) ...
danpost danpost

2019/1/10

#
All you should have in the Tracking_Missile class is moving, animating and edge checking. All collisions with actors will be done by the other classes (Dino, Tank, Bowser and Helicopter):
import greenfoot.*;

public class Tracking_Missile.class extends Actor
{
    private int imgTimer;

    public void act()
    {
        // moving
        setLocation(getX()+15, getY());
        
        // setting image
        imgTimer = (imgTimer+1)%50;
        if (imgTimer%10 == 0) setImage("m"+(1+imgTimer/10)+".png");

        // hitting edge
        if (isAtEdge()) getWorld().removeObject(this);
    }
}
Zamoht Zamoht

2019/1/10

#
The problem seems to be that the missile will remove itself before the helicopter takes damage. Remove the part in your killActors() method where the missile is removed by touching the helicopter.
Zamoht Zamoht

2019/1/10

#
What danpost said :D
danpost danpost

2019/1/10

#
I was going to add the following to the class:
public Tracking_Missile()
{
    setImage("m1.png");
}
so the missile has an initial image.
You need to login to post a reply.