Posts Tagged ‘import’

Last exercise combine two image side-by-side. In this post, the two images overlap with alpha setting. The layout is same as in last exercise “Combine bitmap side-by-side“. Main code: package com.test.androidimageprocessing; import java.io.FileNotFoundException; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ImageView; import…

Read More »

AndroidDrawBitmap_BlurMaskFilter

This takes a mask, and blurs its edge by the specified radius. Whether or or not to include the original mask, and whether the blur goes outside, inside, or straddles, the original mask’s border, is controlled by the Blur enum. package com.example.androiddrawbitmap; import java.io.FileNotFoundException; import android.net.Uri; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BlurMaskFilter; import android.graphics.Canvas;…

Read More »

 

In this part of the Java 2D games tutorial we will create a simple Pacman game clone.

Pacman is an arcade game originally developed by a Japanese company Namco in 1980. Pacman became one of the most popular arcade games ever.

Development

The following code example is a remake of a Pacman game by Brian Postma available at javaboutique. I have modified and simplified the code. So that it is easier to understand.

The goal of the game is to collect all the points in the maze and avoid the ghosts. The pacman is animated in two ways. His position in the maze and his body. We animate his body with four images, depending on the direction. The animation is used to create the illusion of pacman opening and closing his mouth. The maze consists of 15 x 15 squares. The structure of the maze is based on a simple array of integers. Pacman has three lives. We also count the score.

The game consists of two files.

