HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0705
ああもんど背景などのテクスチャ画像をコードで描画したい10解決


ああもんど

リンク

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



この記事に返信する


kanamaru

リンク

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で適度な大きさで描画して
横幅を半分にするなどして花びらに近い形に変形し
それを回転コピーしながら配置すればそれっぽく見えるかもしれません。



kanamaru

リンク

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に変更してください。

本当はもっとぼかしやシャープネスを多用したり
輪郭の抽出などがあるとリアルになるのですが...
これだけでも結構な処理時間がかかるので
簡易な方法にさせていただきました。



kanamaru

リンク

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先生に聞きますので…



kanamaru

リンク

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の範囲で構成された
バリューノイズのグラフ関数を作り、
その値を描画域に反映させる……

大まかにこんな感じで良いのでしょうか。。。
もうお腹いっぱいです…



ONION software Copyright 1997-2023(c) All rights reserved.