Multi-threading in brick-and-mortar games

Source: Internet
Author: User

 

I learned multithreading a few days ago. Now I have summarized my own brick-hitting game to deepen my understanding of multithreading. (If you have any incorrect ideas, please correct them !). First, let's look at the game:

First, you must have an interface that has been implemented many times before. The specific code is as follows:

/**

* Initialize the form

*/

Public void initFrame (){

This. setTitle ("Furious ball"); // you can specify the title of the form.

This. setSize (500,750); // sets the size of the form.

// This. getContentPane (). setBackground (Color. BLACK );

This. setLayout (new FlowLayout (); // sets the stream layout manager.

JButton bt = new JButton ("START ");

JButton bt1 = new JButton ("stop ");

 

JPanel panel = new JPanel ();

 

Dimension d = new Dimension (495,650 );

 

Panel. setBackground (Color. BLACK );

Panel. setPreferredSize (d );

 

This. add (bt );

This. add (bt1 );

This. add (panel );

 

This. setResizable (false); // you can specify the unchangeable size of the form.

This. setdefaclocloseoperation (3); // click Close to exit the form.

This. setVisible (true); // display the form on the screen.

 

// Set the focus

Bt. setFocusable (false );

Bt1.setFocusable (false );

Panel. setFocusable (true );

 

Final Graphics g = panel. getGraphics (); // obtain the canvas

}

After the form is obtained, a baffle plate is required. Therefore, a baffle class is defined, and the baffle can be moved horizontally at the bottom of the form. Therefore, the baffle class defined here is the interface for implementing MouseMotionListener, this allows the drawn bezel to move as the mouse moves, and then defines the attributes of the baffle and implements the method of drawing the baffle in this class. The baffle attributes include coordinates, length, width, and color in the upper left corner. For the sake of beauty, a picture of the baffle is drawn directly. The specific code is as follows:

Public class Fender implements MouseMotionListener {

 

Public static int x = 0;

Public static int getX (){

Return x;

}

 

Public int y = 630;

Public int width = 100;

Private int height = 20;

Private JPanel;

Private Graphics g;

 

Public Fender (){}

Public Fender (netjava. wxh0807pm1. BallFrame. mypanel panel ){

 

This. panel = panel;

G = panel. getGraphics ();

}

// Override the parent class Method

Public void mouseMoved (MouseEvent e ){

// Clear the image

G. setColor (panel. getBackground ());

G. fillRect (x, y, width, height );

X = e. getX ();

 

// G. setColor (Color. RED );

If (x >=400 ){

X = 400;

}

// Draw the baffle

CreateFender (g, x, y, width, height );

}

// Method for drawing bezel

Public void createFender (Graphics g, int x, int y, int width, int height ){

Javax. swing. ImageIcon = new javax. swing. ImageIcon ("src \ netjava \ wxh0807pm1 \ image \ 5.png ");

G. drawImage (icon. getImage (), x, y, width, height, null );

}

Public void mouseDragged (MouseEvent e ){

 

}

}

Then you need to draw the self-designed bricks. Here, the bricks are drawn directly in the form of maps. The first step is to prepare several pictures of bricks, and then regard the area to be painted as a two-dimensional array. The zero element in the two-dimensional array indicates that no bricks are drawn in the area, use different numbers to represent different bricks, and then design the elements of a two-dimensional array in another file to draw the map you want to draw. After the two-dimensional array is designed, you must first define a method to read the file into the memory, and then use the input and output stream knowledge. As we have summarized above, it is no longer a bit of a wordy here. However, the string is read, so you also need to define a method to convert the string to an array, and then define a static method to get the image, finally, define a method to create a map based on the obtained array and image. Write the preceding three methods into a class. The Code is as follows:

Public class MapTest {

 

/**

* Read the map data in the file.

*

* @ Param path

* @ Return

*/

Public static int [] [] readMap (String path ){

Try {

// Create a file input stream

FileInputStream FCM = new FileInputStream (path );

BufferedInputStream bis = new BufferedInputStream (FCM );

 

Byte [] bs = new byte [bis. available ()];

// Read data from the stream to the array

Bis. read (bs );

 

String str = new String (bs );

 

// Process the string

 

// System. out. println (str );

 

Int [] [] arr = changeToArray (str );

Return arr;

 

} Catch (Exception ef ){

Ef. printStackTrace ();

}

 

Return null;

}

 

/**

* Convert a string to an array

*

* @ Param str

* @ Return

*/

Private static int [] [] changeToArray (String str ){

 

// Split the string into a String Array Based on the carriage return linefeed

String [] strs = str. split ("\ r \ n ");

 

Int [] [] array = new int [strs. length] [strs [0]. length ()];

 

// Traverse the String Array

For (int I = 0; I <strs. length; I ++ ){

String s = strs [I];

// Parse the string

Char [] cs = s. toCharArray ();

 

For (int j = 0; j <cs. length; j ++ ){

Char c = cs [j];

// Convert a string to a number

Int num = Integer. parseInt (c + "");

 

Array [I] [j] = num;

 

}

 

}

Return array;

}

 

// Obtain the image object based on the path

Public static ImageIcon createImageIcon (String path ){

Java.net. URL url = MapTest. class. getResource (path );

ImageIcon icon = new ImageIcon (url );

Return icon;

}

}

The code for the last method is as follows:

/**

* Create a map based on the map Array

* @ Param array

*/

Public static void createMap (int [] [] array, Graphics g ){

 

For (int I = 0; I <array. length; I ++ ){

For (int j = 0; j <array [I]. length; j ++ ){

 

If (array [I] [j]! = 0 ){

Int num = array [I] [j];

String path = "image/" + num + ". png ";

// Construct an image object based on the path

ImageIcon = MapTest. createImageIcon (path );

G. drawImage (icon. getImage (), 35 * j, 15 * I, null );

 

}

 

}

 

}

 

}

After the above methods are written, you only need to call them to draw bricks. Now we need to draw a ball. This ball is a thread, so we need to define a ball. In this class, we need to define the attributes and methods of the ball, in the moving process of the ball, we also need to judge the collision rebound between the ball and the left and right sides of the interface, as well as the collision between the ball and the brick. The collision between the ball and the brick mainly considers the collision with the ball from the four sides of the brick, because the array obtained based on the above method can get the position of each brick, and then traverse the array, determine whether each brick in the array is in conflict with the ball, and then rebound accordingly. After the Brick hits the ball, it should be removed, the so-called elimination is to draw bricks into the same color as the background, and change the corresponding elements in the array to zero. Then, judge whether the ball is in conflict with the bezel. If it is in conflict, it will bounce back. If the bezel does not catch the ball, the game will end. Then, you can write a method to determine whether or not the array has won. In the same way, you can traverse the obtained array. If all the elements in the array are zero, it means that all the bricks have been completed, and then they have won. The code for the specific point is as follows:

/**

* Ball games

* @ Author lenovo

*

*/

Public class Ball extends Thread {

 

Java. util. Random rd = new java. util. Random ();

 

Public static int x0 = 240;

Public static int y0 = 605;

Private int width = 20;

Private int height = 20;

Private int x1;

Private int y1;

 

Private JPanel;

Private Graphics g;

Private Fender fd;

 

Public static boolean isStop = false;

Public static boolean isPause = false;

 

Public Ball (){}

Public Ball (JPanel, Fender fd ){

This. fd = fd;

This. panel = panel;

G = panel. getGraphics ();

 

 

// Increment of the ball

X1 = 8;

Y1 =-8;

 

}

 

Public void run (){

Draw ();

}

 

 

 

Public void draw (){

Fender fd = new Fender ();

While (! IsStop ){

 

While (! IsPause ){

 

// Javax. swing. ImageIcon = new javax. swing. ImageIcon ("src \ netjava \ wxh0807pm1 \ image \ 6.png ");

 

// Clear the image

G. setColor (panel. getBackground ());

G. fillRect (x0, y0, width, height );

 

// Traverse the array to determine whether it is in conflict with bricks

// Int [] [] array = MapTest. readMap ("src \ netjava \ wxh0806 \ image \ map ");

For (int I = 0; I <BallFrame. arr. length; I ++ ){

For (int j = 0; j <BallFrame. arr [I]. length; j ++ ){

If (BallFrame. arr [I] [j]! = 0 ){

If (x0> = 35 * J-1 & x0 <= 35 * j + 10 & y0 <= 15 * I + 15 & y0> = 15 * I) {// left-side collision of bricks

G. setColor (panel. getBackground ());

G. fillRect (35 * j, 15 * I, 36, 15 );

 

// System. out. println ("11 ");

BallFrame. arr [I] [j] = 0;

X1 =-x1;

} Else if (y0> = 15 * I-1 & y0 <= 15 * I + 15 & x0 <= 35 * j + 35 & x0> = 35 * j) {// determine the upper part of the brick

G. setColor (panel. getBackground ());

G. fillRect (35 * j, 15 * I, 36, 15 );

 

// System. out. println ("12 ");

BallFrame. arr [I] [j] = 0;

Y1 =-y1;

} Else if (y0 <= 15 * I + 15 + 1 & y0> = 15 * I & x0 <= 35 * j + 35 & x0> = 35 * j) {// lower part of the brick

G. setColor (panel. getBackground ());

G. fillRect (35 * j, 15 * I, 36, 15 );

 

// System. out. println ("13 ");

BallFrame. arr [I] [j] = 0;

Y1 =-y1;

} Else if (x0> = 35 * j + 35 + 1 & x0 <= 35 * j + 35-10 & y0 <= 15 * I + 15 & y0> = 15 * I) {// right side of the brick

G. setColor (panel. getBackground ());

G. fillRect (35 * j, 15 * I, 36, 15 );

 

// System. out. println ("14 ");

BallFrame. arr [I] [j] = 0;

X1 =-x1;

}

}

 

 

}

}

 

 

IsWin (BallFrame. arr );

 

If (x1! = 0 ){

If (x0 <= 0 | x0> = 470) {// left and right sides

X1 =-x1;

// System. out. println ("1 ");

} Else if (y0 <= 0) {// two upper and lower walls

Y1 =-y1;

// System. out. println ("2 ");

} Else if (x0 <= 0 & y0 <= 0) | x0 <= 0 | (x0 >=470 & y0 <= 0) | x0> = 470) {// vertical collision of Four Walls

X1 =-x1; y1 =-y1;

// System. out. println ("3 ");

 

 

}

 

Else if (y0> = 630-20 & y0 <= 630-20 + 10 & x0 <= Fender. getX () + 100-10 & x0> = Fender. getX ()-10 ){

// System. out. println ("------------");

Y1 =-y1;

// System. out. println ("0 ");

} Else if (y0> 640 & y0 <650 ){

Javax. swing. JOptionPane. showMessageDialog (null, "Come on! ");

}

X0 + = x1;

Y0 + = y1;

 

// Draw the ball

CreateBall (g, x0, y0 );

// G. drawImage (icon. getImage (), x0 + = x1, y0 + = y1, null );

 

// G. setColor (Color. RED );

// G. fillOval (x0 + = x1, y0 + = y1, width, height );

 

}

 

Try {

Thread. sleep (40 );

} Catch (Exception ep ){

Ep. printStackTrace ();

}

 

 

}

 

Try {

Thread. sleep (1 );

} Catch (Exception ef ){

Ef. printStackTrace ();

}

 

 

 

}

 

}

 

// Method for ball painting

Public void createBall (Graphics g, int x, int y ){

Javax. swing. ImageIcon = new javax. swing. ImageIcon ("src \ netjava \ wxh0807pm1 \ image \ 6.png ");

G. drawImage (icon. getImage (), x, y, null );

}

 

 

/**

* Method for determining whether to win or lose

* @ Param chars

*/

Public void isWin (int [] [] array ){

Int count = 0;

For (int m = 0; m <array. length; m ++ ){

For (int n = 0; n <array [m]. length; n ++ ){

If (array [m] [n]! = 0 ){

Count ++;

}

}

}

System. out. println (count );

If (count = 0 ){

JOptionPane. showMessageDialog (null, "you win !!! ");

StopThread ();

}

}

 

}

 

