Android環境におけるシューティングゲームの開発

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
太陽
記事: 4
登録日時: 9年前
住所: 地球

Android環境におけるシューティングゲームの開発

#1

投稿記事 by 太陽 » 9年前

初めまして。
Android環境におけるシューティングゲームについて質問です。
プログラミング歴は一年にも満たない初心者です。

現在、大学でAndroidアプリの開発をしており
私自身、四聖龍神禄のようなシューティングゲームを
Androidで開発しようと躍起になっているのですが、
自機の弾の描画が上手くいかなくて苦しんでおります。

私自身は何の入力をしていなくても、自機から前方向(上方向)に
連続的な弾が描画されるプログラムを作成したいのですが、
このプログラムでは、弾が勝手に前方向に進んでしまい、
更に弾が重なって?しまいます。

どのようにすれば等間隔な連続的な弾が描画されるのか
また、なにもしなくても弾が描画されるようになるのか教えて下さい。

一週間くらい悩んでいるのですが、一向に解決の糸口がつかめません。
どうかご教授お願いします!!!

HyperMotion2D.java

コード:

package com.hypermotion2d;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.roxiga.hypermotion2d.Sprite2D;

import android.content.Context;
import android.media.MediaPlayer;
import android.opengl.GLSurfaceView;
import android.view.SurfaceHolder;

public class HyperMotion2D implements GLSurfaceView.Renderer {
	
	//コンテキスト
	private Context _context;
	//高さ、幅
	public int _width,_height;
	//タッチしたのかを識別
	public boolean _touch;
	//タッチしたかの識別
	//弾を発射するかどうか
	public boolean _touchEvent = false;
	//現在押している座標
	private float _xPos,_yPos; 
	public boolean[] _flagOneBullet = new boolean[20];
	
	//create
    private Sprite2D _title = new Sprite2D();
    private Sprite2D _earth = new Sprite2D();
    
    //画面制御
    //0 タイトル
    //1 メイン画面
    //2 ゲームオーバー
    //3 シナリオ画面
	public static final int GS_TITLE = 0;
	public static final int GS_MAIN  = 1;
	public static final int GS_GAMEOVER = 2;
	public static final int GS_SCENARIO = 3;
	public int _gameState = GS_TITLE;
	
	//キャラクタの高さ
	private static final int XY_SIZE = 64;
	
	//キャラクタの移動制御
	private float _jitJudgmentX,_jitJudgmentY;
	
	//敵のデータ
	private static final int ENEMY_NUM = 8;
	private Sprite2D[] _enemy = new Sprite2D[ENEMY_NUM];
	private Sprite2D _ship = new Sprite2D(); 
	
	//長いBGMを再生するときに使うインスタンス
	//スタート画面用
	private MediaPlayer _mpBGMStart = new MediaPlayer();
	//メイン画面用
	private MediaPlayer _mpBGMMain = new MediaPlayer();
	
	//自機用の弾幕//最大20
	private static final int _oneBulletMax = 20;
	private Sprite2D[] _oneBullet = new Sprite2D[_oneBulletMax];
	
	//コンストラクタ
	public HyperMotion2D(Context context){
	    _context = context;
	    _mpBGMStart = MediaPlayer.create(context,R.raw.startbgm);
	    _mpBGMMain = MediaPlayer.create(context,R.raw.mainbgm);
	}
	
	//フレーム制御
	public void onDrawFrame(GL10 gl){
		//バッファをクリアにする
	    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
	    switch (_gameState){	    
	    	case GS_TITLE:
	    		//スタート画面に来た時に
	    		_mpBGMStart.start();
		    	_title.draw(gl,getRatio());
		    	break;
		    	
		    case GS_MAIN:
		    	//メインのゲーム画面が来たとき
		    	startBGM();
		    	_earth.draw(gl,getRatio());
		    	enemyDraw01(gl);
		    	charaMove();
		    	for(int i=0;i<_oneBullet.length;i++){
		    		if(_flagOneBullet[i] = true){
		    			_oneBullet[i]._pos._y += 10;
		    			_oneBullet[0].draw(gl);
		    			if(_oneBullet[i]._pos._y < 20){
		    				_flagOneBullet[i] = false;
		    			}
		    		}
		    	}_ship.draw(gl);
		    	break;
		    	
		    case GS_GAMEOVER:
		    	//ゲームオーバになったとき
		    	_earth.draw(gl,getRatio());
		    	enemyDraw01(gl);
		    	enemyMove01();
		    	_ship.draw(gl);
		    	break;
	    }
	}

