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

2015/4/28

Gravity Issue?

Tommy99 Tommy99

2015/4/28

#
Hello. I am trying to use a vector labelled "GRAVITY" to make my fireworks fall to the bottom edge of the world after reaching their peak. The angle and velocity vector that makes them move up is too powerful though, and the fireworks continue to move up forever. Do you know how I can fix this? Here is the code for the Rocket (Firework) class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;

public class Rocket extends SmoothMover
{
    private int trans = 255;
    private int constant_angle = 250;
    Color color1 = getImage().getColor();
    Color color2 = getImage().getColor();

    //If it changes from going up to going down, it reached its peak.
    //Or use vectors.
    //Sky 3. and 4.
    //Rocket.
    //Tail.
    //Part.
    //Use speed. If get speed<5, explode. It's in the Smooth Mover class.
    public Rocket()
    {
        createRocket();
    }  

    
    public void act()
    {
        move();
        createTails();
        explodeIntoParts();
    }

    public void createTails()
    {

        getWorld().addObject(new Tail(color1), getX(), getY()); 
    }

    public void explodeIntoParts()
    {
        if(getSpeed()<5){
            
            {
                
                for(int p=0;p<50;p++) {
                    getWorld().addObject(new Part(color2), getX(), getY() );
                }
                getWorld().removeObject(this);
            }
        }
    }

    public void createRocket()
    {
        GreenfootImage img = new GreenfootImage(10,10);

        
        int red = Greenfoot.getRandomNumber(256);
        int green = Greenfoot.getRandomNumber(256);
        int blue = Greenfoot.getRandomNumber(256);
        img.setColor( new Color(red,green,blue) );
        img.fillOval(0,0,10,10);
        setImage(img);
        int angle = Greenfoot.getRandomNumber(41);
        double velocity = 10.0+Greenfoot.getRandomNumber(51)/10.0;
        int v_angle  = constant_angle+angle;
        addForce(new Vector(v_angle, velocity));
        Sky sky = (Sky)getWorld();
        
        addForce(sky.GRAVITY);
    }
}


Here is the code for the SmoothMover class (the Firework's superclass):
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)

/**
 * A variation of an actor that maintains precise location (using doubles for the co-ordinates
 * instead of ints). It also maintains a current movement in form of a movement vector.
 * 
 * @author Poul Henriksen
 * @author Michael Kolling
 * 
 * @version 2.1
 */
public abstract class SmoothMover extends Actor
{
    private Vector movement;
    private double exactX;
    private double exactY;
    
    public SmoothMover()
    {
        this(new Vector());
    }
    
    /**
     * Create new thing initialised with given speed.
     */
    public SmoothMover(Vector movement)
    {
        this.movement = movement;
    }
    
    /**
     * Move in the current movement direction.
     */
    public void move() 
    {
        exactX = exactX + movement.getX();
        exactY = exactY + movement.getY();

        super.setLocation((int) exactX, (int) exactY);
    }
    
    public boolean atWorldEdge()
    {
        return exactX >= getWorld().getWidth() || exactX < 0
            || exactY >= getWorld().getHeight() || exactY < 0;        
    }

    /**
     * Set the location using exact (double) co-ordinates.
     */
    public void setLocation(double x, double y) 
    {
        exactX = x;
        exactY = y;
        super.setLocation((int) x, (int) y);
    }
    
    /**
     * Set the location of this actor. Redefinition of the standard Greenfoot 
     * method to make sure the exact co-ordinates are updated in sync.
     */
    public void setLocation(int x, int y) 
    {
        exactX = x;
        exactY = y;
        super.setLocation(x, y);
    }

    /**
     * Return the exact x co-ordinate (as a double).
     */
    public double getExactX() 
    {
        return exactX;
    }

    /**
     * Return the exact y co-ordinate (as a double).
     */
    public double getExactY() 
    {
        return exactY;
    }

    /**
     * Modify the current movement by adding a new vector to the existing movement.
     */
    public void addForce(Vector force) 
    {
        movement.add(force);
    }
    
    /**
     * Accelerate the speed of this mover by the given factor. (Factors less than 1 will
     * decelerate.) The direction remains unchanged.
     */
    public void accelerate(double factor)
    {
        movement.scale(factor);
        if (movement.getLength() < 0.15) {
            movement.setNeutral();
        }
    }
    
    /**
     * Return the speed of this actor.
     */
    public double getSpeed()
    {
        return movement.getLength();
    }
    
    /**
     * Return the current movement of this object (as a vector).
     */
    public Vector getMovement() 
    {
        return movement;
    }
}
Here is the code for the Vector class:
import greenfoot.Greenfoot;

/**
 * A 2D vector. The vector can be read and manipulated in Cartesian coordinates
 * (as an x,y-offset pair) or in polar coordinates (as a direction and a length).
 * 
 * @author Poul Henriksen
 * @author Michael Kolling
 * 
 * @version 2.0
 */
