気ままなタンス*プログラミングなどのノートブック

プログラミングやRPGツクール、DTM等について、学んだことや備忘録をアウトプットとして残し、情報を必要としている誰かにとって「かゆいところに手が届く」ブログとなることを願いながら記事を書いています。

【RPGツクールMV】マップ上に表示するウィンドウに関するコードリーディングのメモ

こんにちは!

RPGツクールMVで、マップが切り替わった時にそのマップの名前を表示するウィンドウがありますよね(下記イメージの赤枠)。 f:id:rinne_grid2_1:20180509213711p:plain

このウィンドウはマップに入った時にフェードイン・アウトしながら表示されます。 RPGツクールMVでは、マップの「表示名」に入れるだけで、このマップ名称を表示するウィンドウが有効になるんです!*1

フェードイン・アウトしながらウィンドウを表示する機能は、マップ以外にも、ミニゲーム等のいろんな部分に使えそうです。

そこで、どのようなソースコードでこの仕組みを実現しているのかを調べてみることにしました。

参考とする関数オブジェクト

マップ上で呼び出されることと、マップ名を表示することから、 下記のファイル・関数オブジェクトに当たりをつけて調べました。

  • rpg_scenes.js - Scene_Map
  • rpg_windows.js - Window_MapName

ざっくりとした流れ

  • マップオブジェクトの作成
  • マップ準備完了
  • マップロードイベント発火

マップに必要なウィンドウの準備(Scene_Map.prototype.createDisplayObjects)

まず、マップ用のシーンで定義されたcreateDisplayObjectsで、 ウィンドウレイヤやスプライトセット、さらに今回の対象であるMapNameWindowを作成するメソッドを呼び出します

Scene_Map.prototype.createDisplayObjects = function() {
    this.createSpriteset();
    this.createMapNameWindow();
    this.createWindowLayer();
    this.createAllWindows();
};

マップ表示名のウィンドウ作成(Scene_Map.prototype.createMapNameWindow)

  • createMapNameWindowを呼び出すことによって、this._mapNameWindowにオブジェクトが作成されます
  • また、作成したオブジェクトをシーンの子オブジェクトとして追加します
Scene_Map.prototype.createMapNameWindow = function() {
    this._mapNameWindow = new Window_MapName();
    this.addChild(this._mapNameWindow);
};

マップ名を表示するウィンドウの初期化(Window_MapName.prototype.initialize)

上記createMapNameWindowの中で、Window_MapName()がnewされた時点でinitializeが呼び出されます

Window_MapName.prototype.initialize = function() {
    var width = this.windowWidth();
    var height = this.windowHeight();
    Window_Base.prototype.initialize.call(this, 0, 0, width, height);
    this.opacity = 0;
    this.contentsOpacity = 0;
    this._showCount = 0;
    this.refresh();
};

initializeでは、下記のような初期化を行っているようです。

  • width, heightの設定
  • ウィンドウ自体の透明度の設定
  • コンテンツの透明度の設定
  • フェードインにかける時間の指定
  • ウィンドウ内容のリフレッシュ

マップ名を表示するウィンドウ内容の表示(Window_MapName.prototype.refresh)

Window_MapName.prototype.refresh = function() {
    this.contents.clear();
    if ($gameMap.displayName()) {
        var width = this.contentsWidth();
        this.drawBackground(0, 0, width, this.lineHeight());
        this.drawText($gameMap.displayName(), 0, 0, width, 'center');
    }
};

次に、リフレッシュが呼び出され、 一度コンテンツ(描画領域等)をクリアするようです。

その後、もし表示名$gameMap.displayNameが指定されている場合は、背景やマップ名の表示をしています。

ウィンドウの背景を設定(Window_MapName.prototype.drawBackground)

Window_MapName.prototype.drawBackground = function(x, y, width, height) {
    var color1 = this.dimColor1();
    var color2 = this.dimColor2();
    this.contents.gradientFillRect(x, y, width / 2, height, color2, color1);
    this.contents.gradientFillRect(x + width / 2, y, width / 2, height, color1, color2);
};

マップ名表示の領域のグラデーションは、gradientFillRectで表現されているようです。

マップ名表示ウィンドウをオープン(Scene_Map.prototype.start)

