• 4.9Java游戏项目练习


    4.9Java游戏项目练习

    目的

    巩固之前学的Java的基础

    基本功能的实现步骤

    AWT和Swing是Java中常见的GUI(图形用户界面),但是Java很少用于桌面应用开发,所以无需学习这两门技术
    MyGameFrame类:画游戏窗口
    package com.lucifer.game;

    import javax.swing.*; //需要导入的类
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    /**
    * @Description 飞机游戏的主窗口
    * @Author Lucifer
    */
    public class MyGameFrame extends JFrame {
       /**
        * 写一个方法用来在类里面加载窗口,初始化窗口
        */
       public void launchFrame(){
           /*给游戏窗口加一个标题---settitle*/
           this.setTitle("Make By Lucifer");
           /*窗口可视化---调用方法*/
           this.setVisible(true);
           /*给窗口设置大小---利用setSize方法*/
           this.setSize(600,600);
           /*窗口居中---调用方法*/
           this.setLocation(750,200);
           /*
           设置窗口的位置,根据的是屏幕的x.y轴来设置。
           原点(0,0)位于屏幕右上角
           往下是x轴,往右是y轴
           */

           /*加一个匿名内部类*/
           this.addWindowListener(new WindowAdapter() {
               /*重写一个方法*/
               @Override
               /*正在运行的window窗口,所以是Closing*/
               public void windowClosing(WindowEvent e){
                   /*结束虚拟机*/
                   System.exit(0);
              }
          });
      }

    再窗口中画图形和文本

    窗口类主方法:paint方法

    作用:

    • 做窗口的绘制

    特点:

    • 自动被调用

    • g这个变量相当于一支画笔

    实例:

    /**
    * @Description 飞机游戏的主窗口
    * @Author Lucifer
    */
    public class MyGameFrame extends JFrame {

       /*重写桌面绘制方法*/
       @Override
       public void paint(Graphics g){
           /*
           g本身带有颜色,形参对象是别人传过来的
           在下面来个g的颜色再别的地方再用g画笔就会直接更改
           所以有使用方法:
           用之前先保存,然后最后用完了再改回去---创建对象保存
           改字体的思想一样
            */
           Color c = g.getColor();
           Font f = g.getFont();

           /*画一条线,包括起点的坐标(横、纵坐标)和终点的(横、纵坐标)*/
           g.drawLine(100,100,300,300);
           /*画矩形的方法*/
           g.drawRect(100,100,300,300);
           /*画椭圆的方法*/
           g.drawOval(100,100,300,300);
           /*画实心的矩形*/
           g.fillRect(100,100,300,300);
           /*画字符串*/
           g.drawString("Lucifer",500,500);
           /*变颜色---这个Color是个静态的类,里面有些静态的变量,可以直接使用*/
           g.setColor(Color.BLUE);
           /*设置字体风格*/
           g.setFont(new Font("微软雅黑",Font.BOLD,50)); //形参为一个对象,实参也要创建一个对象去传入

           g.setColor(c);
           g.setFont(f);
      }

    用ImageIO实现图片加载技术(0.3版)

    过程:

    • 将图片加载的方法封装到GameUtil工具类中,便于以后直接调用

    实例:

    import javax.swing.*; //需要导入的类
    import java.awt.*;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    /**
    * @description 飞机游戏的主窗口
    * @author Lucifer
    */
    public class MyGameFrame extends JFrame {

       /*加载图片---创建对象加载*/
       Image Marks = GameUtil.getImage("images/staticPicture.jpg");

       /*重写桌面绘制方法*/
       @Override
       public void paint(Graphics g){
           /*
           g本身带有颜色,形参对象是别人传过来的
           在下面来个g的颜色再别的地方再用g画笔就会直接更改
           所以有使用方法:
           用之前先保存,然后最后用完了再改回去---创建对象保存
           改字体的思想一样
            */
           Color c = g.getColor();
           Font f = g.getFont();

           /*画一条线,包括起点的坐标(横、纵坐标)和终点的(横、纵坐标)*/
           g.drawLine(100,100,300,300);
           /*画矩形的方法*/
           g.drawRect(100,100,300,300);
           /*画椭圆的方法*/
           g.drawOval(100,100,300,300);
           /*画实心的矩形*/
           g.fillRect(100,100,300,300);
           /*画字符串*/
           g.drawString("Lucifer",500,500);
           /*变颜色---这个Color是个静态的类,里面有些静态的变量,可以直接使用*/
           g.setColor(Color.BLUE);
           /*设置字体风格*/
           g.setFont(new Font("微软雅黑",Font.BOLD,50)); //形参为一个对象,实参也要创建一个对象去传入
           /*画出图片*/
           g.drawImage(Marks,50,50,null);

           g.setColor(c);
           g.setFont(f);
      }
    工具类
    package com.lucifer.game;

    import javax.imageio.ImageIO;
    import java.awt.Image;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.net.URL;

    /**
    * 一个工具类
    * @author Lucifer
    */
    public class GameUtil {
       //私有化工具类构造器
       private GameUtil(){
      }

       /**
        * 返回指定路径文件的图片对象
        * @param path
        * @return
        */
       /*工具类的方法*/
       public static Image getImage(String path){
           BufferedImage bi = null;
           try {
               URL u = GameUtil.class.getClassLoader().getResource(path);
               bi = ImageIO.read(u);
          }catch (IOException e){
               e.printStackTrace();
          }
           return bi;
      }
    }

    多线程和内部类实现动画效果

    方法:

    • 再MyGameFrame类中定义"重画窗口线程PaintThread类"

    • 将PaintThread定义成内部类

    实例:

        /*
       定义一个内部类
       好处:
       直接使用外部类的属性
        */
       class PaintThread extends Thread{

           /*
           利用这个线程帮助我们反复重画窗口
            */
           /*重写父类的方法---内部类是子类*/
           @Override
           public void run(){
               while (true){

                   System.out.println("窗口重画次数");
                   /*调用外部类的repaint方法*/
                   repaint(); //paint自动被系统调用,repaint可以自己调用---重画方法

                   try{
                       Thread.sleep(40); //单位是毫秒
                  }catch (InterruptedException e){
                       e.printStackTrace();
                  }
                   /*
                   try中间内容没细说
                    */
              }
          }
      }
    package com.lucifer.game;

    import javax.swing.*; //需要导入的类
    import java.awt.*;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    /**
    * @description 飞机游戏的主窗口
    * @author Lucifer
    */
    public class MyGameFrame extends JFrame {

       /*加载图片---创建对象加载*/
       Image Marks = GameUtil.getImage("images/staticPicture.jpg");
       /*给个背景图片---动图皮卡丘*/
       Image Pkq = GameUtil.getImage("Images/big.gif");
       /*利用变量让Marks动起来*/
       int MarksX = 50, MarksY = 50;

       /*重写桌面绘制方法*/
       @Override
       public void paint(Graphics g){
           /*
           g本身带有颜色,形参对象是别人传过来的
           在下面来个g的颜色再别的地方再用g画笔就会直接更改
           所以有使用方法:
           用之前先保存,然后最后用完了再改回去---创建对象保存
           改字体的思想一样
            */
    //       Color c = g.getColor();
    //       Font f = g.getFont();
    //
    //       /*画一条线,包括起点的坐标(横、纵坐标)和终点的(横、纵坐标)*/
    //       g.drawLine(100,100,300,300);
    //       /*画矩形的方法*/
    //       g.drawRect(100,100,300,300);
    //       /*画椭圆的方法*/
    //       g.drawOval(100,100,300,300);
    //       /*画实心的矩形*/
    //       g.fillRect(100,100,300,300);
    //       /*画字符串*/
    //       g.drawString("Lucifer",500,500);
    //       /*变颜色---这个Color是个静态的类,里面有些静态的变量,可以直接使用*/
    //       g.setColor(Color.BLUE);
    //       /*设置字体风格*/
    //       g.setFont(new Font("微软雅黑",Font.BOLD,50)); //形参为一个对象,实参也要创建一个对象去传入
           /*画出皮卡丘*/
           g.drawImage(Pkq,0,0,null);
           /*画出图片---Marks*/
           g.drawImage(Marks,MarksX,MarksY,null);
           MarksX++;
           MarksY++;

    双缓存技术使用说明:

    GameObject类设计

    目的:

    • 因为制作的内容有很多共性,设计一个GameObject类作为所有物体的父类,方便编程

    共性:

    • 有图片的

    • 物体是有坐标的

    • 移动的速度

    • 物体的宽度和高度

    所以需要定义一个父类,把这些属性放进去,然后以后要使用就去继承即可

    实例:

    package com.lucifer.game;

    import java.awt.*;

    /**
    * 游戏物体的父类
    * @author Lucifer
    */
    public class GameObject {

       //列出他们需要的属性
       /*需要图片---对象*/
    //   private Image img;
       Image img;
       /*需要坐标点---double类型*/
    //   private double x,y;
       double x,y;
       /*他们的移动速度*/
    //   private int speed;
       int speed;
       /*宽度和高度*/
    //   private int width,height;
       int width,height;

    //   //JavaBean方法
    //   public void setImg(Image img){
    //       this.img = img;
    //   }
    //
    //   public Image getImg(){
    //       return img;
    //   }
    //
    //   public void setX(double x){
    //       this.x = x;
    //   }
    //
    //   public double getX(){
    //       return x;
    //   }
    //
    //   public void setY(double y){
    //       this.y = y;
    //   }
    //
    //   public double getY(){
    //       return y;
    //   }
    //
    //   public void setSpeed(int speed){
    //       this.speed = speed;
    //   }
    //
    //   public int getSpeed() {
    //       return speed;
    //   }
    //
    //   public void setHeight(int height) {
    //       this.height = height;
    //   }
    //
    //   public int getHeight() {
    //       return height;
    //   }
    //
    //   public void setWidth(int width) {
    //       this.width = width;
    //   }
    //
    //   public int getWidth() {
    //       return width;
    //   }

       /*定义物体画出自己的方法*/
       public void drawSelf(Graphics g){
           g.drawImage(img,(int)x,(int)y,null);
      }

       //为了方便使用加几个重载的构造器
       public GameObject(Image img, double x, double y, int speed, int width, int height){
           super();
           this.img = img;
           this.x = x;
           this.y = y;
           this.speed = speed;
           this.width = width;
           this.height = height;
      }

       public GameObject(Image img, double x, double y){
           super();
           this.img = img;
           this.x = x;
           this.y = y;
      }

       //无参构造器
       public GameObject(){
      }

       /**
        * 返回物体所在的矩形,便于后期的碰撞检测
        * @return
        */
       public Rectangle getRect(){
           return new Rectangle((int)x, (int)y,width,height);
      }
    }
    然后再写一个class重写里面需要用到的方法
    package com.lucifer.game;

    import java.awt.*;

    /**
    * 继承根类
    * @author Lucifer
    */
    public class Plane extends GameObject{

       /*重写父类方法*/
       /*
       因为这个属性用了private修饰符,所以不能直接重写
        */
       @Override
       public void drawSelf(Graphics g){
           g.drawImage(img,(int)x,(int)y,null);
           x++;
           y++;
      }

       /*重写构造器*/
       public Plane(Image img, double x, double y){
           this.img = img;
           this.x = x;
           this.y = y;
      }
    }
    最后在写一个类去调用
    package com.lucifer.game;

    import javax.swing.*; //需要导入的类
    import java.awt.*;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;

    /**
    * @description 飞机游戏的主窗口
    * @author Lucifer
    */
    public class MyGameFrame extends JFrame {

       /*加载图片---创建对象加载*/
       Image Marks = GameUtil.getImage("images/staticPicture.jpg");
       /*给个背景图片---动图皮卡丘*/
       Image Pkq = GameUtil.getImage("Images/big.gif");
    //   /*利用变量让Marks动起来*/
    //   int MarksX = 50, MarksY = 50;
       /*
       因为定义了Plane的类来写方法,所以这里需要创建对象去调用方法
        */
       Plane p = new Plane(Marks,50,50);
       Plane p2 = new Plane(Marks,69,69);
       Plane p3 = new Plane(Marks,79,79);

       /*重写桌面绘制方法*/
       @Override
       public void paint(Graphics g){
           /*
           g本身带有颜色,形参对象是别人传过来的
           在下面来个g的颜色再别的地方再用g画笔就会直接更改
           所以有使用方法:
           用之前先保存,然后最后用完了再改回去---创建对象保存
           改字体的思想一样
            */
    //       Color c = g.getColor();
    //       Font f = g.getFont();
    //
    //       /*画一条线,包括起点的坐标(横、纵坐标)和终点的(横、纵坐标)*/
    //       g.drawLine(100,100,300,300);
    //       /*画矩形的方法*/
    //       g.drawRect(100,100,300,300);
    //       /*画椭圆的方法*/
    //       g.drawOval(100,100,300,300);
    //       /*画实心的矩形*/
    //       g.fillRect(100,100,300,300);
    //       /*画字符串*/
    //       g.drawString("Lucifer",500,500);
    //       /*变颜色---这个Color是个静态的类,里面有些静态的变量,可以直接使用*/
    //       g.setColor(Color.BLUE);
    //       /*设置字体风格*/
    //       g.setFont(new Font("微软雅黑",Font.BOLD,50)); //形参为一个对象,实参也要创建一个对象去传入
    //       /*画出皮卡丘*/
    //       g.drawImage(Pkq,0,0,null);
    //       /*画出图片---Marks*/
    //       g.drawImage(Marks,MarksX,MarksY,null);
    //       MarksX++;
    //       MarksY++;
    //
    //       g.setColor(c);
    //       g.setFont(f);
           //因为已经在对象里封装了方法,所以直接调用即可
           p.drawSelf(g);
           p2.drawSelf(g);
           p3.drawSelf(g);
           /*
           可以定义不同的对象
           后期可以把对象放进数组或者容器里
            */

      }

       /*
       定义一个内部类
       好处:
       直接使用外部类的属性
        */
       class PaintThread extends Thread{

           /*
           利用这个线程帮助我们反复重画窗口
            */
           /*重写父类的方法---内部类是子类*/
           @Override
           public void run(){
               while (true){

                   System.out.println("窗口重画次数");
                   /*调用外部类的repaint方法*/
                   repaint(); //paint自动被系统调用,repaint可以自己调用---重画方法

                   try{
                       Thread.sleep(40); //单位是毫秒
                  }catch (InterruptedException e){
                       e.printStackTrace();
                  }
                   /*
                   try中间内容没细说
                    */
              }
          }
      }

       /**
        * 写一个方法用来在类里面加载窗口,初始化窗口
        */
       public void launchFrame(){
           /*给游戏窗口加一个标题---settitle*/
           this.setTitle("Make By Lucifer");
           /*窗口可视化---调用方法*/
           this.setVisible(true);
           /*给窗口设置大小---利用setSize方法*/
           this.setSize(600,600);
           /*窗口居中---调用方法*/
           this.setLocation(750,200);
           /*
           设置窗口的位置,根据的是屏幕的x.y轴来设置。
           原点(0,0)位于屏幕右上角
           往下是x轴,往右是y轴
           */

           /*加一个匿名内部类*/
           this.addWindowListener(new WindowAdapter() {
               /*重写一个方法*/
               @Override
               /*正在运行的window窗口,所以是Closing*/
               public void windowClosing(WindowEvent e){
                   /*结束虚拟机*/
                   System.exit(0);
              }
          });

           /*
           启动线程
            */
           new PaintThread().start(); //启动重画窗口的线程
      }

       //main方法调用上面的方法
       public static void main(String[] args) {
           MyGameFrame mgf = new MyGameFrame();
           mgf.launchFrame();
      }
    }
    It's a lonely road!!!
  • 相关阅读:
    java web 初学
    学习2
    学习
    上课
    Java中字母大小写的转换
    心得体会
    servlet请求
    响应设置消息体
    servlet响应-头部信息的设置
    servlet的响应(一)
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/14638844.html
Copyright © 2020-2023  润新知