	//メイン画面用のBGM
	private void startBGM(){
		//BGMを止める
    	_mpBGMStart.stop();
    	//メイン画面に来た時にmainbgmを再生
    	_mpBGMMain.start();
	}
	
	//敵の描画
	private void enemyDraw01(GL10 gl){
		for(int i=0;i<_enemy.length;i++){
			_enemy[i].draw(gl);
		}
	}
	
	//敵の描画
	private void enemyMove01(){
		for(int i=0;i<_enemy.length;i++){
			_enemy[0]._pos._x = (_width-XY_SIZE)/2;
			_enemy[0]._pos._y --;
		}
	}
	
	//画面の比率
	private float getRatio(){	
		return (float)_width/600.0f;
	}
	
	//キャラクタの移動制御
	private void charaMove(){
		//キャラクタの移動制御
		if(_ship._pos._x < 0){
			_ship._pos._x = 0;
		}
		else if(_ship._pos._x > _width-XY_SIZE){
			_ship._pos._x = _width-XY_SIZE;
		}
		else if(_ship._pos._y < 0){
			_ship._pos._y = 0;
		}
		else if(_ship._pos._y > _height-XY_SIZE){
			_ship._pos._y = _height-XY_SIZE;
		}
		
	}
	
	//サーフェス変更
	public void onSurfaceChanged(GL10 gl,int width, int height){
		
	}

	//サーフェス生成
	public void onSurfaceCreated(GL10 gl, EGLConfig config){
	
		//背景色
	   	gl.glClearColor(0.6f,0.8f,1.0f,1.0f);
	    //ディザを無効か
	   	gl.glDisable(GL10.GL_DITHER);
	    //深度テストを有効に
	   	gl.glEnable(GL10.GL_DEPTH_TEST);
	  	//テクスチャ機能をON
	   	gl.glEnable(GL10.GL_TEXTURE_2D);
	  	//透明可能
	   	gl.glEnable(GL10.GL_ALPHA_TEST);
	   	//ブレンド可能
	   	gl.glEnable(GL10.GL_BLEND);
	  	//色のブレンド
	   	gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

		_title.setTexture(gl,_context.getResources(),R.drawable.title);
		_title._texWidth = 600;
		_title._width = 600;
		
		_earth.setTexture(gl,_context.getResources(),R.drawable.earth);
		_earth._texWidth = 600;
		_earth._width = 600;
		
		_ship.setTexture(gl,_context.getResources(),R.drawable.ship);
		
		//弾じゃぁぁぁっぁっぁぁぁぁぁぁぁ
		for(int i=0;i<_oneBullet.length;i++){
			//自機の弾のインスタンスを生成
			//インデックスごとにコンストラクタを呼んで生成
			_oneBullet[i] = new Sprite2D();
			_oneBullet[i].setTexture(gl,_context.getResources(),R.drawable.onebullet);
			_oneBullet[i]._pos._x = _xPos;
			_oneBullet[i]._pos._y = _yPos;
		}
		
		//敵のテクスチャ
		for(int i=0;i<_enemy.length;i++){
			_enemy[i] = new Sprite2D();
			_enemy[i].setTexture(gl,_context.getResources(),R.drawable.enemy);
		}
	}
	
	//サーフェイス終了時に呼ばれる
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
    
	//初期状態
	public void init(){
		for(int i=0;i<_enemy.length;i++){
			_enemy[i]._pos._x = (float)Math.random()*(_width-XY_SIZE);
			_enemy[i]._pos._y = 500 + i*300+(float)Math.random() * 100;
		}
		
		//キャラクタの初期位置
		_ship._pos._x = (_width-XY_SIZE)/2;
		_ship._pos._y = (_height-XY_SIZE)/4;
		
	}	
	