さらに処理を追うと、 マップのシーンが開始する際に、this._mapNameWindow.open()でマップ名表示ウィンドウを開く処理が呼び出されることがわかります。

Scene_Map.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    SceneManager.clearStack();
    if (this._transfer) {
        this.fadeInForTransfer();
        this._mapNameWindow.open();
        $gameMap.autoplay();
    } else if (this.needsFadeIn()) {
        this.startFadeIn(this.fadeSpeed(), false);
    }
    this.menuCalling = false;
};

ウィンドウオープンをフェードインで表現するための準備(Window_MapName.prototype.open)

Window_MapName.prototype.open = function() {
    this.refresh();
    this._showCount = 150;
};

リフレッシュ処理を呼び出し、showCountに150という値をセットしています。 この値がフェードイン・アウトを行う際に増減されるようです。

共通のupdateイベントによる、Windowのアップデート

Window_MapName.prototype.update = function() {
    Window_Base.prototype.update.call(this);
    if (this._showCount > 0 && $gameMap.isNameDisplayEnabled()) {
        this.updateFadeIn();
        this._showCount--;
    } else {
        this.updateFadeOut();
    }
};
Window_MapName.prototype.updateFadeIn = function() {
    this.contentsOpacity += 16;
};

Window_MapName.prototype.updateFadeOut = function() {
    this.contentsOpacity -= 16;
};
  • contentOpacityというのは、名前から察するに透明度のことのようです
    • updateFadeIn()では、contentsOpacity の値を16増やしています
    • updateFadeOutでは、contentsOpacity の値を16減らしています
  • updateは、1フレームごとに呼び出されるので、フレーム毎に不透明度を16増減しているようです。
  • showCountが0より大きい場合はフェードイン、それ以外の場合はフェードアウトを呼び出します。
    • 60フレーム = 1秒 がツクールMVの基本なので、150フレーム=2.5秒でフェードイン・アウトを実行しているようです。
    • ただし、不透明度255が最大であると考えると、150フレーム丁度で表示されるわけではなく、だいたい16フレーム(255/16)くらいで完全に表示され、残り134フレーム+αを表示した後、16フレームで完全に非表示となってしまうことが考えられます。

まとめ

コードリーディングを行うことによって、下記のようなことがわかりました。

  • showCount = フレーム数(1/60秒)で表示時間を制御している
  • フェードイン・フェードアウトは不透明度を増減することによって実現している

*1:RPGツクールVXから実装された素敵な機能です

【雑記】[自己分析]なにがやりたいか聞かれて言葉に詰まった話

なにがやりたいか

懇親会で上司や先輩と飲んでいた時、質問されました。

「よく家でコーディングやってるみたいだけど、やりたいことは何?」

その質問を受けて、少々困惑してしまいました。 なぜならば、自分自身では何がやりたいのか、明確にできているつもりだったのですが、 客観的に見ると、明確に意識できていないことに気づいてしまったのです。

根底にある考え

基本的にはプラグインの開発やフリーゲームの作成を行い、 「人の役に立つことをしたい、人を楽しんでもらいたい」という想いの元に動いています。

仕事でも他の人から「これ作って」「これやって」と言われたら、 その人のことを優先的に考えて行動しています。*1

(どうやったら使いやすいか常に考えたり、はやく使わせてあげたいと常々考えている気がします)

しかし、人の役に立つことをしたいというのは、 先輩からしたら、曖昧な考えであったようでした。 今振り返ると確かにその指摘も妥当だと感じました。

指摘を受けて振り返る

なんとなくではあったのですが、 自分から主体的にモノを考え、何かに取り組むことができておらず、悩み続けていました。

何かを作ろうとしても、 「既存のサービスがあるから作っても無駄」「1から作るにも、数式が入ってくると、膨大な時間がかかりそう」 こんな理由で反射的・無意識的に断念していることがわかりました。

新しいプログラミング言語を学ぶにしても、そこからどんなものを生み出すか見当がつかない状況といえば良いのでしょうか。 (仕事で新言語での開発等に携わっていれば、ノウハウ蓄積の観点で違ったものになったのかもしれません)

本当に先輩が聞きたかったことは何か

会話にズレがあったようにも感じます。

先輩としては、BtoBか、BtoCかという、金銭の絡む話の中で「やりたいこと」が聞きたかった様子でした。

