Title: Networked Drawing Program
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Networked Drawing Program

Features:

- Any number of players allowed
- Just like the previous program, mouse clicks convert points to generic points, the paint routine converts Disk generic locations to pixel locations.
- The following zip file has the Networked Drawing program along with gameNet and all of the other games discussed in "Networked Programs"
NetworkedPrograms.zip
- Scribble is very taxing to the socket. At some point we die with a exception in trying to write user Mouse Drags through the ObjectOutputStream.

MyMain.java

same as everything else including guiChat

MyGameInput.java

package Drawing_networked;

import java.awt.Color;
import java.awt.Point;
import java.io.Serializable;



public class MyGameInput  implements Serializable
{
    static final int CONNECTING=0;
    static final int DISCONNECTING=1;
    static final int MOUSE_PRESSED=2;
    static final int MOUSE_RELEASED=3;
    static final int MOUSE_DRAGGED=4;
    static final int SET_COLOR=5;
    static final int SET_DRAW_TYPE=6;
    static final int SET_FILLED=7;

    String sendersName;
    int cmd=CONNECTING;

    Point point=new Point(-1,-1);
    DrawType drawType;
    boolean filled;
    Color color;

    public void setName(String n)
    {
        sendersName =n;
    }
    public void setCmd(int cmd)
    {
        this.cmd = cmd;
    }

    public void setMousePoint(int cmd, Point dp)
    {
        this.cmd=cmd;
        point = dp;
    }

}




MyGameOutput.java


package Drawing_networked;

import java.io.Serializable;


public class MyGameOutput  implements Serializable
{
    MyGame myGame=null;

    public MyGameOutput(MyGame myGame)
    {
        this.myGame =myGame;
    }

}


MyGame.java


package Drawing_networked;


import gameNet.GameNet_CoreGame;

import java.io.Serializable;
import java.util.ArrayList;

public class MyGame extends GameNet_CoreGame implements Serializable{

    public Drawing drawing = new Drawing();
    public ArrayList<String> drawers = new ArrayList<String>();
    public String currentDrawer=null;

    public Object process(Object ob)
    {
        MyGameInput myGameInput= (MyGameInput)ob;
        getClientIndex(myGameInput.sendersName); //Adds new users if this is their first time

        switch(myGameInput.cmd)
        {
        case MyGameInput.MOUSE_PRESSED:
            if (currentDrawer == null)
                currentDrawer = myGameInput.sendersName;
            if (myGameInput.sendersName.equals(currentDrawer))
                drawing.mousePressed(myGameInput.point);
            break;
        case MyGameInput.MOUSE_RELEASED:
            if (myGameInput.sendersName.equals(currentDrawer))
            {
                drawing.mouseReleased(myGameInput.point);
                currentDrawer = null;
            }
            break;
        case MyGameInput.MOUSE_DRAGGED:
            if (myGameInput.sendersName.equals(currentDrawer))
                drawing.mouseDragged(myGameInput.point);
            break;
        case MyGameInput.CONNECTING:
            break;
        case MyGameInput.DISCONNECTING:
            drawers.remove(myGameInput.sendersName);
            break;
        case MyGameInput.SET_COLOR:
            drawing.setColor(myGameInput.color);
            break;
        case MyGameInput.SET_DRAW_TYPE:
            drawing.setDrawType(myGameInput.drawType);
            break;
        case MyGameInput.SET_FILLED:
            drawing.setFilled(myGameInput.filled);
            break;
        }

        return new MyGameOutput(this);
    }

    int getClientIndex(String name)
    {
        int index = drawers.indexOf(name);
        if (index < 0)
        {
            drawers.add(name);
            index = drawers.size() -1;
        }
        return index;
    }


}





Drawing.java


package Drawing_networked;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.io.Serializable;
import java.util.ArrayList;

enum DrawType {scribble, oval,  rectangle, polygon, line};

class DrawingProperties implements Serializable
{
    DrawType drawType;
    boolean filled;
    Color color;
    DrawingProperties(DrawType drawType, Color color, boolean filled)
    {
        this.drawType = drawType;
        this.color = color;
        this.filled = filled;
    }
}

