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

2023/4/14

I have a poison trap that I want to deal tick damage (damage overtime)

KCee KCee

2023/4/14

#
I have a "poison trap" that when an animal class comes into contact with it, it should blow up, have a poison cloud explosion occur, and then deal damage over time to any animal that came in contact with the cloud of poison. How would i implement something like this? Poison Trap code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;
/**
 * Write a description of class poisonTrap here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class poisonTrap extends Traps
{
    /**
     * Act - do whatever the poisonTrap wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public poisonTrap()
    {
        GreenfootImage image = getImage();
        image.scale(image.getWidth() - 160, image.getHeight() - 210);
        setImage(image);
    }
    
    public void checkHitAnimal()
    {
        ArrayList<Hunter> h = (ArrayList<Hunter>)getObjectsAtOffset(0,0, Hunter.class);
        if (h.size() > 0)
        {
            getWorld().addObject (new Poison(), this.getX(), this.getY());
            getWorld().removeObject(this);
        }
    }
    
    public void act()
    {
        checkHitAnimal();        
    }
}
Poison Cloud code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class poison here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Poison extends Effects
{
    /**
     * Act - do whatever the poison wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    GreenfootImage[] currAnim;
    int animTimer;
    private static final int frameDuration = 3;
    public Poison()
    {
        GreenfootImage[] poisonAni = new GreenfootImage[9];
        for (int i=0; i<9; i++)
        {
            poisonAni[i] = new GreenfootImage("ptile" + i + ".png");
            poisonAni[i].scale (100, 100);
        }
        setAnimation(poisonAni);
    }
    
    public void act()
    {
        //this.getImage().setTransparency(getImage().getTransparency() - 3); //slowly becomes transparent
        removeTouching(Hunter.class);
        setImage();
        /*if (hunter != null)
        {
            getWorld().removeObject(hunter);
        }
        
        if (this.getImage().getTransparency() < 5)
        {
            getWorld().removeObject(this);
        }*/
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() 
    {
        animTimer = (animTimer+1)%(frameDuration*currAnim.length);
        if (animTimer%frameDuration == 0) {
            if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
            setImage(currAnim[animTimer/frameDuration]);
        }
    }
}
Animal code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * The abstract class for all animals in the game
 * 
 * @author Jonathan
 * @version 0.1
 */
public abstract class Animal extends Actor
{
    private boolean isScared;
    protected int speed;
    protected int expDrop;
    protected int health;
    protected BetterGreenfootSound spawnSound;
    protected BetterGreenfootSound deathSound;

    /**
     * Act - do whatever the Animal wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        move();
    }

    public void addedToWorld(World world)
    {
        SoundManager.getInstance().playSound(spawnSound, SoundChannel.SFX);
        // Move to a random location within the bounds of the world
        setLocation(world.getWidth(), Greenfoot.getRandomNumber(69)); //TODO: Get proper bounds
    }

    /**
     * Moves the animal
     */
    protected void move()
    {
        // TODO: Default implementation of animal movement
        if (isScared)
        {
            // Move towards right of the screen and away from the hunters
        }
        else
        {
            // TODO
        }
    }

    /**
     * Scares the animal away from the hunter
     */
    public void scare()
    {
        isScared = true;
    }

    /**
     * Damages the animal by the amount specified
     * @param hunter The hunter that is damaging the animal
     * @param amount The amount of damage to deal
     */
    public void damage(Hunter hunter, int amount)
    {
        health -= amount;
        if (health <= 0)
        {
            die(hunter);
        }
    }

    /**
     * Kills the animal and rewards its killer
     * @param killer The animal's killer
     */
    public void die(Hunter killer)
    {
        killer.increaseExp(expDrop);
        SoundManager.getInstance().playSound(deathSound, SoundChannel.SFX);
        getWorld().removeObject(this);
    }
}
Additionally Id like my other type of trap, a landmine, to deal a set amount of damage to animals when it comes into contact with the explosion Landmine code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;

