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

2019/4/17

Selecting a card that is on the slot

1
2
3
dkalfpqpfjq dkalfpqpfjq

2019/4/17

#
Hi, I am making a fighting card game for my school project. I want the player to be able to choose a card that is on the slot and then choose a card from opponent which is also on the slot by mouse clicking .
/**
     * Check to see if it is player's turn or bot's turn.
     */
    public void checkTurn()
    {
        if (myTurn)
        {
            choose();
            if (!slotEmpty1 || !slotEmpty2 || !slotEmpty3)
            {
                chooseToAttack();
            }
                        
        }
        else
        {
            return;
        }
    }
    
    /**
     * Choose a card to place in the empty slot if it is player's turn.
     */
    private void choose()
    {
        Actor card = getOneObjectAtOffset (getX(), 750, Cards.class);
        if (Greenfoot.mouseMoved(card))
        {
            onThis = Greenfoot.mouseMoved(this);
        }
        if (onThis && !selected)
        {
            setLocation(this.getX(),633);
        }
        else if (!onThis && !selected)
        {
            setLocation(this.getX(),750);
        }
        if (Greenfoot.mouseClicked(this))
        {
            select();
            myTurn = false;
            selected = true;
        }
    } 
    
    /**
     * Put the selected card into the empty slot if it is player's turn
     */
    public void select()
    {
        if (slotEmpty1) //go to slot1
        {
            this.setLocation(slotX[0],slotY[1]);
            getWorld().addObject(new HealthBar(health, currentHealth), slotX[0], slotY[1]-90);
            
        }
        else if (!slotEmpty1 && slotEmpty2)/ //go to slot2
        {
            this.setLocation(slotX[1],slotY[1]);
            getWorld().addObject(new HealthBar(health, currentHealth), slotX[1], slotY[1]-90);
                    }
        else if (!slotEmpty1 && !slotEmpty2 && slotEmpty3) //go to slot3
        {
            this.setLocation(slotX[2],slotY[1]);
            getWorld().addObject(new HealthBar(health, currentHealth), slotX[2], slotY[1]-90);
             
        }
        else if (!slotEmpty1 && !slotEmpty2 && !slotEmpty3) //if all full, don't do anything
        {
           
        }
    }
    
    /**
     * Player choose a card on one of the slots to attack bot
     * When the mouse is on the card, it will create yellow border
     */
    public void chooseToAttack()
    {
        Actor cardOnSlot = getOneObjectAtOffset (getX(), slotY[1], Cards.class);//getOneIntersectingObject(Slot.class);//getOneObjectAtOffset (slot.getX(), slot.getY(), Slot.class);
         
        if (Greenfoot.mouseMoved(cardOnSlot))
        {
            onSlot = Greenfoot.mouseMoved(this);
        }
        if (onSlot && !selectedToAttack)
        {
            GreenfootImage image = getImage();
            image.setColor(new Color(255,202,24));
            image.drawRect(0,0,120+20,175+20);
            setImage(image);
        }
        else if (!onSlot && !selectedToAttack)
        {
            setImage(character); 
        }
        if (Greenfoot.mouseClicked(cardOnSlot))
        {
            chooseBotToAttack();
            GreenfootImage image = getImage();
            image.setColor(new Color(255,202,24));
            image.drawRect(0,0,120+30,175+30);
            setImage(image);
            selectedToAttack = true;
        }
    }
    
    /**
     * Choose a bot card to attack 
     */
    public void chooseBotToAttack()
    {
        if (Greenfoot.mouseMoved(Bot.class))
        {
            onSlot = Greenfoot.mouseMoved(this);
        }
        if (onSlot && !selectedToAttack)
        {
            GreenfootImage image = getImage();
            image.setColor(new Color(255,202,24));
            image.drawRect(0,0,120+20,175+20);
            setImage(image);
        }
        else if (!onSlot && !selectedToAttack)
        {
            setImage(character); 
        }
        if (Greenfoot.mouseClicked(this))
        {
            attack();
            GreenfootImage image = getImage();
            image.setColor(new Color(255,202,24));
            image.drawRect(0,0,120+30,175+30);
            setImage(image);
            myTurn = false;
            selectedToAttack = true;
        }
    }
When I want the card that is already on a slot to be selected to attack, then click on that card, it will only move to the next empty slot. Another problem is in chooseToAttack() method. All the cards will have yellow border after the player's first turn when the mouse pointer is on those card. I only want the cards that are on the slots to have yellow border. Sorry, I am not even sure about what I've got so far. I'd appreciate some help.
danpost danpost

2019/4/17

#
Try changing line 96 to this:
setImage(new GreenfootImage(character));
You will also have to do this in the constructor of the class to keep the original character image intact.
danpost danpost

2019/4/17

