スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

カテゴリ : スポンサー広告

第3回同人ゲーム制作勉強会

第3回同人ゲーム制作勉強会に参加してきました。
前回、前々回では講師としてKAGEX/KAGEZの話をしてきましたが、今回は喋らずお話聞いてきました。
2回目は準備できず残念なことになったり、解説本出す出す詐欺になってたりアレなので首に・・・・・・というわけではないですが。
座ってるだけ、というのは気楽なもんでいいです。

まずは勉強会の紹介をすると、同人サークルたんすかいさんの主催で、同人ゲーム制作者が新宿に集まって情報交換しよう、という会です。
ノベルゲーム系で制作初心者~中級者向けの内容。
同人ノベルゲーム制作者が集まる勉強会はあまり無いんじゃないでしょうか。
そちらに興味ある方なら次回から参加してみても良いと思います。


で、今回の内容ですが既に2週間過ぎてあまり記憶に残ってません。
最近は勉強会のレポート書いていなかったので久々に。
ブログ書くまでが勉強会らしいよ!

参加人数は10人強くらい。
まあそこそこ、といったところ?

とりあえず遅刻してごめんなさい・・・・・・。
当日朝まで作業して、仮眠しようと思ったらちょっと寝過ぎました・・・・・・。
そんなこんなで慌てて会場に着いて資料見ると、事前アンケートの質問内容がしっかり印刷されています。
1人で7個も書いたし! 何故か自分だけ色分けされてるし! なんか恥ずかしい! やめて!

1つめの講演はyositaさんのコストから考えるゲーム制作でしたが、ほとんど終わる所でした。
残念ながら内容は分かりません。。。
しかしお金は大事です。
作ってみると思った以上にお金も時間もかかります。

2つめはSelenium EX-Kさんでゲーム制作のための第一歩、という内容。
本当に初心者向けで、1作目作る人向けだったはず。
やっぱり覚えてない・・・・・・ごめんなさい・・・・・・。
どう考えてもメモ帳とペン忘れてきたのが敗因。

その次はコミティアでやってるノベルゲーム部の紹介など。
実際に配った冊子を貰いましたが、思ったよりしっかりしていて驚きました。
全ページカラーで刷ってます。すごい。
こんなに頑張ってるならコミティア参加しようかな?という気分にもなります。
しかしコミティアでゲーム出しても売れないからね……。
ノベルゲーム部の次回の活動は来年5月のコミティアになるようです。

最後はサークルインタビューということで、事前に集めた質問に答えていく形。
たくさん質問書いてごめんね! 何個か抽出されるんだと思ったんだよ!
売るためには売り子に女性使えってのは笑った。
確かにあれは目立っていいねー。

他にもいろいろありましたがぼんやりとしか思い出せません。
ほとんど忘却の彼方で我ながら恐ろしい。
メモ取らないと駄目。一番勉強になったのはそれでした。


勉強会後の交流会も行ってきました。
柊鰯の柊さんの話をしたのは覚えてます。
猛プッシュされるので気にはなっているんですが、未だに柊鰯やってないなんて言えない。

次回の勉強会は来年の春あたりらしいです。
また自分が話すかはわかりませんがおそらく参加はしてます。
最近は個人的に商業志向が強いので勉強会の内容の方はあんまりなーと思いつつ楽しいので。
春先なら参加人数も増えるんじゃないでしょうか。
暖かくなってくるとフラフラ出歩く人が増えます。
寒い時期は正直外出るの厳しい……。
みんな勉強会参加しようぜ!

続きを閉じる▲

カテゴリ : 感想文

tjsの配列でC#のLINQが使う

使いたかったのでArrayに関数増やしてみた。
ひとつひとつは大したこと無くても数が多くて面倒だった・・・・・・。

実際にtjsで使いどころがあるかは微妙。吉里吉里でツール作るときとかはいいかも。
使いそうなのだけコピペして使ってもいいんじゃないかしら。


/// 指定された位置の要素を返すが、添え字が範囲外の場合は例外を投げる
/// @param index 要素の位置
/// @return 指定された位置の要素
Array.elementAt = function(index) {
  if (index < 0 || index >= this.count) {
    throw new Exception("配列のindexが範囲外です");
  }
  return this[index];
};

/// 配列をコピーして返す
/// @return 配列のコピー
Array.clone = function() {
  var tmp = [];
  tmp.assign(this);
  return tmp;
};

/// 配列の各要素の関数を適用する
/// @param func 各要素を受け取って処理する関数
Array.foreach = function(func) {
  for (var i = 0; i < this.count; ++i) {
    func(this[i], i);
  }
};

/// 配列から辞書配列を生成する
/// キーが重複すると例外を投げる
/// @param keySelector 各要素を受け取ってキーを返す関数
/// @param elementSelector 各要素を受け取って辞書配列の値を返す関数
/// @return keySelectorの戻り値をキー、たいおうするelementSelectorの戻り値を値とする辞書配列
Array.toDictionary = function(keySelector, elementSelector) {
  if (elementSelector === void) elementSelector = function(elm) { return elm; };
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] !== voidthrow new Exception("キーが重複しています。");
    tmp[key] = elementSelector(this[i]);
  }
  return tmp;
};

/// 配列から辞書配列を生成する
/// 辞書配列の要素が配列のため、キーが重なっても格納できる
/// @param keySelector 各要素を受け取ってキーを返す関数
/// @param elementSelector 各要素を受け取って辞書配列の値の配列に入れる要素を返す関数
/// @return keySelectorの戻り値をキー、対応するelementSelectorの戻り値が入った配列を値とする辞書配列
Array.toLookup = function(keySelector, elementSelector) {
  if (elementSelector === void) elementSelector = function(elm) { return elm; };
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] === void) tmp[key] = [];
    tmp[key].add(elementSelector(this[i]));
  }
  return tmp;
};