public class Drawing  implements Serializable{
    DrawingProperties drawingProperties = new DrawingProperties(DrawType.rectangle, Color.blue, false);
    ArrayList shapeArr = new ArrayList();
    Shape inProgress = null;

    public void draw(Graphics g, BoardDimensions boardDimensions)
    {
        for (int i=0; i < shapeArr.size(); i++)
        {
            Shape s = shapeArr.get(i);
            s.draw(g, boardDimensions);
        }
        if (inProgress != null)
            inProgress.draw(g, boardDimensions);
    }

    public void setColor(Color color)
    {
        drawingProperties.color = color;

        //The following only gets used for Polygons
        if (inProgress != null)
            inProgress.setColor(color);
    }

    public void setFilled(boolean filled)
    {
        drawingProperties.filled = filled;

        // The following code is only needed for Polygons
        if (inProgress != null &&
                drawingProperties.drawType == DrawType.polygon)
        {
            PolygonShape p = (PolygonShape)inProgress;
            p.setFilled(filled);
        }
    }
    public void setDrawType(DrawType drawType)
    {
        // Most of this code is dealing with the Polygon case
        if (drawingProperties.drawType == DrawType.polygon)
            exitPolygonMode();

        drawingProperties.drawType = drawType;
    }


    private void exitPolygonMode()
    {
        if (inProgress != null)
            shapeArr.add(inProgress);
        inProgress = null;
    }

    public void mousePressed(Point p)
    {
        if (drawingProperties.drawType == DrawType.polygon)
        {
            if (inProgress == null)
            {
                inProgress = new PolygonShape(drawingProperties.color, drawingProperties.filled);
            }
            inProgress.subsequentPoint(p);
        }
        else
        {
            switch(drawingProperties.drawType)
            {
            case rectangle:
                inProgress = new Rectangle(drawingProperties.color, drawingProperties.filled);
                break;
            case oval:
                inProgress = new Oval(drawingProperties.color, drawingProperties.filled);
                break;
            case line:
                inProgress = new Line(drawingProperties.color);
                break;
            case scribble:
                inProgress = new Scribble(drawingProperties.color);
                break;
            }
            inProgress.firstPoint(p);
        }

    }
    public void mouseDragged(Point p)
    {
        switch(drawingProperties.drawType)
        {
        case rectangle:
        case oval:
        case scribble:
        case line:
            inProgress.subsequentPoint(p);
            break;
        }
    }
    public void mouseReleased(Point p)
    {
        if (drawingProperties.drawType != DrawType.polygon)
        {
            inProgress.subsequentPoint(p);
            shapeArr.add(inProgress);
            inProgress = null;
        }
    }

}

abstract class Shape  implements Serializable
{
    Color color;
    Shape ( Color c)
    {
        color =c;
    }
    void setColor(Color c)
    {
        color = c;
    }
    abstract void firstPoint(Point p);
    abstract void draw(Graphics g, BoardDimensions boardDimensions);
    abstract void subsequentPoint(Point p);
}



class Rectangle extends Shape  implements Serializable
{
    boolean filled=false;
    Point start;
    Point lastPoint;
    Rectangle(Color c, boolean filled)
    {
        super(c);
        lastPoint = start;
        this.filled = filled;
    }
    void firstPoint(Point p)
    {
        start = p;
        lastPoint =p;
    }
    void subsequentPoint(Point p)
    {
        lastPoint = p;
    }
    void draw(Graphics g, BoardDimensions boardDimensions)
    {
        g.setColor(color);
        Point s = boardDimensions.toPixels(start);
        Point l = boardDimensions.toPixels(lastPoint);
        int x = Math.min(s.x, l.x);
        int y = Math.min(s.y, l.y);
        int w = Math.abs(s.x - l.x);
        int h = Math.abs(s.y - l.y);
        if (filled)
            g.fillRect(x, y, w, h);
        else
            g.drawRect(x, y, w, h);
    }
}

