無料で使える Subversion ホスティングサービス 「Assembla」を試す!
今日はプログラマ向け開発支援サービスの紹介です。
色々なプログラムを書いているうちに、自分なりのユーティリティー関数群、ライブラリなど、あとで参照したいソースコードがたまってきた、という経験は、趣味にしろ仕事にしろ、プログラムを書いている方ならあるんじゃないかと思います。
こういったソースは作業効率にも関わるので、どの環境でもアクセスできるのが理想なんですが、管理が意外と面倒くさいんですよね。
会社で便利なコードを書いたから、家でも使おうとしてUSBメモリにでも入れて持ち帰り、家で使うときに更に追記したので、また会社のPCに…なんてことはまどろっこしくてやってられませんし、コピーし忘れで入れたはずの機能がなくなってしまったりと、とても残念なことになりがちです。
こういうときはSubversionを使うと便利なんですが、このちょっとしたソースコードのために自宅にサーバを立てるってのもまた非効率でよろしくないですよね。
こういう時に便利なのがSubversionホスティングサービスです。
もちろん高機能なものを使いたい場合は有料ということになるんですが、今回のような用途で個人で使うレベルなら無料で提供してくれるサービスもいくつか存在します。
今日は「Assembla」というサイトを紹介したいと思います。
Secure Git, Secure Software Development in the Cloud | Assembla
このサイトでは非公開・リポジトリ機能のみの制限がありますが、2GBものストレージを無料で使うことができます。
このサービスを利用する手順を書いておきます。
2010年7月25日現在のAssemblaのトップページはこんな感じです。
このトップページから右上のRegisterを選択。
Registerをクリックすると以下のアカウント作成画面になると思います。
*が付いたものは入力必須です。必要な情報を入力してください。
アカウントが作成できたら、メニュータブの「Create a Space」をクリック。
ここで無料のプラン、今回は Free Private Subversion Repository を選択します。
左にあるタグ一覧から Free を選ぶと一番上に表示されるのでわかりやすいかと思います。
[+ SELECT THIS]をクリック。
Space作成画面です。
名前とURLだけを入力して、下のほうにあるCreate SpaceをクリックすればOKです。
これで完了です。
上のメニュータブから「Source/SVN」を選択するとSVNのURLが見れます。
あとはSubversionのクライアントソフトに上のURLを入力して利用するだけです。
まだクライアントを入れてないと言う方は TortoiseSVN が簡単でおすすめです。
tortoisesvn.tigris.org
色々な環境で使うだろうソースコードはここに一括してコミットしておけば、管理の手間もかかりませんし、どの環境でも編集・更新の作業が自由に出来ます。
私も今、iアプリ用のライブラリを作成中なので、ここにアップしておいて仕事の空いた時間にでも作業を進めようと思ってます。
HTML5のCanvasを試す
今更ですが、HTML5のCanvasを試してみたいと思います。
次期HTMLの規格であるHTML5では、Canvasというものを使って直接図形が描画できるようになりました。
描画速度は、というとそれほど速いわけではないですが、描画の多いものでなければ十分な速度で動くゲームも作れたりします。
(HTML5関連の詳しい資料はHTML5.JP - 次世代HTML標準 HTML5情報サイトへ。)
Canvasのテストとして何を作ろうかと思っているときに、iPhoneアプリのQuick Graphを見つけました。
これは式を入力すると、下画像のようなグラフが簡単に描画できるというアプリです。
このアプリには、Libraryとして幾つか図形を描画できる式が入っているのですが、これが結構面白い形で感心したので、これらをCanvasで描画してみます。
(実行ボタンを押すと動作を開始します。表示されない場合、一度ブラウザを更新してみてください。)
そもそもCanvasに対応していないブラウザもあるようなので、環境によっては上のサンプルは動作しないかもしれません。とりあえず、FirefoxとIEでは動作を確認しました。
(動作が重過ぎる場合、パスの描画をOFFにするとマシになると思います。)
本来ならば(当然と言うべきか)IEはCanvasには対応していません。
では、なぜこのサンプルがIEで動作するかというと、Google謹製のJavaScriptライブラリ「ExplorerCanvas」を使用しているためです。
このExplorerCanvasはCanvasの描画をエミュレートするもので、これを使用すればCanvasに対応していないIEでもCanvasで描画させることができるのです。素晴らしい!さすがGoogle大先生!
しかし、IEはJavaScriptの動作自体が遅いので、エミュレートさせた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; }
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のキャラチップの小さな猫なので、見つかりにくいかもしれないです。
画面をクリックすると猫が一匹増えます。
※たまに猫じゃないのも出てきます。
FirefoxとIEで動作を確認しましたが、猫を増やした場合にIEではちょっと処理速度が落ちるようです。
このスクリプト(WanderCat.js)のソースは以下においておきます。
以前作った迷路(JavaScriptで迷路の自動生成 - valinstの日記)
のキャラ移動コードをそのまま使用しているので、ちょっと無駄が多めかもしれません。