/// 配列の各要素に変換関数を適用する
/// @param selector 各要素を受け取って、変換後の要素を返す関数
/// @return selectorの戻り値が入った配列
Array.select = function(selector) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    tmp.push(selector(this[i], i));
  }
  return tmp;
};

/// 配列の各要素に変換関数を適用する
/// 要素1つが1つ以上の要素に変換される
/// @param selector 各要素を受け取って、変換後の要素の配列を返す関数
/// @return selectorの返した配列を展開して格納した配列
Array.selectMany = function(selector) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    tmp.push(selector(this[i], i)*);
  }
  return tmp;
};

/// 条件を満たす要素のみを抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 条件を満たす要素のみを抽出した配列
Array.where = function(predicate) {
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) {
      tmp.push(this[i]);
    }
  }
  return tmp;
};

/// 配列の全要素を条件に従ってグループ分けする
/// @param keySelector 各要素からキーを返す関数
/// @return keySelectorの戻り値がキー、対応する各要素が入った配列が値となった辞書配列
Array.groupBy = function(keySelector) {
  var tmp = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    if (tmp[key] === void) tmp[key] = [];
    tmp[key].push(this[i]);
  }
  return tmp;
};

/// 配列を条件に従って昇順に整列する
/// @param keySelector 各要素から比較に使う値を返す関数
/// @param comparer 要素を2つ受け取って、最初の値が小さければtrueとなる関数
/// @return 整列ずみの配列
Array.orderBy = function(keySelector, comparer) {
  if (comparer === void) {
    comparer = function(first, second) { return first < second; };
  }
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    var key = keySelector(this[i], i);
    var inserted = false;
    for (var j = 0; j < tmp.count; ++j) {
      if (comparer(key, tmp[j])) {
        tmp.insert(j, this[i]);
        inserted = true;
        break;
      }
    }
    if (!inserted) tmp.push(this[i]);
  }
  return tmp;
};

/// 配列を条件に従って降順に整列する
/// @param keySelector 各要素から比較に使う値を返す関数
/// @param comparer 要素を2つ受け取って、最初の値が小さければtrueとなる関数
/// @return 整列ずみの配列
Array.orderByDescending = function(keySelector, comparer) {
  if (comparer === void) {
    comparer = function(first, second) { return first > second; };
  } else {
    comparer = function { return !comparer(...); } incontextof %[ comparer:comparer ];
  }
  return orderBy(keySelector, comparer);
};

/// 自身(outer)と指定された配列(inner)を内部結合します
/// @param outer 結合する配列
/// @param outerKeySelector 配列outerの各要素を受け取ってキーを返す関数
/// @param innerKeySelector 配列innerの各要素を受け取ってキーを返す関数
/// @param resultSelector キーが一致する配列(outer)と配列(inner)の要素を受け取って結果となる要素を返す関数
/// @return resultSelectorの戻り値が入った配列
/// Array.joinは使われているのでArray.innerJoin
Array.innerJoin = function(inner, outerKeySelector, innerKeySelector, resultSelector) {
  var outerKeys = %[];
  for (var i = 0; i < this.count; ++i) {
    var key = outerKeySelector(this[i]);
    if (outerKeys[key] === void) outerKeys[key] = [];
    outerKeys[key].add(this[i]);
  }
  
  var results = [];
  for (var i = 0; i < inner.count; ++i) {
    var key = innerKeySelector(inner[i]);
    if (outerKeys[key] === voidcontinue;
    for (var j = 0; j < outerKeys[key].count; ++j) {
      results.add(resultSelector(outerKeys[key][j], inner[i]));
    }
  }
  return results;
};

/// 自身(outer)と指定された配列(inner)を左外部結合します
/// @param outer 結合する配列
/// @param outerKeySelector 配列outerの各要素を受け取ってキーを返す関数
/// @param innerKeySelector 配列innerの各要素を受け取ってキーを返す関数
/// @param resultSelector キーが一致する配列(outer)要素と配列(inner)要素の配列を受け取って結果となる要素を返す関数
Array.groupJoin = function(inner, outerKeySelector, innerKeySelector, resultSelector) {
  var innerKeys = %[];
  for (var i = 0; i < inner.count; ++i) {
    var key = innerKeySelector(inner[i]);
    if (innerKeys[key] === void) innerKeys[key] = [];
    innerKeys[key].add(inner[i]);
  }
  
  var results = [];
  for (var i = 0; i < this.count; ++i) {
    var key = outerKeySelector(this[i]);
    results.add(resultSelector(this[i], innerKeys[key] !== void ? innerKeys[key] : []));
  }
  return results;
};

/// 配列の先頭から指定された数だけ抽出する
/// @param count 取り出す数
/// @return 配列の先頭から指定された数だけ取り出した配列
Array.take = function(count) {
  if (count > this.count) count = this.count;
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = this[i];
  }
  return tmp;
};

/// 配列の先頭から指定された数だけ飛ばして、残りを抽出する
/// @param count 飛ばす数
/// @return 配列の先頭から指定された数だけ飛ばした残りの配列
Array.skip = function(count) {
  var tmp = [];
  for (var i = count; i < this.count; ++i) {
    tmp.add(this[i]);
  }
  return tmp;
};

/// 配列の先頭から条件を満たす限りの要素を抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 配列の先頭から条件を満たす限りまでの配列
Array.takeWhile = function(predicate) {
  var count = 0;
  while (predicate(this[count], count) && ++count < this.count);
  return this.take(count);
};

