さて、今回は自機のライフを設定して
ライフがなくなったらゲームオーバーとなる処理を実装します。

あと、敵のミサイルの弾道が直線だけなので、たまに自機のいる位置に攻撃するような弾道とします。

自機ライフ&ゲームオーバー処理

ライフ表示用のメソッドを用意します。
[java]
MainScene.java

private int mainLeftLife = 3;
private int mainRightLife = 3;

private Text mainLeftLifeText;
private Text mainRightLifeText;

@Override
public void init() {

font = FontFactory.create(getBaseActivity().getFontManager(), getBaseActivity().getTextureManager(), 256, 256, Typeface.create(Typeface.DEFAULT, Typeface.BOLD), 32, true, Color.WHITE);
font.load();

showLife(true);

・・・省略・・・
}

private void showLife(boolean initFlag){
if(initFlag){
Sprite leftLifeImage = getBaseActivity().getResourceUtil().getSprite("life.png");
leftLifeImage.setPosition(50 – (leftLifeImage.getWidth() / 2), 50 – (leftLifeImage.getHeight() / 2));
leftLifeImage.setZIndex(controlAreaZIndex + 10);
attachChild(leftLifeImage);

Sprite rightLifeImage = getBaseActivity().getResourceUtil().getSprite("life.png");
rightLifeImage.setPosition(700 – (rightLifeImage.getWidth() / 2), 50 – (rightLifeImage.getHeight() / 2));
rightLifeImage.setZIndex(controlAreaZIndex + 10);
attachChild(rightLifeImage);
}

if(null != mainLeftLifeText) {
mainLeftLifeText.detachSelf();
}
mainLeftLifeText = new Text(0, 0, font, " x " + String.valueOf(mainLeftLife), new TextOptions(HorizontalAlign.CENTER), getBaseActivity().getVertexBufferObjectManager());
mainLeftLifeText.setPosition(80 – (mainLeftLifeText.getWidth() / 2), 50 – (mainLeftLifeText.getHeight() / 2));
mainLeftLifeText.setZIndex(controlAreaZIndex + 10);
mainLeftLifeText.setScale(0.7f);
mainLeftLifeText.setColor(CommonUtil.convertRGB(255), CommonUtil.convertRGB(255), CommonUtil.convertRGB(255));
attachChild(mainLeftLifeText);

if(null != mainRightLifeText) {
mainRightLifeText.detachSelf();
}
mainRightLifeText = new Text(0, 0, font, " x " + String.valueOf(mainRightLife), new TextOptions(HorizontalAlign.CENTER), getBaseActivity().getVertexBufferObjectManager());
mainRightLifeText.setPosition(730 – (mainLeftLifeText.getWidth() / 2), 50 – (mainLeftLifeText.getHeight() / 2));
mainRightLifeText.setZIndex(controlAreaZIndex + 10);
mainRightLifeText.setScale(0.7f);
mainRightLifeText.setColor(CommonUtil.convertRGB(255), CommonUtil.convertRGB(255), CommonUtil.convertRGB(255));
attachChild(mainRightLifeText);

}
[/java]

val5_6

ライフ画像の横に「x3」のようにライフが表示されました。
単に画像と文字を画面に表示しているだけです。
引数がtrueの場合だけ、ライフ画像の表示をします。

[java]
MainScene.java

private void crashLeftMain() {

if(0 == mainLeftLife){
showGameOver();
return;
}

mainLeftLife = mainLeftLife – 1;
showLife(false);

・・・省略・・・
}

