ニンテンドー DS 上でパズルゲーム - 数理情報学科

ニンテンドー DS 上でパズルゲーム
理工学部 数理情報学科
T050049 高山 友里
指導教員 池田 勉
概要
今の社会は,とても便利だと思う.携帯電話が無くては1日を過ごせないという人も少
なくはないはずである. 便利だと思う1つに,携帯ゲーム(PSP,ニンテンドー DS)があ
る.ニンテンドー DS (以下 DS )はソフト次第ではあるが,ゲーム,勉強が出来たり小
説が読めたり最近ではテレビを見ることもできる.育成ゲーム,脳トレーニング,RPG な
ど幅広いソフトがあることで,子供からお年寄りまで幅広い層で利用されている.身近に
あるゲームなので,自分でプログラムを書くことが出来たら面白いと思ったので,DS の
ソフトを作ってみようと考えたのが動機である.
研究の方法として,プログラムを作成するにあたっての環境作りから始めることした.環
境つくりをしたパソコンの OS は Windows XP である.もっとも欠かせないのは DevkiPro
であり,仕様の異なるハードウェア・OS 上で同じ仕様のものを動かす役割がある.DS の
CPU は ARM なので専用のコンパイラが必要になり,devkitARM を利用する.それと同
時に必要になるのが,MSYS と MinGW である.MSYS は MinGW を利用する最小の環
境を提供しているアプリケーションで,この2つを一緒に使用すれば,Unix 系 OS と同様
の感覚でプログラミングが出来る.プログラミングの言語は C++ を使用する.C++ で
プログラムを作成し,make すると nds ファイルが出来上がる.nds ファイルは,ニンテ
ンドー DS 用のエミュレータを使って動作を確認することが可能である.DS の本体を所
持していれば,micro SD Card に nds ファイルをコピーをする.さらに,マルチメディア
ツールを使用すると DS のソフトとして DS 本体で起動させることが出来る.
プログラミングは,DS の自作プログラムを作っている方のサイトで, nds ファイルの
ソースを分析することから始まった.今までは C 言語と Java をやったことがあったので,
C++ も同じような感じで出来るだろうと考えていたが,nds ファイルを作るためのプロ
グラムは,画面や使用する色の設定,とにかく細かいところまでの設定が必要になるので,
簡単なプログラムを書けるようになるまでの時間が長かった.
出来上がった nds ファイルは,最初に考えていたものよりも,簡単な仕様になってしまっ
た.最初に考えをまとめた時は,音を入れたりタイマーをつけてみようと思っていた.そ
れぞれ単独では出来そうだったが,音・タイマー・ゲームの機能を同時に行うことは困難
だと判断したため,ゲームの機能だけになった.一から勉強をして,作成したプログラム
だけあって,出来上がって DS の実機で動作したことが非常に嬉しい.
2008 年度 卒業論文
ニンテンドー DS 上でパズルゲーム
龍谷大学 理工学部 数理情報学科
T050049 氏名:高山 友里
指導教員 池田 勉
目次
1
はじめに
1
2
開発環境
1
2.1
devkitPro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1
2.2
MinGW,MSYS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2
2.3
Emulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4
3
4
5
DS のプログラム仕様
5
3.1
BG-MAP モード . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
3.2
画像ファイルのヘッダファイル . . . . . . . . . . . . . . . . . . . . . . . .
5
プログラム
6
4.1
画面を表示させるプログラム . . . . . . . . . . . . . . . . . . . . . . . . . .
6
4.2
画像を背景にするプログラム . . . . . . . . . . . . . . . . . . . . . . . . . .
7
パズルゲーム
8
5.1
パズルの初期配置 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
5.2
タイルへ変換 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
5.3
パズルを移動させる
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
5.4
main 文 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
11
6
おわりに
I
資料
13
1
はじめに
1
今回,卒業研究の内容を決めたきっかけは,勉強を楽しくするにはどうしたらいいのか
と思っているからである.そもそも勉強は,机に向かってするというのが普通だと思う.好
きな教科だったらやる気があってはかどるだろうけど,苦手な教科ではそうはいかない.私
自身,数学なら難しい問題でもしっかりと机に向っていられたが,社会になるとどうして
も苦手意識があるため,集中して勉強できなかったものだ.好きな教科だったらいいのに,
ゲームやったら難しいくても楽しいのにと思うことが何度もあった.勉強になって,しか
もそれがゲーム感覚で楽しめる方法を考えたところ,携帯型ゲーム機が頭に出てきた.携
帯型ゲーム機は,小型で軽量化されていて,充電をしておけばどこでも楽しむことができ
る.少しの空いた時間でも活用できる便利なツールだと考えた.そこで気になったのがニ
ンテンドー DS の存在だ.もちろん遊ぶことも出来て,勉強のソフトもそろっているので,
私の考えていることを実現させるためには必要だと思った.まずニンテンドー DS のソフ
トがどのようにして出来ているのかを調べてみた.書籍で DS のソフトのことを書いてあ
るものがなかったため,インターネットで検索をして,DS の自作プログラムを作ってい
る人の所にたどり着いた.言語は C++ で,書いたプログラムを DS のソフトとするため
には,特別な環境を作らなくてはいけないことがわかった.いきなり勉強のソフトを作れ
るわけでもなく,DS のプログラムの内容を理解するところから始め,簡単なゲームを作っ
てみようと思う.
開発環境
2
開発するのに使ったパソコンの OS は,Windows XP である.DS のソフトを開発する
ための言語は,C++ である.DS の CPU が ARM なので,ARM 用の開発環境が必要に
なるのだが,一般的なのが devkitPro である. プログラム cpp ファイルを変換して nds
ファイルにするのには MinGW と MSYS を使用する.cpp ファイルでプログラムを作り,
make をして出来た nds ファイルをエミュレータ NO$GBA で動作確認をするという作業を
繰り返して,開発をしていく.Windows Vista でも開発環境を整えてみたが,make 出来
るものと出来ないものがあるため,vista で開発することは避けた方がいい.
2.1
devkitPro
devkitPro では,DS の他に,PSP の開発環境も用意することができるが,今回必要な
DS の環境だけを整えることにする.まず,
『SOUCEFORGE.NET』にアクセスをする.検
索バーのところに,devkitPro を入力して検索する.検索結果(図 2.1)の一番上に探して
いる devkitPro が出てくるので,クリックして進んでいく.ような画面が出てくる.進んで
いくと,devkitPro の最新版がダウンロードできる.現在は『devkitProUpdater-1.4.9.exe』
が最新版である.このインストーラーを使用すると,コンパイラからライブラリまで開発
に必要な環境を作ることができる.
1
図 2.1: devkitPro 検索結果
インストールする際に保存できる場所を選べるところが出てくるが,のちのち設定をしな
くてはいけないので,デフォルトのままで進んでいく.インストール出来たら,ヘッダファ
イル nds.h を使用できるように環境変数を変更する.コントロールパネルを開き,図 2.2
と同じアイコンをクリックする.
図 2.2: システムのアイコン
図 2.3: システムのプロパティ
ここで環境変数の変更が出来る.図 2.3 の上部の詳細設定のタブをクリックし,下段に
あるシステムの環境変数のところから,Path を探して編集を行う.変数値のところに,
『C:devkitPro\devkitProARM\bin;』を書き加えます.こうすることで,nds.h が使える
ようになった.インストールする際に保存する場所を変更している場合は,保存した場所
を書き加える.ここで環境変数の変更をしておかないと,nds.h を使うことが出来ない為,
きちんと変更を行っておく必要がある.
2.2
MinGW,MSYS
MinGW は Windows のための最小の GNU を表している.MSYS と両方を合わせて,
完結可能な環境を作れる.コンピュータ上のレジストリやファイルに対して影響を与え
ないため,リムーバブル・ディスクから使用することが可能である.devkitPro と同様,
2
図 2.4: MinGW 検索結果
『SOUCFORGE.NET』にアクセスをし,検索バーに MinGW をいれ検索をする.先ほど
は一番上に出てきたが,図 2.4 のように MinGW を探してクリックする.
図 2.5: MSYS 検索結果
やはり devkitPro と同様,最新版を手に入れることができる.現在の最新版は,
『MinGW
5.1.4』である.ダウンロードしてインストールを始める.MinGW を導入できたら,続い
て MSYS を導入する.MSYS とは,MinGW を補う目的で作られたパッケージである.
Windows 上で動作するシェルやテキスト操作ユーティリティなどを統合している.ソフト
ウェアを構築・インストールするために最低限必要なツール軍を提供しており,また仮想
ターミナルソフトや CUI のテキストエディタも同梱しているので,MinGW と併用する
最小限の Unix 風の CUI 環境として利用することが出来る.図 2.5 検索結果より MSYS
を探し,インストールしておく.
3
インストールし終わったら,devkitPro の時のように,環境変数の変更を行う.コント
ロールパネルを開き,システムをクリックする.システムの環境変数のところで Path を
探し編集をする.変数値のところに,
『C:\MinGW\bin;』と『C:\msys\1.0\bin;』を追加
する.これで make のコマンドが使用できるようになった.
2.3
Emulator
プログラムを作成したら,どのように動作の確認をすればいいのかという疑問が上がっ
てくる.その時に役立つのが,エミュレータの存在である.エミュレータとは,あるシス
テム上で他の OS や CPU の機能を再現して,その OS(CPU) 向けのアプリケーションソ
フトを動作させるソフトウェアのことである.ダウンロードしておくことで,DS 本体を
持っていなくても,作成したファイルを動作させることができる.ただ難点もいくつかあ
り,画像がうまく表示されなかったり,音を使用すると雑音が入りこむことがある.今回作
ろうとしているプログラムには,精巧なものを求めているわけではないので,気にしない
ことにする.開発中の動作確認にはエミュレータを使用し,最終的な確認は DS の実機で
行わなければならない.使用するエミュレータは, NO$GBA (ノーキャッシュGBA) であ
る.GBA とあるが,GBA と DS の両方に対応している.いくつかある DS のエミュレー
タの中からこれを選んだのは,他のエミュレータと比べると処理速度が速いからである.
まず『http://nocash.emubase.de/』にアクセスをする.図のトップ画面からから NO$GBA
を探してクリックする.NO$GBA のページに行くのだが,このページもまた英語だらけであ
る.最初の方には,バージョンの説明が書いてある.エミュレータも最新版をダウンロー
ドしたいところだが,有料になっている.だが1つ前版は無料配布されているので,安心
してもよい.下にさがっていくと,
図 2.7: NO$GBA
図 2.6: トップページ
を見つけることが出来る.書いてある通り,Freeware のバージョンをダウンロードでき
4
る.上側の windows version をダウンロードする.保存する場所だが,今までの devkitPro
や MinGW ,MSYS は環境変数の変更を必要としていたため,デフォルトのままにして
いたが,NO$GBA はエミュレータであり,環境変数の変更は必要がないので,適当な場所に
保存する.
DS のプログラム仕様
3
3.1
BG-MAP モード
DS ではテキストやスプライトのようなものを扱うための機能が付いている.それが,画
面モードと呼ばれるものである.テキストなどの表示向けの画面を BG と呼んでいる.BG
画面は全部で4枚ある.前後関係を自由に設定し,重ねて表示させることもできる.
表 1 画面モードの設定により,それぞれの仕様が決まることになる.Text,Affine,Extended
にはそれぞれ特徴がある.
Mode
BG0
BG1
BG2
BG3
0
1
2
3
4
5
6
Text/3D
Text/3D
Text/3D
Text/3D
Text/3D
Text/3D
3D
Text
Text
Text
Text
Text
Text
-
Text
Text
Affine
Text
Affine
Extended
Large
Text
Affine
Affine
Extended
Extended
Extended
-
表 1: BG モードの対応表
•Text 8x8 ドットのタイルを並べるモード.32x32 のタイルを並べた BG-Map 画面
を縦横に繋ぐことができる.
• Affine Text 同様,8x8 ドットのタイルを並べるモード.16x16 ∼ 128x128 タイルの
画面を1つだけ持っている.伸縮回転させての表示が出来る.
• Extended 32,768 色のダイレクトカラーモードが使える.さらに伸縮回転させての
表示が出来る.
Extendet を使用すれば,Bitmap などをそのまま表示させることが容易になる.
3.2
画像ファイルのヘッダファイル
画像ファイルをプログラムで使って,DS に表示をさせるときには,画像ファイルのヘッ
ダファイルが必要となる.そこで便利なのが, grit というツールだ.このツールは画像
ファイル bmp,png などを DS 用のフォーマットに変換してくれる.devkitPro の最新版
5
にはデフォルトで入っているので,新たにインストールする必要はない.古いバージョン
の devkitPro を使用している場合は grit の公式サイト [4] からダウンロードしておくと便
利である.使用方法は非常に簡単で,コマンドをコンソール上にて入力し,オプションを
いくつか指定する.また,.grit のファイルを作っておいてもよい.コンソール上で使用す
る場合はここで例を出してみる.sample.bmp という画像ファイルがあるとしよう.これ
をモード 0 で使用する画像のヘッダファイルに変換するためには,コンソール上で,
grit.exe sample.bmp -gt -gB8
とする.作成されたファイルは,新たに build というフォルダを作って入れておく.その
他の方法として,sample.grit のファイルを作る.中身を
# bitmap format
-gt
# 16 bit bitmap
-gB8
のようにして,data フォルダに入れておく.この方法では make したときにヘッダファイ
ルが作成される.
4
4.1
1
2
プログラム
画面を表示させるプログラム
#include <nds.h>
#include <stdio.h>
3
4
volatile int frame = 0;
5
6
7
8
void vblank() {
frame++;
}
9
10
11
12
13
14
15
16
17
int main(void)
{
irqInit();
irqSet(IRQ VBLANK, vblank);
irqEnable(IRQ VBLANK);
videoSetMode(0);
videoSetModeSub(MODE 0 2D | DISPLAY BG0 ACTIVE);
vramSetBankC(VRAM C MAIN BG);
6
BG0 CR = BG MAP BASE(31);
18
19
SUB BG0 CR = BG MAP BASE(31);
20
21
BG PALETTE SUB[255] = RGB15(31,31,31);
consoleInitDefault((u16∗)SCREEN BASE BLOCK(31),
(u16∗)CHAR BASE BLOCK(0), 16);
22
23
24
25
for(;;)
swiWaitForVBlank();
26
27
28
}
これは,とりあえず画面を表示しているプログラムである.12,13,14 行目の
• irqInit();
• irqSet(IRQ_VBLANK,vblank);
• irqEnable(IRQ_VBLANK);
では,現在実行中のプログラムを停止し呼び出す特殊コードの設定をしている.一般的に
はハードウェア発生が目的だが,ソフトウェアの発生もある.
15,16,17 行目
• videoSetMode(0);
• videoSetModeSub(MODE_0_2D) DISPLAY_BG0_ACTIVE);
• vramSetBankC(FRAM_C_MAIN_BG);
では 3-1 の画面モードの設定をしている.15 行目がメインスクリーン,16 行目が下画面
のサブスクリーンの設定についてで,上スクリーンは (0) としているので何の処理も設定
していない.
4.2
画像を背景にするプログラム
パズルゲームで使用する画像をとりあえず背景に表示してみる.
#include <nds.h>
#include <stdio.h>
#include "othelloBoard.h"
int main(void) {
irqInit();
irqSet(IRQ VBLANK, 0);
7
videoSetMode(MODE 5 2D | DISPLAY BG3 ACTIVE);
vramSetBankA(VRAM A MAIN BG 0x06000000);
lcdMainOnBottom();
BG3
BG3
BG3
BG3
BG3
BG3
BG3
CR = BG BMP16 256x256 | BG BMP BASE(0);
YDX = 0;
XDX = 1 ¿ 8;
XDY = 0;
YDY = 1 ¿ 8;
CX = 0;
CY = 0;
for(int i = 0; i < 256∗192; i++) {
((u16∗)BG BMP RAM(0))[i] = ((u16∗)othelloBoardBitmap)[i] | BIT(15);;
}
while(1) {
swiWaitForVBlank();
}
return 0;
}
• lcdMainOnBottom();
メインスクリーンを下に設定している関数である.タッチスクリーンを使うことはないの
ですが,メインスクリーンは下に設定している.
• BG3_CR = BG_BMP16_256x256 BG_BMP_BASE(0);
コントロールレジスタというレジスタを操作し,VRAM にどんなことが書き込まれるか
を DS に指示をしている.
• BG3_YDX = 0; … BG3_CY = 0;
回転,拡大,縮小,スクロールに関して設定している.ここに書いてあるのは,回転・拡
大縮小・スクロールなしの設定である.
ここまでで,初期化が終了する.ビットマップを貼る方法は,for 文のところで貼り付けて
いる.
5
パズルゲーム
第3章では DS のプログラムの中身をじっくりと勉強した.第4章では 3章で学んだこ
とを踏まえて,簡単なプログラムを作成した.この章では,目的としているパズルゲーム
の製作をしている.
十字キーを使ってパズルのタイルを交換していき,ばらばらに配置された絵を元通りの絵
8
に戻すというプログラムを作成した.画像ファイルの中身は,0:背景,1:壁,2:空
きマス,3∼27:パズルのピースになっている.
5.1
パズルの初期配置
char levelMap[MAX_LEVEL][80] = {
{
0, 1,
1, 1, 1, 1, 1,
0, 1,
3, 8, 13, 18, 23,
0, 1,
4, 9, 14, 19, 24,
0, 1,
5, 10, 15, 20, 25,
0, 1,
6, 11, 16, 21, 26,
0, 1,
7, 12, 17, 22, 27,
0, 1,
1, 1, 1, 1, 1,
0, 1,
1, 1, 1, 1, 1,
},
{
0, 1,
1, 1, 1, 1, 1,
0, 1, 17, 3, 16, 21, 10,
0, 1, 26, 13, 22, 9, 5,
0, 1, 15, 8, 4, 14, 18,
0, 1, 20, 24, 12, 11, 6,
0, 1, 25, 19, 7, 23, 27,
0, 1,
1, 1, 1, 1, 1,
0, 1,
1, 1, 1, 1, 1,
}
};
1,
1,
1,
1,
1,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0
1,
1,
1,
1,
1,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0
ここで,パズルの絵の配置を指定している.上側がパズルゲームをする前に見せる完成
図のパズル配置,下側がバラバラにしたパズルの配置を示している.0が背景の黒色,1
がゲームの壁,2が空きマス,3∼27 がそれぞれのパズルのピースである.空きマスの部
分がパズルをする際になくてはならない存在だ.
5.2
タイルへ変換
void setVRAMFromMap(u16* mapMemory, char* map) {
for(int y = 0; y < 8; y++) {
for(int x = 0; x < 10; x++) {
char c = (*map++) * 9;
mapMemory[x * 3 + y * 3 * 32] = c;
9
mapMemory[x
mapMemory[x
mapMemory[x
mapMemory[x
mapMemory[x
mapMemory[x
mapMemory[x
mapMemory[x
*
*
*
*
*
*
*
*
3
3
3
3
3
3
3
3
+
+
+
+
+
+
+
+
y * 3 * 32 + 1] = c + 1;
y * 3* 32 + 2] = c + 2;
(y * 3 + 1) * 32] = c + 3;
(y * 3 + 1) * 32 + 1] = c +
(y * 3 + 1) * 32 + 2] = c +
(y * 3 + 2) * 32] = c + 6;
(y * 3 + 2) * 32 + 1] = c +
(y * 3 + 2) * 32 + 2] = c +
4;
5;
7;
8;
}
}
}
パズルの情報をタイルに変換し,VRAM に配置する関数である.DS のソフトを作る際
に画像を用いる場合は,8x8 を基本としている.今回のプログラムでは,パズルのピース
1つを 24 x 24 にしているため上から4行目の部分で *9 とする必要がある.
5.3
パズルを移動させる
void move(int dx, int dy, char*map) {
int pos = 0;
int a, b, c, d, e, Q;
Q = 2;
while(map[pos] != Q) {
pos++;
}
int dp = dx + dy * 10;
a
b
c
d
e
=
=
=
=
=
map[pos
map[pos
map[pos
map[pos
map[pos
+
+
+
+
+
dp];
dp +
dp +
dp +
dp +
dp];
dp + dp];
dp + dp + dp];
dp + dp + dp + dp];
if(a == 1) {
count--;
return;
}
10
if(b == 1 || (b > 2 && b <= 27) || (c > 2 && c <= 27) ||
(d > 2 && d <= 27) || e == 1) {
map[pos] = a;
map[pos + dp] = Q;
return;
}
}
pos は空きマスが map の配列のどこにあるのか探すために用いられている.空きマス
は2なので Q = 2 と置いておく.while 文でマップ配列の中空きマス(Q)がどこにある
か調べ,見つかるまで pos の値を増やしていく. pos + dp で次に進むマスの配列番号を
取得している.つまり a = map[pos + dp] ならば,空きマスが次に進むマスのことを表し
ている.同じように,b は2つ先,c は3つ先,d は4つ先,e は5つ先のマスのことを意
味している.最初の if 文 if (a == 1) … では,空きマスと交換しようとしている場所が壁
だったら,何もしないという意味.count– としているのは,main 文の時に合わせて説明
をする.
.次の if 文も考え方は同じで,b や e が壁の時,または b, c, d がパズルのピース
であるとき,pos + dp のピースと空きマスを交換するという意味である.
5.4
main 文
5.1,5.2,5.3 を使って main 文を完成させる.必要なところだけ抜粋して説明をする.
int main(void) {
/* 中略 */
swiCopy(soukobanPal, BG_PALETTE 256);
/* 省略 */
swiCopy(soukobanTiles, tileMemory, 24 * 24 * 28 / 2);
char map[80];
swiCopy(levelMap[0], map, 40);
(1)
scanKeys();
if(kesDown()) {
if(keysDown() & KEY_A) { (2)
swiCopy(levelMap[1], 40);
}
}
11
while(1) {
iprintf("\x1b[10;0H count = %04d\n", count);
scanKeys();
if(keysDown()) {
if(keysCown() & KEY_RIGHT){
count++;
move(-1, 0, map);
}else if(keysCown() & KEY_LEFT){
count++;
move(1, 0, map);
}else if(keysCown() & KEY_UP){
count++;
move(0, -1, map);
}else if(keysCown() & KEY_DOWN){
count++;
move(0, 1, map);
}else if(keysCown() & KEY_START){
swiCopy(levelMap[stage],map, 40);
count = 0;
}
}
setBRAMFromMap(mapMemory, map);
swiWaitForVBlank();
}
return 0;
}
(1) のところで,パズルゲームの完成図をまず表示している.(2) ではキー入力を出来る
ように設定をして,DS の A ボタン (エミュレータでは1) を押すと,パズルがバラバラに
なった levelMap[1] が表示される.While 文で,やっとパズルゲームの動作をループさせ
ている.右でピースを右に空きマスを左に移動させれるようになっている.ここで,それ
ぞれの if 文に count++; をいれて,何回移動をさせたかを計測している.5.3 で count–;
を入れていたのは,main 文でとりあえずキー入力をしたら count を増やすようにしてい
るからである.隣が壁だろうと count は増えていってしまうので, 5.3 のように隣が壁の
時には main 文での増加を減らす目的で count–; を入れて調整をしている.最後の if 文,
else if(keysDown() & KEY_START)… で,ゲームのリセットが出来る.その時には count
を 0 にリセットして最初の状態に戻るようになっている.
12
6
おわりに
ニンテンドー DS の中身ってどういう風になっているのかというところから始まり,DS
のソフトを作っているプログラムを1から勉強しました.言語が C++ で,使ったことは
なかったのですが,プログラム自体を書くことはスムーズにできました.画面の設定,画
像ファイルの設定などが難しく,[1] に頼ることになってしまいました.パズルの動かし方
は自分で考え,思い通りに動かせるまで試行錯誤をした.最初考えていた機能は,カウン
ト,リセット,完成しているか,完成していれば次の面に進む,時間を計測,などをつけ
るつもりだった.完成して一通り動かせるようになってからは,イラストにこだわったり,
移動させた回数を表示,リセットでき,リセット回数も表示できるようにした.キー入力
出来るようになった.時間の機能は計算やらするのが難しいため,途中で断念した.完成
しているかどうかを判定して,完成していれば次のステージに進む機能を付けたかったが,
1つのプログラムに2つ以上のイラストを使用するのがよくわからなくて,教科書代わり
にしていたサイトを見て頑張ってみた.しかし勉強しだしたのが遅かったこともあって出
来なかった.
DS は画面が2つあって同時に使うこともできるので,せっかくだから両方の画面を同時に
使ってみた.しかし DS の特徴であるタッチスクリーンの機能を使えるように出来なかっ
たので,残念に思う.自分が作ったプログラムが DS のソフトに変換でき,マジコンを使
うことで実機で動かせて非常に嬉しかった.
13
参考文献
[1] http://void-main.org/dsprogram/,Nintendo DS でプログラミング
[2] http://meraman.dip.jp/index.php?FrontPage,めらまん
[3] http://akkera102.sakura.ne.jp/gbadev/,GBA develop Wiki
[4] http://www.coranac.com/man/grit/html/grit.htm,i. Grit 0.8.3 : Table of Contents
14
資料
I
• パズルゲームのプログラム
#include <nds.h>
#include <stdio.h>
#include "souko.h"
#define MAX LEVEL (4)
char levelMap[MAX LEVEL][80] = {
{
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 2, 9, 6, 1, 1, 1, 0,
0, 1, 1, 5, 8, 7, 1, 1, 1, 0,
0, 1, 1, 3, 4, 10, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 1, 1, 0
}
};
void setVRAMFromMap(u16∗ mapMemory, char∗ map) {
for(int y = 0; y < 8; y++) {
for(int x = 0; x < 10; x++) {
char c = (∗map++) ∗ 9;
mapMemory[x ∗ 3 + y ∗ 3 ∗ 32] = c;
mapMemory[x ∗ 3 + y ∗ 3 ∗ 32 + 1] = c + 1;
mapMemory[x ∗ 3 + y ∗ 3∗ 32 + 2] = c + 2;
mapMemory[x ∗ 3 + (y ∗ 3 + 1) ∗ 32] = c + 3;
mapMemory[x ∗ 3 + (y ∗ 3 + 1) ∗ 32 + 1] = c +
mapMemory[x ∗ 3 + (y ∗ 3 + 1) ∗ 32 + 2] = c +
mapMemory[x ∗ 3 + (y ∗ 3 + 2) ∗ 32] = c + 6;
mapMemory[x ∗ 3 + (y ∗ 3 + 2) ∗ 32 + 1] = c +
mapMemory[x ∗ 3 + (y ∗ 3 + 2) ∗ 32 + 2] = c +
}
}
}
int checkClear(char∗ map) {
for(int i = 0; i < 80; i++) {
1
4;
5;
7;
8;
if(map[i] == 2) {
return false;
}
}
return true;
}
void move(int dx, int dy, char∗ map) {
int pos = 0;
int a,b, Q;
Q = 10;
while(map[pos] 6= Q) {
pos++;
}
int dp = dx + dy ∗ 10;
a = map[pos + dp];
b = map[pos + dp + dp];
if(a == 1) {
return;
}
if(b ≤ 9) {
map[pos] = a;
map[pos + dp] = Q;
return;
}
}
int main(void) {
irqInit();
irqEnable(IRQ VBLANK);
videoSetMode(MODE 0 2D | DISPLAY BG0 ACTIVE);
videoSetModeSub(MODE 0 2D | DISPLAY BG0 ACTIVE);
vramSetMainBanks(VRAM A MAIN BG 0x06000000,
VRAM B LCD, VRAM C SUB BG, VRAM D LCD);
SUB BG0 CR = BG MAP BASE(31);
BG PALETTE SUB[255] = RGB15(0,31,0);
consoleInitDefault((u16∗)SCREEN BASE BLOCK SUB(31),
2
(u16∗)CHAR BASE BLOCK SUB(0), 16);
lcdMainOnBottom();
BG0 CR = BG 32x32 | BG COLOR 256 | BG MAP BASE(0) |
BG TILE BASE(1);
swiCopy(soukoPal, BG PALETTE, 256);
u8∗ tileMemory = (u8∗)BG TILE RAM(1);
u16∗ mapMemory = (u16∗)BG MAP RAM(0);
swiCopy(soukoTiles, tileMemory, 24 ∗ 24 ∗ 11 / 2);
int stage = 0;
int clear = 0;
char map[80];
swiCopy(levelMap[0], map, 40);
while(1) {
iprintf("\x1b[10;0H Stage %04d\n", stage + 1);
scanKeys();
if(keysDown()) {
if(clear) {
}
}
}
}
}
clear = 0;
stage++;
swiCopy(levelMap[stage], map, 40);
else if(keysDown() & KEY RIGHT) {
move(1, 0, map);
else if(keysDown() & KEY LEFT) {
move(−1, 0, map);
else if(keysDown() & KEY UP) {
move(0, −1, map);
else if(keysDown() & KEY DOWN) {
move(0, 1, map);
else if(keysDown() & KEY START) {
swiCopy(levelMap[stage], map, 40);
}
}
setVRAMFromMap(mapMemory, map);
swiWaitForVBlank();
}
3
return 0;
}
4