/// 配列の先頭から条件を満たす限りの要素を飛ばし、残りを抽出する
/// @param predicate 各要素を受け取って条件を満たすか返す関数
/// @return 配列の先頭から条件を満たす限り飛ばした残りの配列
Array.skipWhile = function(predicate) {
  var count = 0;
  while (predicate(this[count], count) && ++count < this.count);
  return this.skip(count);
};

/// 配列から同一の要素を取り除く
/// @return 重複した要素を取り除いた配列
Array.distinct = function() {
  var tmp = [];
  var values = %[];
  for (var i = 0; i < this.count; ++i) {
    var value = this[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  return tmp;
};

/// 現在の配列の後ろに、指定された配列を連結する
/// @param array 連結する配列
/// @return 連結された配列
Array.concat = function(array) {
  var tmp = [];
  tmp.push(this*, array*);
  return tmp;
};

/// 配列を添え字が同じ各要素ごとにマージする
/// 配列の長さが異なる場合、短い方の長さになる
/// @param array マージする配列
/// @param resultSelector 2つの要素を受け取って、マージした要素を返す関数
/// @return resultSelectorの戻り値が入った配列
Array.zip = function(array, resultSelector) {
  var tmp = [];
  var count = this.count > array.count ? array.count : this.count;
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = resultSelector(this[i], array[i]);
  }
  return tmp;
};

/// 2つの配列の和集合を生成する
/// @param array 対象となる配列
/// @return 指定された配列との和集合の配列
Array.union = function(array) {
  var tmp = [];
  var values = %[];
  for (var i = 0; i < this.count; ++i) {
    var value = this[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  for (var i = 0; i < array.count; ++i) {
    var value = array[i];
    if (values[value]) continue;
    tmp.add(value);
    values[value] = true;
  }
  return tmp;
};

/// 2つの配列から積集合を生成する
/// @param array 対象となる配列
/// @return 指定された配列との積集合の配列
Array.intersect = function(array) {
  var values = %[];
  for (var i = this.count-1; i >= 0; --i) {
    values[this[i]] = true;
  }
  var tmp = [];
  for (var i = 0; i < array.count; ++i) {
    if (!values[array[i]]) continue;
    tmp.add(array[i]);
    values[array[i]] = false;
  }
  return tmp;
};

/// 現在の配列から、指定された配列に含まれる要素と同一の要素を除いた配列を得る(差集合)
/// @param array 対象となる配列
/// @return 指定された配列の要素を取り除いた配列
Array.except = function(array) {
  var values = %[];
  for (var i = array.count-1; i >= 0; --i) {
    values[array[i]] = true;
  }
  var tmp = [];
  for (var i = 0; i < this.count; ++i) {
    if (values[this[i]]) continue;
    tmp.add(this[i]);
    values[this[i]] = true;
  }
  return tmp;
};

/// 比較関数を使用して2つの配列が同一か返す
/// @param array 比較対象となる配列
/// @param comparer 要素を比較する関数
/// @return comparerが全ての呼び出しに対してtrueを返したらtrue
Array.sequenceEqual = function(array, comparer) {
  if (this.count != array.count) return false;
  for (var i = this.count-1; i >= 0; --i) {
    if (!comparer(this[i], array[i])) return false;
  }
  return true;
};

/// 最初に条件を満たす要素を得る
/// @param predicate 条件を判定する関数
/// @param value 条件を満たす要素が存在しなかったときに返す値
/// @return 最初から見ていって最初にpredicateを満たす要素
Array.first = function(predicate, value=void) {
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) return this[i];
  }
  return value;
};

/// 最後に条件を満たす要素を得る
/// @param predicate 条件を判定する関数
/// @param value 条件を満たす要素が存在しなかったときに返す値
/// @return 最後から見ていって最初にpredicateを満たす要素
Array.last = function(predicate, value=void) {
  for (var i = this.count-1; i >= 0; --i) {
    if (predicate(this[i], i)) return this[i];
  }
  return value;
};

/// 連続した値が要素となった配列を生成
/// @param start 開始する値
/// @param count 生成する数
/// @return start + i(0...count)の配列
Array.range = function(start, count) {
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = start + i;
  }
  return tmp;
};

/// 同じ値が連続した配列を生成
/// @param element 要素
/// @param count 要素の数
/// @return elementがcount個だけ入った配列
Array.repeat = function(element, count) {
  var tmp = [];
  for (var i = count-1; i >= 0; --i) {
    tmp[i] = element;
  }
  return tmp;
};

/// 空の配列を生成
/// @return 空の配列
Array.empty = function() {
  return [];
};

/// 条件を満たす要素が存在するか調べる
/// @param predicate 条件を判定する関数
/// @return 条件を満たす要素が1つでも存在すればtrue
Array.any = function(predicate) {
  for (var i = 0; i < this.count; ++i) {
    if (predicate(this[i], i)) return true;
  }
  return false;
};

/// 全ての要素が条件を満たすか調べる
/// @param predicate 条件を判定する関数
/// @return 全ての要素が条件を満たせばtrue
Array.all = function(predicate) {
  for (var i = 0; i < this.count; ++i) {
    if (!predicate(this[i], i)) return false;
  }
  return true;
};

/// 配列に特定の要素が存在するか調べる
/// @param value 検索する要素
/// @param comparer 2つの要素を受け取って、等しいか返す関数。省略時は === で比較
/// @return 指定された要素が1つでも存在すればtrue
Array.contains = function(value, comparer) {
  if (comparer === void) {
    comparer = function(first, secound) { return first === second; };
  }
  for (var i = 0; i < this.count; ++i) {
    if (comparer(value, this[i])) return true;
  }
  return false;
};

/// 配列の全要素を数値に変換し、その和を得る
/// @return 配列の全要素の和
Array.sum = function() {
  var v = 0;
  for (var i = this.count-1; i >= 0; --i) {
    v += +this[i];
  }
  return v;
};

