一、实现思路(emmmm,这个地方我很大程度参照了别人的写法)

   由于键盘按键众多,因此使用选择框JComboBox 进行按键选择,点击一个JButton 按钮后,读取所有选择框中的内容,然后存到一个用于保存键位设置的对象Key中,然后在坦克移动的时候根据对象Key中的数据判断对坦克的操作。

    同时,为了保证每次打开游戏时,能够保留上一次的按键设置,使用对象流将对象Key存入文件,以后创建KeySet的对象后,从文件中读取保存对象Key的信息,并使用;如果文件不存在或者文件为空,那么就重新new一个Key对象,并在用户确定按键设置后将新的Key对象存入文件中,以便下一次打开。

  同时,我们也需要绘制选择界面,首先就是将选择框JComboBox 以及按钮JButton 加入JFrame里面,并设置好位置等等,同时我们需要提示用户当前的按键是什么,为了简单,直接paint到JFrame里面了。

二、JComboBox的使用

  1) JComboBox  UP =  new JComboBox<String>()

      创建类JComboBox的对象,用String代表选择内容的类型,这里用的是String型

    2) UP.setFont(new Font(Font.SERIF, Font.BOLD, 20));

      设置选择框中字体的类型

    3)   UP.setBounds(100, 100, 150, 50);

      设置选择框的大小和相对位置,相对位置为相对于JFrame的位置

    4)   UP.addItem("VK_UP");

      像选择框中添加选择,这里我添加了上移键的默认位置 VK_UP就是键盘上的那个向上的箭头

    5)  jframe.add(UP);

      jrame就是JFrame的对象,我们需要把选择框加入其中,才可以让别人看得见并进行操作

    6)  String up = (String) UP.getSelectedItem();

      获取选择框的选择内容,并转型,因为返回值是Object类型的

 三、一些次要的功能

  1)错误提示

    比如选择按键的时候,同一个按键实现了两个功能,就会出现如下的情况

    同时,出现了用户名没有输入或者为空的时候也会进行提示,如下

    实现方法:JOptionPane.showMessageDialog(jframe, "按键重复!", "警告", 0);

      第一个参数代表要显示在的窗口,第二个参数为提示信息,第三个参数为标题,第四个参数为提示信息类型

  2)音乐播放

    this.music = new Music(11);

     music.start();

    构造方法中参数为音乐类型,Music为自定义的类,具体请参考另一篇博文

    通过start()方法用多线程开始播放音乐。

public void actionPerformed(ActionEvent e) {
if(e.getSource() == music_button) {
if(tot++ % 2 == 0) {
music.close();
}else {
music.open();
}
}
  ......
}

    这个地方设置了一个musci_button的按钮,就是图中左上角的那个,实现点击后暂停或者重新播放。

四、效果展示

 五、代码区

   类Key

package component;

import java.awt.event.KeyEvent;
import java.io.Serializable; public class Key implements Serializable{
private static final long serialVersionUID = 1L;
public int MY_UP;
public int MY_DOWN;
public int MY_LEFT;
public int MY_RIGHT;
public int MY_ATTACK;
public Key() {
MY_UP = KeyEvent.VK_UP;
MY_DOWN = KeyEvent.VK_DOWN;
MY_LEFT = KeyEvent.VK_LEFT;
MY_RIGHT = KeyEvent.VK_RIGHT;
MY_ATTACK = KeyEvent.VK_SPACE;
}
public Key(int MY_UP,int MY_DOWN,int MY_LEFT,int MY_RIGHT,int MY_ATTACK) {
this.MY_UP = MY_UP;
this.MY_DOWN = MY_DOWN;
this.MY_LEFT = MY_LEFT;
this.MY_RIGHT = MY_RIGHT;
this.MY_ATTACK = MY_ATTACK;
}
}

  类KeySet

