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

2016/1/28

Cannonball won't stop accelerating while off the screen

TheRealJK TheRealJK

2016/1/28

#
I'm making a cannon game where you shoot targets with the click of a mouse. I want the cannonball to accelerate downwards while on the screen to imitate the action of falling. While i have managed to do this on the first shot, the following shots fire towards the bottom of the screen because the acceleration continues while the ball is not in the world. How do I make it so that the acceleration resets each time a cannonball is shot?
Super_Hippo Super_Hippo

2016/1/28

#
Do you use a static value for the acceleration? If yes, do not do it.
TheRealJK TheRealJK

2016/1/28

#
This is my code for my bullet class. what should i fix?
import greenfoot.*;

/**
 * Write a description of class bullet here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class bullet extends Actor
{
    private int Vspeed = 0;
    private int acceleration = 1;
    boolean bulletExist = false;
    /**
     * Act - do whatever the bullet wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public bullet() 
    {
        GreenfootImage myImage = getImage();
        int myNewHeight = myImage.getHeight()/2;
        int myNewWidth = myImage.getWidth()/2;
        myImage.scale(myNewWidth, myNewHeight);
    }    

    public void act()
    {
        move(40);
        fall();
        disappearAtEdge();
    }

    public void fall()
    {
        if (this != null && bulletExist == false)
        {
            setLocation(getX(), getY() + Vspeed);
            Vspeed = Vspeed + acceleration;
            bulletExist = true;
        }
        else
        {
            bulletExist = false;
        }
    }

    /**
     * 
     */
    public String edge()
    {
        int x = getX();
        int y = getY();
        World space = getWorld();
        int rightSide = getWorld().getWidth() - 1;
        int bottomSide = getWorld().getHeight() - 1;
        if (y == 0)
        {
            return "top";
        }
        else if (x == 0)
        {
            return "left";
        }
        else if (y == bottomSide)
        {
            return "bottom";
        }
        else if (x == rightSide)
        {
            return "right";
        }
        else
        {
            return null;
        }
    }

    public void disappearAtEdge()
    {
        String edge = edge();
        World space = getWorld();
        if(edge == "right")
        {
            space.removeObject(this);
        }
        if(edge == "bottom")
        {
            space.removeObject(this);
        }
        if(edge == "left")
        {
            space.removeObject(this);
        }
    }
}
Super_Hippo Super_Hippo

2016/1/28

#
You use 'move(40)' to move the bullet. If you want it to accelerate, you have to use the 'Vspeed' variable. What do you want the 'fall' method to do? I don't think that it does what you think.
TheRealJK TheRealJK

2016/1/29

#
Since I have the bullet fire towards my mouse, the move(40) just makes it fire at 40 towards my mouse. The fall method actually works, but the problem is that it the bullet continues to accelerate when it is not on the screen. So the next time i fire a shot, Vspeed continues where it left off.
TheRealJK TheRealJK

2016/1/29

#
Alright, I figured it out, I just set Vspeed = 0 in my disappearAtEdge() method. This doesn't allow me to fire multiple shots at the same time, but I didn't want that anyway. Thanks for the help!
Super_Hippo Super_Hippo

2016/1/29

#
sec
danpost danpost

2016/1/29

#
You are comparing String objects using the conditional equality symbol, '=='. If the String objects are not one in the same object (regardless of their content being similar or not), your result will be 'false'. Use the 'equals' method of the Object class to compare the contents of the String objects for equality:
if ("left".equals(edge))
Super_Hippo Super_Hippo

2016/1/29

#
'move(40)' makes the bullet move 40 cells every act cycle. If you use 'normal' speed, then this is very fast. Okay, let's take a look at the 'fall' method:
    public void fall()
    {
        if (this != null && bulletExist == false)
        {
            setLocation(getX(), getY() + Vspeed);
            Vspeed = Vspeed + acceleration;
            bulletExist = true;
        }
        else
        {
            bulletExist = false;
        }
    }
Line 3: 'this != null' is always true, so useless. First act cycle, the bullet moves 40 cells. 'bulletExist' is false, so the first if-block is executed. Line 5 doesn't do anything because 'Vspeed' is 0. After line 6, 'Vspeed' is 1. Line 7 sets 'bulletExist' to true. Second act cycle, the bullet moves another 40 cells. 'bulletExist' is true, so it will be set back to false in line 11. Third act cycle, the bullet moves 40 cells, then it will move 1 cell downwards and 'Vspeed' is set to 2. So the bullet moves 120 cells to the direction it is facing while falling down the first cell. Then every 80 cells it will fall another 2, 3, 4, ... cells. When you fire a shot, do you create a new bullet object or do you only set the location of the old one? If creating a new one, it will have its own variables, so 'Vspeed' starts at 0 again. Does the removing at the edge of world works? If not, you can use this instead of the two methods you have for it:
int x=getX(), y=getY(), w=getWorld().getWidth(), h=getWorld().getHeight();
if (x<1 || x>w-2 || y<1 || y>h-2) getWorld().removeObject(this);
TheRealJK TheRealJK

2016/1/29

#
Well, I don't know what I did, but this works:
public class bullet extends Actor
{
    private int Vspeed = 0;
    private int acceleration = 1;
    /**
     * Act - do whatever the bullet wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public bullet() 
    {
        GreenfootImage myImage = getImage();
        int myNewHeight = myImage.getHeight()/2;
        int myNewWidth = myImage.getWidth()/2;
        myImage.scale(myNewWidth, myNewHeight);
    }    

    public void act()
    {
        move(40);
        fall();
        disappearAtEdge();
    }

    public void fall()
    {
        if (this != null)
            {
                setLocation(getX(), getY() + Vspeed);
                Vspeed = Vspeed + acceleration;
                return;
        }
    }

    /**
     * 
     */
    public String edge()
    {
        int x = getX();
        int y = getY();
        World space = getWorld();
        int rightSide = getWorld().getWidth() - 1;
        int bottomSide = getWorld().getHeight() - 1;
        if (y == 0)
        {
            return "top";
        }
        else if (x == 0)
        {
            return "left";
        }
        else if (y == bottomSide)
        {
            return "bottom";
        }
        else if (x == rightSide)
        {
            return "right";
        }
        else
        {
            return null;
        }
    }

    public void disappearAtEdge()
    {
        String edge = edge();
        World space = getWorld();
        if(edge == "right")
        {
            space.removeObject(this);
            Vspeed = 0;
        }
        if(edge == "bottom")
        {
            space.removeObject(this);
            Vspeed = 0;
        }
        if(edge == "left")
        {
            space.removeObject(this);
            Vspeed = 0;
        }
    }
}
TheRealJK TheRealJK

2016/1/29

#
The addition of lines 73, 78, and 83 made it work just fine.
danpost danpost

2016/1/29

#
TheRealJK wrote...
Well, I don't know what I did, but this works: < Code Omitted >
The addition of lines 73, 78, and 83 made it work just fine.
You must be adding the same bullet into the world each time your actor shoots. You should probably show the class code for the actor that is using this bullet class.
You need to login to post a reply.