Board.java
package pacman;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {

    Dimension d;
    Font smallfont = new Font("Helvetica", Font.BOLD, 14);

    FontMetrics fmsmall, fmlarge;
    Image ii;
    Color dotcolor = new Color(192, 192, 0);
    Color mazecolor;

    boolean ingame = false;
    boolean dying = false;

    final int blocksize = 24;
    final int nrofblocks = 15;
    final int scrsize = nrofblocks * blocksize;
    final int pacanimdelay = 2;
    final int pacmananimcount = 4;
    final int maxghosts = 12;
    final int pacmanspeed = 6;

    int pacanimcount = pacanimdelay;
    int pacanimdir = 1;
    int pacmananimpos = 0;
    int nrofghosts = 6;
    int pacsleft, score;
    int deathcounter;
    int[] dx, dy;
    int[] ghostx, ghosty, ghostdx, ghostdy, ghostspeed;

    Image ghost;
    Image pacman1, pacman2up, pacman2left, pacman2right, pacman2down;
    Image pacman3up, pacman3down, pacman3left, pacman3right;
    Image pacman4up, pacman4down, pacman4left, pacman4right;

    int pacmanx, pacmany, pacmandx, pacmandy;
    int reqdx, reqdy, viewdx, viewdy;

    final short leveldata[] =
    { 19, 26, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 22,
      21, 0,  0,  0,  17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20,
      21, 0,  0,  0,  17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 
      21, 0,  0,  0,  17, 16, 16, 24, 16, 16, 16, 16, 16, 16, 20, 
      17, 18, 18, 18, 16, 16, 20, 0,  17, 16, 16, 16, 16, 16, 20,
      17, 16, 16, 16, 16, 16, 20, 0,  17, 16, 16, 16, 16, 24, 20, 
      25, 16, 16, 16, 24, 24, 28, 0,  25, 24, 24, 16, 20, 0,  21, 
      1,  17, 16, 20, 0,  0,  0,  0,  0,  0,  0,  17, 20, 0,  21,
      1,  17, 16, 16, 18, 18, 22, 0,  19, 18, 18, 16, 20, 0,  21,
      1,  17, 16, 16, 16, 16, 20, 0,  17, 16, 16, 16, 20, 0,  21, 
      1,  17, 16, 16, 16, 16, 20, 0,  17, 16, 16, 16, 20, 0,  21,
      1,  17, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 20, 0,  21,
      1,  17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 0,  21,
      1,  25, 24, 24, 24, 24, 24, 24, 24, 24, 16, 16, 16, 18, 20,
      9,  8,  8,  8,  8,  8,  8,  8,  8,  8,  25, 24, 24, 24, 28 };

    final int validspeeds[] = { 1, 2, 3, 4, 6, 8 };
    final int maxspeed = 6;

    int currentspeed = 3;
    short[] screendata;
    Timer timer;

    public Board() {

        GetImages();

        addKeyListener(new TAdapter());

        screendata = new short[nrofblocks * nrofblocks];
        mazecolor = new Color(5, 100, 5);
        setFocusable(true);

        d = new Dimension(400, 400);

        setBackground(Color.black);
        setDoubleBuffered(true);

        ghostx = new int[maxghosts];
        ghostdx = new int[maxghosts];
        ghosty = new int[maxghosts];
        ghostdy = new int[maxghosts];
        ghostspeed = new int[maxghosts];
        dx = new int[4];
        dy = new int[4];
        timer = new Timer(40, this);
        timer.start();
    }

    public void addNotify() {
        super.addNotify();
        GameInit();
    }

    public void DoAnim() {
        pacanimcount--;
        if (pacanimcount <= 0) {
            pacanimcount = pacanimdelay;
            pacmananimpos = pacmananimpos + pacanimdir;
            if (pacmananimpos == (pacmananimcount - 1) || pacmananimpos == 0)
                pacanimdir = -pacanimdir;
        }
    }

    public void PlayGame(Graphics2D g2d) {
        if (dying) {
            Death();
        } else {
            MovePacMan();
            DrawPacMan(g2d);
            moveGhosts(g2d);
            CheckMaze();
        }
    }

    public void ShowIntroScreen(Graphics2D g2d) {

        g2d.setColor(new Color(0, 32, 48));
        g2d.fillRect(50, scrsize / 2 - 30, scrsize - 100, 50);
        g2d.setColor(Color.white);
        g2d.drawRect(50, scrsize / 2 - 30, scrsize - 100, 50);

        String s = "Press s to start.";
        Font small = new Font("Helvetica", Font.BOLD, 14);
        FontMetrics metr = this.getFontMetrics(small);

        g2d.setColor(Color.white);
        g2d.setFont(small);
        g2d.drawString(s, (scrsize - metr.stringWidth(s)) / 2, scrsize / 2);
    }

    public void DrawScore(Graphics2D g) {
        int i;
        String s;

        g.setFont(smallfont);
        g.setColor(new Color(96, 128, 255));
        s = "Score: " + score;
        g.drawString(s, scrsize / 2 + 96, scrsize + 16);
        for (i = 0; i < pacsleft; i++) {
            g.drawImage(pacman3left, i * 28 + 8, scrsize + 1, this);
        }
    }

    public void CheckMaze() {
        short i = 0;
        boolean finished = true;

        while (i < nrofblocks * nrofblocks && finished) {
            if ((screendata[i] & 48) != 0)
                finished = false;
            i++;
        }

        if (finished) {
            score += 50;

            if (nrofghosts < maxghosts)
                nrofghosts++;
            if (currentspeed < maxspeed)
                currentspeed++;
            LevelInit();
        }
    }

    public void Death() {

        pacsleft--;
        if (pacsleft == 0)
            ingame = false;
        LevelContinue();
    }

    public void moveGhosts(Graphics2D g2d) {
        short i;
        int pos;
        int count;

        for (i = 0; i < nrofghosts; i++) {
            if (ghostx[i] % blocksize == 0 && ghosty[i] % blocksize == 0) {
                pos =
 ghostx[i] / blocksize + nrofblocks * (int)(ghosty[i] / blocksize);

                count = 0;
                if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
                    dx[count] = -1;
                    dy[count] = 0;
                    count++;
                }
                if ((screendata[pos] & 2) == 0 && ghostdy[i] != 1) {
                    dx[count] = 0;
                    dy[count] = -1;
                    count++;
                }
                if ((screendata[pos] & 4) == 0 && ghostdx[i] != -1) {
                    dx[count] = 1;
                    dy[count] = 0;
                    count++;
                }
                if ((screendata[pos] & 8) == 0 && ghostdy[i] != -1) {
                    dx[count] = 0;
                    dy[count] = 1;
                    count++;
                }

                if (count == 0) {
                    if ((screendata[pos] & 15) == 15) {
                        ghostdx[i] = 0;
                        ghostdy[i] = 0;
                    } else {
                        ghostdx[i] = -ghostdx[i];
                        ghostdy[i] = -ghostdy[i];
                    }
                } else {
                    count = (int)(Math.random() * count);
                    if (count > 3)
                        count = 3;
                    ghostdx[i] = dx[count];
                    ghostdy[i] = dy[count];
                }

            }
            ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
            ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
            DrawGhost(g2d, ghostx[i] + 1, ghosty[i] + 1);

            if (pacmanx > (ghostx[i] - 12) && pacmanx < (ghostx[i] + 12) &&
                pacmany > (ghosty[i] - 12) && pacmany < (ghosty[i] + 12) &&
                ingame) {

                dying = true;
                deathcounter = 64;

            }
        }
    }

    public void DrawGhost(Graphics2D g2d, int x, int y) {
        g2d.drawImage(ghost, x, y, this);
    }

    public void MovePacMan() {
        int pos;
        short ch;

        if (reqdx == -pacmandx && reqdy == -pacmandy) {
            pacmandx = reqdx;
            pacmandy = reqdy;
            viewdx = pacmandx;
            viewdy = pacmandy;
        }
        if (pacmanx % blocksize == 0 && pacmany % blocksize == 0) {
            pos =
 pacmanx / blocksize + nrofblocks * (int)(pacmany / blocksize);
            ch = screendata[pos];

            if ((ch & 16) != 0) {
                screendata[pos] = (short)(ch & 15);
                score++;
            }

            if (reqdx != 0 || reqdy != 0) {
                if (!((reqdx == -1 && reqdy == 0 && (ch & 1) != 0) ||
                      (reqdx == 1 && reqdy == 0 && (ch & 4) != 0) ||
                      (reqdx == 0 && reqdy == -1 && (ch & 2) != 0) ||
                      (reqdx == 0 && reqdy == 1 && (ch & 8) != 0))) {
                    pacmandx = reqdx;
                    pacmandy = reqdy;
                    viewdx = pacmandx;
                    viewdy = pacmandy;
                }
            }

            // Check for standstill
            if ((pacmandx == -1 && pacmandy == 0 && (ch & 1) != 0) ||
                (pacmandx == 1 && pacmandy == 0 && (ch & 4) != 0) ||
                (pacmandx == 0 && pacmandy == -1 && (ch & 2) != 0) ||
                (pacmandx == 0 && pacmandy == 1 && (ch & 8) != 0)) {
                pacmandx = 0;
                pacmandy = 0;
            }
        }
        pacmanx = pacmanx + pacmanspeed * pacmandx;
        pacmany = pacmany + pacmanspeed * pacmandy;
    }

    public void DrawPacMan(Graphics2D g2d) {
        if (viewdx == -1)
            DrawPacManLeft(g2d);
        else if (viewdx == 1)
            DrawPacManRight(g2d);
        else if (viewdy == -1)
            DrawPacManUp(g2d);
        else
            DrawPacManDown(g2d);
    }

    public void DrawPacManUp(Graphics2D g2d) {
        switch (pacmananimpos) {
        case 1:
            g2d.drawImage(pacman2up, pacmanx + 1, pacmany + 1, this);
            break;
        case 2:
            g2d.drawImage(pacman3up, pacmanx + 1, pacmany + 1, this);
            break;
        case 3:
            g2d.drawImage(pacman4up, pacmanx + 1, pacmany + 1, this);
            break;
        default:
            g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
            break;
        }
    }

    public void DrawPacManDown(Graphics2D g2d) {
        switch (pacmananimpos) {
        case 1:
            g2d.drawImage(pacman2down, pacmanx + 1, pacmany + 1, this);
            break;
        case 2:
            g2d.drawImage(pacman3down, pacmanx + 1, pacmany + 1, this);
            break;
        case 3:
            g2d.drawImage(pacman4down, pacmanx + 1, pacmany + 1, this);
            break;
        default:
            g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
            break;
        }
    }

    public void DrawPacManLeft(Graphics2D g2d) {
        switch (pacmananimpos) {
        case 1:
            g2d.drawImage(pacman2left, pacmanx + 1, pacmany + 1, this);
            break;
        case 2:
            g2d.drawImage(pacman3left, pacmanx + 1, pacmany + 1, this);
            break;
        case 3:
            g2d.drawImage(pacman4left, pacmanx + 1, pacmany + 1, this);
            break;
        default:
            g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
            break;
        }
    }

    public void DrawPacManRight(Graphics2D g2d) {
        switch (pacmananimpos) {
        case 1:
            g2d.drawImage(pacman2right, pacmanx + 1, pacmany + 1, this);
            break;
        case 2:
            g2d.drawImage(pacman3right, pacmanx + 1, pacmany + 1, this);
            break;
        case 3:
            g2d.drawImage(pacman4right, pacmanx + 1, pacmany + 1, this);
            break;
        default:
            g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
            break;
        }
    }

    public void DrawMaze(Graphics2D g2d) {
        short i = 0;
        int x, y;

        for (y = 0; y < scrsize; y += blocksize) {
            for (x = 0; x < scrsize; x += blocksize) {
                g2d.setColor(mazecolor);
                g2d.setStroke(new BasicStroke(2));

                if ((screendata[i] & 1) != 0) // draws left
                {
                    g2d.drawLine(x, y, x, y + blocksize - 1);
                }
                if ((screendata[i] & 2) != 0) // draws top
                {
                    g2d.drawLine(x, y, x + blocksize - 1, y);
                }
                if ((screendata[i] & 4) != 0) // draws right
                {
                    g2d.drawLine(x + blocksize - 1, y, x + blocksize - 1,
                                 y + blocksize - 1);
                }
                if ((screendata[i] & 8) != 0) // draws bottom
                {
                    g2d.drawLine(x, y + blocksize - 1, x + blocksize - 1,
                                 y + blocksize - 1);
                }
                if ((screendata[i] & 16) != 0) // draws point
                {
                    g2d.setColor(dotcolor);
                    g2d.fillRect(x + 11, y + 11, 2, 2);
                }
                i++;
            }
        }
    }

    public void GameInit() {
        pacsleft = 3;
        score = 0;
        LevelInit();
        nrofghosts = 6;
        currentspeed = 3;
    }

    public void LevelInit() {
        int i;
        for (i = 0; i < nrofblocks * nrofblocks; i++)
            screendata[i] = leveldata[i];

        LevelContinue();
    }

    public void LevelContinue() {
        short i;
        int dx = 1;
        int random;

        for (i = 0; i < nrofghosts; i++) {
            ghosty[i] = 4 * blocksize;
            ghostx[i] = 4 * blocksize;
            ghostdy[i] = 0;
            ghostdx[i] = dx;
            dx = -dx;
            random = (int)(Math.random() * (currentspeed + 1));
            if (random > currentspeed)
                random = currentspeed;
            ghostspeed[i] = validspeeds[random];
        }

        pacmanx = 7 * blocksize;
        pacmany = 11 * blocksize;
        pacmandx = 0;
        pacmandy = 0;
        reqdx = 0;
        reqdy = 0;
        viewdx = -1;
        viewdy = 0;
        dying = false;
    }

    public void GetImages()
    {

      ghost = new ImageIcon(Board.class.getResource("../pacpix/ghost.png")).getImage();
      pacman1 = new ImageIcon(Board.class.getResource("../pacpix/pacman.png")).getImage();
      pacman2up = new ImageIcon(Board.class.getResource("../pacpix/up1.png")).getImage();
      pacman3up = new ImageIcon(Board.class.getResource("../pacpix/up2.png")).getImage();
      pacman4up = new ImageIcon(Board.class.getResource("../pacpix/up3.png")).getImage();
      pacman2down = new ImageIcon(Board.class.getResource("../pacpix/down1.png")).getImage();
      pacman3down = new ImageIcon(Board.class.getResource("../pacpix/down2.png")).getImage(); 
      pacman4down = new ImageIcon(Board.class.getResource("../pacpix/down3.png")).getImage();
      pacman2left = new ImageIcon(Board.class.getResource("../pacpix/left1.png")).getImage();
      pacman3left = new ImageIcon(Board.class.getResource("../pacpix/left2.png")).getImage();
      pacman4left = new ImageIcon(Board.class.getResource("../pacpix/left3.png")).getImage();
      pacman2right = new ImageIcon(Board.class.getResource("../pacpix/right1.png")).getImage();
      pacman3right = new ImageIcon(Board.class.getResource("../pacpix/right2.png")).getImage();
      pacman4right = new ImageIcon(Board.class.getResource("../pacpix/right3.png")).getImage();

    }

    public void paint(Graphics g)
    {
      super.paint(g);

      Graphics2D g2d = (Graphics2D) g;

      g2d.setColor(Color.black);
      g2d.fillRect(0, 0, d.width, d.height);

      DrawMaze(g2d);
      DrawScore(g2d);
      DoAnim();
      if (ingame)
        PlayGame(g2d);
      else
        ShowIntroScreen(g2d);

      g.drawImage(ii, 5, 5, this);
      Toolkit.getDefaultToolkit().sync();
      g.dispose();
    }

    class TAdapter extends KeyAdapter {
        public void keyPressed(KeyEvent e) {

          int key = e.getKeyCode();

          if (ingame)
          {
            if (key == KeyEvent.VK_LEFT)
            {
              reqdx=-1;
              reqdy=0;
            }
            else if (key == KeyEvent.VK_RIGHT)
            {
              reqdx=1;
              reqdy=0;
            }
            else if (key == KeyEvent.VK_UP)
            {
              reqdx=0;
              reqdy=-1;
            }
            else if (key == KeyEvent.VK_DOWN)
            {
              reqdx=0;
              reqdy=1;
            }
            else if (key == KeyEvent.VK_ESCAPE && timer.isRunning())
            {
              ingame=false;
            }
            else if (key == KeyEvent.VK_PAUSE) {
                if (timer.isRunning())
                    timer.stop();
                else timer.start();
            }
          }
          else
          {
            if (key == 's' || key == 'S')
          {
              ingame=true;
              GameInit();
            }
          }
      }

          public void keyReleased(KeyEvent e) {
              int key = e.getKeyCode();

              if (key == Event.LEFT || key == Event.RIGHT || 
                 key == Event.UP ||  key == Event.DOWN)
              {
                reqdx=0;
                reqdy=0;
              }
          }
      }

    public void actionPerformed(ActionEvent e) {
        repaint();  
    }
}