	//onTouchEventより遷移
	//タッチした瞬間の行動を制御
	public void actionDown(float x,float y){
		
	}
	
	//onTouchEventより遷移
	//タッチして、画面を触っている最中の行動を制御
	public void actionMove(float x,float y){
		_jitJudgmentX = x - _ship._pos._x;
		_jitJudgmentY = y - _ship._pos._y;
		
		//当たり判定 /円の当たり判定を作成
		float _hitJudgment = _jitJudgmentX * _jitJudgmentX + _jitJudgmentY * _jitJudgmentY;
		
		//当たり判定の距離
		float _radius = 100*100;
		
		switch (_gameState){
			case GS_MAIN:
				if(_hitJudgment <= _radius){
					_ship._pos._x = (int)x;
					_ship._pos._y = (int)y;
					for(int i=0;i<_oneBullet.length;i++){
						_oneBullet[i]._pos._x = (int)x;
						_oneBullet[i]._pos._y = (int)y;
					}
				}
				break;
		}
	}

	//onTouchEventより遷移
	//タッチを離した時の行動を制御
	public void actionUp(float x,float y){
		switch ( _gameState ){
			case GS_TITLE:
				init();
				_gameState = GS_MAIN;
				break;
			case GS_MAIN:
				break;
			case GS_GAMEOVER:
				_gameState = GS_TITLE;
				break;
		}
 	}
}
最後に編集したユーザー 太陽 on 2015年10月11日(日) 22:49 [ 編集 2 回目 ]

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: Android環境におけるシューティングゲームの開発

#2

投稿記事 by みけCAT » 9年前

全くテストしていませんが、ループの中なのに0番目の要素にしかアクセスしていない場所(91行目、127行目、128行目)が怪しいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: Android環境におけるシューティングゲームの開発

#3

投稿記事 by みけCAT » 9年前

また、89行目の常に真である条件式も怪しいです。

コード:

if(_flagOneBullet[i]){
の間違いではないでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

太陽
記事: 4
登録日時: 9年前
住所: 地球

Re: Android環境におけるシューティングゲームの開発

#4

投稿記事 by 太陽 » 9年前

みけCAT様。返信ありがとうございます。

指摘していただいたところなどを直したら、下記のプログラムになり、
等間隔な連続的な弾の描画は行うことはできました。

ですが、まだ問題点は残っており、20個描画が終わったら、
また20個の弾の描画をしたいと思っているのですが、
如何せん描画ができないといったところです。

HyperMotion2D.java

コード:

package com.hypermotion2d;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import com.roxiga.hypermotion2d.Sprite2D;

import android.content.Context;
import android.media.MediaPlayer;
import android.opengl.GLSurfaceView;
import android.view.SurfaceHolder;

public class HyperMotion2D implements GLSurfaceView.Renderer {
	
	//コンテキスト
	private Context _context;
	//高さ、幅
	public int _width,_height;
	//タッチしたのかを識別
	public boolean _touch;
	//タッチしたかの識別
	//弾を発射するかどうか
	public boolean _touchEvent = false;
	//public boolean _touchEvent02 = false;
	//現在押している座標
	private float _xPos,_yPos; 
	
	//自機の用の弾を出しているかのフラグ
	public boolean[] _flagOneBullet = new boolean[20];
	public boolean _flagOneBulletMax;
	public int _oneBulletCount = 0;
	
	//create
    private Sprite2D _title = new Sprite2D();
    private Sprite2D _earth = new Sprite2D();
    
    //画面制御
    //0 タイトル
    //1 メイン画面
    //2 ゲームオーバー
    //3 シナリオ画面
	public static final int GS_TITLE = 0;
	public static final int GS_MAIN  = 1;
	public static final int GS_GAMEOVER = 2;
	public static final int GS_SCENARIO = 3;
	public int _gameState = GS_TITLE;
	
	//このゲームの時間
	//最大値
	private int _time = 0;
	private final int _timeLimit = 3;
	
	//キャラクタの高さ
	private static final int XY_SIZE = 64;
	
	//キャラクタの移動制御
	//どこを触れればキャラクタが動くのか
	private float _jitJudgmentX,_jitJudgmentY;
	
	//private final int _heightMax = getHeight();
	//sound
	//private static SoundPool _spExplode;
	//private int _soundID;
	
	//敵のデータ
	private static final int ENEMY_NUM = 8;
	private Sprite2D[] _enemy = new Sprite2D[ENEMY_NUM];
	//敵の動き
	//private Vector2D[] _enemyDelta = new Vector2D[ENEMY_NUM];
	
	private Sprite2D _ship = new Sprite2D(); 
	
	//長いBGMを再生するときに使うインスタンス
	//スタート画面用
	private MediaPlayer _mpBGMStart = new MediaPlayer();
	//メイン画面用
	private MediaPlayer _mpBGMMain = new MediaPlayer();
	
	private final int oneBulletDelta = 10;
	
	//自機用の弾幕//最大20
	private static final int _oneBulletMax = 20;
	private Sprite2D[] _oneBullet = new Sprite2D[_oneBulletMax];
	//private Sprite2D[] _oneBulletDelta = new Sprite2D[_oneBulletMax];
	
	//コンストラクタ
	public HyperMotion2D(Context context){
	    _context = context;
	    
	    //bgmファイルを生成
	    _mpBGMStart = MediaPlayer.create(context,R.raw.startbgm);
	    _mpBGMMain = MediaPlayer.create(context,R.raw.mainbgm);
	}
	
	//フレーム制御
	public void onDrawFrame(GL10 gl){
		//バッファをクリアにする
	    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
	    switch (_gameState){	    
	    	case GS_TITLE:
	    		_mpBGMStart.start();
		    	_title.draw(gl,getRatio());
		    	break;
		    	
		    case GS_MAIN:
		    	startBGM();
		    	_earth.draw(gl,getRatio());
		    	enemyDraw01(gl);
		    	charaMove(); 
		    	oneBulletDraw(gl);
		    	_ship.draw(gl);
		    	break;
		    	
		    case GS_GAMEOVER:
		    	_earth.draw(gl,getRatio());
		    	enemyDraw01(gl);
		    	enemyMove01();
		    	_ship.draw(gl);
		    	break;
	    }
	}

	//自機の弾発射
	public void oneBulletDraw(GL10 gl){
		if(_touchEvent == true ){
    		for(int i=0;i<_oneBullet.length;i++){
    			if(_flagOneBullet[i] == false){
    				_flagOneBullet[i] = true;
    				_oneBullet[i]._pos._x = _xPos;
    				_oneBullet[i]._pos._y = _yPos + 20;
    				break;
    			}
    		}
    	}
		
		for(int i=0;i<_oneBullet.length;i++){
			if(_flagOneBullet[i] == true){
				_oneBullet[i]._pos._y = _oneBullet[i]._pos._y + 20;
				_oneBullet[i].draw(gl);
				_oneBulletCount++;
				if(_oneBulletCount == _oneBullet.length){
					oneBulletDraw(gl);
				}
			}
		}
	}
	
	//メイン画面用のBGM
	private void startBGM(){
		//BGMを止める
    	_mpBGMStart.stop();
    	//メイン画面に来た時にmainbgmを再生
    	_mpBGMMain.start();
	}
	
	//敵の描画
	private void enemyDraw01(GL10 gl){
		for(int i=0;i<_enemy.length;i++){
			_enemy[i].draw(gl);
		}
	}

	//画面の比率
	private float getRatio(){	
		return (float)_width/600.0f;
	}
	
	//キャラクタの移動制御
	private void charaMove(){
		if(_ship._pos._x < 0){
			_ship._pos._x = 0;
		}
		else if(_ship._pos._x > _width-XY_SIZE){
			_ship._pos._x = _width-XY_SIZE;
		}
		else if(_ship._pos._y < 0){
			_ship._pos._y = 0;
		}
		else if(_ship._pos._y > _height-XY_SIZE){
			_ship._pos._y = _height-XY_SIZE;
		}
		
	}
	
	//サーフェス変更
	public void onSurfaceChanged(GL10 gl,/*SurfaceHolder holder,
	        int format,int w,int h*/int width, int height){
		
	}

	//サーフェス生成
	public void onSurfaceCreated(GL10 gl, EGLConfig config){
		
		//背景色
	   	gl.glClearColor(0.6f,0.8f,1.0f,1.0f);
	    //ディザを無効か
	   	gl.glDisable(GL10.GL_DITHER);
	    //深度テストを有効に
	   	gl.glEnable(GL10.GL_DEPTH_TEST);
	  	//テクスチャ機能をON
	   	gl.glEnable(GL10.GL_TEXTURE_2D);
	  	//透明可能
	   	gl.glEnable(GL10.GL_ALPHA_TEST);
	   	//ブレンド可能
	   	gl.glEnable(GL10.GL_BLEND);
	  	//色のブレンド
	   	gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);

		_title.setTexture(gl,_context.getResources(),R.drawable.title);
		_title._texWidth = 600;
		_title._width = 600;
		
		_earth.setTexture(gl,_context.getResources(),R.drawable.earth);
		_earth._texWidth = 600;
		_earth._width = 600;
		
		_ship.setTexture(gl,_context.getResources(),R.drawable.ship);
		
		//弾
		for(int i=0;i<_oneBullet.length;i++){
			//自機の弾のインスタンスを生成
			//インデックスごとにコンストラクタを呼んで生成
			_oneBullet[i] = new Sprite2D();
			_oneBullet[i].setTexture(gl,_context.getResources(),R.drawable.onebullet);
			
			_oneBullet[i]._pos._x = _xPos;
			_oneBullet[i]._pos._y = _yPos;
		}
		
		//敵のテクスチャ
		for(int i=0;i<_enemy.length;i++){
			_enemy[i] = new Sprite2D();
			_enemy[i].setTexture(gl,_context.getResources(),R.drawable.enemy);
		}
	}
	
	//サーフェイス終了時に呼ばれる
    public void surfaceDestroyed(SurfaceHolder holder) {
        //thread=null;
    }
	
	//初期状態
	public void init(){
		for(int i=0;i<_enemy.length;i++){
			_enemy[i]._pos._x = (float)Math.random()*(_width-XY_SIZE);
			_enemy[i]._pos._y = 500 + i*300+(float)Math.random() * 100;
		}
                _ship._pos._x = (_width-XY_SIZE)/2;
		_ship._pos._y = (_height-XY_SIZE)/4;
		
	}	
	
	//タッチした瞬間の行動を制御
	public void actionDown(float x,float y){
		//とりあえず代入
		//_xPos = x;
		//_yPos = y;
	}
	
	//タッチして、画面を触っている最中の行動を制御
	public void actionMove(float x,float y){
		_jitJudgmentX = x - _ship._pos._x;
		_jitJudgmentY = y - _ship._pos._y;
		
		//当たり判定 
		float _hitJudgment = _jitJudgmentX * _jitJudgmentX + _jitJudgmentY * _jitJudgmentY;
		
		//当たり判定の距離
		float _radius = 100*100;
		
		switch (_gameState){
			case GS_MAIN:
				//キャラクタの移動制御//タッチ画面の
				if(_hitJudgment <= _radius){
					_ship._pos._x = (int)x;
					_ship._pos._y = (int)y;
					for(int i=0;i<_oneBullet.length;i++){
						_xPos = (int)x;
						_yPos = (int)y;
						_touchEvent = true;
				}
				break;
		}
	}

	//タッチを離した時の行動を制御
	public void actionUp(float x,float y){
		switch ( _gameState ){
			case GS_TITLE:
				init();
				_gameState = GS_MAIN;
				break;
			case GS_MAIN:
				break;
			case GS_GAMEOVER:
				_gameState = GS_TITLE;
				break;
		}
 	}
}

閉鎖

“C言語何でも質問掲示板” へ戻る