private void showGameOver() {

// 敵スプライトのModifireをクリアする。
for(Enemy enemy : enemyList){
enemy.getEnemySprite().clearEntityModifiers();
}

// ゲームオーバー画面の背景画像
Text text = new Text(0, 0, font, "ゲームオーバー", new TextOptions(HorizontalAlign.CENTER), getBaseActivity().getVertexBufferObjectManager());
text.setPosition(camera.getWidth() / 2 – text.getWidth() / 2, -text.getHeight() -20);
text.setScale(2f);
text.setColor(CommonUtil.convertRGB(255), CommonUtil.convertRGB(255), CommonUtil.convertRGB(255));
attachChild(text);

sortChildren();

text.registerEntityModifier(new SequenceEntityModifier(
new DelayModifier(1.0f), new MoveModifier(3.0f,
text.getX(), text.getX(), text.getY(), camera.getHeight() / 2 – text.getHeight() / 2,
EaseQuadOut.getInstance())));
}
[/java]
自機がクラッシュした際に、showLifeを呼び出して再度ライフ文字の表示を行います。
ライフが0になった場合にshowGameOverを呼び出します。

ゲームオーバーの文字を表示します。

val5_7

敵のミサイルの弾道

現在はEnemyクラスにミサイルの弾道を一つだけ保持していて
ミサイル毎の弾道を定義できないので、ミサイルと弾道をセットで
保持できるようにクラスを生成します。

[java]
package org.geex.twinspacehero.enemy;

import java.awt.Rectangle;

public class EnemyWepon {

private Rectangle weponSprite;

private float moveWeponX = 0f;
private float moveWeponY = 0f;

public Rectangle getWeponSprite() {
return weponSprite;
}

public void setWeponSprite(Rectangle weponSprite) {
this.weponSprite = weponSprite;
}

public float getMoveWeponX() {
return moveWeponX;
}

public void setMoveWeponX(float moveWeponX) {
this.moveWeponX = moveWeponX;
}

public float getMoveWeponY() {
return moveWeponY;
}

public void setMoveWeponY(float moveWeponY) {
this.moveWeponY = moveWeponY;
}
}
[/java]
weponSprite:ミサイルの画像
moveWeponX:X座標の弾道
moveWeponY:Y座標の弾道

[java]
Enemy.java

private List<EnemyWepon> weponList = new ArrayList<EnemyWepon>();

public void setWeponType(Rectangle rect){
rect.setZIndex(-10);
rect.setColor(CommonUtil.convertRGB(200), CommonUtil.convertRGB(200), CommonUtil.convertRGB(200));
rect.setPosition(enemySprite.getX() + enemySprite.getWidth() / 2, enemySprite.getY() + enemySprite.getHeight());

Sprite targetMainSprite;

float x = 0;
float y = 1;
int randam = (int) (Math.random() * 10);
// ※1
if(5 < randam){
int randam2 = (int) (Math.random() * 10);

if(5 < randam2){
targetMainSprite = mainLeftSprite;
}else{
targetMainSprite = mainRightSprite;
}

// ※2
float[] firstXY = {rect.getX() + rect.getWidth() / 2, rect.getY() + rect.getHeight()};
float[] secondXY = {targetMainSprite.getX() + targetMainSprite.getWidth() / 2, targetMainSprite.getY()};

double angle = getAngleByTwoPosition(firstXY, secondXY);

// 移動距離と角度からx方向、y方向の移動量を求める
double distance = getDistanceTwoPosition(firstXY, secondXY) * 0.02f;

x = -(float) (distance * Math
.cos(angle * Math.PI / 180.0));
y = -(float) (distance * Math
.sin(angle * Math.PI / 180.0));
}

EnemyWepon enemyWepon = new EnemyWepon();
enemyWepon.setWeponSprite(rect);
enemyWepon.setMoveWeponX((x / y));
enemyWepon.setMoveWeponY(1);

weponList.add(enemyWepon);
}
[/java]
※1.半分の確立で、自機に向かってミサイルを発射するようにします。
更に半分の確立で、どちらの自機に対してミサイルを発射するかを決めています。

※2.よくやる計算ですね。
2点の座標から角度を元に移動距離を求めます。

>enemyWepon.setMoveWeponX((x / y));
>enemyWepon.setMoveWeponY(1);
更に、Y軸を1固定とするので、計算結果をxをY:1に対応する値に計算します。

上記のEnemyの変更箇所に合わせて、MainSceneを変更すれば、
敵のミサイル毎に弾道を設定できるようになります。

val5_8

次回は、ボスとゲームクリア、できればアイテムの実装などをしたいと思います。