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

2015/10/29

Enemy hit reaction

Genora51 Genora51

2015/10/29

#
I am working on a platform game. Some enemies have more health than others, and for those that take more than 1 hit to destroy, I want to show a reaction to the hit. At the moment, the loss of health is invisible until it reaches 0, and they die. I need some way for the image to change, for a second or permanently, to show that the health has changed (I don't want to make tons of images for each enemy). I also don't want to use transparency, because the background is quite dark. Is this reaction possible?
danpost danpost

2015/10/30

#
Of course, it is possible. All it takes is one or two images per character. BTW, if you use both light and dark colors in the image(s), the background cannot be effective in hiding the image very well. And there is nothing to stop you from alternating between the original image and one reaction image for a short time.
Genora51 Genora51

2015/10/30

#
The issue is that with quite a lot of different characters in the game, it would be really useful to have one method that does this for me, instead of having tons of different images, so I'm really looking for a command or imported module that will allow me to change lightness, saturation etc.
danpost danpost

2015/10/30

#
You could programmatically create an image that takes all non-transparent pixels of one image and changes them to, let us say, white. Then alternate between the original and it. These images can be made during compilation to avoid any lag while the program runs.
Genora51 Genora51

2015/10/30

#
I get the idea but I haven't really got into the nitty-gritty of drawables. How exactly would I find all non-transparent pixels?
danpost danpost

2015/10/30

#
The GreenfootImage class has methods like 'getColorAt' and 'setColorAt' and the Color class has a method 'getAlpha' which can be used to find the transparency value of Color objects. You can use 'for' loops to traverse the pixels of the images.
Genora51 Genora51

2015/10/31

#
Thanks so much.
Genora51 Genora51

2015/11/1

#
I Implemented the code you suggested, but there are a few problems. Some enemies are just brighter than usual, some go brighter but don't turn back, and others do nothing. Here is my code for the enemy class - there are a few empty methods, but they are designed for customising the behaviour of subclasses. The important bits are act, imgset, enemy and react.
import greenfoot.*;
/**
 * Write a description of class enemy here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class enemy extends Actor
{
    /**
     * Act - do whatever the enemy wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public int tophealth;
    public int health;
    private GreenfootImage img = getImage();
    private GreenfootImage re = img;
    private int timer = 0;
    public void imgset(){
        for(int i = re.getWidth();i >= 0; i--){
            for(int j = re.getHeight(); j >= 0; j--){
                try{re.setColorAt(i,j,re.getColorAt(i,j).brighter());}catch(Throwable e){}
            }
        }
    }
    public void react(){
        if(hit()){
            setImage(re);
            timer = 32;
        }
        if(timer > 0){timer--;}else{setImage(img);}
    }
    public enemy(){
        hset();
        this.health = tophealth;
        imgset();
    }
    public void hset(){
        tophealth = 1;
    }
    public boolean hit(){
        Object fib;
        try{fib = getOneIntersectingObject(wizf1.class);}catch(Throwable e){fib = null;};
        return fib != null;
    }
    public void act() 
    {
        // Add your action code here.
        react();
        if(getOneIntersectingObject(wizard.class) != null){
            level wld = (level) getWorld();
            wld.reset();
        }
        if(hit()){
            health--;
            getWorld().removeObject(getOneIntersectingObject(wizf1.class));
        }
        if(health <= 0){
            dest();
            getWorld().removeObject(this);
        }
        action();
    }
    public void action(){}
    public void dest(){}
}
The try is because of a few errors I had earlier, but the actual brightening itself does brighten the whole image well. It's just the rest I'm not sure about.
Genora51 Genora51

2015/11/1

#
Also, wizf1 is a class of a fireball that damages the enemy, and wizard is the class of the user's character.
danpost danpost

2015/11/1

#
Using try to avoid common errors is not good programming. See if you can find a way to avoid the errors without using try. Line 17 should create a new image -- not reference the same image:
private GreenfootImage re = new GreenfootImage(img);
danpost danpost

2015/11/1

#
As far as where you are using try now: Line 22 probably was because you were getting indexOutOfBounds exceptions. Change lines 20 through 24 to:
for (int i=0; i<img.getWidth(); i++)
    for (int j=0; j<img.getHeight(); j++)
        re.setColorAt(i, j, img.getColorAt(i, j).brighter());
You were starting one row off the image to the right and below where no color can be (hence the exception). Line 43 would not throw an exception unless the enemy was not in the world when the hit method was called (illegalStateException). The method can be changed to this:
private boolean hit()
{
    if (getWorld() == null) return false;
    return getOneIntersectingObject(wizf1.class) != null;
}
You need to login to post a reply.