2011년 1월 28일 금요일

Android 2D 게임 제작 - 02 ( with WiEngine )

기본적인 환경 구성.

1. 우선 기본적인 Project 의 구성.

WiEngine 는 기본적으로 NDK 로 작성 되었다.
그래서 속도는 비교적 빠른 편이지만, 호환성은...어느 정도 인지 장담하기 어렵다.

내가 사용하는 기기인 갤럭시A ( SHW-M100S ) 에서는 별 무리 없이 잘 작동 한다.

2. MainActivity -> 기본적인 Activity 이고 나머지는 이놈을 상속 해서 사용한다.


package com.cnp.wizard;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.text.TextUtils;

import com.wiyun.engine.nodes.Director;
import com.wiyun.engine.nodes.Director.IDirectorLifecycleListener;

public abstract class MainActivity extends Activity implements IDirectorLifecycleListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   Director.getInstance().addLifecycleListener(this);
}

protected String checkPrecondition() {
return null;
}

@Override
protected void onPause() {
        super.onPause();

        Director.getInstance().pause();
    }

    @Override
    protected void onResume() {
        super.onResume();

        Director.getInstance().resume();
    }

    @Override
    protected void onDestroy() {
     Director.getInstance().end();
    
        super.onDestroy();
    }
  
    public void onDirectorEnded() {
    }
  
    public void onSurfaceChanged(int w, int h) {
    }
  
    public void onSurfaceCreated() {
     final String error = checkPrecondition();
     if(!TextUtils.isEmpty(error)) {
     runOnUiThread(new Runnable() {
           public void run() {
            AlertDialog.Builder builder = new Builder(MainActivity.this);
            builder.setMessage(error)
            .setNegativeButton("OK", new OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
            finish();
            }
            }).show();
           }
            });
     }
    }
  
    public void onSurfaceDestroyed() {
    }
}

3. mainActivity 를 상속한 GameActivity
/*
 * Copyright (c) 2010 WiYun Inc.

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.cnp.wizard;

import android.os.Bundle;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;

import com.wiyun.engine.actions.Action;
import com.wiyun.engine.actions.Animate;
import com.wiyun.engine.actions.IntervalAction;
import com.wiyun.engine.actions.MoveTo;
import com.wiyun.engine.actions.RepeatForever;
import com.wiyun.engine.actions.Sequence;
import com.wiyun.engine.nodes.AtlasAnimation;
import com.wiyun.engine.nodes.AtlasSprite;
import com.wiyun.engine.nodes.Director;
import com.wiyun.engine.nodes.Layer;
import com.wiyun.engine.nodes.Scene;
import com.wiyun.engine.nodes.Sprite;
import com.wiyun.engine.opengl.Texture2D;
import com.wiyun.engine.opengl.TextureAtlas;
import com.wiyun.engine.opengl.WYGLSurfaceView;
import com.wiyun.engine.tmx.ObjectGroup;
import com.wiyun.engine.tmx.TMXTileMap;
import com.wiyun.engine.types.WYRect;
import com.wiyun.engine.types.WYSize;
import com.wiyun.engine.utils.ResolutionIndependent;

public class GameActivity extends MainActivity {
    private WYGLSurfaceView mGLSurfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        mGLSurfaceView = new WYGLSurfaceView(this);
        setContentView(mGLSurfaceView);

        // show FPS
        Director.getInstance().setDisplayFPS(true);

        Scene scene = Scene.make();
        scene.addChild(new MyLayer());

        // Make the Scene active
        Director.getInstance().runWithScene(scene);
    }

    static class MyLayer extends Layer {
        private static float ITEM_WIDTH = 0;
        private static float ITEM_HEIGHT = 0;
        private TMXTileMap mMap;
     private float mLastX;
     private float mLastY;

     public static final int TAG_SPRITE_MANAGER = 1;    
        public MyLayer() {
          ITEM_WIDTH = 47;//ResolutionIndependent.resolveDp(47);
              ITEM_HEIGHT = 70;//ResolutionIndependent.resolveDp(70);

              WYSize s = Director.getInstance().getWindowSize();

              // add manager
              TextureAtlas atlas = TextureAtlas.make(Texture2D.makePNG(R.drawable.mainc));
              mMap = TMXTileMap.make(R.raw.t);
              ObjectGroup ogs = mMap.getObjectGroup("Wall");
              
              
              //og.
              //addChild(mMap);

              // add sprite
              AtlasSprite sprite = AtlasSprite.make(WYRect.make(0, 0, ITEM_WIDTH, ITEM_HEIGHT), atlas);
              addChild(sprite);
              sprite.setPosition(s.width / 2, s.height / 2);
              
              // create animation and add it to atlas sprite
              AtlasAnimation anim = new AtlasAnimation(0);
              anim.addFrame(0.1f,  
               frameAt(0, 0),
               frameAt(1, 0),
               frameAt(2, 0),
               frameAt(3, 0), 
               frameAt(4, 0),
               frameAt(5, 0),
               frameAt(6, 0),
               frameAt(7, 0),
               frameAt(8, 0)
               );
              
              Animate a = Animate.make(anim);
              sprite.runAction(RepeatForever.make(a));
              setTouchEnabled(true);
          }

        @Override
        public boolean wyTouchesBegan(MotionEvent event) {
         mLastX = event.getX();
         mLastY = event.getY();
         return true;
        }          
        private WYRect frameAt(int x, int y) {
           return WYRect.make(x * ITEM_WIDTH, y * ITEM_HEIGHT, ITEM_WIDTH, ITEM_HEIGHT);
        }
        
        @Override
        public boolean wyTouchesMoved(MotionEvent event) {
         // remember android event origin is not same as OpenGL
         // you can use Director.getInstance().convertToGL(event.getX(), event.getY()) to convert it to GL coordinate
         float x = event.getX();
         float y = event.getY();
         float deltaX = x - mLastX;
         float deltaY = y - mLastY;
         mLastX = x;
         mLastY = y;
        
         mMap.translate(deltaX, -deltaY);
         return true;
        }        
    }
}

코드에 대한 자세한 설명...다음 포스트에서...^^


실행 결과.^^

Android 2D 게임 제작 - 01 ( with WiEngine )

개인 보관 차원의 자료임.

WiEngine 를 이용한 2D 게임 제작.
WiEngine 에 대한 기본 예제.

기본적으로 WiEngine은 Cocos2D 를 형식을 따르고 있다.

목표 게임

Solomin's KEY

1986년에 테크모에서 제작한 퍼즐 아케이드 게임이다. 총 50개의 스테이지로 구성되어 있으며 열쇠를 줍고 다음 관문으로 들어가는 문으로 들어가는 방식의 게임이다. 주인공이 벽돌을 만들고 허물 수 있는 능력을 가진 아주 독특한 구조의 게임이다.


일단 시작. ㅋㅋ