Welcome to Dream.In.Code
Click Here
Getting Help is Easy!

Join 118,659 Programmers for FREE! Ask your question and get quick answers from experts. There are 861 online right now! We've got more than 500 tutorials and 2,000 snippets. Join and find out why Dream.In.Code is the #1 programming help community on the internet! Registration is fast and FREE... Join Now!



Sailing - Or how do you make an irregular Shape

 
Reply to this topicStart new topic

Sailing - Or how do you make an irregular Shape, How to use Shape to represent a boat

peter.ruffner
post 24 May, 2008 - 11:36 PM
Post #1


New D.I.C Head

*
Joined: 5 May, 2008
Posts: 4

Hello All,
I was wondering if I could get some help here. This is an applet to teach basic sailing skills (reading the wind, adjusting the boat direction and sails, etc.) You steer the boat by using the left and right arrow keys. But note, like driving a boat with a tiller, you push left to turn right and you push right to turn left. Right now, you can speed up and slow down by using the up and down arrow keys. I've ordered a book, "This physics of sailing" to help program how the sails work.

I have a blue JPanel with a proposed path of white dots on it. It has little black lines moving around which represent boats. Notice that when they turn they rotate around their bow - like a real boat when it turns. (I want to move the center (the boats location) to where the mast would be - about a third of the length behind the bow.)

What I need help with is using shapes to make the boat shape. (it might be easier to do without Shapes.) I think it is some combination of GeneralPath and the Shape interface. You can't extend GeneralPath and if I use Shape, I still need some kind of base object.

Some issues:
1) If I want to use AffineTransform, can I change the direction before drawing each boat?
2) Do I have to draw each boat in a buffer with a new AffineTransform and copy them to the JPanel using transparency to have the background dropout? (And turn off antialiasing until the copy.)
3) Shape wise, it should have one or two arcs for the bow and some lines or a rectangle for the stern. I'd like it to have a white fill with a black outline.
4) The rudder and sails are sub shapes - how do I do that?
5) To use the keys, I needed to set the focus, it doesn't work automatically - you still have to click on the JPanel to set the focus. Can someone tell me how to fix this?
6) Currently moveold() and drawold() are active so you can see how it works.
7) It has a main() so you can run it from NetBeans IDE.
8) Thanks in advance for any help.


Here is the Sailboat class
CODE

//Sailboat.java

package ruffner.peter.Sailboat;

//import java.awt.Rectangle;
import java.awt.Graphics2D;
import java.awt.geom.Arc2D;
import java.awt.geom.GeneralPath;
import java.awt.Color;
import java.awt.Graphics.*;
import java.awt.Shape;
import java.awt.Dimension;
//import java.awt.geom.GeneralPath;

//Arc2D.Double(double x, double y, double w, double h, double start, double extent, int type)

//public class Sailboat extends GeneralPath implements Shape {
public class Sailboat extends Object {

    protected int x, x2;
    protected int y, y2;
    int length;
    int width;
    int panelWidth;
    int panelHeight;
    Dimension d;
    double course;
    double rudder = 0;
    double speed;
    double max_speed;
    Boolean splitH = false;
    Boolean splitV = false;
    Arc2D myshape;

    //only constructor used
    public Sailboat(Dimension nd) {
        d = nd; //edges of panel
        x = (int)(Math.random() * d.width);
        y = (int)(Math.random() * d.height);
        panelWidth = nd.width;
        panelHeight = nd.height;
        length = 14;
        width = 4;
        course = (Math.random() * 360f);
        speed = (Math.random() * 5f);
        max_speed = 5;
    }

    //this constructor not used
    public Sailboat(int nx, int ny, double ncourse, Dimension nd) {
        //x = nx;
        //y = ny;
        x = (int)(Math.random() * 24);
        y = (int)(Math.random() * 120);
        length = 14;
        width = 4;
        course = ncourse;
        d = nd;
        panelWidth = nd.width;
        panelHeight = nd.height - 30;
        speed = 2;
        max_speed = 5;
    }


    //this constructor not used
    public Sailboat(int nx, int ny, int nl, int nw, double nc, double ns, double nms, Dimension nd) {
        x = nx;
        y = ny;
        length = nl;
        width = nw;
        course = nc;
        d = nd;
        panelWidth = nd.width;
        panelHeight = nd.height;
        speed = ns;
        max_speed = nms;
    }


    //public void moveTo(int nx, int ny){
    //    x = nx;
    //    y = ny;
    //}

    public void turnRight(){
        rudder = addDegree(rudder, 2);
        if (rudder > 45){
            rudder = 45;
        }
        //System.out.println("x=" + x + "/y=" + y + "/course=" + course + "/rudder=" + rudder + "/speed=" + speed);
    }

