Use IDEA to make a Java object-oriented game "Forgive Hat Battle"

Achievement display

Insert picture description here

Production ideas

Step 1: Discover the class (object)

人物-小丑: Buffoon
子弹-帽子:Missile
墙体:Wall
爆炸物:Explode

Step 2: Discover the attributes

小丑:宽和高,位置(x,y),移动速度
帽子:宽和高,位置(x,y),移动速度
墙体:宽和高,位置(x,y)
爆炸物:宽和高,位置(x,y)

Step 3: Discover the method

小丑:移动、攻击、人物撞边界
子弹:移动、子弹撞墙、子弹撞边界
爆炸物:消失

Difficulty analysis

How to create the form

public class GameClient extends Frame

Implement Java form by inheriting Frame class

public class Frame extends Window implements MenuContainer

The Frame class inherits the Window class and MenuContainer interface

How to load pictures into the form

Step 1: Create CommonUtils, a commonly used tool class, and create a new getImage method to convert image resources into Java objects

public class CommonUtils {
    
    
    /**
     * 读取图片资源, 转变为Java对象 Image
     * @param imgPath  图片路径
     * @return Image对象
     */
    public static Image getImage(String imgPath) {
    
    
        ImageIcon imageIcon = new ImageIcon(imgPath);
        return imageIcon.getImage();
    }
}

Step 2: Call the getImage method to add the object image

