月別: 2016年4月

シューティングゲーム開発_Vol2



前回の記事を見直したら、ソース記述しただけで
特に説明を記載してませんでした。。

すみません。

攻撃実装

今回は2機のミサイルと、ミサイルの移動を実装します。

■MainScene
[java]
@Override
public void init(){

・・・省略・・・

weponMainLeftSprite();
weponMainRightSprite();
registerUpdateHandler(timerHandler);

}

// ※2
TimerHandler timerHandler = new TimerHandler(1 / 60f, true, new ITimerCallback() {
public void onTimePassed(TimerHandler pTimerHandler) {
List<Rectangle> removeLeftWepon = new ArrayList<Rectangle>();
for(Rectangle rect : weponLeftList){
if(rect.getY() < -10){
removeLeftWepon.add(rect);
rect.detachSelf();
rect.dispose();
}else {
rect.setPosition(rect.getX(), rect.getY() – 3);
}
}
weponLeftList.removeAll(removeLeftWepon);

List<Rectangle> removeRightWepon = new ArrayList<Rectangle>();
for(Rectangle rect : weponRightList){
if(rect.getY() < -10){
removeRightWepon.add(rect);
rect.detachSelf();
rect.dispose();
}else {
rect.setPosition(rect.getX(), rect.getY() – 3);
}
}
weponRightList.removeAll(removeRightWepon);
}
});

// ※1
private void weponMainLeftSprite(){
mainLeftSprite.registerEntityModifier(new SequenceEntityModifier(
new DelayModifier(0.5f, new IEntityModifier.IEntityModifierListener() {
@Override
public void onModifierFinished(
IModifier<IEntity> pModifier, IEntity pItem) {

final Rectangle rect = new Rectangle(mainLeftSprite.getX() + mainLeftSprite.getWidth(), mainLeftSprite.getY(), 5, 5, getBaseActivity().getVertexBufferObjectManager());
attachChild(rect);

rect.setColor(convertRGB(200), convertRGB(200), convertRGB(200));
rect.setPosition(mainLeftSprite.getX() + mainLeftSprite.getWidth() / 2, mainLeftSprite.getY());
rect.setZIndex(10);

weponLeftList.add(rect);

weponMainLeftSprite();
}

@Override
public void onModifierStarted(IModifier<IEntity> pModifier,
IEntity pItem) {
}
})));
}

private void weponMainRightSprite(){
mainRightSprite.registerEntityModifier(new SequenceEntityModifier(
new DelayModifier(0.5f, new IEntityModifier.IEntityModifierListener() {
@Override
public void onModifierFinished(
IModifier<IEntity> pModifier, IEntity pItem) {

final Rectangle rect = new Rectangle(mainRightSprite.getX() + mainRightSprite.getWidth(), mainRightSprite.getY(), 5, 5, getBaseActivity().getVertexBufferObjectManager());
attachChild(rect);

rect.setColor(convertRGB(200), convertRGB(200), convertRGB(200));
rect.setPosition(mainRightSprite.getX() + mainRightSprite.getWidth() / 2, mainRightSprite.getY());
rect.setZIndex(10);

weponRightList.add(rect);

weponMainRightSprite();
}

@Override
public void onModifierStarted(IModifier<IEntity> pModifier,
IEntity pItem) {
}
})));
}

private float convertRGB(int val){
return val / 255f;
}

[/java]

