2010年3月7日

MiyakoでTetris


先日のエントリのとおり、Miyakoを使って、Tetrisを作ってみた。
ずいぶん時間がかかった。
Miyakoはあんまリアルタイムゲーム向きのライブラリじゃないのかな?
動きがぎくしゃく&キー入力が微妙。

これをもう少し遊べるように改造するのはありかもしれないけど、とりあえず、「できた!」ってことで、終わりにしておこうかな。

ちなみに所要時間は、4日ぐらいかな。
スコアをつける、落下スピードを変える(早くなる)、ブロック消すときのイフェクト、次のブロックを表示、などの改善が考えられそう。
というか、こういうのを改善しないと、ゲームとしてはおもしろくないですね。

ソースは、以下に貼り付けておきます。


# -*- coding: utf-8 -*-
# Miyako Tetris
#
#
# 2010 mole

require 'miyako'

include Miyako

$sprite_size=16
$depth=2
Width = 10
Height = 20
Color[:gray] = [200,200,200,255]
Color[:orange] = [255, 160, 64]
Color[:dark_orange] = [80, 50, 20]
Color[:half_orange] = [128, 80, 32]
# 画面描画自動化のために、Sprite.[]=メソッドで登録
# Sprite[:blocks] = @blocks
# Sprite[:red_ruby] = @red_ruby
# Sprite[:blue_dia] = @blue_dia




$blockcolors = Array.new(7)
$blockcolors[0] = "black"
$blockcolors[1] = "green"
$blockcolors[2] = "cyan"
$blockcolors[3] = "blue"
$blockcolors[4] = "orange"
$blockcolors[5] = "purple"
$blockcolors[6] = "yellow"
$blockcolors[7] = "red"
$blockcolors[8] = "gray"

Blockparts = Array.new(7)
Blockparts[0] = []
Blockparts[1] = [[-1,0],[0,0],[0,1],[1,1]] # tetris
Blockparts[2] = [[0,0],[1,0],[-1,1],[0,1]] # invers tetris
Blockparts[3] = [[0,0],[0,1],[1,1],[2,1]] # L
Blockparts[4] = [[-1,0],[0,0],[1,0],[2,0]] # bar
Blockparts[5] = [[0,0],[0,1],[1,0],[2,0]] # invers L
Blockparts[6] = [[-1,0],[0,0],[1,0],[0,1]] # T
Blockparts[7] = [[0,0],[1,0],[0,1],[1,1]] # square


class Blocks
def initialize(tp = 1, x = 5, y = 1)
@tp = tp
@x = x
@y = y
@parts = Marshal.load(Marshal.dump(Blockparts[@tp]))
end
def move(nx, ny)
if check_move(nx,ny) then
@x=nx
@y=ny
end
end
def turn()
@parts.each {|bp|
bx = bp[0]
by = bp[1]
bp[0] = -by
bp[1] = bx
}
if !check_move() then
@parts.each {|bp|
bx = bp[0]
by = bp[1]
bp[0] = by
bp[1] = -bx
}
end
end
def check_move(nx = @x, ny = @y)
@parts.each {|bp|
new_pos = nx+bp[0]+(ny+bp[1])*(Width+2)
if !((new_pos>0) and (new_pos < (Width+2)*(Height+1)) and $stage[new_pos] == 0) then
return false
end
}
return true
end

def show()
@parts.each {|bp|
draw_block(@x+bp[0],@y+bp[1],$blockcolors[@tp])
}
end
def fix()
@parts.each {|bp|
$stage[@x+bp[0]+(@y+bp[1])*(Width+2)]=@tp
}
end
attr_accessor :x,:y,:parts, :tp
end

def erase_line (auto_erase = true)
filled_line = Array.new
for i in 1..19 do
check_line = 0
for j in 1..Width do
check_line = check_line+1 if $stage[j+i*(Width+2)]>0
end
if check_line == Width then
filled_line << i
end
end
filled_line.each{ |l|
for i in 0..l-1 do
for j in 1..Width do
$stage[j+(l-i)*(Width+2)]=$stage[j+(l-i-1)*(Width+2)]
end
end
}