package component;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import javax.swing.*; public class KeySet extends JPanel implements ActionListener{
private static final long serialVersionUID = 1675L;
private Key key = null;
private JFrame jframe;
private JComboBox<String> UP;
private JComboBox<String> RIGHT;
private JComboBox<String> DOWN;
private JComboBox<String> LEFT;
private JComboBox<String> ATTACK;// 攻击
private JTextField txt = null;// 输入名字
private JButton ENSURE;
private JButton music_button = new JButton("");
private Music music;
private static int tot = 0; public static void main(String[] args) {
new KeySet();
} public KeySet() {
this.readData();
this.music = new Music(11);
music.start();
jframe = new JFrame("设置");
jframe.setSize(1200, 600);
jframe.setLocationRelativeTo(null);// 不可扩大
jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jframe.setLayout(null); ENSURE = new JButton("保存");// 确定按键
ENSURE.setFont(new Font(Font.SERIF, Font.BOLD, 20));// 设置字体
ENSURE.setBounds(100, 400, 100, 50);// 设置按钮
jframe.add(ENSURE);
ENSURE.addActionListener(this); UP = new JComboBox<String>();
UP.setFont(new Font(Font.SERIF, Font.BOLD, 20));
UP.addItem("VK_UP");// 初始值
UP.setBounds(100, 100, 150, 50);
addChoose(UP);// 添加备选项 RIGHT = new JComboBox<String>();
RIGHT.setFont(new Font(Font.SERIF, Font.BOLD, 20));
RIGHT.addItem("VK_RIGHT");
RIGHT.setBounds(400, 200, 150, 50);
addChoose(RIGHT); DOWN = new JComboBox<String>();
DOWN.setFont(new Font(Font.SERIF, Font.BOLD, 20));
DOWN.addItem("VK_DOWN");
DOWN.setBounds(400, 100, 150, 50);
addChoose(DOWN); LEFT = new JComboBox<String>();
LEFT.setFont(new Font(Font.SERIF, Font.BOLD, 20));
LEFT.addItem("VK_LEFT");
LEFT.setBounds(100, 200, 150, 50);
addChoose(LEFT); ATTACK = new JComboBox<String>();
ATTACK.setFont(new Font(Font.SERIF, Font.BOLD, 20));
ATTACK.addItem("VK_SPACE");
ATTACK.setBounds(100, 300, 150, 50);
addChoose(ATTACK); txt = new JTextField("用户名");
txt.setBounds(400, 300, 150, 50);
txt.setFont(new Font(Font.SERIF, Font.BOLD, 20)); //music_button.setBackground(Color.CYAN);
music_button.setBounds(0, 0, 75, 75);
music_button.setIcon(new ImageIcon("img/music2.png"));
music_button.addActionListener(this); jframe.add(UP);
jframe.add(RIGHT);
jframe.add(DOWN);
jframe.add(LEFT);
jframe.add(ATTACK);
jframe.add(txt);
jframe.add(music_button); this.setBounds(0, 0, 1200, 600);
jframe.add(this); // 将画板加入画笔
jframe.repaint();
jframe.setVisible(true); } public void paint(Graphics g) {
Font f = new Font(Font.SERIF,Font.BOLD,20);
g.setFont(f);
g.drawString("上移键:", 100, 80);
g.drawString("下移键:", 400, 80);
g.drawString("左移键:", 100, 180);
g.drawString("右移键:", 400, 180);
g.drawString("攻击键:", 100, 280);
g.drawString("名字:",400,280);//画出选项 String up = "向上键 VK_"+(char)key.MY_UP+" ";
String down = "向下键 VK_"+(char)key.MY_DOWN+" ";
String left = "向左键 VK_"+(char)key.MY_LEFT+" ";
String right = "向右键 VK_"+(char)key.MY_RIGHT+" ";
String attack = "攻击键 VK_" +(char)key.MY_ATTACK+" ";
System.out.println(key.MY_ATTACK); g.drawString("当前键:", 600, 150);//画出当前选择
if(key.MY_UP == 38) {
g.drawString("向上: VK_UP", 600, 200);
}
else {
g.drawString(up, 600, 200);
}
if(key.MY_DOWN == 40) {
g.drawString("向下: VK_DOWN", 800, 200);
}
else {
g.drawString(down, 800, 200);
}
if(key.MY_LEFT == 37) {
g.drawString("向左: VK_LEFT",600,250);
}
else {
g.drawString(left, 600, 250);
}
if(key.MY_RIGHT == 39) {
g.drawString("向右: VK_RIGHT",800,250);
}
else {
g.drawString(right, 800, 250);
}
if(key.MY_ATTACK == 32) {
g.drawString("攻击: 空格",700,300);
}
else {
g.drawString(attack, 700, 300);
}
} // 判断按键是否重复
private boolean judge() {
String a = (String) UP.getSelectedItem();
String b = (String) RIGHT.getSelectedItem();
String c = (String) DOWN.getSelectedItem();
String d = (String) LEFT.getSelectedItem();
String e = (String) ATTACK.getSelectedItem();
if (a.equals(b) || a.equals(c) || a.equals(d) || a.equals(e)) {
return true;
} else if (b.equals(c) || b.equals(d) || b.equals(e)) {
return true;
} else if (c.equals(d) || c.equals(e) || c.equals(e)) {
return true;
}
return false;
} private void addChoose(JComboBox<String> now) {
for (int i = 0; i <= 9; i++) {
now.addItem(String.valueOf(i));// 添加 1 - 9
}
for (int i = 65; i <= 90; i++) {
now.addItem((char) (i) + " "); // 添加'A' ~ 'Z'
}
} // 读入本地文件 如果文件不存在 就创建一个新的key
private boolean readData() {
File file = new File("key.txt");
if(!file.exists() || file.length() == 0) {
try {
file.createNewFile();
key = new Key();
saveData();
return true;
} catch (IOException e) {
e.printStackTrace();
}
} ObjectInputStream ois = null;// 读入流
try {
FileInputStream fis = new FileInputStream("key.txt");
ois = new ObjectInputStream(fis);
key = (Key) ois.readObject(); // 读入 } catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (ois != null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
this.saveData(); // 保存
}
return true;
} private boolean saveData() {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("key.txt"));
oos.writeObject(key);
oos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
} @Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == music_button) {
if(tot++ % 2 == 0) {
music.close();
}else {
music.open();
}
}else if(e.getSource() == ENSURE) {
if (judge()) {
JOptionPane.showMessageDialog(jframe, "按键重复!", "警告", 0);
} else if (txt.getText().equals("") || txt.getText().equals("用户名")) {
JOptionPane.showMessageDialog(jframe, "请输入用户名", "警告", 0);
} else {// 只有一个按键
String up = (String) UP.getSelectedItem();// 获取向上
if (!up.equals("VK_UP")) { // 不是默认值
char a = up.charAt(0); // 获取选中的
key.MY_UP = (int) a; // 用int保存
} else {
key.MY_UP = 38;
}
String down = (String) DOWN.getSelectedItem();// 获取向下的操作
if (!down.equals("VK_DOWN")) {
char a = down.charAt(0);
key.MY_DOWN = (int) a;
} else {
key.MY_DOWN = 40;
}
String left = (String) LEFT.getSelectedItem();
if (!left.equals("VK_LEFT")) {
char a = left.charAt(0);
key.MY_LEFT = (int) a;
} else {
key.MY_LEFT = 37;
}
String right = (String) RIGHT.getSelectedItem();
if (!right.equals("VK_RIGHT")) {
char a = right.charAt(0);
key.MY_RIGHT = (int) a;
} else {
key.MY_RIGHT = 39;
}
String attack = (String) ATTACK.getSelectedItem();
if (!attack.equals("VK_SPACE")) {
char a = attack.charAt(0);
key.MY_ATTACK = (int) a;
System.out.println((char)a + " " + attack);
} else {
key.MY_ATTACK = 32;
}
String name = txt.getText();
System.out.println(name); saveData();// 存入文件
music.close();
new Choose(name,key); // 进入关卡选择
jframe.dispose();
} } } }