しかし、現在の自分としては報酬等、かかわりのない部分で動いています(が、やりたいことは明確に言えません)*2

今後自分はなにをしていくべきか

未完成の状態にあるものを挙げてみることにします

  • ツクールMVゲーム
  • ツクールVX aceゲーム
  • プラグイン(RecollectionMode)の機能追加

最近はツクールMVも影響で、JavaScriptを学ぶことが多くなってきました。 (ツクールMVJavaScript、Node.jsやES2015)

クライアント側で完結するものだけではなくWebアプリも作りたいと考えています(主にDjango。だけどネタがないのです・・・)

少し整理すると、「やりたいことは盛りだくさんな状況」であるが、やりたいことが多すぎて、結局何にも取り組めていない状況と言えそうです。

質問に即答できなかったことを後悔しつつ、自己分析を実施するきっかけとなったので、結果オーライですね。

*1:もちろん自分の仕事が忙しいときは少々ずれることはあります

*2:というよりも、今は言えないだけで作りたいものがでてきたら当然それが最優先になるので、一時的なものだとも思うのです

【RPGツクールMV】回想モードプラグイン用の補助ツール「RecoGene」を公開しました

RPGツクールMVの回想モード導入プラグイン用のツール「RecoGene」を作りました。

α版:RecoGene - RecollectionMode.jsジェネレータ

f:id:rinne_grid2_1:20160511211307j:plain

RecoGeneとは?

RPGツクールMVの回想モード導入プラグイン「RecollectionMode.js」の設定生成ツールです。 Web画面上でCG設定に関する情報を入力し、設定済みのプラグインをダウンロードできます。 さらに、既存のRecollectionMode.js(バージョン1.1.2以降)ファイルから、設定を読み込み、編集することも可能です

主な機能

  • 画面上でCG設定を入力し、設定済みプラグインを保存
  • CG設定のjsonを保存
  • 既存プラグイン(js)の設定を読み込み、設定を編集

注意事項

α版ということもあり、不具合が含まれている可能性があります。 必ずプラグインのバックアップを実施いただきますようお願いします。

使い方

1.「回想用のCG設定」タブを開き、CG設定を入力します。

f:id:rinne_grid2_1:20160511204209j:plain

2.(必要に応じて)「回想モードのウィンドウ設定」タブを開き、回想モードのウィンドウ関係の設定を行います

f:id:rinne_grid2_1:20160511205019j:plain

3.(必要に応じて)「回想モードのBGM設定」タブを開き、BGMに関する設定を行います。

f:id:rinne_grid2_1:20160511205212j:plain

4.(必要に応じて)「その他設定」タブを開き、セーブ共有や一時マップの設定を行います。

f:id:rinne_grid2_1:20160511205347j:plain

5.下記画像の赤枠「プラグイン保存」ボタンを押下します

f:id:rinne_grid2_1:20160511205347j:plain

6.以下のようなダイアログが出てくるので、赤枠「クリップボードに保存」ボタンを押下します

f:id:rinne_grid2_1:20160511205555j:plain

7.任意のファイルを作成し、クリップボードの内容を貼り付けます。

  • 文字コードはUTF-8を指定します。
  • 拡張子はjsです。

8.ツクールMVにプラグインを登録します。

9.ツクールMVを起動し、プラグイン内容が反映されていることを確認します

f:id:rinne_grid2_1:20160511210702j:plain

設定のアップロード

  • RecollectionMode.jsのバージョン1.1.2以降を利用している場合、設定を読み込むことができます

1.「設定をアップロード」ボタンを押下し、プラグインファイルを選択します

f:id:rinne_grid2_1:20160511210932j:plain

2.プラグイン内容が読み込まれたことを確認します

f:id:rinne_grid2_1:20160511211307j:plain

作成について

普段JavaScript・jsonを記述しない方にとっては、 直接プラグイン設定を変更することに対して少々抵抗感があるのではないかと考え、GUIツールを作成しました。

少しでもお役に立てれば幸いです。

不具合等ありましたら、こちらの記事のコメント欄に投稿をお願いします。

【RPGツクールMV】[中級者向け]セーブ・ロードで利用されているプログラムの調査記録