The Commons.java file has some common constants.

final short leveldata[] =
{ 19, 26, 26, 26, 18, ... };

These numbers make up the maze. They provide information out of which we create the corners and the points. For example number 19 in the upper left corner means, that the square will have top and left borders and a point. (16 + 2 + 1)

 public void doAnim() {
     pacanimcount--;
     if (pacanimcount <= 0) {
         pacanimcount = pacanimdelay;
         pacmananimpos = pacmananimpos + pacanimdir;
         if (pacmananimpos == (pacmananimcount - 1) || pacmananimpos == 0)
             pacanimdir = -pacanimdir;
     }
 }

The doAnim() counts the pacmananimpos variable, which determines what pacman image is drawn. There are four pacman images. There is also a pacanimdelay variable, which makes the animation a bit slower. Otherwise the pacman would open his mouth too fast.

boolean finished = true;

while (i < nrofblocks * nrofblocks && finished) {
    if ((screendata[i] & 16) != 0)
        finished = false;
    i++;
}

This code is part of the checkMaze() method. It checks, if there are any points left for the Pacman to eat. Number 16 stands for a point. If all points are consumed, we move to the next level.

Next we will examine the moveGhosts() method. The ghosts move one square and then decide, if they change the direction.

if (ghostx[i] % blocksize == 0 && ghosty[i] % blocksize == 0) {

Continue only if you have finished moving one square.

pos = ghostx[i] / blocksize + nrofblocks * (int)(ghosty[i] / blocksize);

This line determines, where the ghost is situated. In which position/square. There are 225 theoretical positions. (A ghost cannot move over walls. )

if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
    dx[count] = -1;
    dy[count] = 0;
    count++;
}