class Line extends Shape  implements Serializable
{
    Point start;
    Point lastPoint;
    Line(Color c)
    {
        super(c);
    }
    void firstPoint(Point p)
    {
        start = p;
        lastPoint =p;
    }
    void subsequentPoint(Point p)
    {
        lastPoint = p;
    }
    void draw(Graphics g, BoardDimensions boardDimensions)
    {
        g.setColor(color);
        Point s = boardDimensions.toPixels(start);
        Point l = boardDimensions.toPixels(lastPoint);
        g.drawLine(s.x,  s.y,  l.x,  l.y);
    }
}

class Oval extends Shape  implements Serializable
{
    boolean filled=false;
    Point start;
    Point lastPoint;
    Oval(Color c, boolean filled)
    {
        super(c);
        this.filled = filled;
    }
    void firstPoint(Point p)
    {
        start = p;
        lastPoint =p;
    }
    void subsequentPoint(Point p)
    {
        lastPoint = p;
    }
    void draw(Graphics g, BoardDimensions boardDimensions)
    {
        g.setColor(color);
        Point s = boardDimensions.toPixels(start);
        Point l = boardDimensions.toPixels(lastPoint);
        int x = Math.min(s.x, l.x);
        int y = Math.min(s.y, l.y);
        int w = Math.abs(s.x - l.x);
        int h = Math.abs(s.y - l.y);
        if (filled)
            g.fillOval(x, y, w, h);
        else
            g.drawOval(x, y, w, h);
    }
}


class Scribble extends Shape  implements Serializable
{
    ArrayList points= new ArrayList();
    Scribble(Color c)
    {
        super(c);
    }
    void firstPoint(Point p)
    {
        points.add(p);
    }
    void subsequentPoint(Point p)
    {
        points.add(p);
    }
    void draw(Graphics g, BoardDimensions boardDimensions)
    {
        g.setColor(color);
        for (int i=1; i < points.size(); i++)
        {
            Point f = boardDimensions.toPixels(points.get(i-1));
            Point n = boardDimensions.toPixels(points.get(i));
            g.drawLine(f.x, f.y, n.x, n.y);
        }
    }
}

class PolygonShape extends Shape  implements Serializable
{
    ArrayList points= new ArrayList();
    boolean filled;
    PolygonShape(Color c, boolean filled)
    {
        super(c);
        this.filled = filled;
    }
    void setFilled(boolean filled)
    {
        this.filled = filled;
    }
    void firstPoint(Point p)
    { // currently not called
        points.add(p);
    }
    void draw(Graphics g, BoardDimensions boardDimensions)
    {
        int[] y = new int[points.size()];
        int[] x = new int[points.size()];
        g.setColor(color);

        for (int i=0; i < points.size(); i++)
        {
        	Point p = boardDimensions.toPixels(points.get(i));
            x[i]=p.x;
            y[i]=p.y;
        }
        Polygon poly = new Polygon(x, y, x.length);
        if (filled)
            g.fillPolygon(poly);
        else
            g.drawPolygon(poly);
    }
    void subsequentPoint(Point p)
    {
        points.add(p);
    }
}


MyUserInterface.java


package Drawing_networked;

import gameNet.GameNet_UserInterface;
import gameNet.GamePlayer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

public class MyUserInterface extends JFrame implements ActionListener, GameNet_UserInterface{

    DrawingPanel drawingPanel = new DrawingPanel();
    JButton polygon_done;
    JCheckBox filled ;
    JLabel currentDrawer;


    String[] colors = {"red", "green", "blue"};
    JRadioButton[] rbColors=new JRadioButton[colors.length];

    String[] shapes = {"rectangle", "oval","line","scribble", "polygon"};
    JRadioButton[] rbDrawType=new JRadioButton[shapes.length];

    GamePlayer myGamePlayer;
    MyGameInput myGameInput = new MyGameInput();

    MyGame myGame=null;


