ä»æ¥ãã¢ãã€ã«ã²ãŒã ãéåžžã«äººæ°ãããããšã¯åšç¥ã®äºå®ã§ãã ãã¹ãŠã®éçºè ã¯ãåå¿è ã§ãã£ãŠãããããã®ã²ãŒã ã®1ã€ãäœæããæ©äŒããããŸãã å€ãã®å Žåããã©ãããã©ãŒã ã®éžæã§çåãçããŸãã ãã¡ãããiOSãšAndroidãWP7ãšMeeGoããã¹ã¯ããããšãã©ãŠã¶ã§ãã²ãŒã ãããã«ã©ãã«ã§ã眮ãããã§ãã ãããŠãããããã¹ãŠãç¡æã®ããŒã«ã䜿çšããŠç°¡åã«å®è£ ã§ããŸãã
ãã®èšäºã§ã¯ãã³ãŒããã©ãããã©ãŒã ã®äž»èŠéšåãç¬ç«ãããæ®ãã¯ç¹å®ã®ãã©ãããã©ãŒã ããšã«äŸ¿å©ãªéçºããŒã«ã䜿çšããæ¹æ³ã説æããŸãã
äžã®å³ã«ç€ºãããŠããã²ãŒã ã®ç®çã¯ããªã³ãŽãé£ãã§ããéã«ãã£ããããããšã§ãã æéãçµã€ã«ã€ããŠããªã³ãŽã®æ°ãå¢å ããããããèŠéãããšã¯ããå°é£ã«ãªããŸãã ãªã³ãŽã¯ä»»æã®è§åºŠã§èœäžãã Box2Dç©çãšã³ãžã³ã®ãããã§å転ããå¢çç·ããçŸå®çã«è·³ãè¿ããŸãã ã²ãŒã ã¯AndroidãQt察å¿ãã©ãããã©ãŒã ïŒSymbianãMaemoãMeeGoãWindowsãLinuxãMac OS XïŒããã³Google Chromeãã©ãŠã¶ãŒã§å®è¡ãããŸãã
䟿å©ãªããŒã«ã®éžæ
ã³ãŒãã®äž»èŠéšåã¯çŽç²ãªC ++ã§èšè¿°ããã®ã§ïŒèšäºã®æåŸã§èªã¿ãŸãïŒããã¹ãŠã®IDEããããè¡ããŸãã Qt CreatorãéžæããŸãããããšãã°Microsoft Visual StudioãEclipseã®äœ¿çšã劚ãããã®ã¯ãããŸããã
Androidãã©ãããã©ãŒã ã§ã¯ãlibgdxã©ã€ãã©ãªãŒã«çŠç¹ãåœãŠãŸãã ãã®å©ããåããŠããã¯ã¹ãã£ãç°¡åã«æç»ãããµãŠã³ããåçããä»ã®å¿ èŠãªããšãè¡ãããšãã§ããŸãã
ãã¹ã¯ãããã§ã²ãŒã ãéçºããããã®ããŒã«ãšããŠãQtãåãäžããŸãã ç§ã¯ãã®ã©ã€ãã©ãªã«é·ãé粟éããŠãããç§ãåã°ããããšããããŸããã Qtã䜿çšãããšãã¢ãã€ã«ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã SymbianãMaemoãããã³MeeGoã®ãµããŒããšãã圢ã§çŽ æŽãããããŒãã¹ãããããŸãã
ãŸããç¹ã«ãã®èšäºã§ã¯ãHTML5ãjavascriptãããã³Google Native Clientã䜿çšããŠãã²ãŒã ãGoogle Chromeã§å®è¡ããŸãã HTML5 CanvasãšAudioã䜿çšããŸããããããã©ãã»ã©ç°¡åã§ã·ã³ãã«ãªã®ããããããŸãã
ããžãã¯ã®å®è£ ã¯è€éã§ã¯ãªããããããã«ã€ããŠã¯èª¬æããŸããïŒèª°ã§ãã³ãŒããèŠãããšãã§ããŸã ïŒã 代ããã«ããã¹ãŠã®ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ã§ã²ãŒã ãåäœãããæ¹æ³ã«éäžããŸãã
究極ã®ãã©ãããã©ãŒã ããã®æœè±¡å
åè¿°ããããã«ãã³ãŒãã®å€§éšåã¯ãã¹ãŠã®ãã©ãããã©ãŒã ã«å ±éã§ãã ãããããšã³ãžã³ããšåŒã³ãŸãããã 2ã€ã®åé¡ã解決ããå¿ èŠããããŸãã 1ã€ç®ã¯ãåãã©ãããã©ãŒã ã§ãšã³ãžã³ã¡ãœãããåŒã³åºãããšã§ãã
ãã®ããã«ããšã³ãžã³ã¯ãã©ãããã©ãŒã ã«æ¬¡ã®ã€ã³ã¿ãŒãã§ã€ã¹ãæäŸããŸãã
class Application { public: Application(); ~Application(); void render(); void touch(int x, int y); //... };
ããŸããŸãªãã©ãããã©ãŒã ã§ã®æç»ããã³å ¥åãã³ãã©ãŒã®åŒã³åºãã¯ãApplicationã¯ã©ã¹ããã¡ãœãããåŒã³åºããŸããããšãã°ãQtã䜿çšããŠããå Žåã次ã®ããã«ãªããŸãã
void QtPlatrom::paintEvent(QPaintEvent *) { QPainter painter(this); m_painter = &painter; m_app->render(); } void QtPlatrom::mousePressEvent(QMouseEvent *e) { QWidget::mousePressEvent(e); m_app->touch(e->x(), height() - e->y()); }
C ++ããJavaã«ã¢ã¯ã»ã¹ããå¿ èŠããããããAndroidã§ã¯ããå°ãè€éã«ãªããŸãã
private native void renderNative(); private native void touchNative(int x, int y); static { System.loadLibrary("fruitclick"); } public void render() { renderNative(); } public boolean touchDown(int x, int y, int pointer, int button) { touchNative(x, Gdx.graphics.getHeight() - y); return false; }
ãã®åŸã察å¿ããã¡ãœãããC ++ã§åŒã³åºãããŸãã
void Java_com_fruitclick_Application_renderNative(JNIEnv* env, jobject thiz) { g_app->render(); } void Java_com_fruitclick_Application_touchNative(JNIEnv* env, jobject thiz, jint x, jint y) { g_app->touch(x, y); }
JavaScriptãããã©ãŠã¶ã§Native Clientã䜿çšããå ŽåãC ++ã«çŽæ¥ã¢ã¯ã»ã¹ããããšã¯ã§ããŸããã代ããã«ãã¢ãžã¥ãŒã«ã«ã¡ãã»ãŒãžãéä¿¡ããå¿ èŠããããŸããããšãã°ã次ã®è¡ã§ãã
function onTouch(e) { var coords = getCursorPosition(e); var x = coords[0]; var y = canvas.height - coords[1]; var message = "touch " + x.toString() + " " + y.toString(); FruitclickModule.postMessage(message); } function simulate() { FruitclickModule.postMessage('render'); setTimeout("simulate()", 16); }
C ++ã§ã¯ãã¡ãã»ãŒãžã解æãããã³ã³ãã³ãã«å¿ããŠããããã®ã¡ãœãããåŒã³åºãããŸãã
void NaclPlatform::HandleMessage(const pp::Var& var) { if (!var.is_string()) return; std::stringstream stream(var.AsString()); std::string type; stream >> type; if (type == "render") { m_app.render(); } else if (type == "touch") { int x; int y; stream >> x >> y; m_app.touch(x, y); } }
çµæãšããŠããšã³ãžã³ã¯åŒã³åºããã©ã®ãã©ãããã©ãŒã ããã®ãã®ã§ãããã¯é¢ä¿ãªããããããæœè±¡åãããŸãã ãããã圌ã¯ãã€ã³ãïŒxãyïŒã§ç»é¢ã«è§Šããããç©çåŠãåŠçããŠç»é¢ã«ç»åã衚瀺ããæãæ¥ãããšãç¥ã£ãŠããŸãã
éã®çžäºäœçš
2çªç®ã®ã¿ã¹ã¯ã¯ããšã³ãžã³ãšãã©ãããã©ãŒã ã®éã®çžäºäœçšã§ãã
ããã¯ããšã³ãžã³ãç»é¢ã«ç»åãšããã¹ãã衚瀺ãããµãŠã³ããåçããæ¯åãããã¿ã€ãã³ã°ãæ瀺ããããã«å¿ èŠã§ãã ãããè¡ãã«ã¯ããã¹ãŠã®ãã©ãããã©ãŒã ã§å ±éã®ã€ã³ã¿ãŒãã§ãŒã¹ãå®è£ ããå¿ èŠããããŸãã ãã®Platformã€ã³ã¿ãŒãã§ã€ã¹ãåŒã³åºããŸãã
class Platform { public: enum Texture { APPLE = 0, BACKGROUND }; static void draw(Texture id, float x, float y, float angle = 0); static void drawText(const char* text, float x, float y); enum Sound { CRUNCH = 0, CRASH }; static void playSound(Sound id); static void vibrate(); //... };
ãšã³ãžã³ã¬ãã«ã§ã¯ãç¹å®ã®ãã©ãããã©ãŒã ã«æ¥ç¶ããŸãããåçãé³å£°ãã¡ã€ã«ãã¢ããããŒãããã代ããã«æ°å€èå¥åã䜿çšããŸãã ç»é¢ã«ç»åã衚瀺ããããé³å£°ãåçãããå Žåã次ã®ããã«ããŸãã
Platform::draw(Platform::BACKGROUND, screenWidth/2, screenHeight/2); Platform::playSound(Platform::CRASH);
ãããã£ãŠããšã³ãžã³ã¯ãåãã©ãããã©ãŒã ã§ã®ããŸããŸãªæäœã®å®è£ ã®è©³çŽ°ããæœè±¡åãããŸãã ããããããããããã«ã¯ã©ã¹å³ã瀺ããŸãã
ããã¯ãã¹ãŠé£ããã§ããïŒ ç¢ºèªããªãã§ãã ããã ãã¡ãããæéãè²»ããå¿ èŠããããŸãããã»ãšãã©ã®å Žåãã¢ããªã±ãŒã·ã§ã³ããžãã¯ã®ããã°ã©ãã³ã°ã«è²»ããããæéãšæ¯èŒããŠç¡èŠã§ããŸãã å¿ èŠãªæäœããšã«ãAndroidãQtãããã³ãã€ãã£ãã¯ã©ã€ã¢ã³ããã©ãããã©ãŒã ã®ã³ãŒããæäŸããŸãã
ç»åã®æç»ãAndroidïŒlibgdxïŒïŒ
public void draw(int id, float x, float y, float angle) { TextureRegion region = null; switch (id) { case BACKGROUND: region = background; break; case APPLE: region = apple; break; default: break; } float w = region.getRegionWidth(); float h = region.getRegionHeight(); batch.draw(region, x - w/2, y - h/2, w/2, h/2, w, h, 1, 1, angle); }
æç»ç»åãQtïŒ
void QtPlatrom::drawImpl(Texture id, float x, float y, float angle) { QPixmap* pixmap = NULL; switch(id) { case FruitClick::Platform::APPLE: pixmap = &m_apple; break; case FruitClick::Platform::BACKGROUND: pixmap = &m_background; break; default: break; } y = height() - y; m_painter->translate(x, y); m_painter->rotate(-angle); int w = pixmap->width(); int h = pixmap->height(); m_painter->drawPixmap(-w/2, -h/2, w, h, *pixmap); m_painter->rotate(angle); m_painter->translate(-x, -y); }
ç»åã®æç»ãjavascriptïŒHTML5 CanvasïŒïŒ
function draw(id, x, y, angle) { y = canvas.height - y; var image = null; switch(id) { case 0: image = apple; break; case 1: image = background; break; } context.translate(x, y); context.rotate(-angle); context.drawImage(image, -image.width/2, -image.height/2); context.rotate(angle); context.translate(-x, -y); }
ããã¹ãã®æç»ãAndroidïŒlibgdxïŒïŒ
public void drawText(String text, float x, float y) { font.draw(batch, text, x, y); }
ããã¹ãã®æç»ãQtïŒ
void QtPlatrom::drawTextImpl(const char *text, float x, float y) { y = height() - y; m_painter->drawText(x, y, text); }
ããã¹ãã®æç»ãjavascriptïŒHTML5 CanvasïŒïŒ
function drawText(text, x, y) { y = canvas.height - y; context.fillText(text, x, y); }
ãµãŠã³ããã¬ã€ãAndroidïŒlibgdxïŒïŒ
public void playSound(int id) { switch (id) { case CRUNCH: crunch.play(); break; case CRASH: crash.play(); break; } }
ãµãŠã³ãåçãQtïŒ
void QtPlatrom::playSoundImpl(Sound id) { switch (id) { case FruitClick::Platform::CRUNCH: m_crunch.play(); break; case FruitClick::Platform::CRASH: m_crash.play(); break; default: break; } }
ãµãŠã³ããjavascriptïŒHTML5ãªãŒãã£ãªïŒãåçããŸãã
function playSound(id) { var sound = null; switch(id) { case 0: sound = crunch; break; case 1: sound = crash; break; } sound.currentTime = 0; sound.play(); }
æ¯åãAndroidïŒlibgdxïŒïŒ
void vibrate() { Gdx.input.vibrate(100); }
Androidåãã«å®è£ ãããšãã¯ãC ++ããJavaã³ãŒããåŒã³åºãããšãå°ã工倫ããå¿ èŠããããŸããå¿ èŠãªJavaã¡ãœããã®IDãååŸãããïŒ
void setupEnv(JNIEnv* env, jobject thiz) { g_env = env; g_activity = thiz; g_activityClass = env->GetObjectClass(thiz); drawID = env->GetMethodID(g_activityClass, "draw", "(IFFF)V"); drawTextID = env->GetMethodID(g_activityClass, "drawText", "(Ljava/lang/String;FF)V"); playSoundID = env->GetMethodID(g_activityClass, "playSound", "(I)V"); }
ãããŠãããããåŒã³åºããŸãïŒ
void AndroidPlatform::drawImpl(FruitClick::Platform::Texture id, float x, float y, float angle) { g_env->CallVoidMethod(g_activity, drawID, id, x, y, angle); } void AndroidPlatform::drawTextImpl(const char* text, float x, float y) { jstring javaString = g_env->NewStringUTF(text); g_env->CallVoidMethod(g_activity, drawTextID, javaString, x, y); } void AndroidPlatform::playSoundImpl(FruitClick::Platform::Sound id) { g_env->CallVoidMethod(g_activity, playSoundID, id); }
Native Clientã«ã¯éèŠãªç¶æ³ããããŸã-C ++ã³ãŒãããjavascriptã«ã¡ãã»ãŒãžãéä¿¡ããå¿ èŠããããŸãïŒ
const char* sep = "|"; void NaclPlatform::drawImpl(FruitClick::Platform::Texture id, float x, float y, float angle) { std::stringstream stream; stream << "draw" << sep << id << sep << x << sep << y << sep << angle; PostMessage(pp::Var(stream.str())); } void NaclPlatform::drawTextImpl(const char* text, float x, float y) { std::stringstream stream; stream << "drawText" << sep << text << sep << x << sep << y; PostMessage(pp::Var(stream.str())); } void NaclPlatform::playSoundImpl(FruitClick::Platform::Sound id) { std::stringstream stream; stream << "playSound" << sep << id; PostMessage(pp::Var(stream.str())); }
ãŸããjavascriptã§ã¯ããããã®ã¡ãã»ãŒãžã解æãããŸãã
function handleMessage(message_event) { params = message_event.data.split("|"); if (params[0] == "draw") { draw(parseInt(params[1]), parseInt(params[2]), parseInt(params[3]), parseFloat(params[4])); } else if (params[0] == "drawText") { drawText(params[1], parseInt(params[2]), parseInt(params[3])); } else if (params[0] == "playSound") { playSound(parseInt(params[1])); } }
çµæ
ãã®åçŽãªã²ãŒã ã¯ãCatch the BullseyeãšåŒã°ããŸãã èµ·åããŠæ°åéä¿æããããšãããšãæåã¯æåããŸããã§ããã
- ãã€ãã£ãã¯ã©ã€ã¢ã³ãããŒãžã§ã³ ïŒææ°ããŒãžã§ã³ã®Google Chromeãã©ãŠã¶ãŒã䜿çšããŠããããšãããã³ãã€ãã£ãã¯ã©ã€ã¢ã³ããaboutïŒpluginsããã³aboutïŒãã©ã°ã«å«ãŸããŠããããšã確èªããŠãã ããïŒã nexeå®è¡å¯èœãã¡ã€ã«ã®ãµã€ãºã¯ã32ãããã·ã¹ãã ã®å Žåã¯4.2 MBã64ãããã·ã¹ãã ã®å Žåã¯4.9 MBã§ã;ãã£ããæ¥ç¶ããŠããéã¯å°ãåŸ ã€å¿ èŠããããŸãã
-WindowsããŒãžã§ã³ -Google Chromeãæ°ã«å ¥ããªã人åãã
ãããªïŒ
ãã®ã²ãŒã ã¯Androidãšãã¥ã¬ãŒã¿ãŒãšç§ã®LG Optimusã§åé¡ãªãåäœããŸãã Qt Simulatorã§ãåãç¶æ³ã§ãïŒãããã¯ã®åé ã®Nokia N9ã®ã¹ã¯ãªãŒã³ã·ã§ããïŒã
ã³ãŒã
ããã§ã³ãŒããååŸã§ããŸãããç¹ã«JavaãšC ++ãjavascriptãšC ++ã®çµã¿åãããæ åœããŠããã»ã¯ã·ã§ã³ïŒããã«ã€ããŠè³ªåãããå Žåã¯ããæ°è»œã«ãåãåãããã ããïŒ
ãªãã§ãããªããšïŒ
ããªãã®å€ãã¯ããªãèªè»¢è»ãæžãã®ã§ããããïŒ ããšãã°ã MarmaladeãŸãã¯Unityãããå Žåã ã¯ãããããã圌ãã¯ãéãããããŸãããããŠããªãåçŽãª2Dããã¡ãã®ããã«ãã®ãããªãããŒãŠã§ã€ãã§ããïŒ ãŸããQtã¯AndroidãšiOSã§èµ·åããŸãããå®éã«ã¯Androidã§ã¯é³å£°ãšOpenGLããªããŠãèµ·åã§ãããiOSå šè¬ã§ã¯YouTubeã®åç»ã®ã¿ã§ãã ç§ã¯Qtãæ¬åœã«å¥œãã§ãè¿ãå°æ¥ãiOSããã³Androidåãã®ã¢ããªã±ãŒã·ã§ã³ãMeeGoåãã®ã¢ããªã±ãŒã·ã§ã³ãšåããããç°¡åã«äœæã§ããããšãé¡ã£ãŠããŸãããçŸæç¹ã§ã¯ããããã®ãã©ãããã©ãŒã çšã«ä»ã®ããŒã«ã䜿çšããæ¹ãè¯ãã§ãããã
ã¡ãªãã
ãã®èšäºã§èª¬æããã¢ãããŒãã䜿çšãããšããã©ãããã©ãŒã ã«çžãããããšãªããå¿ èŠãªããŒã«ã䜿çšã§ããå°æ¥çã«ã¯ç°¡åã«å€æŽã§ããŸãã ãã¹ã¯ããã-QtãŸãã¯GTKãAndroid-libgdxãŸãã¯AndEngineãiOS-cocos2dã§ã¯ãéžæã¯ããªã次第ã§ãã ãã©ãããã©ãŒã ãæäŸããAPIã䜿çšããŠããšã³ãžã³ãå®å šã«æŸæ£ã§ããŸãã ã»ãšãã©ã®å Žåãåªãã匷åãªC ++ã䜿çšããŠããæ°ã«å ¥ãã®IDEã§ã³ãŒããèšè¿°ããã³ãããã°ã§ããŸãã
çæ
ãã¡ãããæ¬ ç¹ããããŸããããšãã°ãæ¢è£œã®UIã³ã³ããŒãã³ãã䜿çšã§ããªã-C ++ã§ããããå®è£ ããå¿ èŠããããŸãã ãŸãã¯ãã¢ããªã±ãŒã·ã§ã³ã®UIéšåãåãã©ãããã©ãŒã ã«è»¢éããŸãã ãŸããåãã©ãããã©ãŒã ã詳ããç¥ãå¿ èŠããããŸãããå®è·µã瀺ãããã«ããã®ç¥ãåãããå®å šã«éããããšã¯ã§ããŸããã
ç¶è¡ããã«ã¯ïŒ
C ++ã§ã®ã¢ãã€ã«ãã©ãããã©ãŒã çšã®ã²ãŒã ã¯ãŸã æªãèãã ãšæããŸããïŒ æã£ãŠããé³¥ãèŠãŠãã ããã ããŒããµãã¿ãŒã®çŽ æŽãããããã©ãŒãã³ã¹ãã楜ãã¿ãã ããã C ++ãµããŒãã¯ã»ãŒã©ãã«ã§ããããæ°ããæšæºC ++ 11ããã¹ãŠã®NDKã«å®è£ ãããåŸãããã«æ¹åããããšããäºå®ãèããŠãã ããã