/// 配列の全要素から最小値を求める
/// @return 配列の要素の中で最も小さい値
Array.min = function() {
  var v = this[-1];
  for (var i = this.count-2; i >= 0; --i) {
    if (v > this[i]) v = this[i];
  }
  return v;
};

/// 配列の全要素から最大値を求める
/// @return 配列の要素の中で最も大きい値
Array.max = function() {
  var v = this[-1];
  for (var i = this.count-2; i >= 0; --i) {
    if (v < this[i]) v = this[i];
  }
  return v;
};

/// 配列の全要素から平均値を求める
/// @return 配列の全要素の平均値
Array.average = function() {
  return this.sum() / this.count;
};

/// 配列の全要素を集計する
/// @param func 要素を集計する関数
/// @return 指定された関数で集計された結果
Array.aggregate = function(func) {
  var tmp = void;
  for (var i = 0; i < this.count; ++i) {
    tmp = func(tmp, this[i]);
  }
  return tmp;
};

続きを閉じる▲

タグ : 吉里吉里 TJS

カテゴリ : TJS

「吉里吉里」と「かざぐるマウス」の相性問題

同人ノベルゲームやエロゲなどで広く使われている吉里吉里エンジンですが、かざぐるマウスと同時に使用すると問題があるようです。

マウスホイールがきかなくなったり、キーボードがきかなくなったりします。
ctrlキー、エンターキーやマウスホイールなどで読み進められないので、ノベルゲームとしては致命的にプレーしずらくなります。
ホイールでバックログを見ることすらできない・・・・・・。

とりあえずの回避方法ですが、かざぐるマウスの「マウスカーソルの位置に入力フォーカスをあわせる」のチェックを外してください。
オフにしてもそこまで困る機能ではない・・・・・・と思います。

kazaguru_krkr.jpg

タグ : 吉里吉里

カテゴリ : 吉里吉里

吉里吉里安定版と開発版の違いメモ

現在の安定版(2.32rev2)と最新開発版(2.31.2012.831, revision:5057)の違いメモ
バグが修正されたり実行速度が速くなったり機能が増えたりしているので開発版を使うべき
開発版のexeは下記URLにあります
https://sv.kikyou.info/svn/kirikiri2/trunk/kirikiri2/bin/win32/



・Scripts.execStorage(),Scripts.evalStorage(), Scripts.exec(), Scripts.eval()の引数contextを追加
Scripts.execStorage(storage, mode='', context=global)
Scripts.evalStorage(storage, mode='', context=global)
Scripts.exec(script, name='', linesof=0, context=global)
Scripts.eval(script, name='', linesof=0, context=global)
storage:評価または実行するファイル名
mode:ファイル読み込みモードを指定できます。"o"を前置した10進数値でバイト単位の読み込み開始位置を指定できます
context:実行コンテキストを指定できます
script:評価または実行するtjsスクリプト
name:エラーメッセージ中で使用するファイル名を指定できます
linesof:エラーメッセージ中で使用する行番号を指定できます
mode、name、linesofは安定版でも使えますがリファレンスでは省略されています

・System.terminate(), System.exit()の引数codeを追加
System.terminate(code=0)
System.exit(code=0)
code:終了コードを指定します
吉里吉里でツール作るときに便利かも

・Storages.clearArchiveCache()を追加
アーカイブのキャッシュをクリアするらしい?

・System.graphicCachLimit=gcsAutoの時のキャッシュ量計算式変更
メモリ512MB以上のときに64MB固定だったのを、物理メモリの1/10に変更
今はメモリたくさん載っているのが当たり前なのでグラフィックキャッシュ量が大幅に変わります
使用する画像が小さければ大して影響ないかもしれません

・コマンドラインオプションとして"-dsvolfactor"を追加
サウンドの音量を設定したときに、実際の聞こえる音の大きさが変わっている可能性があります
今までより直感的な音量になっているらしいです
現在の安定版と同じ動作にしたい場合は-dsvolfactor='5000'を指定

・マルチスレッド動作の軽量化

・プライマリレイヤ外でもウィンドウのマウスイベントが発生するように変更

・KAGParser.mp追加、KAGParserでのtjs式評価時のコンテキストをglobalからKAGParserオブジェクト自身に変更
説明面倒なので略

・Layer.onMouseDownの直前にLayer.onMouseMoveが必ず呼ばれるように変更

・バグ修正
>>=と>>>=が逆だったらしい
KAGParser.restoreでエラーが出る件
マルチスレット描画時のバグ
その他

・その他プラグインなど
公式レポジトリにあるプラグインは開発版基準で作られているので安定版では動かない物も
プラグインもどんどん機能増えてます

続きを閉じる▲

タグ : 吉里吉里

カテゴリ : TJS

KAGEZ説明会のお知らせのお知らせ

去年から出す出すと言いつつ何ら音沙汰のない吉里吉里/KAGEZ解説本ですが、2012年中には出そうにもありません!
やばいなーと思いつつ文章を書く時間もありませんので適当に喋ってお茶を濁します。
詳細は以下。

オフでやると準備など面倒なのでオンラインでやります。
細かいことは決めてませんが、おそらくustreamで画面流しつつKAGEZの使い方や技術的な事をお話しします。
日時も未定ですが11~12月の土日のどこかの昼間になると思います。
録画も出来るはずなので合わなければそっちで見ればいいです。

対象は吉里吉里/KAGがそこそこ使える知識のある方。
そこそこ、というのは[backlay]と[trans]を駆使してトランジションできたり、マクロで%とmpを使い分けられたりすれば大丈夫だと思います。

日時など決まりましたらこのブログでまた告知します。
需要調査も兼ねているので、聞いてやろうという方は右下の拍手ボタン押すかコメントで何か言ってください。
よろしくお願いします。