回想モードプラグインで、セーブデータ間のスイッチ情報を共有する機能の実装を検討していました。

その中で、セーブ・ロード時に利用するメソッドやゲームオブジェクトの変化といった詳細な情報が必要となり、調査したので記録に残します。

loadFromLocalFile(ローカル実行時のセーブファイル読み込み)

// rpg_managers.js 610行目
StorageManager.loadFromLocalFile = function(savefileId) {
    var data = null;
    var fs = require('fs');
    var filePath = this.localFilePath(savefileId);
    if (fs.existsSync(filePath)) {
        data = fs.readFileSync(filePath, { encoding: 'utf8' });
    }
    return LZString.decompressFromBase64(data);
};
  • this.localFilePathは、以下のような条件でパスを返す
    • savefileIdが0より小さい場合:"config.rpgsave"を返す
    • savefileIdが0と同じ場合:"global.rpgsave"を返す
    • savefileIdが1以上の場合:"file%1.rpgsave".format(savefileId)を返す

loadFromWebStorage(ブラウザ実行時のセーブファイル読み込み)

// rpg_managers.js 639行目
StorageManager.loadFromWebStorage = function(savefileId) {
    var key = this.webStorageKey(savefileId);
    var data = localStorage.getItem(key);
    return LZString.decompressFromBase64(data);
};
  • this.webStorageKeyは以下のような条件でキー名を返す
    • savefileIdが0より小さい場合:"RPG Config"
    • savefileIdが0と同じ場合:"RPG Global"
    • savefileIdが1以上の場合:"RPG File%1".format(savefileId);

saveToLocalFile(ローカル実行時のセーブファイル書き込み)

// rpg_managers.js 599行目
StorageManager.saveToLocalFile = function(savefileId, json) {
    var data = LZString.compressToBase64(json);
    var fs = require('fs');
    var dirPath = this.localFileDirectoryPath();
    var filePath = this.localFilePath(savefileId);
    if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath);
    }
    fs.writeFileSync(filePath, data);
};
  • 引数で受け取ったjsonをBase64にエンコード

saveToWebStorage(ブラウザ実行時のセーブファイル書き込み)

// rpg_managers.js 633行目
StorageManager.saveToWebStorage = function(savefileId, json) {
    var key = this.webStorageKey(savefileId);
    var data = LZString.compressToBase64(json);
    localStorage.setItem(key, data);
};

ローカルか、ブラウザ実行かの判定

非常にわかりやすいメソッド名ですね。

// rpg_managers.js 595行目
StorageManager.isLocalMode = function() {
    return Utils.isNwjs();
};

セーブ(ローカル、ブラウザ)の判定

// rpg_managers.js 563行目
StorageManager.save = function(savefileId, json) {
    if (this.isLocalMode()) {
        this.saveToLocalFile(savefileId, json);
    } else {
        this.saveToWebStorage(savefileId, json);
    }
};

セーブの呼び出し

json文字列の長さが200,000以上だった場合はワーニングを出力するようですね。ただ、その条件に一致する場合に変数操作は行っておらず、エラー等にはならないようです。

// rpg_managers.js 362行目
DataManager.saveGameWithoutRescue = function(savefileId) {
    var json = JsonEx.stringify(this.makeSaveContents());
    if (json.length >= 200000) {
        console.warn('Save data too big!');
    }
    StorageManager.save(savefileId, json);
    this._lastAccessedId = savefileId;
    var globalInfo = this.loadGlobalInfo() || [];
    globalInfo[savefileId] = this.makeSavefileInfo();
    this.saveGlobalInfo(globalInfo);
    return true;
};
  • this.makeSaveContentsで、ゲーム変数($gameSystem等)をオブジェクトに格納
// rpg_managers.js 422行目
DataManager.makeSaveContents = function() {
    // A save data does not contain $gameTemp, $gameMessage, and $gameTroop.
    var contents = {};
    contents.system       = $gameSystem;
    contents.screen       = $gameScreen;
    contents.timer        = $gameTimer;
    contents.switches     = $gameSwitches;
    contents.variables    = $gameVariables;
    contents.selfSwitches = $gameSelfSwitches;
    contents.actors       = $gameActors;
    contents.party        = $gameParty;
    contents.map          = $gameMap;
    contents.player       = $gamePlayer;
    return contents;
};
  • ゲーム変数を格納したオブジェクトをjsonに変換し、563行目のsaveメソッドに渡す
  • makeSavefileInfoメソッドで、セーブ画面に表示するキャラクターやプレイ時間等の情報をオブジェクトにセットする