end

def new_game()
@bl1=Blocks.new(1)
@tet_timer = WaitCounter.new(300)
$start = 1
$gameover = false
@tet_timer.start
clear_stage()
end

def s_pos(x,y)
return x+y*(Width+2)
end

def draw_stage()
for i in 0..Width+1 do
for j in 0..Height do
draw_block(i,j,$blockcolors[$stage[s_pos(i,j)]])
end
end
@bl1.show()
end

def clear_stage()
$stage = Array.new((Width+2)*(Height+1),0)
for i in 0..Height do
$stage[s_pos(0,i)] = 8
$stage[s_pos(Width+1,i)] = 8
end
for i in 0..(Width+2) do
$stage[s_pos(i, Height)] = 8
end
end

def draw_block(pos_x,pos_y,col)
x=pos_x*$sprite_size
y=pos_y*$sprite_size
if col != "black" then
Drawing.rect(Screen, [x,y,$sprite_size,$sprite_size],eval(':'+col),true)
Drawing.rect(Screen, [x+$depth,y+$depth,$sprite_size-$depth*2,$sprite_size-$depth*2],eval(':dark_'+col),true)
Drawing.rect(Screen, [x+$sprite_size-$depth,y,$depth,$sprite_size],eval(':half_'+col),true)
Drawing.rect(Screen, [x,y+$sprite_size-$depth,$sprite_size,$depth],eval(':half_'+col),true)
end
end


def player_move()
input_key = Input.pushed_amount
if (input_key[1]==1) then
@bl1.move(@bl1.x, @bl1.y+1)
elsif (input_key[1]==-1) then
@bl1.turn()
elsif !(input_key[0]==0) then
@bl1.move(@bl1.x+input_key[0], @bl1.y)
end
end

def block_down()
if ((@tet_timer.now % 3 ) == 0)
if @bl1.check_move(@bl1.x, @bl1.y+1) then
@bl1.y = @bl1.y+1
else
block_new()
end
end
end

def block_new()
@bl1.fix()
erase_line(true)
@bl1=Blocks.new(rand(max = 7) + 1)
@tet_timer.reset
if !@bl1.check_move() then
$gameover = true
end
end

$start = 0
$gameover = false
Miyako.main_loop do
break if Input.quit_or_escape?
if ($start==0) then
new_game()
elsif $gameover then
if Input.pushed_any?(:btn1) then
$start = 0
end
else
player_move()
block_down()
end
draw_stage()
end

2010年2月23日

ゲームライブラリMiyakoをインストールしてみた

日経ソフトウェアの連載でおもしろそうな方がいたので、ネットで検索してみると、1時間でテトリスを作ってみたという動画をニコニコ動画に公開していた。
どうしても気になって、ニコ動、ユーザ登録して、視聴してみたら、ほんとうに1時間強でテトリスができあがっていた。
しかも、開発環境のインストールも含めて。

これ、ほんとうにすごいことだなあ。
僕も久々にゲーム作ろうかなと思い、以前から気になっていてだけは買っていたゲームライブラリのMiyakoのインストールを試みる。
予定では、Tetrisの画面ぐらいまでは作成して寝ようかなというところ。

ところがこれが、おおはまり。
Rubyのインストールまでしたのに終わらない(涙)

というわけで、一応やったことの記録。
  1. Ruby 1.9.1のインストール
  2. Macports経由で、SDL関係(libsdl, ttf, gfx, image)、rubysdlなどなど。
    この際、あまりにもエラーが多いので、port upgrade outdated すると、かなりうまく動いた。
  3. 依存パッケージとしてインストールされる、help2manがエラーが出る。めんどうなので、perlモジュールをチェックする部分をコメントアウト。
    後で泣きを見るかもしれないけど、とりあえず今はMiyakoを動かすことが最優先。
  4. SGEをインストール。
    国内のURLを紹介しているサイトのリンクはリンク切れ。
  5. gem経由で、rsdl、miyakoをインストール
    sudo gem install ruby-miyako