続きを閉じる▲

カテゴリ : 告知

KAGParserExb.dll更新。属性名マクロ

KAGParserExb.dllを更新しました。
新しく属性名マクロが追加されています。

属性名マクロでは属性名の別名が登録できます。
例えば以下のようになります。
; "t"を"time"の別名として定義
@amacro name=t target=time
; @wait time=1000と同じ
@wait t=1000
よく使う属性が簡単に書けるようになったりします。
上手く使えば便利かもしれません。

続きを閉じる▲

タグ : 吉里吉里

カテゴリ : 雑記

吉里吉里イベント発生順メモ

「onKeyDownとonKeyPress」や「onMouseDownとonClick」など似たような関数たくさんあるけど、どんな順番で呼ばれるの?というメモ。
前提:イベントシステムについて

まずは結果見てわかりそうなところ
・ウィンドウのactionは、ウィンドウ、レイヤの関数が呼ばれた直後に呼ばれる
ただしレイヤのonHitTestではactionは呼ばれない

・レイヤよりも先にウィンドウのアクションが呼ばれる
Window.onMouseWheelの後にLayer.onMouseWheelなど

・onHitTestは結構呼ばれまくる。
実際のイベントと1対1では対応しない
レイヤの上にマウス置いてるだけでも定期的に呼ばれます
Layer.enabledがfalseだろうが呼ばれます

・なんだか複雑でめんどくさい
呼び出し順に依存するロジックにはしない方が良さそう


以下実際に試した結果。
Window.actionは全て直前のイベントについての呼び出しです。

■レイヤにフォーカスがあるときにマウスホイールを回す
Window.onMouseWheel
Window.action
Layer.onMouseWheel
Window.action

■レイヤにフォーカスがあるときにキーを押す
Window.onKeyDown
Window.action
Layer.onKeyDown
Window.action
Window.onKeyPress
Window.action
Layer.onKeyPress
Window.action

■レイヤにフォーカスがあるときにキーを離す
Window.onKeyUp
Window.action
Layer.onKeyUp
Window.action

■レイヤ上でマウス左ボタンを押す
Window.onMouseDown
Window.action
Layer.onHitTest
Layer.onHitTest
Layer.onMouseDown
Window.action
Window.onMouseMove
Window.action
Window.onClick
Window.action
Layer.onHitTest
Layer.onClick
Window.action

■マウス左ボタンを離す
WIndow.onMouseUp
Window.action
Layer.onMouseUp
Window.action

■レイヤ上でマウスを動かす
Window.onMouseMove
Window.action
Layer.onHitTest
Layer.onMouseMove
Window.action

■レイヤAからレイヤBにマウス移動
Window.onMouseMove
Window.action
LayerB.onHitTest
LayerA.onMouseLeave
Window.action
LayerB.onHitTest
LayerB.onMouseEnter
Window.action
LayerB.onHitTest
LayerB.onMouseMove
Window.action
Window.onMouseMove
Window.action

■レイヤAにフォーカスがあるときにタブキーを押す(レイヤBへフォーカス移動)
Window.onKeyDown
Window.action
LayerA.onSearchNextFocusable
Window.action
LayerB.onBeforeFocus
Window.action
LayerA.onBlur
Window.action
LayerB.onFocus
Window.action
Window.onKeyPress
Window.action
LayerB.onKeyPress
Window.action

■レイヤ上でダブルクリック
Window.onMouseDown
Window.action
Layer.onHitTest
Layer.onHitTest
Layer.onMouseDown
Window.action
Window.onMouseMove
Window.action
Window.onClick
Window.action
Layer.onHitTest
Layer.onClick
Window.action
Window.onMouseUp
Window.action
Layer.onMouseUp
Window.action
Layer.onHitTest
Window.onMouseMove
Window.action
Layer.onHitTest
Window.onDoubleClick
Window.action
Layer.onHitTest
Layer.onDoubleClick
Window.action
Window.onMouseDown
Window.action
Layer.onHitTest
Layer.onHitTest
Layer.onMouseDown
Window.action
Window.onMouseMove
Window.action
Window.onMouseUp
Window.action
Layer.onMouseUp
Window.action


おまけで試すときに使ったコード。ScriptsEx便利
何かイベント起きるたびにコンソールに記録されていきます。
// プラグイン読み込み
Plugins.link("ScriptsEx.dll");

// ウィンドウとレイヤを生成
var win = new Window();
win.visible = true;
var parentLayer = new Layer(win, null);
parentLayer.setPos(006464);
parentLayer.fillRect(0064640xFF0000FF);
parentLayer.visible = true;
var childLayer = new Layer(win, parentLayer);
childLayer.setPos(003232);
childLayer.fillRect(0032320xFF000000);
childLayer.visible = true;


/**
 * イベント関連の関数をメッセージ出力するように上書きする
 * @param obj 上書きするオブジェクト
 * @param msg 出力するメッセージ
 */

