無料で使える Subversion ホスティングサービス 「Assembla」を試す!

今日はプログラマ向け開発支援サービスの紹介です。

色々なプログラムを書いているうちに、自分なりのユーティリティー関数群、ライブラリなど、あとで参照したいソースコードがたまってきた、という経験は、趣味にしろ仕事にしろ、プログラムを書いている方ならあるんじゃないかと思います。

こういったソースは作業効率にも関わるので、どの環境でもアクセスできるのが理想なんですが、管理が意外と面倒くさいんですよね。


会社で便利なコードを書いたから、家でも使おうとしてUSBメモリにでも入れて持ち帰り、家で使うときに更に追記したので、また会社のPCに…なんてことはまどろっこしくてやってられませんし、コピーし忘れで入れたはずの機能がなくなってしまったりと、とても残念なことになりがちです。


こういうときはSubversionを使うと便利なんですが、このちょっとしたソースコードのために自宅にサーバを立てるってのもまた非効率でよろしくないですよね。


こういう時に便利なのがSubversionホスティングサービスです。
もちろん高機能なものを使いたい場合は有料ということになるんですが、今回のような用途で個人で使うレベルなら無料で提供してくれるサービスもいくつか存在します。


今日は「Assembla」というサイトを紹介したいと思います。
Secure Git, Secure Software Development in the Cloud | Assembla


このサイトでは非公開・リポジトリ機能のみの制限がありますが、2GBものストレージを無料で使うことができます。

このサービスを利用する手順を書いておきます。


2010年7月25日現在のAssemblaのトップページはこんな感じです。
このトップページから右上のRegisterを選択。
SC000



Registerをクリックすると以下のアカウント作成画面になると思います。
*が付いたものは入力必須です。必要な情報を入力してください。
SC001



アカウントが作成できたら、メニュータブの「Create a Space」をクリック。
ここで無料のプラン、今回は Free Private Subversion Repository を選択します。
左にあるタグ一覧から Free を選ぶと一番上に表示されるのでわかりやすいかと思います。
[+ SELECT THIS]をクリック。
SC002


Space作成画面です。
名前とURLだけを入力して、下のほうにあるCreate SpaceをクリックすればOKです。
SC003


これで完了です。
上のメニュータブから「Source/SVN」を選択するとSVNのURLが見れます。
SC004


あとはSubversionのクライアントソフトに上のURLを入力して利用するだけです。
まだクライアントを入れてないと言う方は TortoiseSVN が簡単でおすすめです。
tortoisesvn.tigris.org


色々な環境で使うだろうソースコードはここに一括してコミットしておけば、管理の手間もかかりませんし、どの環境でも編集・更新の作業が自由に出来ます。

私も今、iアプリ用のライブラリを作成中なので、ここにアップしておいて仕事の空いた時間にでも作業を進めようと思ってます。

HTML5のCanvasを試す

今更ですが、HTML5Canvasを試してみたいと思います。


次期HTMLの規格であるHTML5では、Canvasというものを使って直接図形が描画できるようになりました。
描画速度は、というとそれほど速いわけではないですが、描画の多いものでなければ十分な速度で動くゲームも作れたりします。
(HTML5関連の詳しい資料はHTML5.JP - 次世代HTML標準 HTML5情報サイトへ。)


Canvasのテストとして何を作ろうかと思っているときに、iPhoneアプリQuick Graphを見つけました。


これは式を入力すると、下画像のようなグラフが簡単に描画できるというアプリです。
iPod ScreenShot-Quick Graph


このアプリには、Libraryとして幾つか図形を描画できる式が入っているのですが、これが結構面白い形で感心したので、これらをCanvasで描画してみます。
(実行ボタンを押すと動作を開始します。表示されない場合、一度ブラウザを更新してみてください。)

そもそもCanvasに対応していないブラウザもあるようなので、環境によっては上のサンプルは動作しないかもしれません。とりあえず、FirefoxIEでは動作を確認しました。
(動作が重過ぎる場合、パスの描画をOFFにするとマシになると思います。)


