HSPで画像の一部だけを表示したいときは基本的にはgcopy
命令ですが、もっと高度な切り取りをするならgsquare
命令です。長方形以外の切り方ができる上に、同時に様々な変形を施すことができます。ただ、ちょっと使い方がややこしかったのでメモ。
リファレンスにはどう書いてるの
冒頭部分では
任意の四角形を描画
gsquare p1,p2,p3,p4,p5
p1=0~(0) : コピー元のウィンドウID (マイナス値ならば塗りつぶし)
p2=変数名 : コピー先X座標が格納される数値型配列変数名
p3=変数名 : コピー先Y座標が格納される数値型配列変数名
p4=変数名 : コピー元X座標が格納される数値型配列変数名
p5=変数名 : コピー元Y座標が格納される数値型配列変数名解説
任意の4点を持つ四角形をコピーまたは塗りつぶします。
p1で、画像コピー元のウィンドウIDを指定します。p2,p3にはコピー先の座標4つを配列に格納した変数を指定します。
p4,p5にはコピー元の座標4つを配列に格納した変数を指定します。
配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。
とあります。
どういうことか
この命令では、
- まずp4, p5の説明より 画像を四角形であればいかなる形にも切り取ることができます。
- さらに、p2, p3の説明より 切り取ってできた図形を変形して描画する機能まで備わっています。
かなりいろいろできそうです。
つかいかた
- 切り取り対象の画像を読み込む
- コピー先(描画範囲)の座標を決める
- その座標をX, Yごとに配列化しておく
- コピー元(切り取り範囲)についても同様にする
-
gSquare
命令で描画する
切り取り対象の画像を読み込む
使われる画像は一度別のバッファに読みこまれていなければなりません。
celload
命令
もしくは
buffer
命令からのpicload
命令
を使って、画像を読み込みましょう。
celload "Origin.png", 1 //ウィンドウIDは適当でおk
OR
buffer 1 //ウィンドウIDは適当でおk
picload "Origin.png"
コピー先の座標を決める・その座標をX, Yごとに配列化しておく
ややこしいのはここです。
コピー先の長方形の頂点4つのX座標、Y座標ごとに4要素の配列(座標配列と呼びましょう)を用意して引数として渡さなければならないのですが、
リファレンスには
配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。
とあります。座標配列の中身はこの順番でないと意図した動きをしません(違う順番にした時の動きは実例を参照してください)。左上から、時計回りに格納しましょう1。(図を参照)
また、配列は整数のみです。ddim
で宣言した配列では落ちます。
上の図の例でいけば、コードは以下のようになります。
dim copyToX, 4
dim copyToY, 4
//ddim copyToX, 4 //ERROR: 実数不可!アニメーションさせたい等の理由で実数計算をした後はint()で囲うべし
//X座標について設定
copyToX(0) = a //copyToX.0 = aも可
copyToX(1) = c
copyToX(2) = e
copyToX(3) = g
//Y座標について設定
copyToY(0) = b
copyToY(1) = d
copyToY(2) = f
copyToY(3) = h
コピー元も同様にする
座標の与え方はコピー先と同様です。X座標、Y座標ともに配列を用意し格納します。
dim copyFromX, 4
dim copyFromY, 4
//後はコピー先の設定と同様
ちなみにコピー元の指定は省略できません。もしウィンドウ全体を描画の対象にしたい(つまり変形のみ行いたい)ときは、画像を読み込む際に以下のようにgsel
命令で描画対象を移動して、
gsel 1 //描画対象の画像の入っているウィンドウIDに切り替え
copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0
copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY
gsel 0 //戻すのを忘れずに
とやればいいでしょう。
gsquare
命令を実行
あとはgSquare
命令を打つだけです。順番を間違えないようにしましょう(buffer
命令を使用して読み込んだ場合はgsel 0
を忘れずに)。
gsquare 1, copyToX, copyToY, copyFromX, copyFromY
ウィンドウID, コピー先X座標、コピー先Y座標、コピー元X座標、コピー元Y座標 の順番です。
これで切り取り・変形の加えられた画像が描画されます。描画は、gmode
命令の影響を受けます23。
実例
画像を切り取って表示したい
コピー元の座標を切り取る範囲にしましょう。コピー先は、その切り取った範囲と全く同じ形の四角形になるように設定します45。
以下の例では、コピー元から台形状に画像を切り出して描画しています。画像は次のものを使います。名前はOrigin.png
です。
screen 0, 640, 480
cls 4
celload "Origin.png", 1
dim copyToX, 4
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4
//コピー元
//X座標について設定
copyFromX(0) = 20
copyFromX(1) = 130
copyFromX(2) = 130
copyFromX(3) = 20
//Y座標について設定
copyFromY(0) = 60
copyFromY(1) = 40
copyFromY(2) = 110
copyFromY(3) = 90
//コピー先(形が同じになるように注意して)
//X座標について設定
copyToX(0) = 0
copyToX(1) = 110
copyToX(2) = 110
copyToX(3) = 0
//Y座標について設定
copyToY(0) = 20
copyToY(1) = 0
copyToY(2) = 70
copyToY(3) = 50
gsquare 1, copyToX, copyToY, copyFromX, copyFromY
画像を変形したい
コピー先の座標を変えましょう。拡大・縮小もできます。
以下の例では、画像の切り取りは行わず、輪郭が先ほどの例の出力と同じ形になるように画像を変形させています。
screen 0, 640, 480
celload "Origin.png", 1
cls 4
dim copyToX, 4
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4
//コピー元
gsel 1 //描画対象のウィンドウIDを指定する
copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0
copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY
gsel 0 //戻すのを忘れずに
//コピー先
//X座標について設定
copyToX(0) = 0
copyToX(1) = 110
copyToX(2) = 110
copyToX(3) = 0
//Y座標について設定
copyToY(0) = 20
copyToY(1) = 0
copyToY(2) = 70
copyToY(3) = 50
gsquare 1, copyToX, copyToY, copyFromX, copyFromY
回転・反転もできちゃう
リファレンスには
配列変数には、左上(0),右上(1),右下(2),左下(3) の順番に座標を入れておく必要があります。
とありましたが、
この座標配列の中身を、1つずつ前(もしくは後ろ)にシフトするなどしてその順番を狂わせると、画像が回転・反転されて描画されます6。
screen 0, 640, 480
cls 4
celload "Origin.png", 1
dim copyToX, 4
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4
//コピー元
gsel 1 //描画対象のウィンドウIDを指定する
copyFromX(0) = 0
copyFromX(1) = ginfo_winX
copyFromX(2) = ginfo_winX
copyFromX(3) = 0
copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY
gsel 0 //戻すのを忘れずに
//コピー先
//X座標について設定
copyToX(0) = 150
copyToX(1) = 150
copyToX(2) = 0
copyToX(3) = 0
//Y座標について設定
copyToY(0) = 0
copyToY(1) = 150
copyToY(2) = 150
copyToY(3) = 0
gsquare 1, copyToX, copyToY, copyFromX, copyFromY
ただし、gSquare
命令は回転に対してはあまり実用的ではありません。
回転を行うならば、専用の命令gRotate
命令が存在しています。この命令は回転のない長方形の切り抜きにも対応しているため、そういう場合はそっちを使いましょう。もし回転のある長方形や長方形以外を切り取ったあとに回転したい場合は、gSquare
命令のみを使ってゴリゴリやることもできることにはできますが、例えば
- 別のウィンドウIDを初期化
- そこに
gSquare
で切り取った図形をそのまま描き込む - そのウィンドウ全体を
gRotate
命令で回転して描画
という処理をしたほうが現実的です。
反転処理に関しては(何もinclude
しない場合は)この命令が最適のようです。もし反転処理でもっと簡単な手がありましたらコメント・編集リクエストで指摘お願いします。
三角形に切る?!?
切り取り位置が自由に設定できるということは、
4点のうち2点を同一の点にすれば、三角形に切り抜けるんじゃね?
そこで実験してみました。画像は先ほどと同じものを使います。
うまくいけば、元の画像を右上から対角線で切ったとき下側に来る半分が描画されるはずです。
実験用コード
screen 0, 640, 480
cls 4
celload "Origin.png", 1
dim copyToX, 4
dim copyToY, 4
dim copyFromX, 4
dim copyFromY, 4
//コピー元
gsel 1 //描画対象のウィンドウIDを指定する
/* コピー元の座標指定の1番目と2番目が同じ点を示しています。
* 右下に頂角を持つ直角二等辺三角形になるはず...
*/
copyFromX(0) = 0
copyFromX(1) = 0
copyFromX(2) = ginfo_winX
copyFromX(3) = 0
copyFromY(0) = 0
copyFromY(1) = 0
copyFromY(2) = ginfo_winY
copyFromY(3) = ginfo_winY
gsel 0 //戻すのを忘れずに
//コピー先
//X座標について設定
copyToX(0) = 0
copyToX(1) = 0
copyToX(2) = 150
copyToX(3) = 0
//Y座標について設定
copyToY(0) = 0
copyToY(1) = 0
copyToY(2) = 150
copyToY(3) = 150
gsquare 1, copyToX, copyToY, copyFromX, copyFromY
結果
完 全 勝 利
まとめ
-
gSquare
命令は、回転のない長方形に限らず、四角形全て・果てには三角形状に任意の画像を切り取ることが可能な命令。 - 画像を切り取るだけでなく、変形処理もできる。切り取ってからの変形(回転・反転を含む)も許されている。
- その自由度から、切り取り範囲・描画範囲はどんな形であれ4つの点すべてについて必ず指定しなければならない。
- 回転のない長方形に切りたいときは
gcopy
命令を、回転のない長方形の範囲を回転させて描画したい場合はgRotate
命令を使おう。
-
特に、コピー先やコピー元が回転のない長方形のときに、(回転のない長方形は対角上の2点を与えれば確定するため)X座標(Y座標)の配列には左右(上下)の位置2個だけを格納していれば良いと考えがちですが、それを実行すると妙なものが描画されてしまいます。この命令はかなり自由度が高く、コピー元もコピー先も四角形ならどんな図形でも切り取り変形して描画できるという仕様になっているため、長方形であれ、4つの頂点すべてについて格納しなければなりません(だから回転のない長方形を切り取るときには
gcopy
を使ったほうがいいのです)。もし各々の座標配列に2つの数値を入れるという仕様なら、コピー先やコピー元が正方形や長方形・ひし形以外の四角形になることができません。 ↩ -
ただしアルファブレンド(
gmode 7
)は効きません。 ↩ -
コピー元とコピー先で画面モードが違う(パレットとフルカラー)と落ちるので注意しましょう。 ↩
-
長方形以外の形に切った時でも難しくありません。各頂点を時計回りする際に、前の頂点との座標の差が同じになるようにすればいいのです。 ↩
-
回転のない長方形に切るなら
gcopy
命令を使いましょう。その方が楽です。 ↩ -
変に狂わせると描画範囲がねじれたり妙なものが描画されたりしますのでご注意を。 ↩