UbuntuでもD言語からSDLを使ってみる

ゲームなどを作るときによく使われる画面描画ライブラリの一つに「SDL」というのがあります。
D言語からSDLを使う場合は、Windowsの場合の方法は結構見つかりますが、Linuxだとあまり見つかりません。
なので適当に書いてみました。

SDLのインストール

Ubuntuなら簡単です。

sudo apt-get install libsdl-dev

これで、SDLC言語用ライブラリ自体は簡単にインストールできます。

D言語用ライブラリの準備

http://shinh.skr.jp/d/porting.html」の「SDL」をクリックしてダウンロードし、ダウンロードした圧縮ファイルを解凍して出てきた「SDLディレクトリを、
適当に作っておいた作業用ディレクトリの中に入れました。
しかし、D言語用ライブラリが作られた時とD言語のバージョンが違うため、このままでは動きません。このまま使ってしまうと、

SDL/SDL_version_.d(66): Error: identifier 'bit' is not defined
SDL/SDL_version_.d(66): Error: bit is used as a type
SDL/SDL_cdrom.d(52): Error: identifier 'bit' is not defined
SDL/SDL_cdrom.d(52): Error: bit is used as a type
SDL/SDL_video.d(135): Error: identifier 'bit' is not defined
SDL/SDL_video.d(135): Error: bit is used as a type
SDL/SDL_video.d(189): Error: identifier 'bit' is not defined
SDL/SDL_video.d(189): Error: bit is used as a type
SDL/SDL_quit.d(43): Error: identifier 'bit' is not defined
SDL/SDL_quit.d(43): Error: bit is used as a type

こんなエラーが出てしまいます。
それを回避するためには、プログラムを書き換える必要があります。
エラーメッセージを読んで、エラーに出てきたソースコードで、「bit」という型を使っているところを、全て「bool」型を使うように書き換えておきます。
そうすれば動作するようになります。

使ってみる

さっき「SDLディレクトリを入れた作業用ディレクトリの中に、
http://www5.atwiki.jp/yaruhara/pages/74.html#id_f29e7466 このページの「SDLを動かす(画面を出す)」というところにあるプログラムを、「sdltest.d」という名前で保存しました。
そして、「dmd sdltest.d -ISDL -L-lSDL」でコンパイルします。
コンパイルすると「sdltest」という実行ファイルができるので、それを実行すればウィンドウが表示されます。


コードを書き換える以外は一般的なやり方だと思います。
他のライブラリにも応用できそうな気もするので、別のライブラリでも試してみたいです。

Google App EngineをScalaで使ってみる。

久しぶりのScalaだったので少し忘れているところもあって苦労しましたが、なんとか動かすことができました。
方法を書いておきます。

http://code.google.com/intl/ja/appengine/docs/java/gettingstarted/creating.html
http://code.google.com/intl/ja/appengine/docs/java/tools/ant.html
http://www.scala-lang.org/node/98
この三つのページなどを参考にしてやってみました。

ちなみに、JREJDK、GAEのSDKScala以外にも、antが必要です。

まずはディレクトリを作る

GaeTest/
  src/
    META-INF/
  war/
    WEB-INF/
      lib/
      classes/

こんな感じになるように、適当にディレクトリを作っておきます。

ビルド設定ファイルを書く

GaeTestディレクトリの中に、

