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


HSPTV!掲示板


未解決 解決 停止 削除要請

2020
0603
とあるプログラマ2D UI (GUIウィジェット) の作成について2解決


とあるプログラマ

リンク

2020/6/3(Wed) 22:46:24|NO.90686

HSPでゲームを作っている人などにお聞きしたいのですが、メニューなどの2DなUIをどう作成しているでしょうか。


現在私はHSP3でツールソフト(ゲームではなくてメモ帳やMSペイントのような、いわゆる作業ソフト)を製作していますが、どうしてもHSP標準やWindowsコモンコントロールといった既存のコントロールではなく、独自のコントロールを新規に作る必要があります。
しかしHSP3にはクラス継承といった機能もありませんし完全にゼロから作る必要がありますが、これらをどうやって作っていくかというのが現在悩んでいる課題です。

HSPコンテスト等の作品を拝見するとゲームなどは特に"独自のUI"を持っているのが分かります。なのでこれらをどうやって作成・描画しているかを知りたいのです。


具体的に現在私が考えてる方法は、

A)
子ウィンドウを複数作成しコントロールオブジェクトごとに割り当てて描画する。描画はGDIまたはGDI+を使用。ボタンやつまみなど1オブジェクトの中でも部品ごとに別のウィンドウを作成する。

B)
GDI+(A2D)でオフスクリーンバッファに描画する。描画したものを画面に貼り付ける。

の2種なのですが、それぞれメリット・デメリットがあり

A)
子ウィンドウごとで処理できるのでクリック判定や移動(ドラッグ処理)が楽。
しかしウィンドウをまたぐ描画方法がないので、オブジェクト上にダイアログのようなオーバーレイ表示をすることが不可。
子ウィンドウのアクションからオブジェクトのIDを識別するためにウィンドウIDまたはウィンドウハンドルをrepeat等でいちいち比較する必要がある。

B)
描画されたものはウィンドウ自体に貼り付けられるので、ダイアログのようなオーバーレイな表示ができる。
描画されたものはすべて同じ「描画されたもの」なのでクリック判定が難しい。ボタンならまだしもトラックバーのようなクリック位置をピンポイントで知る必要があるオブジェクトは非常に厳しい。
「オブジェクト」という個々の存在が薄く、処理も個別で独立するには難がある。

といった具合です。



そもそも「コモンコントロールを使わない」という時点でかなりの苦行な気もしますが、目的の動作をコモンコントロールだと行えない・継承もできない となるとこのような方法しかないと思います…(オーナー/カスタムドローというわけでもないし)

説明が下手くそなので恐らく伝わらない部分も多いと思いますが、「ゲームはこのようにしてUIを描画してるよ!」や「自分はこういう方法で作ったことあるよ!」くらいのことでもよいのでご教授いただければ幸いです…


追伸
HSP3でQt使える方法があれば教えていただけると助かります。



この記事に返信する


MIZUSHIKI

リンク

2020/6/6(Sat) 22:02:43|NO.90708

>HSPでゲームを作っている人などにお聞きしたいのですが、メニューなどの2DなUIをどう作成しているでしょうか。

私もまったくの門外漢なのですが、どなたも回答されないので自作モジュールの宣伝も込めてコメントします。

(一般的な方法でない独自な手法であることをお許しください。。。)

>A)
>子ウィンドウを複数作成しコントロールオブジェクトごとに割り当てて描画する。描画はGDIまたはGDI+を使用。ボタンやつまみなど1オブジェクトの中でも部品ごとに別のウィンドウを作成する。

A)の方法で紹介させて頂きます。

>ウィンドウをまたぐ描画方法
>オブジェクト上にダイアログのようなオーバーレイ表示

a2d+AlphaLayer.hspモジュール を利用することでアルファ値付き半透明子ウィンドウを作成できます。
これを利用してオブジェクトを描画します。
また、最前面のレイヤーにオーバーレイしたいものを描けば子ウィンドウをまたぐ描画ができます。


リンクからモジュールをダウンロードしてください。
http://suwa.pupu.jp/HSP/index.html
(a2d+AlphaLayer/mod_TimerRepeat モジュール)

以下サンプルですが、
オブジェクトの再利用性や複数使用時のことは考えられてません。。。
★動作状況の動画を撮りました。
 http://suwa.pupu.jp/data/object-sample.mp4

