import java.lang.*; import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import Obj; public class St extends Applet implements Runnable, KeyListener, MouseListener { Thread cycleExec = null; // thread private int sleepTime = 16; // threadスリープ時間 // 仮想画面関連変数 private int bgWidth = 480; // BG画面幅 private int bgHeight = 320; // BG画面高さ private Image bgBuff; // BGバッファ private Graphics bg; // BGバッファGraphics // キー入力管理変数 private boolean KeyPress[]; // キー入力判定配列 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 final int KEYS = 5; // 識別キー個数 private boolean spKeyRel = true; // " "キーリピートフラグ private boolean init; // 初期化判定フラグ private Obj own; // 自機オブジェクト private Obj zapper[]; // 自機弾オブジェクト static final int zapNum = 8; // 自機弾個数 static final int zapRange = 96; // 自機弾寿命 private int zapCnt = 0; // 自機弾カウンタ private Obj lMeteo[]; // 隕石(大)オブジェクト static final int lMetNum = 6; // 隕石(大)個数 private int lMetCnt = 0; // 隕石(大)カウンタ private Obj mMeteo[]; // 隕石(中)オブジェクト static final int mMetNum = 18; // 隕石(中)個数 private int mMetCnt = 0; // 隕石(中)カウンタ private Obj sMeteo[]; // 隕石(小)オブジェクト static final int sMetNum = 54; // 隕石(小)個数 private int sMetCnt = 0; // 隕石(小)カウンタ private Obj particle[]; // 破片オブジェクト static final int ptcNum = 96; // 破片個数 private int ptcCnt = 0; // 破片カウンタ static final int ptcLife = 64; // 破片寿命 private Color ownCol = new Color(0x00ff00); // 自機色 private Color zapCol = new Color(0x00ff00); // 自機弾色 private Color metCol = new Color(0x00cf00); // 隕石色 private Color grdCol = new Color(0x006f00); // グリッド色 private Color toneCol[]; // 明->暗色配列 static final int phTitle = 0; // タイトル状態 static final int phPlay = 1; // プレイ中状態 static final int phGover = 2; // GameOver状態 int phase = phTitle; // 状態管理変数 private int score; // Score private int stage; // Stage番号 // Stage対応隕石個数,分裂数 int mSts[][] = {{4, 2}, {5, 2}, {6, 2}, {4, 3}, {5, 3}, {6, 3}}; static final int stageNum = 6; // Stage数 private int mNum; // 隕石個数 private int mDiv; // 隕石分裂数 static final int lMetScore = 40; // 隕石(大)得点 static final int mMetScore = 20; // 隕石(中)得点 static final int sMetScore = 10; // 隕石(小)得点 // 自機形状 double ownShape[][] = {{ 7.0, 0.0}, { -5.0, 4.0}, { -5.0, -4.0}, { 7.0, 0.0}}; // 自機弾形状 double zapShape[][] = {{ -2.0, 1.5}, { 2.0, 0.0}, { -2.0, -1.5}, { -2.0, 1.5} }; // 隕石(大)形状 double lMetShape[][] = {{ 15.0, -5.0}, { 5.0, 20.0}, { -5.0, 10.0}, {-15.0, 15.0}, {-20.0, -10.0}, { 5.0, -20.0}, { 15.0, -5.0}}; // 隕石(中)形状 double mMetShape[][] = {{ 8.0, -3.0}, { 3.0, 10.0}, { -3.0, 5.0}, { -8.0, 8.0}, {-12.0, -5.0}, { 3.0, -10.0}, { 8.0, -3.0}}; // 隕石(小)形状 double sMetShape[][] = {{ 4.0, -2.0}, { 2.0, 5.0}, { -1.0, 2.0}, { -4.0, 4.0}, { -5.0, -3.0}, { 2.0, -5.0}, { 4.0, -2.0}}; // 破片形状 double ptcShape[][] = {{ 0.0, 3.0}, { 2.0, -1.0}, { -2.0, -1.0}, { 0.0, 3.0}}; // 12pointフォント private Font font12 = new Font("Helvetica", Font.PLAIN, 12); // 14pointフォント private Font font14 = new Font("Helvetica", Font.PLAIN, 14); // タイトル表示時用カウンタ private int titCnt = 0; private int titCntInc = 1; // コンストラクタ public St() { } public void init() { init = false; // オフスクリーン作成 try { bgBuff = createImage(bgWidth, bgHeight); } catch (Exception e) {} // BG画面作成 bg = bgBuff.getGraphics(); bg.setFont(font12); // キー入力管理変数初期化 KeyPress=new boolean[KEYS]; for(int i=0; i暗色配列作成 toneCol = new Color[ptcLife]; for(int i=0; i= stageNum) { stage = 0; } } } //================================================================== // 各オブジェクト移動処理 //================================================================== void objMove() { ownMove(); zapMove(); metMove(); ptcMove(); } // 自機移動処理 void ownMove() { if(KeyPress[UP]) { own.thrust(own.vecTh, 0.1, 3.0); } // if(KeyPress[DOWN]) { // } if(KeyPress[LEFT]) { own.subVecTh(5.0); } if(KeyPress[RIGHT]) { own.addVecTh(5.0); } if(KeyPress[SPACE]) { // 押しっぱなしは駄目 KeyPress[SPACE] = false; // 発射弾数チェック if(zapCnt < zapNum) { // 空きオブジェクト検索 for(int i=0; i= ptcNum) { break; } // 空きオブジェクト検索 if(particle[i].life == 0) { particle[i].life = ptcLife-1; particle[i].rotTh = (Math.random() - 0.5)*10.0; particle[i].vecTh = Math.random() * 359.0; particle[i].posX = posx; particle[i].posY = posy; particle[i].vX = vx; particle[i].vY = vy; particle[i].thrust(Math.random() * 359.0, Math.random(), 10.0); ptcCnt++; // 指定数作成したら終了 mkCnt++; if(mkCnt >= num) { break; } } } } // 隕石(大)作成 void lMetMake(double posx, double posy, double vx, double vy, int num) { int mkCnt = 0; for(int i=0; i= lMetNum) { break; } // 空きオブジェクト検索 if(lMeteo[i].life == 0) { lMeteo[i].life = -1; lMeteo[i].rotTh = (Math.random() - 0.5)*10.0; lMeteo[i].vecTh = Math.random() * 359.0; lMeteo[i].posX = posx; lMeteo[i].posY = posy; lMeteo[i].vX = vx; lMeteo[i].vY = vy; lMeteo[i].thrust(Math.random() * 359.0, Math.random()+0.5, 2.0); lMetCnt++; // 指定数作成したら終了 mkCnt++; if(mkCnt >= num) { break; } } } } // 隕石(中)作成 void mMetMake(double posx, double posy, double vx, double vy, int num) { int mkCnt = 0; for(int i=0; i= mMetNum) { break; } // 空きオブジェクト検索 if(mMeteo[i].life == 0) { mMeteo[i].life = -1; mMeteo[i].rotTh = (Math.random() - 0.5)*10.0; mMeteo[i].vecTh = Math.random() * 359.0; mMeteo[i].posX = posx; mMeteo[i].posY = posy; mMeteo[i].vX = vx; mMeteo[i].vY = vy; mMeteo[i].thrust(Math.random() * 359.0, Math.random(), 2.0); mMetCnt++; // 指定数作成したら終了 mkCnt++; if(mkCnt >= num) { break; } } } } // 隕石(小)作成 void sMetMake(double posx, double posy, double vx, double vy, int num) { int mkCnt = 0; for(int i=0; i= sMetNum) { break; } // 空きオブジェクト検索 if(sMeteo[i].life == 0) { sMeteo[i].life = -1; sMeteo[i].rotTh = (Math.random() - 0.5)*10.0; sMeteo[i].vecTh = Math.random() * 359.0; sMeteo[i].posX = posx; sMeteo[i].posY = posy; sMeteo[i].vX = vx; sMeteo[i].vY = vy; sMeteo[i].thrust(Math.random() * 359.0, Math.random(), 2.0); sMetCnt++; // 指定数作成したら終了 mkCnt++; if(mkCnt >= num) { break; } } } } //================================================================== // 各オブジェクト衝突判定 //================================================================== void objColl() { zapColl(); ownColl(); } // 自機弾当たり判定 void zapColl() { for(int i=0; i= ptcLife) { titCnt = ptcLife-1; titCntInc = -titCntInc; } if(titCnt < 0) { titCnt = 0; titCntInc = -titCntInc; } } // プレイ中ステータス表示 void stsDraw() { // Score表示 bg.setColor(Color.green); String str = Integer.toString(score); str = "00000"+str; String str2 = str.substring(str.length() - 5); bg.drawString("Score : "+str2, 10, 13); } // GameOver時表示 void govDraw() { bg.setColor(Color.green); // 何故か繰り返し描かないと表示されない処理系がある for(int i=0; i<16; i++) { bg.drawString("Game Over", 204, 150); bg.drawString("Hit [Down] key to replay.", 165, 181); } } //================================================================== // KeyListener Method //================================================================== public void keyPressed(KeyEvent e) { switch(e.getKeyCode()) { case KeyEvent.VK_UP: case KeyEvent.VK_NUMPAD8: KeyPress[UP]=true; KeyPress[DOWN]=false; break; case KeyEvent.VK_DOWN: case KeyEvent.VK_NUMPAD2: KeyPress[DOWN]=true; KeyPress[UP]=false; if(phase == phGover) { initStatus(); phase = phPlay; } break; case KeyEvent.VK_LEFT: case KeyEvent.VK_NUMPAD4: KeyPress[LEFT]=true; KeyPress[RIGHT]=false; break; case KeyEvent.VK_RIGHT: case KeyEvent.VK_NUMPAD6: KeyPress[RIGHT]=true; KeyPress[LEFT]=false; break; case KeyEvent.VK_SPACE: if(spKeyRel) { KeyPress[SPACE]=true; spKeyRel = false; } else { KeyPress[SPACE]=false; } break; } } public void keyReleased(KeyEvent e) { switch(e.getKeyCode()) { case KeyEvent.VK_UP: KeyPress[UP]=false; break; case KeyEvent.VK_DOWN: KeyPress[DOWN]=false; break; case KeyEvent.VK_LEFT: KeyPress[LEFT]=false; break; case KeyEvent.VK_RIGHT: KeyPress[RIGHT]=false; break; case KeyEvent.VK_SPACE: KeyPress[SPACE]=false; spKeyRel = true; break; } } public void keyTyped(KeyEvent e) { } //================================================================== // MouseListener Method //================================================================== public void mouseClicked(MouseEvent e) { // マウスクリック if(phase == phTitle) { for(int i=0; i= 360.0) { vecTh -= 360.0; } } // 姿勢角減少(左回り) public void subVecTh(double th // 減少差分 ) { vecTh -= th; if(vecTh < 0.0) { vecTh += 360.0; } } // 指定方位へ加速 public void thrust(double th, // 加速方位 double v, // 加速量 double limV // 制限速度 ) { double vel2; vX += v * Math.cos(th * d2r); vY += v * Math.sin(th * d2r); vel2 = vX*vX+vY*vY; // 制限速度を超えた場合、速度の正規化を行う。 if(vel2 > limV*limV) { vX *= ((limV*limV) / vel2); vY *= ((limV*limV) / vel2); } } // 一定率加減速 public void reduce(double rate // 加減速率 ) { vX *= rate; vY *= rate; } // 移動処理 public void move() { // 姿勢角計算 vecTh += rotTh; if(vecTh >= 360.0) { vecTh -= 360.0; } if(vecTh < 0.0) { vecTh += 360.0; } // 位置計算 posX += vX; posY += vY; if(posX >= scrW) { posX -= scrW; } if(posX < 0.0) { posX += scrW; } if(posY >= scrH) { posY -= scrH; } if(posY < 0.0) { posY += scrH; } } }