// game_managers.js 411行目
DataManager.makeSavefileInfo = function() {
    var info = {};
    info.globalId   = this._globalId;
    info.title      = $dataSystem.gameTitle;
    info.characters = $gameParty.charactersForSavefile();
    info.faces      = $gameParty.facesForSavefile();
    info.playtime   = $gameSystem.playtimeText();
    info.timestamp  = Date.now();
    return info;
};

ロード(ローカル、ブラウザ)の判定

StorageManager.load = function(savefileId) {
    if (this.isLocalMode()) {
        return this.loadFromLocalFile(savefileId);
    } else {
        return this.loadFromWebStorage(savefileId);
    }
};

ロードの呼び出し

DataManager.loadGameWithoutRescue = function(savefileId) {
    var globalInfo = this.loadGlobalInfo();
    if (this.isThisGameFile(savefileId)) {
        var json = StorageManager.load(savefileId);
        this.createGameObjects();
        this.extractSaveContents(JsonEx.parse(json));
        this._lastAccessedId = savefileId;
        return true;
    } else {
        return false;
    }
};
  • StorageManager.loadで、セーブファイルから文字列(Base64からデコード済み)を取得
  • this.createGameObjectsで、Game_XXXXオブジェクトを生成
// game_managers.js 194行目
DataManager.createGameObjects = function() {
    $gameTemp          = new Game_Temp();
    $gameSystem        = new Game_System();
    $gameScreen        = new Game_Screen();
    $gameTimer         = new Game_Timer();
    $gameMessage       = new Game_Message();
    $gameSwitches      = new Game_Switches();
    $gameVariables     = new Game_Variables();
    $gameSelfSwitches  = new Game_SelfSwitches();
    $gameActors        = new Game_Actors();
    $gameParty         = new Game_Party();
    $gameTroop         = new Game_Troop();
    $gameMap           = new Game_Map();
    $gamePlayer        = new Game_Player();
};
  • セーブファイルの文字列を、jsonパースし、ゲーム変数($gameSystem等)に格納
// game_managers.js 438行目
DataManager.extractSaveContents = function(contents) {
    $gameSystem        = contents.system;
    $gameScreen        = contents.screen;
    $gameTimer         = contents.timer;
    $gameSwitches      = contents.switches;
    $gameVariables     = contents.variables;
    $gameSelfSwitches  = contents.selfSwitches;
    $gameActors        = contents.actors;
    $gameParty         = contents.party;
    $gameMap           = contents.map;
    $gamePlayer        = contents.player;
};

それでは、皆様も楽しいツクールライフを!

【Windows10】[オススメ]スタートメニューを使いやすくするための工夫

Windows10スタートメニューの不満点

Windows10を利用していて、使いづらいと思うことがあります。

それは、スタートメニューに、「マイコンピュータ」(各ドライブのルート)への移動方法がないことです。

僕はいつもスタートメニューから、「マイコンピュータ」を経由して、 各フォルダに移動していたので、そのルートが断ち切られてしまい少々不便に感じていました。

ちょっとした工夫

そこで一つ工夫をすることにしました。

単純ではありますが、 スタートメニューの上部に「マイコンピュータ」に対応する「PC」タイルを配置するというものです。

  • スタートメニューを開いたら、すぐに「PC」がある

こうすることで、従来までの「スタートメニュー」と同じような操作で各ドライブのルートに移動することができます。

f:id:rinne_grid2_1:20160418093353p:plain

やりかた

1. 左下の検索(WebとWindowsを検索)より、「PC」を検索

f:id:rinne_grid2_1:20160418093819p:plain

2. 「PC」が見つかったら右クリックをして「スタート画面にピン留めする」を選択

f:id:rinne_grid2_1:20160418093912p:plain

3. 一旦スタートメニューを閉じて、再度開き、「タイル」がある部分を下にスクロールし「PC」を見つける

f:id:rinne_grid2_1:20160418094024p:plain

4. 「PC」を上部にドラッグドロップし、グループに名前をつける