If there is no obstacle on the left and the ghost is not already moving to the right, the ghost will move to the left. What does this code really mean? If the ghost enters a tunnel, he will continue in the same direction until he is out of the tunnel. Moving of ghosts is partly random. We do not apply this randomness inside long tunnels. The ghost might get stuck there.

if (pacmanx > (ghostx[i] - 12) && pacmanx < (ghostx[i] + 12) &&
    pacmany > (ghosty[i] - 12) && pacmany < (ghosty[i] + 12) &&
    ingame) {

    dying = true;
    deathcounter = 64;
}

If there is a collision between ghosts and a pacman, the pacman dies.

Next we are going to examine the movePacman() method. The reqdx and reqdy variables are determined in the TAdapter inner class. These variables are controlled with cursor keys.

if ((ch & 16) != 0) {
    screendata[pos] = (short)(ch & 15);
    score++;
}

If the pacman moves to a position, where there is a point, we remove it from the maze and increase the score value.

if ((pacmandx == -1 && pacmandy == 0 && (ch & 1) != 0) ||
    (pacmandx == 1 && pacmandy == 0 && (ch & 4) != 0) ||
    (pacmandx == 0 && pacmandy == -1 && (ch & 2) != 0) ||
    (pacmandx == 0 && pacmandy == 1 && (ch & 8) != 0)) {
    pacmandx = 0;
    pacmandy = 0;
}

If the pacman cannot move further it his current direction, there is a standstill.

public void drawPacMan(Graphics2D g2d) {
    if (viewdx == -1)
        drawPacManLeft(g2d);
    else if (viewdx == 1)
        drawPacManRight(g2d);
    else if (viewdy == -1)
        drawPacManUp(g2d);
    else
        drawPacManDown(g2d);
}

There are four possible directions for a pacman. There are four images for all directions. The images are used to animate pacman opening a closing his mouth.

The drawMaze() method draws the maze out of the numbers in the screendata array. Number 1 is a left border, 2 is a top border, 4 is a right border, 8 is a bottom border and 16 is a point. We simply go through all 225 squares int the maze. For example we have 9 in the screendata array. We have the first bit (1) and the fourth bit (8) set. So we draw a bottom and a left border on this particular square.

if ((screendata[i] & 1) != 0) // draws left
{
    g2d.drawLine(x, y, x, y + blocksize - 1);
}

Draw a left border if the first bit of a number is set.

PacMan.java
package packman;