    public void turnLeft(){
        rudder  = addDegree(rudder, -2);
        if (rudder < -45){
            rudder = -45;
        }
        //System.out.println("x=" + x + "/y=" + y + "/course=" + course + "/rudder=" + rudder + "/speed=" + speed);
    }

    public void incSpeed(){
        speed = (int)speed + 1;
        //System.out.println("x=" + x + "/y=" + y + "/course=" + course + "/rudder=" + rudder + "/speed=" + speed);
    }

    public void decSpeed(){
        speed = (int)speed - 1;
        //System.out.println("x=" + x + "/y=" + y + "/course=" + course + "/rudder=" + rudder + "/speed=" + speed);
    }
    
    //use sin, cos to get next ccordinate pair
    public void moveold() {
        course -= rudder;

        //find the front of the boat
        x = x + (int)(Math.sin(Math.toRadians(course)) * speed);
        y = y + (int)(Math.cos(Math.toRadians(course)) * speed);

        //find the back of the boat
        x2 = (x + (int)(Math.sin(Math.toRadians(addDegree(course + rudder, 180d))) * (length + 3)));
        y2 = (y + (int)(Math.cos(Math.toRadians(addDegree(course + rudder, 180d))) * (length + 3)));

        //horizontal split
        //right side
        if (x > panelWidth || x2 > panelWidth) {    //part is off right side
            if (x > panelWidth && x2 > panelWidth){    //all is off right side
                x = x - panelWidth;                    //reset position to left side of panel
                splitH = false;
            }else{                                    //back  is off right side of panel
                splitH = true;                        //boat straddels H - draw two boats
            }
        }
        //left side
        if (x < 0 || x2 < 0){                        //part is off left side
            if (x < 0 && x2 < 0){                     //all is off left side
                x = x + panelWidth;                    //reset position to right side of panel
                splitH = false;
                //System.out.println("reseting location to x=" + x + "/y=" + y + "/width=" + panelWidth);
            }else{                        //back  is off left side of panel
                splitH = true;                        //boat straddels H - draw two boats
            }
        }

        //vertical split
        //bottom
        if (y > panelHeight || y2 > panelHeight) {    //part is off right side
            if (y > panelHeight && y2 > panelHeight){//all is not off right side
                y = y - panelHeight;                //reset position to left side of panel
                splitV = false;
            }else{            //back  is off right side of panel
                splitV = true;                        //boat straddels H - draw two boats
            }
        }
        //top
        if (y < 0 || y2 < 0){                        //front is off left side
            if (y < 0 && y2 < 0){                     //all is not off left side
                y = y + panelHeight;                //reset position to right side of panel
                splitV = false;
            }else{                        //back  is off left side of panel
                splitV = true;                        //boat straddels H - draw two boats
            }
        }
    }


    


    //use sin, cos to get next ccordinate pair
    public void move() {
        course = addDegree(course, rudder);

        //find the front of the boat
        //location plus 1/3 length

        //location minus 2/3 length

        
        
/*
        //check for wrap-around on screen
        //horizontal split
        //right side
        if (x > panelWidth || x2 > panelWidth) {    //part is off right side
            if (x > panelWidth && x2 > panelWidth){    //all is off right side
                x = x - panelWidth;                    //reset position to left side of panel
                splitH = false;
            }else{                                    //back  is off right side of panel
                splitH = true;                        //boat straddels H - draw two boats
            }
        }
        //left side
        if (x < 0 || x2 < 0){                        //part is off left side
            if (x < 0 && x2 < 0){                     //all is off left side
                x = x + panelWidth;                    //reset position to right side of panel
                splitH = false;
                //System.out.println("reseting location to x=" + x + "/y=" + y + "/width=" + panelWidth);
            }else{                        //back  is off left side of panel
                splitH = true;                        //boat straddels H - draw two boats
            }
        }

        //vertical split
        //bottom
        if (y > panelHeight || y2 > panelHeight) {    //part is off right side
            if (y > panelHeight && y2 > panelHeight){//all is not off right side
                y = y - panelHeight;                //reset position to left side of panel
                splitV = false;
            }else{            //back  is off right side of panel
                splitV = true;                        //boat straddels H - draw two boats
            }
        }
        //top
        if (y < 0 || y2 < 0){                        //front is off left side
            if (y < 0 && y2 < 0){                     //all is not off left side
                y = y + panelHeight;                //reset position to right side of panel
                splitV = false;
            }else{                        //back  is off left side of panel
                splitV = true;                        //boat straddels H - draw two boats
            }

        }
*/
    }


    public void draw() {
    }