	@Override
	public void receivedMessage(Object ob) {
		MyGameOutput myGameOutput = (MyGameOutput)ob;
		myGame = myGameOutput.myGame;
		drawingPanel.newScreen(myGame);
		
		String cd = myGame.currentDrawer;		
		currentDrawer.setText((cd==null)?"":cd+ " drawing");
		
		DrawingProperties drawingProperties = myGame.drawing.drawingProperties;
		
		filled.setSelected(drawingProperties.filled);
		switch (drawingProperties.drawType)
		{
		case rectangle:
			filled.setVisible(true);
			polygon_done.setVisible(false);
			rbDrawType[0].setSelected(true);
			break;
		case oval:
			filled.setVisible(true);
			polygon_done.setVisible(false);
			rbDrawType[1].setSelected(true);
			break;
		case line:
			filled.setVisible(false);
			polygon_done.setVisible(false);
			rbDrawType[2].setSelected(true);
			break;
		case scribble:
			filled.setVisible(false);
			polygon_done.setVisible(false);
			rbDrawType[3].setSelected(true);
			break;
		case polygon:
			filled.setVisible(true);
			polygon_done.setVisible(true);
			rbDrawType[4].setSelected(true);
			break;			
		}
		if (drawingProperties.color.equals(Color.red))
		{
		    rbColors[0].setSelected(true);
		}
		else if (drawingProperties.color.equals(Color.green))
		{
		    rbColors[1].setSelected(true);			
		}
		else // must be blue
		{
		    rbColors[2].setSelected(true);			
		}

		
	}

	@Override
	public void startUserInterface(GamePlayer player) {
		myGamePlayer = player;
		drawingPanel.setGamePlayer(player);
		myGameInput.setName(myGamePlayer.getPlayerName());
		myGamePlayer.sendMessage(myGameInput);
	}

    MyUserInterface()
    {
        super("My Drawing Program");

        setSize(800, 400);
        addWindowListener( new Termination());

        myLayout();


        setVisible(true);
    }

    private void myLayout( )
    {
        ButtonGroup shapeGroup= new ButtonGroup();
        ButtonGroup colorGroup= new ButtonGroup();

        setLayout(new BorderLayout());

        //Drawing in the Center
        add(drawingPanel, BorderLayout.CENTER);

        JPanel north = new JPanel();
        north.setLayout(new FlowLayout());

        currentDrawer = new JLabel("");
        north.add(currentDrawer);
        filled = new JCheckBox("filled");
        north.add(filled);
        filled.addActionListener(this);


        // Create the Shape Radio buttons on the North
        for (int i= 0; i < shapes.length; i++)
        {
            JRadioButton rb = new JRadioButton(shapes[i]);
            rbDrawType[i] = rb;
            if (i == 0)
                rb.setSelected(true);
            shapeGroup.add(rb);
            north.add(rb);
            rb.addActionListener(this);
        }

        polygon_done = new JButton("polygon_done");

        polygon_done.setVisible(false);
        polygon_done.addActionListener(this);
        north.add(polygon_done);

        add(north, BorderLayout.NORTH);

        JPanel west = new JPanel();
        west.setLayout(new GridLayout(0, 1));

        //Create the Color radio buttons on the West
        for (int i=0; i < colors.length; i++)
        {
            JRadioButton rb = new JRadioButton(colors[i]);
            rbColors[i] = rb;
            if (i==0)
                rb.setSelected(true);
            colorGroup.add(rb);
            west.add(rb);
            rb.addActionListener(this);
        }
        add(west, BorderLayout.WEST);

    }


    @Override
    public void actionPerformed(ActionEvent actionEvent) {
        String action = actionEvent.getActionCommand();
        System.out.println(action);

        switch(action)
        {
        case "filled":
        	myGameInput.filled = filled.isSelected();
        	myGameInput.setCmd(MyGameInput.SET_FILLED);
            break;
        case "red":
        	myGameInput.color = Color.red;
        	myGameInput.setCmd(MyGameInput.SET_COLOR);
            break;
        case "green":
        	myGameInput.color = Color.green;
        	myGameInput.setCmd(MyGameInput.SET_COLOR);
            break;
        case "blue":
        	myGameInput.color = Color.blue;
        	myGameInput.setCmd(MyGameInput.SET_COLOR);
            break;
        case "rectangle":
        	myGameInput.drawType = DrawType.rectangle;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;
        case "oval":
        	myGameInput.drawType = DrawType.oval;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;
        case "line":
        	myGameInput.drawType = DrawType.line;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;

        case "scribble":
        	myGameInput.drawType = DrawType.scribble;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;
        case "polygon":
        	myGameInput.drawType = DrawType.polygon;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;
        case "polygon_done":
        	myGameInput.drawType = DrawType.polygon;
        	myGameInput.setCmd(MyGameInput.SET_DRAW_TYPE);
            break;
        }
        myGamePlayer.sendMessage(myGameInput);

    }

