小球乱撞游戏

任务:

1、用一个线程控制所有的小球对象

2、控制小球的暂停/恢复

3、小球碰撞反弹

代码实现:

一、窗体创建

  public class UI extends JFrame {
    public void showUI(){
        //窗体
        setTitle("线程游戏");
        setSize(900,900);
        //居中显示
        setLocationRelativeTo(null);
        //退出线程
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        //设置窗体背景颜色
        getContentPane().setBackground(Color.WHITE);
        //流式布局管理器
        setLayout(new FlowLayout());
        //画笔对象:在界面程序中显示自定义类型
        //自定义内容显示在哪个组件上,画笔就从该组件上获取
        //从窗体上获取画笔对象
        //鼠标监听器
        //引用类型:(接口)interface,(类)class,数组
        GameMouse mouse = new GameMouse();
        //添加按钮
        String[] s = {"开始","暂停","添加"};
        for (int i = 0; i < s.length ; i++) {
            JButton bt = new JButton(s[i]);
            bt.setSize(60,40);
            add(bt);
            bt.addActionListener(mouse);
        }
        setVisible(true);
        Graphics g = getGraphics();
        mouse.gr = g;
        //给窗体添加键盘监听器方法
        addKeyListener(mouse);
        //让窗体获取焦点
        requestFocus();
    }
    public static void main(String[] args) {
        new UI().showUI();
    }
}

在窗体创建时,需要注意几个点:

①setVisible方法应在getGraphics方法前面,创建的按钮(在窗体需要控制的对象)都需添加监听器。

②新知识:获取焦点requesFocus();顾名思义,就是获取你需要操作的对象将它“聚焦”,例如:平时你在登陆qq界面时,有个账号输入框和密码输入框,假如你先鼠标点击了电脑桌面的app,这时聚焦点不在qq账号输入框那,你需要用鼠标点击一下(聚焦一下),才能输入。

二、创建小球类

package BallGamev4;

import java.awt.*;

public class Ball {
    //属性
    public int x,y,speedX,speedY,size;
    public Color color;
    //初始化属性
    public Ball(){
        x = (int)(Math.random()*700);//Math.random()是一个[0.0,1.0]区间的随机数
        y = (int)(Math.random()*600);
        speedX = 3;
        speedY = 3;
        size = (int)(Math.random()*30+40);
        color = Color.BLACK;
    }
    public Ball(int x,int y){
        this.x = x;
        this.y = y;
        size = 50;
        color = Color.BLACK;
    }
    //绘制小球
    public void drawBall(Graphics g){
        g.setColor(Color.WHITE);
        g.fillOval(x,y,size,size);
        x += speedX;
        y += speedY;
        g.setColor(color);
        g.fillOval(x,y,size,size);
        if(x+size > 900 || x<0){
            speedX = -speedX;
        }
        if(y+size > 900 || y<0){
            speedY = -speedY;
        }

    }
}

在小球类中,我们实现了小球撞墙反弹功能,在这里我们有设置小球speedX,speedY的关于x,y轴上的速度,只要当球碰撞到边界时,把速度修改为负的就好了。

还有一种实现小球撞墙反弹,这里我们只有一个速度变量,添加了一个角度alpha变量.看似第一种简单得多。

        x+=speed*Math.sin(alpha*Math.PI/180);
        y-=speed*Math.cos(alpha*Math.PI/180);
        if(x<=10||x>=730)alpha=360-alpha;
        if(y<=220||y>=730)alpha=180-alpha;

三、监听器类

package BallGamev4;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;

public class GameMouse implements ActionListener, KeyListener {
    UI ui = new UI();
    //画笔:引用传递
    public Graphics gr;
    public BallThread bt;
    public ArrayList<Ball> listBall = new ArrayList<>();
    public Ball mb;
    //创建对象:类名 对象名 = new 构造方法
    //构造方法:public 类名(参数类型 参数名){方法体。。}
    //作用1、创建对象 2、初始化属性
    //每个类都有一个默认的无参构造方法,当自定义构造方法,那么默认的无参构造方法就被替代了
    //单例模式:
    @Override
    public void actionPerformed(ActionEvent e) {
        //让窗体获取焦点:
        ui.requestFocus();
        System.out.println("点击开始");
        String s = e.getActionCommand();
        //获取当前事件源对象
        JButton jbt = (JButton) e.getSource();
        if("暂停".equals(s)){
            bt.flag = true;
            jbt.setText("恢复");
        }else if("恢复".equals(s)){
            bt.flag = false;
            jbt.setText("暂停");
        }else if("开始".equals(s)){
            if(bt==null){
                //创建线程对象
                bt = new BallThread(gr,listBall);
                //启动线程,每个线程只能调用一个start方法
                Thread t = new Thread(bt);
                t.start();
            }
        }else if("添加".equals(s)){
            Ball ball = new Ball();
            listBall.add(ball);
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    public Graphics getGr() {
        return gr;
    }

    public void setGr(Graphics gr) {
        this.gr = gr;
    }
}

注意:①获取按钮上的字符用的是getActionCommand方法。

②获取当前事件源对象getSource方法。

③我们为了只让启动一条线程,在启动线程前做个判断,若线程对象为null才从新创建。

④我们实现小球添加是通过创建一个动态数组,点击一下“添加”就新建一个小球对象,后面画的时候再遍历它。

⑤我们实现小球暂停是在小球线程类中创建一个布尔类型,如果点击“暂停”按钮,布尔值变为true,然后在线程类中

if(flag){

continue;

}

线程run方法就不会往下运行了,从而就不调用小球的draw方法,实现了暂停。

四、小球线程类

package BallGamev4;

import java.awt.*;
import java.util.ArrayList;

/**
 * 继承线程类: Thread
 * 实现Runnable接口
 */
public class BallThread implements Runnable{
    public Graphics gr;
    public boolean flag = false;//用来控制线程暂停的标记
    public ArrayList<Ball> listBall;
    public BallThread(Graphics gr,ArrayList<Ball> listBall){
        this.gr = gr;
        this.listBall = listBall;
    }
    //重写run方法:启动线程后自动执行的方法
    //当run方法执行完,该线程结束,它占用的资源被回收
    @Override
    public void run() {
        int x = (int)(Math.random()*700),y=0;
        while(true){
            //延时
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if(flag){
                continue;
            }
            //遍历listBall列表
            for (int i = 0; i < listBall.size(); i++) {
                Ball ball = listBall.get(i);
                ball.drawBall(gr);
            }
        }
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值