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

2014/1/3

Orbs not bouncing off the walls

LifeTimeStudent LifeTimeStudent

2014/1/3

#
I am having trouble with making my orbs bounce off the wall when they hit it. They all run to the bottom right corner of the world and stay there. The instructions state: 9. Your next step is to account for a collision with the walls. You will accomplish this within a method called turnIfNeeded(), which will be called from the act() method of Orb. The turnIfNeeded() method may call four separate methods, which you write in this step. The four methods are: turnAtLeftWall(), turnAtRightWall(), turnAtFloor(), and turnAtRoof(). 10. Cause the Orb to make a noise if it bounces off of a wall. The code for one of the four methods, turnAtFloor(), is provided below. Use it as a model to create the three other methods. public void turnAtFloor() { if (getY() + getImage().getHeight()/2 >= getWorld().getHeight()) { vel.reverseY(); } } Here is my code: Please help me figure out what is wrong with it. Thanks in advance public class Orb extends Actor { private Velocity vel; //instance variable for Orb() constructor. private double exactX; private double exactY; private Velocity movement; private String sound = "4e.wav"; private boolean touched = false; /** * Creates a new velocity object with specified x and y speeds. */ public void Orb(int xSpeed, int ySpeed) { Velocity vel = new Velocity(0, 0); } public void act()//calls for the methods that tell the orb what to do { move(); turnIfNeeded(); } /** * method that controls the movement of the orb */ public void move() //7 { exactX = exactX + getX();// gets the location of the orb exactY = exactY + getY(); Velocity velocity = new Velocity(); velocity.getXSpeed();// gets the speed of the orb velocity.getYSpeed(); super.setLocation((int) exactX, (int) exactY);//sets the new location of the orb } /** * 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);//converts from double to int } /** * Set location. 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((int) x, (int) y);//converts from double to int } /** * 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; } /** * Check whether we have hit any of the edges of the universe. If so, bounce off it. */ private void turnIfNeeded() { turnAtLeftWall(); turnAtRightWall(); turnAtFloor(); turnAtRoof(); } /** * Check whether we have hit the left wall of the universe. If so, bounce off it. */ public void turnAtLeftWall() { //if touching the left side, turn if (getX() + getImage().getWidth()/2 >= getWorld().getWidth()) { vel.reverseX(); //Throws the error: //java.lang.NullPointerException //at Orb.turnAtLeftWall(Orb.java:101) //at Orb.turnIfNeeded(Orb.java:87) //at Orb.act(Orb.java:29) Greenfoot.playSound(sound); } } /** * Check whether we have hit the right edge of the universe. If so, bounce off it. */ public void turnAtRightWall() { //if touching the right side, turn if (getX() + getImage().getWidth()/2 >= getWorld().getWidth()) { vel.reverseX(); Greenfoot.playSound(sound); } } /** * Check whether we have hit the floor of the universe. If so, bounce off it. */ public void turnAtFloor() { //if at the bottom, turn if (getY() + getImage().getHeight()/2 >= getWorld().getHeight()) { vel.reverseY(); Greenfoot.playSound(sound); } } /** * Check whether we have hit the roof of the universe. If so, bounce off it. */ public void turnAtRoof() { //if at the top, turn if (getY() + getImage().getHeight()/2 >= getWorld().getHeight()) { vel.reverseY(); Greenfoot.playSound(sound); } } /** * play this sound when the orb hits any of the edges of the universe */ public void playSound() { Greenfoot.playSound(sound); } } public class Velocity { // instance variables double dx; double dy; int direction; double length; private int xSpeed = 0; private int ySpeed = 0; /** * Create a new, neutral velocity. */ public Velocity() { } /** * Constructor for objects of class Velocity * */ public Velocity(int initXSpeed, int initYSpeed) { xSpeed = initXSpeed; ySpeed = initYSpeed; this.dx = dx; this.dy = dy; } /** * Create a velocity by specifying the x and y offsets from start to end points. */ public Velocity(double dx, double dy) { this.dx = dx; this.dy = dy; updatePolar(); } /** * Set the direction of the velocity, leaving the length intact. */ public void setDirection(int direction) { this.direction = direction; updateCartesian(); } /** * Add another vector to the velocity. */ public void add(Velocity other) { dx += other.dx; dy += other.dy; updatePolar(); } /** * Set the length of the velocity, leaving the direction intact. */ public void setLength(double length) { this.length = length; updateCartesian(); } /** * Scale the velocity up (factor > 1) or down (factor < 1). The direction * remains unchanged. */ public void scale(double factor) { length = length * factor; updateCartesian(); } /** * Set this vector to the neutral velocity */ public void setNeutral() { dx = 0.0; dy = 0.0; length = 0.0; direction = 0; } /** * Revert to horizontal component of this movement velocity. */ public void revertHorizontal() { dx = -dx; updatePolar(); } /** * Revert to vertical component of this movement velocity. */ public void revertVertical() { dy = -dy; updatePolar(); } /** * Return the x offset of the velocity. */ public double getX() { return dx; } /** * Return the y offset of the velocity. */ public double getY() { return dy; } /** * Return the direction of the velocity (in degrees). 0 is EAST. */ public int getDirection() { return direction; } /** * Return the length of the velocity. */ 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); } /** * Get speed in the X direction * * return the speed in X direction */ public int getXSpeed() { return xSpeed; } /** * Get speed in the Y direction * * return the speed in Y direction */ public int getYSpeed() { return ySpeed; } /** * reverseX - reverse the speed in X direction */ public void reverseX() { xSpeed = -xSpeed; } /** * reverseY - reverse the speed in X direction */ public void reverseY() { ySpeed = -ySpeed; } /** * 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)); } }
Gevater_Tod4711 Gevater_Tod4711

2014/1/3

#
I think there are some problems in your turn methods and also in your move method. In your move method you probably wanted the Orb object to move in the direction of the Velocity. Therefore you should change the move method like this:
1
2
3
public void move() {
    setLocation((int) exactX + vel.getXSpeed(), (int) exactY + vel.getYSpeed());
}
Your turn methods should be changed like this I think:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void turnAtLeftWall() {
    //if touching the left side, turn
    if (getX() - getImage().getWidth()/2 <= 10) {
        vel.reverseX();
        Greenfoot.playSound(sound);
    }
}
 
public void turnAtRightWall() {
    //if touching the right side, turn
    if (getX() + getImage().getWidth()/2 >= getWorld().getWidth() - 10) {
        vel.reverseX();
        Greenfoot.playSound(sound);
    }
}
 
public void turnAtFloor() {
    //if at the bottom, turn
    if (getY() + getImage().getHeight()/2 >= getWorld().getHeight() - 10) {
        vel.reverseY();
        Greenfoot.playSound(sound);
    }
}
 
public void turnAtRoof() {
    //if at the top, turn
    if (getY() - getImage().getHeight()/2 <= 10) {
        vel.reverseY();
        Greenfoot.playSound(sound);
    }
}
danpost danpost

2014/1/3

#
The 'turnAtRight' and 'turnAtFloor' methods were fine the way you had them. The 'turnAtLeft' and 'turnAtRoof' methods, however, are not performing the correct comparisons. Your example method for 'turnAtFloor' has the y-coordinate for the location of the bottom edge of the image of your actor being compared to the y-coordinate for the bottom edge of the world. You need the 'turnAtLeft' method to compare the x-coordinate for the location of the left edge of the image of your actor compared to the x-coordinate for the left edge of the world (similar for the roof). Your 'nullPointerException' error is due to the fact that your 'vel' field is never assigned any value. You have a method called 'public void Orb' which appears to do that (your description says: "Creates a new velocity object with specified x and y speeds"; however, it is never called. Methods are declared with a return type (in this case, you have 'void' as the return type which indicates that nothing is returned from the method); constructors do not have return types and are executed anytime the 'new' keyword is used. Also, you have two arguments for 'Orb' which are never used within the block. Solution: remove the 'void' from the declaration statement of what should be the constructor and replace '(0, 0)' when creating the Velocity object with '(xSpeed, ySpeed)'.
LifeTimeStudent LifeTimeStudent

2014/1/3

#
Here is my new orb constructor: /** * Creates a new velocity object with specified x and y speeds. */ public Orb(int xSpeed, int ySpeed) { Velocity vel = new Velocity(xSpeed, ySpeed); } When I try to compile it, I get this error message: constructor Orb in class Orb cannot be applied to given types; required: int,int; found: no arguments; reason: actual and formal argument lists differ in length /** * Create a given number of orbs in the universe. */ public void randomOrb(int number) { for(int i=0; i<number; i++) { Orb Orb = new Orb(); int x = 50 + Greenfoot.getRandomNumber(getWidth() - 100); int y = 50 + Greenfoot.getRandomNumber(getHeight() - 100); addObject(Orb, x, y); } }
danpost danpost

2014/1/3

#
If you are setting specific values for the 'xSpeed' and 'ySpeed' fields of the Orb objects you create, they need to be passed to the current constructor. For example:
1
2
3
int xVel = 5;
int yVel = 3;
Orb orb = new Orb(xVel, yVel);
If you are setting random values for those fields, change the constructor declaration statement to
1
public Orb()
and select the random values for those fields in the constructor.
LifeTimeStudent LifeTimeStudent

2014/1/3

#
I am for sure setting specific values (per the assignment instructions). public class OrbWorld extends World { /** * Constructor for objects of class OrbWorld. * */ public OrbWorld() { // Create a new world with 600x400 cells with a cell size of 1x1 pixels. super(600, 400, 1); randomOrb(5);//5 random orbs are created } /** * Create a given number of orbs in the universe. */ public void randomOrb(int number) { for(int i=0; i<number; i++) { int xVel = 5; int yVel = 3; Orb orb = new Orb(xVel, yVel); int x = 50 + Greenfoot.getRandomNumber(getWidth() - 100); int y = 50 + Greenfoot.getRandomNumber(getHeight() - 100); addObject(Orb, x, y); //now I get an error message that says cannot find symbol //- variable Orb pointed to this line. These error messages mess //me up, I don't understand what it is trying to tell me is wrong and //how to fix it. } } }
danpost danpost

2014/1/3

#
Your class is called 'Orb'; the Orb object you created is called 'orb'. That is what you are adding to the world.
LifeTimeStudent LifeTimeStudent

2014/1/3

#
Sigh, thanks!! I have been looking at this for so many hours.
LifeTimeStudent LifeTimeStudent

2014/1/3

#
Now that, that problem is solved, Im still getting the null exception error when I click run (it compiles just fine): /** * Check whether we have hit the left wall of the universe. If so, bounce off it. */ public void turnAtLeftWall() { //if touching the left side, turn if(getX() + getImage().getWidth()/2 >= getWorld().getWidth()) { vel.reverseX(); //Throws the error: //at Orb.turnAtLeftWall(Orb.java:101) //at Orb.turnIfNeeded(Orb.java:87) //at Orb.act(Orb.java:28) Greenfoot.playSound(sound); } } What I understand you saying is this: “You need the 'turnAtLeft' method to compare the x-coordinate for the location of the left edge of the image of your actor (getX() + getImage().getWidth()/2) compared to the x-coordinate for the left edge of the world (getWorld().getWidth()).” Am I correct? If so, it seems as though that is what I have done. However, I am sure I do not understand correctly, what you are saying. I am sorry for my lack of understanding; I really want to learn what I am doing wrong and how I can fix it. Thanks for your patients!
danpost danpost

2014/1/3

#
The left edge of your image is at 'getX() - getImage().getWidth()/2' (minus; not plus) and the x-coordinate at the left edge of the world is zero.
You need to login to post a reply.