	//*******************************************
	//  Inner class
	//*******************************************
	class Termination extends WindowAdapter
	{
		public void windowClosing(WindowEvent e)
		{
			myGameInput.setCmd(MyGameInput.DISCONNECTING);
			myGamePlayer.sendMessage(myGameInput);
			myGamePlayer.doneWithGame();
			System.exit(0);
		}
	}


}


DrawingPanel.java


package Drawing_networked;

import gameNet.GamePlayer;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class DrawingPanel extends JPanel{
   // Drawing drawing = new Drawing(); // This will now come from the MyGame class
    MyGame myGame=null;

    Image offScreenImage = null;
    Dimension screenDimension = null;
    BoardDimensions boardDimensions = new BoardDimensions();
    GamePlayer myGamePlayer=null;
    MyGameInput myGameInput= new MyGameInput();


    public void setGamePlayer(GamePlayer gp)
    {
        myGamePlayer = gp;
        myGameInput.setName(myGamePlayer.getPlayerName());
    }

    public void newScreen(MyGame myGame)
    {
        this.myGame = myGame;
        repaint();
    }


    DrawingPanel()
    {
        MyMouseHandler mmh = new MyMouseHandler();
        addMouseListener(mmh);
        addMouseMotionListener(mmh);
    }
    public void paint(Graphics screen)
    {
        Dimension dimen = getSize();
        if (offScreenImage==null || !dimen.equals(screenDimension))
        {
            screenDimension = dimen;
            offScreenImage = createImage(dimen.width, dimen.height);
        }
        Graphics g = offScreenImage.getGraphics();
        g.setColor(Color.white);
        g.fillRect(0, 0, dimen.width, dimen.height);

        boardDimensions.setParms(dimen);
        if (myGame == null)
            return;

        myGame.drawing.draw(g, boardDimensions);

        screen.drawImage(offScreenImage, 0,0, this);
    }


    // INNER Class
    class MyMouseHandler extends MouseAdapter
    {
        Point getPoint(MouseEvent e)
        {
            return boardDimensions.toGeneric(e.getPoint());
        }
        public void mousePressed(MouseEvent e)
        {
            Point p = getPoint(e);
            myGameInput.setMousePoint(MyGameInput.MOUSE_PRESSED, p);
            myGamePlayer.sendMessage(myGameInput);
            //drawing.mousePressed(getPoint(e));
            //repaint();  // We will repaint our drawing when this comes from the MyGame class
        }
        public void mouseReleased(MouseEvent e)
        {
            Point p = getPoint(e);
            myGameInput.setMousePoint(MyGameInput.MOUSE_RELEASED, p);
            myGamePlayer.sendMessage(myGameInput);
        }
        public void mouseDragged(MouseEvent e)
        {
            Point p = getPoint(e);
            myGameInput.setMousePoint(MyGameInput.MOUSE_DRAGGED, p);
            myGamePlayer.sendMessage(myGameInput);
        }
    }

    // End of INNER Class
}




BoardDimensions.java


package Drawing_networked;

import java.awt.Dimension;
import java.awt.Point;

public class BoardDimensions {

    private int screen_width=-1, screen_height=-1;
    private double scale_width=0.0, scale_height=0.0;
    private double generic_size = 1000000.0; // One million

    public void setParms(Dimension dimension)
    {
        screen_width = dimension.width;
        screen_height = dimension.height;
        scale_width = generic_size/screen_width;
        scale_height = generic_size/screen_height;
    }
    Point toGeneric(Point p)
    {
        int x = (int)(p.x * scale_width);
        int y = (int)(p.y * scale_height);
        return new Point(x,y);
    }
    Point toPixels(Point p)
    {
        int x = (int)(p.x / scale_width);
        int y = (int)(p.y / scale_height);
        return new Point(x,y);
    }


}



October 20, 2013 8:58 AM