前回までは
・画面の重力制御
・ボールの表示
・プレイヤーの移動&移動方向の補助線
今回はゲームクリア・ゲームオーバーの処理を実装したいと思います。
ゲームクリア/ゲームオーバー
まず初めに、ゲームクリアの定義ですが
・相手ゴールにボールを入れる。
単純ですね。
ただ、今のままだとボールに入ってもボールが跳ね返ってしまうので
ゴールの背中部分だけ壁をなくします。
ついでなので、ゴールポストも作っちゃいましょう。
[java]
MainScene.java
@Override
public void init() {
・・・省略・・・
final VertexBufferObjectManager vertexBufferObjectManager = getBaseActivity().getVertexBufferObjectManager();
final Rectangle ground1 = new Rectangle(0, camera.getHeight() – 2, 170, 2, vertexBufferObjectManager);
final Rectangle ground2 = new Rectangle((camera.getWidth() / 3) * 2, camera.getHeight() – 2, 307, 2, vertexBufferObjectManager);
final Rectangle ground3 = new Rectangle(170, camera.getHeight() – 40, 4, 40, vertexBufferObjectManager);
final Rectangle ground4 = new Rectangle(307, camera.getHeight() – 40, 4, 40, vertexBufferObjectManager);
final Rectangle roof1 = new Rectangle(0, 0, 170, 2, vertexBufferObjectManager);
final Rectangle roof2 = new Rectangle((camera.getWidth() / 3) * 2, 0,307, 2, vertexBufferObjectManager);
final Rectangle roof3 = new Rectangle(170, 0, 4, 40, vertexBufferObjectManager);
final Rectangle roof4 = new Rectangle(307, 0, 4, 40, vertexBufferObjectManager);
final Rectangle left = new Rectangle(0, 0, 2, camera.getHeight(), vertexBufferObjectManager);
final Rectangle right = new Rectangle(camera.getWidth() – 2, 0, 2, camera.getHeight(), vertexBufferObjectManager);
final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(0, 0.8f, 0.1f);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground1, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground2, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground3, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground4, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof1, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof2, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof3, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof4, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyDef.BodyType.StaticBody, wallFixtureDef);
PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyDef.BodyType.StaticBody, wallFixtureDef);
roof1.setColor(0, 0, 0);
roof2.setColor(0, 0, 0);
roof3.setColor(0, 0, 0);
roof4.setColor(0, 0, 0);
ground1.setColor(0, 0, 0);
ground2.setColor(0, 0, 0);
ground3.setColor(0, 0, 0);
ground4.setColor(0, 0, 0);
this.attachChild(ground1);
this.attachChild(ground2);
this.attachChild(ground3);
this.attachChild(ground4);
this.attachChild(roof1);
this.attachChild(roof2);
this.attachChild(roof3);
this.attachChild(roof4);
this.attachChild(left);
this.attachChild(right);
・・・省略・・・
}
[/java]
roof1/roof2でゴールポストの絵に合わせたゴール部分だけ開いた壁を作ります。
roof3/roof4で左右のゴールポスト部分の壁を作ります。
色は分かりやすいように一旦黒にしておきましょう。
>roof1.setColor(0, 0, 0);
※自分のゴールも同じようにします。
つづいてゲームクリアの判定処理です。
[java]
// アップデートハンドラー
TimerHandler timerHandler = new TimerHandler(1 / 60f, true, new ITimerCallback() {
public void onTimePassed(TimerHandler pTimerHandler) {
if(isEnd){
return;
}
if(-50 > ballSprite.getY()){
showGameClear();
}
if(camera.getHeight() + 50 < ballSprite.getY()){
showGameOver();
}
if(currentTime <= 0){
showGameOver();
}
}
});
[/java]
1秒間に60回処理するハンドラーを登録します。
ボールのスプライトのY座標が-50より小さい場合、ゲームクリアとします。
すなわち、画面上部にボールが隠れるくらい移動した場合です。
同じように、ゲームオーバー処理も実装します。
画面の高さ+50よりY座標が大きい場合、ゲームオーバーとします。
>if(currentTime <= 0)は制限時間が0になったら終了処理ですね。
制限時間のカウント処理を後述します。
このハンドラーをinit()メソッドで設定します。
>registerUpdateHandler(timerHandler);
ゲームの制限時間
[java]
private void countTime(){
if(isEnd){
return;
}
currentTime–;
currentTimeText.setText("Time " + currentTime);
currentTimeText.setColor(0,0,0);
if(currentTime <= 0){
return;
}
registerUpdateHandler(new TimerHandler(1, new ITimerCallback() {
public void onTimePassed(TimerHandler pTimerHandler) {
countTime();
}
}));
}
[/java]
1秒毎に、自分自身を呼び出すようにして、currentTimeを1ずつマイナスしていきます。
currentTimeをsetTextで画面に表示していくと、毎秒数字がマイナスされた値が表示されます。
このメソッドをinit()でよびだすようにします。
ゲームクリア/ゲームオーバーシーン
[java]
private void showGameClear(){
isEnd = true;
Text text = new Text(0, 0, font, "ゴーーーーーール!!", new TextOptions(HorizontalAlign.CENTER), getBaseActivity().getVertexBufferObjectManager());
text.setPosition((camera.getWidth() / 2) – (text.getWidth() / 2), (camera.getHeight() / 2) – (text.getHeight() / 2));
text.setColor(convertRGB(246),convertRGB(6),convertRGB(6));
attachChild(text);
text.registerEntityModifier(new ParallelEntityModifier(new ScaleModifier(3.0f, 0.1f, 1.5f), new RotationByModifier(2.0f, 360)));
physicsClear();
setEndButton();
}
private void showGameOver(){
isEnd = true;
Text text = new Text(0, 0, font, "ゲームオーバー!!", new TextOptions(HorizontalAlign.CENTER), getBaseActivity().getVertexBufferObjectManager());
text.setPosition((camera.getWidth() / 2) – (text.getWidth() / 2), (camera.getHeight() / 2) – (text.getHeight() / 2));
text.setColor(convertRGB(246),convertRGB(6),convertRGB(6));
attachChild(text);
text.registerEntityModifier(new ParallelEntityModifier(new ScaleModifier(3.0f, 0.1f, 1.5f), new RotationByModifier(2.0f, 360)));
physicsClear();
setEndButton();
}
private void setEndButton(){
ButtonSprite btnRetry = getBaseActivity().getResourceUtil()
.getButtonSprite("retry1.png", "retry1.png");
btnRetry.setPosition((camera.getWidth() / 2) – (btnRetry.getWidth() / 2), (camera.getHeight() / 2) + 50);
btnRetry.setTag(TAG_RETRY);
btnRetry.setOnClickListener(this);
attachChild(btnRetry);
registerTouchArea(btnRetry);
ButtonSprite btnMenu = getBaseActivity().getResourceUtil()
.getButtonSprite("stageSelect1.png", "stageSelect1.png");
btnMenu.setPosition((camera.getWidth() / 2) – (btnRetry.getWidth() / 2), (camera.getHeight() / 2) + 150);
btnMenu.setTag(TAG_STAGE);
btnMenu.setOnClickListener(this);
attachChild(btnMenu);
registerTouchArea(btnMenu);
}
private void physicsClear() {
Iterator<Body> localIterator = mPhysicsWorld.getBodies();
while (true) {
if (!localIterator.hasNext()) {
mPhysicsWorld.clearForces();
mPhysicsWorld.clearPhysicsConnectors();
mPhysicsWorld.reset();
return;
}
try {
final Body localBody = (Body) localIterator.next();
Sprite sprite = (Sprite) localBody.getUserData();
if(null == sprite){
continue;
}
sprite.detachSelf();
mPhysicsWorld.destroyBody(localBody);
} catch (Exception localException) {
Debug.e(localException);
}
}
}
public void onClick(ButtonSprite pButtonSprite, float pTouchAreaLocalX,
float pTouchAreaLocalY) {
//btnPressedSound.play();
switch (pButtonSprite.getTag()) {
case TAG_RETRY:
physicsAllClear();
MainScene mainScene = new MainScene(getBaseActivity(), camera, stage);
getBaseActivity().refreshRunningScene(mainScene);
break;
case TAG_STAGE:
physicsAllClear();
StageSelectScene stageSelectScene = new StageSelectScene(getBaseActivity());
getBaseActivity().refreshRunningScene(stageSelectScene);
break;
}
}
[/java]
>showGameClear
上記メソッドでisEndをtrueにします。
このフラグで、各処理でゲーム処理の判定をしているところをスキップするようにします。
それから、ゲームクリア時のメッセージを画面に表示します。
「ゴーーーーーール!!」回転しながら段々大きくなるように表示してます。
>physicsClear
画面に表示されているBodyや画像などをクリアしてます。
>setEndButton
ゲーム終了時の「リトライ」「ステージ選択」などの遷移用の画像を表示します。
※ステージ選択については今後記載します。
>onClick
各ボタンが押下された時の処理です。
リトライは、再度MainSceneをセットして起動します。
ステージは、ステージ選択画面のSceneをセットして起動します。
これで、ゲームクリア・ゲームオーバーの処理ができました!
次回はディフェンダー・キーパーの敵キャラを表示します。