f:id:rinne_grid2_1:20160418094057p:plain

5. これで完成

f:id:rinne_grid2_1:20160418094116p:plain

僕のPCはこんな感じにしています。

PC、マイドキュメント、コントロールパネルを追加

f:id:rinne_grid2_1:20160418094920p:plain

その他

なお、「スタートメニューからじゃなくて、エクスプローラ開くときにクイックアクセスじゃなくてPCに移動したい」という場合は、 以下の記事の迷った点と備忘録を参照すると、やり方が書いてあります。

http://rinnegrid.hatenablog.com/entry/2015/08/17/071745rinnegrid.hatenablog.com

検索バーで入力すればすぐに出てくるのですが、 毎回入力するのはわりと手間ですし、やはり慣れている操作方法でできるのがベストだと思います。

【読書メモ】あなたの話はなぜ「通じない」のか-part2

こんにちは。前回に続いて、山田ズーニーさんの本「あなたの話はなぜ「通じない」のか」について 読書メモと感想を記述します。

あなたの話はなぜ「通じない」のか (ちくま文庫)

あなたの話はなぜ「通じない」のか (ちくま文庫)

前回の記事

www.rinsymbol.net

本記事の読書メモの定義

  • まず以下の基準で書籍内容を引用させていただきます。
    • 僕自身が読書していて、心に残った言葉
    • 書籍に線を引いた文章(電子書籍の場合マーカー引いた文章)
  • 記事の最後に個人的な感想を述べます(状況によっては、心に残った言葉の直後に感想が入ることもあります)

表記方法

  • 引用について

このようなボックスの中に記載されている文章は 引用を表しています

それでは早速、読書メモを記述いたします。

目次

読書メモ

コミュニケーション技術を磨いてどうなりたいのか

ある人は「交渉で常に自分が勝てるようになりたい」と言うかもしれない。
またある人は「人間関係で傷つかないようになりたい」と言うかもしれない。
あなたの目指すコミュニケーションのゴールは何だろう?

【Memo】
じぶんのゴール

交渉やお客様との打ち合わせで、
相手の話に真剣に耳を傾け、相手の抱える問題を解決して、信頼し合う関係を作りたい

著者(山田ズーニーさん)のコミュニケーションゴール

自分の想いで人と通じ合うこと

伝えなければ、伝わらない

わかってもらえないと思うとき、落ち込んだり、相手をうらんだりする前に
二つ自問してみよう。

  • わかってもらうために自分はどんなことをしてきたか?
  • 自分は人のことをわかろうとしているのか?
【Memo】
言わなきゃ、結局何もわからない。
自分の言葉で、伝えるように心がけている。

「黙っていい仕事をしていればわかってもらえる」と私は思っていた。
でも多くの人が忙しく、さまざまな仕事をしている会社では、
人の仕事をいちいち見てはいられない。
仕事の成果を見ても、どうやってつくったかプロセスまでわからない。
ましてや隣りの席に居る一の頭の中の、まだ形にしていないものを、
一体どうやってわかれというのだろう

感想

わかってもらうために自分はどんなことをしてきたか?

自分は人のことをわかろうとしているのか?

この問いは、僕にとって非常に厳しいものでした。 二つの問いを突き付けられ、何か、心に刺さるような感覚があったのです。

わかってもらうために、何をしてきたか?

確かに何冊か、コミュニケーションに関する本を読みました。 しかし、実際に人とのコミュニケーションで、実践していません。

人のことをわかろうとしているのか?

「興味がない話は理解できない」とそもそも聴く気を失っていることがあるように思います。

読書を進めて見えてきた願望

お客さんに「もう一度おっしゃっていただけませんか」と言えるようになりたいと考えました。 基本ですが、お客さんの分野の知識を理解していない状態で話を聞くと、わからないことだらけになってしまいます。 そして、説明のお願いを躊躇してしまうのです。

今後について

ポイントを絞って話をすること、相手の話を要約すること、 相手の言ったことを理解すること、自分の伝えたいことを明確にしておくこと

これらがうまくできず、怖くて逃げている節があるように思いました。

もっと相手を決めつけず、相手のことを考えることができれば、生きやすくなるのではないかと感じました。

【読書メモ】あなたの話はなぜ「通じない」のか-part1