本来ならば(当然と言うべきか)IECanvasには対応していません。


では、なぜこのサンプルがIEで動作するかというと、Google謹製のJavaScriptライブラリ「ExplorerCanvas」を使用しているためです。


このExplorerCanvasCanvasの描画をエミュレートするもので、これを使用すればCanvasに対応していないIEでもCanvasで描画させることができるのです。素晴らしい!さすがGoogle大先生!


しかし、IEJavaScriptの動作自体が遅いので、エミュレートさせたCanvasの描画はとても遅くなっています。
(追記:コメント欄でご指摘いただきました。JavaScriptの動作が遅いせいと言う以上に、描画にVMLを用いているから速度がでないのだそうです。)


上のサンプルでも5fps前後しかでないようです。
(また、今のところCanvasの動作を完全にエミュレートできるわけではなく、一部正しく動作しないコードもあるようです。)


まだちらっとしか触ってないCanvasですが、使いやすい感じですね。
JavaScriptでのゲーム製作がよりやりやすくなったんじゃないかと思います。


一応、今回のサンプルのコードを以下においておきます。

続きを読む

OpenGLによる3Dプログラミング

なにやら大仰なタイトルをつけてしまいましたが、これからしばらくOpenGLを使っての3Dグラフィックのプログラミングについて書いていきたいと思います。
とりあえずはOpenGLのインストールから。


今回はこちらのGLUTをインストールしたいと思います。
http://www.xmission.com/~nate/glut.htm

OpenGLの利点として、OSに依存しないコードを書けるということがあるのですが、それはOpenGLがシステムとの連携を完全に捨てたためで、OpenGL自体にはウィンドウの表示などの機能はありません。

そこで、結局はシステムの連携部分でOS依存のコードを書かなければいけないのですが、GLUTはそのシステムとの連携部分をまるごとやってくれるというライブラリです。

GLUTを使えば、別環境への移植も簡単に出来ますし、OpenGLの利点を生かすためにも、今回はGLUTを利用したいと思います。



上記サイトからウィンドウズ向けのパッケージを入手します。
これを書いている時点でのバージョンは glut-3.7.6-bin.zip (117 KB) でした。
(このパッケージにOpenGLも含まれているので、ダウンロードするのはこのファイルだけでOKです)

入手したファイルを解凍後、開発環境にOpenGLを設定します。

[Visual Studioインストール先]\VC\include
内に"GL"というフォルダを作成して、glut.h をコピー。

[Visual Studioインストール先]\VC\lib
内に glut32.lib をコピー。

C:\WINDOWS\system32
内に glut32.dll をコピー。

これでOpenGLのインストールは完了です。



それでは早速、OpenGL+GLUTを使ってみます。
Visual Studioのプロジェクトの設定はコンソールアプリケーション、空のプロジェクトとしてください。
main.cppというファイルを作成。
以下をコピーしてビルドしてみてください。
ビルドに成功すればOpenGLが正しくインストールできたことになります。

#include <GL/glut.h>

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
}

int main(int argc, char *argv[])
{
    glutInit(&argc , argv);
    glutInitWindowPosition(100 , 50);
    glutInitWindowSize(500 , 500);
    glutInitDisplayMode(GLUT_RGBA);

    glutCreateWindow("Hello, OpenGL");
    glClearColor(0.0, 0.0, 1.0, 1.0);
    glutDisplayFunc(display);
    glutMainLoop();

    return 0;
}

[実行結果]
HelloOpenGL実行結果

glutDisplayFuncで設定された関数が描画イベントごとに呼び出されます。

glClearはglClearColorで設定された色で引数で指定されたバッファを塗りつぶし、glFlushで画面に出力しています。


とりあえず、OpenGLの導入は完了です。
なんかOpenGLのインストールって面倒な印象があったんですが、意外と簡単に出来ますね。

ActionScriptで文字の縁取りをする

ActionScriptで縁取り文字を表示したい場合、複数のテキストフィールドを作って、それらを上下左右に重ねて表示することで、それっぽいものができます。