import javax.swing.JFrame;

import pacman.Board;

public class PacMan extends JFrame
{

  public PacMan()
  {
    add(new Board());
    setTitle("Pacman");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    setSize(380, 420);
    setLocationRelativeTo(null);
    setVisible(true);
  }  public static void main(String[] args) {
      new PacMan();
  }
}

This is a PacMan file with a main method.

Pacman

Figure: Pacman

This was the Pacman game.

 

In this part of the Java 2D games tutorial, we will create a Java Snake game clone.

Snake

Snake is an older classic video game. It was first created in late 70s. Later it was brought to PCs. In this game the player controls a snake. The objective is to eat as many apples as possible. Each time the snake eats an apple, its body grows. The snake must avoid the walls and its own body. This game is sometimes called Nibbles.

Development

The size of each of the joints of a snake is 10px. The snake is controlled with the cursor keys. Initially the snake has three joints. The game is started by pressing one of the cursor keys. If the game is finished, we display Game Over message in the middle of the Board.

Board.java
package snake2;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Board extends JPanel implements ActionListener {

    private final int WIDTH = 300;
    private final int HEIGHT = 300;
    private final int DOT_SIZE = 10;
    private final int ALL_DOTS = 900;
    private final int RAND_POS = 29;
    private final int DELAY = 140;

    private int x[] = new int[ALL_DOTS];
    private int y[] = new int[ALL_DOTS];

    private int dots;
    private int apple_x;
    private int apple_y;

    private boolean left = false;
    private boolean right = true;
    private boolean up = false;
    private boolean down = false;
    private boolean inGame = true;

    private Timer timer;
    private Image ball;
    private Image apple;
    private Image head;

    public Board() {
        addKeyListener(new TAdapter());

        setBackground(Color.black);

        ImageIcon iid = new ImageIcon(this.getClass().getResource("dot.png"));
        ball = iid.getImage();

        ImageIcon iia = new ImageIcon(this.getClass().getResource("apple.png"));
        apple = iia.getImage();

        ImageIcon iih = new ImageIcon(this.getClass().getResource("head.png"));
        head = iih.getImage();

        setFocusable(true);
        initGame();
    }

    public void initGame() {

        dots = 3;

        for (int z = 0; z < dots; z++) {
            x[z] = 50 - z*10;
            y[z] = 50;
        }

        locateApple();

        timer = new Timer(DELAY, this);
        timer.start();
    }

    public void paint(Graphics g) {
        super.paint(g);

        if (inGame) {

            g.drawImage(apple, apple_x, apple_y, this);

            for (int z = 0; z < dots; z++) {
                if (z == 0)
                    g.drawImage(head, x[z], y[z], this);
                else g.drawImage(ball, x[z], y[z], this);
            }

            Toolkit.getDefaultToolkit().sync();
            g.dispose();

        } else {
            gameOver(g);
        }
    }

    public void gameOver(Graphics g) {
        String msg = "Game Over";
        Font small = new Font("Helvetica", Font.BOLD, 14);
        FontMetrics metr = this.getFontMetrics(small);

        g.setColor(Color.white);
        g.setFont(small);
        g.drawString(msg, (WIDTH - metr.stringWidth(msg)) / 2,
                     HEIGHT / 2);
    }

    public void checkApple() {

        if ((x[0] == apple_x) && (y[0] == apple_y)) {
            dots++;
            locateApple();
        }
    }

    public void move() {

        for (int z = dots; z > 0; z--) {
            x[z] = x[(z - 1)];
            y[z] = y[(z - 1)];
        }

        if (left) {
            x[0] -= DOT_SIZE;
        }

        if (right) {
            x[0] += DOT_SIZE;
        }

        if (up) {
            y[0] -= DOT_SIZE;
        }

        if (down) {
            y[0] += DOT_SIZE;
        }
    }

    public void checkCollision() {

          for (int z = dots; z > 0; z--) {

              if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
                  inGame = false;
              }
          }

        if (y[0] > HEIGHT) {
            inGame = false;
        }

        if (y[0] < 0) {
            inGame = false;
        }

        if (x[0] > WIDTH) {
            inGame = false;
        }

        if (x[0] < 0) {
            inGame = false;
        }
    }

    public void locateApple() {
        int r = (int) (Math.random() * RAND_POS);
        apple_x = ((r * DOT_SIZE));
        r = (int) (Math.random() * RAND_POS);
        apple_y = ((r * DOT_SIZE));
    }

    public void actionPerformed(ActionEvent e) {

        if (inGame) {
            checkApple();
            checkCollision();
            move();
        }

        repaint();
    }

    private class TAdapter extends KeyAdapter {

        public void keyPressed(KeyEvent e) {

            int key = e.getKeyCode();

            if ((key == KeyEvent.VK_LEFT) && (!right)) {
                left = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_RIGHT) && (!left)) {
                right = true;
                up = false;
                down = false;
            }

            if ((key == KeyEvent.VK_UP) && (!down)) {
                up = true;
                right = false;
                left = false;
            }

            if ((key == KeyEvent.VK_DOWN) && (!up)) {
                down = true;
                right = false;
                left = false;
            }
        }
    }
}

First we will define the constants used in our game.

private final int WIDTH = 300;
private final int HEIGHT = 300;
private final int DOT_SIZE = 10;
private final int ALL_DOTS = 900;
private final int RAND_POS = 29;
private final int DELAY = 140;

The WIDTH and HEIGHT constants determine the size of the Board. The DOT_SIZE is the size of the apple and the dot of the snake. The ALL_DOTS constant defines the maximum number of possible dots on the Board. (900 = 300*300/10*10) The RAND_POS constant is used to calculate a random position of an apple. The DELAY constant determines the speed of the game.