#
I find it difficult to determine what class this code is in. It is obvious an Actor subclass. It deals with both the player and the bot choosing (attack) cards. That kind of rules both of them out. You say you are highlighting cards to yellow and the code highlight the currently acting actor, which indicates that this is the Cards class. However, the code for choosing does not belong in the Cards class. A class, in general, should contain only those state (in fields) and behavior (in methods) that a single object created from the class has. A card will have an image and a world with a location in that world. These are taken care of in the Actor class. A card can be selected, it can be on or off a slot and it can be used to attack. A card does not choose from a number of cards (which may or may not include itself).
dkalfpqpfjq dkalfpqpfjq

2019/4/17

#
Thanks for your reply! I am wondering if you could help with another problem. I would like the selected card (card on slot) to have yellow border whenever the mouse is on that card. (in chooseToAttack method) Currently, all of the cards including the cards not on the slot will have yellow border as well. Is line 81 correct?
  Actor cardOnSlot = getOneObjectAtOffset (getX(), slotY[1], Cards.class);
dkalfpqpfjq dkalfpqpfjq

2019/4/17

#
I have sperate class for Cards (player) and Bot (computer, programmed). In case you would like to know the code for Bot class.
/**
     * Check if it is bot's turn
     */
    public void checkTurn()
    {
        if (!Cards.myTurn)
        {
            Greenfoot.delay(7);
            botTurn();
        }
        else
        {
            return;
        }
    }
    /**
     * It is bot's turn. 
     */
    public void botTurn()
    {
        if (bSlotEmpty1) //go to slot1
        {
            placeCard();
            //bSlotEmpty1 = false;
        }
        else if (bSlotEmpty2)//go to slot2
        {
            int i = Greenfoot.getRandomNumber(1);
            if (i==0)
            {
                placeCard();
                //bSlotEmpty2 = false;
            }
            else if (i==1)
            {
                attack();
            }
            
        }
        else if (bSlotEmpty3)//go to slot3
        {
            int i = Greenfoot.getRandomNumber(1);
            if (i==0)
            {
                placeCard();
                //bSlotEmpty3 = false;
            }
            else if (i==1)
            {
                attack();
            }
             
        }
        else if (!bSlotEmpty1 && !bSlotEmpty2 && !bSlotEmpty3) //if all full, don't do anything
        {
            attack();
        }
    }
    /**
     * Place a card into an empty slot
     */
    private void placeCard()
    {
        MyWorld myWorld = (MyWorld) getWorld();
        myWorld.getRandom();
        randomCard = ((MyWorld) getWorld()).randomBotCard;
        List<Bot> bots = getWorld().getObjects(Bot.class);
        for (Bot bot : bots)
        {
            if (getX() == 60+randomCard*120)
            {
                if (bSlotEmpty1)
                {
                    this.setRotation(0);
                    this.setLocation(slotX[0],slotY[0]);//720,320
                    getWorld().addObject(new HealthBar(botHealth, botCurrentHealth), slotX[0], slotY[0]+90);
                }
                else if (!bSlotEmpty1 && bSlotEmpty2)
                {
                    this.setRotation(0);
                    this.setLocation(slotX[1],slotY[0]);
                    getWorld().addObject(new HealthBar(botHealth, botCurrentHealth), slotX[1], slotY[0]+90);
                }
                else if (!bSlotEmpty1 && !bSlotEmpty2 && bSlotEmpty3)
                {
                    this.setRotation(0);
                    this.setLocation(slotX[2],slotY[0]);
                    getWorld().addObject(new HealthBar(botHealth, botCurrentHealth), slotX[2], slotY[0]+90);
                }
                Cards.myTurn = true;
            }
        }
        // Bot botCard = (Bot)getOneObjectAtOffset(60+randomCard*120, 0, Bot.class);
        
    }
I haven't got to work on attack method yet.
danpost danpost

2019/4/17

#
dkalfpqpfjq wrote...
I would like the selected card (card on slot) to have yellow border whenever the mouse is on that card. (in chooseToAttack method) Currently, all of the cards including the cards not on the slot will have yellow border as well. Is line 81 correct? << Code Omitted >>
I am quite sure it is not correct in one sense. Note that the two int parameters are offset values, not absolute values. Closer might be:
Actor cardOnSlot = getOneObjectAtOffset(0, slotY[1]-getY(), Cards.class);
However, again, this appears to deal with other cards and not with the card whose act method is currently running. Also, I do not understand why you want to get a reference to a card that is some "vector" away from another card.
danpost danpost

2019/4/17

#
dkalfpqpfjq wrote...
I have sperate class for Cards (player) and Bot (computer, programmed).
You should have three separate classes -- Player, Bot and Cards (or Card). Your World subclass (or game world) should control the running of the game (whose turn it is, when the game is over, etc. -- general game stuff). That may also include tracking the selected cards and processing the attacks.
dkalfpqpfjq dkalfpqpfjq

2019/4/18

