概要概要
Javaを使用して実店舗のゲームを実装します。ゲームインターフェイスには次の要素が含まれます
- 上部にさまざまな色のレンガ
- ボトムバッフル
- 小さなボール
- ゲーム情報表示パネル
- ゲームプレイには
マウスまたはキーボードを使用してベゼルを移動します
- レンガを分解し、ポイントを獲得する
- 各ラウンドに3つのチャンスがあり、バッフルが小さなボールを受け取らなかった場合、チャンスは1つ減ります。
- 黒いボールがノックアウトされると小道具が落とされ、バッフルが小道具を受け取るとバッフルが長くなります
- ゲームの難易度を選択できます
機能実現
まず、クラス全体がGraphicsProgramから継承されます。プログラムの開始後、最初にinit()メソッドが実行され、次にrun()メソッドが実行されます。
public class Arkanoid extends GraphicsProgram
{
public void init()
{
// 进行初始化
}
public void run()
{
// 具体执行
}
}
次に、init()で、ゲームインターフェイスを作成します。
レンガを作成する
ブリックを作成する前に、色と対応するスコアを格納するコンテナを準備します。ここでは、マップによって実現されます。キーはColorオブジェクトを保存し、値はスコアを保存します。
Map<Color,Integer> brickColors;
colors=new Color[]{
Color.BLACK,Color.BLUE,Color.CYAN,Color.DARK_GRAY,Color.GRAY,Color.GREEN,
Color.LIGHT_GRAY,Color.MAGENTA,Color.ORANGE,Color.PINK,Color.RED,Color.YELLOW
};
brickColors=new HashMap<>();
for(int i=0;i<colors.length;i++)
{
Color color=colors[i];
// 黑色砖块是特殊砖块,打掉不得分,但是可以掉落胶囊
if(color.getRGB() == Color.BLACK.getRGB())
{
brickColors.put(color,0);
}
else
{
brickColors.put(color,colors.length%(i+1)+1);
}
}
ブリックカラーを使用して、次のステップは指定された行と列のブリックを作成することです。ここでは、GRectを使用してブリックを表します。
注意すべき点の1つは、GRectにはデフォルトで1ピクセルの境界線があることです。これを削除しない場合は、レンガの幅を計算するときにこの1ピクセルを考慮する必要があります。
final int ROWS=6;
final int COLUMNS=12;
// 砖块实心部分的宽,高
brickW=GAME_PANE_WIDTH/COLUMNS;
brickH=brickW/2;
for(int i=0;i<ROWS;i++)
{
for(int j=0;j<COLUMNS;j++)
{
GRect brick=new GRect(brickW,brickH);
brick.setFilled(true);
brick.setColor(colors[randomGenerator.nextInt(0,brickColors.size()-1)]);
brick.setLineWidth(0);
double x=j*brickW;
double y=i*brickH;
add(brick,x,y);
}
}
バッフルとボールを作成する
バッフルとボールを作成し、それぞれGRectとGOvalを使用して、適切な位置に追加します。
ゲーム情報表示パネルを作成する
ゲーム情報表示パネルでは、ゲームで実装する機能に応じて情報を表示するパネルを追加することができます。
ここでは、[ゲームチャンス] [スコア] [ゲームの難易度] [もう1つのゲーム]などのパネルを作成します。
最も外側はJPanelを使用して作成され、レイアウト方法はGirdLayoutであり、各アイテムをそれに追加できます。
マウスまたはキーボードを使用して、ベゼルの動きを制御します
バッフルをマウスと一緒に動かす機能を実現するには、ゲームインターフェイスの最も外側のコンポーネントにマウスリスナーを直接追加する必要があります。
メソッドaddMouseListeners()を呼び出してから、mouseMoved(MouseEvent)メソッドをオーバーライドします。このメソッドでは、バッフルの位置をマウスの位置に応じて設定できます。バッフルの移動範囲を制限し、ゲームインターフェイスを超えないように注意してください。
addMouseListeners();
public void mouseMoved(MouseEvent e)
{
if(gameover) // 游戏结束,恢复挡板在底部正中央
{
paddle.setLocation(GAME_PANE_WIDTH/2.-paddle.getWidth()/2,GAME_PANE_HEIGHT-paddle.getHeight()-30);
}
else // 游戏运行中,动态改变挡板水平方向的位置
{
//paddle.setLocation(e.getX()-PADDLE_W/2,e.getY()-PADDLE_H/2);
// 限制挡板左侧和右侧不能超出游戏界面的范围
double x=e.getX()-paddle.getWidth()/2;
if(x<0)
{
x=0;
}
if(x>GAME_PANE_WIDTH-paddle.getWidth())
{
x=GAME_PANE_WIDTH-paddle.getWidth();
}
paddle.setLocation(x,paddle.getY());
}
}
マウスを使用するのと同様に、キーボードを使用してバッフルの動きを操作するには、キーイベントリスナーも必要です。
addKeyListeners();
@Override
public void keyTyped(KeyEvent e)
{
double x=paddle.getX();
char keyChar=e.getKeyChar();
if(keyChar == '1') // 左移
{
x-=paddle.getWidth()*1.5;
if(x<=0)
{
x=0;
}
}
else if(keyChar == '2') // 右移
{
x+=paddle.getWidth()*1.5;
if(x>GAME_PANE_WIDTH-paddle.getWidth())
{
x=GAME_PANE_WIDTH-paddle.getWidth();
}
}
paddle.setLocation(x,paddle.getY());
}
動くボール
ボールを動かすには、ゲームが終了していない限り、ループ内にいる必要があります。常にmove()を呼び出すだけです。
ゲームを開始する前に、ボールに初期移動速度を与える必要があり、速度は毎回異なります。
VELOCITY_X=3;
VELOCITY_Y=5;
boolean gameover=false;
public void init()
{
int offset=randomGenerator.nextInt(0,3);
vx=VELOCITY_X+offset; // 水平速度
vy=-(VELOCITY_Y+offset); // 竖直速度
}
public void run()
{
while(!gameover)
{
ball.move(vx,vy);
pause(DELAY);
}
}
ボールが壁に当たったかどうかを検出します
ゲームインターフェイスの幅と高さ、およびボールの現在の座標に従って、ボールが壁に当たるかどうかを判断するために、ボールがゲームインターフェイスの境界に接触するかどうかを判断します。
ボールが上壁または下壁に当たるとy方向の速度が逆になり、左壁または右壁に当たるとx方向の速度が逆になります。
コードは次のようになります
if(hitBottomWall() || hitTopWall())
{
vy=-vy;
}
if(hitLeftWall() || hitRightWall())
{
vx=-vx;
}
ボールがレンガに当たって跳ね返ると、レンガが消えます
まず、レンガをボールにぶつけます。
4つの頂点を検出する必要があります。ここではサンプルコードのみを示します。
GObject getCollidingObject()
{
GObject element=getElementAt(x,y);
if(element!=null)
return element;
return null;
}
次に、ボールがレンガに当たる場所に応じてボールの軌道を変更します
レンガは、4つの側面から伸びる線に従って、その周りの8つの領域に分割できます。
- まっすぐ上、まっすぐ下
- 正の左、正の右
- 左上、左下、右上、右下
ボールの中心が上部または下部の領域にある場合は、y方向の速度を取ります。
ボールの中心が正の左または右の領域にある場合は、x方向の速度を取ります。
ボールの中心が別の領域にある場合、それはボールがレンガの4つの頂点に正確に当たることを意味し、x方向とy方向の速度が同時に逆になります。
boolean changeX=false;
boolean changeY=false;
private void changeXY(GObject element,double center_x,double center_y)
{
double left_brick=element.getX();
double top_brick=element.getY();
double right_brick=left_brick+brickW;
double bottom_brick=top_brick+brickH;
if(center_y>top_brick && center_y<bottom_brick) // 小球在砖块的左侧,或右侧
{
changeX=true;
}
else if(center_x>left_brick && center_x<right_brick) // 小球在砖块的上侧,或xia侧
{
changeY=true;
}
else // 小球在砖块的4个顶点范围
{
changeX=true;
changeY=true;
}
}
最後に、runメソッドで、変数changeXとchangeYに従ってvxとvyを変更します。
GObject element=getCollidingObject();
if(element != null)
{
if(element == paddle) // 如果打到挡板,反弹
{
vy=-vy;
// 加一下速
if(vx>0)
vx+=va;
else
vx-=va;
if(vy>0)
vy+=va;
else
vy-=va;
continue;
}
else
{
if(changeX)
vx=-vx;
if(changeY)
vy=-vy;
remove(element);
}
}
スコア
レンガを打つときは、レンガの色に応じた色に対応するスコアを取得し、スコアに追加するだけです。
GObject element=getCollidingObject();
if(element != null)
{
Color color=element.getColor();
int point=brickColors.get(color);
score+=point;
scoreLabel_num.setText(""+score);
}
小道具を落とし、小道具を受け取り、バッフルが長くなります
黒いレンガを叩くと、レンガの下に小道具が表示され、垂直に落下します。小道具が下の壁に落ちる前にバッフルを使用して小道具に接続すると、バッフルが長くなります。
まず、ドロップされたアイテムを格納する配列リストを定義します。
黒レンガを叩いた後、小道具を作成してコンテナに追加します。
最後に、コンテナ内の小道具を「落下」させます。
バッフルが小道具を受け取った場合は、そのサイズをリセットします。
ArrayList<GImage> falls;
if(color.getRGB() == Color.BLACK.getRGB())// 如果是黑砖块,落下道具
{
Toolkit toolkit=Toolkit.getDefaultToolkit();
Image image=toolkit.createImage("fall.png");
GImage fall=new GImage(image);
fall.setSize(PADDLE_W,PADDLE_W);
add(fall,element.getX(),element.getY());
falls.add(fall);
}
for(GImage fall:falls)
{
if(fall != null)
{
fall.move(0,5);
// 接到了道具
if(Math.abs(paddle.getY()-fall.getY()-fall.getHeight())<=0.1 && (Math.abs(fall.getX()-paddle.getX())<=paddle.getWidth()-0.1))
{
remove(fall);
double newWidth=paddle.getWidth()*1.5;
if(newWidth>=GAME_PANE_WIDTH)
{
newWidth=GAME_PANE_WIDTH;
}
paddle.setSize(newWidth,paddle.getHeight());
}
}
}
ゲームの難易度を設定する
ここでの難しさは、ボールがバッフルから跳ね返るときにボールの速度を上げることです。加速度の大きさによって、
3つの難易度レベルに分けられます:[簡単] [一般] [難しい]。
3つのラジオボタンを作成し、それらのモニターを設定し、それらが選択されたときに加速範囲を変更します
double va=0;
JRadioButton simpleBtn=new JRadioButton("简单",true);
JRadioButton middleBtn=new JRadioButton("一般");
JRadioButton diffcultyBtn=new JRadioButton("困难");
simpleBtn.addActionListener(e ->
{
va=0;
});
middleBtn.addActionListener(e ->
{
va=1;
});
diffcultyBtn.addActionListener(e ->
{
va=2;
});
次に、runメソッドで、vx、vyに加速度を追加します
if(element == paddle) // 如果打到挡板,反弹
{
vy=-vy;
// 加一下速
if(vx>0)
vx+=va;
else
vx-=va;
if(vy>0)
vy+=va;
else
vy-=va;
}