private int x[] = new int[ALL_DOTS];
private int y[] = new int[ALL_DOTS];

These two arrays store x, y coordinates of all joints of a snake.

In the move() method we have the key algorithm of the game. To understand it, look at how the snake is moving. You control the head of the snake. You can change its direction with the cursor keys. The rest of the joints move one position up the chain. The second joint moves where the first was, the third joint where the second was etc.

 for (int z = dots; z > 0; z--) {
     x[z] = x[(z - 1)];
     y[z] = y[(z - 1)];
 }

This code moves the joints up the chain.

if (left) {
    x[0] -= DOT_SIZE;
}

Move the head to the left.

In the checkCollision() method, we determine if the snake has hit itself or one of the walls.

for (int z = dots; z > 0; z--) {

    if ((z > 4) && (x[0] == x[z]) && (y[0] == y[z])) {
        inGame = false;
    }
}

Finish the game, if the snake hits one of its joints with the head.

if (y[0] > HEIGHT) {
    inGame = false;
}

Finish the game, if the snake hits the bottom of the Board.

Snake.java
package snake2;

import javax.swing.JFrame;

public class Snake extends JFrame {

    public Snake() {

        add(new Board());

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(320, 340);
        setLocationRelativeTo(null);
        setTitle("Snake");

        setResizable(false);
        setVisible(true);
    }    public static void main(String[] args) {
        new Snake();
    }
}

This is the main class.

Snake

Figure: Snake

This was the Snake game.

 

Deutsch: Logo der Christlich Sozialen Volkspartei

Loading CSV file into Database can be cumbersome task if your Database provider does not offer an out of box feature for this. Most of the time you’ll spend up in creating valid insert statements and putting up values escaping all special characters. Importing CSV files gets a bit complicated when you start doing things like importing files with description fields that can contain punctuation (such as commas or single-double quotation marks).

So here’s a simple Java Utility class that can be used to load CSV file into Database. Note how we used some of the best practices for loading data. The CSV file is parsed line by line and SQL insert query is created. The values in query are binded and query is added to SQL batch. Each batch is executed when a limit is reached (in this case 1000 queries per batch).

Import CSV into Database example

Let’s us check an example. Below is the sample CSV file that I want to upload in database table Customer.

employee.csv – Sample CSV file:

EMPLOYEE_ID,FIRSTNAME,LASTNAME,BIRTHDATE,SALARY
1,Dean,Winchester,27.03.1975,60000
2,John,Winchester,01.05.1960,120000
3,Sam,Winchester,04.01.1980,56000

The Table customer contains few fields. We added fields of different types like VARCHAR, DATE, NUMBER to check our load method works properly.

Table: Customer – Database table

CREATE TABLE Customer (
  EMPLOYEE_ID  NUMBER,
  FIRSTNAME    VARCHAR2(50 BYTE),
  LASTNAME     VARCHAR2(50 BYTE),
  BIRTHDATE    DATE,
  SALARY       NUMBER
)

Following is a sample Java class that will use CSVLoader utility class (we will come to this shortly).

Main.java – Load sample.csv to database

