/*********************************************** * 水面の表現 * 2000/10/16      33_kaki *********************************************/ import java.applet.*; import java.awt.*; import java.awt.image.*; import java.io.*; import java.net.*; import java.util.*; public class Applet1 extends Applet implements Runnable { Thread t; //時間 int time = 0; //サインコサイン用(1周期==4096) int time_count = 0; //シーンの場合分けに使う int loading_time = 0; //ローディング用 float scal = 1.1f; //拡大縮小時の倍率 final int HEIGHT = 200;//画面の幅 final int WIDTH = 200; int pbuf[] = new int[WIDTH * HEIGHT]; //バックバッファ配列 int texbuf[] = new int[200 * 200]; //テクスチャ配列 int texbuf2[] = new int[300 * 300]; int texbuf3[] = new int[200 * 200]; int texbuf4[] = new int[200 * 200]; //int texbuf5[] = new int[200 * 200]; //欠番 int texbuf6[] = new int[200 * 200]; //int titlebuf[] = new int[200 * 50]; Image pimage; //バックバッファイメージ Image teximage; //テクスチャイメージ Image teximage2; Image teximage3; Image teximage4; //Image teximage5; //欠番 Image teximage6; Image loadimage; //ロード画面用 Graphics loadg; Color load_color; //AudioClip ac;//音楽読みこみ用 int cos_table[] = new int[4096]; //サインコサインテーブル int sin_table[] = new int[4096]; int state; //処理を場合分けする final int STATE_INIT = 0; final int STATE_LOADING = 1; final int STATE_LOADED = 2; final int STATE_PREPARING = 3; final int STATE_EXECUTE = 4; int loading_ver_x[] = new int[3];//ローディング時に使うポリゴンの頂点座標 int loading_ver_y[] = new int[3]; MediaTracker Tracker = new MediaTracker(this);//メディアトラッカー int gameCtr; int depthTbl[][][] = new int[2][200][200]; //水深テーブル int flip1,flip2; //フレームレート表示に使う static float fps = 0; static int count = 59; static long time2 = System.currentTimeMillis(); /************************************************** *       汎用処理 * FireWorksさんのソースより拝借 *************************************************/ /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ //----------------------------- // イメージの読みこみ //----------------------------- private Image LoadImage(String imgName, int cur, int total, boolean wait) { Image tmpImg; tmpImg = getImage(this.getDocumentBase(), imgName); Tracker.addImage(tmpImg,cur); //ステータス欄を更新 getAppletContext().showStatus("Loading image ("+cur+"/" + total + ")"); //待つ if (wait) { try { Tracker.waitForAll(); } catch (InterruptedException e) {} Tracker = null; } //ステータス欄を更新 getAppletContext().showStatus(""); return tmpImg; } //----------------------------------------- //  イメージから配列を生成する //----------------------------------------- private void ImageToArray(int dest[], Image img) { int w = img.getWidth(this); int h = img.getHeight(this); PixelGrabber pg; pg = new PixelGrabber(img, 0,0,w,h, dest, 0, w); try{ pg.grabPixels(); } catch( InterruptedException e) { System.out.println(e); } } //--------------------------------------- //   配列からイメージを作る //---------------------------------------- private Image ArrayToImage(int src[], int w, int h) { return createImage( new MemoryImageSource(w,h, src, 0, w)); } //------------------------------------ // 配列の中身を描画する //------------------------------------ private void DrawArray(Graphics g, int src[], int x0, int y0, int w, int h) { g.drawImage(ArrayToImage(src,w,h), x0,y0,this); } //------------------------------- // 色を50%の暗さにする //------------------------------- private int halfColor(int a) { return ( ((a>>1) & 0x007f7f7f) | 0xff000000) ; } //------------------------------ // 色を暗くする //------------------------------ private int darkColor(int a) { int R,G,B; R = ((a & 0x00ff0000) >> 16)* (sin_table[(time) & 4095] + 65536) >> 17; G = ((a & 0x0000ff00) >> 8)* (sin_table[(time)&4095] + 65536) >> 17; B = (a & 0x000000ff) * (cos_table[time&4095] + 65536) >> 17; return(0xff000000 | (R << 16) | (G << 8) | B); } //----------------- // ネガポジ反転 //---------------- private int invertColor(int a) { int R,G,B; R = 255 - ((a & 0x00ff0000) >> 16); G = 255 - ((a & 0x0000ff00) >> 8); B = 255 - (a & 0x000000ff); return(0xff000000 | (R << 16) | (G << 8) | B); } //--------------------------------------- // 色の加算 //--------------------------------------- private int addColor(int a,int b) { int mask1 = 0x00fefefe; int mask2 = 0x01010100; int c,d; c = d = (a & mask1) + (b & mask1); c &= mask2; //桁上がり検出マスク c -= c >> 8; //桁上がりをしたところは、0xffになる return ( c | d | 0xff000000); } //------------------------ //     色の除外 //----------------------- private int excludeColor(int a,int b) { int R,G,B; R = Math.abs((((a & 0x00ff0000) >> 16))- ((((b & 0x00ff0000) >> 16)))); G = Math.abs((((a & 0x0000ff00) >> 8 )) - ((((b & 0x0000ff00) >> 8 )))); B = Math.abs((((a & 0x000000ff) )) - ((((b & 0x000000ff) )))); return 0xff000000 | (R<<16) | (G<<8) | B; } //------------------------------------ // 半透明 //------------------------------------ private int midColor(int a,int b) { return (((a>>1) & 0x007f7f7f) + ((b>>1) & 0x007f7f7f)) | 0xff000000; } //---------------------------- // 半透明(256段階ブレンド) //---------------------------- private int blendColor(int a,int b,int rate_a) { int R,G,B; R = (((a & 0x00ff0000) >> 16) * rate_a) + (((b & 0x00ff0000) >> 16) * (255-rate_a)) >> 8; G = (((a & 0x0000ff00) >> 8 ) * rate_a) + (((b & 0x0000ff00) >> 8 ) * (255-rate_a)) >> 8; B = (((a & 0x000000ff) ) * rate_a) + (((b & 0x000000ff) ) * (255-rate_a)) >> 8; return 0xff000000 | (R<<16) | (G<<8) | B; } //------------------------ // フレームレート表示 //------------------------ public void FrameRate(Graphics g) { //FPS計測 if (++count == 60){ fps = 1000 / (float)((System.currentTimeMillis() - time2) / 60); time2 = System.currentTimeMillis(); count = 0; } g.setColor(Color.blue); g.drawString("FPS " + fps,0,16); } /*************************************************** * ここから、アプレットの処理 * **************************************************/ /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ //------------------------------------- // 初期化処理 //------------------------------------- public void init() { state = STATE_INIT; //スレッドを開始する t = new Thread(this); t.start(); } //----------------------------------- //   スレッドラン //----------------------------------- public void run() { try{ while(true){ //状態を確認して、処理を分岐 switch(state){ case STATE_INIT:{ //イメージを読みこむ teximage = LoadImage("girl.gif", 1,5, false); teximage2 = LoadImage("water.gif", 2,5, false); teximage3 = LoadImage("light.gif", 3,5, false); teximage4 = LoadImage("light2.gif", 4,5, false); teximage6 = LoadImage("hanabi.gif", 5,5, false); //titleimage = LoadImage("title.gif", 6,6, false); //読みこみ中に表示する三角形頂点初期化 loading_ver_x[0] = 30; loading_ver_x[1] = 40; loading_ver_x[2] = 30; loading_ver_y[0] = 120; loading_ver_y[1] = 125; loading_ver_y[2] = 130; //ロード時に表示する円の色設定 load_color = new Color(0,0,255); //ロード画面イメージ作成 loadimage = createImage(WIDTH,HEIGHT); //状態を次に移す state = STATE_LOADING; break; } case STATE_LOADING:{ if(Tracker.checkAll(true)){ //読みこみが完了した state = STATE_LOADED; //repaint(); } else{ //ローディング待機画面表示 repaint(); } break; } case STATE_LOADED:{ repaint(); state = STATE_PREPARING; break; } case STATE_PREPARING:{ //サインコサインテーブル初期化 // 2πラジアン=360° for(int i=0; i<4096; i++){ cos_table[i] = (int) (Math.cos((double)i / 2048.0 * 3.14159265358979) * 65536.0); sin_table[i] = (int) (Math.sin((double)i / 2048.0 * 3.14159265358979) * 65536.0); } //イメージを配列に変換 ImageToArray(texbuf,teximage); ImageToArray(texbuf2,teximage2); ImageToArray(texbuf3,teximage3); ImageToArray(texbuf4,teximage4); ImageToArray(texbuf6,teximage6); //ImageToArray(titlebuf,titleimage); //水面配列クリア for(int x = 0;x <200;x++){ for(int y = 0;y <200;y++){ for(int z=0;z<2;z++){ depthTbl[z][x][y] = texbuf[200*y + x]; } } } state = STATE_EXECUTE; break; } case STATE_EXECUTE:{ //if(time_count%3 == 1 || time_count%3 == 2)//シーンを間引く(処理を軽くする) //continue; repaint();//実行中 break; } } //寝てよし Thread.sleep(20); } } catch(Exception e){ } } //------------------------------- // 再描画 //------------------------------- public void update(Graphics g) { paint(g); } //------------------------------- //    水面を描写する //------------------------------- public void DrawWater() { int x,y; int depth_R;//Red int depth_G;//Green int depth_B;//Blue int depth; ClearWater();//水面配列のクリア //カウンタを使って、二枚の水面テーブルをフリップする。 flip1 = gameCtr&1; //gameCtrが奇数なら真 flip2 = flip1^1; //flip1が偶数なら1 //水面の計算 for(y=1; y<199; y++){ for(x=1; x<199; x++){ //ピクセルごとに上下左右の色成分の平均を出す //赤 depth_R =(depthTbl[flip1][x-1][y ]&0x00ff0000)>>16; //左 depth_R +=(depthTbl[flip1][x ][y-1]&0x00ff0000)>>16; //上 depth_R +=(depthTbl[flip1][x+1][y ]&0x00ff0000)>>16; //右 depth_R +=(depthTbl[flip1][x ][y+1]&0x00ff0000)>>16; //下 depth_R = depth_R>>1; if((depth_R -= (depthTbl[flip2][x ][y ]&0x00ff0000)>>16)<0)//水面の中央を引く depth_R = 0x00000000;//0以下なら0 if(depth_R > 0x000000ff) depth_R = 0x000000ff;//飽和処理 //緑 depth_G =(depthTbl[flip1][x-1][y ]&0x0000ff00)>>8; //左 depth_G +=(depthTbl[flip1][x ][y-1]&0x0000ff00)>>8; //上 depth_G +=(depthTbl[flip1][x+1][y ]&0x0000ff00)>>8; //右 depth_G +=(depthTbl[flip1][x ][y+1]&0x0000ff00)>>8; //下 depth_G = depth_G>>1; if((depth_G -= (depthTbl[flip2][x ][y ]&0x0000ff00)>>8) < 0)//水面の中央を引く depth_G = 0x00000000;//0以下なら0 if(depth_G > 0x000000ff) depth_G = 0x000000ff;//飽和処理 //青 depth_B =(depthTbl[flip1][x-1][y ]&0x000000ff); //左 depth_B +=(depthTbl[flip1][x ][y-1]&0x000000ff); //上 depth_B +=(depthTbl[flip1][x+1][y ]&0x000000ff); //右 depth_B +=(depthTbl[flip1][x ][y+1]&0x000000ff); //下 depth_B = depth_B>>1; if((depth_B -= (depthTbl[flip2][x ][y ]&0x000000ff)) < 0) depth_B = 0x00000000;//0以下なら0 if(depth_B > 0x000000ff) depth_B = 0x000000ff;//飽和処理 //各成分を合成する depth = (depth_R<<16) | (depth_G<<8) | (depth_B); //色が噴出すような効果を出す(ゆらぎを与える) if(time_count >= 1180) if(depth<=0x00000000) depth= texbuf3[200*y + x]&0x00555555; depth |= 0xff000000;//アルファ成分を足す depthTbl[flip2][x][y]=(depth); //次回の水面に結果を代入 } } //サーフェイスに水面を描画する for(y=0; y 0){ sampling = (1/scal);//サンプリングの間隔を求める } else{ sampling = 0.000001f; } //拡大、縮小 for (y=0,ty=0; y=0 && ty>=0 && tx<200 && ty<200) pbuf[y*200 + x] = addColor(pbuf[y*200 + x],darkColor(texbuf[((int)ty)*200 + ((int)tx)])); else pbuf[y*200 + x] = 0x00000000; } } } //---------------------------- // バックバッファに描画する //--------------------------- private void CRender() { int x=0,y=0; //ループカウンタ int px,py; //テクスチャ内の座標 int gpix; //これから書きこむ色 int ysint,xcost; // y*cosT, y*sinT int xsint,ycost; //時間によって色々な処理を場合分けしている /*↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/ //ハルナぴょんを半透明合成する if(time_count > 300 && time_count < 800 || time_count > 1300){ for (y=0; y 800 && time_count < 1300){ time += 1300; for (y=0; y 1300){ for (y=0; y>1; xsint = ((100-x) * sin_table[time])>>1; px1 = xsint>>1 ; dpx1 = (sin_table[time])>>1; py1 = ycost>>1 ; dpy1 = (sin_table[time])>>1; for (x=0; x> 16) + 150; py = (py1 >> 16) + 150; px1 += dpx1; py1 += dpy1; pbuf[y*200+x] = blendColor(pbuf[y*200+x],texbuf2[py*300+px],240); } } } DrawWater(); //水面の計算 if(time_count > 800 && time_count < 850){ Scaling(scal,texbuf);//拡大縮小処理をバッファに重ねる } else if(time_count > 900 && time_count < 1300){ Scaling(scal,texbuf6);//拡大縮小処理2 } /* //ハルナぴょんを加算合成する if(time_count < 800 || time_count > 1300){ for(x=0; x1365){ time_count = 0; } time += 3; time &= 4095; //拡大率の上げ下げ if(time_count > 800 && time_count < 900){ scal += 0.05f;//拡大していく } else if(time_count == 900){ scal = 5.01f; } else if(time_count > 900 && time_count < 1300){ scal -= 0.01f;//縮小していく } } //------------------------- //  画像読みこみ時の処理 //------------------------ public void LoadLoad(Graphics g) { if(loadg == null) loadg = loadimage.getGraphics();//グラフィックコンテキストをもらう loadg.setColor(Color.white); loadg.fillRect(0,0,200,200);//画面を白で塗りつぶす loadg.setColor(load_color); int r = (loading_time*loading_time)/2;//円の直径 loadg.drawOval(100-r/2,100-r/2,r,r);//円を描画する loadg.setColor(new Color(0,0,255-loading_time)); if((loading_time % 10) == 0){ for(int i=0;i<3;i++){ loading_ver_x[i] += 10 ;//三角形を10pixl進ませる } } loadg.fillPolygon(loading_ver_x,loading_ver_y,3); loadg.fill3DRect(20,80,150,30,true); loadg.setColor(Color.white); loadg.setFont(new Font("Courier",Font.BOLD,14)); loadg.drawString("Now Loading ...",30,100); g.drawImage(loadimage,0,0,this); loading_time++; loading_time %= 130; if(loading_time == 129){ for(int i=0;i<3;i++){ loading_ver_x[i] -= 130; //三角形を130pixl戻す } } } //------------------------------- //  描画処理 //------------------------------ public void paint(Graphics g) { if(state == STATE_EXECUTE){ CRender();//バックバッファに描画する pimage = ArrayToImage(pbuf,200,200);//バックバッファ配列をイメージにする g.drawImage(pimage,0,0,this); //FrameRate(g);//デバッグ用 } else{ //画像読みこみ、初期化中の表示処理 if(state == STATE_LOADING){ LoadLoad(g);//読みこみ中待機画面表示 } else{ //初期化中メッセージ表示 g.setColor(Color.white); g.fillRect(0,0,200,200); g.setColor(Color.black); g.setFont(new Font("Courier",Font.BOLD,14)); g.drawString("初期化しています…。",30,100); } } } }