Then define the pause and continue methods in the ball to control the thread of the ball. The specific code is as follows:

// Pause Method

Public static void pauseThread (){

IsPause = true;

}

 

// Continue Method

Public static void resumeThread (){

IsPause = false;

}

 

// Stop Method

Public static void stopThread (){

IsPause = true;

IsStop = true;

}

 

// Initial Method

Public static void initThread (){

IsPause = false;

IsStop = false;

}

 

Then define an internal Anonymous class in the method of initializing the form to start the thread. However, all variables not in this class must be defined as final. The specific code is as follows:

// Anonymous internal class

ActionListener alt = new ActionListener (){

 

 

Public void actionreceivmed (ActionEvent e ){

 

String command = e. getActionCommand ();

If (command. equals ("START ")){

 

 

// Read the file

Int [] [] array = MapTest. readMap ("src \ netjava \ wxh0807pm1 \ image \ map ");

 

Arr = array;

 

// Draw an image

CreateMap (array, g );

 

Ball B = new Ball (panel, fd );

B. start ();

 

Bt. setText ("paused ");

 

}

 

If (command. equals ("Suspend ")){

 

Ball. pauseThread ();

Bt. setText ("continue ");

}

 

If (command. equals ("continue ")){

Ball. resumeThread ();

Bt. setText ("paused ");

}

 

If (command. equals ("stop ")){

 

Ball. stopThread ();

Bt. setText ("START ");

}

}

 

};

