volatile

めるくすとーりあ/C++/Win32API

DxLibで文字列の色を途中から変えられるようにする(改良)

以前投稿したDxLibで文字列の色を途中から変えられるようにするソースコード、少しお粗末だったので改良しました。
推理ゲームなど、重要な単語の色付けなどが必要な際に使ってみてください。

volatile.hatenablog.com

文字列の色を途中から変更する

使用するには今回配布するFontColor.hをインクルードし、DrawFormatStringToHandleColor関数を呼び出します。

void DrawFormatStringToHandleColor(int x, int y, unsigned int Color,
 int FontHandle,char *FormatString, ...)

引数はDXライブラリのDrawFormatStringToHandle関数と変わりません。

  • int x , y : 文字列を描画する起点座標
  • unsigned int Color : 描画する文字列の色のコード
  • int FontHandle : 描画に使用するフォントデータの識別番号(ハンドル)
  • char *FormatString : 描画したい書式付き文字列のアドレス
  • ... : 書式付き文字列に付随する引数

↓こんな感じで色付けしたい場合、
Lorem ipsum dolor sit amet

引数FormatStringは以下のような感じに指定することにします。

"Lorem [dd830c]ipsum [-]dolor [1464b3]sit [-]amet"

[xxxxxx](xxxxxxは16進数のカラーコード)以降の文字はカラーコードと同じ色になり、[-]で以降デフォルトの色になります。

使用例

f:id:volatile1:20190316124850p:plain

▲usage

// ...
const char *string = "あの[fc585a]イーハトーヴォ[-]の[49b21f]すきとおった風[-]、"
		"[eb8900]夏[-]でも[2ed2fd]底に冷たさをもつ青いそら[-]、\n"
		"[49b21f]うつくしい森[-]で飾られた[fc585a]モリーオ市[-]、"
		"[fc585a]郊外[-]の[fdbf2d]ぎらぎらひかる[49b21f]草の波[-]。\n"
		"[ff0000]Lorem ipsum dolor sit amet, [00ff00]consectetur adipiscing elit,\n"
		"[0000ff]sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.[-]\n"
		"%d + %d = [abcdef]%d";

		DrawFormatStringToHandleColor(0, 100, 0xffffff, FontHandle, string, 30, 40, 30 + 40);
// ...

改良点

  • 余計な変数(即値とか)を無くした
  • 関数のinline化
  • 分岐命令を書き直して高速化を図った
  • FormatStringをstd::string型にする際に使用するchar配列str_cの要素数を65536から4096へ

(私のPCで)以前のDrawFormatStringToHandleEx関数と比べて約10%の高速化を実現(デバッグだと約20%)
(std::regex使わなければより早くなるかも?std::stringも使わないのは辛くて面倒)

配布先

複製・改変・再配布・商用利用等、ご自由にどうぞ。著作権の表記等も求めません。
github.com



ではまた~

Win32API挫折しそうになりつつ頑張る#2

誰が見るのかなこんなの…

ウィンドウデスクトップアプリケーションのテンプレートソースコード