package net.viralpatel.java;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
    private static String JDBC_CONNECTION_URL =
            "jdbc:oracle:thin:SCOTT/TIGER@localhost:1500:MyDB";
    
    public static void main(String[] args) {
        try {
            CSVLoader loader = new CSVLoader(getCon());
            
            loader.loadCSV("C:\\employee.sql", "CUSTOMER", true);
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private static Connection getCon() {
        Connection connection = null;
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            connection = DriverManager.getConnection(JDBC_CONNECTION_URL);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

In above Main class, we created an object of class CSVLoader using parameterized constructor and passed java.sql.Connection object.

Then we called the loadCSV method with three arguments. First the path of CSV file, second the table name where data needs to be loaded and third boolean parameter which decides whether table has to be truncated before inserting new records.

Execute this Java class and you’ll see the records getting inserted in table.

csv-load-java-database-example

The CSV is successfully loaded in database.

Let’s check the Utility class now. I strongly recommend you to go through below tutorials as the Utility class combines the idea from these tutorials.

  1. Batch Insert In Java – JDBC
  2. Read / Write CSV file in Java
  3. Check if String is valid Date in Java

The utility class uses OpenCSV library to load and parse CSV file. Then it uses the idea of Batching in JDBC to batch insert queries and execute them. Each CSV value is checked if it is valid date before inserting.

CSVLoader.java – Utility class to load CSV into Database

package net.viralpatel.java;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import au.com.bytecode.opencsv.CSVReader;
/**
 *
 * @author viralpatel.net
 *
 */
public class CSVLoader {
    private static final
        String SQL_INSERT = "INSERT INTO ${table}(${keys}) VALUES(${values})";
    private static final String TABLE_REGEX = "\\$\\{table\\}";
    private static final String KEYS_REGEX = "\\$\\{keys\\}";
    private static final String VALUES_REGEX = "\\$\\{values\\}";
    private Connection connection;
    private char seprator;
    /**
     * Public constructor to build CSVLoader object with
     * Connection details. The connection is closed on success
     * or failure.
     * @param connection
     */
    public CSVLoader(Connection connection) {
        this.connection = connection;
        //Set default separator
        this.seprator = ',';
    }
    
    /**
     * Parse CSV file using OpenCSV library and load in
     * given database table.
     * @param csvFile Input CSV file
     * @param tableName Database table name to import data
     * @param truncateBeforeLoad Truncate the table before inserting
     *          new records.
     * @throws Exception
     */
    public void loadCSV(String csvFile, String tableName,
            boolean truncateBeforeLoad) throws Exception {
        CSVReader csvReader = null;
        if(null == this.connection) {
            throw new Exception("Not a valid connection.");
        }
        try {
            
            csvReader = new CSVReader(new FileReader(csvFile), this.seprator);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("Error occured while executing file. "
                    + e.getMessage());
        }
        String[] headerRow = csvReader.readNext();
        if (null == headerRow) {
            throw new FileNotFoundException(
                    "No columns defined in given CSV file." +
                    "Please check the CSV file format.");
        }
        String questionmarks = StringUtils.repeat("?,", headerRow.length);
        questionmarks = (String) questionmarks.subSequence(0, questionmarks
                .length() - 1);
        String query = SQL_INSERT.replaceFirst(TABLE_REGEX, tableName);
        query = query
                .replaceFirst(KEYS_REGEX, StringUtils.join(headerRow, ","));
        query = query.replaceFirst(VALUES_REGEX, questionmarks);
        System.out.println("Query: " + query);
        String[] nextLine;
        Connection con = null;
        PreparedStatement ps = null;
        try {
            con = this.connection;
            con.setAutoCommit(false);
            ps = con.prepareStatement(query);
            if(truncateBeforeLoad) {
                //delete data from table before loading csv
                con.createStatement().execute("DELETE FROM " + tableName);
            }
            final int batchSize = 1000;
            int count = 0;
            Date date = null;
            while ((nextLine = csvReader.readNext()) != null) {
                if (null != nextLine) {
                    int index = 1;
                    for (String string : nextLine) {
                        date = DateUtil.convertToDate(string);
                        if (null != date) {
                            ps.setDate(index++, new java.sql.Date(date
                                    .getTime()));
                        } else {
                            ps.setString(index++, string);
                        }
                    }
                    ps.addBatch();
                }
                if (++count % batchSize == 0) {
                    ps.executeBatch();
                }
            }
            ps.executeBatch(); // insert remaining records
            con.commit();
        } catch (Exception e) {
            con.rollback();
            e.printStackTrace();
            throw new Exception(
                    "Error occured while loading data from file to database."
                            + e.getMessage());
        } finally {
            if (null != ps)
                ps.close();
            if (null != con)
                con.close();
            csvReader.close();
        }
    }
    public char getSeprator() {
        return seprator;
    }
    public void setSeprator(char seprator) {
        this.seprator = seprator;
    }
}

The class looks complicated but it is simple :)

The loadCSV methods combines the idea from above three tutorials and create insert queries.

Following is the usage of this class if you want to use it in your project:

Usage

CSVLoader loader = new CSVLoader(connection);
loader.loadCSV("C:\\employee.csv", "TABLE_NAME", true);

Load file with semicolon as delimeter:

CSVLoader loader = new CSVLoader(connection);
loader.setSeparator(';');
loader.loadCSV("C:\\employee.csv", "TABLE_NAME", true);

Load file without truncating the table:

CSVLoader loader = new CSVLoader(connection);
loader.loadCSV("C:\\employee.csv", "TABLE_NAME", false);

Hope this helps.

Download Source Code

Load_CSV_Database_Java_example.zip (2.05 MB)

– First of all, as a user app, I think it should not access the root “/” directly. So I assign root to Environment.getExternalStorageDirectory(), it’s the Android external storage directory.
– Secondly, if a file/directory is hidden or un-readable, it will not be display.

Example of File Explorer

Create /res/layout/row.xml, the layout of the rows in the list.

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rowtext"
    android:layout_width="fill_parent"
    android:layout_height="30sp"
    android:textSize="25sp" />

The main layout with a ListView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical">

    <TextView
        android:id="@+id/path"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" />
    <ListView
        android:id="@android:id/list"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        />
    <TextView
        android:id="@android:id/empty"
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="No Data"
        />

</LinearLayout>

Main code.

package com.example.androidexplorer;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.os.Environment;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends ListActivity {

 private List<String> item = null;
 private List<String> path = null;
 private String root;
 private TextView myPath;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myPath = (TextView)findViewById(R.id.path);

        root = Environment.getExternalStorageDirectory().getPath();

        getDir(root);
    }

    private void getDir(String dirPath)
    {
     myPath.setText("Location: " + dirPath);
     item = new ArrayList<String>();
     path = new ArrayList<String>();
     File f = new File(dirPath);
     File[] files = f.listFiles();

     if(!dirPath.equals(root))
     {
      item.add(root);
      path.add(root);
      item.add("../");
      path.add(f.getParent()); 
     }

     for(int i=0; i < files.length; i++)
     {
      File file = files[i];

      if(!file.isHidden() && file.canRead()){
       path.add(file.getPath());
          if(file.isDirectory()){
           item.add(file.getName() + "/");
          }else{
           item.add(file.getName());
          }
      } 
     }

     ArrayAdapter<String> fileList =
       new ArrayAdapter<String>(this, R.layout.row, item);
     setListAdapter(fileList); 
    }

 @Override
 protected void onListItemClick(ListView l, View v, int position, long id) {
  // TODO Auto-generated method stub
  File file = new File(path.get(position));

  if (file.isDirectory())
  {
   if(file.canRead()){
    getDir(path.get(position));
   }else{
    new AlertDialog.Builder(this)
     .setIcon(R.drawable.ic_launcher)
     .setTitle("[" + file.getName() + "] folder can't be read!")
     .setPositiveButton("OK", null).show(); 
   } 
  }else {
   new AlertDialog.Builder(this)
     .setIcon(R.drawable.ic_launcher)
     .setTitle("[" + file.getName() + "]")
     .setPositiveButton("OK", null).show();

    }
 }

}

Download the files.

Enhanced by Zemanta

ListView in simplest form with plain text only. This exercise describe how to add a icon in ListView.

ListView, with icon

create a new file in /res/layout/row.xml, to setup our layout on each row.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon"/>
<TextView
android:id="@+id/weekofday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

AndroidList.java

package com.exercise.AndroidList;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class AndroidList extends ListActivity {

String[] DayOfWeek = {"Sunday", "Monday", "Tuesday",
  "Wednesday", "Thursday", "Friday", "Saturday"
};

   /** Called when the activity is first created. */
   @Override
   public void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       //setContentView(R.layout.main);
       setListAdapter(new ArrayAdapter<String>(this,
         R.layout.row, R.id.weekofday, DayOfWeek));
   }
}
Enhanced by Zemanta

