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

2022/6/1

Help with transferring actor's instance variables

Gabe8469 Gabe8469

2022/6/1

#
Hello, I'm currently making a game and there are subclasses of enemies that have their own unique sets of characteristics, such as HP. I've made it so that whenever the player comes in contact with an enemy, it should send them to the fight screen world, which takes the enemy actor as a parameter, it then spawns in the enemy actor. However, when I created this class, I used minion1 as a placeholder, and I cannot make it work with any enemy that the player touches. I made a method in the player class that detects what enemy has been touched, and I use that method in the attack class in order to spawn said enemy, but since they are all a subclass of Enemies, I cannot seem to make it work. Any help would be appreciated.
// Player class
public void act()
    {
        movement();
        fightTrigger();
        levelUp();
        borderDetection();
        playMusic();
        if (fighting == false)
        {
            theme.stop();
        }
    }

public Actor getEnemyTrigger()
    {
        fighting = true;
        Minion one = new Minion();
        Minion2 two = new Minion2();
        Minion3 three = new Minion3();
        Boss finalBoss = new Boss();
        
        Actor minion1Trigger = getOneIntersectingObject(Minion.class);
        if (minion1Trigger != null)
        {
            return one;
        }
        Actor minion2Trigger = getOneIntersectingObject(Minion2.class);
        if (minion2Trigger != null)
        {
            return two;
        }
        Actor minion3Trigger = getOneIntersectingObject(Minion3.class);
        if (minion3Trigger != null)
        {
            return three;
        }
        Actor BossTrigger = getOneIntersectingObject(Boss.class);
        if (BossTrigger != null)
        {
            return finalBoss;
        }
        return null;
    }

//Alternate Attempt

public void fightTrigger()
    {
        fighting = true;
        Minion one = new Minion();
        Minion2 two = new Minion2();
        Minion3 three = new Minion3();
        Boss finalBoss = new Boss();
        
        
        Actor minion1Trigger = getOneIntersectingObject(Minion.class);
        if (minion1Trigger != null)
        {
            Greenfoot.setWorld(new FightScreen(one));
        }
        Actor minion2Trigger = getOneIntersectingObject(Minion2.class);
        if (minion2Trigger != null)
        {
            Greenfoot.setWorld(new FightScreen(two));
        }
        Actor minion3Trigger = getOneIntersectingObject(Minion3.class);
        if (minion3Trigger != null)
        {
            Greenfoot.setWorld(new FightScreen(three));
        }
        Actor BossTrigger = getOneIntersectingObject(Boss.class);
        if (BossTrigger != null)
        {
            Greenfoot.setWorld(new FightScreen(finalBoss));
        }
    }

