|
|
2009/3/25(Wed) 21:12:18|NO.24115
「ノベル風」のメッセージ(一文字ずつ表示されたり影があったり)表示をしたいのですが、
他の処理とも並列して行いたいので、ループ内に入れなければなりません。
また、レイヤー(ここでは画面バッファ)に画面を保存し、メインループで
画面のコピーをし、他のレイヤーと合成する(挙げているスクリプトにはありませんが)のですが、
どのようにすればいいでしょうか?
以下に私が作成したスクリプトを挙げますが、
見て分る通り、改行は無視されますし、半角文字はそういう処理をしてないので、文字化けしますし、
何故か文字レイヤーの背景が一部入り込んでいます。。
汚いスクリプトですが、こんな感じです。
buffer 1
color 255:boxf
gsel 0
text="あいうえお\nかきくけこ\nさしすせそ\nたちつてと\nAあいうえお"
color 230,230,230:boxf
repeat
flag++:if flag=10{
flag=0
moji = strmid(text,(cnt/10)*2,2)
gsel 1
font "MS ゴシック",23
color 255,255,255:pos (cnt*2)+2,12:mes moji
color 0,0,0:pos cnt*2,10:mes moji
gsel 0
color 255
gmode 4,,,256
gcopy 1,0,0,640,40
}
wait 1
loop
よろしくおねがいします。
|
|
2009/3/25(Wed) 21:25:37|NO.24117
コードが129〜159か、224〜252の範囲にある場合は、
次の1バイトと合わせて1文字の全角コードとなる。
(HSP3文字列のひみつ(中級者向け) (hsp3str.htm) より)
|
|
2009/3/25(Wed) 21:29:21|NO.24118
>checkさん
回答ありがとうございます。
「A」のみなら文字化けして「AA」ならひとつの全角文字として扱われると言う事でしょうか?
それは存じてますが、根本的解決にならないかと思います。。
|
|
2009/3/25(Wed) 21:33:32|NO.24121
だから、描画する文字を取得するときに、
1バイト文字だったら1文字、2バイト文字だったら2文字取得すれば
文字化けしない
|
|
2009/3/25(Wed) 21:39:16|NO.24122
>checkさん
回答ありがとうございます。
そういうことですか。失礼しました。
具体的にはどういう風に判定すればよいでしょうか?
またcntを使って位置を設定してるので、位置がだんだんずれてくると思うのですが、
対策などどのようにしたらよいでしょうか?
|
|
2009/3/25(Wed) 21:40:25|NO.24123
>具体的にはどういう風に判定すればよいでしょうか?
だから、コードが129〜159か、224〜252の範囲にある場合は、
次の1バイトと合わせて1文字の全角コードとなる。
peekとifを使って判定
|
|
2009/3/25(Wed) 21:42:05|NO.24124
text命令は駄目なの?
|
|
2009/3/25(Wed) 22:30:50|NO.24130
>text命令は駄目なの?
他の処理と並列して行う為、それは出来ない訳です。。
|
|
2009/3/25(Wed) 23:31:38|NO.24143
>checkさん
すみません。ありがとうございます。
ひとまずその問題は大丈夫だと思います。
|
|
2009/3/25(Wed) 23:41:44|NO.24145
>GENKIさん
回答ありがとうございます。
>改行を見つけたら、改行後の位置から表示し始めるようにpos命令のパラメータを変更してください。
やはり、その方法しかないでしょうか・・・?
>フォントには大きく分けて2種類あります。...
それは知りませんでした! なるほど。。
>ループ内にfont命令必要ないですよ。
おっと・・・間違ってましたね。。
確か、これが指定される度にフォントが用意されるのですよね。。(汗)
もっと合理的な方法は無いのでしょうか?
あと、メッセージレイヤーの背景色(コピーされない設定)がコピー先にもコピーされている問題は、
どのようにしたら解決できるでしょうか?
複数の質問ですみませんが、よろしくお願いします。
|
|
2009/3/26(Thu) 01:26:40|NO.24147
> もっと合理的な方法は無いのでしょうか?
何を持って合理的とするのか…。
モジュール化してしまえば、実際に使用するときのスクリプトはすっきりすると思います。
少しひねってこういうカラオケ的な表示もありかと。
screen 1
font msgothic,32
mes {"あいうえお
かきくけこ"}
gsel 0,1
sx(0)=0,0
*main
redraw 1 : await 16 : redraw 0 : color 0,0, 255 : boxf : color : pos 0,0
sx(0)+=3 : sx(0) = limit(sx(0),0,32*5)
gcopy 1, 0,0, sx,32
if sx(0)>=32*5 {
sx(1)+=3 : sx(1) = limit(sx(1),0,32*5)
pos 0,32
gcopy 1, 0,32, sx(1),32
}
goto *main
最近のゲームだと1文字ずつ表示するタイプとは別に、このタイプの表示も見かけます。
(個人的には、1文字ずつよりこのタイプの方が好き。)
> あと、メッセージレイヤーの背景色(コピーされない設定)がコピー先にもコピーされている問題は、
> どのようにしたら解決できるでしょうか?
文字にアンチエイリアスがかかっているため背景と文字との中間色が作られ、コピーされています。
font命令のマニュアルには「(WindowsXPでは、常にアンチエイリアスが有効になります。)」とあるため
これが原因と考えられます。私にはこの回避方法は分かりません。
とりあえず出来うる対処法としては、背景色を輪郭が残っても目立たないような色にすることです。
今回の場合、文字が黒と白なので、背景色を赤ではなく白、または黒、その中間の灰色、コピー先
ウィンドウの背景色、このあたりにすれば目立たなくなると思います。
ちゃんとした解決方法は他の方よろしくお願いします。
|
|
2009/3/26(Thu) 01:57:42|NO.24148
>GENKIさん
回答ありがとうございます。
>何を持って合理的とするのか…。
説明不足でした…「他に方法は無いのか?」と言う事です。
>モジュール化してしまえば、実際に使用するときのスクリプトはすっきりすると思います。
モジュール化については見当していますが、実際やった事が無いのでよく分りません。
教えていただけますでしょうか?(本当、初心者ですみません。。)
>文字にアンチエイリアスがかかっているため背景と文字との中間色が作られ、コピーされています。
なるほど…確かに類似色を使えば誤魔化す事はできますね。
ただ、やっぱりすっきりしませんね。。
誰かこの問題の対処法を知っている方、お願いしますっ!
|
|
2009/3/26(Thu) 02:06:49|NO.24149
モジュール化についてはHSPマニュアルの
モジュール機能ガイド(中上級者向け) (module.htm) を読め
メッセージレイヤーの問題については、そのまま文字を描いてはいけないのか?
|
|
2009/3/26(Thu) 02:14:11|NO.24150
>checkさん
回答ありがとうございます。
>メッセージレイヤーの問題については、そのまま文字を描いてはいけないのか?
はい。他にレイヤーが存在しており、常時書き換えられるので、
一文字しか表示されなくなります。
また、すっきりさせる為でもあります。
構成はこうなってます。
[メッセージレイヤー]>[メニューレイヤー]>[メッセージウィンドウレイヤー]>[キャラ絵レイヤー]>[背景レイヤー]
|
|
2009/3/26(Thu) 02:27:53|NO.24151
自分で表示させる文字をペイントで作れば?
一色にすればアンチエイリアスの問題も起こらないけれど、見難い。
|
|
2009/3/26(Thu) 02:39:13|NO.24152
>メッセージ表示
昔載せたような…と思ったら過去ログに行ってましたか…。
過去ログを「D.K」で検索していただければ
私のつたないサンプルとcoinさんにより改良・モジュール化されたものがヒットするかと。
|
|
2009/3/26(Thu) 02:40:20|NO.24153
>checkさん
>自分で表示させる文字をペイントで作れば?
流石にそれは非効率だと思います。。
|
|
2009/3/26(Thu) 02:48:47|NO.24154
>D.Kさん
回答ありがとうございます。
私がしたい事と非常に似てますね。。
参考にします。
(質問は継続します)
一応まとめ。。
・半角文字が文字化けする(解決)
・改行が無視される(未実装だがおそらくできそう)
→メッセージレイヤーの不具合(未解決)
複数の質問になってしまい、すみません。
|
|
2009/3/26(Thu) 03:13:18|NO.24155
文字が黒と白だけなら、それぞれ減算合成と加算合成でなんとかなりませんか?
|
|
2009/3/26(Thu) 03:32:48|NO.24156
>SYAMさん
>文字が黒と白だけなら、それぞれ減算合成と加算合成でなんとかなりませんか?
それらについてあまり詳しくないので、スクリプトを載せていただけませんでしょうか?
|
|
2009/3/26(Thu) 09:27:20|NO.24157
加算も減算も、ドットごとの色の値を足したり引いたりした色になるというものです。
あとはgmode 命令のヘルプを見たらわかると思います。
gmodeにはもうひとつピクセルアルファブレンドってものもあるので、ついでにそれも入れたサンプルを示します。
screen 1,256,24,0:cls 4
font msgothic,24,17
color 64,64,64
pos 2,2 : mes "猫いじりたいなあ"
color 255,255,255
pos 0,0 : mes "猫いじりたいなあ"
screen 2,512,24,0:cls 4
color 255,255,255
boxf 0,0,256,24
pos 256,0 : gcopy 1,0,0,256,24
screen 0,256,72,0:
repeat 500:pos rnd(256),rnd(72)
color rnd(256),rnd(256),rnd(256)
mes "猫"
loop
;加算合成
gmode 5,,,255
pos 0,0 : gcopy 1,0,0,256,24
;減算合成
gmode 6,,,255
pos 0,24 : gcopy 1,0,0,256,24
;ピクセルアルファブレンド
gmode 7,,,255
pos 0,48 : gcopy 2,0,0,256,24
;以下はgmode7のコピー元にグラデーションをかけた応用例.
gsel 2
repeat 24
c=cnt*10+25
color 255,c,128
line 0,cnt,255,cnt
loop
gsel 0
gmode 7,,,255
pos 0,48 : gcopy 2,0,0,256,24
理解しにくいのは減算かもしれませんが・・・、
色の成分ごとの明るさを引き算します。ですから、白(255,255,255)を“引く”と、結果は黒(0,0,0)になりますね。
※実際には加算も減算も検索したらわかる話ではありますが・・・理解の足しにでもなれば幸い。
|
|
2009/3/26(Thu) 09:29:38|NO.24158
orz
gmode 7 の1つめの例を2つめの例で上書きしてますね。。。
ヘタこいたあああ。
|
|
2009/3/26(Thu) 14:16:01|NO.24173
こんなのはどうですか?
#define cls_x : color 100,100,100 : boxf : color 0,0,0
;メインループの活動を示すための画像を登録
screen 2,100,100,2
boxf 0,0,100,100
;メッセージボックス用のウインドウ
screen 1,640,100,2
gsel 0
randomize
;#########################################
*hajime
gosub *メッセージ表示
gosub *メインループ
goto *hajime
;#########################################
;メインループとメインの処理
*メインループ
gsel 0
repeat 100
title "メインループ中"+str(cnt)
gosub *メインの処理
loop
return
;メインループの処理
*メインの処理
color 255,255,255 : boxf ;画面更新
pos rnd(640),rnd(480) : gmode 0,100,100 : gcopy 2,0,0
wait 10
return
;#########################################
;メッセージ表示とメッセージ入力待ちの処理
*メッセージ表示
title "メッセージ表示中"
gsel 1
;半角文字のサイズを記憶
cls_x : mes "a" : cls_x
mesx_x = ginfo_mesx : mesy_y = ginfo_mesy
;必要な変数の初期化
msg = "こんにちはHSPです\nhspです\n改行もできる。"
cunt = 0 : mesx = 0 : mesy = 0
;メッセージ表示のメインループ
repeat
a=peek(msg,cunt) ;文字コードを読みだす
if a = 13 : cunt++ : mesy += mesy_y : mesx = 0 : continue ;"\n"の文字コードは二つあるため両方ともスキップ&改行の処理
if a = 10 : cunt++ : mesx = 0 : continue ;
gsel 1
if (a >= 129 & a <= 159 | a >= 224 & a <= 252) {
pos mesx,mesy : mes strmid(msg,cunt,2)
cunt+=2 : mesx+=mesx_x * 2 ;全角文字の場合は半角文字の大きさ*2
}else{
pos mesx,mesy : mes strmid(msg,cunt,1)
cunt++ : mesx+=mesx_x ;半角の場合はそのまま
}
gsel 0 : redraw 0
gosub *メインの処理
pos 0,0 : gmode 0,640,100 : gcopy 1,0,0
redraw 1
if strlen(msg)-1 <= cunt : break
loop
;エンターキーの入力を待つ
repeat
getkey p1,13
if p1=1 : break
redraw 0
gsel 1 : color clr,clr,clr : pos (640/2)-(ginfo_mesx/2),75 : mes "▽"
gsel 0 : gosub *メインの処理
pos 0,0 : gmode 0,640,100 : gcopy 1,0,0
redraw 1
clr+=30
if clr>=255 : clr=0 :
loop
return
| |
|
2009/3/27(Fri) 01:19:46|NO.24186
>SYAMさん
回答ありがとうございます。
なるほど。そんなことができるんですね。。
…でも、何か影の白が灰色になってると思うのですが、
白にはできないのでしょうか?
>窓口さん
回答ありがとうございます。
一先ずこのサンプルを少し弄って使わせて頂きます。
|
|
2009/3/27(Fri) 04:07:40|NO.24187
>…でも、何か影の白が灰色になってると思うのですが、
そうなってる理由を自分で考えようと思わないのか?
|
|
2009/3/27(Fri) 11:27:34|NO.24192
問題は中間色を使ったアンチエイリアシングのせいで背景色が混じってしまうことですよね。それの代わりとして、中間色である灰色を文字の近くに意図的に混ぜ込んだのが影の灰色です。
影の灰色が 灰色に見えないように 自然に背景に混ざりこんでいればOKだったわけですが、前回のスクリプトでは確かにそのことがわかりにくかったかもしれません。
影が灰色っぽくても、失敗には見えませんからね。
なので、今度は失敗が失敗らしく見えるよう、本来の問題が実際に発生するサンプルを示します。
// gmode 0〜6用.
buffer 1,48,48,0:cls 4
font msgothic,48,16
pos 0,0 : color 255,255,255:mes "猫"
// gmode 7用.
buffer 2,96,48,0:cls:color 0,0,0:boxf 48,0,96,48
font msgothic,48,16
pos 48,0 : color 255,255,255:mes "猫"
// グラデーションのかかった背景.
screen 0,48*8,112,0:cls 4:font msgothic,10
repeat 96:color 255-cnt,128,cnt+159:line 0,cnt,48*8,cnt:loop
color 0,255,0:repeat 8:pos cnt*48+10,98:mes "mode "+cnt : loop
color 255,255,255 ;gmode 4で透過する色.
alpha=64,256
repeat 2 : n=cnt
repeat 7
gmode cnt,,,alpha(n)
pos cnt*48,48*n:gcopy 1,0,0,48,48
loop
gmode 7,,,alpha(n)
pos 7*48,48*n:gcopy 2,0,0,48,48
loop
gmode 0〜7の合成がどのように行われるかを示しています。上段は不透明度を64まで下げたもの、下段は不透明(gmode2などの完全な透過はする)です。
mode2だと、コピー元の背景である黒と、文字の白が混じった灰色が出てきてしまっています。
その部分が、mode5 や mode7では灰色ではなく ちゃんと薄い白として貼り付けられているのがわかるでしょうか?
※参考までに…
半透明合成について、mode5,6は加減算だけで済み、mode3,4,7では加減算と割り算を使います。割り算は加減算より重いため、処理はmode5,6のほうがずっと速いです。
しかしmode5の場合は単純な加算なので、合成先がもともと明るいと真っ白になりやすいのです。実際、サンプルでもmode7よりも強い白になってエイリアシングが目立っていますね。
| |
|
2009/3/27(Fri) 14:35:46|NO.24201
>SYAMさん
回答ありがとうございます。おぉ。確かにきれいに白い文字がでてますね。。
ちょっとサンプルを弄って目的の結果にしたのですが、
こんな感じで良いんでしょうか?
画面コピー等についてはついこの間に手を出したばかりなので、非効率な編集をしてるかもしれませんが、
「ここをこうした方が良い」などありましたらご指摘して下さると幸いです。 // gmode 0〜6用.
buffer 1,48,48,0:cls 4
font msgothic,48,16
pos 0,0 : color 255,255,255:mes "猫"
// gmode 7用.
buffer 2,96,48,0:cls:color 0,0,0:boxf 48,0,96,48
font msgothic,48,16
pos 48,0 : color 255,255,255:mes "猫"
// グラデーションのかかった背景.
screen 0,48*8,112,0:cls 4:font msgothic,10
repeat 96:color 255-cnt,128,cnt+159:line 0,cnt,48*8,cnt:loop
alpha=64,256
///// ここから編集 /////
;影(白)描画
gmode 7,,,alpha(1)
pos 12,12:gcopy 2,0,0,48,48
;文字(黒)描写
gmode 6,,,alpha(1)
pos 10,10:gcopy 1,0,0,48,48
///// ここまで編集 /////
|
|
2009/3/27(Fri) 15:14:42|NO.24203
gmode 5 はコピー先が明るいと白飛びしますが、gmode 6 は同じ理由でコピー先が暗いと黒くつぶれてやっぱりギザがめだつようになります。
それを避けるために gmode 7 を使うのであれば、白以外の文字を出すには コピー元の左半分の真っ白の部分を別の色で塗りつぶすことになります。
色自体はなんでもよく、たとえばグラデーションをかけたりとかもできるというのは 先に示したほうのサンプルからわかると思います。
|
|
2009/3/27(Fri) 18:17:33|NO.24208
グラデーションの話をしている中突然すいません。
何かの処理をしながら文字を表示するモジュールを作ってみました。
こんな感じでどうですか?
#module
#uselib "winmm.dll"
#cfunc timeGetTime "timeGetTime"
#deffunc mes_set str ms_message,int ms_time,int ms_shade
//mes_timeで↑内容を使えるようにする
mt_message=ms_message
mt_time=ms_time
//影の色
mt_shade=ms_shade
dim mt_color,3
dim shade,3
shade.0=ginfo_r,ginfo_g,ginfo_b
//カウント開始
now=timegettime()
mt_before=0
//カレントポジションの取得
ms_beforeX=ginfo(22)
ms_beforeY=ginfo(23)
//フォントのX,Yサイズの取得
mes" "
ms_X=ginfo(14)
ms_Y=ginfo(15)
//カレントポジションを戻す
pos ms_beforeX,ms_beforeY
return
#deffunc mes_time
//タイマーから表示する文字数を算出
mt_word=0
mt_len=(timegettime()-now)/mt_time
repeat mt_len
if peek(mt_message,mt_word)>=129 & peek(mt_message,mt_word)<=159:mt_word+
if peek(mt_message,mt_word)>=224 & peek(mt_message,mt_word)<=252:mt_word+
mt_word+
if mt_word>strlen(mt_message):mt_word=strlen(mt_message):break
loop
//カレントポジションの取得
mt_beforeX=ginfo(22)
mt_beforeY=ginfo(23)
//影を表示する場合の処理
if mt_shade=1 {
//現在のカラーコードを記憶
mt_color.0=ginfo_r,ginfo_g,ginfo_b
//影の色を選択
color shade.0,shade.1,shade.2
//影の表示
pos ms_beforeX+ms_Y/10,ms_beforeY+ms_Y/10
mes strmid(mt_message,0,mt_word)
//カラーコードを戻す
color mt_color.0,mt_color.1,mt_color.2
}
//mes_set時のカレントポジションに文字を表示
pos ms_beforeX,ms_beforeY
mes strmid(mt_message,0,mt_word)
//全ての文字が表示されていれば0を返す。
if mt_word=strlen(mt_message):return 0
//カレントポジションを戻す
pos mt_beforeX,mt_beforeY
return 1
#global
//▼▼▼サンプル▼▼▼
color:boxf
font msgothic,20
color 128,128,128
//mes_set命令で表示する文字、表示速度、影の有無を設定します。
mes_set"サンプルの文字列です。\n改行に対応していて、\n[ABC]や[def]、[\\\"]などの1バイト文字にも対応しています。\n文字を表示しながら別の処理を行うことも可能ですが、\nmes_time命令を入れ忘れると文字は表示されません。\nこのサンプルでは、はじめにawait10で300ループさせた後、\nマウスポインタの位置に円が表示されます。\n300ループ中はcntの内容をtitle命令で表示しているため、\nPCのスペックによって完了まで誤差が生じます。",100,1
color 255,255,255
//試しに300ループ待ってみます。
repeat 300
title""+cnt+"ループ目"
//mes_time命令でmes_setが実行されてから経過した時間分の文字を表示します。
mes_time
await 10
loop
title"ここからは別の処理、マウスポインタの位置に文字が表示されます。"
repeat
redraw 0
color:boxf
//mes_time命令では現在のカラーコードが適用されるので、途中で変更すると文字色も変わります。
color 255,255,255
mes_time
//別の処理。マウスポインタの位置に円が表示されるだけです。
circle mousex-5,mousey-5,mousex+5,mousey+5
redraw 1
if stat=0:break
wait 1
loop
mes"終了"
dialog"文字が完全に表示されました。"
//▼▼▼命令の解説▼▼▼
/*
・mes_set命令
mes_set "strings",p1,p2
"strings" : 表示する文字列
p1 : 1文字を表示するのにかかる時間。1000で1秒
p2 : 影の表示。1で影を表示します。
この命令が実行された瞬間から時間を計測していきます。
影の色は、この命令が実行された時のカラーコードが適用されます。
・mes_time命令
mes_time
パラメータはありません。
この命令が実行されると[mes_set]命令が実行されてから現在までの経過時間分の文字が表示されます。
全ての文字が表示し終わるとstatに0が代入され、それ以外では1が代入されます。
全ての文字が表示し終わっている時間でこの命令を実行した場合のみ、カレントポジションが変更されます。
*/
| |
|
2009/3/28(Sat) 12:38:01|NO.24227
ノベルゲームということはEnterキーを押したら文字をすぐに表示できなければ
いけませんでしたね。一応それも出来るようにしておきました。
No.24208の
#global
の1行上に
#deffunc mes_end
now=timegettime()-strlen(mt_message)*mt_time
return
を入れてください。
・mes_end命令
mes_end
mes_timeに同じくパラメータはありません。
この命令が実行されるとタイマーを変更して全文字を表示する時間まで変更します。
つまり、現在経過した時間にかかわらずmes_setで設定してあった文字を全て表示できるようにします。
時間を変更するだけなので、この命令実行後にmes_time命令を再度実行しなければ文字は表示されません。
|
|