'Java 미니게임 구현': 탱크 배틀(계속)
지난 블로그 게시물 "자바 미니 게임 구현": 탱크 전투에서는 탱크를 네 방향으로 이동하도록 제어하는 기능만 소개했습니다. 오늘은 이를 기반으로 계속해서 작은 기능을 하나씩 완성해 보겠습니다.
완료된 기능: 키보드 키에 따라 탱크를 8방향으로 이동하도록 제어
이 기능을 완료하려면 몇 가지 작업이 필요합니다
1. 키보드의 키 누름 상황은 키보드 누르기 및 떼기의 모니터링 이벤트를 다시 작성하는 것입니다
<code>采用4个boolean变量来记录,按下为true,抬起为false </code>
구체적인 구현 코드는 다음과 같습니다.
<code class="hljs java"> //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_L,b_U,b_R,b_D; //记录键盘的按键情况 public void keyMonitor(KeyEvent e){ int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向,即第二步要完成的内容,具体实现看博文下面 moveDirection(); } //键盘按键松下时,也要进行记录 public void keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=false; break; case KeyEvent.VK_UP: b_U=false; break; case KeyEvent.VK_RIGHT: b_R=false; break; case KeyEvent.VK_DOWN: b_D=false; break; } }</code>
2. 기록에 따르면 1
<code class="hljs dos">8个运行方向采用一个枚举类型来保存。即 private enum Direction{ L,LU,U,RU,R,RD,D,LD,STOP } //例如:如果键盘的左键和下键被按下,则运行方向dir=Direction.LD. //定义一个变量来表示坦克要运行的方向,初始状态为STOP private Direction dir = Direction.STOP; //根据键盘的按键情况来确定坦克的运行方向 private void moveDirection() {//L,LU,U,RU,R,RD,D,LD,STOP if(b_L&&!b_U&&!b_R&&!b_D){ dir = Direction.L; } else if(b_L&&b_U&&!b_R&&!b_D){ dir = Direction.LU; } else if(!b_L&&b_U&&!b_R&&!b_D){ dir = Direction.U; } else if(!b_L&&b_U&&b_R&&!b_D){ dir = Direction.RU; } else if(!b_L&&!b_U&&b_R&&!b_D){ dir = Direction.R; } else if(!b_L&&!b_U&&b_R&&b_D){ dir = Direction.RD; } else if(!b_L&&!b_U&&!b_R&&b_D){ dir = Direction.D; } else if(b_L&&!b_U&&!b_R&&b_D){ dir = Direction.LD; } else{//其它所有情况,都是不动 dir = Direction.STOP; } } </code>
버튼을 눌러 탱크의 주행 방향을 결정합니다. 3. 2의 이동 방향에 따라 특정 주행 속도를 결정합니다. 예를 들어 왼쪽 하단 방향으로 이동하면 탱크의 현재 위치(x,y) ->(x-XSPEED,y+YSPEED), 여기서 XSPEED 및 YSPEED는 x 및 y축의 실행 속도입니다.
<code class="hljs rust"> //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=XSPEED; private void move(){ if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } else if(dir==Direction.STOP){ //... nothing } }</code>
위 세 단계의 전체 코드는 다음과 같습니다.
<code class="hljs java"> public class Tank { //坦克所在的位置坐标 private int x; private int y; //定义两个常量,表示运动的速度 private static final int XSPEED = 5; private static final int YSPEED = 5; //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_L,b_U,b_R,b_D; //定义一个枚举类型来表示运行的方向 private enum Direction{ L,LU,U,RU,R,RD,D,LD,STOP } //定义一个变量来表示坦克要运行的方向,初始状态为STOP private Direction dir = Direction.STOP; public Tank(int x, int y) { super(); this.x = x; this.y = y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public void setY(int y) { this.y = y; } public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.RED); g.fillOval(x, y, 30, 30); g.setColor(c); move();//根据键盘按键的结果改变坦克所在的位置 } //记录键盘的按键情况 public void keyMonitor(KeyEvent e){ int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection(); } //键盘按键松下时,也要进行记录 public void keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key){ case KeyEvent.VK_LEFT: b_L=false; break; case KeyEvent.VK_UP: b_U=false; break; case KeyEvent.VK_RIGHT: b_R=false; break; case KeyEvent.VK_DOWN: b_D=false; break; } } //根据键盘的按键情况来确定坦克的运行方向 private void moveDirection() {//L,LU,U,RU,R,RD,D,LD,STOP if(b_L&&!b_U&&!b_R&&!b_D){ dir = Direction.L; } else if(b_L&&b_U&&!b_R&&!b_D){ dir = Direction.LU; } else if(!b_L&&b_U&&!b_R&&!b_D){ dir = Direction.U; } else if(!b_L&&b_U&&b_R&&!b_D){ dir = Direction.RU; } else if(!b_L&&!b_U&&b_R&&!b_D){ dir = Direction.R; } else if(!b_L&&!b_U&&b_R&&b_D){ dir = Direction.RD; } else if(!b_L&&!b_U&&!b_R&&b_D){ dir = Direction.D; } else if(b_L&&!b_U&&!b_R&&b_D){ dir = Direction.LD; } else{//其它所有情况,都是不动 dir = Direction.STOP; } } //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=XSPEED; private void move(){ if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } else if(dir==Direction.STOP){ //... nothing } } }</code>
TarkClient.java 파일의 주요 수정 사항은 버튼 리프트 방법을 다시 작성하는 것입니다.
<code class="hljs java"> private class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { tk.keyMonitor(e); } @Override public void keyReleased(KeyEvent e) { tk.keyReleased(e); } }</code>
이상으로 8방향 탱크 제어가 완료되었습니다.
완성된 기능: 탱크가 총알을 쏠 수 있습니다
탱크 전투이기 때문에 총알을 쏠 수 있어야겠죠?
먼저 Bullet 클래스를 만듭니다. Bullet 클래스에는 위치 및 방향 속성은 물론 그리기 메서드와 이동 메서드도 있어야 합니다.
코드는 다음과 같습니다.
<code class="hljs java"> public class Missile { //定义两个常量,表示运动的速度 private static final int XSPEED = 20; private static final int YSPEED = 20; //子弹所在的位置 private int x; private int y; //子弹的运行方向 private Direction dir; public Missile(int x, int y, Direction dir) { this.x = x; this.y = y; this.dir = dir; } public void draw(Graphics g){ Color c = g.getColor(); g.setColor(Color.YELLOW); g.fillOval(x, y, 5, 5); g.setColor(c); move(); } private void move() { if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } } } </code>
그럼 인터페이스에 제어되지 않는 총알을 그려서 테스트해 보겠습니다.
TankClient 클래스에는 Missile이 있습니다. 그런 다음 페인트에서 Missile의 그리기를 호출하여 그립니다.
<code class="hljs java"> public class TankClient extends Frame{ //....无关代码没有显示 private Missile ms =new Missile(50,50,Direction.D);//一个子弹对象 @Override public void paint(Graphics g) { //直接调用坦克至圣的draw方法 tk.draw(g); if(ms!=null){ ms.draw(g); } } //....无关代码没有显示 }</code>
이제 Ctrl 키를 누르면 탱크에서 총알이 발사된다는 사실을 깨달아야 합니다. 탱크는 총알을 발사하기 때문에 탱크 클래스에는 fire()라는 총알을 발사하는 메서드가 있어야 하며 반환 값은 총알 개체입니다. 총알 개체는 탱크의 현재 위치와 방향으로 초기화됩니다.
<code class="hljs cs"> public Missile fire(){ Missile ms = new Missile(x,y,dir); return ms; } </code>
Ctrl 키를 눌렀을 때 총알을 발사하고 싶습니다.
그래서 탱크 클래스의 keyPressed 메소드에 키 값이 ctrl인 경우를 추가합니다. Fire()에서 반환된 Missile 개체는 TankClient 클래스의 Missile 참조를 초기화하는 데 사용해야 하기 때문입니다. 따라서 Tank 클래스에서 TankClient의 Missile 참조에 액세스하려면 TankClient에 대한 참조를 보유해야 합니다.
<code class="hljs cs"> private TankClient tc; public Tank(int x, int y) { this.x = x; this.y = y; } public Tank(int x, int y, TankClient tc) { this(x,y); this.tc = tc; } //记录键盘的按键情况 public void keyPressed(KeyEvent e){ int key=e.getKeyCode(); //System.out.println(key); switch(key){ case 17: //按下Ctrl键时的处理情况,tc是一个TankClient对象,里面有一个子弹的引用 tc.setMs(fire()); break; case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection();
TankClient.java 클래스의 코드는 다음과 같습니다.
<code class="hljs java"> public class TankClient extends Frame{ private final static int GAME_WIDTH=600; private final static int GAME_HEIGHT=600; private Tank tk=new Tank(50,50,this);//将this穿进去初始化TankClient private Missile ms ;//持有一个Missile的引用 public Missile getMs() { return ms; } public void setMs(Missile ms) { this.ms = ms; } private Image offScreenImage = null; public static void main(String[] args) { new TankClient().launchFrame(); } @Override public void update(Graphics g) { if (offScreenImage == null) { offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT); } Graphics goffScreen = offScreenImage.getGraphics();// 重新定义一个画虚拟桌布的画笔// Color c = goffScreen.getColor(); goffScreen.setColor(Color.darkGray); goffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); goffScreen.setColor(c); paint(goffScreen); g.drawImage(offScreenImage, 0, 0, null); } @Override public void paint(Graphics g) { //直接调用坦克至圣的draw方法 tk.draw(g); if(ms!=null){ ms.draw(g); } } public void launchFrame(){ this.setTitle("坦克大战"); this.setLocation(300, 400); this.setSize(GAME_WIDTH, GAME_HEIGHT); this.setBackground(Color.GRAY); //为关闭窗口添加响应 this.addWindowListener(new WindowAdapter(){ @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); //设置是否允许用户改变窗口的大小,这里限制下,不允许 this.setResizable(false); this.setVisible(true); new Thread(new MyRepaint()).start(); this.addKeyListener(new KeyMonitor()); } private class MyRepaint implements Runnable{ @Override public void run() { while(true){ //每50ms重画一次 repaint(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } } private class KeyMonitor extends KeyAdapter{ @Override public void keyPressed(KeyEvent e) { tk.keyPressed(e); } @Override public void keyReleased(KeyEvent e) { tk.keyReleased(e); } } } </code>
위에서는 Ctrl 키를 눌러 총알을 발사하는 탱크를 구현했습니다.
아직 끝나지 않았습니다! ! !
위 내용은 "Java 미니게임 구현": 탱크 배틀(계속) 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java의 난수 생성기 안내. 여기서는 예제를 통해 Java의 함수와 예제를 통해 두 가지 다른 생성기에 대해 설명합니다.

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

자바의 암스트롱 번호 안내 여기에서는 일부 코드와 함께 Java의 Armstrong 번호에 대한 소개를 논의합니다.

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다