public class GameClient extends Frame {
    
    
    Image bg_image = CommonUtils.getImage("images/bg.png");
    Image explode = CommonUtils.getImage("images/explode.png");
    Image missile = CommonUtils.getImage("images/missile.png");
    Image wall_h = CommonUtils.getImage("images/wall-h.png");
    Image wall_v = CommonUtils.getImage("images/wall-v.png");
    Image buffoon = CommonUtils.getImage("images/body/s-left.png");

Step 3: Rewrite the paint method of Framed to implement the form to load pictures

@Override
    public void paint(Graphics g){
    
    
        //画背景图
        g.drawImage(bg_image,0,0,1100,700,this);
        //画小丑
        g.drawImage(buffoon,300,200,80,80,this);
        //画爆炸物
        g.drawImage(explode,800,400,90,90,this);
        //画原谅帽
        g.drawImage(missile,300,300,60,60,this);
        //画横着的墙体
        g.drawImage(wall_h,400,300,100,20,this);
        //画竖着的墙体
        g.drawImage(wall_v,400,300,20,100,this);

The drawImage method of the Graphics class needs to provide the Image class parameter, the x parameter of the form, the y parameter of the form, the width of the Image class, the length of the Image class, and the observer (the object to be notified when more images are converted)

Implementation of object movement

The direction of the target map is usually determined by the rule of "up to north, lower to south, left west and right east". The eight directions of movement usually refer to north, northeast, east, southeast, south, southwest, west, and northwest. Therefore, when defining the moving direction, use up, left, bottom, right, top right, bottom right, top left, and bottom left to indicate

Designed by Lin Jiabin

小丑:移动  move<Orientation类传递方向参数>
'left向左'   :x = x - this.speed;
'right向右'  :x = x + this.speed;
'down向下'   :y = y + this.speed;
'up向上'     :y = y - this.speed;
'ur东北方向'  : x = x + this.speed;
                y = y - this.speed;
'ul西北方向'  : x = x - this.speed;
                y = y - this.speed;
'dr东南方向'  : x = x + this.speed;
                y = y + this.speed;
'dl西南方向'  : x = x - this.speed;
                y = y + this.speed;

The realization of form closing

    public void start() {
    
    
        //窗体添加侦听方法
        this.addWindowListener(new WindowAdapter() {
    
    
            @Override
            public void windowClosing(WindowEvent e) {
    
    
                super.windowClosing(e);
                //退出游戏
                System.exit(0);
            }
        });

WindowAdapter class :
1. An abstract adapter class that receives window events. The methods in this class are empty. The purpose of this class is to facilitate the creation of listener objects.
2. Extend this class to create a WindowEvent listener and override the method for the required event. (If you want to implement the WindowListener interface, you must define all methods in the interface. This abstract class defines all methods as null, so you only need to define methods for the events you care about.
3. Use extended classes to create listener objects , And then use the addWindowListener method of the window to register a listener with the window. When the state of the window is changed by opening, closing, activating or deactivating, iconizing or de-iconizing, the relevant method in the listener object will be called , And pass WindowEvent to the method.
windowAdapter listener

The realization of key event trigger

 this.addKeyListener(new KeyAdapter() {
    
    
             //键盘按下的时候出发
            @Override
            public void keyPressed(KeyEvent e) {
    
    
                super.keyPressed(e);
            }
            //键盘松开
            @Override
            public void keyReleased(KeyEvent e) {
    
    
                //获取被按下的键对应的数值,如,a:67,b:68
                int keyCode = e.getKeyCode();
                switch (keyCode){
    
    
                    case KeyEvent.VK_UP:
                        System.out.println("向上走!!!");
                        buffoon.setDir("UP");
                        break;
                    case KeyEvent.VK_DOWN:
                        System.out.println("向下走");
                        buffoon.setDir("DOWN");
                        break;
                    case KeyEvent.VK_RIGHT:
                        System.out.println("向右走");
                        buffoon.setDir("RIGHT");
                        break;
                    case KeyEvent.VK_LEFT:
                        System.out.println("向左走!!");
                        buffoon.setDir("LEFT");
                        break;
                }
                buffoon.move(buffoon.getDir());
            }
        });

Key points of keystroke

Point 1:'new KeyAdapter()' Create a new key event listener, and register the listener to the main form through addKeyListener();
Point 2: Rewrite KeyAdapter methods, namely KeyTyped (type), KeyPresdded (press Next), KeyReleased (released). Here we only listen to the KeyPressed event and rewrite this method to realize the change of the character's direction state; the
third point: KeyEvent e.getKeyCode returns the key value corresponding to the key pressed, refer to the key value property of KeyEvent. Java 8 online API

Create object Buffoon.move() method

    public void move(String dir){
    
    
        switch (dir){
    
    
            case "UP":
                this.y -= this.speed;
                setDir("STOP");
                break;
            case "DOWN":
                this.y += this.speed;
                setDir("STOP");
                break;
            case "RIGHT":
                this.x += this.speed;
                setDir("STOP");
                break;
            case "LEFT":
                this.x -= this.speed;
                setDir("STOP");
                break;
        }

Every time a key event is monitored, the move method is called to realize the movement of the buffoon object

Call the move method every time a key event is monitored

Principle of object movement

The moving picture of the object is also called animation. It displays a series of continuous animated pictures frame by frame on the screen, and then displays the next frame at a short interval. This is repeated, using the human eye’s “persistence of vision”. 'The phenomenon subjectively feels as if the objects in the picture are moving.
FPS (Frames Per Second) is the number of frames per second. One frame is a static portrait, and the movie playback speed is 24FPS. The more frames, the smoother the displayed motion. In general, the minimum to avoid jerky movements is 30FPS. FPS Baidu Encyclopedia

Animated moving porter-thread

What is a thread? A
thread is the smallest unit that an operating system can perform operation scheduling. It is included in the process and is the actual operating unit in the process. A thread refers to a single sequential control flow in a process. Multiple threads can be concurrent in a process, and each thread executes different tasks in parallel.

/**
 * 定义一个重新绘制画面的线程,相当于招一个工人专门去从事这项工作
 */
public class RePaintThread implements Runnable{
    
    
    @Override
    //线程操作的全都在run方法中
    public void run() {
    
    
        while (true){
    
    
            //每50毫秒 执行一次
            try {
    
    
                Thread.sleep(20);
                //重新绘制图像
                gameClient.repaint();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

Point 1: Runnable interface
public class RePaintThread implements Runnable
When creating a thread with an object that implements interface Runnable, starting the thread will cause the run method of the object to be called in an independently executing thread.
Point two: Override the Run method
The general contract of the run method is: it may perform any desired action.
Repaint the image
gameClient.repaint();
Key point 3: Thread.sleep—the time interval between repeated execution of the thread 1. Use'While(
true)' to construct an infinite loop
2. Perform repaint() in an infinite loop to repaint the shape method
3. Thread interrupted exception (InterruptedException) is one of the manifestations of the current thread being interrupted. When you encounter this exception, if you don't know how to handle it, you should throw it upward.
catch clause

Guess you like

Origin blog.csdn.net/qq_42760141/article/details/109599610