2013年6月20日木曜日

アクションゲームサンプルコード


アクションゲームサンプルコード を公開します。

サンプルの実行画像

ソースとAPKはこちら


ボタンは見えませんが、画面の左半分を触るとキャラクターが左右に移動します。
画面右側を押すとジャンプします。
地面から落ちると、落ち続けます・・・・・

大雑把な雛形です。自分で設計したものなので効率的であるかはわかりません。
すべてJAVAで書かれています。
キャラクターや障害物を増やすにはデータ作成管理クラスが必要になります。
戻るボタンで終了します。

大まかな構造としては

タッチスレッドでパラメーターを変更。
・移動ならXをプラス
・ジャンプなら慣性のFをプラス

描画スレッドで位置や慣性を計算。
・障害物に触れていないなら空中
・空中なら落下



//ゲーム画面呼び出しクラス
public class MainActivity   extends Activity {
private GameView gameView;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        
gameView=new GameView(this);
setContentView(gameView);

}    
}

//画面クラス
public class GameView extends SurfaceView{
 private GameViewCallBack cb;
 private long time;

 public GameView(Context context) {
     super(context);
     SurfaceHolder holder = getHolder();
     cb = new GameViewCallBack();
     cb.setContext(context);
     holder.addCallback(cb);

 }
@Override
public boolean onTouchEvent(MotionEvent event) {


//連続タップ防止 
if(time+100<System.currentTimeMillis()){

time=System.currentTimeMillis();

float x = event.getX(); // X座標を取得
       float y = event.getY(); // Y座標を取得  
cb.setTouchPoint( x , y );



}
return true;
}
   // キーイベント発生時、呼び出されます
   @Override
   public boolean dispatchKeyEvent(KeyEvent event) {
       if (event.getAction() == KeyEvent.ACTION_UP) { // キーが離された時
           switch (event.getKeyCode()) {
           case KeyEvent.KEYCODE_HOME: 
              
               
           case KeyEvent.KEYCODE_BACK:
            cb.teisi();
            return false;
           default:
           }
       }
       return super.dispatchKeyEvent(event);
   }
}


//描画スレッド
public class GameViewCallBack implements SurfaceHolder.Callback, Runnable{

private SurfaceHolder holder = null;
private Thread thread = null;
//スレッドの管理
private boolean isAttached = true;
//コントローラー
private Controler cl;
//プレイヤー情報
private PlayCharcter pc;
//障害物
private Syougai sg;

      private float w, h;
      //中心位置
      private int   cx, cy;
private Context context;
      
      public void setContext(Context rr){
     context=rr;
      }
      
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

this.w = width;
this.h = height;
this.cx=(int)(w*0.50);
this.cy=(int)(h*0.50);
cl=new Controler(width, height);
pc =new PlayCharcter(cx,cy,context);
//左、下、幅、高さ
sg = new Syougai(50,(int) (h-100),1000,100);

}

@Override
public void surfaceCreated(SurfaceHolder holder) {

this.holder = holder;
thread = new Thread(this);
thread.start(); 
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
      isAttached = false;
      thread = null;
}

private long t1 = 0, t2 = 0; 