#
Thank you for your reply! I will try to make those separate classes as you advised first. I have one question. Currently my Bot class also contains the code for the cards of the Bot. (It actually represents bot's cards). As you said, I should have put 3 separate classes. Should I put the bot's cards in Bot class or Card class along with player's cards?
danpost danpost

2019/4/18

#
dkalfpqpfjq wrote...
Currently my Bot class also contains the code for the cards of the Bot. (It actually represents bot's cards). As you said, I should have put 3 separate classes. Should I put the bot's cards in Bot class or Card class along with player's cards?
I want to ask if the bot always has certain cards and if the player always has certain other cards, but it does not really matter. What matters is how you determine what cards each have. Both the bot and player classes should contain a list of cards that contains the cards that it has. Along with the list, you can have methods to return a single card or all cards from its list and a method each to add or remove a card. As a possible alternative, which really depends on how your game works, is to use arrays instead on lists as they can be used to determine order or placement of the cards. I cannot be more helpful on the matter unless I know a lot more about how the game is to work (basic game instruction and game play). As far as who has what cards, it might be wise to add an additional class to contain the list and associated methods, then have both the player and bot classes extend it. For example, you could have a Player class (containing the list stuff) with extensions of Bot and Human. Your world could then keep an array of Player objects (one Human object and one Bot object) and not have to refer to any one specifically as the actual type that it is.
dkalfpqpfjq dkalfpqpfjq

2019/4/18

#
Both Bot and Player have 12 cards of different "characters" that has different values of health and attack. Bot and player takes turn and can either place a card in an empty slot (if there isn't they cannot put the cards anymore) or use one of the cards that is already placed on the slot to attack one of the opponent cards that is on the slot. Each player has 3 slots, and only the cards that is on the slots can attack or get damaged. When the card has 0 or less health, it is removed, and that slot becomes empty. The game ends when one side ran out of their cards.
danpost danpost

2019/4/18

#
dkalfpqpfjq wrote...
<< Game Description Omitted >>.
Okay. Best would be to use List type objects due to the fact that the sizes need to change. I would suggest that the Player objects (Human and Bot objects) be located at the slots and have their yellowish images turn their transparencies on and off depending on whose turn it is, thereby "highlighting" the slot cards and signifying whose turn it is. The Card class can control a hover-highlighter and the MyWorld class can control a selected-highlighter. A single-click on a slot card can select it. A double-click on a player card can "slot" it. A single-click on a opponents slot card while a card is selected by the player at turn can initiate a "battle".
dkalfpqpfjq dkalfpqpfjq

2019/4/19

#
Okay. I will try what you have suggested. Thanks for your help!
dkalfpqpfjq dkalfpqpfjq

2019/4/19

#
I decided to use arrow key when the player is choosing their attacking card that is on the slot. Because I faced a problem, when I double-click on a card to select it as attacking card, it will move to the next slot after my first click. (single-click is to choose card to put on the slot) So I got these so far in my Player class
private int[] slotX = {310, 720, 1150};
private int[] slotY = {220, 515};


/**
     * Player choose a card on one of the slots to attack bot
     * When the mouse is on the card, it will create yellow border
     */
    public void chooseToAttack()
    {
        if (!keyPressed && Greenfoot.isKeyDown("right"))
        {
            keyPressed = true;
            if (getWorld().getObjects(SelectRectangle.class).isEmpty())
            {
                getWorld().addObject(new SelectRectangle(255,202,24), slotX[0], slotY[1]);
            }
            else
            {
                SelectRectangle selectRectangle = (SelectRectangle)getWorld().getObjects(SelectRectangle.class).get(0);
                selectRectangle.playerAttack();
            }
        }
        if (keyPressed && !Greenfoot.isKeyDown("right"))
        {
            keyPressed = false; 
        }
        if (!keyPressed && Greenfoot.isKeyDown("up"))
        {
            keyPressed = true;  
            //card is selected;
        }
        if (keyPressed && !Greenfoot.isKeyDown("up"))
        {
            keyPressed = false;
        }
    }
And the following is the code in SelectRectangle class. I want this rectangle to show up so that the player can see which card the player is selecting. I would like this rectangle to move to next (to the right) card that is on slot when right arrow key is pressed.
 /**
     * Move to right slot when selecting a card.
     */
    public void playerAttack()
    {
                        int i =0;
                this.setLocation(slotX[i],slotY[1]);
                while (getObjectsInRange(0, Cards.class) == null)
                {
                    this.setLocation(slotX[i+1], slotY[1]);
                }
                if (i > 2)
                {
                    this.setLocation(slotX[0], slotY[1]);
                }
                i++;
 
    }
I am not sure about the while loop in playerAttack() method. Currently, the rectangle won't move to next slot, it will just appear on the first slot. Could someone help me with this problem? Thank you.
danpost danpost

2019/4/19

#
The condition on line 8 will never be true. A List type object is always returned. What you really want to ask is if the list is empty or not:
while (getObjectsInRange(0, Cards.class).isEmpty())
You will have an infinite loop IndexOutOfBounds error thrown if there are no cards to the right of the actors location. I really think, however, you may be going about this in the wrong way. You should use the array to determine what card to move the select rectangle to.
dkalfpqpfjq dkalfpqpfjq

2019/4/19

#
Okay. Is there any way that I can put in and out some value from array? I've never used array in that way. So could you provide an example code please?
There are more replies on the next page.
1
2
3