#include "a2d+AlphaLayer.hsp" #include "mod_TimerRepeat.hsp" ; スライダーの設定値を簡単に取得するため利用 // // スライダー // // 横棒 alCreateImage 0, 300,30 ; 仮想イメージ(ID 0) alColor 0, 0, 0, 1 alFillRect ; 薄膜貼っとかないと円の上端と下端がクリック反応しない(アルファ値0だと無反応) alColor 200, 200, 200, 255 alFillRect 15, alGetHeight()/2-5, alGetWidth()-30, 10 //とりあえず非表示で張り付けてしまう。(子ウィンドウを乗せていくため) alalSetParent 0,,1, 100,100, *dummy ; 子ウィンドウにクリック判定を付けるため親もコールバック設定する必要あり(ダミー) // 丸 alCreateImage 1, 30,30 ; 仮想イメージ(ID 1) alColor 255, 64, 64, 255 alFillEllip 0, 0, alGetWidth()-1, alGetHeight()-1 alalSetParent 1,0,, 135,0, *click ; 仮想イメージ(ID 0)の子ウィンドウとする。さらにクリック判定のためのコールバックをセット。 // ここでスライダーを表示 alalShow 0 // // 前面レイヤー(オーバーレイ表示) : ボールをウィンドウ内でバウンドさせる // alCreateImage 2,ginfo_sx,ginfo_sy ; 仮想イメージ(ID 2) alColor 100,100,255,125 alalSetParent 2 alalZtop 2 goto *OJAMA stop *click switch iparam case 0x0201 ;WM_LBUTTONDOWN alalGetRect 1, rect ; アルファレイヤー(ID 1)の位置を取得 ret = 1.0/270*(rect(0)) mes "スライダー値: "+ret // スライダーの値を簡単に取得するため timer_repeat を使用。 timer_repeat 50 alalGetRect 0, uniq(rect0),-1 ; アルファレイヤー(ID 0)の位置を取得(p3=-1でスクリーン座標) uniq(x) = ginfo_mx - uniq(rect0)(0)-15 ; timer_repeat内ではuniq()でユニークな変数を定義できる。 if uniq(x)<0 :uniq(x)=0 if uniq(x)>270 :uniq(x)=270 alalWidth 1, ,,uniq(x) ; スライダーの●の位置を変更 alalGetRect 1, uniq(rect) ; アルファレイヤー(ID 1)の位置を取得 uniq(ret) = 1.0/270*(uniq(rect)(0)) title "スライダー値: "+uniq(ret) alColor 100,100,255,uniq(ret)*255 ; スライダーの値に合わせて ball の透明度を変更 // クリックを離していたら timer_repeat を終了させる。 getkey uniq(clk),1 if uniq(clk) == 0 :timer_break timer_deinit: mes "スライダー値: "+1.0/270*(uniq(rect)(0)) timer_loop swbreak swend return *dummy return // // オブジェクト(スライダー)の前面と背面にオジャマ描画 // *OJAMA bpx=5 : bpy=5 ; ボール用初期値 repeat // line color rnd(100)+155,rnd(100)+155,rnd(100)+155 a = rnd(ginfo_sx+ginfo_sy) cxy = ginfo_cx, ginfo_cy line a(0)*(a(0)<ginfo_sx), (a(0)-ginfo_sx)*(a(0)>=ginfo_sx), ginfo_sx, ginfo_sy pos cxy(0),cxy(1) // ball blx=blx+bpx : if blx<=0 || blx>=ginfo_sx-100 : bpx=-bpx bly=bly+bpy : if bly<=0 || bly>=ginfo_sy-100 : bpy=-bpy alErase alFillEllip blx,bly, 100,100 alalRedraw 2 ; アルファレイヤー再描画 color await 32 if cxy(1)>ginfo_sy-100 : break loop color 255,0,0 mes "OJAMA STOP!!" stop
(対応OS : Windows 8 以降)

結構細かな注意点がありますが、コメントアウト部分を読んでご理解願います。
a2d+AlphaLayer.hsp、mod_TimerRepeat.hsp の使い方は同梱のヘルプを参照してください。



とあるプログラマ

リンク

2020/6/10(Wed) 23:22:11|NO.90737

なるほど、こんなモジュールもあるんですね。(HSP3の未知のモジュールはまだまだあるので どこかにまとめて掲載してほしい…)

パッと見ですが、結構便利そうなモジュールですね。
少し詳しく見ていきたいと思います。

MIZUSHIKIさん、回答ありがとうございます。



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