@Override
public void run() {
while( isAttached ){
t1 = System.currentTimeMillis();
hyouji();
atari();
byouga();
// スリープ 60fpsの確保
t2 = System.currentTimeMillis();
if(t2 - t1 < 16){ 
try {
Thread.sleep(16 - (t2 - t1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public void teisi(){
isAttached=false;
thread = null;
 
}
//コントロール
public void setTouchPoint(float x, float y) {

int tmp =cl.getTouthActionProt((int)x,(int)y);
if(tmp==100){
pc.btnAction(1);
}else{
pc.moveAction(tmp);
}
}


public void byouga(){

//描画処理を開始
Canvas canvas = holder.lockCanvas();
if(canvas==null){
return;
}
//背景
canvas.drawColor(0,PorterDuff.Mode.CLEAR );
Paint paint = new Paint();//かり

paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.GREEN);
canvas.drawRect(new RectF(sg.l, sg.t, sg.r, sg.b), paint);

pc.byouga(canvas, cx, cy);
//描画処理を終了
holder.unlockCanvasAndPost(canvas);
}
//各データの計算 キャラの状態 あたり判定
private void atari(){
//慣性移動計算 障害物への移動適応
pc.kansei();
//キャラと足場が接触 pc.y仮
if(cx>=sg.l && cx<=sg.r && pc.y>=sg.t&&cy<=sg.b){
//if(pc.x>=sg.l && pc.x<=sg.r && pc.y>=sg.t&&pc.y<=sg.b){
pc.s=0;//立ち
pc.y=sg.t;//位置補正 めり込み防止
}else{//こちらへ来ないとジャンプできない
pc.s=-1;//浮び
}

sg.sukuro(pc.x,pc.y);
}
//表示領域に存在する? hFLをたてる
private void hyouji(){
sg.hFL=true;

}

}

//コントローラーくらす
public class Controler {

private int w,h,ox=0,oy=0;
private int hidari,migi,a,j,m;
public Controler(int ww,int hh){
w=ww;
h=hh;
j= (int) (w*0.75);
a= (int) (w*0.50);
migi= (int) (w*0.25);
//hidari= (int) (w*0.75);
}
public int getTouthActionProt(int xx,int yy){
int action=0;
if(xx>=j){
action=100;
}else if(xx>=a){
action =200;
}else if(xx>=migi){
action=20;
}else{
action=-20;
}
return action;
}
}

//キャラクタークラス

public  class PlayCharcter {

private Paint paint;
//慣性 重力
private int kt=0,ky=0,kp=0,kf=0;
//座標を管理
public int x=0,y=0,w=0,h=0;//当たり判定計算用
public Bitmap gazo;
public int s=-1;//状態 0 地上 -1 空中
private Context context;
//コンストラクタ
public PlayCharcter(int xx,int yy,Context c){
paint = new Paint();
        paint.setColor(Color.WHITE);
        x=xx;//初期位置
        y=yy;       
        
       
        context =c;
        gazo = BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher);
        
        w=gazo.getWidth();
        h=gazo.getHeight();
        
        y-=h;
        
        
}
public void byouga(Canvas canvas,int xx,int yy){
canvas.drawBitmap(gazo, xx, yy-h, null);
}
//右手操作
public void btnAction(int aa){
if(s==0){
kf=7;//ジャンプの実験
y-=3;
}
}
//左手操作
public void moveAction(int aa){
x+=aa;
}
public void kansei(){

if(s==-1){
kt=ky;
ky+=(ky-kp)+kf;
kp=kt;
kf=-1;
//慣性を適応
y-=ky;
}else{
ky=0;
kp=0;
}
}

}

//障害物くらす
public class Syougai {
public int x,y,w,h,t,b,r,l,T,B,R,L;
//表示フラグ
public boolean hFL=false;
private Paint paint;
public Syougai(int xx,int yy,int ww,int hh){
x=xx;
y=yy;
w=ww;
h=hh;
//絶対座標
T=y;
L=x;
R=x+w;
B=y+h;
t=y;
l=x;
r=x+w;
b=y+h;
paint = new Paint();
        paint.setColor(Color.GREEN);
}
//プレイヤーの移動情報を適応
public void sukuro(int xx,int yy){
t=T-yy;
l=L-xx;
r=R-xx;
b=B-yy;

}
//描画処理
public void byouga(Canvas canvas){
canvas.drawRect(new RectF(l, t, r, b), paint);
}
}

権限は必要ありません。APILEVELは9以上

アクションゲームさえ作れれば大抵のゲームは作れると思います。
設計書は再設計後に記事にします。

0 件のコメント:

コメントを投稿