2011년 5월 12일 목요일

Xcode 4

http://mfiles.naver.net/a530b90a102e2f9fb752340638d5a6db7d2ad3ef/20110512_21_blogfile/herossg_1305211094659_5K4424_torrent/xcode_4_final.6233989.tpb.torrent?type=attachment

2011년 3월 4일 금요일

Corona SDK......02 - Sprite Animation

ㅎㅎ
게임에 있어서 가장 중요한 Sprite Animation ..

Corona SDK 는 두가지 방법을 지원한다.

하나는 일정한 크기의 타일(?) 방식의 Sprite Animation .
또 하나는 크기가 일정하지 않은 Sprite 를 연결해서 보여주는 방식.
( Sprite Sheets 방식 )

예를 보면 바로 이해 될듯. ㅋㅋ

크기가 일정한 Sprite.

크기가 일정 하지 않은 Sprite

크기가 일정한 Sprite 를 사용하는게 훨씬 쉽다.ㅡ,.ㅡ

require "sprite"  -- sprite 를 사용하기 위한 라이브러리(?) 추가
display.setStatusBar( display.HiddenStatusBar )  -- Status Bar 감추기

baseline = 280

-- sprite 객체(?) 이용하여 sheet2 를 생성하는데...
-- 파일 은 greenman 이고, 하나의 Sprite 타일이 128, 128 이다 라는 의미
local sheet2 = sprite.newSpriteSheet( "greenman.png", 128, 128 )

-- sprite 객체(?)인 sheet2 를 이용해서 sprite set 생성
-- sprite 타일 갯수가 1 ~ 15 라는 의미
-- 타일의 순서는 
-- 1  2  3  4
-- 5  6  7  8
-- 9 10 11 12
-- 13 14 15

local spriteSet2 = sprite.newSpriteSet(sheet2, 1, 15)

-- sprireset 을 setting 한다.
-- man 은 sprite 이름 정도로 이해 하면...
-- 1 .. 15 를 200 ms 동안 재생.
-- 젤 뒤에 0 이 나름 중요한 것이다. 
-- 0 이면 무한 반복...
-- 1 보다 크면...숫자 만큼 반복.
-- -1 이면 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 14 13 12 11 ......3 2 1
-- 이렇게 반복. 됨.
sprite.add( spriteSet2, "man", 1, 15, 200, 0 )  

-- 화면에 출력하기 위한 instance 생성...
-- 및 위치 설정.
local instance2 = sprite.newSprite( spriteSet2 )
instance2.x = 3 * display.contentWidth / 4 + 30
instance2.y = baseline - 55

-- man 으로 설정 된 놈을 불러 오고....
instance2:prepare("man")
-- animation paly...
instance2:play()

sprite sheet 는 담 기회에...
이건 솔직히 어려운게 아니라 넘 손이 많이 간다.ㅡ,.ㅡ



2011년 3월 2일 수요일

Corona SDK......01 - Hello World

Corona SDK 는 기본적으로 두개의 파일이 필요 한듯..

config.lua -> 화명 해상도 등 설정 파일인듯...
main.lua -> 이건 이름이 달라도 상관 없는듯...

config.lua 내용

-- config.lua

application =
{
content =
{
width = 320,  -- 가로 해상도
height = 480,  -- 세로 해상도
scale = "zoomEven" -- zoom to fill screen, possibly cropping edges
},
}

Scale 는

  • "none" - turns off dynamic content scaling
    : Content 와 Sacle 를 무시(?)
  • "letterbox" - uniformly scales up content as much as possible, while still showing all content on the screen. This is similar to watching a widescreen DVD on a non-widescreen TV set, except that you can use offstage content to fill the "bleed" areas rather than displaying black bars.
    : 대충 봐서는...Content 를 가능한 최대로 표시 한다는 옵션.
    : 마치 DVD 영화를 TV 에서 보면 아래 위가 검은색으로 채워 지는것 같음.
       
  • "zoomEven" - uniformly scales up content to fill the screen, while preserving aspect ratio. Some content may appear offscreen, if the new screen has a different aspect ratio
    : 가로 세로 비율을 유지하면서 스크린에 내용 채우기.
  • "zoomStretch" - non-uniformly scales up content to fill the screen. All content will remain onscreen, but it may be stretched vertically or horizontally.
    : 비율을 유지 하지 않고 스크린에 맞게 내용 채우기.
    : 가로 / 세로 한쪽을 길어져서 보일 수 있음. 

실제 게임을 만들기 위해서는 별다른 차이가 없어 보임. ( 현재까지는.. )

main.lua


local textObject = display.newText( "Hello World!", 50, 50, native.systemFont, 124 )
-- 화면에 Text 박스(?) 를 생성함.
-- display.newText Text 박스를 생성하는 Function 정도(?)
textObject:setTextColor( 255,255,255 )
-- Text 박스의 색 지정.

** display : displayObject 를 생성 할때 사용 하는놈..
Image 를 만들고 싶어면...
local image = display.newImage("xxx.png")

이렇게 해서 생성 할 수 있음. 

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개의 스테이지로 구성되어 있으며 열쇠를 줍고 다음 관문으로 들어가는 문으로 들어가는 방식의 게임이다. 주인공이 벽돌을 만들고 허물 수 있는 능력을 가진 아주 독특한 구조의 게임이다.


일단 시작. ㅋㅋ