■説明!!
※1
initメソッドからweponMainLeftSprite / weponMainRightSpriteを呼び出します。
weponMainLeftSpriteメソッドで、
・mainLeftSprite.registerEntityModifier(Spriteへの変更処理を設定します。)
・SequenceEntityModifier(指定した変更処理を順番に処理するように設定します。)
・DelayModifier(0.5f, new IEntityModifier.IEntityModifierListener(0.5秒たってからメソッド内の処理をするように設定します。)

// 5dp四方の画像を描画します。
final Rectangle rect = new Rectangle(mainLeftSprite.getX() + mainLeftSprite.getWidth(), mainLeftSprite.getY(), 5, 5, getBaseActivity().getVertexBufferObjectManager());
attachChild(rect);

// 色を指定
rect.setColor(convertRGB(200), convertRGB(200), convertRGB(200));

// ポジションの指定をします。
// 【mainLeftSprite.getX() + mainLeftSprite.getWidth() / 2】でSpriteのX座標の中央値を指定します。
rect.setPosition(mainLeftSprite.getX() + mainLeftSprite.getWidth() / 2, mainLeftSprite.getY());
rect.setZIndex(10);

// 機体のミサイルをリストで保持します。(ミサイルの画像を移動するのに使用します。)
weponLeftList.add(rect);

// 再帰的に呼び出して常に0.5秒事にミサイルを発射するようにする。
weponMainLeftSprite();

※2
initメソッドからtimerHandlerをregisterUpdateHandlerにセットして毎秒60回(1 / 60f)呼び出すようにします。
ここのメソッドで敵(未実装)の移動やミサイルの移動、あたり判定を行う予定です。

[java]
// 削除用のリストを用意(for文で回している最中に要素を削除するとエラーとなるので削除対象を保持する)
List<Rectangle> removeLeftWepon = new ArrayList<Rectangle>();

// 左機のミサイルを移動する。画面から外れたミサイルは削除する。
for(Rectangle rect : weponLeftList){
// 画面上部から-10のところまでミサイルがきたら不要なので、削除用リストに保持
if(rect.getY() < -10){
removeLeftWepon.add(rect);
// 画像をクリア
rect.detachSelf();
rect.dispose();
}else {
// 画像を移動する。上方向に-3の速度で移動
rect.setPosition(rect.getX(), rect.getY() – 3);
}
}
// 削除対象をリストから除去
weponLeftList.removeAll(removeLeftWepon);
[/java]

■上記の処理をすると2機からミサイルが発射されます!

こんな感じ
wepon

次回は自動で発射されるミサイルの一時停止と必殺ボタンを実装したいと思います。

{ Add a Comment }

第2弾、第3弾避けゲーリリース!



会社の勉強会で開発していたAndengineというゲームエンジンを利用して作成したゲーム。

リリースしましたー!

■よけろ!ききいっぱつ!
こちら2016/01から開発を開始して、2016/4にようやく完了しました!
基本的には「AndEngineでつくるAndroid 2Dゲーム」という参考書に記載のある技術のみで
完結しています。

■よけろ!かんいっぱつ!
これは「よけろ!ききいっぱつ!」がほぼ完成してから着手しました。
ベースのアプリを改造して開発したので、約10時間程度でできたと思います。

やっぱり1本ゲームアプリを作ると色々と感覚がつかめてきて
「こうしたい!」と思ったときに「じゃあこうすればいいかなー」と色々と考えれるので
まずは地道に小さいアプリから作ってみるのがアプリ開発を学ぶ近道かなと感じました。

いきなり凝ったアプリを開発しようと思うと、途中で行き詰ったりして
モチベーションがあがらずに結局完成しないという事になりかねないですね。

私も普段アプリの妄想してて、かなり凝ったイメージがあるのですが
それは追々頑張ってみようと思います。

みなさん暇つぶしにGoogle Playでダウンロードしてみてください。

でわでわ!

{ Add a Comment }

シューティングゲーム開発_Vol1



傾きセンサーを使用した2つのゲームは、ほぼ作り終えたので。
次はシューティングゲームを作ってみようと思います!

タイトルは
【ツインスペースヒーロー!!】

Andengineの「AnalogOnScreenControl」を2つ配置して

二つの機体を同時に操作するシューティングです。
今回はコントローラの配置します。
※ここで記載する内容は「AndEngineでつくるAndroid 2Dゲーム」の参考書の
プロジェクト構成を前提としています。

[java]
public class MainActivity extends MultiSceneActivity implements
SensorEventListener {

// 画面のサイズ。
private int CAMERA_WIDTH = 800;
private int CAMERA_HEIGHT = 480;

public static Camera camera;

public EngineOptions onCreateEngineOptions() {
this.camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

EngineOptions eo = new EngineOptions(true,
ScreenOrientation.LANDSCAPE_FIXED,
new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);

// ふたつコントローラを使用するのでマルチタッチの設定をする。
eo.getTouchOptions().setNeedsMultiTouch(true);
}
}

public class MainScene extends KeyListenScene implements
ButtonSprite.OnClickListener {
private BitmapTextureAtlas mOnScreenControlTexture;
private ITextureRegion mOnScreenControlBaseTextureRegion;
private ITextureRegion mOnScreenControlKnobTextureRegion;

private AnimatedSprite mainLeftSprite;
private AnimatedSprite mainRightSprite;

@Override
public void init(){
// 背景設定
setBackground(new Background(convertRGB(0), convertRGB(0), convertRGB(0)));

// 左側のコントローラエリア作成
final Rectangle rect = new Rectangle(0, 0, 150, 480, getBaseActivity().getVertexBufferObjectManager());
attachChild(rect);

rect.setColor(convertRGB(50), convertRGB(50), convertRGB(50));
rect.setPosition(0, 0);
rect.setZIndex(controlAreaZIndex);
sortChildren();

// 右側のコントローラエリア作成
final Rectangle rect2 = new Rectangle(700, 0, 150, 480, getBaseActivity().getVertexBufferObjectManager());
attachChild(rect2);

rect2.setColor(convertRGB(50), convertRGB(50), convertRGB(50));
rect2.setPosition(650, 0);
rect2.setZIndex(controlAreaZIndex);
sortChildren();

// コントローラの画像登録
this.mOnScreenControlTexture = new BitmapTextureAtlas(getBaseActivity().getTextureManager(), 256, 128, TextureOptions.BILINEAR);
this.mOnScreenControlBaseTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, getBaseActivity(), "onscreen_control_base.png", 0, 0);
this.mOnScreenControlKnobTextureRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(this.mOnScreenControlTexture, getBaseActivity(), "onscreen_control_knob.png", 128, 0);
this.mOnScreenControlTexture.load();

// コントローラ描画メソッド
drawAnalogControls();
}

// コントローラとコントローラの操作対象の機体を描画
private void drawAnalogControls(){

// 左の機体を描画
mainLeftSprite = getBaseActivity().getResourceUtil().getAnimatedSprite("main1.png", 1, 2);
mainLeftSprite.setZIndex(mainZIndex);
mainLeftSprite.setPosition(200, 450);

attachChild(mainLeftSprite);

// 左の機体操作用のハンドラー
final PhysicsHandler physicsHandler1 = new PhysicsHandler(mainLeftSprite);
mainLeftSprite.registerUpdateHandler(physicsHandler1);

// 右の機体を描画
mainRightSprite = getBaseActivity().getResourceUtil().getAnimatedSprite("main2.png",1,2);
mainRightSprite.setZIndex(mainZIndex);
mainRightSprite.setPosition(600, 450);

attachChild(mainRightSprite);

// 右の機体操作用のハンドラー
final PhysicsHandler physicsHandler2 = new PhysicsHandler(mainRightSprite);
mainRightSprite.registerUpdateHandler(physicsHandler2);

sortChildren();

// leftControl
final float x1 = 20;
final float y1 = getBaseActivity().getEngine().getCamera().getHeight() – this.mOnScreenControlBaseTextureRegion.getHeight() – 30;
final AnalogOnScreenControl leftControl = new AnalogOnScreenControl(x1, y1, MainActivity.camera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, getBaseActivity().getVertexBufferObjectManager(), new AnalogOnScreenControl.IAnalogOnScreenControlListener() {
@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {

// 機体の移動制限
System.out.println("mainLeftSprite:" + mainLeftSprite.getX() + "/" + mainLeftSprite.getY());
boolean backMove = false;
if(mainLeftSprite.getX() &lt; 155) {
physicsHandler1.setVelocity(50, 0);
backMove = true;
}
if(645 &lt; mainLeftSprite.getX() + mainLeftSprite.getWidth()){
physicsHandler1.setVelocity(-50, 0);
backMove = true;
}
if(mainLeftSprite.getY() &lt; 5) {
physicsHandler1.setVelocity(0, 50);
backMove = true;
}
if(475 &lt; mainLeftSprite.getY() + mainLeftSprite.getHeight()){
physicsHandler1.setVelocity(0, -50);
backMove = true;
}

// 機体の移動
if(!backMove){
physicsHandler1.setVelocity(pValueX * 100, pValueY * 100);
}
}

@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
/* Nothing. */
}
});
leftControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
leftControl.getControlBase().setAlpha(0.5f);

this.setChildScene(leftControl);

// rightControl
final float y2 = y1;
final float x2 = getBaseActivity().getEngine().getCamera().getWidth() – this.mOnScreenControlBaseTextureRegion.getWidth() – 20;
final AnalogOnScreenControl rightControl = new AnalogOnScreenControl(x2, y2, MainActivity.camera, this.mOnScreenControlBaseTextureRegion, this.mOnScreenControlKnobTextureRegion, 0.1f, getBaseActivity().getVertexBufferObjectManager(), new AnalogOnScreenControl.IAnalogOnScreenControlListener() {
@Override
public void onControlChange(final BaseOnScreenControl pBaseOnScreenControl, final float pValueX, final float pValueY) {
System.out.println("mainRightSprite:" + mainRightSprite.getX() + "/" + mainRightSprite.getY());
boolean backMove = false;
if(mainRightSprite.getX() &lt; 155) {
physicsHandler2.setVelocity(50, 0);
backMove = true;
}
if(645 &lt; mainRightSprite.getX() + mainRightSprite.getWidth()){
physicsHandler2.setVelocity(-50, 0);
backMove = true;
}
if(mainRightSprite.getY() &lt; 5) {
physicsHandler2.setVelocity(0, 50);
backMove = true;
}
if(475 &lt; mainRightSprite.getY() + mainRightSprite.getHeight()){
physicsHandler2.setVelocity(0, -50);
backMove = true;
}
if(!backMove){
physicsHandler2.setVelocity(pValueX * 100, pValueY * 100);
}
}

@Override
public void onControlClick(final AnalogOnScreenControl pAnalogOnScreenControl) {
/* Nothing. */
}
});
rightControl.getControlBase().setBlendFunction(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);
rightControl.getControlBase().setAlpha(0.5f);

leftControl.setChildScene(rightControl);
}