こんにちは。今回は山田ズーニーさんの本「あなたの話はなぜ「通じない」のか」について 読書メモと感想を記述します。

あなたの話はなぜ「通じない」のか (ちくま文庫)

あなたの話はなぜ「通じない」のか (ちくま文庫)

本記事の読書メモの定義

  • まず以下の基準で書籍内容を引用させていただきます。
    • 僕自身が読書していて、心に残った言葉
    • 書籍に線を引いた文章(電子書籍の場合マーカー引いた文章)
  • 記事の最後に個人的な感想を述べます(状況によっては、心に残った言葉の直後に感想が入ることもあります)

表記方法

  • 引用について

このようなボックスの中に記載されている文章は 引用を表しています

それでは早速、読書メモを記述いたします。

目次

読書メモ

発信者によって印象が変わってしまう

同じことでも、あなたが言うのと別の人が言うのでは、 与える印象がまるで違う。人間もメッセージを伝えるメディア(=媒介)だとすれば あなたは相手からどんな風に見られているだろうか

話が通じるために実行すべきこと

日ごろから人との関わり合いの中で、 自分というメディアの信頼性を高めていく必要がある。

話が通じるためにおさえておきたい基礎

  • 自分のメディア力を上げる

あなたという人間への信頼、共感を高めながら相手に言いたいことを伝えるか、その技術をつかむ。 話が通じるとは"勝ち負けでなく、あなたと相手の間に橋を架けるようなものだ"

  • 相手にとっての意味を考える

相手とはどんな人か?
例えばあなたが「恋人と映画に行った」ことを話すとする。
もし相手が映画好きで感性が合う人なら、映画の情報として「役立つ知らせ」という意味がでてくる。
また相手が沈んでいて、あなたの話が笑えるものだったら「気が晴れる楽しい話」という意味がでてくる。
相手へのメリットが何もなかったとしたら、あなたの話は「単なる自慢」とうつるかもしれない。

人は自分に関係ない、意味のない話はなかなか聞こうとしないものだ。
まずこの厳しい現実をしっかり押さえよう

  • 自分が一番言いたいことをはっきりさせる

自分が一番言いたいことを、極力はっきりさせておき、 それを頭か結論にもってくるだけで、ずいぶん話は通じやすくなる。 「言いたいことはあるんだけど、自分でもはっきりしない」という状態で切り出すと 相手までモヤモヤさせてしまう

  • 意見の理由を説明する

自分に都合のいい理由ばかりでたたみかけてもだめだ。 あなたと、相手の真ん中に「理由」がある。理由を、自分側、相手側、あるいはもっと普遍的な 角度からと、多角的に引いてくる方法や、論理的な説得の筋道を組み立てていく技術もつかもう

  • 自分の根っこの想いにうそをつかない

その人の根っこにある想い・発言の動機、これを「根本思想」という。 「言葉はちょうど氷山の見えるところのようなもので、水面下には、その何倍もの大きな その人の生き方や価値観が横たわっている」
本書は「自分に想いにうそをつかない」ということを一歩も譲らず考えた。

感想

書籍で述べられていることに関して、読んだ直後は「当たり前じゃん」となっているものの、 実際の会話では意識できていないということが多いのではないでしょうか。

僕自身は、当然実践できていませんし、実践する前の段階で止まってしまうように思います。

「仕事での報告」に限り、事実を手短に話すことを意識してはいるものの、 自分が一番言いたいこと(キーセンテンスやキラーメッセージ)を常に意識できておらず、なんとなく話してしまうこともあります。

さらに一番やってはいけないこと・・・話をする際に、「前提は知っているだろう」ということで、 前提事項や理由を省くこともあります。

これらの基礎を元に、今まで「話が通じなかった」と感じた時の経験を思い出し 「自分はダメだ」で終わるのではなく、原因と対処方法を考えるべきだと強く感じました。

結局のところ、「通じない」痛みによって当時の「思い出」がマイナスイメージとなっていることから、 傷つくのが嫌で、どうにも重い腰が動かせないのではないのかなと思います。

どこかの本で読んだか忘れてしまったのですが、 "自分が伝える"ことが大事なのではなく、"相手に伝わる"ことが大事なんですよね。

part2はこちら

www.rinsymbol.net