function eventOverride(obj, msg)
{
  var keys= Scripts.getObjectKeys(obj);
  for (var i = 0; i < keys.count; ++i) {
    var key = keys[i];
    if (key.substr(0,2) === "on" && obj[key] instanceof "Function") {
      // 名前が"on"で始まる関数を上書き
      obj[key] = function(*) {
        global.Debug.message(msg, funcName, *); // メッセージと関数名、引数を出力
        orgFunc(*); // 元の関数を呼ぶ
      } incontextof %[ msg:msg, funcName:key, orgFunc:obj[key] ];
    }
  }
}
eventOverride(win, "Window:");
eventOverride(parentLayer, "ParentLayer:");
eventOverride(childLayer, "ChildLayer:");
// ウィンドウのactionもメッセージ出力するように上書き
win.actionTargetNames = %[ win => "Window", parentLayer => "ParentLayer", childLayer => "ChildLayer" ];
win.action = function(ev) {
  var target = ev.target;
  var type = ev.type;
  delete ev.target;
  delete ev.type;
  var args = [];
  args.assign(ev);
  global.Debug.message("Window:""Action", actionTargetNames[target], type, args*);
incontextof win;

続きを閉じる▲

タグ : 吉里吉里 TJS

カテゴリ : 吉里吉里

KAGParserExb.dll更新 ver. 1.01

KAGParser拡張プラグイン KAGParserExb.dllを更新しました。

・開発版の吉里吉里でしか正常に動かなかったので、安定版の吉里吉里(2.32 rev.2)でも動作するdllを追加しました。
開発版を使うのがおすすめですが、どうしても安定版を使いたい人は使ってください。
最新開発版の吉里吉里は以下のURLから入手できます。
https://sv.kikyou.info/svn/kirikiri2/trunk/kirikiri2/bin/win32/

・パラメータマクロ使用時の注意が追加されています。
詳細は同梱の「使い方.txt」に書かれていますが、MainWindow.tjsを一部書き換える必要があります。

続きを閉じる▲

カテゴリ : 雑記

空行にラベルを入れるだけマシーン

スクリプトを読み込んで、空行ごとに連番でラベルを入れるだけのツール。
非常に単純な作りで公開するのもためらわれるレベルですが何かの参考になれば。
少しtjs使えればこのくらいあっという間に作れるようになります。
http://www.biscrat.com/krkr/files/insertLabel.zip

タグ : 吉里吉里

カテゴリ : プラグイン配布

吉里吉里で256x256のアイコンを設定するメモ

吉里吉里で大きいサイズのアイコンを使ってみます。

■アイコンについて
吉里吉里デフォルトのアイコンはお魚ですが、ゲームごとにアイコンを変更できます。
そのアイコンですが、Windows XPでは48x48サイズまでですがWindows Vistaからは256x256サイズのアイコンも表示できます。

大きいサイズのアイコンも準備するとちょっと豪華に見えるので作ってみてもいいかもしれません。
large_icon_sample.jpg
(吉里吉里のお魚アイコンと256x256のアイコンを並べてみる)


実際にどんなサイズのアイコンを準備すればいいのか、以下のガイドラインの「Size requirements」の項目が参考になります。
http://msdn.microsoft.com/en-us/library/aa511280.aspx
英語で面倒ですがアプリケーションのアイコンサイズは「256x256, 64x64, 48x48, 32,32, 24x24, 16x16」となっています。
追加で「128x128, 96x96, 64x64, 40x40, 24x24, 22x22, 14x14, 10x10, 8x8」などもアリのようです。
さらに以下のURLを見ると、192x192, 128x128, 96x96, 72x72について実際に使われているゲームがあるようです。
http://green.ribbon.to/~erog/Note017.html


アイコンの色深度については前述のガイドラインで32-bit, 24-bit, 8-bit, 4-bitが言及されています。
余力があれば全て準備しておいたほうがいいのだと思います。


■アイコンファイルを作る
アイコンファイル(.ico)の作り方はここでは説明しません。
自分の場合は以下で配布されている『@icon変換』などで変換しています。
http://www.towofu.net/soft/
アイコンの作り方は検索すれば色々と出てきます。


■アイコンを設定してみる
吉里吉里ではアイコンを設定するのにkrkrconf.exeというツールが付属しています。
しかし使ってみると、サイズの大きいアイコンは設定できません。
icon_error.jpg
(大きいアイコンを設定しようとするとエラー)


ではどうするかですが、exeのアイコン変更ができる他のツールを使えばいいです。
ここではフリーの「Resource Hacker」を使ってみます。

以下からJapanese版をダウンロードします。
http://www.angusj.com/resourcehacker/

zip形式で圧縮されているので、解凍して「ResHacker.exe」を起動します。
メニューの「ファイル」>「開く」からアイコンを変更したいkrkr.exeを選びます。
開いたら「アクション」>「アイコンを置き換える」から作成したアイコンファイルを選び、置き換えます。
「ファイル」>「保存する」で保存すればOKです。
resource_hacker.jpg


あまり検証などしてませんが大丈夫だと思います。
何か問題などあれば教えてください。

続きを閉じる▲

タグ : 吉里吉里

カテゴリ : 吉里吉里

C82夏コミ情報

明後日からいよいよ夏コミです。
自分のサークル名義では参加しませんが何作かお手伝いしてます。

tensho_banner_l.jpg
「根無し草」さんで売り子やってます。(2日目西ね04a)
2日目土曜日はこのスペースにいるはずです。

新作『天照花嫁日記・弐』など色々と頒布予定。
製作の方にはタッチしてません。



aikano_banner.jpg
「とらいあんぐる!」さん、『アイドル彼女』。(3日目東ノ18a)
巨乳でアイドルな彼女とイチャイチャするR18ノベル。
リンク先に体験版もあるのでまずはそちらをチェック。

システム提供してます。
見た目オーソドックスなんですが動作が微妙に違ったり地味に大変だった……。
色々作ったので次回以降また楽になるはず。



「granat」さん、『すり替えられた果実の破片』
2日目西し25b「650の無味乾燥」さんのスペースで体験版を頒布予定。
幽明心理ADV、というらしい。
本職のライターだけあってテキスト上手いです。

システム提供してます。
分岐が多くてシステムも特殊なんですが体験板だと未実装でよくわからない。
製品版は冬コミ予定。



「ねこやなC」さん、『俺が記憶喪失の間…一体何が?』の第二章を頒布予定。(2日目西の08b)
第一章はリンク先から無料ダウンロードできるのでやってみるといいと思います。
記憶喪失な主人公という設定ですが1章はひと通りキャラ紹介してそのまま終わってしまいます。
まだ何も分からぬ。第二章はどうなるんでしょ。

システム提供してますが、内容はほぼ関わってないので知りません。
比較的ツールなど揃っていたバージョンなので概ね何とかなったようです。すごい。




「WTH」さん、『ENDLESS SUMMER TIME』。(1日目東ム08a)
ペルソナ4の二次創作で、女性向けR18ノベル。
リンク先に体験板もあるようです。

一部スクリプトのお手伝いをしてます。
まだ作業中。うぎゃー

続きを閉じる▲

タグ : コミケ

カテゴリ : 告知

18禁NTRノベル『鬼監督と俺の彼女』DL版公開

めくじら」さんより『鬼監督と俺の彼女~女優の卵が鬼監督と肉体関係を結んだ理由~』が発売になりました。
システム提供などをさせてもらっています。


サークル「めくじら」さんの寝取られシリーズ4作品目で、18禁寝取られノベルゲーム。
かわいい制服姿の美少女と出会い、色々あって彼氏彼女になってイチャイチャします。
ここでやめときゃいいのに……その彼女が他の男とベッドインです。
ぎゃあああああ


完成までの紆余曲折を経て、いつの間にやらテキストだけで1.27MBという大作に。
ラノベ換算で6冊分です。
スクリプトを入れたシナリオ量となると2MBに届かん、というところ。

絵も可愛らしくて素敵。
作品規模が大きくなっても値段は据え置き1500円と格安。
オススメできる作品です。
普通のエロゲにマンネリ感がある方は寝取られ初挑戦してみるのも一興。



システムは体験版から目に見えては変わってません。
細かいバグを大量に修正したり、メニューの設定項目が多すぎだったのをすっきりさせたりしました。
少し大きいところでは、ロード時にバックログを戻す処理が抜けていたので追加しました。
この作品のデバッグを通してKAGEZのバグをかなり減らせたと思います。

最近は特殊なシステムを要求してくるゲームばかりだったのでスタンダードな今作は作りやすかったです。
名前欄を使わない点以外はほぼ標準のシステムだと思います。


体験版には含まれないクリア後特典ですが、CG鑑賞と回想とおまけシナリオがあります。
ちょっとは新しいものを作ろうと、CG鑑賞で原寸1600x1200のCGを見れる機能が付きました。
拡縮ボタンを付ける+CGをドラッグ出来るようにする、程度ですが普通のCG鑑賞よりはいいはずです。

フルスクリーン時など画面が大きいときはCGが拡大されないようにしたかったのですが、そこまで間に合わず。
1600x1200だとウィンドウ解像度の800x600より大きいので一部しか見えません。
他の部分を見るにはドラッグして絵を動かす必要があります。
十分に解像度があれば高解像度のまま一度に全体を見れるようにしたいんですが。無念。


演出スクリプトはサークルの方にやって頂いたのですが、立ち絵、CGなど非常に良く動きます。
よくぞここまで。自分でもここまで動かさないかも。
スクリプトの知識はあまりなくても、開発ツールを駆使して手間をかければここまで出来るようです。

続きを閉じる▲

カテゴリ : 告知

第2回、同人ゲーム制作勉強会の感想

6月23日のたんすかいさん主催、同人ゲーム制作勉強会に参加してきました。
感想などメモ。

(1)同人ゲームサークルのリーダーの役割仕事 yositaさん
◆テキトーに内容メモ
・ゲームを完成させるには、コミュニケーションとタスク管理が大切!
□コミュニケーション
・コミュニケーション方法 = 対面、電話、Skype、チャット、メール、掲示板など
・メーリングリストと掲示板の併用がおすすめ
・メーリングリスト = ○早い ×すぐに埋もれてしまう
・掲示板 = ○長く続くもの ×ログインがめんどい
・運用のルールを決める
・反応を早くする
□タスク管理
・優先度と期限をつける
・やっぱりコミュニケーションが大事
・mixi、掲示板、aipo、OpenePne、サイボウズ、Redmine、Backlogなど
・Backlogがおすすめ
・バージョン管理システム(Subversion)を使おう

◆感想
コミュニケーション大事だよねーっていう。
自分は外注請ける側ですがメールだけなのは割としんどかったりします。
反応を早くするのも大事です。
どんどん指示や問い合わせなどが来ると、やらねばならぬ気がしてきます。
メール見たらすぐに返した方がいいです。後回しダメです。これは自戒すべきところ。

バージョン管理は使いましょう。
ほとんど自分だけで完結できて、完成したものを送るだけならいいんですが、頻繁にデータやりとりするのにメールのみはムリです。
何らかの譲れぬ信念があってどうしてもバージョン管理を使わないとしても、SugerSyncやDropBoxなどで同期するだけでも全然違います。

コミュニケーションツールで多少使ったと言えるのはサイボウズLiveくらいであんまり良く分からない。
サイボウズLiveはちょっと使いやすいとは言い難かった……。
Redmineは個人でちょっと触ってみましたがよく分からん。
結局はただのツールなので、人間側で運用ルールを決めるのが重要なのだと思います。
プロジェクト管理みたいなのはちゃんと勉強したいんだけどなかなか手が出せてない。

お金なんぼかかるのっていう話もありましたが、同人だとピンキリよねー。
無料でやる人から仕事としてやってる人まで。
仕事としてシステム外注やってる自分ですが、そのお値段は仕事募集ページに書いてます。
http://www.biscrat.com/works/index.html
自分としては破格の安さですが同人サークル側さんとしては高いのかしら。
報酬はそのゲームにかけられる時間に直結するので大切です。
システムの外注を同人で請けてる人をほとんど知らんのでどんなもんなのか分からん。



(2)ノベルゲームエンジンの乗換手順と、「AIRNovel」一押しの理由 ぢょほほんさん
◆テキトーに内容メモ
・『柊鰯』に感激した
・NScripterからAIRNovelに移行
移植自体は簡単だった
・AIRNoverのいいところ
シンプルで分かりやすい
Windows/Mac/iOS/Androidで動く
拡張できる。オープンソース

◆感想
AIRNovel結局ちゃんと触ってない。
以下、無責任にも知らないことを適当にいいます。信じないで自分で調べてください。

AdobeAIRを使っているので多分ActionScriptなのだけど、TJSと似通っているので吉里吉里使ってる人は実は使いやすいかも。
スマフォとかで動かす分には何となく重いイメージが。
とりあえず現在のPCノベルゲームをそのままスマフォで動かそうとするのは無理があると思う。

フレームワーク部分のライセンスがMPLなのが嫌な感じ。
そこからいじった場合は必ずオープンソースにする必要があります。
自分はオープンソースにする方ですが、出す出さないを選べるのは重要よね。出せない部分は当然あります。
吉里吉里でいうKAG相当部分はフレームワークに含まれないらしいのと動的リンクにすればオープンにしなくていいらしいので大体大丈夫なのかな。
公式ページが見た目綺麗なんだけどよくわからん。

モバイル対応はこれから必要なのだけど開発環境揃えるのが大変でなかなか手出せてない。
あちこちで話聞くに、色々不満ありつつも現状ArtemisEngineが一番マシという感触。
個人的にはエンジンから作ってみたい。


(3)KAGEZの始め方 sakano
自分の講演。KAGEZの話をしてきました。
準備時間が取れず、半分くらいアドリブでかなり残念な出来。
当日配った資料は以下のURLからダウンロードできます。
http://www.biscrat.com/krkr/files/tansukai2_handout.pdf

KAGEZ自体が自分の目の届かない所で使ってもらうには早すぎる段階で厳しいものがあります。


(4)シナリオの書き方 yositaさん
◆テキトーに内容メモ
・自宅では気が散る → 外に出て作業(ファミレス、マック
・ポメラがおすすめ。シナリオ書く以外の余計なことができない
・書き上げるコツ
短くても、ありきたりでもいいのでとにかく書く
モチベーションを上げる。立ち絵やCG、曲が出来た、など
・推敲は他人にしてもらう。数日寝かしてから読む。印刷する


◆感想
ちょっと力尽きてた。あんまり内容覚えてない。
シナリオは超重要です。シナリオだけあれば何かしら完成します。
立ち絵もBGMもフリー素材がありますがシナリオ素材はまあ無いので頑張って書くしかない。
色々とハウツー本を読んだりしますが実際にシナリオ書いたことは無いのでなんとも言えない。


(5)懇親会
勉強会終わってからは酒飲んでわいわいする会。
こちらのほうが勉強になったりモチベーションもらったりして大切なのですが省略。

続きを閉じる▲

カテゴリ : 感想文

KAGEXを使わない人へ、KAGEXの使い方

使ってみるととても便利なKAGEXですが、問題が無いわけでもありません。
説明が少ないだったりバグが多いだったり、敢えてKAGを使うという方もいると思います。

ただし直接使うのはKAGだとしても、まだKAGEXにも利用価値があります。

KAGを使うコツはマクロを上手に作ることです。
しかし、これがどうにも難しいです。
どんなマクロを作れば便利になるのか、実際に作ってみて経験値がたまらないとわかりません。

マクロの作り方はリファレンスに載っています。
でも、実際にどう使えばいいのかは自分で考えなければなりません。

ここでKAGEXを見てみるとヒントが得られます。
ノベルゲームを作るのに役立つ機能がたくさん詰め込まれているので、それを真似してみるとどんどん使いやすくなってきます。


ということでKAGEXの文法を参考に、少しだけKAGのマクロを組んでみました。
http://www.biscrat.com/krkr/files/kag_macro_sample.zip

立ち絵、背景、BGM、効果音、ボイスなどのマクロがついています。
KAGのタグを直接使うよりは圧倒的に便利なはずです。
出来る限りTJSの知識は使っていないので、KAGしか分からない方でも参考になるかと思います。
もしTJSが使えればもっと色々と出来るようになってきます。

同梱のKAGParserExb.dllはこちらからダウンロードできます。
TJSを使わずとも簡単に省略表記が実現できたりして便利です。

続きを閉じる▲

タグ : 吉里吉里 KAG

カテゴリ : KAG

KAGParser拡張プラグイン KAGParserExb.dll

ダウンロード
吉里吉里のKAGParserクラスを高機能なものに置き換えます。
複数行タグやパラメータマクロなど、便利な機能が使えるようになります。

吉里吉里公式レポジトリで配布されているKAGParserEx.dllの一部を変更したプラグインです。
元のKAGParserEx.dllのソースは以下で配布されてます。
https://sv.kikyou.info/svn/kirikiri2/trunk/kirikiri2/src/plugins/win32/KAGParserEx/

元のKAGParserEx.dllはかなり便利なのですが、コンパイル済みのdllが配布されていないせいかほとんど使われてません。
勿体無いのでコンパイルして配布。
ついでに先頭に;を書くという残念な仕様は改善したりしています。
また、属性名マクロの機能を追加しています。

詳しい説明は同梱のドキュメントを参照してください。


過去のバージョンと変更履歴はgithubから参照できます。
https://github.com/sakano/KAGParserExb

続きを閉じる▲

タグ : 吉里吉里 プラグイン

カテゴリ : プラグイン配布

最新記事
カテゴリ

openclose

記事一覧
Twitter
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。