<project>
  <property name="sdk.dir" location="/home/ユーザー名/appengine-java-sdk" />
  <property environment="env" />
  <import file="${sdk.dir}/config/user/ant-macros.xml" />
  <path id="project.classpath">
    <pathelement path="war/WEB-INF/classes" />
    <fileset dir="war/WEB-INF/lib/">
      <include name="**/*.jar" />
    </fileset>
    <fileset dir="${sdk.dir}/lib">
      <include name="shared/**/*.jar" />
    </fileset>
  </path>
  <target name="copyjars" description="Copies the App Engine JARs to the WAR.">
    <copy
      todir="war/WEB-INF/lib"
      flatten="true">
      <fileset dir="${sdk.dir}/lib/user">
        <include name="**/*.jar" />
      </fileset>
    </copy>
    <copy
      todir="war/WEB-INF/lib"
      flatten="true">
      <fileset dir="${env.SCALA_HOME}/lib">
        <include name="scala-library.jar" />
      </fileset>
    </copy>
  </target>
  <target name="compile" depends="copyjars" description="Compile program">
    <taskdef
      resource="scala/tools/ant/antlib.xml"
      classpath="tools/scala-compiler.jar">
      <classpath>
        <pathelement location="${env.SCALA_HOME}/lib/scala-compiler.jar" />
        <pathelement location="${env.SCALA_HOME}/lib/scala-library.jar" />
      </classpath>
    </taskdef>
    <mkdir dir="war/WEB-INF/classes" />
    <copy todir="war/WEB-INF/classes">
      <fileset dir="src">
        <exclude name="**/*.java" />
      </fileset>
    </copy>
    <scalac
      srcdir="src"
      destdir="war/WEB-INF/classes"
      classpathref="project.classpath" />
  </target>
  <target name="datanucleusenhance" depends="compile"
    description="Performs JDO enhancement on compiled data classes.">
    <enhance_war war="war" />
  </target>
  <target name="runserver" depends="datanucleusenhance"
    description="Starts the development server.">
    <dev_appserver war="war" />
  </target>
</project>

こんな感じのXMLファイルを、「build.xml」という名前で置いておきます。

プログラムを書く

srcディレクトリの中に「gaetest」というディレクトリを作り、
その中に「TestServlet.scala」という名前でこんなプログラムを書きました。

package gaetest

import java.io.IOException
import javax.servlet.http._

class TestServlet extends HttpServlet {
  override def doGet(req: HttpServletRequest, resp: HttpServletResponse) = {
    resp.setContentType("text/plain")
    resp.getWriter().println("Hello, Scala world!")
  }
}

設定ファイルを書く

warディレクトリの中にあるWEB-INFディレクトリの中に、二つのファイルを作ります。
まずはweb.xmlです。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE web-app PUBLIC
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
  <servlet>
    <servlet-name>gaetest</servlet-name>
    <servlet-class>gaetest.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>gaetest</servlet-name>
    <url-pattern>/gaetest</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

こんな感じです。次は、appengine-web.xmlです。

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application></application>
  <version>1</version>
</appengine-web-app>

こんな感じのファイルを置いておきます。

ビルドして実行

最後に、GaeTestディレクトリに戻り、
「ant compile」というコマンドを実行してビルドします。
そして、「ant runserver」というコマンドを実行すると、開発用サーバーが起動します。
ブラウザで「http://localhost:8080/gaetest」にアクセスすると、「Hello, Scala world!」と表示されます。

ニコニコ動画をHTML5で再生するBookmarkletをChrome拡張にしてみた

