실전 사운드 처리 프로그래밍 Lecture #11
강의 목차 게임 개발에서 실제로 활용할 수 있도록 사운드를 처리하는 방법을 알아본다. Mobile Programming
사운드 처리 개요 (1) 모바일 게임의 주요 화면 중에 사운드 처리 화면 (c) 게임 타이틀, (d) 메인 메뉴, (f~h) 게임 화면 등 (a) 로고 (b) 공지사항 (c) 게임 타이틀 (d) 메인 메뉴 (e) 게임 로딩 (f) 게임 시작 I (g) 게임 시작 II (h) 게임 시작 III Mobile Programming
게임 타이틀 화면 제작 (1) 타이틀 화면 만드는 과정 주요 기능과 리소스 사운드 처리 이미지 그리기 리소스 title.wav bg_img.png title1.png title2.png title3.png Mobile Programming
게임 타이틀 화면 제작 (2) 게임 타이틀 사운드 처리하기 ➊ 사운드 파일 생성 ➋ 사운드 관리자 생성 ➌ 사운드 재생 ➊ InputStream in = getClass().getResourceAsStream("/title.wav"); ➋ mPlayer = Manager.createPlayer(in, "audio/x-wav"); ➌ mPlayer.start( ); Mobile Programming
게임 타이틀 화면 제작 (3) 게임 타이틀 사운드 처리하기 사운드 파일 생성 public InputStream getResourceAsStream(String name) 사운드 관리자 생성 public static Player createPlayer(InputStream stream, String type) 사운드 파일의 MIME 타입 Mobile Programming
게임 타이틀 화면 제작 (4) 사운드 재생 및 종료 프로그램 사운드 재생 사운드 종료 try { Player p = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR); p.start( ); p.stop( ); } catch(MediaException me) { } } catch(IOException ioe) { } 사운드 종료 final public void soundStop( ) { if(mPlayer != null) { mPlayer.stop( ); mPlayer = null; } catch(Exception e) { } } Mobile Programming
게임 타이틀 화면 제작 (5) 게임 타이틀 처리 코드 변수 선언 생성자 paint( ) 메소드 추가 & 수정 부분 /* 타이틀 이미지 */ private Image title1, title2, title3; /* 사운드 처리 */ private Player mPlayer; private boolean sound; 생성자 /* try ~ catch 문에 추가 */ title1 = Image.createImage“( /images/title/title1.png”); // 삼국지 title2 = Image.createImage“( /images/title/title2.png”); // 아이 title3 = Image.createImage“( /images/title/title3.png”); // 플러스 paint( ) 메소드 public void paint(Graphics g) { if(gameState == g_LOGO) { draw_logo(g); } else if(gameState == g_NOTICE) { draw_notice(g); } else if(gameState == g_TITLE) { if(!sound) soundPlay“( title”); draw_title(g); } Mobile Programming
게임 타이틀 화면 제작 (6) 게임 타이틀 처리 코드 draw_title( ) 추가 & 수정 부분 01 public void draw_title(Graphics g) { 02 g.drawImage(bg_img, 0, 0, Graphics.TOP | Graphics.LEFT); 03 g.drawImage(title1, 0, 0, Graphics.TOP | Graphics.LEFT); 04 g.drawImage(title2, getWidth()/2, title1.getHeight()+10, Graphics.TOP | Graphics.HCENTER); 05 g.drawImage(title3, getWidth()/2+50, title1.getHeight()+50, 06 } Mobile Programming
게임 타이틀 화면 제작 (7) 게임 타이틀 처리 코드 soundPaly( ) soundStop( ) 메소드 추가 부분 01 public void soundPlay(String name) { 02 soundStop(); 03 try { 04 InputStream in = getClass().getResourceAsStream“( /”+name+“.wav”); 05 mPlayer = Manager.createPlayer(in, “audio/x-wav”); 06 mPlayer.start(); 07 } catch(Exception e) { } 08 sound = true; 09 } soundStop( ) 01 final public void soundStop() { 02 if(mPlayer != null) { 03 try { 04 mPlayer.stop(); 05 mPlayer = null; 06 sound = false; 07 } catch(Exception e) { } 08 } Mobile Programming
[예제 9-1] TitleCanvas.java 게임 타이틀 화면 제작 (8) 01 import javax.microedition.lcdui.*; 02 import javax.microedition.media.*; 03 04 import java.io.*; 05 06 public class TitleCanvas extends Canvas implements Runnable { 07 private Thread thread; 08 private Image bg_img; 09 /* 타이틀 이미지 */ 10 private Image title1, title2, title3; 11 /* 사운드 처리 */ 12 private Player mPlayer; 13 private boolean sound; 14 15 public TitleCanvas( ) { 16 try { 17 bg_img = Image.createImage("/bg_img.png"); // 배경 18 title1 = Image.createImage("/title1.png"); // 삼국지 19 title2 = Image.createImage("/title2.png"); // 아이 20 title3 = Image.createImage("/title3.png"); // 플러스 21 } catch (IOException e) { 22 System.out.println("이미지 파일을 생성할 수 없습니다."); 23 } 24 thread = new Thread(this); 25 thread.start( ); // run( ) 호출 26 } [예제 9-1] TitleCanvas.java Mobile Programming
[예제 9-1] TitleCanvas.java 게임 타이틀 화면 제작 (9) 27 public void run( ) { 28 while(true) { 29 try { 30 Thread.sleep(200); 31 } catch(InterruptedException e) { 32 System.out.println(e); 33 } 34 repaint( ); // paint( ) 호출 35 } 36 } 37 public void paint(Graphics g) { 38 if(!sound) soundPlay("title"); 39 draw_title(g); 40 } 41 public void draw_title(Graphics g) { 42 g.setColor(255,255,255); // 흰색 43 g.fillRect(0, 0, getWidth( ), getHeight( )); // 전체 화면을 흰색으로 44 g.drawImage(bg_img,0, 0, Graphics.TOP | Graphics.LEFT); // 배경 45 g.drawImage(title1,0, 0, Graphics.TOP | Graphics.LEFT); 46 g.drawImage(title2, getWidth( )/2, title1.getHeight( )+ 10, Graphics.TOP | Graphics.HCENTER); 47 g.drawImage(title3, getWidth( )/2+50, title1.getHeight( )+50, Graphics.TOP | Graphics.HCENTER); 48 } [예제 9-1] TitleCanvas.java Mobile Programming
[예제 9-1] TitleCanvas.java 게임 타이틀 화면 제작 (10) 49 public void soundPlay(String name) { 50 soundStop( ); 51 try { 52 InputStream in = getClass( ).getResourceAsStream("/"+name+".wav"); 53 mPlayer = Manager.createPlayer(in, "audio/x-wav"); 54 mPlayer.start( ); 55 } catch(Exception e) { } 56 sound = true; 57 } 58 final public void soundStop( ) { 59 if(mPlayer != null) { 60 try { 61 mPlayer.stop( ); 62 mPlayer = null; 63 sound = false; 64 } catch(Exception e) { } 65 } 66 } 67 } [예제 9-1] TitleCanvas.java Mobile Programming
메인 메뉴 화면 제작 (1) 메인 메뉴 화면 구성 주요 기능과 리소스 이미지 그리기 <UP>, <Down> 키를 이용한 메뉴 항목 선택 클리핑 리소스 bg_img.png main/00.png main/01.png main/02.png menumov.wav Mobile Programming
메인 메뉴 화면 제작 (2) 메인 메뉴 화면에 클리핑 적용하기 사각형 모양의 특정 부분만 화면에 출력할 때 이용 setClip(int x, int y, int width, int height); Mobile Programming
메인 메뉴 화면 제작 (3) 메뉴 항목의 클리핑 적용 예 적용 결과 int tempH[] = {32, 30, 30, 32, 32, 34, 32}; ... for(byte i=0; i < tempH.length; i++) { if(menuSelect == i) { g.setClip(width/2-(menu_img2.getWidth() >> 1 ), tempY, menu_img2.getWidth(), tempH[i]); g.drawImage(menu_img2, width/2, height/2, Graphics.VCENTER | Graphics.HCENTER); 적용 결과 Mobile Programming
메인 메뉴 화면 제작 (4) 메인 메뉴 처리 코드 변수 선언 생성자 추가 & 수정 부분 /* 메뉴 처리 */ static final byte g_MENU = 4; static final byte g_LOADING = 5; private Image menu_img1, menu_img2, cursor; private byte menuSelect; private int width, height; 생성자 width = getWidth(); height = getHeight(); /* try ~ catch 문에 추가 */ menu_img1 = Image.createImage“( /images/menu/00.png”); menu_img2 = Image.createImage“( /images/menu/01.png”); cursor = Image.createImage“( /images/menu/02.png”); Mobile Programming
메인 메뉴 화면 제작 (5) 메인 메뉴 처리 코드 paint( ) 메소드 draw_title( ) 추가 & 수정 부분 public void paint(Graphics g) { if(gameState == g_LOGO) { draw_logo(g); } else if(gameState == g_NOTICE) { draw_notice(g); } else if(gameState == g_TITLE) { if(!sound) soundPlay“( title”); draw_title(g); } } else if(gameState == g_MENU) { soundStop(); draw_background_img(g); // 배경 화면 초기화 draw_menu(g); draw_title( ) if(isKeyPressed) { switch(getGameAction(keyCode)) { default: gameState = g_MENU; isKeyPressed = false; Mobile Programming
메인 메뉴 화면 제작 (6) 메인 메뉴 처리 코드 draw_menu() 메소드 추가 부분 01 public void draw_menu(Graphics g) { 02 int tempY = height/2- (menu_img2.getHeight()/2 ); 03 int tempH[] = {32, 30, 30, 32, 32, 34, 32}; 04 g.drawImage(menu_img1, width/2, height/2, Graphics.VCENTER | Graphics.HCENTER); 05 06 for(byte i=0; i < tempH.length; i++) { 07 if(menuSelect == i) { 08 g.setClip(width/2-(menu_img2.getWidth() >> 1), tempY, menu_img2.getWidth(), tempH[i]); 09 g.drawImage(menu_img2, width/2, height/2, Graphics.VCENTER | Graphics.HCENTER); 10 g.setClip(0, 0, width, height); 11 g.drawImage(cursor, width/2-(menu_img2.getWidth() >> 1),tempY-3, Graphics.TOP | Graphics.RIGHT); 12 } 13 tempY += tempH[i]; 14 } 15 if(isKeyPressed) { 16 switch(getGameAction(keyCode)) { 17 case UP: 18 menuSelect--; 19 if(menuSelect<0) menuSelect=6; 20 soundPlay“( menumov”); 21 break; Mobile Programming
draw_backgr ound_img() 메인 메뉴 화면 제작 (7) 메인 메뉴 처리 코드 메소드 추가 부분 draw_menu() 22 case DOWN: 23 menuSelect++; 24 if(menuSelect>6) menuSelect=0; 25 soundPlay“( menumov”); 26 break; 27 case FIRE: 28 if(menuSelect == 0) { // 게임 시작 29 gameState = g_LOADING; 30 logoCount = 0; 31 } 32 break; 33 } 34 } 35 isKeyPressed = false; 36 } 메소드 추가 부분 draw_backgr ound_img() public void draw_background_img(Graphics g) { g.drawImage(bg_img, 0, 0, Graphics.TOP | Graphics.LEFT); } Mobile Programming
메인 메뉴 화면 제작 (8) [예제 9-2] MenuCanvas.java 001 import javax.microedition.lcdui.*; 002 import javax.microedition.media.*; 003 004 import java.io.*; 005 006 public class MenuCanvas extends Canvas implements Runnable { 007 /* 로고 */ 008 private int logoCount; 009 private byte gameState; 010 private Thread thread; 011 private Image bg_img; 012 private Image loading_img; 013 /* 이벤트 처리 */ 014 private boolean isKeyPressed = false; 015 private int keyCode; 016 /* 사운드 처리 */ 017 private Player mPlayer; 018 private boolean sound; 019 /* 메뉴 처리 */ 020 static final byte g_MENU = 4; 021 static final byte g_LOADING = 5; 022 private Image menu_img1, menu_img2, cursor; 023 private byte menuSelect; 024 private int width, height; 025 [예제 9-2] MenuCanvas.java Mobile Programming
메인 메뉴 화면 제작 (9) [예제 9-2] MenuCanvas.java 026 public MenuCanvas( ) { 027 width = getWidth( ); 028 height = getHeight( ); 029 try { 030 bg_img = Image.createImage("/bg_img.png"); // 배경 031 loading_img = Image.createImage("/loading.png"); // 로딩 032 menu_img1 = Image.createImage("/00.png"); // 메뉴1 033 menu_img2 = Image.createImage("/01.png"); // 메뉴2 034 cursor = Image.createImage("/02.png"); // 메뉴 커서 035 } catch(IOException e) { 036 System.out.println("이미지 파일을 생성할 수 없습니다."); 037 } 038 gameState = g_MENU; 039 thread = new Thread(this); 040 thread.start( ); // run( ) 호출 041 } 042 public void run( ) { 043 while(true) { 044 try { 045 Thread.sleep(200); 046 } catch(InterruptedException e) { 047 System.out.println(e); 048 } 049 repaint( ); // paint( ) 호출 050 } 051 } [예제 9-2] MenuCanvas.java Mobile Programming
메인 메뉴 화면 제작 (10) [예제 9-2] MenuCanvas.java 052 public void paint(Graphics g) { 053 if(gameState == g_MENU) { 054 soundStop( ); 055 draw_background_img(g); // 배경 화면 초기화 056 draw_menu(g); 057 } else if(gameState == g_LOADING) { 058 draw_loading(g); 059 } 060 } 061 public void draw_menu(Graphics g) { 062 int tempY = height/2 - (menu_img2.getHeight( )/2 ); 063 int tempH[] = {32, 30, 30, 32, 32, 34, 32}; 064 g.drawImage(menu_img1, width/2, height/2, Graphics.VCENTER | Graphics.HCENTER); 065 066 for(byte i=0; i < tempH.length; i++) { 067 if(menuSelect == i) { 068 g.setClip(width/2 - (menu_img2.getWidth( ) >> 1 ), tempY, menu_img2.getWidth( ), tempH[i]); 069 g.drawImage(menu_img2, width/2, height/2, Graphics.VCENTER|Graphics.HCENTER); 070 g.setClip(0, 0, width, height); 071 g.drawImage(cursor, width/2 - (menu_img2.getWidth( ) >> 1), tempY-3, Graphics.TOP|Graphics.RIGHT); 072 } 073 tempY += tempH[i]; 074 } [예제 9-2] MenuCanvas.java Mobile Programming
메인 메뉴 화면 제작 (11) [예제 9-2] MenuCanvas.java 075 if(isKeyPressed) { 076 switch(getGameAction(keyCode)) { 077 case UP: 078 menuSelect--; 079 if(menuSelect<0) menuSelect=6; 080 soundPlay("menumov"); 081 break; 082 case DOWN: 083 menuSelect++; 084 if(menuSelect > 6) menuSelect=0; 085 soundPlay("menumov"); 086 break; 087 case FIRE : 088 if(menuSelect == 0) { // 게임 시작 089 gameState = g_LOADING; 090 logoCount = 0; 091 } 092 break; 093 } 094 } 095 isKeyPressed = false; 096 } [예제 9-2] MenuCanvas.java Mobile Programming
메인 메뉴 화면 제작 (12) [예제 9-2] MenuCanvas.java 097 public void draw_loading(Graphics g) { 098 g.setColor(0, 255, 0); 099 g.fillRect(0, 0, width, height); 100 g.drawImage(loading_img, width/2, height/2, Graphics.VCENTER|Graphics.HCENTER); 101 int x = width/2 - loading_img.getWidth( )/2; 102 int y = height/2 - loading_img.getHeight( )/2; 103 g.fillRect(x, y, loading_img.getWidth( ), loading_img.getHeight( )/2 - logoCount); 104 g.fillRect(x, height/2 + logoCount, loading_img.getWidth( ), loading_img.getHeight( )/2 - logoCount); 105 if(logoCount < 7) logoCount += 1; 106 else logoCount+=2; 107 if(logoCount >= 18) { 108 gameState = g_MENU; 109 logoCount = 0; 110 } 111 } 112 public void draw_background_img(Graphics g) { 113 g.drawImage(bg_img, 0, 0, Graphics.TOP | Graphics.LEFT); 114 } [예제 9-2] MenuCanvas.java Mobile Programming
메인 메뉴 화면 제작 (13) [예제 9-2] MenuCanvas.java 115 public void keyPressed(int keyCode) { 116 isKeyPressed = true; 117 this.keyCode = keyCode; 118 } 119 public void soundPlay(String name) { 120 soundStop( ); 121 try { 122 InputStream in = getClass( ).getResourceAsStream("/"+name+".wav"); 123 mPlayer = Manager.createPlayer(in, "audio/x-wav"); 124 mPlayer.start( ); 125 } catch (Exception e) { } 126 sound = true; 127 } 128 final public void soundStop( ) { 129 if(mPlayer != null) { 130 try { 131 mPlayer.stop( ); 132 mPlayer = null; 133 sound = false; 134 } catch(Exception e) { } 135 } 136 } 137 } [예제 9-2] MenuCanvas.java Mobile Programming
게임 시작 화면 제작 (1) 게임 시작 화면 만드는 과정 주요 기능과 리소스 이미지 그리기 효과음 재생 클리핑 리소스 readyGo.png bigNum/04.png smallNum/00.png smallNum/01.png smallNum/03.png back/00.png back/01.png back/02.png back/03.png back/04.png ready.wav go.wav Mobile Programming
게임 시작 화면 제작 (2) 게임 시작 화면 처리 코드 변수 선언 생성자 paint() 메소드 추가 & 수정 부분 /* 게임 시작 */ private int stage, life, score, hidden, hint; private int showCnt = 0; private int flow = 0; private Image readyGo_img; private Image BACK_IMG[] = null; private Image SMALLNUM_IMG[] = null; private Image BIGNUM_IMG[] = null; private Image ORIGINAL_IMG = null; static final byte g_GAME_RUN = 7; 생성자 /* try ~ catch 문에 추가 */ readyGo_img = Image.createImage“( /images/menu/readyGo.png”); paint() 메소드 ... } else if(gameState == g_READY_GO) { draw_back(g); draw_readyGo(g); } Mobile Programming
게임 시작 화면 제작 (3) 게임 시작 화면 처리 코드 draw_loading() 메 소드 추가 & 수정 부분 ... 09 if(logoCount == 1) { 11 commonGameInit(); 12 } 13 if(logoCount < 7) logoCount += 1; 14 else logoCount += 2; 15 if(logoCount >= 18) { 16 gameState = g_READY_GO; 17 logoCount = 0; 18 } 19 } Mobile Programming
게임 시작 화면 제작 (4) 게임 시작 화면 처리 코드 commonGameInit () 메소드 메소드 추가 부분 메소드 추가 부분 commonGameInit () 메소드 01 public void commonGameInit() { 02 hint = 3; 03 life = 3; 04 hidden = 4; 05 showCnt = 0; 06 stage = 1; 07 score = 0; 08 BACK_IMG = createImg“( back”, 8); 09 SMALLNUM_IMG = createImg“( smallNum”, 10); 10 BIGNUM_IMG = createImg“( bigNum”, 5); 11 ORIGINAL_IMG = createImg“( original”,“ stage”); 12 System.gc(); 13 logoCount = 2; 14 } Mobile Programming
게임 시작 화면 제작 (5) 게임 시작 화면 처리 코드 draw_readyGo() 메소드 메소드 추가 부분 메소드 추가 부분 draw_readyGo() 메소드 01 public void draw_readyGo(Graphics g) { 02 showCnt++; 03 if(showCnt < 5) { 04 if(flow == 0) { 05 soundPlay“( ready”); 06 flow = 1; 07 } 08 g.setClip(width/2-(readyGo_img.getWidth()/2), height/2-16,readyGo_img.getWidth(), readyGo_img.getHeight()/2); 09 g.drawImage(readyGo_img, width/2, height/2+16,Graphics.VCENTER | Graphics.HCENTER); 10 } 11 else if(showCnt < 10) { 12 if(flow == 1) { 13 soundPlay“( go”); 14 flow = 2; 15 } 16 g.setClip(width/2-(readyGo_img.getWidth()/2), height/2-16,readyGo_img.getWidth(), readyGo_img.getHeight()/2); 17 g.drawImage(readyGo_img, width/2, height/2-16,Graphics.VCENTER | Graphics.HCENTER); 18 } 19 else if(showCnt >= 10) { 20 gameState = g_GAME_RUN; 21 showCnt = 0; 22 } 23 g.setClip(0, 0, width, height); 24 } Mobile Programming
게임 시작 화면 제작 (6) 게임 시작 화면 처리 코드 draw_back() 메소드 메소드 추가 부분 메소드 추가 부분 draw_back() 메소드 01 public void draw_back(Graphics g) { 02 // 경계선( 상 하 ) 03 for(int i=0; i<width; i = BACK_IMG[4].getWidth()+i) { 04 g.drawImage(BACK_IMG[4], i, 44, Graphics.TOP | Graphics.LEFT); 05 g.drawImage(BACK_IMG[4], i, 244, Graphics.TOP | Graphics.LEFT); 06 } 07 // 경계선 가운데(가로) 08 for(int i=0; i< width; i = BACK_IMG[4].getWidth()+i) { 09 g.drawImage(BACK_IMG[4], i, 144, Graphics.TOP | Graphics.LEFT); 10 } 11 g.setColor(181, 181, 255); 12 for(byte i=0; i<= width/10; i++) g.fillRect((10*i), 0, 5, 44); 13 for(byte i=0; i<= width/10; i++) g.fillRect((10*i), 248, 5, 43); 14 g.setColor(222, 222, 255); 15 for(byte i=0; i<= width/10; i++) g.fillRect((10*i)+5, 0, 5, 44); 16 for(byte i=0; i<= width/10; i++) g.fillRect((10*i)+5, 248, 5, 43); 17 g.drawImage(BACK_IMG[0], 1, 0, Graphics.TOP | Graphics.LEFT); 18 // hidden 19 if(hidden >= 0) 20 g.drawImage(BIGNUM_IMG[hidden], width/2-1, 3,Graphics.TOP | Graphics.HCENTER); 21 g.drawImage(SMALLNUM_IMG[stage/10], 28, 22, Graphics.TOP | Graphics.LEFT); g.drawImage(SMALLNUM_IMG[stage%10], 44, 22, Graphics.TOP | Graphics.LEFT); 23 // score 24 int tempX = 164; String str = Integer.toString(score); 26 if(str.length() < 5 ) { 27 for(byte i=0; i< 5 - str.length(); i++) { Mobile Programming
게임 시작 화면 제작 (7) 게임 시작 화면 처리 코드 draw_back() 메소드 메소드 추가 부분 메소드 추가 부분 draw_back() 메소드 28 g.drawImage(SMALLNUM_IMG[0], tempX, 22, Graphics.TOP | Graphics.LEFT); 29 tempX += 14; 30 } 31 } 32 for(byte i=0; i< str.length(); i++) { 33 int a = Integer.parseInt(str.substring(i, i+1)); 34 g.drawImage(SMALLNUM_IMG[a], tempX, 22, Graphics.TOP | Graphics.LEFT); 35 tempX += 14; 36 } 37 // time 38 g.drawImage(BACK_IMG[1], 1, 244, Graphics.TOP | Graphics.LEFT); 39 // life 40 g.drawImage(BACK_IMG[2], 1, height-1, Graphics.BOTTOM | Graphics.LEFT); 41 g.drawImage(SMALLNUM_IMG[life], BACK_IMG[2].getWidth()+4, height-8, Graphics.BOTTOM | Graphics.LEFT); 42 // hint 43 g.drawImage(BACK_IMG[3], BACK_IMG[2].getWidth()+4+SMALLNUM_IMG[life].getWidth()+6, height-2, Graphics.BOTTOM | Graphics.LEFT); 44 g.drawImage(SMALLNUM_IMG[hint], BACK_IMG[2].getWidth()+4+SMALLNUM_IMG[life].getWidth()+6+BACK_IMG[3].getWidth()+8, height-8, Graphics.BOTTOM | Graphics.HCENTER); 45 // power 46 g.drawImage(BACK_IMG[6], width-(BACK_IMG[6].getWidth()/2), height-4, Graphics.BOTTOM | Graphics.LEFT); 47 // image 48 g.drawImage(ORIGINAL_IMG,0, 48, Graphics.TOP | Graphics.LEFT); 49 g.drawImage(ORIGINAL_IMG,0, 148, Graphics.TOP | Graphics.LEFT); 50 } Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (8) 001 import javax.microedition.lcdui.*; 002 import javax.microedition.media.*; 003 import java.io.*; 004 005 public class ReadyGoCanvas extends Canvas implements Runnable { 006 private byte gameState; 007 private Thread thread; 008 private Player mPlayer; 009 private boolean sound; 010 private int width, height; 011 /* Ready Go */ 012 private int stage, life, score, hidden, hint; 013 private int showCnt = 0; 014 private int flow = 0; 015 private Image readyGo_img; 016 private Image BACK_IMG[] = null; 017 private Image SMALLNUM_IMG[] = null; 018 private Image BIGNUM_IMG[] = null; 019 private Image ORIGINAL_IMG = null; 020 021 public ReadyGoCanvas( ) { 022 width = getWidth( ); 023 height = getHeight( ); [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (9) 024 try { 025 readyGo_img = Image.createImage("/readyGo.png"); 026 } catch (IOException e) { 027 System.out.println("이미지 파일을 생성할 수 없습니다."); 028 } 029 commonGameInit( ); 030 thread = new Thread(this); 031 thread.start( ); // run( ) 호출 032 } 033 public void run( ) { 034 while(true) { 035 try { Thread.sleep(200); 036 } catch(InterruptedException e) { 037 System.out.println(e); 038 } 039 repaint( ); // paint( ) 호출 040 } 041 } 042 public void paint(Graphics g) { 043 if(flow <= 2) { 044 draw_back(g); 045 draw_readyGo(g); 046 } 047 } [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (10) 048 public void commonGameInit( ) { 049 hint = 3; 050 life = 3; 051 hidden = 4; 052 showCnt = 0; 053 stage = 1; 054 score = 0; 055 BACK_IMG = createImg("back", 8); 056 SMALLNUM_IMG = createImg("smallNum", 10); 057 BIGNUM_IMG = createImg("bigNum", 5); 058 ORIGINAL_IMG = createImg("original", "stage"); 059 System.gc( ); 060 } 061 public void draw_readyGo(Graphics g) { 062 showCnt++; 063 if(showCnt < 5) { 064 if(flow == 0) { 065 soundPlay("ready"); 066 flow = 1; 067 } 068 g.setClip(width/2-(readyGo_img.getWidth( )/2), height/2-16, readyGo_img.getWidth( ), readyGo_img.getHeight( )/2); 069 g.drawImage(readyGo_img, width/2, height/2+16,Graphics.VCENTER|Graphics.HCENTER); 070 } [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (11) 071 else if(showCnt < 10) { 072 if(flow == 1) { 073 soundPlay("go"); 074 flow = 2; 075 } 076 g.setClip(width/2-(readyGo_img.getWidth( )/2), height/2-16, readyGo_img.getWidth( ), readyGo_img.getHeight( )/2); 077 g.drawImage(readyGo_img, width/2, height/2-16, Graphics.VCENTER|Graphics.HCENTER); 078 } 079 else if(showCnt >= 10) { 080 showCnt = 0; 081 flow = 3; 082 } 083 g.setClip(0,0,width, height); 084 } 085 public void draw_back(Graphics g) { 086 // 경계선(상하) 087 for(int i=0; i< width; i = BACK_IMG[4].getWidth( )+i) { 088 g.drawImage(BACK_IMG[4], i, 44, Graphics.TOP | Graphics.LEFT); 089 g.drawImage(BACK_IMG[4], i, 244,Graphics.TOP | Graphics.LEFT); 090 } 091 // 경계선 가운데(가로) 092 for(int i=0; i< width; i = BACK_IMG[4].getWidth( )+i) { 093 g.drawImage(BACK_IMG[4], i, 144, Graphics.TOP|Graphics.LEFT); 094 } [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (12) 095 g.setColor(181, 181, 255); 096 for(byte i=0; i<= width/10; i++) g.fillRect((10*i), 0, 5, 44); 097 for(byte i=0; i<= width/10; i++) g.fillRect((10*i), 248, 5, 43); 098 g.setColor(222, 222, 255); 099 100 for(byte i=0; i<= width/10; i++) g.fillRect((10*i)+5, 0, 5, 44); 101 for(byte i=0; i<= width/10; i++) g.fillRect((10*i)+5, 248, 5, 43); 102 g.drawImage(BACK_IMG[0], 1, 0, Graphics.TOP|Graphics.LEFT); 103 104 // hidden 105 if(hidden >= 0) 106 g.drawImage(BIGNUM_IMG[hidden], width/2-1, 3, Graphics.TOP|Graphics.HCENTER); 107 g.drawImage(SMALLNUM_IMG[stage/10], 28, 22, Graphics.TOP|Graphics.LEFT); 108 g.drawImage(SMALLNUM_IMG[stage%10], 44, 22, Graphics.TOP|Graphics.LEFT); 109 110 // score 111 int tempX = 164; 112 String str = Integer.toString(score); 113 if(str.length( ) < 5) { 114 for(byte i=0; i< 5 - str.length( ); i++) { 115 g.drawImage(SMALLNUM_IMG[0], tempX, 22, Graphics.TOP|Graphics.LEFT); 116 tempX += 14; 117 } 118 } [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (13) 119 for(byte i=0; i< str.length( ); i++) { 120 int a = Integer.parseInt(str.substring(i,i+1)); 121 g.drawImage(SMALLNUM_IMG[a], tempX, 22, Graphics.TOP|Graphics.LEFT); 122 tempX += 14; } // time 125 g.drawImage(BACK_IMG[1], 1, 244, Graphics.TOP|Graphics.LEFT); 126 // life 127 g.drawImage(BACK_IMG[2], 1, height-1, Graphics.BOTTOM | Graphics.LEFT); 128 g.drawImage(SMALLNUM_IMG[life], BACK_IMG[2].getWidth( )+4, height-8 , Graphics.BOTTOM|Graphics.LEFT); 129 // hint 130 g.drawImage(BACK_IMG[3], BACK_IMG[2].getWidth( )+ 4+SMALLNUM_IMG[life].getWidth( )+6, height-2, Graphics.BOTTOM|Graphics.LEFT); 131 g.drawImage(SMALLNUM_IMG[hint], BACK_IMG[2].getWidth( )+4+ SMALLNUM_IMG[life].getWidth( )+6+BACK_IMG[3].getWidth( )+8, height-8, Graphics.BOTTOM|Graphics.HCENTER); 132 // power 133 g.drawImage(BACK_IMG[6], width-(BACK_IMG[6].getWidth( )/2), height-4, Graphics.BOTTOM|Graphics.LEFT); 134 // image 135 g.drawImage(ORIGINAL_IMG,0, 48, Graphics.TOP|Graphics.LEFT); 136 g.drawImage(ORIGINAL_IMG,0, 148, Graphics.TOP|Graphics.LEFT); 137 } [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (14) 138 public void soundPlay(String name) { 139 soundStop( ); 140 try { 141 InputStream in = getClass( ).getResourceAsStream("/"+name+".wav"); 142 mPlayer = Manager.createPlayer(in, "audio/x-wav"); 143 mPlayer.start( ); 144 } catch(Exception e) { } 145 sound = true; 146 } 147 final public void soundStop( ) { 148 if(mPlayer != null) { 149 try { 150 mPlayer.stop( ); 151 mPlayer = null; 152 sound = false; 153 } catch(Exception e) { } 154 } } 156 public Image[] createImg(String add, int size) { 157 Image img[] = null; 158 try { 159 img = new Image[size]; 160 for(byte i=0; i<size; i++) 161 img[i] = Image.createImage("/images/"+add+"/0"+i+".png"); [예제 9-3] ReadyGoCanvas.java Mobile Programming
[예제 9-3] ReadyGoCanvas.java 게임 시작 화면 제작 (15) 162 } catch(Exception e) { 163 System.out.println("Exception:" + e + "("+add+")"); 164 } catch(OutOfMemoryError omError) { 165 System.out.println(add + "out" + Runtime.getRuntime( ).freeMemory( )); 166 } 167 return img; 168 } 169 public Image createImg(String add, String name) { 170 Image img = null; 171 try { 172 if(name.equals("stage")) 173 img = Image.createImage("/images/"+add+"/stage"+stage+".png"); 174 else 175 img = Image.createImage ("/images/"+add+"/"+name+".png"); 176 } catch(IOException e) { 177 System.out.println(add+ " createImg 이미지 없다."); 178 } catch (OutOfMemoryError omError) { 179 System.out.println(add+ " out "); 180 } 181 return img; 182 } 183 } [예제 9-3] ReadyGoCanvas.java Mobile Programming