所謂Windowsでのデスクトップアプリケーション(GUI)を作る際にまず最初に描くことになるであろう基本的なソースコードです。
Visual StudioWindows Desktop Applicationを選ぶと最初からテンプレートが書かれているのですが、もっとシンプルなものがいい(メニューバー・アイコンいらない、リソースファイル勝手に作るな、#include "stdafx.h" とかやめろ、etc...)という方の為に一部修正・削除して100行未満に抑えたソースコード(WinMain.cpp)を載せます。
Empty Projectで何もない状態からこのWinMain.cppを貼って下さい。


gist0fee52fbc41c3ed70d912072b8da2509

以上!

DxLibで文字列の色を途中から変えられるようにする

DxLibでゲームを作っているのですが、文字列の色を途中から変えるにはどうしたらいいんだろうと苦悩した末に完成しました。
推理ゲームなど、重要な単語の色付けなどに便利です。

追記1

改良して高速化しました。
なのでこの記事は正直無意味な存在と化した。
volatile.hatenablog.com


f:id:volatile1:20180320152332p:plain

文字列の色を途中から変更する

使用するには今回紹介する自作関数、DrawFormatStringToHandleExを使います。

↓こんな感じで色付けしたい場合、
Lorem ipsum dolor sit amet

文字列リテラルは以下のような感じに指定することにします。

"Lorem [dd830c]ipsum [-]dolor [1464b3]sit [-]amet"

[xxxxxx](xxxxxxは16進数のカラーコード)以降の文字はカラーコードと同じ色になり、[-]で以降デフォルトの色になります。

FontEx.hをインクルードして、こんな感じで使ってください。

	static int FontHandle = CreateFontToHandle("MSゴシック", -1, -1, -1);
	DrawFormatStringToHandleEx(0, 0, 0xffffff, FontHandle,
		"あの[dd830c]イーハトーヴォ[-]のすきとおった風、夏でも底に冷たさをもつ青いそら、\n\
うつくしい森で飾られた[286f2c]モリーオ市[-]、郊外のぎらぎらひかる草の波。\n\
Lorem ipsum dolor sit amet, [0000ff]consectetur adipiscing elit,\n\
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.[-]\n\
%d + %d = [ff0000]%d[-]", 30, 40, 30 + 40);

追記2

「私のgithubにFontEx.hがあります!リンク先をどうぞ!」とかいっておきながらリンクを貼っていなかった馬鹿(私)がいました。
申し訳ありません。
github.com

一応リンク先に飛べない時用にこちらにもソースコードを書いときます。
ヘッダファイル(FontEx.h)を新規作成・コピペしてください。
もし使いたい場合は私(volatile)が作った事を示すクレジット表記等は書かなくて結構です。

// FontEx.h
#pragma once
#include <vector>
#include <regex>
#include <DxLib.h>

inline unsigned int convert_dex(const std::string& str) {
	std::string s(str, 1, 6);
	s = "0x" + s;
	return (stoi(s, nullptr, 16));
}

template <typename ... Args>
void DrawFormatStringToHandleEx(int x, int y, unsigned int Color, int FontHandle, const TCHAR *FormatString, Args const & ... args) {
	unsigned int cr = Color;
	std::vector<std::string> vec; //splited string
	static TCHAR str_c[65536]; //<-65536: Maximum number of string

	sprintf_s(str_c, 65536, FormatString, args...);
	std::string str_s = str_c; //string to split
	std::regex re{ R"((\[(([\da-f]{6})|-)\])|\n)" }; // separater
	auto ite = std::sregex_token_iterator(str_s.begin(), str_s.end(), re, { -1,0 });
	auto end = std::sregex_token_iterator();

	while (ite != end) {
		vec.push_back(*ite++);
	}

	int _x = x, _y = y;
	for (const auto &i : vec) {
		if (std::regex_match(i, re) == true) {
			if (i == "[-]") {
				cr = Color;
				continue;
			}
			else if (i == "\n");
			else { 
				cr = convert_dex(i);
				continue; }
		}

		if (i == "\n") {
			_x = x;
			_y += GetFontLineSpaceToHandle(FontHandle);
		}
		else {
			DrawFormatStringToHandle(_x, _y, cr, FontHandle, i.c_str());
			_x += GetDrawFormatStringWidthToHandle(FontHandle, i.c_str());
		}
	}
}

C++学んで1・2年経って書いたソースコードなので高速化・最適化の余地はまだありそうですね…
ではまた~

メルスト 降臨の遊び方 by My Guild

私のギルドにいる某スペシャリストが教えてくれたのでメモメモ。

概説

降臨イベントは4ギルドで協力してボスを倒していくイベントです。開催時間は土日の9:00-11:00、20:00-22:00です。

コマンド

  • 出撃: 出撃してボスにダメージを与えます
  • 応援: 初期SPを増加させます。SPは号令にも使います
  • 挑発: ボスモンスターを引きつけます
  • 支援: 30bp回復します。ただし、誰かと交互でないと押せません
  • 号令: 10分間、与ダメと挑発効果を1.5倍にします。ただし、初期SPが50000減ります
応援

25bpを消費して初期SPを200増加させます。降臨イベントでは初期SPを減らして使用する号令コマンドが非常に重要なので、応援も相当回数必要になります。

挑発

15bpを消費してモンスターを自ギルドへ引きつけます。詳細は【部位数の厳選】、【背面ボーナス】および【挑発役】へ。

支援

30bp回復します。降臨イベントでのbp源になります。4ギルド内の誰かと交互に押さないと回復できないので積極的に使用しましょう。ギルバトと異なり、降臨イベントではこのボタンを使用してほぼ無制限にbpを使えます。

号令

50000SPを消費して10分間与ダメ・挑発効果を1.5倍にします。ギルドが与えるダメージ量に大きく影響するので、号令は常に発動できるようにします。

モンスターの部位数

降臨モンスターは、その時その時で1~5の部位数を持ちます。3部位の場合はモンスターに最大3箇所攻撃がヒットするので、同時攻撃数3のユニットを使うと効率的にダメージを与えられます。

3部位のモンスターに同時攻撃数4のユニットで攻撃すると、同時攻撃数1つ分だけ攻撃がヒットせず、若干効率が落ちます。同時攻撃数1のユニットでは、ムダは無いですが総合火力が不足することになります。

モンスターは初期状態では部位数???となっていますが、3ギルド以上からの出撃で何部位かがわかります。また、中央の巣に戻るか1レベル撃退されるたびに部位数はリセットされ、???になります。

部位数の厳選

部位数は多いほど良いです。したがって、効率よくモンスターを撃退するために部位数3以上を狙います。手順は、まず3ギルド以上の出撃によって部位数を明らかにします。ここで部位数2以下ならリセット対象です

モンスターは初期状態では中央の巣にいますが、ダメージを与えるか挑発をすることによって、ギルドの方向へと進行してきます。

このとき進行されているギルド以外のギルドが挑発コマンドを繰り返し実行することによって、モンスターは進行方向を変えます。このときに中央の巣へ一度戻れば部位数のリセットは完了です。これを部位数3以上になるまで行います。

背面ボーナス

モンスターが特定のギルドへ進行している場合、その進行度によって最大で正面からの攻撃1倍、側面からの攻撃1.5倍、背面からの攻撃2倍の与ダメージ補正がつきます

したがって、挑発する場合はしっかりと引きつけを行い他ギルドがダメージを出しやすくすることが重要です。

挑発役

ボスの撃退においては3部位以上の部位数のリセットを防ぐため、また背面ボーナスを受けるため、1ギルドが挑発し続ける必要があります

挑発役は4ギルド間で相談して決めることになりますが、基本的にはローテーションで受け持つことになります。したがって、ギルドログや降臨ルームのチャットをよく確認して自ギルドが挑発役のときにはしっかり挑発をしましょう。

また、部位数厳選の際には挑発役は挑発を停止します。他のギルドが引いて巣に戻してくれるのを待ちましょう。

パーティの組み方

「中衛打撃1・中後衛4」か、「前衛1・中後衛3・回復1」の構成が基本です

中衛打撃パーティを使う場合は、中衛打撃ユニットに着けるフィクセイト・アタック・クイックの3つのルーンをある程度強化しておく必要があり、少し敷居は高いです。

シードは「パライズアサルト・パライズアサルツ・ソウル・ブレイク・エクステンドタイム」がおすすめです。エクステンドタイムの代わりにソウルを入れても構いません。

ブレイクはボスの属性(撃退レベル1毎に変化)に合わせたものを選びましょう。

f:id:volatile1:20180201161839j:plainf:id:volatile1:20180201161847j:plain
f:id:volatile1:20180201161852j:plainf:id:volatile1:20180201161857j:plain

範囲攻撃

降臨モンスターは範囲攻撃という特殊な攻撃を仕掛けてきます。普通の攻撃とモーション・音・攻撃範囲が違うので、そこで見分けましょう。また範囲攻撃中はモンスターに与えるダメージが大幅に上がります

パライズ系シードを範囲攻撃中に撃つと与ダメージ増加状態を維持したまま麻痺状態に出来るので、範囲攻撃が解除される前にパライズを撃ちましょう

結局どうすればいいの?

  • 朝はひたすら応援と支援を交互に押してSPを貯める
  • ギルログ等を確認し、挑発役が回ってきたら挑発と支援を交互に押す
  • 挑発役のときに2部位以下だったら、一時的に挑発をやめて他のギルドに巣に戻してもらう
  • 他ギルドがしっかり引きつけてくれていれば積極的に出撃する

注意事項

挑発コマンドは挑発役以外のときに押してはいけません。例外は部位数厳選の際に、ボスを巣に引き戻すときだけです。4ギルド80人の協力が大事ですので、ダメージが出せない方も応援挑発等の協力をしましょう。

降臨解説サイト

Win32API挫折しそうになりつつ頑張る#1

Win32APIの参考書買いましたがぶ厚すぎて(669ページ)挫折しそう。でも頑張ります。

Win32 APIシステムプログラミング with Visual C++ 2008

Win32 APIシステムプログラミング with Visual C++ 2008

サンプル#1(Hello_world/Release/Hello_world.exe)

ウィンドウ生成のプログラムを作りました。
興味ある方は私のGitHubから落とせるので遊んだり改造してみてください。

左クリックでメッセージボックスを表示、ユーザーに挨拶してくれます。
また、メニューバーの「Setting」で表示されるダイアログボックスから挨拶で使われる名前を変更できますよ。

f:id:volatile1:20180118220411p:plain
左クリックで挨拶してくれます。

ではまた。