|
|
2020/7/5(Sun) 15:41:11|NO.90911
こんにちは。
ゲームの背景画像をコードで表現したいです。
単純で簡単なものであれば作れるのですが、
空と雲、海の水面、石だたみ、木の橋、桜の花びらの道
の様な凝ったものになるとさっぱりです。
上記の様なものをコードで表現する手法がありましたら
ご教示頂けないでしょうか。
素直に画像を使おうかとも思うのですが。
ここでお聞きしてからと思いまして、
宜しくお願いいたします。
単純で簡単なもののイメージサンプル
screen 0,256,256
pos 0,0 :button goto "草",*草
pos 64,0 :button goto "土",*土
pos 64*2,0 :button goto "道",*道
pos 64*3,0 :button goto "木",*木
stop
*草
r=140:g=220:b=110
goto *描画
*土
r=200:g=180:b=120
goto *描画
*道
r=120:g=120:b=120
goto *描画
*木
r=230:g=180:b=130
goto *描画
*描画
baratuki=30
randomize
color r,g,b
boxf
repeat 3000
x=rnd(256):xx=x+rnd(4)
y=rnd(256):yy=y+rnd(4)
color r-rnd(baratuki),g-rnd(baratuki),b-rnd(baratuki)
boxf x,y,xx,yy
loop
stop
|
|
2020/7/5(Sun) 16:30:55|NO.90912
雲や水面はパーリンノイズというのを使えば作れるとは思いますが
作るのは難しいと思います。
石畳はイメージサンプルの石の時を改良したらそれっぽくはなりました。
screen 0,256,256
r=120:g=120:b=120
baratuki=30
randomize
color r,g,b
boxf
repeat 3000
x=rnd(256):xx=x+rnd(4)
y=rnd(256):yy=y+rnd(4)
color r-rnd(baratuki),g-rnd(baratuki),b-rnd(baratuki)
boxf x,y,xx,yy
loop
color 0,0,0
repeat 9
cnt1=cnt
repeat 8
line 16*(cnt1\2)+32*cnt,32*cnt1,16*(cnt1\2)+32*cnt,32*(cnt1+1)
loop
line 0,cnt*32,256,cnt*32
loop
stop
ただきれいすぎるので要改良ですが。
桜の花びらの道はちょっと方法が思い浮かばないです。
桜の花びらの形さえ作れば乱数で回転させて乱数で配置すればできるとは思います。
|
|
2020/7/5(Sun) 19:02:47|NO.90913
>空と雲
簡易のぼかしを利用してやってみましたが。。。
最初のカラーパターンのせいか微妙になってしまいました。
途中経過が分かりやすいように1秒ウェイトを入れています。
screen 0, 256, 256, 0;
randomize;
// カラーパターン(薄い水色、水色、空色、薄い灰色、灰色)
patern_r = 128, 0, 0, 192, 128;
patern_g = 255, 255, 128, 192, 128;
patern_b = 255, 255, 255, 192, 128;
pnum = 5; // カラーパターンの数
block = 32; // ブロックサイズ
repeat 6
title "処理中 block="+block+"";
pidx = cnt;
redraw 0;
repeat 256 / block
x = cnt * block;
av_r = 0;
av_g = 0;
av_b = 0;
repeat 256 / block
y = cnt * block;
if( pidx == 0 ) { // 最初はカラーパターンの色で大まかに塗り潰す
cidx = rnd(pnum);
color patern_r(cidx), patern_g(cidx), patern_b(cidx);
boxf x, y, x + block - 1, y + block - 1;
}
else { // 2回目以降はブロックサイズを半分にして周囲の色の平均値で塗り潰す
// 左のブロックの色を取得
if( x - 1 < 0 ) {
nx = ginfo_winx - 1; // 一番左端のブロックだった場合は右端の座標にする
}
else {
nx = x - 1; // 1ブロック左の座標を取得
}
ny = y;
pget nx, ny;
av_r = ginfo_r;
av_g = ginfo_g;
av_b = ginfo_b;
// 上のブロックの色を取得
if( y - 1 < 0 ) {
ny = ginfo_winy - 1; // 一番上端のブロックだった場合は下端の座標にする
}
else {
ny = y - 1; // 1ブロック上の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 右のブロックの色を取得
if( x + block > ginfo_winx - 1 ) {
nx = 0; // 一番右端のブロックだった場合は左端の座標にする
}
else {
nx = x + block; // 1ブロック右の座標を取得
}
ny = y;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 下のブロックの色を取得
if( y + block > ginfo_winy - 1 ) {
ny = 0; // 一番下端のブロックだった場合は上端の座標にする
}
else {
ny = y + block; // 1ブロック下の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 周囲4ブロックの色の平均値で塗り潰す
av_r /= 4;
av_g /= 4;
av_b /= 4;
color av_r, av_g, av_b;
boxf x, y, x + block - 1, y + block - 1;
}
loop
loop
block /= 2; // ブロックサイズを半分にして次のループへ
redraw 1;
await 1000;
loop
title "終了";

| |
|
2020/7/5(Sun) 19:50:21|NO.90914
>桜の花びらの道
これはkanamaruさんの仰る通り、
一旦花びらの図形をバッファに描いてランダムに配置するしかないかと。
花びらの図形を描くのが難しいのですが、
桜の花びらに近い形のハートの曲線式を応用してみると
Artlet2Dなどで描画できるかもしれません。
もっとシンプルな方法としては
ハートの記号(♥)をfont&mesで適度な大きさで描画して
横幅を半分にするなどして花びらに近い形に変形し
それを回転コピーしながら配置すればそれっぽく見えるかもしれません。
|
|
2020/7/5(Sun) 21:29:53|NO.90917
桜の花びらの道の描画方法をcssでの桜の花びらに作り方を参考に作ってみました。
pset使ってるので花びらを動かしたりすると処理が重いかもしれません。
screen 0,640,480
buffer 1,20,20
repeat 20
x=cnt
repeat 20
y=cnt
color 0,0,0
if((x*x+y*y<20*20)&&((20-x)*(20-x)+(20-y)*(20-y)<20*20)):color 255,192,203
pset x,y
await 0
loop
loop
color 0,0,0
boxf 14,6,20,0
gsel 0
repeat 50//花びらの数
pos rnd(640),rnd(480)
gmode 2,20,20
grotate 1,0,0,rnd(628)/100,20,20
await 0
loop
花びらの数は自由に変えてみてください。
|
|
2020/7/5(Sun) 22:43:03|NO.90918
早々にありがとうございます
スゴイ技があるのですね
お二人のソースを自分用に
コピペして纏めさせて頂きました
解決としますが、
もし木目調の質感の出し方などあれば
また教えて頂けますと嬉しいです。
sx=256:sy=256
screen 0,sx,sy
objsize 32
pos 32*0,0 :button goto "草",*草
pos 32*1,0 :button goto "土",*土
pos 32*2,0 :button goto "道",*道
pos 32*3,0 :button goto "木",*木
pos 32*4,0 :button goto "雲",*雲
pos 32*5,0 :button goto "桜",*桜
pos 32*6,0 :button goto "レンガ",*石
pos 32*7,0 :button goto "消",*消
//花びら
buffer 1,20,20
repeat 20
x=cnt
repeat 20
y=cnt
color 0,0,0
if((x*x+y*y<20*20)&&((20-x)*(20-x)+(20-y)*(20-y)<20*20)):color 255,192,203
pset x,y
await 0
loop
loop
color 0,0,0
boxf 14,0,20,6
gsel 0
stop
*消
color 255,255,255
boxf
stop
*草
r=140:g=220:b=110
goto *描画
*土
r=200:g=180:b=120
goto *描画
*道
r=120:g=120:b=120
goto *描画
*木
r=230:g=180:b=130
goto *描画
*石
bunkatu=8//2,4,8,16…
color 0,0,0
repeat bunkatu+1
cnt1=cnt
repeat bunkatu
color rnd(30)+30,rnd(30)+30,rnd(30)+30
line sx/bunkatu/2*(cnt1\2)+sx/bunkatu*cnt,sx/bunkatu*cnt1,sx/bunkatu/2*(cnt1\2)+sx/bunkatu*cnt,sx/bunkatu*(cnt1+1)
loop
line 0,cnt*sx/bunkatu,sy,cnt*sx/bunkatu
loop
stop
*桜
gmode 2,20,20
repeat 20//花びらの数
pos rnd(sx),rnd(sy)
grotate 1,0,0,rnd(628)/100,20,20
await 0
loop
stop
*雲
// カラーパターン(薄い水色、水色、空色、薄い灰色、灰色)
patern_r = 128, 96, 64, 32, 255;
patern_g = 255, 255, 255, 255, 255;
patern_b = 255, 255, 255, 255, 255;
pnum = 5; // カラーパターンの数
block = 32; // ブロックサイズ
repeat 6
title "処理中 block="+block+"";
pidx = cnt;
redraw 0;
repeat sx / block
x = cnt * block;
av_r = 0;
av_g = 0;
av_b = 0;
repeat sy / block
y = cnt * block;
if( pidx == 0 ) { // 最初はカラーパターンの色で大まかに塗り潰す
cidx = rnd(pnum);
color patern_r(cidx), patern_g(cidx), patern_b(cidx);
boxf x, y, x + block - 1, y + block - 1;
}
else { // 2回目以降はブロックサイズを半分にして周囲の色の平均値で塗り潰す
// 左のブロックの色を取得
if( x - 1 < 0 ) {
nx = ginfo_winx - 1; // 一番左端のブロックだった場合は右端の座標にする
}
else {
nx = x - 1; // 1ブロック左の座標を取得
}
ny = y;
pget nx, ny;
av_r = ginfo_r;
av_g = ginfo_g;
av_b = ginfo_b;
// 上のブロックの色を取得
if( y - 1 < 0 ) {
ny = ginfo_winy - 1; // 一番上端のブロックだった場合は下端の座標にする
}
else {
ny = y - 1; // 1ブロック上の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 右のブロックの色を取得
if( x + block > ginfo_winx - 1 ) {
nx = 0; // 一番右端のブロックだった場合は左端の座標にする
}
else {
nx = x + block; // 1ブロック右の座標を取得
}
ny = y;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 下のブロックの色を取得
if( y + block > ginfo_winy - 1 ) {
ny = 0; // 一番下端のブロックだった場合は上端の座標にする
}
else {
ny = y + block; // 1ブロック下の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 周囲4ブロックの色の平均値で塗り潰す
av_r /= 4;
av_g /= 4;
av_b /= 4;
color av_r, av_g, av_b;
boxf x, y, x + block - 1, y + block - 1;
}
loop
loop
block /= 2; // ブロックサイズを半分にして次のループへ
redraw 1;
await 1000;
loop
stop
*描画
baratuki=30
randomize
color r,g,b
boxf
repeat 3000
x=rnd(sx):xx=x+rnd(4)
y=rnd(sy):yy=y+rnd(4)
color r-rnd(baratuki),g-rnd(baratuki),b-rnd(baratuki)
boxf x,y,xx,yy
loop

| |
|
2020/7/6(Mon) 17:02:05|NO.90921
>木目調
基本的な流れとして
色は違いますが最初は雲と同じ処理です。
雲の模様を縦か横に引き伸ばして木目に見えるようにし
そのあとは色調を調節して年輪のような模様を作ります。
という感じの事をやってみました。
screen 0, 256, 256, 0, 0, 0;
color 255, 128, 0: boxf; // 明るめの木の色で塗り潰しておく
randomize;
title "処理中";
screen 1, 256, 256, 0, 300, 0;
// カラーパターン(薄い水色、水色、空色、薄い灰色、灰色)
patern_r = 0, 32, 64, 96, 128, 160, 192, 224, 255;
patern_g = 0, 32, 64, 96, 128, 160, 192, 224, 255;
patern_b = 0, 32, 64, 96, 128, 160, 192, 224, 255;
pnum = 9; // カラーパターンの数
block = 32; // ブロックサイズ
repeat 6
pidx = cnt;
redraw 0;
repeat ginfo_winx / block
x = cnt * block;
av_r = 0;
av_g = 0;
av_b = 0;
repeat ginfo_winy / block
y = cnt * block;
if( pidx == 0 ) { // 最初はカラーパターンの色で大まかに塗り潰す
cidx = rnd(pnum);
color patern_r(cidx), patern_g(cidx), patern_b(cidx);
boxf x, y, x + block - 1, y + block - 1;
}
else { // 2回目以降はブロックサイズを半分にして周囲の色の平均値で塗り潰す
// 左のブロックの色を取得
if( x - 1 < 0 ) {
nx = ginfo_winx - 1; // 一番左端のブロックだった場合は右端の座標にする
}
else {
nx = x - 1; // 1ブロック左の座標を取得
}
ny = y;
pget nx, ny;
av_r = ginfo_r;
av_g = ginfo_g;
av_b = ginfo_b;
// 上のブロックの色を取得
if( y - 1 < 0 ) {
ny = ginfo_winy - 1; // 一番上端のブロックだった場合は下端の座標にする
}
else {
ny = y - 1; // 1ブロック上の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 右のブロックの色を取得
if( x + block > ginfo_winx - 1 ) {
nx = 0; // 一番右端のブロックだった場合は左端の座標にする
}
else {
nx = x + block; // 1ブロック右の座標を取得
}
ny = y;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 下のブロックの色を取得
if( y + block > ginfo_winy - 1 ) {
ny = 0; // 一番下端のブロックだった場合は上端の座標にする
}
else {
ny = y + block; // 1ブロック下の座標を取得
}
nx = x;
pget nx, ny;
av_r += ginfo_r;
av_g += ginfo_g;
av_b += ginfo_b;
// 周囲4ブロックの色の平均値で塗り潰す
av_r /= 4;
av_g /= 4;
av_b /= 4;
color av_r, av_g, av_b;
boxf x, y, x + block - 1, y + block - 1;
}
loop
loop
block /= 2; // ブロックサイズを半分にして次のループへ
redraw 1;
loop
// 10倍横長で拡大コピー
screen 2, 256, 256, 0, 600, 0;
gzoom 256*10, 256, 1, 0, 0, 256, 256, 1;
// 色調を少し単純化して年輪ぽくする
repeat ginfo_winx
x = cnt;
repeat ginfo_winy
y = cnt;
pget x, y;
av_r = ginfo_r / 8 * 8;
av_g = ginfo_g / 8 * 8;
av_b = ginfo_b / 8 * 8;
color av_r, av_g, av_b;
pset x, y;
loop
loop
// 元の画面に50%くらいで減算コピー
gsel 0, 1;
gmode 6,,,128;
gcopy 2, 0, 0, 256, 256;
// 以下蛇足
// ノイズを入れて少しだけ質感を出す
gsel 1, 1;
color 0, 0, 0: boxf;
repeat 1500
x = rnd(ginfo_winx);
y = rnd(ginfo_winy);
color 32, 32, 32: pset x, y; // 薄い黒点
color 16, 16, 16: pset x-1, y: pset x+1, y: pset x, y-1: pset x, y+1; // ぼかし用に更に薄い黒点を周囲に配置
loop
// 元の画面に25%くらいで減算コピー
gsel 0, 1;
gmode 6,,,64;
gcopy 1, 0, 0, 256, 256;
title "処理完了";
途中の加工用で使っているscreen 1と2は経過を分かりやすくしただけなので
不要ならばbufferに変更してください。
本当はもっとぼかしやシャープネスを多用したり
輪郭の抽出などがあるとリアルになるのですが...
これだけでも結構な処理時間がかかるので
簡易な方法にさせていただきました。

| |
|
2020/7/6(Mon) 23:30:19|NO.90924
パーリンノイズを使えば雲も波も木目もリアルに作れるなと思い
とりあえず少し簡単なバリューノイズを作ってみたのですが
処理に時間がかかるようです。
一応公開してみますが処理が遅いので参考になるかどうか。
#module test
#defcfunc fract double d
return d-int(d)
#defcfunc random double x,double y
return fract(sin(12.9898*x+78.233*y)*43758.5453)
#defcfunc animation double f
return sin(f * 6.283 + u_anim * 2.0)*0.5+0.5
#defcfunc whitenoise int x,int y
return animation(random(x,y))
#defcfunc inter double f
return f * f * f * (f * (6.0 * f - 15.0) + 10.0)
#defcfunc mix double d1,double d2,double d3
return d1*(1.0-d3)+d2*d3
#defcfunc valuenoise double u,double v
i_u = int(u*8)
i_v = int(v*8)
f_u = fract(u*8)
f_v = fract(v*8)
f1 = animation(random(i_u,i_v))
f2 = animation(random(i_u+1,i_v))
f3 = animation(random(i_u,i_v+1))
f4 = animation(random(i_u+1,i_v+1))
return mix(mix(f1,f2,inter(f_u)),mix(f3,f4,inter(f_u)),inter(f_v))
#defcfunc octavev double u,double v
a=1.0
f=1.0
maxvalue=0.0
totalvalue=0.0
per=0.5
repeat 5
totalvalue += a*valuenoise(u*f,v*f)
maxvalue+=a
a*=per
f*=2.0
loop
return totalvalue/maxvalue
#global
repeat 640
x=1.0*cnt/640
repeat 480
y=1.0*cnt/480
color octavev(x,y)*255,octavev(x,y)*255,octavev(x,y)*255
boxf x*640,y*480,x*640+1,y*480+1
loop
loop
処理が遅いですが十分雲っぽい表現ができていると思います。
波や木目調も上記の応用で出来るはず。

| |
|
2020/7/7(Tue) 12:02:40|NO.90925
追加のご回答ありがとうございます。
無知な私目にご教示頂き感謝します。
お二方の手法ですが、これはどちらも
同じ事をされているのでしょうか。
kanamaruさんは関数を用いられて、
あらやさんのものは画像からアプローチされている
との認識になりますでしょうか。
すみません、的外れなことを
申しているかもしれません。
あと大変恐れ入りますが、
kanamaruさんのサンプルの関数について
簡易な説明をいただくことは出来ませんでしょうか。
fractは少数分離、randomは疑似ランダム値ですよね、
animationはサイン波…?
もうこのあたりで分からなくなり、interでいよいよ総崩壊します。
手がかりのヒント頂ければgoogle先生に聞きますので…
|
|
2020/7/7(Tue) 12:51:57|NO.90926
正直に言うと僕も理解はしていません。
とあるサイトにあったシェーダー言語やc言語(もしかしたらC++かもしれません)のプログラムをhspに移植しただけです。
ほとんどの部分は
https://yrlab.zatunen.com/webgl/noise/noise.html
を移植して、fBmはうまく実装できなかったので
https://qiita.com/keny30827/items/f4e29a4a90779cf94da6
を参考にしました。
バリューノイズやパーリンノイズについて調べてみれば理解が進むかもしれません。
わかっていることだけ言うと、
animation関数は無視しても大丈夫です。アニメーションさせなければ理解させなくても影響はないと思います。
試してないですがu_animを1ずつ変化させてからノイズを再生成すれば
ノイズがアニメーションすると思います。
(処理が遅くて無理だとは思いますが。)
以下は僕の理解です。間違っているかもしれません
正方形を考えます。対象の座標を内部に持ちます。
その四つの頂点に対してホワイトノイズを生成します。
その後、正方形の中のどこに座標かあるかで割合を決めて、
(厳密にはuv座標というのを使っています。cntを640や480で割っているのはそれが理由です。)
その割合を使って縦と横に補間を行うといった流れだと思います。
|
|
2020/7/7(Tue) 17:48:59|NO.90931
ご説明&URLありがとうございます。
用語を知らず読んでしまいましたので
アタマが何度もフリーズしました。
interはパーリンさんが考えた
素晴らしい補間関数なのですね
randomはランダム風のテーブルで
これを補完する、0〜1の範囲で構成された
バリューノイズのグラフ関数を作り、
その値を描画域に反映させる……
大まかにこんな感じで良いのでしょうか。。。
もうお腹いっぱいです…
|
|