public final class Vector
{
    double dx;
    double dy;
    int direction;
    double length;
    
    /**
     * Create a new, neutral vector.
     */
    public Vector()
    {
    }

    /**
     * Create a vector with given direction and length. The direction should be in
     * the range [0..359], where 0 is EAST, and degrees increase clockwise.
     */
    public Vector(int direction, double length)
    {
        this.length = length;
        this.direction = direction;
        updateCartesian();
    }

    /**
     * Create a vector by specifying the x and y offsets from start to end points.
     */
    public Vector(double dx, double dy)
    {
        this.dx = dx;
        this.dy = dy;
        updatePolar();
    }

    /**
     * Set the direction of this vector, leaving the length intact.
     */
    public void setDirection(int direction) 
    {
        this.direction = direction;
        updateCartesian();
    }
   
    /**
     * Add another vector to this vector.
     */
    public void add(Vector other) 
    {
        dx += other.dx;
        dy += other.dy;
        updatePolar();
    }
    
    /**
     * Set the length of this vector, leaving the direction intact.
     */
    public void setLength(double length) 
    {
        this.length = length;
        updateCartesian();
    }
    
    /**
     * Scale this vector up (factor greater than 1) or down (factor less than 1). 
     * The direction remains unchanged.
     */
    public void scale(double factor) 
    {
        length = length * factor;
        updateCartesian();
    }
    
    /**
     * Set this vector to the neutral vector (length 0).
     */
    public void setNeutral() {
        dx = 0.0;
        dy = 0.0;
        length = 0.0;
        direction = 0;
    }
    
    /**
     * Revert to horizontal component of this movement vector.
     */
    public void revertHorizontal() {
        dx = -dx;
        updatePolar();
    }
    
    /**
     * Revert to vertical component of this movement vector.
     */
    public void revertVertical() {
        dy = -dy;
        updatePolar();
    }
    
    /**
     * Return the x offset of this vector (start to end point).
     */
    public double getX() {
        return dx;
    }
     
    /**
     * Return the y offset of this vector (start to end point).
     */
    public double getY() {
        return  dy;
    }
    
    /**
     * Return the direction of this vector (in degrees). 0 is EAST.
     */
    public int getDirection() {
        return direction;
    }
    
    /**
     * Return the length of this vector.
     */
    public double getLength() {
        return length;
    }

    /**
     * Update the direction and length from the current dx, dy.
     */
    private void updatePolar() 
    {
        this.direction = (int) Math.toDegrees(Math.atan2(dy, dx));
        this.length = Math.sqrt(dx*dx+dy*dy);
    }   
    
    /**
     * Update dx and dy from the current direction and length.
     */
    private void updateCartesian() 
    {
        dx = length * Math.cos(Math.toRadians(direction));
        dy = length * Math.sin(Math.toRadians(direction));   
    }
}
Thank you very much.
danpost danpost

2015/4/28

#
You are adding the force of gravity once when the Rocket is constructed. You need to add it constantly (every act cycle); so, add it in the 'act' method.
Tommy99 Tommy99

2015/4/28

#
Oh okay. It worked wonderfully! Thank you!
Tommy99 Tommy99

2015/4/28

#
Also, do you know why the tail isn't showing up? And why the rocket doesn't explode at the peak? Tail Code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;

public class Tail extends Actor
{
    private int size = 8;
    public int trans = 255;
    
    
    public Tail(Color color1)
    {
        
        
        GreenfootImage img = new GreenfootImage(size,size);
        getImage().setColor(color1);
        setImage(img);
        
    }
    
    public void act() 
    {
        disappear();
        
    }    
    
    public void disappear()
    {
        trans--;
        getImage().setTransparency(trans);
        if(trans==0){
            getWorld().removeObject(this);
        }
    }
}
Part Class:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;

public class Part extends SmoothMover
{
    
    
    public Part(Color color2)
    {
        double velocity = 1.0 + Greenfoot.getRandomNumber(101)/10.0;
        GreenfootImage img = new GreenfootImage(5,5);
        
        img.fillOval(0,0,5,5); 
        getImage().setColor(color2);
        setImage(img);
        int angle = Greenfoot.getRandomNumber(360);
        
        
        
        
        addForce(new Vector(angle, velocity));
        
        
        
    }
    
    public void act() 
    {
        ifAtEdge();
        Sky sky = (Sky)getWorld();
        addForce(sky.GRAVITY);
        
    }  
    
    public void ifAtEdge()
    {
        if(isAtEdge()) {
            getWorld().removeObject(this);
        }
    }
    
    
    
    
    
}
Thank you again.
danpost danpost

2015/4/28

#
The rocket does have a tail and does explode -- you just do not see it happening. Line 15 of the Tail class and line 14 of the Parts class set the drawing color for those objects; yet, you are not using any of the drawing methods of the GreenfootImage class to apply those colors to the images of the objects created from those classes.
Tommy99 Tommy99

2015/4/28

#
Oh okay. It worked. Thank you!
You need to login to post a reply.