Author’s brief introduction

Author name: The programming world is clear and hidden

CSDN blog expert, engaged in software development for many years, proficient in Java, JavaScript, the blogger is also from scratch to learn and grow step by step, know the importance of learning and accumulation, like to fight with the majority of ADC to upgrade, welcome your attention, look forward to learning, growth and take off with you!

Series directory

1. Java Tetris 2. Java backgammon 3. Old Java programmer spent a day writing a plane war 4. The old Java programmer spent 2 days to write a continuous look 6. Java elimination fun (love elimination every day) 7. Java snake small game 8. Java minesweeper small game 9

Quote:

A few days ago back to their hometown, see fish swimming in the river, river under one’s fingers itch, I once wanted to go fishing, but my daughter reminded me that I don’t eat wild animals, it suddenly let me back to reality, originally I was more than 30 years old, is really old programmer, since the old programmer can’t go to the river to catch fish, I made it myself a game of big fish eat small fish too! So it came, it came, it came with the COMPUTER and the JDK on its shoulder.

rendering

Implementation approach

Because do is simple version, so the idea is also very simple.

  1. Draw the window.
  2. Create a menu
  3. Create our fish
  4. Create the enemy fish
  5. Keyboard event listener
  6. Create the main thread, redraw the interface, and periodically create enemy fish.
  7. Processing other details

Code implementation

Create a window

First create a game form class GameFrame, inherit to JFrame, used to display on the screen (window object), each game has a window, set the window title, size, layout, etc.

package com.view;

import java.awt.BorderLayout;
import javax.swing.JFrame;