以上でインストールは何とか終わったのだが、ここからのエラーが苦しかった。
サンプルを動かそうとすると、sans-serifが見つからないというエラー。
本を参照すると、serifが明朝系、sans-serifがゴシック系のデフォルトフォントらしい。
このフォントは、OSによって適当なものが割り当てられているのだが、どうもこれを見つけることができない。

OSX(Snow Leopard)の場合は、ヒラギノ系が指定されているが、とりあえず、Osaka.ttfをfont.rbに追加してみる。
そうすると、ぶじ動く。

次に、ヒラギノをサンプルのあるディレクトリにコピーして起動するも、エラー。
ヒラギノをhiramin.otfなどの名前に変えて見ると、うまく動く。

どうやら、日本語のフォント名のサーチに失敗している模様。
Rubyの問題かと思って、スクリプトを書いてみて、日本語フォントを読めているかチェック。

Dir.glob("/Library/Fonts/"+"*") {|d|
d = d.encode(Encoding::UTF_8)coding::UTF_8))
d = d.tr("\\", "\/")
print d +"\n" if (d =~ /\/([^\/\.]+\.otf)\z/)
}
というスクリプトを作ってテストしてみても、ちゃんと読めている。
たぶん、こうして読み込んだフォント名と、font.rbで指定したフォント名のマッチの部分がおかしいのだと思う。

が、この辺で力尽きる。

とりあえず、ヒラギノ明朝と角ゴをhiraminとhirakakuというリンクを張り、これをfont.rbで指定してやることで、何とか動くようになった。
やれやれだ。

2010年2月22日

iPhone、脱獄できない・・・

iPhone買ってそろそろ二ヶ月になるから、脱獄でもするか。。。
そんな感じでネットを調べてみると、3GSでOSを3.1.3にあげてしまうと脱獄できないらしい。
そういえば、この前、何気なくアップしてしまった。

じゃあ、ツールがでるのを待てばいいのか、というとことはそう簡単ではないらしい。
そもそも3GSは脱獄できないと思った方がよさそう。
なんでも、OS3.1.2のときでも、脱獄して電源を切るとリカバリモードになる。
こういうの、テザードジェイルブレイク(脱獄)というそうだ。

わりと飛行機に乗る機会が多いし、電源が持たなくて、電源落ちてしまうこともときどきある。
そのたびにリカバリモードになるということは、常にリカバリモードから復帰させるために、パソコンを持ち歩かなければならない。
うーん、それはちょっとないんじゃないかな。

iPhone買ってから、どのタイミングで脱獄しようかと楽しみにしてたのに、どうやらもともとだめだった様。
なんだか残念だな。

それと同時に、ハードウェアとか、会社が決めた枠の外には触らせないというポリシーが強いAppleとこれ以上つきあうのはどうかと感じ始めた。
パソコンはMacがいいけど、他のデバイスは、もっと自由で実験して遊べるものに変えたいな。

今さらながら、NOKIAのE72にしようかなと思う日々。
でも今ならAndroidですよね?

2010年2月6日

emacsでシンプルな物書き環境

誘惑を断ち切って文章を書くのに集中したい!という人は多いようで、専用のアプリケーションが開発され、けっこう話題になった。
それが、Writeroom
(フリーのWindows版クローンがDark Room
最近ではそれに音楽と集中できる(と思える)背景をセットにしたアプリケーションも開発されている。
MOONGIFTさんで紹介されているのが、Windows用のCreaWriterとOSX用のOmmWriterレビュー)だ。

でも、文章を書くときには、普段使っているエディタがいいというのも人情。
キーバインドは違うし、いろいろ便利なモードはあるし。。。
ぽっと出のエディタと使い込んだエディタは快適さが違うのですよ。
(文章書くのに集中するんなら、あんま関係ないかもしれないけどね)