public int getHP()
    {
        return health;
    }
    
    public void setHP(int newHP)
    {
        health = newHP;
    }
    
    
    public int getAttack()
    {
        return attack;
    }
    
    public void setAttack(int newAttack)
    {
        attack = newAttack;
    }
    
    public int getXP()
    {
        return XP;
    }    
    
    public void addXP(int newXP)
    {
        XP = XP + newXP;
    }
    
    public void levelUp()
    {
        if (XP > 8)
        {
            health += 2;
            attack += 2;
            XP = 0;
        }


//FightMenu, subclass of Player

public class FightMenu extends Player
{
    public GreenfootSound fightMusic = new GreenfootSound("fightsong.mp3");
    public GreenfootSound bonk = new GreenfootSound("le bonk.mp3");
    
    Player dog = new Player();
    Minion enemy = new Minion(); //should be replaced with whatever actor the player touches
    
    
    int playerHP = dog.getHP();
    int minionHP = enemy.getEnemyHP();
    int playerAttack = dog.getAttack();
    int enemyAttack = enemy.getEnemyAttack();

    public void act()
    {
        dog.stopMusic();
        createEnemy(dog.getEnemyTrigger());
    }

public void createEnemy(Actor enemy)
    {
        getWorld().addObject(enemy, 320,400);
    }

//Attack class, subclass of FightMenu

public class Attack extends FightMenu
{
    
    
    public void act()
    {
        dog.stopMusic();
        checkVictory();
        checkLose();
        clicked();
        playMusic();
        if(minionHP<= 0 || playerHP <= 0)
        {
            stopMusic();
            getWorld().removeObject(enemy);
        }
        
    }
    
    public void checkVictory()
    {
        if (minionHP <= 0)
        {
            dog.addXP(dog.getXP() + enemy.getEnemyXP());
        
            getWorld().removeObject(enemy);
            getWorld().showText("You Won!", 320, 365);
            getWorld().showText("", 530,400);
            Greenfoot.delay(120);
            getWorld().showText("You gained " + enemy.getEnemyXP() + " experience!", 320, 365);
            Greenfoot.delay(120);
            stopMusic();
            levelUp();
            Greenfoot.setWorld(new BasementAfterFight());
            
            dog.setFightStatus(false);
            
        }
    }
    
    public void clicked()
    {
        getWorld().showText("What will you do?", 320,365);
        getWorld().showText("Enemy HP: " + minionHP, 530,380);
        getWorld().showText("Your HP: " + playerHP, 530, 420);
        
        if (Greenfoot.mouseClicked(this))
        {
            playBonk();
            int amountAttacked = (int)(Math.random()*playerAttack) + 2;
            minionHP = minionHP - amountAttacked;
                
            
            playBonk();
            getWorld().showText("You attacked for " + amountAttacked +"!", 320,365);
            if(minionHP <= 0)
            {
                minionHP = 0;
            }
            getWorld().showText("Enemy HP: " + minionHP, 530,380);
            Greenfoot.delay(120);
            getWorld().showText("", 320,355);
            
            enemyAttack();
        }
    }
    
    public void enemyAttack()
    {
        if(minionHP != 0)
        {
            playBonk();
            int amountEnemyAttacked = (int)(Math.random()*enemyAttack) + 2;
            playerHP = playerHP - amountEnemyAttacked;
            
            getWorld().showText("You're attacked for " + amountEnemyAttacked +"!", 320,365);
            if(playerHP <= 0)
            {
                playerHP = 0;
            }
            getWorld().showText("Enemy HP: " + minionHP, 530,380);
            Greenfoot.delay(120);
            getWorld().showText("", 320,355);
            getWorld().showText("Your HP: " + playerHP, 530, 420);
        }
    }
    
    public void checkLose()
    {
        if (playerHP <= 0)
        {
            getWorld().showText("You Lost.", 320, 365);
            Greenfoot.delay(120);
            stopMusic();
            Greenfoot.setWorld(new StartMenu());
        }
    }
    
    public void levelUp()
    {
        if (dog.getXP() > 8)
        {
            dog.setHP(dog.getHP() + 2);
            dog.setAttack(dog.getAttack() + 2);
            getWorld().showText("You Leveled Up!", 320, 365);
            Greenfoot.delay(120);
            getWorld().showText("All Stats Increased By 3.", 320, 365);
            Greenfoot.delay(120);
        }
    }

    
}

// Enemies class

public class Enemies extends Actor
{
    private int speed = 2;
    private int hp;
    private int attack;
    private int enemyXP;
    
        
    
    /**
     * Act - do whatever the Enemies wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
        movement();
        checkVictory();
    }
    
    public void movement()
    {
        if(this.getWorld().getClass() == Basement.class ||this.getWorld().getClass() == EnemyRoom.class  )
        {
            if((this.isTouching(Wall2.class)))
            {
                speed = -speed;
                move(speed);
            }
            move(speed);
        }
        
        
    }
    
    public void checkVictory()
    {
        Player dog = new Player();
        Minion enemy = new Minion();
        
        int playerHP = dog.getHP();
        int minionHP = enemy.getEnemyHP();
        
        if (minionHP <= 0)
        {
            dog.addXP(dog.getXP() + enemy.getEnemyXP());
        
            getWorld().removeObject(enemy);
            getWorld().showText("You Won!", 320, 380);
            Greenfoot.delay(120);
            getWorld().showText("You gained " + enemy.getEnemyXP() + " experience!", 320, 380);
            Greenfoot.setWorld(new Basement());
        }
    }
    
    public int getEnemyHP()
    {
        return hp;
    }

    public void setMinionHP(int newHP)
    {
        hp = newHP;
    }
    
    public int getEnemyAttack()
    {
        return attack;
    }
    
    public int getEnemyXP()
    {
        return enemyXP;
    }
}

// Example of enemy, subclass of enemies

public class Minion extends Enemies
{
    public int hp = 10;
    private int attack = 3;
    private int enemyXP = 4;
    
    /**
     * Act - do whatever the Minion wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act()
    {
       movement();
    }
    
    public int getEnemyHP()
    {
        return hp;
    }

    public void setMinionHP(int newHP)
    {
        hp = newHP;
    }
    
    public int getEnemyAttack()
    {
        return attack;
    }
    
    public int getEnemyXP()
    {
        return enemyXP;
    }
    
    
}


// Fight screen

public FightScreen(Actor enemy)
    {    
        super(640, 480, 1); 
        
        addObject(enemy, 320, 175);
        addObject(new BoxTest(),320, 400);
        addObject(new IconTest(),90,395);
        addObject(new Attack(), 320, 410);

    }
Spock47 Spock47

2022/6/1

#
I suggest the following changes: 1. Rename class "Enemies" to "Enemy" (an object of a class represents one entity, see Player, Minion, Attack); so it is easier to understand when the class name is singular, too. (It still can be different entities at different times, so an Enemy can be a Minion or it can be a Boss, but it is always one at a time):
public class Enemy extens Actor
2. The FightMenu has a player variable in it, but is itself not a player, so it should inherit from Actor, not from Player:
public class FightMenu extends Actor
3. Add parameters for player and enemy to fight menu, change type of enemy to Enemy and remove the init values from these declared attributes:
    private Player dog;
    private Enemy enemy; //whatever actor the player touches
    public FightMenu(final Player player, final Enemy enemy) {
        this.dog = player;
        this.enemy = enemy;
    }
4. Add player parameter to FightScreen's constructor, too and pass it through to the attack:
    public FightScreen(final Player player, final Actor enemy)
    {    
        ....
        addObject(new Attack(player, enemy), 320, 410);
    }
5. Now, the enemy trigger gets simple, just replace by:
    public void fightTrigger()
    {
        final Actor enemy = getOneIntersectingObject(Enemy.class);
        if (enemy != null)
        {
            Greenfoot.setWorld(new FightScreen(this, enemy));
            fighting = true;
        }
    }
Note: In your implementation, the same player* is used in the normal world and in the fight scene, too. This means that class Player implements two behaviors (behavior "player in normal world" and "player in fight screen"). That means that you have to keep pace of in which state the player is and always make sure that each behavior is only done in the right situation. (e.g. that Player does not try to use fightTrigger, when already in a fight). You could get around this, if you instead send an "avatar" of the player into the fight. In that case, you would implement all normal world behavior into Player class, all fighting screen behavior into PlayerFightingAvatar class and don't have to care about current state or something. (You don't have to do this, both ways are possible. I just wanted to give some thoughts.) * the same is true for the enemy, too. Live long and prosper, Spock47
Gabe8469 Gabe8469

2022/6/1

#
Spock47 wrote...
4. Add player parameter to FightScreen's constructor, too and pass it through to the attack:
    public FightScreen(final Player player, final Actor enemy)
    {    
        ....
        addObject(new Attack(player, enemy), 320, 410);
    }
Spock47
What should my Attack constructor look like? I tried copying the same constructor as FightMenu, as they both ask for a player and an enemy, but it keeps telling me that the constructor cannot be applied to the given types, saying that Player and Enemy are required and that it found no arguments. It also tells me that this.enemy = enemy; doesn't work because "greenfoot.Actor cannot be converted to Enemy." This is all in the Attack class. Thank you.
Spock47 Spock47

2022/6/1

#
Gabe8469 wrote...
What should my Attack constructor look like? I tried copying the same constructor as FightMenu, as they both ask for a player and an enemy, but it keeps telling me that the constructor cannot be applied to the given types, saying that Player and Enemy are required and that it found no arguments. It also tells me that this.enemy = enemy; doesn't work because "greenfoot.Actor cannot be converted to Enemy." This is all in the Attack class. Thank you.
Yes, sorry, my fault. The enemy parameter of FightScreen should be of type Enemy, not Actor.
    public FightScreen(final Player player, final Enemy enemy)
    {    
        ....
        addObject(new Attack(player, enemy), 320, 410);
    }
And the triggered enemy needs to have type Enemy, too:
    public void fightTrigger()
    {
        final Enemy enemy = (Enemy)getOneIntersectingObject(Enemy.class);
        if (enemy != null)
        {
            Greenfoot.setWorld(new FightScreen(this, enemy));
            fighting = true;
        }
    }
Then it should work as you said: Attack has the same constructor as FightMenu:
public Attack(final Player player, final Enemy enemy) {
    super(player, enemy);
}
Gabe8469 Gabe8469

2022/6/1

#
Sweet, now it's working perfectly! Thanks alot for your help!
You need to login to post a reply.