It’s the simplest form of ListView, extends ListActivity. The list is displayed as a single line of plain text, using the simple Android built-in layout “android.R.layout.simple_list_item_1”.

A simple ListView, extends ListActivity

package com.exercise.AndroidList;

import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;

public class AndroidList extends ListActivity {
 
 String[] DayOfWeek = {"Sunday", "Monday", "Tuesday",
   "Wednesday", "Thursday", "Friday", "Saturday"
 };
 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.main);
        setListAdapter(new ArrayAdapter<String>(this, 
          android.R.layout.simple_list_item_1, DayOfWeek));
    }
}

 

Web browser

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;

public class WebBrowser
{
public static void main(String [] args)
{
JFrame frame = new EditorPaneFrame();
frame.show();
}
}
class EditorPaneFrame extends JFrame
{

private JTextField url;
private JCheckBox editable;
private JButton loadButton;
private JButton backButton;
private JEditorPane editorPane;
private Stack urlStack = new Stack();

public EditorPaneFrame()
{
setTitle(“Java Web Browser”);
setSize(600,400);
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
} );

// set up text field and load button for typing in URL

url = new JTextField(30);

loadButton = new JButton(“Load”);
loadButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
try
{
// remember URL for back button
urlStack.push(url.getText());
editorPane.setPage(url.getText());
}
catch(Exception e)
{
editorPane.setText(“Error: ” +e);
}
}
});

// set up back button and button action

backButton = new JButton(“Back”);
backButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
if(urlStack.size()<=1) return;
try
{
urlStack.pop();
String urlString = (String)urlStack.peek();
url.setText(urlString);
editorPane.setPage(urlString);
}
catch(IOException e)
{
editorPane.setText(“Error : ” +e);
}
}
});

editorPane = new JEditorPane();
editorPane.setEditable(false);
editorPane.addHyperlinkListener(new HyperlinkListener()
{
public void hyperlinkUpdate(HyperlinkEvent event)
{
if(event.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
{
try
{
urlStack.push(event.getURL().toString());
url.setText(event.getURL().toString());

editorPane.setPage(event.getURL());
}
catch(IOException e)
{
editorPane.setText(“Error: ” + e);
}
}
}
});

editable = new JCheckBox();
editable.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
editorPane.setEditable(editable.isSelected());
}
});

Container contentPane = getContentPane();
contentPane.add(new JScrollPane(editorPane), “Center”);

JPanel panel = new JPanel();
panel.add(new JLabel(“URL”));
panel.add(url);
panel.add(loadButton);
panel.add(backButton);
panel.add(new JLabel(“Editable”));
panel.add(editable);

contentPane.add(panel,”South”);
}

}

English: SMTP transfer model Blue arrows can b...

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import javax.swing.*;

public class MailClient
{
public static void main(String []args)
{
JFrame frame = new MailClientFrame();
frame.show();
}
}
class MailClientFrame extends JFrame implements ActionListener
{

private BufferedReader in;
private PrintWriter out;
private JTextField from;
private JTextField to;
private JTextField smtpServer;
private JTextArea message;
private JTextArea response;
private JLabel fromLbl;
private JLabel toLbl;
private JLabel serverLbl;

public MailClientFrame()
{
setTitle(“Mail Client”);
setSize(250,400);

addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{
System.exit(0);
}
}
);

getContentPane().setLayout(new FlowLayout(FlowLayout.LEFT));

fromLbl = new JLabel(“From: “);
getContentPane().add(fromLbl);

from = new JTextField(20);
getContentPane().add(from);

toLbl = new JLabel(“To: “);
getContentPane().add(toLbl);

to = new JTextField(20);
getContentPane().add(to);

serverLbl = new JLabel(“SMTP Server:”);
getContentPane().add(serverLbl);

smtpServer = new JTextField(20);
getContentPane().add(smtpServer);

message = new JTextArea(5,20);
getContentPane().add(message);

JScrollPane p = new JScrollPane(message);
getContentPane().add(p);

response = new JTextArea(5,20);
getContentPane().add(response);

JScrollPane p1 = new JScrollPane(response);
getContentPane().add(p1);

JButton sendButton  = new JButton(“Send”);
sendButton.addActionListener(this);

JPanel buttonPanel = new JPanel();
buttonPanel.add(sendButton);

getContentPane().add(sendButton);

}

public void actionPerformed(ActionEvent evt)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
sendMail();
}
}
);
}

public void sendMail()
{
try
{
Socket s = new Socket(smtpServer.getText(),25);
out  = new PrintWriter(s.getOutputStream());
in = new BufferedReader(new InputStreamReader(s.getInputStream()));

String hostName = InetAddress.getLocalHost().getHostName();
send(null);
send(“HELO” + hostName);
send(“MAIL FROM:”+ from.getText());
send(“RCPT TO:” + to.getText());
send(“DATA”);
out.println(message.getText());
send(“.”);
s.close();
}
catch(IOException e)
{
response.append(“Error:” + e);
}
}

public void send(String s) throws IOException
{
if(s!=null)
{
response.append(s+”\n”);
out.println(s);
out.flush();
}
String line;
if ( (line = in.readLine())!=null)
{
response.append(line+”\n”);
}
}
}