ニコニコ動画HTML5で再生するBookmarklet「NicoHTML5」(http://d.hatena.ne.jp/saiten/20100225/1267110155)をGoogle Chromeの拡張にしてみました。

注意: この拡張にはまだうまく動かないところや変な動作をするところもあるので、使用は自己責任でお願いします。
さらに、HTML5再生に対応した動画(H.264形式)ではコメントができなくなってしまいます。(元のBookmarkletの仕様)
Google Docsにアップロードしておきました。ダウンロード
ソースコードもzip圧縮してアップロードしています。ダウンロード

Bookmarkletが読み込むJavascriptを少し書き換えて、拡張の一部にして使っています。
HTML5再生に対応した動画(H.264形式)か、そうでないかを判定し、自動的に切り替えるようになっていますが、少し変なところもあるようです。
ただ拡張にしただけではなく、元のBookmarkletXMLHttpRequestの制限により、再生するのに一つ手間がかかるのですが、
クロスドメイン通信ができる拡張では、それがいらなくなっています。
大部分はContent Scriptsで作られていますが、Content Scriptsだけではクロスドメイン通信ができないので、動画情報データの取得部分だけはBackground Pagesを使ってやっています。

Content Scriptsのコードとscriptタグで読み込まれたスクリプトの間でデータを受け渡すのに、受け渡し専用のdivタグを入れたりと変な方法を使っています。

Gaucheのパターンマッチを使いやすくするマクロを作った。

Gaucheでもutil.matchを使えばパターンマッチができますが、括弧が多いのであまり読みやすいとは言えません。
それをなんとかしようと思い、書いてみました。

こんな感じになっています。

このマクロを使えば、階乗はこんな感じに書けます。括弧が減るので読みやすくなります。

(def fact
  0 -> 1
  n -> (* n (fact (- n 1))))

Gaucheの「pa$」は結構便利ですね。特に、述語を受け取ることが多いリスト処理関係のところで便利です。

Google翻訳の読み上げ機能をJavascriptから使えるようにするライブラリ「gtts.js」を作ってみた。

元は現在進行中のプロジェクトの一部でしたが、ライブラリ化したら便利だと思い、ライブラリとして使えるようにして、
さらに、バージョン管理ソフトの勉強も兼ねてGitHubに投稿してみました。

ライブラリは http://github.com/tana/gtts.js ここにあります。
まだページなども作れていないです。

とりあえず、今回は使い方などを書いておきます。

説明

このライブラリはJavascriptなので、HTMLのscriptタグを使って読み込んで使います。これは他のJavascriptライブラリと同じですね。
Google翻訳の読み上げ機能のAPIは音声をMP3形式で出力するので、それを再生して使います。
HTML5には音声再生用のaudioタグがありますが、対応していない環境も多く、audioタグは使えてもMP3には対応しない場合も多いので、今回はFlashを使っています。
しかし、AdobeFlash作成ソフトは持っていないので、前回使ってみたhaXeを使って作りました。
使う時は、こんな感じで使えます。

Gtts.init();
Gtts.speak("hello", "en");

「Gtts.init」関数で、ライブラリを使う準備をしています。中では、HTMLのbodyの中にFlashのobjectタグを入れたりしています。
この関数は、通常は引数はいりませんが、HTMLがあるディレクトリとは別のディレクトリにgtts.swfがある場合、gtts.swfの場所を指定することができます。
「Gtts.speak」関数で、テキストを読み上げます。最初の引数には読み上げるテキスト、二つ目の引数には、テキストの言語を指定します。英語の場合は「en」です。

関数はこの二つしかありません。シンプルです。

これからやりたいこと

  1. audioタグが使える環境ではそれを使うようにする。
  2. もっとわかりやすいドキュメントを書く。

今回はとてもわかりにくい文章になってしまったと思います。この記事を最後まで読んでくれてありがとうございました。

haXeという言語を使ってみた。

JavascriptFlashPHPなどを生成することができる、ActionScriptに似ているようで少し違うようなプログラミング言語haXe」を使ってみました。

インストール

Ubuntuなら、簡単です。

sudo apt-get install haxe

コンパイラはこれでインストールできます。

使ってみる

http://haxe.org/doc/flash/0_start ここを参考にしました。
まず、こんなコードを書いてみました。

import flash.text.TextField;
class Hello {
  static function main() {
    var tf = new TextField();
    tf.text = "Hello!";
    flash.Lib.current.addChild(tf);
  }
}

Flash用のコードなので、Flashコンパイルします。今回はFlash9以降で動くようにするので、

haxe -main Hello -swf9 hello.swf

コンパイルします。
生成された「hello.swf」をブラウザで開くと、、「Hello!」と表示されます。

Pure言語邪道テクニック? Whileを作る

この方法はあまり使うべきではないと思いますが、Pure言語で手続き型言語的なプログラムを書く方法として書いておきます。
まず最初に、While関数の定義です。

while expr body = body () $$ while expr body if expr ();
                = () otherwise;

普通に、「exprを実行してtrueだったらbodyを実行する」ということです。
exprとbodyは引数が一つの関数ですが、引数を与えているのは関数を実行させるためだけです。
次に、使い方の例として、「hogeという文字を10回出力する」というプログラムです。書き換えられる変数を使っています。

using system;
let c = ref 0;
while (\x -> get c < 10) (\x -> puts "hoge" $$ put c (get c + 1));

とても関数型言語のプログラムとは思えない書き方です。