ソースコードは以下のような感じです。

function createTF(mc:MovieClip, instname:String, x:Number, y:Number, w:Number, h:Number){
    var depth = mc.getNextHighestDepth();
    return mc.createTextField(instname, depth, x, y, w, h);
}

var format:TextFormat = new TextFormat;
format.size = 15;
format.bold = true;

var tf1:TextField = createTF(_root, "NormalText", 40, 40, 230, 40);
tf1.text = "縁取りなしのテキストです。";
tf1.setTextFormat(format);

function createEdgeText(text:String, mc:MovieClip, instname:String, x:Number, y:Number, w:Number, h:Number, fmt:TextFormat):Void
{
    var px:Array = [0,  1,  0, -1, 1, -1,  1, -1];
    var py:Array = [1,  0, -1,  0, 1, -1, -1,  1];
    var tf:TextField;
    
    for(var i:Number = 0; i < 8; ++i){
        tf = createTF(mc, instname+i, x + px[i], y + py[i], w, h);
        tf.text = text;
        tf.setTextFormat(fmt);
    }
    tf = createTF(mc, instname, x, y, w, h);
    tf.text = text;
    tf.textColor = 0xffffff;
    tf.setTextFormat(fmt);
}

createEdgeText("こちらが縁取りしたテキストです。", _root, "EdgeText", 40, 80, 230, 40, format);


今回のサンプルではTextFormatでboldを指定しています。別に必須というわけではないですが、これがないと、環境によっては汚く見えてしまうことがあるようです。

FlashDevelopで使えるボタンクラス

FlashDevelopで使えるボタンクラスを書きました。

SimpleButtonって名前が良かったんですが、それだと被ってしまうのでEasyButtonに。ちょっと変ですが。