// Add listener

Bt. addActionListener (alt );

Bt1.addActionListener (alt );

Fender fd = new Fender (panel );

Panel. addMouseMotionListener (fd );

 

Then re-paint the bezel, ball, and Brick. The re-painting code is as follows:

// Redraw

Class mypanel extends JPanel {

 

Public void paint (Graphics g ){

 

// Override the parent class Method

Super. paint (g );

// Traverse the brick array for re-painting

For (int I = 0; I <arr. length; I ++ ){

For (int j = 0; j <arr [I]. length; j ++ ){

If (arr [I] [j]! = 0 ){

Int num = arr [I] [j];

String path = "image/" + num + ". png ";

ImageIcon = MapTest. createImageIcon (path );

G. drawImage (icon. getImage (), 35 * j, 15 * I, 35, 15, null );

}

}

}

// Redraw the bezel

Fender f = new Fender (this );

 

F. createFender (g, Fender. x, 630,100, 20 );

// Redraw the ball

Ball ball = new Ball ();

Ball. createBall (g, Ball. x0, Ball. y0 );

 

 

}

 

}

 

Here, the basic game has been developed, but it is found that the bricks are not completely eliminated or the bricks that have not been encountered have been erased, so we need to restart a thread to refresh the drawing area continuously. The specific code is as follows:

// Refresh the canvas listening thread

Class PaintThread extends Thread {

 

Public void run (){

While (! Ball. isStop ){

While (! Ball. isPause ){

// Redraw

Repaint ();

 

 

Try {

Thread. sleep (1 );

} Catch (Exception ef ){

Ef. printStackTrace ();

}

 

}

 

Try {

Thread. sleep (1 );

} Catch (Exception ef ){

Ef. printStackTrace ();

}

 

}

}

 

}

 

After this, the above problem is solved, but the baffle and ball are constantly flashing. In this case, we need to eliminate flickering in swing based on the double buffering principle, the above re-painting code is changed as follows:

// Redraw

Class mypanel extends JPanel {

 

Public void paint (Graphics g ){

 

// Rewrite the double buffer mechanism

Offline image = this. createImage (495,650 );

 

// Obtain the canvas of the captured image

Graphics gImage = offline image. getGraphics ();

 

// Obtain the background color of the canvas and fill the canvas with this color. If there is no fill effect, the drag effect will appear.

GImage. setColor (gImage. getColor ());

 

// Clear the image in the previous step, which is equivalent to gImage. clearRect (0, 0, WIDTH, HEIGHT)

GImage. fillRect (0, 0,495,650 );

 

 

// Override the parent class Method

Super. paint (gImage );

// Traverse the brick array for re-painting

For (int I = 0; I <arr. length; I ++ ){

For (int j = 0; j <arr [I]. length; j ++ ){

If (arr [I] [j]! = 0 ){

Int num = arr [I] [j];

String path = "image/" + num + ". png ";

ImageIcon = MapTest. createImageIcon (path );

GImage. drawImage (icon. getImage (), 35 * j, 15 * I, 35, 15, null );

}

}

}

// Redraw the bezel

Fender f = new Fender (this );

 

F. createFender (gImage, Fender. x, 630,100, 20 );

// Redraw the ball

Ball ball = new Ball ();

Ball. createBall (gImage, Ball. x0, Ball. y0 );

 

 

// Load the next image to the form canvas to obtain the effect of each painting.

G. drawImage (offline image, 0, 0, null );

 

}

 

}

At this point, a brick-and-mortar game has basically been implemented, but this game is still very simple, there are still many problems, and great improvements are needed. But the main purpose here is to deeply understand multithreading and the gains in this process.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.