JAVA 프로그래밍

문제

탑 뷰 맵에서 방향키를 이용하여 캐릭터가 상하좌우로 이동하는 문제입니다 이를 해결하는 다음 프로그램을 해석하세요 
 

알고리즘

 뷰 패널 
   키리스너에 방향키로 이동하는 캐릭터를 등록
   주기적으로 활성화되는 타이머 등록
      최신 정보 업데이트
      화면 출력

방향키로 이동하는 객체
   키를 누르면 상하좌우 이동방향 설정
   키를 해제하면 이동방향 해제
   이동 허용 범위내에서만 객체 이동

탑 뷰 캐릭터
   벽이 아니면 캐릭터 이동
   캐릭터와 전체 맵을 출력


  이미지: 길, 벽, 캐릭터

 

  탑 뷰 게임의 클래스 다이어그램

 

 
  탑 뷰 게임의 초기화 과정

 

  탑 뷰 게임에서 방향키 입력시 처리 과정

 

  탑 뷰 게임에서 주기적으로 화면 업데이트 과정

 
 

프로그램 코드

E001	// 이벤트 대기중
E002	// → 키 입력
E003	// 1초마다 타이머 활성화
E004	// → 키 해제
	 
	// 파일명 : ./Chapter14/TopViewGameMain.java
	import javax.swing.*;
	import move.TopViewObject;
	import move.ViewPanel;
	 
	public class TopViewGameMain
	{
1		public static void main( String[] args )
		{
			final String imagePath = "C:\\Users\\user\\Downloads\\JAVA-main\\src\\move\\image\\";
			// 미로 맵을 2차원 배열로 초기화
			int[][] map = { { 1,1,1,1,1,1,1 },
			                { 1,0,0,1,0,0,1 },
			                { 1,1,0,1,0,1,1 },
			                { 1,0,0,1,0,0,1 },
			                { 1,0,1,1,1,0,1 },
			                { 1,0,0,0,0,0,1 },
			                { 1,1,1,1,1,1,1 }
			              };
			 
			// 판을 틀에 끼우고 실행 준비 완료
2			ViewPanel panel =
3			                  new ViewPanel(
4			                                 new TopViewObject( map, 1, 1, imagePath ) );
			JFrame frame = new JFrame( "탑 뷰 맵" );
			frame.getContentPane().add( panel );
			frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
			frame.pack();
			frame.setVisible(true);
5		}
	}
		 
	// 파일명 : ./src/move/ViewPanel.java
	package move;
	 
	import java.awt.*;
	import java.awt.event.*;
	import javax.swing.*;
	 
	// 뷰 패널  
	public class ViewPanel extends JPanel
	{
		protected ObjectByKey character;
		protected Timer timer;
		 
V1b		public ViewPanel( ObjectByKey character ){
			// 키리스너에 방향키로 이동하는 캐릭터를 등록   
			this.character = character;
			addKeyListener( character );
			setFocusable( true );
			requestFocus();
			setPreferredSize( new Dimension( character.backgroundWidth(), character.backgroundHeight() ) );
	 
			// 주기적으로 활성화되는 타이머 등록 
			timer = new Timer( 100, new ActionListener() {
			                	@Override
V2b			                	public void actionPerformed( ActionEvent event ) {
V21			                		update();
V22			                		repaint();
V2e			                	}
			                });
			timer.start();
V1e		}
		 
		// 최신 정보 업데이트  
V3b		protected void update() {
V31			character.move();
V3e		}
		 
		// 화면 출력 
		@Override
V4b		public void paint( Graphics g ){
			super.paint( g );
V41			character.paint( g );
V4e		}
	}
 
 
	// 파일명 : ./src/move/TopViewObject.java
	package move;
	 
	import java.awt.*;
	import javax.swing.*;
	 
	// 탑 뷰 캐릭터 
	public class TopViewObject extends ObjectByKey
	{
		protected int[][] map;
		protected Image[] image;
		protected final int PATH = 0, WALL = 1, CHARACTER = 2;
		 
T1b		public TopViewObject( int[][] map, int x, int y, final String imagePath ) {
T11			super( imagePath+"character.png", x, y, 0, 0, map[0].length-1, map.length-1 );
			this.map = map;
			this.image = new Image[3];
			this.image[PATH     ] = new ImageIcon( imagePath + "path.png" ).getImage();
			this.image[WALL     ] = new ImageIcon( imagePath + "wall.png" ).getImage();
			this.image[CHARACTER] = new ImageIcon( imagePath + "character.png" ).getImage();
T1e		}
		 
		// 벽이 아니면 캐릭터 이동 
		@Override
T2b		public void move( int directionX, int directionY ) {
			if( map[y+directionY][x+directionX] != WALL )
T21				super.move( directionX, directionY );
T2e		}
	 
		// 캐릭터와 전체 맵을 출력 
		@Override
T3b		public void paint( Graphics g ){
			for( int y = 0; y <= map.length; y++ ){
				for( int x = 0; x <= map[0].length; x++ ){
					int index = WALL;
					if ( ( this.x == x ) && ( this.y == y ) )
						index = CHARACTER;
					else if ( ( minX <= x ) && ( x <= maxX ) && ( minY <= y ) && ( y <= maxY ) )
						index = map[y][x];
					g.drawImage( image[index], x*IMGSIZE, y*IMGSIZE, IMGSIZE, IMGSIZE, null );
				}
			}
T3e		}
		 
		@Override
		public int backgroundWidth(){
			return IMGSIZE * ( map[0].length );
		}
		@Override
		public int backgroundHeight(){
			return IMGSIZE * ( map.length );
		}
	}
 
 
	// 파일명 : ./src/move/ObjectByKey.java
	package move;
	 
	import java.awt.*;
	import java.awt.event.*;
	import javax.swing.*;
	 
	// 방향키로 이동하는 객체 
	public class ObjectByKey extends KeyAdapter
	{
		private Image image;
		protected int x, y, directionX, directionY;
		protected int minX, minY, maxX, maxY;
		public static final int LEFT = -1, RIGHT = 1, UP = -1, DOWN = 1, STOP = 0, IMGSIZE = 40;
	 
		// 초기화: 이미지, 현재 위치, 이동 허용 범위, 이동 방향을 설정
K1b		public ObjectByKey( String image, int x, int y, int minX, int minY, int maxX, int maxY ) {
			this.image = new ImageIcon( image ).getImage();
			this.x = x;
			this.y = y;
			this.minX = minX;
			this.minY = minY;
			this.maxX = maxX;
			this.maxY = maxY;
			this.directionX = STOP;
			this.directionY = STOP;
K1e		}
	 
		// 키를 누르면 상하좌우 이동방향 설정 
		@Override
K2b		public void keyPressed( KeyEvent event ) {
			switch( event.getKeyCode() ) {
			case KeyEvent.VK_ESCAPE:
				System.exit(0);
				break;
			case KeyEvent.VK_LEFT: case 'A': case 'a':
				directionX = LEFT;
				break;
			case KeyEvent.VK_RIGHT: case 'D': case 'd':
K21				directionX = RIGHT;
				break;
			case KeyEvent.VK_UP: case 'W': case 'w':
				directionY = UP;
				break;
			case KeyEvent.VK_DOWN: case 'S': case 's':
K22				directionY = DOWN;
				break;
			}
K2e		}
		 
		// 키를 해제하면 이동방향 해제   
		@Override
K3b		public void keyReleased( KeyEvent event ) {
			switch( event.getKeyCode() ) {
			case KeyEvent.VK_LEFT: case 'A': case 'a':
			case KeyEvent.VK_RIGHT: case 'D': case 'd':
K31				directionX = STOP;
				break;
			case KeyEvent.VK_UP: case 'W': case 'w':
			case KeyEvent.VK_DOWN: case 'S': case 's':
				directionY = STOP;
				break;
			}
K3e		}
		 
		// 이동 허용 범위내에서만 객체 이동 
K4b		public void move() {
K41			move( directionX, directionY );
K4e		}
K5b		public void move( int directionX, int directionY ) {
			this.x += directionX;
			this.y += directionY;
			this.x = ( this.x <= minX ) ? minX : this.x;
			this.y = ( this.y <= minY ) ? minY : this.y;
			this.x = ( this.x >= maxX ) ? maxX : this.x;
			this.y = ( this.y >= maxY ) ? maxY : this.y;
K5e		}
	 
		// 현재 위치에 객체를 출력
K6b		public void paint( Graphics g ) {
			g.drawImage( image, x, y, IMGSIZE, IMGSIZE, null );
K6e		}
			 
		public int directionX() {
			return directionX;
		}
	 
		public int directionY() {
			return directionY;
		}
		 
		public int backgroundWidth(){
			return maxX;
		}
		 
		public int backgroundHeight(){
			return maxY;
		}
	}

실행 순서

 
 					※ 실행순서 및 메모리상태는 A키(이전) 및 D키(다음)를 눌러도 확인할 수 있습니다