package  
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.text.TextField;
    
    /**
     * 簡易ボタンクラス
     * @author valinst
     */
    public class EasyButton 
    {
        /** このクラスの描画オブジェクトはすべてこの上に存在する */
        private var buttonBase:Sprite;
        
        /** 各状態のボタンスプライト */
        private var upState:Sprite;
        private var overState:Sprite;
        private var downState:Sprite;
        
        /** ボタンのラベル */
        private var buttonText:TextField;
        
        /** 透明のボタンスプライト */
        private var clearButton:Sprite;
        
        /** ユーザー定義の各イベントの関数を保持 */
        private var events:Array/*of Function*/;
        
        /** ボタンの動作状態 */
        private var isEnable:Boolean;

        /**
         * コンストラクタ
         * @param   base   ボタンを置くスプライト
         * @param   text   ボタンの表示文字
         * @param   x      ボタンの位置X
         * @param   y      ボタンの位置Y
         * @param   width  ボタンの幅(省略可)
         * @param   height ボタンの高さ(省略可)
         */
        public function EasyButton(base:Sprite, text:String, x:int, y:int, width:int = 100, height:int = 20) 
        {
            // ベースとなるスプライトをボタンモードで作成
            buttonBase = new Sprite();
            buttonBase.buttonMode = true;
            
            // ボタンの各状態のスプライトを作成
            upState = makeRoundRect(0xEEEEEE, width, height, 10);
            overState = makeRoundRect(0xFFFFFF, width, height, 10);
            downState = makeRoundRect(0xDDDDDD, width, height, 10);         
            upState.visible = true;
            overState.visible = false;
            downState.visible = false;
            
            buttonBase.addChild(upState);
            buttonBase.addChild(overState);
            buttonBase.addChild(downState);
            
            
            // テキストフィールドの設定
            buttonText = new TextField();
            buttonText.y = height / 2 - 10;
            buttonText.width = width;
            buttonText.height = height;
            buttonText.text = text;
            buttonText.autoSize = "center";
            buttonText.selectable = false;
            buttonBase.addChild(buttonText);
            
            // そのままだと、テキストフィールド上でマウスのイベントが上手く動作しないので、
            // すべてを設定した後で、最後に透明のスプライトを被せる
            clearButton = makeRoundRect(0x000000, width, height, 10, 0);
            buttonBase.addChild(clearButton);
            
            buttonBase.x = x;
            buttonBase.y = y;
            base.addChild(buttonBase);
            
            buttonBase.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            buttonBase.addEventListener(MouseEvent.MOUSE_UP,   onMouseUp);          
            buttonBase.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
            buttonBase.addEventListener(MouseEvent.MOUSE_OUT,  onMouseOut);
            
            isEnable = false;
                        
            events = new Array;
        }
        
        /**
         * 各状態のときに呼び出される関数を設定
         * @param   event イベント
         * @param   func  設定する関数
         */
        public function addEventListener(event:String, func:Function):void
        {
            // 既にイベントが登録されていたら
            // event が MOUSE_DOWN, MOUSE_UP, MOUSE_OVER, MOUSE_OUT
            // という場合を想定
            if (buttonBase.hasEventListener(event)) {
                events[event] = func;
            }else {
                // ボタン側が処理する必要がないイベントも登録できるようにしておく
                buttonBase.addEventListener(event, func);
            }
        }
        
        /**
         * ボタンの表示文字を設定
         */
        public function set text(str:String):void
        {
            buttonText.text = str;
        }
        /**
         * ボタンの表示文字を取得
         */     
        public function get text():String
        {
            return buttonText.text;
        }
        
        /**
         * 表示状態を設定
         */
        public function set visible(flg:Boolean):void
        {
            buttonBase.visible = flg;
            if (flg && downState.visible) {
                downState.visible = false;
            }
        }       
        /**
         * 表示状態を取得
         */
        public function get visible():Boolean
        {
            return buttonBase.visible;
        }
        
        /**
         * ボタン動作状態を設定
         */
        public function set enable(flg:Boolean):void
        {
            isEnable = flg;
        }       
        /**
         * ボタン動作状態を取得
         */
        public function get enable():Boolean
        {
            return isEnable;
        }
        
        /**
         * ボタンが押されたとき
         * @param   event
         */
        private function onMouseDown(event:MouseEvent):void
        {
            if (isEnable) return;
            downState.visible = true;       
            if (events[MouseEvent.MOUSE_DOWN])
                events[MouseEvent.MOUSE_DOWN]();
        }
        /**
         * ボタンが離されたとき
         * @param   event
         */
        private function onMouseUp(event:MouseEvent):void
        {
            if (isEnable) return;
            downState.visible = false;
            if (events[MouseEvent.MOUSE_UP])
                events[MouseEvent.MOUSE_UP]();
        }
        /**
         * マウスが乗ったとき
         * @param   event
         */
        private function onMouseOver(event:MouseEvent):void
        {
            if (isEnable) return;
            overState.visible = true;
            if (events[MouseEvent.MOUSE_OVER])
                events[MouseEvent.MOUSE_OVER]();
        }
        /**
         * マウスが降りたとき
         * @param   event
         */
        private function onMouseOut(event:MouseEvent):void
        {
            if (isEnable) return;
            overState.visible = false;
            if (events[MouseEvent.MOUSE_OUT])
                events[MouseEvent.MOUSE_OUT]();
        }
        
        /**
         * 角丸の図形を描いたスプライトを作って返す
         * @param   color   色
         * @param   width   幅
         * @param   height  高さ
         * @param   round   角丸の大きさ
         * @return  スプライト
         */     
        private function makeRoundRect(color:uint, width:int, height:int, round:int, alpha:Number=1.0):Sprite
        {
            var s:Sprite = new Sprite();
            s.graphics.lineStyle(2, 0x888888, 1);
            s.graphics.beginFill(color);
            s.graphics.drawRoundRect(0, 0, width, height, round);
            s.graphics.endFill();
            s.alpha = alpha;
            return s;
        }
    }   
}

 
使い方サンプル

 

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    
    [SWF(width="300", height="300")]
    public class Main extends Sprite 
    {
        private var button:EasyButton;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point          
            button = new EasyButton(this, "ボタン", 100, 30);
            
            var bigButton:EasyButton = new EasyButton(this, "大きいボタン", 50, 70, 200, 200);
            bigButton.addEventListener(MouseEvent.MOUSE_DOWN, function():void {
                bigButton.text = "マウスダウン";
            });     
            bigButton.addEventListener(MouseEvent.MOUSE_UP, function():void {
                bigButton.text = "マウスアップ";
            });         
            bigButton.addEventListener(MouseEvent.MOUSE_OVER, function():void {
                bigButton.text = "マウスオーバー";
            });
            bigButton.addEventListener(MouseEvent.MOUSE_OUT, function():void {
                bigButton.text = "マウスアウト";
            });
        }
        
    }
    
}

 
基本的な機能しかないですが、SimpleButtonよりも使いやすいんじゃないかと思います。
とりあえずボタンが欲しいなって思ったときにどうぞ。
 