    public void draw(Graphics2D g2) {
        int x1;
        int y1;
        //int x2;
        //int y2;

        int a1;
        int b1;
        int a2;
        int b2;

        //aft is course - 180 degrees
        //draw hull
        

        //draw rudder - start at the end of the boat and go 5 pixcels

/*
        if (splitH || splitV){
            a1 = x;
            b1 = y;
            if (splitH){                    //split H
                //split H
                if (x > panelWidth) {        //right
                    a1 = x - panelWidth;
                }else {                        //left
                    a1 = x + panelWidth;
                }
            }
            if (splitV){                            //split V
                //split v
                if (y > panelHeight) {        //bottom
                    b1 = y - panelHeight;
                }else {                        //top
                    b1 = y + panelHeight;
                }
            }
            g2.setColor(Color.red);
            g2.drawLine(a1, b1, a2, b2);
            g2.drawLine(a1, b1, a2, b2);
        }
*/
    }


    //old version of draw backed up
    public void drawold(Graphics2D g2) {
        int x1;
        int y1;
        //int x2;
        //int y2;

        int a1;
        int b1;
        int a2;
        int b2;

        //aft is course - 180 degrees
        g2.setColor(Color.black);
        //draw hull
        x1 = (x + (int)(Math.sin(Math.toRadians(addDegree(course, 180d))) * length));
        y1 = (y + (int)(Math.cos(Math.toRadians(addDegree(course, 180d))) * length));
        //x2 =;
        //y2 =;
        g2.drawLine(x, y, x1, y1);

        //draw rudder - start at the end of the boat and go 5 pixcels
        //x1 = (x + (int)(Math.sin(Math.toRadians(addDegree(course, 180d))) * (length + 2)));
        //y1 = (y + (int)(Math.cos(Math.toRadians(addDegree(course, 180d))) * (length + 2)));
        x2 = (x1 + (int)(Math.sin(Math.toRadians(addDegree(addDegree(course, rudder), 180d))) * (0 + 5)));
        y2 = (y1 + (int)(Math.cos(Math.toRadians(addDegree(addDegree(course, rudder), 180d))) * (0 + 5)));
        g2.drawLine(x1, y1, x2, y2);

        if (splitH || splitV){
            a1 = x;
            b1 = y;
            if (splitH){                    //split H
                //split H
                if (x > panelWidth) {        //right
                    a1 = x - panelWidth;
                }else {                        //left
                    a1 = x + panelWidth;
                }
            }
            if (splitV){                            //split V
                //split v
                if (y > panelHeight) {        //bottom
                    b1 = y - panelHeight;
                }else {                        //top
                    b1 = y + panelHeight;
                }
            }
            g2.setColor(Color.red);
            a2 = (a1 + (int)(Math.sin(Math.toRadians(addDegree(course, 180d))) * length));
            b2 = (b1 + (int)(Math.cos(Math.toRadians(addDegree(course, 180d))) * length));
            g2.drawLine(a1, b1, a2, b2);
            //a1 = (x2 + (int)(Math.sin(Math.toRadians(addDegree(course, 180d))) * (length + 2)));
            //b1 = (y2 + (int)(Math.cos(Math.toRadians(addDegree(course, 180d))) * (length + 2)));
            a2 = (a1 + (int)(Math.sin(Math.toRadians(addDegree(addDegree(course, rudder), 180d))) * (0 + 5)));
            b2 = (b1 + (int)(Math.cos(Math.toRadians(addDegree(addDegree(course, rudder), 180d))) * (0 + 5)));
            g2.drawLine(a1, b1, a2, b2);
        }
    }


    public double addDegree(double a, double b) {

        return((a + b) % 360d);
    }

        @Override
    public String toString(){
        String s = "x=" + x + "/y=" + y + "/course=" + course + "/rudder=" + rudder;
        return (s);
    }
}


The Sailing class doesn't seem to fit here so it is included in a zip file.



This post has been edited by peter.ruffner: 25 May, 2008 - 11:30 PM


Attached File(s)
Attached File  ruffner.zip ( 5.28k ) Number of downloads: 16
User is offlineProfile CardPM

Go to the top of the page


peter.ruffner
post 24 May, 2008 - 11:45 PM
Post #2


New D.I.C Head

*
Joined: 5 May, 2008
Posts: 4

Here is a zip file with everything (I hope - I don't know why the files got cut off.)
This post is not needed as I have added a zip file to the original post.

This post has been edited by peter.ruffner: 25 May, 2008 - 11:32 PM


Attached File(s)
Attached File  Sailing1.zip ( 34.26k ) Number of downloads: 15
User is offlineProfile CardPM

Go to the top of the page

Fast ReplyReply to this topicStart new topic
Time is now: 10/12/08 04:02AM

Live Help!

Tutorials

Programming

Web Development

Reference Sheets

Code Snippets

Bye Bye Ads

Free DIC T-Shirt

T-Shirt Example

Related Sites

Monthly Drawing

Thumb Drive

Partners

Top Contributors

Top 10 Kudos This Month