Starlingを始める
Starlingとは、stage3Dで2D描画で扱いやすく作られたフレームワークです。
stage3Dではハードウェアアクセラレーションで高速なGPU描画が可能となります。
airアプリプロジェクトを作ってみたらはまったからメモ。
webアプリケーションの設定でプロジェクトを作ると、インストールされているFlashPlayerで実行できるんですが、airだとそうじゃないらしい。。。
怒られた。。
そこでair3.9っていう最新っぽいのを試してみる。
http://www.adobe.com/devnet/air/air-sdk-download.html
上記はコンパイラなので、以下のアーカイブを参照したほうがいいかも。
http://helpx.adobe.com/air/kb/archived-air-sdk-version.html
ランタイムバージョンを落としてみた。
けど、通らない…!
普通にwebアプリケーションプロジェクトとして始めようかな。
でもそれだと、ローカルでクロスドメインとか面倒なことでてきそうだな。
stage3Dではハードウェアアクセラレーションで高速なGPU描画が可能となります。
airアプリプロジェクトを作ってみたらはまったからメモ。
webアプリケーションの設定でプロジェクトを作ると、インストールされているFlashPlayerで実行できるんですが、airだとそうじゃないらしい。。。
怒られた。。
そこでair3.9っていう最新っぽいのを試してみる。
http://www.adobe.com/devnet/air/air-sdk-download.html
上記はコンパイラなので、以下のアーカイブを参照したほうがいいかも。
http://helpx.adobe.com/air/kb/archived-air-sdk-version.html
ランタイムバージョンを落としてみた。
けど、通らない…!
普通にwebアプリケーションプロジェクトとして始めようかな。
でもそれだと、ローカルでクロスドメインとか面倒なことでてきそうだな。
テンプレートメソッド、ファクトリーパターン
テンプレートメソッドパターン
大本の汎用的なアルゴリズムを記述したテンプレートクラス抽象インターフェース
package factory
{
public interface IField
{
// 「フィールドを描く」というメソッドを定義
function drawField():void;
}
}
実装クラス
package factory
{
public class FootballField implements IField
{
public function FootballField()
{
}
public function drawField():void
{
trace('Drawing the Football Fieald!');
}
}
}
抽象テンプレートクラス
package factory
{
/**
* テンプレートメソッド抽象クラス
*
*/
public class BaseGame
{
public function BaseGame()
{
}
public function initialize():void
{
// 無処理
}
public function createField():IField
{
throw new Error('createField:Abstract Methd!');
}
}
}
継承クラス
package factory
{
/**
* テンプレートメソッドを継承するクラス
*
*/
public class FootballGame extends BaseGame
{
public function FootballGame()
{
super();
}
override public function initialize():void
{
var field:IField = createField();
field.drawField();
}
override public function createField():IField
{
return new FootballField();
}
}
}
コードだけでは理解するのが難しいので、クラス図を書いたほうがいい。
「テンプレートとなる抽象クラスで処理のアルゴリズムを書き、
抽象インターフェースで各処理の詳細を記述していく」
というイメージかな。
シングルトンパターン
デザインパターンの勉強を始めたので、その勉強録です。
まともに今までデザインパターンを勉強したことがなく、なんとなくソース読んで、似たような仕様で書くっていうのを今まで繰り返してました。
インターンの時にシングルトンを全く意味不明なまま使っていて、結局その時理解せずにインターンを終えてしまった苦い思い出が思い出されます。
今回はこの本に沿って、ActionScriptでデザインパターンを勉強していきたいと思います。(本当はC++とかでやりたい)
ActionScriptでデザインパターンを解説している唯一の本で、丁寧に解説してくれていて理解しやすいと思います。
静的なデータとかこういった形で持つ事が多いですかね。
SingletonEnforcerクラス
シングルトンのクラスのみが使用できるSingletonEnforcerクラスをコンストラクタの引数にして、強制的にコンストラクタを外部で呼び出せなくする手法。
まともに今までデザインパターンを勉強したことがなく、なんとなくソース読んで、似たような仕様で書くっていうのを今まで繰り返してました。
インターンの時にシングルトンを全く意味不明なまま使っていて、結局その時理解せずにインターンを終えてしまった苦い思い出が思い出されます。
今回はこの本に沿って、ActionScriptでデザインパターンを勉強していきたいと思います。(本当はC++とかでやりたい)
ActionScriptでデザインパターンを解説している唯一の本で、丁寧に解説してくれていて理解しやすいと思います。
シングルトンパターン
「クラスのインスタンスを一つしか作らない」ようにするパターンです。静的なデータとかこういった形で持つ事が多いですかね。
SingletonEnforcerクラス
シングルトンのクラスのみが使用できるSingletonEnforcerクラスをコンストラクタの引数にして、強制的にコンストラクタを外部で呼び出せなくする手法。
package
{
/**
* シングルトンパターンクラス
*
*/
public class SingletonClass
{
// privateでstaticな変数
private static var _instance:SingletonClass;
/**
* constructor
*
*/
public function SingletonClass(enforcer:SingletonEnforcer)
{
}
/**
* インスタンス取得メソッド
* @return SingletonClass
*
*/
public static function getInstance():SingletonClass
{
if (SingletonClass._instance == null)
{
SingletonClass._instance = new SingletonClass(new SingletonEnforcer());
}
return SingletonClass._instance;
}
public function sayHello():void
{
trace('Hello World');
}
}
}
/**
* コンストラクタを強制的に呼び出せなくするため
* 外部からアクセス不可能な空クラスを定義
*
*/
class SingletonEnforcer {}
AS3でカスタムイベント
Flash開発する上ではイベントの処理は必要ですよね。 僕はFlashを勉強し始めて、二週間ちょっとですが、もう何回使ったかわかりません。 そのくらい頻繁に用いるイベント処理。 ゲームを制作する時とかは自分でイベントを作りたくなります。 「着地した瞬間」とか「的に当たった瞬間」とか「ゴール地点に到達した瞬間」とかね。 今日、カスタムイベントの定義の方法を勉強したので、復習を込めた備忘録です。
カヤックのブログの説明がよかったです。
今回作成したサンプルです。
壁にボールが当たるとイベントが発生します。
【Main.as】
メインのクラス
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
/**
* 円をクリックすれば、ステージを円が跳ね返っていく
* 跳ね返った瞬間にイベントディスパッチする
*/
public class Main extends MovieClip {
// キャラインスタンス
private var chara:Chara;
// 壁にあたった回数
private var cnt:uint;
public function Main() {
// キャラのインスタンスを生成
chara = new Chara();
// クリックイベントを設定
chara.addEventListener(MouseEvent.CLICK, onCharaClick);
// 壁に当たるカスタムイベントを設定
chara.addEventListener(CharaEvent.HIT_WALL, onCharaHitWall);
// 中央に配置
chara.x = stage.stageWidth / 2;
chara.y = stage.stageHeight / 2;
addChild(chara);
// 壁にあたった回数
cnt = 0;
// テキスト表示
outputText.text = cnt.toString() + "回 壁にあたった";
}
/**
* キャラのクリックイベント
* @param {MouseEvent.CLICK} e : マウスイベントオブジェクト
* @return {void} :
*/
private function onCharaClick(e:MouseEvent):void {
// キャラの毎フレームイベントを設定
chara.addEventListener(Event.ENTER_FRAME, onCharaEnterFrame);
}
/**
* キャラの毎フレーム関数
* @param {Event} e : イベントオブジェクト
* @return {void} :
*/
private function onCharaEnterFrame(e:Event):void {
chara.moveChara();
}
/**
* キャラが壁にあたったイベントハンドラ
* @param {CharaEvent} e : キャライベントオブジェクト
* @return {void} :
*/
private function onCharaHitWall(e:CharaEvent):void {
// 壁にあたった回数をインクリメント
cnt++;
trace("壁にあたった" + cnt.toString() + "回");
// テキスト表示
outputText.text = cnt.toString() + "回 壁にあたった";
}
}
}
【Chara.as】
キャラの動きとイベントの設定
package {
import flash.display.MovieClip;
public class Chara extends MovieClip {
// キャラのスピード
private var speedX:int;
private var speedY:int;
public function Chara() {
// ランダムなスピードの値設定
speedX = Math.random() * 10;
speedY = Math.random() * 10;
}
/**
* キャラを動かす関数
* @param {} :
* @return {void} :
*/
public function moveChara():void {
// 動かす
x += speedX;
y += speedY;
// 壁にあたったかどうかのフラグ
var isHitWall:Boolean = false;
// 壁にあたった時のはねかえり処理
if(x < width / 2) {
x = width / 2;
speedX *= -1;
isHitWall = true;
} else if(x > stage.stageWidth - width / 2) {
x = stage.stageWidth - width / 2;
speedX *= -1;
isHitWall = true;
}
if(y < height / 2) {
y = height / 2;
speedY *= -1;
isHitWall = true;
} else if(y > stage.stageHeight - height / 2) {
y = stage.stageHeight - height / 2;
speedY *= -1;
isHitWall = true;
}
// ヒットイベントをブロードキャスト( = 登録されたリスナーのメソッドを実行する)する
if(isHitWall == true) {
var evt:CharaEvent = new CharaEvent(CharaEvent.HIT_WALL);
dispatchEvent(evt);
}
}
}
}
【CharaEvent.as】
このクラスでイベントを定義している
package {
import flash.events.Event;
public class CharaEvent extends Event {
// イベントの種類を定義(静的なプロパティ)
public static const HIT_WALL:String = "hitWall";
public function CharaEvent(type:String, bubbles:Boolean = false, cancelable:Boolean = false) {
// 継承元のEventクラスのコンストラクタを呼び出す
super(type, bubbles, cancelable);
}
// EventDispacherを呼び出すためのオーバーライド
override public function clone():Event {
return new CharaEvent(type, bubbles, cancelable);
}
// toString()出力用
override public function toString():String {
return formatToString("CharaEvent", "type", "bubbles", "cancelable");
}
}
}
FlashからJSON書き出し
タイトルの通り、FlashからJSONファイルの書き出しをやってみました。
今回は、「Flashからphpファイルに値を渡して、それをJSON形式で書き出す」という流れです。
こちらのサイトにphpとFlashの連携方法が書かれていたので、そちらを参考にしつつ行いました。
AS3でPHPと通信する
【ConnectPHP.as】
package connectphp
{
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.net.URLRequestMethod;
import flash.net.URLVariables;
public class ConnectPHP extends EventDispatcher
{
public static const COMPLETE:String = "connectPHP_complete";
/**
* コンストラクタ
*/
public function ConnectPHP(url:String = null, variables:Object = null)
{
if (url && variables)
{
sendAndLoad(url, variables);
}
}
/**
* phpファイルにデータの内容を送信する
* @param {String} : phpデータのパス
* @param {String} : データの中身
*/
public function sendAndLoad(url:String, variables:Object):void
{
var urlRequest:URLRequest = new URLRequest(url);
// php に送信するデータをオブジェクト形式で保存する
var urlVariables:URLVariables = new URLVariables();
// 引数のデータを全て渡す
for (var i:String in variables)
{
urlVariables[i] = variables[i];
}
// urlRequest.dataに渡す
urlRequest.data = urlVariables;
// phpへの送信方法
urlRequest.method = URLRequestMethod.POST;
// phpファイルをリクエスト
var urlLoader:URLLoader = new URLLoader();
urlLoader.dataFormat = URLLoaderDataFormat.VARIABLES;
urlLoader.addEventListener(Event.COMPLETE, completeHandler);
urlLoader.load(urlRequest);
}
/**
* phpファイルの呼び出しが終了したときのイベントハンドラ
*/
private function completeHandler(e:Event):void
{
// イベントディスパッチ
dispatchEvent(new Event(COMPLETE));
}
}
}
【data.php】
phpファイル
このファイルを通せば、"name".jsonというJSON形式のファイルが出来上がります。
// 保存する中身
$name = $_POST["name"];
$userData = $_POST["userData"];
// jsonデータ
$dataFile = "$name.json";
// 書き込むデータ
$contents = "$userData";
// データを開く(データ名が存在しない場合は、作成を試みる)
$fp = fopen($dataFile, "w");
// データを書き込む
if(fwrite($fp, $contents) === false) { // 型も値も含めて厳密に比較してくれる
echo "書き込めなかった";
exit;
}
fclose($fp);
?>
【Main.as】
メインのドキュメントクラス
package connectphp
{
import flash.display.MovieClip;
import flash.events.Event;
import connectphp.*;
public class Main extends MovieClip
{
/**
* コンストラクタ
*/
public function Main()
{
// 保存したいデータのオブジェクトを作る
var userData:Object = {
// 名前
name: "tanaka",
// 買い物リスト
item:[
"ファブリーズ",
"ジョイ",
"キャベツ",
"カレールー",
"じゃがいも"
]
};
// オブジェクトをJSON形式の文字列に変換
var userDataForJson:String = JSON.stringify(userData);
// 送るデータ
var sendData:Object = new Object();
sendData.name = userData.name.toString();
sendData.userData = userDataForJson;
// データをphpに送る
var connectPHP:ConnectPHP = new ConnectPHP();
connectPHP.addEventListener(ConnectPHP.COMPLETE, completeHandler);
connectPHP.sendAndLoad("data.php", sendData);
}
private function completeHandler(e:Event):void
{
trace("送信完了");
}
}
}
earth.idlコンパイル方法
(1) Microsoft Visual C++ 2008 Express EditionからVisual Studio 2008 コマンド プロンプトを起動
(2) コマンドラインは以下の通り
midl /cpp_cmd cl.exe /cpp_opt "/E" /out "出力先ディレクトリ" "earth.idlのあるディレクトリ"
*スペースに注意
参考:IDLコンパイル成功!
http://futr.cocolog-nifty.com/blog/2008/04/idl_f4f5.html
Google Earth COM API を C++ で使う
http://oshiro.bpe.es.osaka-u.ac.jp/people/staff/imura/computer/misc/google_earth_com_api/disp_content
------以下サンプルプログラムを空のプロジェクトから記述(追加のインクルードファイルにearth.hを追加)------
// main.cpp
(2) コマンドラインは以下の通り
midl /cpp_cmd cl.exe /cpp_opt "/E" /out "出力先ディレクトリ" "earth.idlのあるディレクトリ"
*スペースに注意
参考:IDLコンパイル成功!
http://futr.cocolog-nifty.com/blog/2008/04/idl_f4f5.html
Google Earth COM API を C++ で使う
http://oshiro.bpe.es.osaka-u.ac.jp/people/staff/imura/computer/misc/google_earth_com_api/disp_content
------以下サンプルプログラムを空のプロジェクトから記述(追加のインクルードファイルにearth.hを追加)------
// main.cpp
#include
#include
#include "earth.h"
using namespace std;
int
main( int argc, char **argv )
{
IApplicationGE *app;
ICameraInfoGE *camera;
HRESULT hr;
// COMの初期化
CoInitialize( 0 );
// IApplicationGE を得る
hr = CoCreateInstance(
CLSID_ApplicationGE,
0,
CLSCTX_LOCAL_SERVER,
IID_IApplicationGE,
reinterpret_cast( &app ));
if ( FAILED( hr )) {
cerr << "cannot create IApplicationGE" << endl;
return -1;
}
// Google Earth の情報を得る
AppTypeGE app_type;
int major, minor, build;
app->get_VersionAppType( &app_type );
app->get_VersionMajor( &major );
app->get_VersionMinor( &minor );
app->get_VersionBuild( &build );
cout << "You are using ";
switch ( app_type ) {
case EnterpriseClientGE:
cout << "Google Earth Enterprise Client" << endl;
break;
case ProGE:
cout << "Google Earth Pro" << endl;
break;
case PlusGE:
cout << "Google Earth Plus" << endl;
break;
case FreeGE:
cout << "Google Earth Free" << endl;
break;
default:
cout << "Unknown" << endl;
break;
}
cout << "version: " << major << "." << minor << "." << build << endl;
// 初期化が終了するまで待つ
BOOL is_initialized;
do {
hr = app->IsInitialized( &is_initialized );
} while ( is_initialized == false );
// 現在のカメラ位置に関する情報を得る
// まずカメラのインスタンスを取得する
hr = app->GetCamera( true, &camera );
if ( FAILED( hr )) {
cerr << "IApplicationGE::GetCamera() failed" << endl;
return -1;
}
// 各種パラメータの値を得る
double lat, lon, alt;
AltitudeModeGE alt_mode;
double range, tilt, azimuth;
camera->get_FocusPointLatitude( &lat ); // 緯度
camera->get_FocusPointLongitude( &lon ); // 経度
camera->get_FocusPointAltitude( &alt ); // 高度
camera->get_FocusPointAltitudeMode( &alt_mode ); // 高度の計測方法
camera->get_Range( &range );
camera->get_Tilt( &tilt );
camera->get_Azimuth( &azimuth );
cout << "現在の視点情報" << endl;
cout << "注視点の緯度: " << lat << endl;
cout << "注視点の経度: " << lon << endl;
cout << "注視点の高度: " << alt << endl;
cout << "高度の原点は地表: " << alt_mode << endl;
cout << "注視点からの距離: " << range << endl;
cout << "天頂角: " << tilt << endl; // 水平だと90度
cout << "方位角: " << azimuth << endl; // 注視点に対して視点が真南にあると
// 0度。そこから時計まわりに角度が増える。
// カメラを設定する
app->SetCameraParams( 34.7316, // 緯度
135.734, // 経度
0.0, // 高度
RelativeToGroundAltitudeGE, // 高度の計測方法
300.0, // 距離
0.0, // 天頂角
0.0, // 方位角
0.1 ); // 移動速度 (5.0より大きいと瞬時に移動)
// 終了
CoUninitialize();
return 0;
}
for each
var mc1:MovieClip = new MovieClip();
mc1.name = 'material';
var mc2:MovieClip = new MovieClip();
mc2.name = 'furniture';
var mc3:MovieClip = new MovieClip();
mc3.name = 'instant';
var obj:Object = {
material: mc1,
furniture:mc2,
instant:mc3
};
trace('--------------------------------------');
for (var key:String in obj)
{
trace(obj[key]);
trace(key);
}
/*
[object MovieClip]
furniture
[object MovieClip]
instant
[object MovieClip]
material
*/
trace('obj[item]--------------------------------------');
for each(var item:String in obj)
{
trace(item);
}
/*
[object MovieClip]
[object MovieClip]
[object MovieClip]
*/
trace('elementがobjになる--------------------------------------');
for each(var element:Object in obj)
{
trace(element);
}
/*
[object MovieClip]
[object MovieClip]
[object MovieClip]
*/