/*
JavaScript版RPGイベント戦闘処理
2010-12-31 創作プログラミングの街
*/
KEYFLAG_SELECT = 1;
KEYFLAG_UP = 2;
KEYFLAG_DOWN = 4;
KEYFLAG_LEFT = 8;
KEYFLAG_RIGHT = 16;
// メッセージ表示ウインドウクラス
var MessageWindow = function() {
// 表示位置
var x, y;
// 表示サイズ
var width, height;
// 枠の太さ
var borderWidth;
// テキスト領域の幅
var drawWidth;
// テキスト領域の高さ
var drawHeight;
// テキスト領域左上端座標
var drawX, drawY;
// テキスト領域余白
var textPadding;
// テキスト
var pages = null;
// フォント
var font;
// 行の高さ
var lineHeight;
var lineNum;
// ウインドウ状態
var status;
var STATUS_NONE;
var STATUS_PUTTING;
var STATUS_PAGEWAIT;
var STATUS_EXITWAIT;
// 表示中情報
var drawingPage;
var drawingLine;
var drawingChar;
// キー解放待機フラグ
var keyWait;
// 処理時間カウント
var actionCount;
// 表示フラグ
var display;
// 初期化
this.init = function() {
// フォントに等幅14ピクセルを指定
this.font = "14px monospace";
// 行高さ設定
this.lineHeight = 16;
// ウインドウ枠幅設定
this.borderWidth = 1;
// テキスト領域余白設定
this.textPadding = 2;
this.drawingPage = 0;
this.drawingLine = 0;
this.drawingChar = 0;
this.STATUS_NONE = 0;
this.STATUS_PUTTING = 1;
this.STATUS_PAGEWAIT = 2;
this.STATUS_EXITWAIT = 3;
this.STATUS_EXIT = 4;
this.status = this.STATUS_NONE;
this.actionCount = 0;
this.keyWait = false;
this.display = false;
}
// Canvas上表示位置設定
this.setPosition = function(x, y) {
// ウインドウ描画位置設定
this.x = x;
this.y = y;
// テキスト描画位置設定
this.drawX = x + this.borderWidth + this.textPadding;
this.drawY = y + this.borderWidth + this.textPadding;
}
// ウインドウサイズ設定
this.setSize = function(w, h) {
this.width = w;
this.height = h;
// テキスト領域描画幅算出
this.drawWidth = w - (this.borderWidth + this.textPadding) * 2;
// テキスト領域高さ算出
this.drawHeight = h - (this.borderWidth + this.textPadding) * 2;
// テキスト領域の描画可能行数算出
this.lineNum = Math.floor(this.drawHeight / this.lineHeight);
}
// 表示テキスト設定
this.setText = function(text, context) {
context.font = this.font;
this.pages = new Array();
if (text == null || text.length < 1) {
return;
}
var i = 0
var line = '';
var pos = 0;
var lines = new Array();
// テキスト描画領域の横幅に合わせて各行のテキスト作成
while (pos < text.length) {
var pageFlag = false;
// 改行指定が入るか横幅がテキスト領域を超えるまで文字追加
while (pos < text.length && context.measureText(line + text.charAt(pos)).width < this.drawWidth) {
// <:br>タグなら改行し現在位置をタグの次の文字へ
if (text.indexOf('<:br>', pos) == pos) {
pos += 5;
break;
}
// <:page>タグなら改ページ記号を挿入
if (text.indexOf('<:page>', pos) == pos) {
pos += 7;
pageFlag = true;
break;
}
line = line + text.charAt(pos++);
}
// 文字列を追加
lines.push(line);
if (pageFlag) {
lines.push("\f");
}
line = '';
}
var lineIndex = 0;
do {
// ページ毎のテキスト行配列作成
var pageLines = new Array();
// 最終ページ
if ((lines.length - lineIndex) <= this.lineNum) {
for (i = lineIndex;i < lines.length;i++) {
pageLines.push(lines[i]);
}
lineIndex = lines.length;
} else {
var pageLineIndex = 0;
while ((lineIndex < lines.length) && (pageLineIndex++ < (this.lineNum - 1))) {
if (lines[lineIndex].charAt(0) == "\f") {
lineIndex++;
break;
}
pageLines.push(lines[lineIndex]);
lineIndex++;
}
}
if (pageLines.length > 0) {
this.pages.push(pageLines);
}
} while (lineIndex < lines.length);
}
// 表示
this.show = function() {
// 表示フラグをセット
this.display = true;
// 表示状態を初期化
this.drawingPage = 0;
this.drawingLine = 0;
this.drawingChar = 0;
this.status = this.STATUS_PUTTING;
this.keyWait = false;
}
// 非表示
this.hide = function() {
// 表示フラグをリセット
this.display = false;
}
// 描画
this.draw = function(context) {
if (!this.display) {
return;
}
// ウインドウ領域全体を白でクリア
context.fillStyle = '#ffffff';
context.fillRect(this.x, this.y, this.width, this.height);
// 枠を残して黒でクリア
context.fillStyle = '#000000';
context.fillRect(this.x + this.borderWidth, this.y + this.borderWidth, this.width - this.borderWidth * 2, this.height - this.borderWidth * 2);
// テキスト描画設定
context.font = this.font;
context.fillStyle = '#ffffff';
context.textBaseline = 'top';
if (this.pages == null || this.pages.length < 1) {
return;
}
var i;
// 各行のテキストを描画
for (i = 0;i < this.drawingLine;i++) {
if (this.pages[this.drawingPage][i]) {
context.fillText(this.pages[this.drawingPage][i], this.drawX, this.drawY + i * this.lineHeight);
}
}
if (this.pages[this.drawingPage][this.drawingLine]) {
context.fillText(this.pages[this.drawingPage][this.drawingLine].substring(0, this.drawingChar), this.drawX, this.drawY + i * this.lineHeight);
}
// ページ表示完了時に次ページがあれば次ページ案内を表示
if (this.status == this.STATUS_PAGEWAIT && (this.actionCount % 20) > 10) {
context.beginPath();
// ウインドウ下部に三角形のパスを設定
context.moveTo(this.drawX + (this.drawWidth / 2) - 6, 2 + this.drawY + (this.lineNum - 1) * this.lineHeight);
context.lineTo(this.drawX + (this.drawWidth / 2) + 6, 2 + this.drawY + (this.lineNum - 1) * this.lineHeight);
context.lineTo(this.drawX + (this.drawWidth / 2), 14 + this.drawY + (this.lineNum - 1) * this.lineHeight);
context.closePath();
context.fillStyle = '#ffffff';
// 設定したパスを塗りつぶす
context.fill();
}
}
this.action = function(key) {
this.actionCount++;
if (this.pages == null || this.pages.length < 1) {
return false;
}
// キー解放待機中なら戻る
if (this.keyWait) {
if (key == 0) {
this.keyWait = false;
} else {
return true;
}
}
switch (this.status) {
// 文字表示中
case this.STATUS_PUTTING:
this.drawingChar++;
// キーが押されたらページ最後まで一気に表示
if (key == 1) {
this.drawingChar = this.pages[this.drawingPage][this.drawingLine].length - 1;
this.drawingLine = this.pages[this.drawingPage].length - 1;
this.keyWait = true;
return true;
}
if (!this.pages[this.drawingPage]) {
this.status = this.STATUS_PAGEWAIT;
drawingPage++;
} else {
// 行の最後まで表示したら次の行/ページ、または終了待機へ
if (this.pages[this.drawingPage][this.drawingLine].length < this.drawingChar) {
// ページ全体の表示が終わったら次ページ遷移/終了待機
if (this.drawingLine == this.pages[this.drawingPage].length - 1) {
if (this.drawingPage == this.pages.length - 1) {
this.status = this.STATUS_EXITWAIT;
} else {
this.status = this.STATUS_PAGEWAIT;
}
} else {
// 表示対象を次の行へ
this.drawingLine++;
// 描画文字位置を行頭へ
this.drawingChar = 0;
}
}
}
break;
// 次ページ待機中
case this.STATUS_PAGEWAIT:
// キーが押されたら次ページへ
if (key == 1) {
this.drawingPage++;
this.drawingLine = 0;
this.drawingChar = 0;
this.status = this.STATUS_PUTTING;
this.keyWait = true;
}
break;
// 終了待機
case this.STATUS_EXITWAIT:
// キーが押されたら非表示に
if (key == 1) {
this.status = this.STATUS_EXIT;
return false;
}
break;
}
return true;
}
// テキスト全体の表示が終わったか?
this.isTextEnd = function() {
if (this.status == this.STATUS_PUTTING || this.status == this.STATUS_PAGEWAIT) {
return false;
}
return true;
}
// 表示終了状態か?
this.isTextEnd = function() {
return this.status == this.STATUS_EXIT;
}
}
// 選択ダイアログクラス
var SelectDialog = function() {
// 表示位置
var x, y;
// 表示サイズ
var width, height;
// 枠の太さ
var borderWidth;
// テキスト領域の幅
var drawWidth;
// テキスト領域の高さ
var drawHeight;
// テキスト領域左上端座標
var drawX, drawY;
// テキスト領域余白
var textPadding;
// 選択肢
var items = null;
// フォント
var font;
// 行の高さ
var lineHeight;
// ウインドウ状態
var status;
var STATUS_NONE;
var STATUS_SELECTED;
// キー解放待機フラグ
var upKeyWait;
var downKeyWait;
// 表示フラグ
var display;
// カーソル位置
var index;
// 初期化
this.init = function() {
// フォントに等幅14ピクセルを指定
this.font = "14px monospace";
// 行高さ設定
this.lineHeight = 18;
// ウインドウ枠幅設定
this.borderWidth = 1;
// テキスト領域余白設定
this.textPadding = 2;
this.STATUS_NONE = 0;
this.STATUS_SELECTED = 1;
this.status = this.STATUS_NONE;
this.upKeyWait = 0;
this.downKeyWait = 0;
this.display = false;
this.index = 0;
this.setPosition(0, 0);
}
this.reset = function() {
this.status = this.STATUS_NONE;
this.upKeyWait = 0;
this.downKeyWait = 0;
this.index = 0;
}
// Canvas上表示位置設定
this.setPosition = function(x, y) {
// ウインドウ描画位置設定
this.x = x;
this.y = y;
// テキスト描画位置設定
this.drawX = x + this.borderWidth + this.textPadding;
this.drawY = y + this.borderWidth + this.textPadding;
}
// ウインドウサイズ設定
this.setDrawingSize = function(w, h) {
this.width = w + (this.borderWidth + this.textPadding) * 2;
this.height = h + (this.borderWidth + this.textPadding) * 2;
}
// 表示テキスト設定
this.setItems = function(items, context) {
var i;
this.items = new Array();
if (items && items.length > 0) {
for (i = 0;i < items.length;i++) {
this.items[i] = new String(items[i]);
}
}
context.font = this.font;
var maxWidth = 0;
// 選択肢文字列中の最大描画幅を取得
for (i = 0;i < items.length;i++) {
if (context.measureText(items[i]).width > maxWidth) {
maxWidth = context.measureText(items[i]).width;
}
}
// 選択肢の描画サイズに合わせてウインドウサイズ設定
this.setDrawingSize(maxWidth + 18, this.lineHeight * items.length);
}
// 表示
this.show = function() {
// 表示フラグをセット
this.display = true;
this.status = this.STATUS_NONE;
this.keyWait = false;
}
// 非表示
this.hide = function() {
// 表示フラグをリセット
this.display = false;
}
// 描画
this.draw = function(context) {
if (!this.display) {
return;
}
// ウインドウ領域全体を白でクリア
context.fillStyle = '#ffffff';
context.fillRect(this.x, this.y, this.width, this.height);
// 枠を残して黒でクリア
context.fillStyle = '#000000';
context.fillRect(this.x + this.borderWidth, this.y + this.borderWidth, this.width - this.borderWidth * 2, this.height - this.borderWidth * 2);
// テキスト描画設定
context.font = this.font;
context.fillStyle = '#ffffff';
context.textBaseline = 'top';
if (this.items == null || this.items.length < 1) {
return;
}
// 各行のテキストを描画
for (i = 0;i < this.items.length;i++) {
context.fillText(this.items[i], this.drawX + 16, this.drawY + i * this.lineHeight + 2);
}
context.fillStyle = '#ffffff';
context.beginPath();
// 現在の選択インデックスの位置に三角形のパスを設定
context.moveTo(this.drawX + 2, this.drawY + this.index * this.lineHeight + 3);
context.lineTo(this.drawX + 2, this.drawY + this.index * this.lineHeight + 14);
context.lineTo(this.drawX + 11, this.drawY + this.index * this.lineHeight + 8);
context.closePath();
// 設定したパスを塗りつぶす
context.fill();
}
this.action = function(key) {
if (this.items == null || this.items.length < 1) {
return false;
}
switch (this.status) {
case this.STATUS_NONE:
// 上方向キー処理待機状態更新
if (this.upKeyWait > 0) {
if ((key & KEYFLAG_UP) == 0) {
// 上キーが離されたら処理待機終了
this.upKeyWait = 0;
} else {
this.upKeyWait--;
}
}
// 下方向キー処理待機状態更新
if (this.downKeyWait > 0) {
if ((key & KEYFLAG_DOWN) == 0) {
// 下キーが離されたら処理待機終了
this.downKeyWait = 0;
} else {
this.downKeyWait--;
}
}
// リターンキー押下
if ((key & KEYFLAG_SELECT) != 0) {
// 選択状態に
this.status = this.STATUS_SELECTED;
return false;
}
// 上キー押下
if (this.upKeyWait == 0 && (key & KEYFLAG_UP) != 0 && this.index > 0) {
// 選択インデックスを一つ上へ
this.index--;
// 同一キー押下処理待機ウエイト設定
this.upKeyWait = 10;
}
// 下キー押下
if (this.downKeyWait == 0 && (key & KEYFLAG_DOWN) != 0 && this.index < this.items.length - 1) {
// 選択インデックスを一つ下へ
this.index++;
// 同一キー押下処理待機ウエイト設定
this.downKeyWait = 10;
}
break;
}
return true;
}
}
// HTML出力
document.write('
');
document.write('');
document.write('
');
document.write('
');
document.write('
');
document.write('');
document.write('イベントスクリプトソース
');
document.write('');
document.write('
');
// 開始フラグ
var testStart = false;
// 現在位置
var x = 60;
var y = 63;
// スクロール状態
var scrollState = 0;
// スクロール方向
var scrollDirect = 0;
// スクロール位置
var scrollPos = 0;
// スクロール速度
var scrollSpeed = 2;
var dx = 0;
var dy = 0;
// マップデータ配列
var map = new Array();
var mapAtt = new Array();
var eventList = new Array();
// マップチップサイズ
var tip_width = 32;
var tip_height = 32;
// マップサイズ
var map_cols = 100;
var map_rows = 100;
// 表示領域サイズ(チップ数)
var view_cols = 13;
var view_rows = 13;
var view_top = -Math.floor(view_cols / 2);
var view_left = -Math.floor(view_rows / 2);
var view_right = Math.floor(view_cols / 2);
var view_bottom = Math.floor(view_rows / 2);
var chrPosX = Math.floor(view_cols / 2);
var chrPosY = Math.floor(view_rows / 2);
// 表示領域サイズ
var view_width = view_cols * tip_width;
var view_height = view_rows * tip_height;
// 表示Canvas
var viewCanvas = document.getElementById('view_canvas');
var viewContext;
// マップ描画Canvas(非表示)
var mapCanvas = document.getElementById('map_canvas');
var mapContext;
// リソース画像から生成するImageオブジェクト
var partsImage;
var chrImage;
var evcharImage;
// キー状態フラグ
var keyFlag = 0;
var DIR_UP = KEYFLAG_UP;
var DIR_DOWN = KEYFLAG_DOWN;
var DIR_LEFT = KEYFLAG_LEFT;
var DIR_RIGHT = KEYFLAG_RIGHT;
// ゲームの処理状態
var gameState;
var GAMESTATE_WALK = 0;
var GAMESTATE_EVENT = 1;
// 現在処理中のスクリプト
var eventScriptItems;
// スクリプト変数格納配列
var eventVars;
// スクリプト変数最大番号
var VAL_MAX_INDEX = 99;
var eventItemIndex = 0;
var eventExecCode;
var eventExecArg;
// イベント処理の処理状況
var eventProcess;
var EVENTPROCESS_FETCH = 1;
var EVENTPROCESS_PROCESS = 2;
var EVENTPROCESS_END = 3;
// 現在処理中のイベントコード
var eventProcessItem;
var EVENTCODE_ERROR = -1;
var EVENTCODE_NONE = 0;
var EVENTCODE_GETVAR = 1;
var EVENTCODE_SETVAR = 2;
var EVENTCODE_MESSAGE = 10;
var EVENTCODE_SELECT = 11;
var EVENTCODE_SHOWIMAGE = 12;
var EVENTCODE_SETBGM = 13;
var EVENTCODE_BATTLE = 14;
var EVENTCODE_EQ = 30;
var EVENTCODE_NE = 31;
var EVENTCODE_LT = 32;
var EVENTCODE_LE = 33;
var EVENTCODE_GT = 34;
var EVENTCODE_GE = 35;
var EVENTCODE_IF = 40;
var EVENTCODE_ELSE = 41;
var EVENTCODE_ENDIF = 42;
// イベントコード処理の状態
var eventProcessStage;
var EVENTPROCESSSTAGE_MESSAGE_VIEW = 1;
var EVENTPROCESSSTAGE_MESSAGE_EXIT = 2;
var EVENTPROCESSSTAGE_SELECT_VIEW = 3;
var EVENTPROCESSSTAGE_SELECT_EXIT = 4;
var EVENTPROCESSSTAGE_SHOWIMAGE_LOADING = 5;
var EVENTPROCESSSTAGE_SHOWIMAGE_LOADED = 6;
var EVENTPROCESSSTAGE_SHOWIMAGE_VIEW = 7;
var EVENTPROCESSSTAGE_SHOWIMAGE_EXIT = 8;
var EVENTPROCESSSTAGE_BATTLE = 10;
var EVENTPROCESSSTAGE_BATTLE_EXIT = 11;
// 現在処理中のイベント
var gameEvent = null;
// イベントで表示するメッセージ表示ウインドウ
var eventMessageBox = null;
var eventSelectDlg = null;
var battleState
var BATTLESTATE_NONE = 0;
var BATTLESTATE_START_INIT = 1;
var BATTLESTATE_START_MESSAGE = 2;
var BATTLESTATE_START_EXIT = 3;
var BATTLESTATE_COMMAND_IN = 4;
var BATTLESTATE_COMMAND = 5;
var BATTLESTATE_COMMAND_SELECTED = 6;
var BATTLESTATE_BATTLE = 7;
var BATTLESTATE_BATTLE_END = 8;
var BATTLESTATE_END = 9;
var BATTLESTATE_EXIT = 10;
var BATTLEIMAGE_WIDTH = 128;
var BATTLEIMAGE_HEIGHT = 128;
var battleCommandSelect = null;
var battleMessage = null;
var bgmPlayer = null;
var eventIfLevel = 0;
var eventImage = null;
var eventImageX = 0;
var eventImageY = 0;
// イベント情報クラス
var EventItem = function(chr, x, y, passFlag, script){
// 表示するキャラクタ番号
this.chr = chr;
// イベント位置
this.x = x;
this.y = y;
// 通過フラグ
this.passFlag = passFlag;
// イベントで実行するスクリプト
this.script = script;
}
init();
function init() {
var i;
var j;
// Canvasが利用できなければ戻る
if (!mapCanvas.getContext) {
return;
}
var i;
var j;
// マップデータ初期化
for (i = 0;i < map_rows;i++) {
for (j = 0;j < map_cols;j++) {
map[j + i * map_cols] = 0;
mapAtt[j + i * map_cols] = 0;
}
}
// 乱数でマップデータ作成
for (i = view_rows;i < map_rows - view_rows;i++) {
for (j = view_cols;j < map_cols - view_cols;j++) {
map[j + i * map_cols] = 4 + Math.floor(Math.random() * 5);
}
}
// イベント情報配列作成
eventList = new Array();
for (i = 0;i < 128;i++) {
eventList[i] = null;
}
// イベント変数配列作成
eventVars = new Array();
// イベント変数配列初期化
for (i = 0;i <= VAL_MAX_INDEX;i++) {
eventVars[i] = 0;
}
loadGameData();
document.getElementById("scriptView").value = "";
// Canvasのコンテキスト取得
viewContext = viewCanvas.getContext('2d');
mapContext = mapCanvas.getContext('2d');
// マップ用地形パーツ画像読み込み
partsImage = new Image();
partsImage.src = 'evbattle_parts.png';
// キャラクタ用透過png画像読み込み
chrImage = new Image();
chrImage.src = 'evbattle_chr.png';
// イベントキャラクタ用透過png画像読み込み
evcharImage = new Image();
evcharImage.src = 'evbattle_evchar.gif';
// スクロールテスト領域にキーイベントハンドラを追加
document.getElementById("testArea").onkeydown = keydownHandler;
document.getElementById("testArea").onkeyup = keyupHandler;
// 開始ボタンを有効化
document.getElementById("testBtn").disabled = false;
gameState = GAMESTATE_WALK;
battleState = BATTLESTATE_NONE;
battleMessage = new MessageWindow();
battleMessage.init();
battleMessage.setSize(tip_width * (view_cols - 2), tip_height * 5);
battleMessage.setPosition(tip_width, tip_height * (view_rows - 6));
}
function loadGameData() {
var i;
var j;
// テスト用イベント作成
eventList[1] = new EventItem(1, 60, 60, false, 'message("メッセージ文字列表示テスト<:br><:br><:br><:br>改ページテスト<:page>メッセージウインドウは、画面中央下に一キャラクタ分のスペースをおいて配置。<:br><:br>改行テスト<:br>イベント処理中は、決定キーでメッセージウインドウの操作を行います。<:br><:br>メッセージ連続表示時に決定キーで全行表示、改ページ待機時に決定キーで次ページへ移動、表示完了後に決定キーでウインドウを閉じます。")' + "\n" + 'battle(1)' + "\n" + 'message("戦闘終了")');
eventList[2] = new EventItem(2, 61, 60, false, 'message("BGMを再生しますか?")' + "\n" + 'select(0,"はい いいえ")' + "\n" + "\n" + 'if(eq(getVar(0),0))' + "\n" + "\n" + ' select(1,"市場の朝 落ち葉の月夜")' + "\n" + "\n" + ' if(eq(getVar(1),0))' + "\n" + ' setBgm("itiba")' + "\n" + ' endif()' + "\n" + "\n" + ' if(eq(getVar(1),1))' + "\n" + ' setBgm("otiba")' + "\n" + ' endif()' + "\n" + "\n" + ' message("BGMを設定しました")' + "\n" + "\n" + 'else()' + "\n" + ' message("ではBGM設定は行いません")' + "\n" + 'endif()' + "\n" + "\n" + 'message("画像表示テストを行います")' + "\n" + 'showImage("evbattle.jpg")' + "\n" + 'message("テスト完了")');
// eventList[2] = new EventItem(2, 61, 60, false, 'message("選択ダイアログ表示テスト")' + "\n" + 'select("選択肢1 選択肢2 選択肢3 選択肢4")' + "\n" + 'message("画像表示テスト")' + "\n" + 'showImage("mapevs.jpg")');
// テスト用イベント周辺に草原配置
for (i = 58;i < 63;i++) {
for (j = 58;j < 64;j++) {
map[j + i * map_cols] = 4;
}
}
// テスト用イベント周辺に石畳配置
map[59 + 59 * map_cols] = 1;
map[60 + 59 * map_cols] = 8;
map[61 + 59 * map_cols] = 8;
map[62 + 59 * map_cols] = 1;
map[59 + 60 * map_cols] = 8;
map[60 + 60 * map_cols] = 8;
map[61 + 60 * map_cols] = 8;
map[62 + 60 * map_cols] = 8;
map[59 + 61 * map_cols] = 1;
map[60 + 61 * map_cols] = 8;
map[61 + 61 * map_cols] = 8;
map[62 + 61 * map_cols] = 1;
// マップ属性情報に通過不可の地形を記録
for (i = 0;i < map_rows;i++) {
for (j = 0;j < map_cols;j++) {
if (map[j + i * map_cols] < 4) {
mapAtt[j + i * map_cols] = 0x80;
}
}
}
}
// 開始ボタンクリック時
function start() {
// 開始ボタンを無効化
document.getElementById("testBtn").disabled = true;
drawScrollCanvas(x, y, 0);
draw();
loop();
}
// メインループ
function loop() {
// ゲーム状態に応じた処理
switch (gameState) {
// 通常(移動)状態
case GAMESTATE_WALK:
walk();
break;
// イベント処理中
case GAMESTATE_EVENT:
event();
break;
}
// 描画
draw();
// 一定時間後に再びloop()実行
setTimeout("loop()", 20);
}
// 通常(移動可能)状態の処理
function walk() {
switch (scrollState) {
// 非スクロール時
case 0:
switch (keyFlag) {
// 上キー押下
case DIR_UP:
// 進行方向への接触検査
if (toutch(x, y - 1)) {
dir = DIR_UP;
dx = 0;
dy = -1;
scrollPos = 0;
drawScrollCanvas(x, y, dir);
scrollState = 1;
}
break;
// 下キー押下
case DIR_DOWN:
// 進行方向への接触検査
if (toutch(x, y + 1)) {
dir = DIR_DOWN;
dx = 0;
dy = 1;
scrollPos = 0;
drawScrollCanvas(x, y, dir);
scrollState = 1;
}
break;
// 左キー押下
case DIR_LEFT:
// 進行方向への接触検査
if (toutch(x - 1, y)) {
dir = DIR_LEFT;
dx = -1;
dy = 0;
scrollPos = 0;
drawScrollCanvas(x, y, dir);
scrollState = 1;
}
break;
// 右キー押下
case DIR_RIGHT:
// 進行方向への接触検査
if (toutch(x + 1, y)) {
dir = DIR_RIGHT;
dx = 1;
dy = 0;
scrollPos = 0;
drawScrollCanvas(x, y, dir);
scrollState = 1;
}
break;
}
break;
// スクロール中
case 1:
scrollPos += scrollSpeed;
// スクロール位置更新
if (scrollPos == tip_width) {
x += dx;
y += dy;
// スクロール終了時に同方向キー押下中で移動可能なら続いて移動
if (keyFlag == dir && toutch(x + dx, y + dy)) {
scrollPos = 0;
drawScrollCanvas(x, y, dir);
} else {
scrollState = 0;
}
}
break;
}
}
// イベント処理
function event() {
// イベント処理状態に応じた処理
switch (eventProcess) {
// イベントコード取り込み
case EVENTPROCESS_FETCH:
eventProcessItem = eventScriptItems[eventItemIndex];
switch (eventProcessItem.code) {
// 変数に値を代入
case EVENTCODE_SETVAR:
// 代入する変数インデックス
varIndex = getVal(eventProcessItem.args[0]);
// 代入する値
val = getVal(eventProcessItem.args[1]);
if (varIndex == Number.NaN || val == Number.NaN || varIndex < 0 || varIndex > VAL_MAX_INDEX) {
return;
}
eventVars[varIndex] = val;
eventProcess = EVENTPROCESS_END;
break;
// IF文
case EVENTCODE_IF:
eventIfLevel++;
var ifLevel = 1;
// 引数で指定された条件の判定
if (getBoolean(eventProcessItem.args[0])) {
// 条件を満たしていればそのまま次のコマンドへ
eventProcess = EVENTPROCESS_END;
} else {
// IF文終了かELSEまで飛ばす
while (ifLevel > 0 && ++eventItemIndex < eventScriptItems.length) {
// 現在のif文に対応するelseがあればそこへ移行
if (eventScriptItems[eventItemIndex].code == EVENTCODE_ELSE && ifLevel == 1) {
break;
}
// IF文の中のIF文を飛ばす
switch (eventScriptItems[eventItemIndex].code) {
case EVENTCODE_IF:
ifLevel++;
break;
case EVENTCODE_ENDIF:
ifLevel--;
break;
}
}
eventProcess = EVENTPROCESS_END;
}
break;
// ELSE文(IF文真部分実行後のみここに来るためELSEブロックは実行しない)
case EVENTCODE_ELSE:
var ifLevel = 1;
// 現在のIF文終了まで飛ばす
while (ifLevel > 0 && ++eventItemIndex < eventScriptItems.length) {
// 現在のELSEブロック中のIF文を飛ばす
switch (eventScriptItems[eventItemIndex].code) {
case EVENTCODE_IF:
ifLevel++;
break;
case EVENTCODE_ENDIF:
ifLevel--;
break;
}
}
eventProcess = EVENTPROCESS_END;
break;
// IF文終了
case EVENTCODE_ENDIF:
eventProcess = EVENTPROCESS_END;
break;
// メッセージ表示
case EVENTCODE_MESSAGE:
// コマンド引数(表示文字列)取得
var messageArg = getArgString(eventProcessItem.args[0]);
// メッセージウインドウ作成
eventMessageBox = new MessageWindow();
eventMessageBox.init();
// サイズ設定
eventMessageBox.setSize(tip_width * (view_cols - 2), tip_height * 5);
// ゲーム画面中央に配置
eventMessageBox.setPosition(tip_width, tip_height * (view_rows - 6));
// 表示文字列設定
eventMessageBox.setText(messageArg, viewCanvas.getContext('2d'));
// 可視状態に
eventMessageBox.show();
// イベント状態をメッセージ表示中に
eventProcess = EVENTPROCESS_PROCESS;
eventProcessCode = EVENTCODE_MESSAGE;
eventProcessStage = EVENTPROCESSSTAGE_MESSAGE_VIEW;
break;
// 選択メニュー
case EVENTCODE_SELECT:
// 結果を格納する変数番号取得
var argVar = getVal(eventProcessItem.args[0]);
// コマンド引数(選択し文字列)取得
var argSelect = getArgString(eventProcessItem.args[1]);
// 選択ダイアログ作成
eventSelectDlg = new SelectDialog();
eventSelectDlg.init();
// タブ区切りで格納されている選択肢を分離
var items = argSelect.split("\t");
// 選択肢設定
eventSelectDlg.setItems(items, viewCanvas.getContext('2d'));
// ゲーム画面中央に配置
eventSelectDlg.setPosition((view_width - eventSelectDlg.width) / 2, (view_height - eventSelectDlg.height) / 2);
eventSelectDlg.show();
// イベント状態を選択ダイアログ表示中に
eventProcess = EVENTPROCESS_PROCESS;
eventProcessCode = EVENTCODE_SELECT;
eventProcessStage = EVENTPROCESSSTAGE_SELECT_VIEW;
break;
// 画像表示
case EVENTCODE_SHOWIMAGE:
// コマンド引数(画像ファイルパス)取得
var argImage = getArgString(eventProcessItem.args[0]);
// イベント状態を画像読み込み中に
eventProcess = EVENTPROCESS_PROCESS;
eventProcessCode = EVENTCODE_SHOWIMAGE;
eventProcessStage = EVENTPROCESSSTAGE_SHOWIMAGE_LOADING;
// Imageオブジェクト設定
eventImage = new Image();
// 画像の読み込みが完了したらイベント状態を画像読み込み完了に
eventImage.onload = function() {
eventProcessStage = EVENTPROCESSSTAGE_SHOWIMAGE_LOADED;
}
// 画像読み込み開始
eventImage.src = argImage;
break;
// BGM設定
case EVENTCODE_SETBGM:
// コマンド引数(音声ファイル名)取得
var argBgm = getArgString(eventProcessItem.args[0]);
var bgmType = null;
if (bgmPlayer != null) {
bgmPlayer.pause();
delete bgmPlayer;
}
bgmPlayer = new Audio('');
if (bgmPlayer.canPlayType("audio/ogg") == "maybe" || bgmPlayer.canPlayType("audio/ogg") == "probably") {
bgmType = "ogg";
}
if (bgmPlayer.canPlayType("audio/mp3") == "maybe" || bgmPlayer.canPlayType("audio/mp3") == "probably") {
bgmType = "mp3";
}
bgmPlayer.src = argBgm + '.' + bgmType;
bgmPlayer.addEventListener("ended", function() {
bgmPlayer.currentTime = 0;
bgmPlayer.play();
}, false);
bgmPlayer.play();
eventProcess = EVENTPROCESS_END;
break;
// 戦闘
case EVENTCODE_BATTLE:
eventProcessCode = EVENTCODE_BATTLE;
eventProcessStage = EVENTPROCESSSTAGE_BATTLE;
battleState = BATTLESTATE_START_INIT;
eventProcess = EVENTPROCESS_PROCESS;
break;
}
break;
// イベントコマンド処理中
case EVENTPROCESS_PROCESS:
switch (eventProcessCode) {
// メッセージ表示
case EVENTCODE_MESSAGE:
switch (eventProcessStage) {
case EVENTPROCESSSTAGE_MESSAGE_VIEW:
// メッセージ表示ウインドウの処理が終わったらイベント終了へ
if (!eventMessageBox.action(keyFlag)) {
eventProcessStage = EVENTPROCESSSTAGE_MESSAGE_EXIT;
}
break;
case EVENTPROCESSSTAGE_MESSAGE_EXIT:
if ((keyFlag & KEYFLAG_SELECT) == 0) {
eventProcess = EVENTPROCESS_END;
// メッセージ表示ウインドウを削除
delete eventMessageBox;
eventMessageBox = null;
}
break;
}
break;
// 選択ダイアログ
case EVENTCODE_SELECT:
switch (eventProcessStage) {
case EVENTPROCESSSTAGE_SELECT_VIEW:
// 選択ダイアログの処理が終わったらイベント終了へ
if (!eventSelectDlg.action(keyFlag)) {
// 結果を格納する変数番号取得
var argVar = getVal(eventProcessItem.args[0]);
// 選択結果を変数に格納
if (argVar >= 0 || argVar <= VAL_MAX_INDEX) {
eventVars[argVar] = eventSelectDlg.index;
}
eventProcessStage = EVENTPROCESSSTAGE_SELECT_EXIT;
}
break;
case EVENTPROCESSSTAGE_SELECT_EXIT:
if ((keyFlag & KEYFLAG_SELECT) == 0) {
eventProcess = EVENTPROCESS_END;
// 選択ダイアログを削除
delete eventSelectDlg;
eventSelectDlg = null;
}
break;
}
break;
// 画像表示
case EVENTCODE_SHOWIMAGE:
switch (eventProcessStage) {
// 画像読み込み完了
case EVENTPROCESSSTAGE_SHOWIMAGE_LOADED:
// 中央に配置するため表示位置計算
eventImageX = (view_width - eventImage.width) / 2;
eventImageY = (view_height - eventImage.height) / 2;
eventProcessStage = EVENTPROCESSSTAGE_SHOWIMAGE_VIEW;
break;
// 画像表示中
case EVENTPROCESSSTAGE_SHOWIMAGE_VIEW:
// リターンキーで終了処理待機状態へ
if ((keyFlag & KEYFLAG_SELECT) != 0) {
eventProcessStage = EVENTPROCESSSTAGE_SHOWIMAGE_EXIT;
}
break;
// 表示処理終了待機
case EVENTPROCESSSTAGE_SHOWIMAGE_EXIT:
// リターンキーが離されたら終了
if ((keyFlag & 1) == 0) {
eventProcess = EVENTPROCESS_END;
// Imageオブジェクトを破棄
delete eventImage;
eventImage = null;
}
break;
}
break;
// 戦闘
case EVENTCODE_BATTLE:
switch (eventProcessStage) {
case EVENTPROCESSSTAGE_BATTLE:
// 戦闘処理
if (!battle()) {
eventProcessStage = EVENTPROCESSSTAGE_BATTLE_EXIT;
}
break;
case EVENTPROCESSSTAGE_BATTLE_EXIT:
// リターンキーが離されたら戦闘終了
if ((keyFlag & 1) == 0) {
// 次のコマンドへ
eventProcess = EVENTPROCESS_END;
}
break;
}
break;
}
break;
// イベント実行終了
case EVENTPROCESS_END:
if (++eventItemIndex < eventScriptItems.length) {
eventProcess = EVENTPROCESS_FETCH;
} else {
// ゲームを通常状態へ
gameState = GAMESTATE_WALK;
}
break;
}
}
function battle() {
switch (battleState) {
case BATTLESTATE_START_INIT:
battleMessage.setText("敵と遭遇", viewCanvas.getContext('2d'));
battleMessage.show();
battleState = BATTLESTATE_START_MESSAGE;
break;
case BATTLESTATE_START_MESSAGE:
battleMessage.action(keyFlag & 1);
if (battleMessage.isTextEnd() && (keyFlag & 1) == 0) {
battleState = BATTLESTATE_START_EXIT;
}
break;
case BATTLESTATE_START_EXIT:
battleState = BATTLESTATE_COMMAND_IN;
battleCommandSelect = new SelectDialog();
battleCommandSelect.init();
battleCommandSelect.setItems(["攻撃", "退避"], viewCanvas.getContext('2d'));
battleCommandSelect.setPosition((view_width - battleCommandSelect.width) / 2, (view_height - battleCommandSelect.height) / 2);
battleCommandSelect.show();
break;
case BATTLESTATE_COMMAND_IN:
if ((keyFlag & KEYFLAG_SELECT) == 0) {
battleCommandSelect.reset();
battleMessage.setText("", viewCanvas.getContext('2d'));
battleState = BATTLESTATE_COMMAND;
}
break;
case BATTLESTATE_COMMAND:
// 選択ダイアログの処理が終わったら戦闘処理へ
if (!battleCommandSelect.action(keyFlag)) {
battleState = BATTLESTATE_COMMAND_SELECTED;
}
break;
case BATTLESTATE_COMMAND_SELECTED:
if ((keyFlag & KEYFLAG_SELECT) == 0) {
switch (battleCommandSelect.index) {
case 0:
battleState = BATTLESTATE_BATTLE;
break;
case 1:
battleState = BATTLESTATE_END;
battleMessage.setText("離脱成功 ", viewCanvas.getContext('2d'));
break;
}
}
break;
case BATTLESTATE_BATTLE:
battleMessage.setText("戦闘処理 ", viewCanvas.getContext('2d'));
battleState = BATTLESTATE_BATTLE_END;
break;
case BATTLESTATE_BATTLE_END:
if ((keyFlag & KEYFLAG_SELECT) != 0) {
battleState = BATTLESTATE_COMMAND_IN;
}
break;
case BATTLESTATE_END:
// 決定キーが離されたら戦闘処理終了待機へ
if ((keyFlag & KEYFLAG_SELECT) == 0) {
battleState = BATTLESTATE_EXIT;
}
break;
case BATTLESTATE_EXIT:
// ゲームを通常状態へ
if ((keyFlag & KEYFLAG_SELECT) != 0) {
battleState = BATTLESTATE_NONE;
// gameState = GAMESTATE_EVENT;
return false;
}
break;
}
return true;
}
// スクリプトで有効な文字列を取得
function getArgString(arg) {
// 先頭と末尾の空白文字削除
var text = chop(arg);
// ""で囲まれていない文字列は無効
if (text == null || text.length < 3 || text.charAt(0) != '"' || text.charAt(text.length - 1) != '"') {
return null;
}
// ""の間の文字列を取得
var str = text.substring(1, text.length - 1);
return str;
}
// 文字列が数字か検査
function isNum(arg) {
var i;
// 空文字列なら偽
if (arg == null || arg.length < 1) {
return false;
}
str = new String(arg);
// 先頭の-を除く
if (str.charAt(0) == '-') {
str = str.substr(1);
}
if (arg == null || arg.length < 1) {
return false;
}
// 0-9以外の文字が出てきたら偽
for (i = 0;i < str.length;i++) {
if (str.charAt(i) < '0' || str.charAt(i) > '9') {
return false;
}
}
// 最後まで条件違反がなければ真
return true;
}
// 文字列を数値評価
function getVal(arg) {
// 数字文字列ならその値を返す
if (isNum(arg)) {
return parseInt(arg, 10);
}
// 文字列をコマンドとして解析
var command = parseCommand(arg);
// 文字列がgetVar(変数の値取得)コマンドならその値を評価
if (command.code == EVENTCODE_GETVAR) {
// 変数番号を取得
var index = getVal(command.args[0]);
// 指定番号が変数番号の範囲になければ異常値
if (index == Number.NaN || index < 0 || index > VAL_MAX_INDEX) {
return Number.NaN;
}
// 変数の値を返す
return eventVars[index];
}
return Number.NaN;
}
// 文字列の条件式の真偽を評価
function getBoolean(arg) {
var command = parseCommand(arg);
switch (command.code) {
// eq()関数(等しい時に真)
case EVENTCODE_EQ:
// 引数として渡された左辺値と右辺値を評価
var leftVal = getVal(command.args[0]);
var rightVal = getVal(command.args[1]);
// 評価不能な値なら無条件にfalse
if (leftVal == Number.NaN || rightVal == Number.NaN) {
return false;
}
return leftVal == rightVal;
// ne()関数(等しくない時に真)
case EVENTCODE_NE:
// 引数として渡された左辺値と右辺値を評価
var leftVal = getVal(command.args[0]);
var rightVal = getVal(command.args[1]);
// 評価不能な値なら無条件にfalse
if (leftVal == Number.NaN || rightVal == Number.NaN) {
return false;
}
return leftVal != rightVal;
}
}
// マップの指定位置へ接触検査
function toutch(x, y) {
var event = getEvent(x, y);
// 指定位置にイベントがなくて通過可能ならtrueを返す
if (event == null && mapAtt[x + y * map_cols] == 0) {
return true;
}
// イベントがなくて通過不可ならfalseを返す
if (event == null) {
return false;
}
document.getElementById('scriptView').value = event.script;
// 指定位置のイベントスクリプトのコマンドを取得
eventScriptItems = getScriptItems(event.script);
if (eventScriptItems == null) {
return;
}
// イベント処理へ移行
gameEvent = event;
eventItemIndex = 0;
gameState = GAMESTATE_EVENT;
eventProcess = EVENTPROCESS_FETCH;
return event.passFlag;
}
// 指定位置のイベントを取得
function getEvent(x, y) {
var i;
// イベント格納配列を走査し、指定位置のイベントがあれば返す
for (i = 0;i < eventList.length;i++) {
if (eventList[i] != null && eventList[i].x == x && eventList[i].y == y) {
return eventList[i];
}
}
return null;
}
// スクリプトソースからコマンド配列を作成
function getScriptItems(src) {
var i;
if (src == null || src.length < 1) {
return null;
}
// 改行を\nに統一
var script = src.replace("\r\n", "\n");
script = src.replace("\r", "\n");
// 各行を配列に格納
var lines = script.split("\n");
var commandList = new Array();
// 各行のコマンドを作成
for (i = 0;i < lines.length;i++) {
var lineItem = parseCommand(lines[i]);
if (lineItem.code != EVENTCODE_NONE) {
commandList.push(lineItem);
}
}
return commandList;
}
// スクリプト文字列からコマンド情報オブジェクトを作成
function parseCommand(str) {
var i;
var result = new Object();
result.script = str;
// 先頭と末尾の空白文字を削除
var item = chop(str);
if (item == null || item.length < 1 || item.indexOf("//") == 0) {
result.code = EVENTCODE_NONE;
} else {
// 最初に(が出てくる位置を探索
var argIndex = item.indexOf("(");
result.code = EVENTCODE_ERROR;
if (argIndex > 0 && item.charAt(item.length - 1) == ')') {
// (までをコマンドとして記録
var command = item.substring(0, argIndex);
// ()内を引数として記録
var arg = chop(item.substring(argIndex + 1, item.length - 1));
// ,で引数を分離し引数配列に格納
if (arg != null && arg.length > 0) {
var args = new Array();
var argItem = '';
var quoteIn = false;
var funcLevel = 0;
for (i = 0;i < arg.length;i++) {
// "が出てきたら"フラグ反転
if (arg.charAt(i) == '"') {
quoteIn = !quoteIn;
}
// ""外で()が出てきたら関数の処理
if (!quoteIn) {
if (arg.charAt(i) == '(') {
funcLevel++;
}
if (arg.charAt(i) == ')') {
funcLevel--;
}
}
if ((!quoteIn && funcLevel == 0 && arg.charAt(i) == ',') || i == arg.length - 1) {
if (i == arg.length - 1) {
argItem = argItem + arg.charAt(i);
}
args.push(chop(argItem));
argItem = '';
} else {
argItem = argItem + arg.charAt(i);
}
}
result.args = args;
} else {
result.args = null;
}
if (command == 'getVar' && args != null && args.length == 1) {
result.code = EVENTCODE_GETVAR;
}
if (command == 'setVar' && args != null && args.length == 2) {
result.code = EVENTCODE_SETVAR;
}
if (command == 'eq' && args != null && args.length == 2) {
result.code = EVENTCODE_EQ;
}
if (command == 'ne' && args != null && args.length == 2) {
result.code = EVENTCODE_NE;
}
if (command == 'message' && args != null && args.length == 1) {
result.code = EVENTCODE_MESSAGE;
}
if (command == 'select' && args != null && args.length == 2) {
result.code = EVENTCODE_SELECT;
}
if (command == 'showImage' && args != null && args.length == 1) {
result.code = EVENTCODE_SHOWIMAGE;
}
if (command == 'setBgm' && args != null && args.length == 1) {
result.code = EVENTCODE_SETBGM;
}
if (command == 'battle' && args != null && args.length == 1) {
result.code = EVENTCODE_BATTLE;
}
if (command == 'if' && args != null && args.length == 1) {
result.code = EVENTCODE_IF;
}
if (command == 'else') {
result.code = EVENTCODE_ELSE;
}
if (command == 'endif') {
result.code = EVENTCODE_ENDIF;
}
}
}
return result;
}
// 指定文字列の先頭と末尾にある空白文字を削除した文字列を返す
function chop(str) {
if (str == null || str.length < 1) {
return null;
}
var result;
var startIndex = 0;
var lastIndex = str.length - 1;
// 行頭から空白文字でない文字が出てくる位置を検索
while (startIndex < str.length && (str.charAt(startIndex) == ' ' || str.charAt(startIndex) == "\t")) {
startIndex++;
}
// 空白文字のみの文字列ならnullを返す
if (startIndex == str.length) {
return null;
}
// 行末から空白文字でない文字が出てくる位置を検索
while (lastIndex >= 0 && (str.charAt(lastIndex) == ' ' || str.charAt(lastIndex) == "\t")) {
lastIndex--;
}
return str.substring(startIndex, lastIndex + 1);
}
// スクロールキャンバス描画
function drawScrollCanvas(sx, sy, dir) {
var i;
var j;
sx += view_left;
sy += view_top;
switch (dir) {
// 新規描画
case 0:
// マップ描画Canvasにスクロール範囲を描画
for (i = 0;i < view_rows;i++) {
for (j = 0;j < view_cols;j++) {
mapContext.drawImage(partsImage, (map[sx + j + (sy + i) * map_cols] % 4) * tip_width, Math.floor(map[sx + j + (sy + i) * map_cols] / 4) * tip_height, tip_width, tip_height, j * tip_width, i * tip_height, tip_width, tip_height);
}
}
break;
// 上スクロール
case DIR_UP:
// マップ描画Canvasにスクロール範囲を描画
for (i = 0;i < view_rows + 1;i++) {
for (j = 0;j < view_cols;j++) {
mapContext.drawImage(partsImage, (map[sx + j + (sy - 1 + i) * map_cols] % 4) * tip_width, Math.floor(map[sx + j + (sy - 1 + i) * map_cols] / 4) * tip_height, tip_width, tip_height, j * tip_width, i * tip_height, tip_width, tip_height);
}
}
break;
// 下スクロール
case DIR_DOWN:
// マップ描画Canvasにスクロール範囲を描画
for (i = 0;i < view_rows + 1;i++) {
for (j = 0;j < view_cols;j++) {
mapContext.drawImage(partsImage, (map[sx + j + (sy + i) * map_cols] % 4) * tip_width, Math.floor(map[sx + j + (sy + i) * map_cols] / 4) * tip_height, tip_width, tip_height, j * tip_width, i * tip_height, tip_width, tip_height);
}
}
break;
// 左スクロール
case DIR_LEFT:
// マップ描画Canvasにスクロール範囲を描画
for (i = 0;i < view_rows;i++) {
for (j = 0;j < view_cols + 1;j++) {
mapContext.drawImage(partsImage, (map[sx - 1 + j + (sy + i) * map_cols] % 4) * tip_width, Math.floor(map[sx - 1 + j + (sy + i) * map_cols] / 4) * tip_height, tip_width, tip_height, j * tip_width, i * tip_height, tip_width, tip_height);
}
}
break;
// 右スクロール
case DIR_RIGHT:
// マップ描画Canvasにスクロール範囲を描画
for (i = 0;i < view_rows;i++) {
for (j = 0;j < view_cols + 1;j++) {
mapContext.drawImage(partsImage, (map[sx + j + (sy + i) * map_cols] % 4) * tip_width, Math.floor(map[sx + j + (sy + i) * map_cols] / 4) * tip_height, tip_width, tip_height, j * tip_width, i * tip_height, tip_width, tip_height);
}
}
break;
}
}
// 表示Canvasに描画
function draw() {
var i;
// Canvasのコンテキスト取得
var viewContext = viewCanvas.getContext('2d');
var drawX = 0;
var drawY = 0;
if (dx > 0) {
drawX = dx * scrollPos;
}
if (dx < 0) {
drawX = tip_width + (dx * scrollPos);
}
if (dy > 0) {
drawY = dy * scrollPos;
}
if (dy < 0) {
drawY = tip_height + (dy * scrollPos);
}
// マップ描画Canvasを転送
viewContext.drawImage(mapCanvas, drawX, drawY, tip_width * view_cols, tip_height * view_rows, 0, 0, tip_width * view_cols, tip_height * view_rows);
var ecx = 0;
var ecy = 0;
if (scrollState == 1) {
if (dx < 0) {
ecx = -drawX + tip_width;
} else {
ecx = -drawX;
}
if (dy < 0) {
ecy = -drawY + tip_height;
} else {
ecy = -drawY;
}
}
// イベントキャラクタ描画
for (i = 0;i < eventList.length;i++) {
if (eventList[i] != null && eventList[i].chr > 0 && (eventList[i].x > x + view_left - 2) && (eventList[i].x < x + view_right + 2) && (eventList[i].y > y + view_top - 2) && (eventList[i].y < y + view_bottom + 2)) {
viewContext.drawImage(evcharImage, ((eventList[i].chr - 1) % 4) * tip_width, Math.floor((eventList[i].chr - 1) / 4) * tip_height, tip_width, tip_height, ecx + (eventList[i].x - (x + view_left)) * tip_width, ecy + (eventList[i].y - (y + view_top)) * tip_height, tip_width, tip_height);
}
}
// 主人公描画
viewContext.drawImage(chrImage, chrPosX * tip_width, chrPosY * tip_height);
// イベント描画
if (gameState == GAMESTATE_EVENT && eventProcessItem) {
switch (eventProcessItem.code) {
case EVENTCODE_MESSAGE:
if (eventProcessStage == EVENTPROCESSSTAGE_MESSAGE_VIEW) {
eventMessageBox.draw(viewContext);
}
break;
case EVENTCODE_SELECT:
if (eventProcessStage == EVENTPROCESSSTAGE_SELECT_VIEW) {
eventSelectDlg.draw(viewContext);
}
break;
case EVENTCODE_SHOWIMAGE:
if (eventProcessStage == EVENTPROCESSSTAGE_SHOWIMAGE_VIEW) {
viewContext.drawImage(eventImage, eventImageX, eventImageY);
}
break;
case EVENTCODE_BATTLE:
// 戦闘描画
if (battleState != BATTLESTATE_NONE) {
viewContext.fillStyle = '#ffffff';
viewContext.fillRect((view_width / 2) - (BATTLEIMAGE_WIDTH + 2) / 2, (view_height / 2) - (BATTLEIMAGE_HEIGHT + 2), BATTLEIMAGE_WIDTH, BATTLEIMAGE_HEIGHT);
battleMessage.draw(viewContext);
if (battleState == BATTLESTATE_COMMAND) {
battleCommandSelect.draw(viewContext);
}
}
break;
}
}
}
// キー押下イベント処理
function keydownHandler(e) {
var code = 0;
code = e.keyCode;
// キー押下状態に応じてキーフラグ設定
switch (code) {
// リターンキー
case 13:
e.preventDefault();
keyFlag |= KEYFLAG_SELECT;
break;
// 上キー
case 38:
e.preventDefault();
keyFlag |= KEYFLAG_UP;
break;
// 下キー
case 40:
e.preventDefault();
keyFlag |= KEYFLAG_DOWN;
break;
// 左キー
case 37:
e.preventDefault();
keyFlag |= KEYFLAG_LEFT;
break;
// 右キー
case 39:
e.preventDefault();
keyFlag |= KEYFLAG_RIGHT;
break;
}
}
// キー解放イベント処理
function keyupHandler(e) {
var code = 0;
code = e.keyCode;
// キー押下状態に応じてキーフラグ設定
switch (code) {
// リターンキー
case 13:
e.preventDefault();
keyFlag &= ~KEYFLAG_SELECT;
break;
// 上キー
case 38:
e.preventDefault();
keyFlag &= ~KEYFLAG_UP;
break;
// 下キー
case 40:
e.preventDefault();
keyFlag &= ~KEYFLAG_DOWN;
break;
// 左キー
case 37:
e.preventDefault();
keyFlag &= ~KEYFLAG_LEFT;
break;
// 右キー
case 39:
e.preventDefault();
keyFlag &= ~KEYFLAG_RIGHT;
break;
}
}