つまりは、emacsでWriteroomは実現できないのか、と思い続けてきた。
emacs+Writeroomで検索すると、いろんなサイトがヒットするが、ほとんどはフルスクリーンにしてメニューバーなどをなくすというものだ。


違う。。。


フルスクリーンにしただけだと、画面が左に寄ってしまって、右側は使えない。
今の横長全盛のディスプレイだと、ずっと画面の左を見て作業しなければらなくなる。
僕がやりたいのは、ディスプレイにまっすぐ向かって作業することだ。

つまりは、入力中のテキスト全体が中央に集められて、左右に均等幅のスペース(マージン)があるというのが理想だ。
そもそも、入力中の画面(フレーム)の左右に適当なマージンを設定するという方法がよく分からなかった。

でも、ようやく回答をみつけた。
なんのことはない、emacs用にdarkroom-modeが公開されていた。
これはWindows用だが、Windows依存部分はフルスクリーンにする部分だけだそうなので、あまり深く考えずにダウンロードして使ってみた。

darkroom-modeの10行目を
;(require 'w32-fullscreen)
として、コメントアウトすることを忘れずに。
そして、M-x darkroom-mode で起動。
ついでに、Carbon Emacsのフルスクリーンモードに移行。

できた!



あとは、設定をまとめて、何かのキーに設定すればいいかも。

追記:
darkroom-modeは自分で画面をフルスクリーンに移行する機能を持っていました。
なので、こんな感じで設定すれば、Ctrl-c dでdarkroom-modeに移行できます。
(require 'darkroom-mode)
(global-set-key "\C-cd" 'darkroom-mode)

その際、フルスクリーン関係でwindows依存部分が残っていたので、これをCarbon Emacsで利用できるように変更します。
130行目
;; (w32-fullscreen-on)
(set-frame-parameter nil 'fullscreen 'fullboth)

175行目
;; (w32-fullscreen-off)
(set-frame-parameter nil 'fullscreen nil)

2010年2月1日

org-modeからのLaTeX利用環境を整備


マニュアルをちゃんと読めば載っていることなんだけど、ついついその場しのぎをやってしまいます。
今日は一念発起して、org-modeでLaTeXをちゃんと使えるようにしようと思い、いろいろといじってみました。
まずは C-c C-x C-lでLaTeXの数式を画像に変換して、文書の編集中に見れるようにしてくれる機能(LaTeXのインラインプレビューとでも言いましょうか。Previewing LaTeX fragmentsと書かれています)を使います。

なぜかデバッガーの画面が出ますが、何度かescを押すと、ぶじインラインで表示されます。
(いいのかな、これで?)
適当な数式を作ってみますと、$Q=\frac{Y^{\alpha} Cl}{L}$が、次のような感じになります。

うん、いい感じ。

次になぜか変換したときに著者が文字化けするので、ファイルの先頭で指定することにしました。
#+AUTHOR: 岡村 土竜
#+TITLE: スローな子育ち
org-modeをインストールしたときには、この機能、ちゃんと有効だったのですが、いつの間にかエラーが出るようになっていました。
プレビューは、LaTeXで変換したdviファイルをpngに変換するものですので、この機能を提供しているdvi2bitmapというプログラムをmacportsからインストールすると、ぶじ動きました。
(この間、libpngのアーキテクチャが古いといわれ、zlibとlibpngに+universalをつけて、再インストールしました)

この他、デフォルトのタイプセット用に、jsarticleを指定して、普段使いのパッケージが使えるようにしておきました。
これはこんな感じ。
(add-to-list 'org-export-latex-classes
'("jsarticle"
\\usepackage{tabularx}
\\usepackage{longtable}
\\usepackage{graphicx}
))
(setq org-export-latex-default-class "jsarticle")
もう少しいじって、PDF画像の貼り付けを楽にしておきたいなと思いますが、それは午後に出もやることにします。
仕事も進めないといけませんしね。