このクラスを書く上で参考にさせていただきました。
ボタン - FlashDevelop 用 AS 3 サンプル集

FlashDevelopで音を再生

FlashDevelopで音を再生したい場合のメモ。
 
サンプル

ソースコード

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.media.Sound;
    import flash.media.SoundChannel;
    import flash.media.SoundTransform;
    import flash.net.URLRequest;
    import flash.text.TextField;
    
    [SWF(width="200", height="100")]
    public class Main extends Sprite 
    {       
        private var sound:Sound;
        private var soundch:SoundChannel;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            
            // URLを指定して読み込み
            var urlRequest:URLRequest;
            urlRequest = new URLRequest("seikai.mp3");
            sound = new Sound(urlRequest);
            
            var text:TextField = new TextField;
            text.text = "クリックして再生";
            addChild(text);

            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        }
        
        private function onMouseDown(e:MouseEvent):void
        {
            // SoundTransformでボリュームを変更 -> 0.5
            var trans:SoundTransform = new SoundTransform(0.5);
            soundch = sound.play(0, 0, trans);

            // ※音を止める場合には soundch.stop(); というようにする
        }       
    }   
}

 

ちなみにFlashに音データを埋め込む場合は、以下のようになります。

package 
{
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.media.Sound;
    
    public class Main extends Sprite 
    {       
        [Embed(source = "../res/snd/seikai.mp3")] private static const sndSample:Class;
        
        private var sound:Sound;
        
        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            
            // 埋め込んだサウンドを使う
            sound = new sndSample as Sound;

            stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
        }
        
        private function onMouseDown(e:MouseEvent):void
        {
            sound.play(0, 0);
        }
    }   
}

 
今回サンプルで鳴らしているような効果音のファイルはWAV形式であることが多いので、FlashでWAVを再生する方法を探していたんですが、どうやらWAVをそのまま再生するというのは出来なくはないけど難しいらしいです。
まぁMP3にエンコードするって大した作業でもないので、別に問題ないですけどね。

ブラウザ上を猫が散歩するブックマークレット

ブラウザ上を猫が散歩するブックマークレットを書きました。



下記をブラウザのアドレス欄にコピペしてみてください。

javascript:(function(){d=document;s=d.createElement('script');s.setAttribute('src','http://gamedev.vs.land.to/hatena/javascript/wandercat00/WanderCat.js');d.documentElement.appendChild(s);}())

画面のどこかで、猫がうろちょろしているはずです。



RPGツクールで使うような16x16のキャラチップの小さな猫なので、見つかりにくいかもしれないです。
画面をクリックすると猫が一匹増えます。
※たまに猫じゃないのも出てきます。



FirefoxIEで動作を確認しましたが、猫を増やした場合にIEではちょっと処理速度が落ちるようです。




このスクリプト(WanderCat.js)のソースは以下においておきます。



以前作った迷路(JavaScriptで迷路の自動生成 - valinstの日記
のキャラ移動コードをそのまま使用しているので、ちょっと無駄が多めかもしれません。

続きを読む