import java.io.*; import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; public final class Ts extends Applet implements Runnable, KeyListener, MouseListener { //======================================================================== // Thread関連情報 //======================================================================== // thread private volatile Thread cycThread = null; private static int sleepTime = 16; // threadスリープ時間 //======================================================================== // システムプロパティ情報 //======================================================================== private static String sysJavaVersion; // Javaバージョン private static String sysJavaVendor; // Javaベンダー private static String sysJavaVendorUrl; // JavaベンダーURL private static String sysJavaApiVersion; // JavaAPIバージョン private static String sysOsName; // OS名称 private static String sysOsArch; // CPUアーキテクチャ private static String sysOsVersion; // OSバージョン //======================================================================== // 仮想画面関連情報 //======================================================================== private final int bgWidth = 256; // BG画面幅 private final int bgHeight = 384; // BG画面高さ private Image bgBuff; // BGバッファ private Graphics bg; // BGバッファGraphics private double scrnSzX; // 画面サイズx private double scrnSzY; // 画面サイズy //======================================================================== // CPU速度計測用情報 //======================================================================== static final int monFrame = 100; // CPU速度計測フレーム数 static int monCntr = 0; // CPU速度計測用カウンタ static int monFlag = 0; // CPU速度計測用フラグ private static long nowTime = 0; private static long oldTime; //======================================================================== // キー入力管理情報 //======================================================================== private boolean keyPress[]; // キー入力判定配列 private final int KEYS = 5; // 識別キー個数 private final int LEFT = 0; // "←"キー識別 private final int RIGHT = 1; // "→"キー識別 private final int UP = 2; // "↑"キー識別 private final int DOWN = 3; // "↓"キー識別 private final int SPACE = 4; // " "キー識別 private int spKeyCntr = 0; // " "キー連射用カウンタ private final int FIRE_INT = 2; // 連射間隔 //======================================================================== // 状態遷移管理情報 //======================================================================== private boolean init; // 初期化判定フラグ static final int phInit = 0; // CPU速度計測状態 static final int phTitle = 1; // タイトル状態 static final int phPlay = 2; // プレイ中状態 static final int phGameover = 3; // GameOver状態 private int phase = phInit; // 状態管理変数 private int filterCnt = 0; // 画面マスク処理用カウンタ private int gameoverCnt = 0; // GAMEOVER文字表示用カウンタ private boolean clearFlag = false; // ゲームクリアフラグ //======================================================================== // 背景関連情報 //======================================================================== private final Color bgCol = new Color(0x404080); // 背景色 private final Color grdCol = new Color(0x8080c0); // グリッド色 private int bgScr = 0; // 背景スクロール量 private Color ownHpCol[]; // 自機HP表示色 private final int ownHpColG = 16; // 自機HP表示色階調 //======================================================================== // タイトル画面関連情報 //======================================================================== private final Color textOsCol = new Color(0xd0d0ff); // システム情報色 private final Color textMsgCol = new Color(0xffffff); // メッセージ色 private final Color titleBgCol = new Color(0x8080c0); // タイトル背景色 //======================================================================== // ちらつき色 //======================================================================== private Color flickCol; private Color flCol[]; private int flCnt = 0; private final int flNum = 4; //======================================================================== // 自機関連情報 //======================================================================== private final int ownMaxTurnRate = 12; // 最大旋回角 private final int ownTurnRate = 4; // 旋回率 private int ownCrs = 0; // 針路(DEG) private final double ownIniPosX = 128.0; // x座標初期値 private final double ownIniPosY = 300.0; // y座標初期値 private final int ownHp = 127; // 自機HP private static int score = 0; //======================================================================== // オブジェクト情報 //======================================================================== private Own own; private Zapper zapper[]; private Spark spark[]; private Blast blast[]; private EnemA eA[]; private EnemB eB[]; private EnemC eC[]; private EnemD eD[]; private Bullet bullet[]; //======================================================================== // 場面展開情報 //======================================================================== private static int tick = 0; // システムカウンタ private static int mapCntr = 0; // マップカウンタ private static int mapWidth; // マップ幅 private static int mapHeight; // マップ高さ private static int level = 0; // 難易度 private static int remain; // 残り時間 //======================================================================== // コンストラクタ //======================================================================== public Ts() { System.out.println("Ts()"); } //======================================================================== // 初期化処理 //======================================================================== public void init() { System.out.println("init()"); //-------------------------------------------------------------------- // 初期化完了フラグの設定 //-------------------------------------------------------------------- init = false; //-------------------------------------------------------------------- // オフスクリーン作成 //-------------------------------------------------------------------- try { bgBuff = createImage(bgWidth, bgHeight); } catch (Exception e) {} //-------------------------------------------------------------------- // BG画面作成 //-------------------------------------------------------------------- bg = bgBuff.getGraphics(); //-------------------------------------------------------------------- // 画面サイズ設定 //-------------------------------------------------------------------- scrnSzX = bgWidth; scrnSzY = bgHeight; //-------------------------------------------------------------------- // キー入力管理変数初期化 //-------------------------------------------------------------------- keyPress = new boolean[KEYS]; for(int i=0; i= flNum) { flCnt = 0; } if((tick & 0x0f) == 0) { if(own.getHp() < ownHp) { own.mdfHp(+1); } } if(phase == phInit) { if(monCntr == 0) { nowTime = System.currentTimeMillis(); } if((monCntr >= monFrame) && monFlag == 0) { monFlag = 1; oldTime = nowTime; nowTime = System.currentTimeMillis(); modTime = (int)((nowTime - oldTime)/monFrame); workTime = modTime - sleepTime; sleepTime = 18 - workTime; if(sleepTime < 8) { sleepTime = 8; } // System.out.println(sleepTime+":"+workTime+" / "+(1000/modTime)+"[frame/sec]"); showStatus("WaitTime:"+sleepTime); phase = phTitle; } monCntr++; } // システムカウンタの更新 tick++; } //======================================================================== // タイトル表示処理 //======================================================================== private void title() { // 背景消去 bg.setColor(titleBgCol); bg.fillRect(0, 0, bgWidth, bgHeight); if(phase == phTitle) { // メッセージ表示 strDraw("CLICK TO START", textMsgCol, 11.0, 192.0, 0, 1.0, 1.0); } if(phase == phInit) { // メッセージ表示 String str = Integer.toString((int)(monFrame-monCntr)); str = "000"+str; String str2 = str.substring(str.length() - 3); strDraw("WAIT/"+str2, textMsgCol, 65.0, 192.0, 0, 1.0, 1.0); } double textY = 358.0; strDraw("JAVA"+sysJavaVersion, textOsCol, 5.0, textY, 0, 0.5, 0.75); textY += 10; strDraw("OS:"+sysOsName+" "+sysOsVersion, textOsCol, 5.0, textY, 0, 0.5, 0.75); textY += 10; strDraw("CPU:"+sysOsArch, textOsCol, 5.0, textY, 0, 0.5, 0.75); textY += 10; } //======================================================================== // 画面マスク処理 //======================================================================== private void maskScreen() { bg.setColor(titleBgCol); for(int i=0; i 60) { strDraw("GAME CLEAR", textMsgCol, 47, 180, 0, 1.0, 1.0); } if(gameoverCnt > 120) { strDraw("CLICK TO REPLAY", textMsgCol, 34.0, 200.0, 0, 0.75, 0.75); } } private void goverDraw() { double scale; double ofsx; int vec; if(gameoverCnt < 90) { scale = 10.0 - (gameoverCnt/10.0); vec = 450 - gameoverCnt*5; } else { scale = 1.0; vec = 0; } // ofsx = (18.0*scale - 18.0)*4.5-9.0*scale; ofsx = 72.0*scale - 81.0; strDraw("GAME OVER", textMsgCol, 47.0-ofsx, 180, vec, scale, scale); if(gameoverCnt > 90) { strDraw("CLICK TO REPLAY", textMsgCol, 34.0, 200.0, 0, 0.75, 0.75); } } //======================================================================== // プレイ中処理 //======================================================================== private void play() { mapRead(); objMove(); objDraw(); objCorr(); } //======================================================================== // マップ情報読み込み処理 //======================================================================== private void mapRead() { char map; if((tick & 0xf) == 0) { for(int x=0; x= mapHeight) { mapCntr = 0; level++; } if(phase == phPlay) { remain--; } if(remain == 0) { phase = phGameover; clearFlag = true; } } } //======================================================================== // 各オブジェクト作成処理 //======================================================================== // // 敵弾作成処理 // private void bulletMake(double posx, double posy, int vec) { for(int i=0; i= num) { break; } } } } // // 爆風作成処理 // void blastMake(double posx, double posy, double vx, double vy, int num) { int mkCnt = 0; for(int i=0; i= num) { break; } } } } //======================================================================== // オブジェクト移動処理 //======================================================================== private void objMove() { if(phase == phPlay) { ownMove(); } enemAMove(); enemBMove(); enemCMove(); enemDMove(); objsMove(bullet); objsMove(zapper); objsMove(blast); objsMove(spark); } // // 自機移動処理 // private void ownMove() { // 上下移動処理 if(keyPress[UP] &&(own.getPosY() > 10.0)) { own.offsetPos(0.0, -2.0); } if(keyPress[DOWN] && (own.getPosY() < scrnSzY-10.0)) { own.offsetPos(0.0, 2.0); } // 左右方向移動処理 if(keyPress[LEFT]) { if(ownCrs >= -ownMaxTurnRate) { ownCrs -= ownTurnRate; } if(own.getPosX() > 10.0) { own.offsetPos(MyMath.sin(ownCrs)*9.0, 0.0); } } else if(keyPress[RIGHT]) { if(ownCrs <= ownMaxTurnRate) { ownCrs += ownTurnRate; } if(own.getPosX() < scrnSzX-10.0) { own.offsetPos(MyMath.sin(ownCrs)*9.0, 0.0); } } else { if(ownCrs > 0) { ownCrs -= ownTurnRate; } if(ownCrs < 0) { ownCrs += ownTurnRate; } } // SPACE key押下時処理 if(keyPress[SPACE] && spKeyCntr == 0) { int makeNum = 0; int makeIdx = 0; // 左右2連射処理 for(int znum=0; znum<2; znum++) { // 発射弾数チェック double zx; if(znum == 0) { zx = -6.0; } else { zx = 6.0; } // 空きオブジェクト検索 for(int i=0; i FIRE_INT) { spKeyCntr = 0; } if(own.isDamaged()) { own.decDamage(); } own.setVecTh(ownCrs); } // // オブジェクト単純移動処理 // private void objsMove(Motion obj[]) { // オブジェクト配列参照 for(int i=0; i 30) { if(eA[i].getBehFlag() == 1) { eA[i].mdfVecTh(-2); } else { eA[i].mdfVecTh(2); } } eA[i].vecMove(); eA[i].offsetPos(0.0, 1.0); if(eA[i].isDamaged()) { eA[i].decDamage(); } // 寿命を1減らす eA[i].decLife(); // 敵弾発射 if((eA[i].getCount() == 20) || (eA[i].getCount() == 30) || (eA[i].getCount() == 50)) { double ex; double ey; double ox; double oy; ex = eA[i].getPosX(); ey = eA[i].getPosY(); ox = own.getPosX(); oy = own.getPosY(); bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(60)-30); if(level >= 1) { bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(80)-40); } if(level >= 2) { bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(100)-50); } } // 画面外に出たらkillする if(eA[i].isRangeOut(0.0, 0.0, scrnSzX, scrnSzY)) { eA[i].kill(); } } } } // // 敵B移動処理 // private void enemBMove() { for(int i=0; i 200.0) { eB[i].setVel(0.0, -4.0); eB[i].setVecTh(270); } // 敵弾発射 if((eB[i].getCount() == 10) || (eB[i].getCount() == 20) || (eB[i].getCount() == 50)) { double ex; double ey; double ox; double oy; ex = eB[i].getPosX(); ey = eB[i].getPosY(); ox = own.getPosX(); oy = own.getPosY(); bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(60)-30); if(level >= 1) { bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(80)-40); } if(level >= 2) { bulletMake(ex, ey, MyMath.getBrg(ex, ey, ox, oy)+MyMath.iRnd(100)-50); } } // 画面外に出たらkillする if(eB[i].isRangeOut(0.0, 0.0, scrnSzX, scrnSzY)) { eB[i].kill(); } } } } // // 敵C移動処理 // private void enemCMove() { for(int i=0; i= 360) { vecTh -= 360; } if(vecTh < 0) { vecTh += 360; } } // ベクトル移動 public final void vecMove() { double vel; count++; vecTh += velTh; if(vecTh >= 360) { vecTh -= 360; } if(vecTh < 0) { vecTh += 360; } vel = MyMath.sqrt(velX*velX+velY*velY); velX = MyMath.cos(vecTh)*vel; velY = MyMath.sin(vecTh)*vel; posX += velX; posY += velY; } // 位置補正 public final void corrPos( double scrnX, double scrnY ) { if(posX >= scrnX) { posX -= scrnX; } if(posX < 0.0) { posX += scrnX; } if(posY >= scrnY) { posY -= scrnY; } if(posY < 0.0) { posY += scrnY; } } // 姿勢角変更 public final void rotTh( int th // 変更差分(+:右回り/-:左回り) ) { vecTh += th; if(vecTh >= 360) { vecTh -= 360; } if(vecTh < 0) { vecTh += 360; } } // 速度ベクトル設定 public final void setVec( int th, // 方位ベクトル double v // 速度スカラ量 ) { velX = v * MyMath.cos(th); velY = v * MyMath.sin(th); } // 指定方位へ加速 public final void thrust( int th, // 加速方位 double v, // 加速量 double limV // 制限速度 ) { double vel; velX += v * MyMath.cos(th); velY += v * MyMath.sin(th); vel = velX*velX+velY*velY; // 制限速度を超えた場合、速度の正規化を行う。 if(vel > limV*limV) { velX *= ((limV*limV) / vel); velY *= ((limV*limV) / vel); } } // 一定率加減速 public final void reduce( double rate // 加減速率 ) { velX *= rate; velY *= rate; } // オブジェクト生死判定 public final boolean isDead() { return !isAlive(); } // オブジェクト生死判定 public final boolean isAlive() { boolean result; if((life == 0) || (hp == 0)) { result = false; } else { result = true; } return result; } // life設定 public final void setLife( int life_ // life設定値 ) { life = life_; } // lifeを0に設定 public final void kill() { life = 0; hp = 0; } // life取得 public final int getLife() { return life; } // life設定値変更 public final void mdfLife( int mdf // 変化量 ) { life += mdf; } // lifeデクリメント public final void decLife() { life--; } public final int getHp() { return hp; } public final void setHp( int hp_ ) { hp = hp_; } public final void mdfHp( int mdf ) { hp += mdf; } public final void decHp() { hp--; } public final void setBehFlag( int flag ) { behFlag = flag; } public final int getBehFlag() { return behFlag; } // カウンタ初期化 public final void initCount() { count = 0; } // カウンタ増 public final void incCount() { count++; } // カウンタ取得 public final int getCount() { return count; } // 位置設定 public final void setPos( double x, // 位置設定x座標 double y // 位置設定y座標 ) { posX = x; posY = y; } // 指定量移動 public final void offsetPos( double dx, double dy ) { posX += dx; posY += dy; } // 位置x座標取得 public final double getPosX() { return posX; } // 位置y座標取得 public final double getPosY() { return posY; } // サイズ取得 public final double getSize() { return size * scale; } // スケール変更 public final void chgScale( double v // 倍率 ) { scale *= v; } // スケール変更 public final void setScale( double v // 倍率 ) { scale = v; } // スケール取得 public final double getScale() { return scale; } // 位置指定範囲内外判定 public final boolean isRangeOut( double x1, // 位置判定x座標(左上端) double y1, // 位置判定y座標(左上端) double x2, // 位置判定x座標(右下端) double y2 // 位置判定y座標(右下端) ) { boolean result; if((posX < x1) || (posX > x2) || (posY < y1) || (posY > y2)) { result = true; } else { result = false; } return result; } // 速度設定 public final void setVel( double vx, // 設定速度x成分 double vy // 設定速度y成分 ) { velX = vx; velY = vy; } // 速度x成分取得 public final double getVX() { return velX; } // 速度y成分取得 public final double getVY() { return velY; } // 姿勢角設定 public final void setVecTh( int th // 設定方位 ) { vecTh = th; } // 姿勢角設定 public final void mdfVecTh( int th // 設定方位 ) { vecTh += th; if(vecTh >= 360) { vecTh -= 360; } if(vecTh < 0) { vecTh += 360; } } // 回転角速度設定 public final void setVelTh( int vel // 設定回転角速度 ) { velTh = vel; } // 姿勢角取得 public final int getVecTh() { return vecTh; } // 回転角速度取得 public final int getVelTh() { return velTh; } public final void setDamage( int dam ) { damage = dam; } public final void decDamage() { damage--; } public final int getDamage() { return damage; } public final boolean isDamaged() { boolean result; if(damage != 0) { result = true; } else { result = false; } return result; } } import java.awt.*; public class Own extends Motion { //======================================================================== // インスタンス変数定義 //======================================================================== private static final double size = 3.0; // サイズ private static final int pNum = 3; // 構成Plate数 private static Plate plate[]; // 構成Plate配列 private static final Color colorC = new Color(0xd0d0d0); // 表示色(Body) private static final int styleC = Plate.LNFL; // 表示スタイル(Body) static final double shapeC[][] = { // 形状(Body) { 0.0, -15.0}, { 3.0, 3.0}, { -3.0, 3.0}, { 0.0, -15.0} }; private static final Color colorR = new Color(0x9090c0); // 表示色(Rwing) private static final int styleR = Plate.LNFL; // 表示スタイル(Rwing) static final double shapeR[][] = { // 形状(Rwing) { 3.0, -6.0}, { 12.0, 8.0}, { 6.0, 6.0}, { 3.0, -6.0} }; private static final Color colorL = new Color(0x9090c0); // 表示色(Lwing) private static final int styleL = Plate.LNFL; // 表示スタイル(Lwing) static final double shapeL[][] = { // 形状(Lwing) { -3.0, -6.0}, {-12.0, 8.0}, { -6.0, 6.0}, { -3.0, -6.0} }; //======================================================================== // 静的初期化 //======================================================================== static { plate = new Plate[pNum]; plate[0] = new Plate(colorC, styleC, shapeC); plate[1] = new Plate(colorL, styleL, shapeL); plate[2] = new Plate(colorR, styleR, shapeR); } //======================================================================== // コンストラクタ //======================================================================== Own(double x, double y) { super(x, y, size); } //======================================================================== // Method //======================================================================== // 画面表示 public final void draw( Graphics g // 表示対象Graphics ) { for(int i=0; i= DEG) { deg -= DEG; } while(deg < 0) { deg += DEG; } result = deg; return result; } //======================================================================== // sqrt関数 //======================================================================== public static final double sqrt( double num // 入力値 ) { return Math.sqrt(num); } //======================================================================== // 整数乱数関数 //======================================================================== public static final int iRnd(int range) { return (int)(Math.random()*range); } //======================================================================== // 実数乱数関数 //======================================================================== public static final double fRnd(double range) { return Math.random()*range; } //======================================================================== // 2点間方位取得 //======================================================================== public static final int getBrg( double x1, double y1, double x2, double y2 ) { double dx, dy; int result = 0; int at; int deg0; boolean rvs; dx = x2 - x1; dy = y2 - y1; // 第1象限 if((dx >= 0) && (dy >= 0)) { if(Math.abs(dy) > Math.abs(dx)) { at = (int)((dx / dy) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 89 - deg0; } else { at = (int)((dy / dx) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = deg0; } } // 第2象限 if((dx < 0) && (dy >= 0)) { if(Math.abs(dy) > Math.abs(dx)) { at = (int)((-dx / dy) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 90 + deg0; } else { at = (int)((dy / -dx) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 179 - deg0; } } // 第3象限 if((dx < 0) && (dy < 0)) { if(Math.abs(dy) > Math.abs(dx)) { at = (int)((-dx / -dy) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 269 - deg0; } else { at = (int)((-dy / -dx) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 180 + deg0; } } // 第4象限 if((dx >= 0) && (dy < 0)) { if(Math.abs(dy) > Math.abs(dx)) { at = (int)((dx / -dy) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 270 + deg0; } else { at = (int)((-dy / dx) * 100) - 1; if(at < 0) { at = 0; } if((at < 0) || (at >= 100)) { System.out.println("at:"+at+",x1:"+x1+",y1:"+y1+",x2:"+x2+",y2:"+y2); } deg0 = regDeg(atanTbl[at]); result = 359 - deg0; } } return result; } }