public class FishFrame extends JFrame {
    public int window_Width = 1180, window_Height = 640;
    public FishFrame(a) {
        setTitle("Big fish eat little fish.");// Window title
        setSize(window_Width, window_Height);// Window resolution
        setLayout(new BorderLayout());
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Click the close button to close the program
        setLocationRelativeTo(null);   // Set to center
    	setResizable(false); // The interface size cannot be changed
        setVisible(true);// Whether the window can display true-- false}}Copy the code

Create the panel container GamePanel to inherit from JPanel

package com.view;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class GamePanel extends JPanel{
	GamePanel gamePanel=this;
	private JFrame mainFrame=null;
	// Initialize the related parameters in the constructor
	public GamePanel(JFrame frame){
		this.setLayout(null); mainFrame = frame; }}Copy the code

Create a Main class to start the window.

package com.main;

import com.view.FishFrame;
import com.view.GamePanel;

public class Main {
    public static void main(String[] args) {
    	FishFrame frame = new FishFrame();
		GamePanel panel = new GamePanel(frame);
		frame.add(panel);
		frame.setVisible(true);// Set the display}}Copy the code

Right click to execute the Main class and the window is created

Draw the background

Create Picture class, responsible for loading all pictures, easy to call

package com.utils;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

public class Picture {
    public static BufferedImage bg0,FishL,FishR;
    
    public static List badFishImages =new ArrayList() ;
    public static List badFishImages1 =new ArrayList() ;
    Static code block - the program starts and executes when the class is loaded
    static {
        try {
            bg0 = ImageIO.read(Picture.class.getClassLoader().getResourceAsStream("img/bg0.jpg"));
            FishL = ImageIO.read(Picture.class.getClassLoader().getResourceAsStream("img/fishIcon0.png"));
            FishR = ImageIO.read(Picture.class.getClassLoader().getResourceAsStream("img/fishIcon0R.png"));
            BufferedImage temp;
            for (int i = 1; i <= 18; i++) {
            	temp = ImageIO.read(Picture.class.getClassLoader().getResourceAsStream("img/fishIcon"+i+".png"));
            	badFishImages.add(temp);
            	temp = ImageIO.read(Picture.class.getClassLoader().getResourceAsStream("img/fishIconL"+i+".png")); badFishImages1.add(temp); }}catch(IOException e) { e.printStackTrace(); }}}Copy the code

Rewrite the paint method in GamePanel and draw the background.

@Override
public void paint(Graphics g) {
	super.paint(g);
	// Draw the background image
	g.drawImage(Picture.bg0, 0.0.null);
}
Copy the code

Run as follows:

Create a menu

// Initialize button
private void  initMenu(a){
	// Create a menu and menu options
	JMenuBar jmb = new JMenuBar();
	JMenu jm1 = new JMenu("Game");
	jm1.setFont(new Font("Song Of song origin", Font.BOLD, 15));// Set the font displayed in the menu
	
	JMenuItem jmi1 = new JMenuItem("Start a new game");
	JMenuItem jmi2 = new JMenuItem("Quit");
	jmi1.setFont(new Font("Song Of song origin", Font.BOLD, 15));
	jmi2.setFont(new Font("Song Of song origin", Font.BOLD, 15));
	
	jm1.add(jmi1);
	jm1.add(jmi2);
	
	jmb.add(jm1);
	mainFrame.setJMenuBar(jmb);// Put the menu Bar on the JFrame
	
	jmi1.addActionListener(this);
	jmi1.setActionCommand("Restart");
	jmi2.addActionListener(this);
	jmi2.setActionCommand("Exit");
}
Copy the code

If you add this code to GamePanel, it will cause an error, so you need to implement ActionListener and rewrite the actionPerformed method.The GamePanel code is as follows:

package com.view;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.plaf.FontUIResource;

import com.utils.Picture;

public class GamePanel extends JPanel implements ActionListener{
	GamePanel gamePanel=this;
	private JFrame mainFrame=null;
	// Initialize the related parameters in the constructor
	public GamePanel(JFrame frame){
		this.setLayout(null);
		mainFrame = frame;
		
		/ / the menu
		initMenu();
	}
	
	@Override
	public void paint(Graphics g) {
    	super.paint(g);
    	// Draw the background image
    	g.drawImage(Picture.bg0, 0.0.null);
    }
	// Initialize button
	private void  initMenu(a){
		// Create a menu and menu options
		JMenuBar jmb = new JMenuBar();
		JMenu jm1 = new JMenu("Game");
		jm1.setFont(new Font("Song Of song origin", Font.BOLD, 15));// Set the font displayed in the menu
		
		JMenuItem jmi1 = new JMenuItem("Start a new game");
		JMenuItem jmi2 = new JMenuItem("Quit");
		jmi1.setFont(new Font("Song Of song origin", Font.BOLD, 15));
		jmi2.setFont(new Font("Song Of song origin", Font.BOLD, 15));
		
		jm1.add(jmi1);
		jm1.add(jmi2);
		
		jmb.add(jm1);
		mainFrame.setJMenuBar(jmb);// Put the menu Bar on the JFrame
		
		jmi1.addActionListener(this);
		jmi1.setActionCommand("Restart");
		jmi2.addActionListener(this);
		jmi2.setActionCommand("Exit");
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		String command = e.getActionCommand();
		UIManager.put("OptionPane.buttonFont".new FontUIResource(new Font("宋体", Font.ITALIC, 18)));
		UIManager.put("OptionPane.messageFont".new FontUIResource(new Font("宋体", Font.ITALIC, 18)));
		if ("Exit".equals(command)) {
			Object[] options = { "Sure"."Cancel" };
			int response = JOptionPane.showOptionDialog(this."Are you sure you want to quit?"."",
					JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null,
					options, options[0]);
			if (response == 0) {
				System.exit(0); }}else if("Restart".equals(command)){ restart(); }}// Start over
	private void restart(a) {}}Copy the code

Create our fish

package com.model;

import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import com.utils.Dir;
import com.utils.Picture;
import com.view.GamePanel;

public class Fish extends ArrayList<Fish> {
    private int x, y,/* Main fish birth coordinates */
            width = 50, height = 30,
            speed = 10;

	private Dir dir;
    private boolean isMoving = false, isLiving = true;
    private GamePanel panel;// Hold each other
    private String group;
    private Graphics g;
    private BufferedImage image=Picture.FishL;
    private int type = 1;//1 right, -1 left

    public Fish(int x, int y, Dir dir, GamePanel panel, String group) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.panel = panel;
        this.group = group;
    }

    public void paint(Graphics g) {
        this.g = g;
        switch (dir) {
            case UP:
            	image = type==1? Picture.FishR:Picture.FishL;break;
            case DOWN:
            	image = type==1? Picture.FishR:Picture.FishL;break;
            case LEFT:
            	type = -1;
            	image = type==1? Picture.FishR:Picture.FishL;break;
            case RIGHT:
            	type = 1;
            	image = type==1? Picture.FishR:Picture.FishL;break;
        }
        
        g.drawImage(image, x, y,width,height, null);
    }

	public void setDir(Dir dir) {
        this.dir = dir;
    }

    public void setMoving(boolean moving) {
        isMoving = moving;
    }

    public void setSpeed(int speed) {
        this.speed = speed;
    }

    public String getGroup(a) {
        return group;
    }

    public void setGroup(String group) {
        this.group = group;
    }

    public boolean isLiving(a) {
        return isLiving;
    }

    public void setLiving(boolean living) {
        isLiving = living;
    }

    public int size(a) {
        return 0;
    }
    
    public int getX(a) {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY(a) {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getWidth(a) {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight(a) {
		return height;
	}

	public void setHeight(int height) {
		this.height = height; }}Copy the code

Instantiate the fish

private void initMyFish(a) {
	myFish = new Fish(0.320, Dir.RIGHT, this."GOOD");		
}
Copy the code

Called in the constructor

// Initialize the related parameters in the constructor
public GamePanel(JFrame frame){
	this.setLayout(null);
	mainFrame = frame;
	
	/ / the menu
	initMenu();
	
	// Create my fish
	initMyFish();
}
Copy the code

Draw in the paint method

@Override
public void paint(Graphics g) {
	super.paint(g);
	// Draw the background image
	g.drawImage(Picture.bg0, 0.0.null);
	/ / draw the fish
    if(myFish! =null) myFish.paint(g);
}
Copy the code

Run as follows (our minnows appear on the left) :

Draw enemy fish

Creating bad fish

package com.model;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.utils.Picture;
import com.view.GamePanel;

public class BadFish {
	private int x, y, width = 50, height = 50, speed = 1;
	private boolean isMoving = false, isLiving = true;
	private GamePanel panel;// Hold each other
	private String group;
	private BufferedImage image;
	private int large = 0;// 0 indicates small, and 1 indicates large
	private int type = 0;// 1 to 18 are different fish
	private List imgList = null;

	public BadFish(GamePanel panel, String group) {
		this.panel = panel;
		this.group = group;
		
		init();

	}

	private void init(a) {
		this.x=1180;
    	Random random = new Random();
    	this.type= random.nextInt(18) +1;
    	this.large = random.nextInt(2) = =0? 0:1;
    	if(large==1){
			imgList = Picture.badFishImages1;
		}else {
			imgList = Picture.badFishImages;
		}
    	image = (BufferedImage)imgList.get(type-1);
        width = image.getWidth();
        height = image.getHeight();
      	y = random.nextInt(590-height);
	}

	public void paint(Graphics g) {
		if(! isLiving) { ArrayList<BadFish> badFishs = panel.badFishss; badFishs.remove(this);
			return;
		}
		g.drawImage(image, x, y, width, height, null);
	}
	

	public void remove(a) {
		this.isMoving=false;
		this.isLiving=false;
		panel.badFishss.remove(this);
	}
	
	public int getX(a) {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY(a) {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getWidth(a) {
		return width;
	}

	public void setWidth(int width) {
		this.width = width;
	}

	public int getHeight(a) {
		return height;
	}

	public void setHeight(int height) {
		this.height = height;
	}
	public boolean isLiving(a) {
		return isLiving;
	}

	public void setLiving(boolean isLiving) {
		this.isLiving = isLiving; }}Copy the code

Instantiate, and call

// Initialize the related parameters in the constructor
public GamePanel(JFrame frame){
	this.setLayout(null);
	mainFrame = frame;
	
	/ / the menu
	initMenu();
	
	// Create my fish
	initMyFish();
	
	// Create an enemy fish
	initBadFishs();
}
// Create bad fish
private void createBadFish(a){
	BadFish badFish = new BadFish(this."BAD");
    badFishss.add(badFish) ;
}
// Create an initial 6
private void initBadFishs(a) {
    for (int i = 0; i < 6; i++) { createBadFish(); }}Copy the code

Draw in the paint method

@Override
	public void paint(Graphics g) {
    	super.paint(g);
    	// Draw the background image
    	g.drawImage(Picture.bg0, 0.0.null);
    	/ / draw the fish
        if(myFish! =null) myFish.paint(g);
        
        // Draw enemy fish
        for (int i = 0; i < badFishss.size(); i++) {
        	 BadFish fish = badFishss.get(i);
        	 if(fish! =null) fish.paint(g); }}Copy the code

Added move method to bad fish

private void move(a) {
	new Thread(new Runnable() {
		@Override
		public void run(a) {
			while (isLiving) {
				
				
				x -= speed;
				if (x + width < 0) {
					x = 1180;
					y = new Random().nextInt(590 - height);
				}
				
				try {
					Thread.sleep(20);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if(! isLiving){break;
				}
			}
		}
	}).start();
}
Copy the code

Add main thread new draw

// The game thread is used to automatically move down
private class GameThread implements Runnable {
	@Override
	public void run(a) {
		while (true) {
			if("start".equals(gameFlag)){
				repaint();
			}
			try {
				Thread.sleep(50);
			} catch(InterruptedException e) { e.printStackTrace(); }}}}Copy the code

Remember to call it in the construct

// Start the main thread
new Thread(new GameThread()).start();
Copy the code

Run as follows:

Add more fish

Add code to paint to periodically create fish and limit the number of fish to 60

if("start".equals(gameFlag)){
	if(time==30){
		time=0;
		if(badFishss.size()<60){ createBadFish(); }}else{ time++; }}Copy the code

Run as shown below:

Add keyboard movement events

Remember to call this method in the construct.

// Add keyboard listener
private void createKeyListener(a) {
	KeyAdapter l = new KeyAdapter() {
		/ / press
		@Override
		public void keyPressed(KeyEvent e) {
			int key = e.getKeyCode();
			switch (key) {
				/ / up
				case KeyEvent.VK_UP:
				case KeyEvent.VK_W:
					if(myFish! =null){
						myFish.move(Dir.UP);
					}
					break;
					
				/ / to the right
				case KeyEvent.VK_RIGHT:
				case KeyEvent.VK_D:
					if(myFish! =null){
						myFish.move(Dir.RIGHT);
					}
					break;
					
				/ / down
				case KeyEvent.VK_DOWN:
				case KeyEvent.VK_S:
					if(myFish! =null){
						myFish.move(Dir.DOWN);
					}
					break;
					
				/ / to the left
				case KeyEvent.VK_LEFT:
				case KeyEvent.VK_A:
					if(myFish! =null){
						myFish.move(Dir.LEFT);
					}
					break; }}/ / to loosen
		@Override
		public void keyReleased(KeyEvent e) {}};// Add keyboard listener to main frame
	mainFrame.addKeyListener(l);
}
Copy the code

Add move method to our Fish class

public void move(Dir dir) {
    	this.setDir(dir);
    	this.setMoving(true);
         
        if(! isMoving) {return;
        }
        
        switch (dir) {
            case UP:
                y -= speed;
                if(y<=0){
                	y=0;
                }
                break;
            case DOWN:
                y += speed;
                if(y>=590-height){
                	y=590-height;
                }
                break;
            case LEFT:
                x -= speed;
                if(x<=0){
                	x=0;
                }
                break;
            case RIGHT:
                x += speed;
                if(x>=1180-width){
                	x=1180-width; }}}Copy the code

At this time our small fish can control the movement with the keyboard.

Deal with fish collisions

To judge the collision between our fish and the enemy fish, because the picture is square, we take out the four vertex coordinates of one fish and judge with another fish respectively. As long as one point is within the range, it means the collision has occurred. Note: the collision problem is clearly explained in the aircraft war, and the diagram is drawn to illustrate it. It can be turned over, the principle is the same.

public boolean isHit(Fish fish,BadFish badFish) {
	if(isHit1(fish, badFish)){// If in collision range
		if(fish.getX()<badFish.getX()){// The fish is on the left of the enemy fish
			if(fish.getY()>badFish.getY()){// The fish is below the enemy fish
				if((fish.getY()+10<badFish.getY()+badFish.getHeight())
						&& (fish.getX() + fish.getWidth()>badFish.getX()+10)) {return true; }}else if(fish.getY()<badFish.getY()){// The fish is above the enemy fish
				if(badFish.getY()+10<fish.getY()+fish.getHeight()
						&&fish.getX() + fish.getWidth()>badFish.getX()+10) {return true; }}}else if(fish.getX()>badFish.getX()){// The fish is on the left of the enemy fish
			if(fish.getY()>badFish.getY()){// The fish is below the enemy fish
				if(fish.getY()+10<badFish.getY()+badFish.getHeight()
						&& badFish.getX() + badFish.getWidth()>fish.getX()+10) {return true; }}else if(fish.getY()<badFish.getY()){// The fish is above the enemy fish
				if(badFish.getY()+10<fish.getY()+fish.getHeight()
						&& badFish.getX() + badFish.getWidth()>fish.getX()+10) {return true; }}}}return false;
}
// Determine if the fish collide
public boolean isHit1(Fish fish,BadFish badFish) {
	1 / / way
	/ / the top left corner
	int x1 = badFish.getX();
	int y1 = badFish.getY();
	/ / the top right corner
	int x2 = badFish.getX()+badFish.getWidth();
	int y2 = badFish.getY();
	/ / the bottom right hand corner
	int x3 = badFish.getX()+badFish.getWidth();
	int y3 = badFish.getY()+badFish.getHeight();
	/ / the bottom left corner
	int x4 = badFish.getX();
	int y4 = badFish.getY()+badFish.getHeight();
	// As long as there is a point in the range, it is considered a collision
	if(comparePointFish(x1,y1,fish)|| comparePointFish(x2,y2,fish)
			||comparePointFish(x3,y3,fish)||comparePointFish(x4,y4,fish) ){
		return true;
	}
	
	// If method 1 fails, use method 2
	2 / / way
	x1 = fish.getX();
	y1 = fish.getY();
	/ / the top right corner
	x2 = fish.getX()+fish.getWidth();
	y2 = fish.getY();
	/ / the bottom right hand corner
	x3 = fish.getX()+fish.getWidth();
	y3 = fish.getY()+fish.getHeight();
	/ / the bottom left corner
	x4 = fish.getX();
	y4 = fish.getY()+fish.getHeight();
	if(comparePoint(x1,y1,badFish)|| comparePoint(x2,y2,badFish)||comparePoint(x3,y3,badFish)||comparePoint(x4,y4,badFish) ){
		return true;
	}
	return false;
}
// Use the coordinates
private boolean comparePointFish(int x,int y,Fish fish){
	// Coordinates greater than the upper left corner and less than the lower right corner are definitely in range
	if(x>fish.getX() && y >fish.getY()
		&& x<fish.getX()+fish.getWidth() && y <fish.getY()+fish.getHeight()	){
		return  true;
	}
	return false;
}
// Use the coordinates
private boolean comparePoint(int x,int y,BadFish badFish){
	// Coordinates greater than the upper left corner and less than the lower right corner are definitely in range
	if(x>badFish.getX() && y >badFish.getY()
		&& x<badFish.getX()+badFish.getWidth() && y <badFish.getY()+badFish.getHeight()){
		return  true;
	}
	return false;
}
Copy the code

In addition, there is a +10 pixel code in the above code, in order to make the collision look more realistic, because the fish for the square image, there are still many gaps in the corners.

Eat enemy fish processing

Add the eat method to the Fish class to make it bigger.

private void eat(a) {
	ArrayList<BadFish> badFishList = panel.badFishss;
	BadFish badFish;
	for (int i = 0; i < badFishList.size(); i++) {
		badFish = badFishList.get(i);
		if(! badFish.isLiving())continue ;
		if(panel.isHit(this, badFish)){/ / fish
			if(this.height>=badFish.getHeight()){// Eat enemy fish
				System.out.println("Eat the enemy fish.");
				System.out.println("this.width==="+this.width);
				// The fish get bigger
				if(this.width<150) {this.height+=2;
    				this.width +=2*1.66;
				}
				// The enemy fish disappears
				badFish.remove();
			}else {// Failed to eject if eaten
				System.out.println("Eaten by enemy fish.");
				
				panel.myFish.isMoving=false;
				panel.myFish.isLiving=false;
				panel.myFish=null;
				
				panel.gameOver();
			}
			break; }}}Copy the code

– Added a collision method to the BadFish class. If the enemy fish is too big, the game will fail and the fish will become too big.

private void hit(a){
	Fish fish = panel.myFish;
	if(fish==null) return;
	if(! isLiving)return ;
	
	if(panel.isHit(fish, this)) {/ / fish
		if(fish.getHeight()>=this.getHeight()){// Eat enemy fish
			System.out.println("Eat enemy fish....");
			// The fish get bigger
			if(fish.getWidth()<150){
				fish.setHeight(fish.getHeight()+2);
				fish.setWidth(fish.getWidth()+3);
			}
			// The enemy fish disappears
			this.remove();
		}else {// Failed to eject if eaten
			System.out.println("Eaten by enemy fish....");
			fish.setMoving(false);
			fish.setLiving(false);
			panel.myFish=null; panel.gameOver(); }}}Copy the code

Operation effect:That’s it, and then you add some other stuff, like starting over, but I don’t want to talk about that.

To see the big guy here, move the rich little hands to praise + reply + collection, can [concern] a wave of better.

Code acquisition method:

Help article [praise] + [collection] + [concern] + [comment], plus V: QQ283582761, I send you!

More wonderful

1. Java Tetris 2. Java backgammon 3. Old Java programmer spent a day writing a plane war 4. The old Java programmer spent 2 days to write a continuous look 6. Java elimination fun (love elimination every day) 7. Java snake small game 8. Java minesweeper small game 9

reading

1. JavaWeb library management system 2. JavaWeb Student dormitory management system 3