Отображение достижений
Идеи производства
Шаг 1. Откройте для себя класс (объект)
人物-小丑: Buffoon
子弹-帽子:Missile
墙体:Wall
爆炸物:Explode
Шаг 2. Откройте для себя атрибуты
小丑:宽和高,位置(x,y),移动速度
帽子:宽和高,位置(x,y),移动速度
墙体:宽和高,位置(x,y)
爆炸物:宽和高,位置(x,y)
Шаг 3. Откройте для себя метод
小丑:移动、攻击、人物撞边界
子弹:移动、子弹撞墙、子弹撞边界
爆炸物:消失
Анализ сложности
Как создать форму
public class GameClient extends Frame
Реализуйте форму Java, наследуя класс Frame
public class Frame extends Window implements MenuContainer
Класс Frame наследует класс Window и интерфейс MenuContainer.
Как загрузить картинки в форму
Шаг 1. Создайте общий инструментальный класс CommonUtils, создайте новый метод getImage для преобразования ресурсов изображения в объекты Java.
public class CommonUtils {
/**
* 读取图片资源, 转变为Java对象 Image
* @param imgPath 图片路径
* @return Image对象
*/
public static Image getImage(String imgPath) {
ImageIcon imageIcon = new ImageIcon(imgPath);
return imageIcon.getImage();
}
}
Шаг 2. Вызовите метод getImage, чтобы добавить изображение объекта
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");
Шаг 3. Перепишите метод рисования Framed, чтобы реализовать форму для загрузки изображений.
@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);
Метод drawImage класса Graphics должен предоставить параметр класса Image, параметр x формы, параметр y формы, ширину класса Image, длину класса Image и наблюдателя (объект, который будет уведомлен при преобразовании большего количества изображений)
Реализация движения объекта
Направление целевой карты обычно определяется правилом «вверх на север, ниже на юг, слева запад и правый восток». Восемь направлений движения обычно относятся к северу, северо-востоку, востоку, юго-востоку, югу, юго-западу, западу и северо-западу. Поэтому, определяя направление движения, используйте верхний, левый, нижний, правый, верхний правый, нижний правый, верхний левый и нижний левый угол, чтобы указать
小丑:移动 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;
Реализация закрытия формы
public void start() {
//窗体添加侦听方法
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
super.windowClosing(e);
//退出游戏
System.exit(0);
}
});
Класс WindowAdapter :
1. Абстрактный класс адаптера, который получает события окна. Методы в этом классе пусты. Цель этого класса - облегчить создание объектов-слушателей.
2. Расширьте этот класс, чтобы создать слушателей WindowEvent и переопределить метод для требуемых событий. (Если вы хотите реализовать интерфейс WindowListener, вы должны определить все методы в интерфейсе. Этот абстрактный класс определяет все методы как нулевые, поэтому вам нужно только определить методы для событий, которые вас интересуют.
3. Используйте расширенные классы для создания объектов-слушателей , А затем используйте метод addWindowListener окна, чтобы зарегистрировать слушателя в окне. Когда состояние окна изменяется путем открытия, закрытия, активации или деактивации, создания значков или де-значков, будет вызван соответствующий метод в объекте прослушивателя , И передайте WindowEvent методу.
WindowAdapter listener
Реализация триггера ключевого события
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());
}
});
Ключевые моменты нажатия клавиш
Точка 1: 'new KeyAdapter ()' Создайте новый прослушиватель ключевого события и зарегистрируйте его в основной форме с помощью addKeyListener ();
Точка 2: Перепишите методы KeyAdapter, а именно KeyTyped (тип), KeyPresdded (нажмите Далее), KeyReleased (выпущен). Здесь мы слушаем только событие KeyPressed и переписываем этот метод, чтобы реализовать изменение состояния направления персонажа;
третий пункт: KeyEvent e.getKeyCode возвращает значение ключа, соответствующее нажатой клавише, обратитесь к свойству значения ключа KeyEvent. Онлайн-API Java 8
Создать объект методом Buffoon.move ()
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;
}
Каждый раз, когда отслеживается ключевое событие, вызывается метод move для реализации движения объекта-шутовца.
Принцип движения объекта
Движущееся изображение объекта также называется анимацией. Оно отображает серию непрерывных анимированных изображений кадр за кадром на экране, а затем отображает следующий кадр с коротким интервалом. Это повторяется, используя «постоянство зрения» человеческого глаза. «Явление субъективно ощущается так, как будто объекты на картинке движутся.
FPS (Frames Per Second) - это количество кадров в секунду. Один кадр представляет собой статический портрет, а скорость воспроизведения видео составляет 24 кадра в секунду. Чем больше кадров, тем плавнее отображается движение. В общем, минимум, необходимый для предотвращения резких движений, составляет 30 кадров в секунду. Энциклопедия FPS Baidu
Анимированный движущийся портер-нить
Что такое поток?
Поток - это наименьший элемент, который операционная система может выполнять по расписанию. Он включен в процесс и является фактически действующей единицей в процессе. Поток относится к одному последовательному потоку управления в процессе.Множественные потоки могут быть параллельны в процессе, и каждый поток выполняет разные задачи параллельно.
/**
* 定义一个重新绘制画面的线程,相当于招一个工人专门去从事这项工作
*/
public class RePaintThread implements Runnable{
@Override
//线程操作的全都在run方法中
public void run() {
while (true){
//每50毫秒 执行一次
try {
Thread.sleep(20);
//重新绘制图像
gameClient.repaint();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Точка 1:
Открытый класс интерфейса Runnable RePaintThread реализует Runnable
При создании потока с объектом, который реализует интерфейс Runnable, запуск потока вызовет метод run объекта в независимо выполняющемся потоке.
Пункт второй: переопределить метод Run
Общий контракт метода run: он может выполнять любое желаемое действие.
Перекрасить изображение
gameClient.repaint ();
Ключевой момент 3: Thread.sleep - интервал времени между повторным выполнением потока 1. Используйте'While (
true) ', чтобы построить бесконечный цикл
2. Выполните repaint () в бесконечном цикле, чтобы перерисовать метод формы
3. Исключение прерывания потока (InterruptedException) является одним из проявлений прерывания текущего потока. Когда вы сталкиваетесь с этим исключением, если вы не знаете, как с ним справиться, вы должны выбросить его вверх.