private float convertRGB(int val){
return val / 255f;
}
}

[/java]

vol5_2

※重要な部分のみコード記載してますので、変数宣言とか一部抜けているかも知れませんがご了承。。

次回以降も随時シューティングゲームの途中経過を記載していきます!

{ Add a Comment }

ゲームエンジン(Andengine)について



文字通り3日坊主でサボってました。
浅野です。

子供達の進級・卒園・入学などでバタバタしてまして。。
と言い訳しておきます。

さて、今日はAndengineというスマホアプリのゲームエンジンの話をします。

ゲーム(スマホアプリ)を作成するにはゲームエンジンを使用すると格段と効率がよくなります。
ゲーム中でよく使用する機能をゲームエンジンが吸収してくれるのでとても助かりますね。
(音楽・画像表示・画像移動などなど)

スマホのゲームエンジンというと、私がパッと思いつくのが以下4つ。
・Unity(C#,Unityscript)
・Cocos2dx(C++)
・Andengine(Java)
・enchant.js(Javascript)

Unity・Cocos2dx・enchant.jsなんかはマルチプラットフォーム対応しているので
魅力的ですね。

ただ、私は普段仕事でJavaを使用しているので、できればJavaを使用したゲームエンジンを探して
Andengineにたどり着きました。
(UnityはC#で開発できるので、割とすんなり馴染めるかと思いますが、まずはAndengineで。)

Andengineで勉強・開発をスムーズにする上で必要なものが3つあります。
1.給料袋
2.堪忍袋
3.お袋



すいませんウソですw

ホントは下記です。
1.参考書(AndEngineでつくるAndroid 2Dゲーム)
2.サンプルアプリ(AndEngine Examples)
3.サンプルソース(AndEngine Examples)

【1.参考書(AndEngineでつくるAndroid 2Dゲーム)】
こちら非常に分かりやすいです。
別に参考書の宣伝をするわけじゃないので、詳細は省きますが
サンプルアプリを3つほど作りながら勉強できます。

私の場合は、適当に流し読みして、本の出版元から
完成したサンプルアプリをDLして、Android Studioで動くようにしました。
実際に動くアプリとソースを用意して、動作の確認&ソースを変えた時の挙動を確認して勉強しました。

【2.サンプルアプリ(AndEngine Examples)】
Google PlayでAndengineのサンプルアプリ集をDLできます。(Google PlayでAndEngine Examplesで検索)
実際にどういうことができるかをサンプルを見て確認し、
じゃあ自分はどういうアプリを作ろうかというのをイメージしました。
※「3.」のソースより若干古いアプリになってますが、まぁ別に支障はないでしょう。
気になるようでしたら、ソースをDLしてAndroid Studioで動かせるようにして確認してみるといいかも。

【3.サンプルソース(AndEngine Examples)】
「2.」でサンプルアプリを確認して、自分が使いたい機能があれば、実際にソースを確認します。
非常にたくさんのサンプルがあるので、必ず役に立つと思います。
(WEBでAndEngine Examplesで検索)

私も現在、「1.」のサンプルアプリの「ゾンビから逃げるゲーム」を参考に
二つほどゲームを作成してます。
(近日公開)

Andengineで勉強してみて、思ったことは(Andengineに限らずですが)
いくら本や、参考サイトをみても、実際に自分でアプリを実装しないと理解できません!

百聞は一見にしかず
百見は一触にしかず

ってことでみなさんバンバンAndengine触っていきましょー

今後はAndengineの実装についてちょこちょこ触れていきます。

{ Add a Comment }