/**
 * Write a description of class Landmine here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Landmine extends Traps
{
    /**
     * Act - do whatever the Landmine wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public Landmine()
    {
        GreenfootImage image = getImage();
        image.scale(image.getWidth() - 150, image.getHeight() - 120);
        setImage(image);
    }
    
    public void checkHitAnimal()
    {
        ArrayList<Hunter> h = (ArrayList<Hunter>)getObjectsAtOffset(0,0, Hunter.class);
        if (h.size() > 0)
        {
            getWorld().addObject (new Explosion(), this.getX(), this.getY());
            getWorld().removeObject(this);
        }
    }
    
    public void act()
    {
        checkHitAnimal();        
    }
}
Explosion code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Explosion here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Explosion extends Effects
{
    GreenfootImage[] currAnim;
    int animTimer;
    private static final int frameDuration = 3;
    public Explosion()
    {
        GreenfootImage[] explosionAni = new GreenfootImage[10];
        for (int i=0; i<10; i++)
        {
            explosionAni[i] = new GreenfootImage("tile" + i + ".png");
            explosionAni[i].scale (100, 100);
        }
        setAnimation(explosionAni);
    }
    
    public void act()
    {
        //this.getImage().setTransparency(getImage().getTransparency() - 3); //slowly becomes transparent
        removeTouching(Hunter.class);
        setImage();
        /*if (hunter != null)
        {
            getWorld().removeObject(hunter);
        }
        
        if (this.getImage().getTransparency() < 5)
        {
            getWorld().removeObject(this);
        }*/
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() 
    {
        animTimer = (animTimer+1)%(frameDuration*currAnim.length);
        if (animTimer%frameDuration == 0) {
            if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
            setImage(currAnim[animTimer/frameDuration]);
        }
    }
}
All my traps are also under a trap superclass: Trap superclass code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Traps here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public abstract class Traps extends Actor
{
    /**
     * Act - do whatever the Traps wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    protected double damage;
    protected double durability;
    
    protected abstract void checkHitAnimal ();
    
    public void act()
    {
        
    }
}
danpost danpost

2023/4/14

#
KCee wrote...
I have a "poison trap" that when an animal class comes into contact with it, it should blow up, have a poison cloud explosion occur, and then deal damage over time to any animal that came in contact with the cloud of poison. How would i implement something like this? << Codes Omitted >>
Things you will need are (1) a list of animals currently touching; (2) a list of times when touching animals first started touching; and (3) a timer for determining when to deal damage. For the lists, you will need the following imports:
import java.util.List;
import java.util.ArrayList;
The field declarations of what are needed would be:
private List<Animal> animals = new ArrayList<Animal>();
private List<Integer> timeHit = new ArrayList<Integer>();
int actTimer;
Then, in act, or a method called by act, you will need the following code to control the contents of the lists (the intersecting animals, plus their matching times):
// remove animals no longer touching from lists
for (int i=0; i<animals.size(); i++) {
    if ( ! intersects(animals.get(i))) {
        animals.remove(i);
        timeHit.remove(i);
        i--;
    }
}
// add newly intersecting animals to lists
List<Animal> currTouching = (List<Animal>)getIntersectingObjects(Animal.class);
for (Animal animal : currTouching) {
    if ( ! animals.contains(animal) ) {
        animals.add(animal);
        timeHit.add(new Integer(actTimer));
    }
}
// deal damage to intersecting animals
for (int i=0; i<animals.size(); i++) {
    if ((actTimer-timeHit.get(i)%20 == 0) {
        animals.get(i).health--;
    }
}
KCee KCee

2023/4/18

#
The poison doesnt seem to be killing the animals. i tried adding if (health == 0) { getWorld().removeObject(this); } but then it just kills almost instantly poison code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.List;
import java.util.ArrayList;
/**
 * Write a description of class poison here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Poison extends Effects
{
    /**
     * Act - do whatever the poison wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    GreenfootImage[] currAnim;
    int animTimer;
    private List<Animal> animals = new ArrayList<Animal>();
    private List<Integer> timeHit = new ArrayList<Integer>();
    int actTimer;
    private static final int frameDuration = 3;
    public Poison()
    {
        GreenfootImage[] poisonAni = new GreenfootImage[9];
        for (int i=0; i<9; i++)
        {
            poisonAni[i] = new GreenfootImage("ptile" + i + ".png");
            poisonAni[i].scale (100, 100);
        }
        setAnimation(poisonAni);
    }
    
    public void act()
    {
        //removeTouching(Animal.class);
        setImage();
        if(getWorld() == null)
            return;
        for (int i=0; i<animals.size(); i++) 
        {
        if ( ! intersects(animals.get(i))) {
            animals.remove(i);
            timeHit.remove(i);
            i--;
        }
        }
        // add newly intersecting animals to lists
        List<Animal> currTouching = (List<Animal>)getIntersectingObjects(Animal.class);
        for (Animal animal : currTouching) 
        {
            if ( ! animals.contains(animal) ) 
            {
                animals.add(animal);
                timeHit.add(new Integer(actTimer));
            }
        }
        // deal damage to intersecting animals
        for (int i=0; i<animals.size(); i++) 
        {
            if ((actTimer-timeHit.get(i)%20 == 0))
            {
                animals.get(i).health--;
            }
        }
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() 
    {
        animTimer = (animTimer+1)%(frameDuration*currAnim.length);
        if (animTimer%frameDuration == 0) {
            if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
            setImage(currAnim[animTimer/frameDuration]);
        }
    }
}
Animal code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Hunter here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Animal extends Actor
{
    /**
     * Act - do whatever the Hunter wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public int health = 10;
    public Animal()
    {
        GreenfootImage image = getImage();
        image.scale(image.getWidth() - 260, image.getHeight() - 250);
        setImage(image);
    }
    
    public void act()
    {
        move(-2);
        if (health == 0)
        {
            getWorld().removeObject(this);
        }
    }
}
also how would i make the explosion do a flat amount of damage like maybe 20 dmg? i only want the explosion to hit once so it doesnt keep hitting the animal if its inside the explosion but already got hit once
danpost danpost

2023/4/19

#
KCee wrote...
The poison doesnt seem to be killing the animals. i tried adding << Code Omitted >> but then it just kills almost instantly poison code: << Code Omitted >>
Increasing the '20' to some higher value (maybe 100-200) at line 60 in the Poison class might do the trick.
also how would i make the explosion do a flat amount of damage like maybe 20 dmg? i only want the explosion to hit once so it doesnt keep hitting the animal if its inside the explosion but already got hit once
You will have to track which animals have been hit using a List object. If intersecting animal is not on list, deal damage and add that animal to the list.
KCee KCee

2023/4/19

#
I tried changing the value of line 60 but it doesnt seem to do anything. I tried changing the values for the hp of the animal and when i inspected the animal after it got hit by the poison, the poison would deal damage until the animals hp hit 4 and then it would just stop dealing damage? does the poison wear off by any chance? if it does that could explain it as maybe the poison doesnt kill it fast enough and just wears off ***(edit) it seems like the poison does exactly 26 damage before stopping***
KCee KCee

2023/4/19

#
wait does the poison only deal damage while the animal is in contact with it or does it deal damage even after its left contact? because i want the animal to be poisoned even after leaving contact with the poison cloud
danpost danpost

2023/4/19

#
KCee wrote...
wait does the poison only deal damage while the animal is in contact with it or does it deal damage even after its left contact? because i want the animal to be poisoned even after leaving contact with the poison cloud
If being poisoned is to be a state of an animal, then the damage should be controlled by the animal, not by the poison object. So, forget everything I stated above. In Animal class, add:
protected boolean poisoned;
protected int poisonTimer;

// **************************************
// in act method
    if (isTouching(Poison.class)) poisoned = true;
    poisonEffect();

// **************************************
// deteriorate health due to any poisoning
protected void poisonEffect() {
    if ( ! poisoned ) return;
    poisonTimer = (poisonTimer+1)%20;
    if (poisonTimer != 0) return;
    health--;
    if (health == 0) getWorld().removeObject(this);
}
You need to login to post a reply.