2011년 5월 12일 목요일
2011년 3월 4일 금요일
Corona SDK......02 - Sprite Animation
ㅎㅎ
게임에 있어서 가장 중요한 Sprite Animation ..
Corona SDK 는 두가지 방법을 지원한다.
하나는 일정한 크기의 타일(?) 방식의 Sprite Animation .
또 하나는 크기가 일정하지 않은 Sprite 를 연결해서 보여주는 방식.
( Sprite Sheets 방식 )
예를 보면 바로 이해 될듯. ㅋㅋ
게임에 있어서 가장 중요한 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 는
실제 게임을 만들기 위해서는 별다른 차이가 없어 보임. ( 현재까지는.. )
main.lua
local textObject = display.newText( "Hello World!", 50, 50, native.systemFont, 124 )
-- 화면에 Text 박스(?) 를 생성함.
-- display.newText Text 박스를 생성하는 Function 정도(?)
textObject:setTextColor( 255,255,255 )
-- Text 박스의 색 지정.
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() {
}
}
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개의 스테이지로 구성되어 있으며 열쇠를 줍고 다음 관문으로 들어가는 문으로 들어가는 방식의 게임이다. 주인공이 벽돌을 만들고 허물 수 있는 능력을 가진 아주 독특한 구조의 게임이다.
일단 시작. ㅋㅋ
WiEngine 를 이용한 2D 게임 제작.
WiEngine 에 대한 기본 예제.
기본적으로 WiEngine은 Cocos2D 를 형식을 따르고 있다.
목표 게임
Solomin's KEY
1986년에 테크모에서 제작한 퍼즐 아케이드 게임이다. 총 50개의 스테이지로 구성되어 있으며 열쇠를 줍고 다음 관문으로 들어가는 문으로 들어가는 방식의 게임이다. 주인공이 벽돌을 만들고 허물 수 있는 능력을 가진 아주 독특한 구조의 게임이다.
일단 시작. ㅋㅋ
피드 구독하기:
글 (Atom)