410 likes | 579 Views
실전 사운드 처리 프로그래밍. Lecture #11. 강의 목차. 게임 개발에서 실제로 활용할 수 있도록 사운드를 처리하는 방법을 알아본다. 사운드 처리 개요 (1). 모바일 게임의 주요 화면 중에 사운드 처리 화면 (c) 게임 타이틀 , (d) 메인 메뉴 , (f~h) 게임 화면 등. (a) 로고 (b) 공지사항 (c) 게임 타이틀 (d) 메인 메뉴.
E N D
실전 사운드 처리 프로그래밍 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) { try { mPlayer.stop( ); mPlayer = null; } catch(Exception e) { } } } Mobile Programming
게임 타이틀 화면 제작 (5) • 게임 타이틀 처리 코드 Mobile Programming
게임 타이틀 화면 제작 (6) • 게임 타이틀 처리 코드 Mobile Programming
게임 타이틀 화면 제작 (7) • 게임 타이틀 처리 코드 Mobile Programming
게임 타이틀 화면 제작 (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) 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
게임 타이틀 화면 제작 (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) • 메인 메뉴 처리 코드 Mobile Programming
메인 메뉴 화면 제작 (5) • 메인 메뉴 처리 코드 Mobile Programming
메인 메뉴 화면 제작 (6) • 메인 메뉴 처리 코드 Mobile Programming
메인 메뉴 화면 제작 (7) • 메인 메뉴 처리 코드 Mobile Programming
메인 메뉴 화면 제작 (8) 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) 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) 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) 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) 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) 115 public void keyPressed(intkeyCode) { 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) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (3) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (4) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (5) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (6) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (7) • 게임 시작 화면 처리 코드 Mobile Programming
게임 시작 화면 제작 (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 intshowCnt = 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( ); 021 public ReadyGoCanvas( ) { 022 width = getWidth( ); 023 height = getHeight( ); [예제 9-3] ReadyGoCanvas.java Mobile Programming
게임 시작 화면 제작 (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
게임 시작 화면 제작 (10) [예제 9-3] ReadyGoCanvas.java 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 } Mobile Programming
게임 시작 화면 제작 (11) [예제 9-3] ReadyGoCanvas.java 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 } Mobile Programming
게임 시작 화면 제작 (12) [예제 9-3] ReadyGoCanvas.java 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 inttempX = 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 } Mobile Programming
게임 시작 화면 제작 (13) [예제 9-3] ReadyGoCanvas.java • 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 } Mobile Programming
게임 시작 화면 제작 (14) [예제 9-3] ReadyGoCanvas.java • 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"); Mobile Programming
게임 시작 화면 제작 (15) [예제 9-3] ReadyGoCanvas.java 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 } Mobile Programming