坦克大战--Java类型 ---- (2)按键设置和用户名的输入的更多相关文章

  1. 坦克大战--Java类型

    写在前面       Java编译器下载教程(真的良心):https://blog.csdn.net/Haidaiya/article/details/81230636 本项目为本人独自制作,请各位尊 ...

  2. 坦克大战--Java类型 ---- (3)实现socket通信

    一.实现思路 使用socket通信的一些方法来实现socket通信,客户端和服务端两边需要约定好通信的接口Port(尽量选高的),客户端需要服务端的IP地址,以实现数据交流. 同时,客户端和服务端需要 ...

  3. 坦克大战--Java类型 ---- (1)音乐播放

    实现原理 我用接口java.applet.AudioClip实现音乐播放,那么我们需要了解这个接口的情况. 我们主要使用其中的三个方法: (1)void loop(); //循环播放(2)void p ...

  4. 坦克大战java版

    吃了可以加血的血块类 import java.awt.*; public class Blood { //血块移动的路径 int[][] pos = { {450,250},{450,252},{45 ...

  5. java制作简单的坦克大战

    坦克大战是我们小时候玩红白机时代的经典游戏,看到有不少小伙伴都使用各种语言实现了一下,手痒痒,也使用java做的一个比较简单的坦克大战,主要面向于学过Java的人群,与学了一段时间的人,有利于面向对象 ...

  6. Java坦克大战 (七) 之图片版

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  7. Java坦克大战 (六) 之增加可玩性

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  8. Java坦克大战 (五) 之产生敌方坦克和爆炸效果

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

  9. Java坦克大战 (四) 之子弹的产生

    本文来自:小易博客专栏.转载请注明出处:http://blog.csdn.net/oldinaction 在此小易将坦克大战这个项目分为几个版本,以此对J2SE的知识进行回顾和总结,希望这样也能给刚学 ...

随机推荐

  1. webpack4(4.41.2) 打包出现 TypeError this.getResolve is not a function

    报错问题: webpack 打包出现 TypeError: this.getResolve is not a function 环境: nodejs 12.13.0 npm 6.12.0 webpac ...

  2. 学习andriod开发之 异步加载图片(二)--- 使用其他进度条

    大家好 我是akira上一节 我们讲到使用AsyncTask 这个类进行异步的下载 主要是涉及到一些图片的更新 这次我们继续上一个demo的改进 . 不知道你是否发现一个问题 上一节我们遗留了两个bu ...

  3. 进程间通信之管道--pipe和fifo使用

    匿名管道pipe 函数原型: #include <unistd.h> int pipe(int fildes[2]); 参数说明 fildes是我们传入的数组,也是一个传出参数.filde ...

  4. hive连接hbase

    使用hive连接hbase 前提说明:一个hive表指向一个hbase表,一对一,不能多对一 建立外部表 CREATE EXTERNAL TABLE test_hbase( key string, m ...

  5. 遍历 ArrayList与Map集合

    import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 遍历 ArrayList * @ ...

  6. Leetcode题目20.有效的括号(简单)

    题目描述: 给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效. 有效字符串需满足: 左括号必须用相同类型的右括号闭合.左括号必须以正确的顺序闭合.注意空字符 ...

  7. STL -- heap结构及算法

    STL -- heap结构及算法 heap(隐式表述,implicit representation) 1. heap概述 : vector + heap算法 heap并不归属于STL容器组件,它是个 ...

  8. jxbrowser java代码直接调用js代码

    https://blog.csdn.net/shuaizai88/article/details/73743669 final Browser browser = new Browser(); Bro ...

  9. Cortex-M3 双堆栈指针(MSP&PSP)

    [双堆栈指针(MSP&PSP)] Cortex-M3内核中有两个堆栈指针(MSP & PSP),但任何时刻只能使用到其中一个. 复位后处于线程模式特权级,默认使用MSP. 通过SP访问 ...

  10. pandas之DataFrame创建、索引、切片等基础操作

    知识点 Series只有行索引,而DataFrame对象既有行索引,也有列索引 行索引,表明不同行,横向索引,叫index,0轴,axis=0 列索引,表明不同列,纵向索引,叫columns,1轴,a ...