GitHub人狼 -- みんなでプログラムを書いてカジュアルに遊びたい!

目的

本記事の目的は,みんなでプログラムを書いてカジュアルに遊ぶためのパーティゲームGitHub人狼」を提案することです. 以下では,このゲームの遊び方,提案の背景,期待する効果,懸念点について説明します.

遊び方

ゲームの概要

GitHub人狼」は,ソフトウェア開発プラットフォーム「GitHub」を利用するゲームです.開発チームに紛れ込んだ「人狼」の妨害を回避しながら「村人」達が成果物を完成させることを目指します.

  • 参加人数:3人以上
  • 所要時間:2時間以上

勝利条件

「村人」と「人狼」の勝利条件を以下に示します.

  • 村人の勝利条件は,開発するべき成果物の「仕様」が定義されており,かつ,以下が全て満たされることです.

    1. 最終的な成果物が実行可能である.
    2. 定義した全ての仕様が実装されている.
  • 人狼の勝利条件は,開発するべき成果物の「仕様」が定義されており,かつ,以下のどちらかが満たされることです.

    1. 最終的な成果物が実行可能でない.
    2. 定義した仕様のうち実装されていないものがある.

勝利条件が満たされない場合またはルール違反をした場合には敗北となります.

ゲームの流れ

ゲームは以下の流れで進行します.

  1. 仕様定義
  2. リポジトリ作成
  3. ロール決定
  4. 開発
  5. 成果発表
仕様定義

開発チーム内で相談し,開発するべき成果物の「仕様」を定義します. 仕様は,成果物に実装するべき動作についてスライドなどにまとめます. 仕様定義に割くことのできる時間は,あらかじめ決めておきます.

リポジトリ作成

GitHub上で開発チームのリポジトリを作成し,メンバーはそれぞれフォークして開発環境を整えます.

ロール決定

開発チームを構成するメンバーそれぞれのロールを決定します. ロールは「村人」と「人狼」のどちらか1つをランダムに割り当てます. ただし,村人の人数が過半数以上となるようにします.

開発

村人は定義した仕様を満たすプログラムの実装を進め,人狼はこれを妨害します. 具体的には,以下の手順を繰り返します.

  1. 開発チームのメンバーはそれぞれプログラムを書く.
  2. プログラムを書いたメンバーはプルリクエストを送る.
  3. プルリクエストに対し,メンバーはマージするかどうかについて匿名で投票する.
  4. 投票でマージの得票数が過半数以上になった時,プルリクエストをマージする.

開発に割くことのできる時間は,あらかじめ決めておきます.

成果物発表

開発チームのメンバーは互いにロールを公開し,成果物発表を行って勝利条件を確認して勝敗を決定します. 成果物発表では,村人は成果物発表を行い,成果物が実行可能であることおよび全ての仕様が満たされていることを示します. 人狼は,成果物が実行可能ではないことまたは満たされていない仕様があることを指摘します.

オプショナルルール

  • 人数に余裕がある場合はゲームマスターがいても良いです.ゲームマスターは,時間管理,ロール決定,票の収集,過半数の得票があったプルリクエストのマージ,勝利条件の確認を行います.
  • 全ての人狼が合意した場合,投了した上で開発に協力することができます.この場合,村人は勝利となり,人狼は敗北となります.
  • GitHubを利用するのではなく,GitBucket,GiteaまたはGogsなどを利用しても良いです.

提案の背景

私は,自分が所属するプログラミングサークルにおいて,以下のような部員同士の交流に関する問題を解決し,プログラミングに触れながらカジュアルに交流したいと考えていました.

  • プログラミング:それぞれの興味がバラバラで個人プレーになりがちである.
  • 勉強会:コミュニケーションが一方的になりがちで,なかなか盛り上がらない.
  • チーム開発,ハッカソン競技プログラミング:ハードルが高く,カジュアルじゃない.
  • 麻雀,人狼,AmongUsなどのパーティゲーム:交流はできるが,そもそもプログラムを書かない.

そして,共同開発に人狼やAmongUsのような駆け引き要素を取り入れることはできないかと考えた結果,上の「GitHub人狼」を思い付きました.

期待する効果

GitHub人狼」で遊ぶことにより,以下の効果が期待できると思います.

  • プログラミングを通してカジュアルに交流できる.
  • プログラミングをパーティゲームとして楽しめる.
  • スキルに差があってもゲームとして成り立つ.
  • 共同開発っぽい体験ができる.
  • プログラミングとGitの練習ができる.

懸念点

以下の懸念点が挙げられます.

  • プログラミングとGitの基本スキルが必要となる.
  • 仕様が曖昧だと勝敗も曖昧になってしまう.
  • 現状ではテストプレイが不十分である.

遊んでみた感想

遊んでみてから書きます.

新入生向けプログラミングハンズオン

目的

本記事は SAMIT Online! 21.04 で行われた発表「新入生向けプログラミングハンズオン 準備」,「新入生向けプログラミングハンズオン」の資料です.

本記事のターゲットは,プログラムを書いたことはないがプログラミングに興味を持っている新入生です. 本記事の目的はそのような新入生がプログラミングを勉強するモチベーションを維持できるようになることです. 本記事は,「自分の手でプログラムを書き,それが動作することを実感する」という体験が勉強のためのモチベーションの維持に繋がるという考えに基づき,新入生にそのような体験してもらうためのハンズオンの資料を提供します.

本記事のハンズオンでは,

  • 新入生がプログラミングの楽しさを知る前に躓くことがないようにすること,
  • プログラミングを勉強を始めるきっかけになる楽しい体験となること

を意識し,以下の4つの条件を満たすようなハンズオンを用意しました.

  • 環境構築の手間をできるだけかけないこと
  • 作成するプログラムの規模が大き過ぎないこと
  • 作成するプログラムが対話的に動作すること
  • 作成するプログラムがグラフィカルに動作すること

このハンズオンでは,ブラウザ上でプログラムを書いて実行できるサービスであるCodePen( https://codepen.io )を利用し,最終的に,ボタンを押すたびにサイコロが振られ,出た目の画像が表示されるプログラムを作成します.

本記事の後半では,本ハンズオンに挑戦してみた後でプログラミングの勉強を始めてみようと思った新入生のために,おすすめのプログラミング勉強法も示しています.

本記事の最後では,YouTubeで開催されたSAMIT Online! 21.04の様子を示しています.

ハンズオンの準備

ブラウザで https://codepen.io/pen/ を開くとCodePen上で自分のプログラムを作成するページが表示されます.

FireFox上でCodePenのページが表示される.
ブラウザでhttps://codepen.io/pen/にアクセスした様子(HTML編集エリア(上段左部),CSS編集エリア(上段中部),JS編集エリア(上段右部),実行結果エリア(下段))

これで本ハンズオンの準備は完了ですが,作成したプログラムを保存する場合にはCodePenのアカウント登録が必要となります. 必要に応じてアカウント登録を行ってください.

ハンズオン

以下に本ハンズオンで取り組んでもらいたい演習を示します. 各演習はそれぞれ以下のように構成されています.

  1. プログラムと実行結果
  2. 解説
  3. 改造の例

各演習のプログラムは,左側のHTMLまたはHTMLとJSの部分に示されています. 各演習の実行結果は,右側のResultの部分に示されています.

各演習は以下のように進めます.

  1. HTMLの部分に示された内容を前節で準備したCodePenのHTML編集エリアに入力し,JSの部分に示された内容を前節で準備したCodePenのJS編集エリアに入力する.
  2. 実行結果の部分に示された内容と同様の内容が前節で準備したCodePenのResultエリアに表示されることを確認する.
  3. 解説を読んでみる(わからない部分は,読み飛ばしても良いです.).
  4. 改造の例を参考にしつつ,自分なりにプログラムを改造してみる.

演習:HTMLでテキストを表示する

プログラムと実行結果

See the Pen bGgmNzP by Jumpaku (@jumpaku) on CodePen.

解説

HTMLとはWebページなどの画面構成を定義する言語です. HTMLは「要素」(<p>こんにちは</p>など)を組み合わせて記述します. 要素とは「タグ」(<p></p>など)によって挟まれた文字列です. <p></p>で挟まれたp要素は一つの段落を表します. HTMLに記述された内容がブラウザに読み込まれると,ブラウザは読み込んだHTML解釈し,解釈した内容をディスプレイに表示します.

上のプログラムのHTMLではタグ<p>とタグ</p>によって「こんにちは」というテキストを挟んだ<p>こんにちは</p>という要素が記述されています. ブラウザはこのHTMLを解釈し,「こんにちは」というテキストを表示します.

改造の例

「こんにちは」とは別のテキストを表示するように改造してみる.

演習:HTMLでボタンを表示する

プログラムと実行結果

See the Pen display-button by Jumpaku (@jumpaku) on CodePen.

解説

上のプログラムのHTMLでは<p>ボタンの表示</p>というp要素と<button>押しても何も起きない</button>というbutton要素が記述されています. button要素は一つのボタンを表します. ブラウザはこのHTMLを解釈し,「ボタンの表示」というテキストと「押しても何も起きない」と書かれたボタンを表示します.

改造の例
  • ボタンを増やしてみる.
  • HTMLに<strike>取り消し線</strike>を追加してみる.

演習:JavaScriptからHTML上のテキストを設定する

プログラムと実行結果

See the Pen XWpxJLR by Jumpaku (@jumpaku) on CodePen.

解説

JavaScriptとは様々な処理を実行することができる言語です. JavaScriptに記述された内容がブラウザに読み込まれると,ブラウザは読み込んだJavaScriptを解釈し,処理を実行します. JavaScriptを用いることでHTMLに記述された内容を表示することができます.

まず,上のプログラムのHTMLには要素<p id="text"></p>が記述されています. この要素は表示するべき文字列を持っていません. また,この要素はタグにはid="text"が記述されています. このようにタグに付け加えられたものを「属性」と言います. 「属性」は要素に様々な情報を付け加えます. 例えば,id=で始まるid属性は,ある要素に別の要素と区別するための名前を付け加えます.

JavaScriptは上のプログラムのJSの部分に示されています.

let e = document.querySelector("#text");

の部分はeという名前の変数を用意し,そこにHTML上から探し出してきた要素を格納しています. 変数とは値を格納することのできる名前を持った箱のようなものです. 変数を用意するときは,let 変数名 = 変数に格納する値;と記述します. このとき,変数名には大文字または小文字のアルファベットと数字を使って好きな名前をつけることができます. documentはHTMLそのものを表すものです. querySelectordocumentが持っている関数で,指定された要素を探す処理を実行します. 関数とはまとまった処理に名前を付けて繰り返し実行できるようにしたものです. 関数を実行するためには関数の名前の後ろに()を付け,その間に処理に必要なデータを記述します. document.querySelector("#要素のid属性")と記述することで,指定したid属性を持つ要素を探し出すことができます.

e.textContent = "こんにちは";

の部分は変数eが持つtextContentという変数に「こんにちは」という文字列を格納しています. textContentは要素が持つ文字列を表す変数です. 文字列はプログラムの記述と区別するために"で囲む必要があります. これにより,HTMLのp要素は文字列を持たないにも関わらず,実行結果で「こんにちは」と表示させることができるようになります.

改造の例

HTMLはそのままでJavaScriptだけを編集することにより,「こんばんは」と表示するように変更してみる.

演習:ボタンを押された時の処理を実装する

プログラムと実行結果

See the Pen add-process-onclick by Jumpaku (@jumpaku) on CodePen.

解説

このプログラムは,ボタンが押されるたびに,ボタンが押された回数をカウントし,回数を表示します.

HTMLのbutton要素にはonclick=で始まるonclick属性が付け加えられています. onclick属性は押された時に実行するJavaScriptのプログラムを指定することができます. このプログラムではボタンのonclick属性にupdate()と記述されているため,ボタンを押すとupdateという関数が実行されることになります.

update関数はJavaScriptの方で次のように定義されています.

function update() {
  count = count + 1;
  counter.textContent = count;
}

関数の定義は

function 関数の名前(処理に必要なデータ1, 処理に必要なデータ2, ...){
  実行する処理1;
  実行する処理2;
  ・
  ・
  ・
}

と記述します. このとき,関数の名前は変数名と同様につけることができます. このプログラムのupdate関数は以下の処理を実行するように定義されています.

  1. 変数countcount1を加えた数を格納する.
  2. 変数counterが持つ変数textContentに変数countの値を格納する.

以上のようにJavaScriptで定義した関数の実行をbutton要素のonclick属性に記述することで,ボタンを押すたびに指定した処理を実行することができます.

改造の例

2個のボタンを用意し,それぞれのボタンが押された回数の合計を表示するように改造してみる.

演習:乱数を使用する

プログラムと実行結果

See the Pen random-number by Jumpaku (@jumpaku) on CodePen.

解説

このプログラムは,ボタンが押されるたびに,0以上1以下のランダムな実数を表示します. JavaScriptではMath.randomという関数を使用することで,0以上1以下のランダムな実数を生成することができます.

改造の例
  • 生成した乱数に1を足すことで2以上3以下のランダムな実数を表示するように改造してみる.
  • 生成した乱数に100をかけることで0以上100以下のランダムな実数を表示するように改造してみる.ただし,JavaScriptではかけ算は×ではなく*という記号が使用されることに注意してください(例えば,Math.random()×100ではなくMath.random()×100と記述することになります.).

演習:乱数の値に応じて表示するテキストを変更する

プログラムと実行結果

See the Pen display-dice-number by Jumpaku (@jumpaku) on CodePen.

解説

このプログラムは,ボタンが押されるたびに,1以上6以下のランダムな整数を表示します.

このプログラムのdice関数はMath.random()により生成した0以上1以下のランダムな実数を1以上6以下のランダムな整数に変換します.

具体的には以下の条件に応じた処理を実行します.

  • もし変数valueが1.0/6.0未満なら,変数diceValueに1を格納する.
  • 上の条件を満たさず,もし変数valueが1.0/6.0未満なら,変数diceValueに1を格納する.
  • 上の条件を満たさず,もし変数valueが2.0/6.0未満なら,変数diceValueに2を格納する.
  • 上の条件を満たさず,もし変数valueが3.0/6.0未満なら,変数diceValueに3を格納する.
  • 上の条件を満たさず,もし変数valueが4.0/6.0未満なら,変数diceValueに4を格納する.
  • 上の条件を満たさず,もし変数valueが5.0/6.0未満なら,変数diceValueに5を格納する.
  • 上の条件を満たさないなら,変数diceValueに6を格納する.

ただし,JavaScriptでは割り算は÷ではなく/という記号が使用されることに注意してください(例えば,1.0÷6.0ではなく1.0/6.0と記述することになります.).

dice関数はこの処理を,「条件に応じた処理」を記述するため構文を利用して記述されています. 「条件に応じた処理」を記述するため構文を以下に示します.

if (条件式1) {
  条件式1が真の時の処理;
} else if (条件式2) {
  条件式1が偽で条件式2が真の時の処理;
}
・
・
・
 else {
  上の全ての条件式が偽の時の処理;
}
改造の例
  • 1から5まではそれぞれ1/10の確率で表示され,6は5/10の確率で表示されるように改造してみる.
  • 1から10までが等しい確率で表示されるように改造してみる.

演習:HTMLのキャンバスに図形を描画する

プログラムと実行結果

See the Pen render-on-canvas by Jumpaku (@jumpaku) on CodePen.

解説

このプログラムはHTMLのcanvas要素に対して,JavaScriptを使用して長方形や円などの図形の描画処理を実行することで文字だけでなく,図形を表示します.

let ctx = e.getContext("2d");

の部分では,変数eが持つgetContext関数を実行することで2次元の「レンダリングコンテキスト」というもの取得し,これを変数ctxに格納しています. レンダリングコンテキストは,以下に示すような,図形を描画するための様々な関数や変数を持っています.

  • strokeStyleは直後に描画する図形の輪郭の色を格納する変数
  • fillStyle:直後に描画する図形の内部の色を格納する変数
  • strokeRect(左上の点のx座標, 左上の点のy座標, 高さ, 幅):長方形の輪郭を描画する関数
  • fillRect(左上の点のx座標, 左上の点のy座標, 高さ, 幅):長方形の内部を描画する関数
  • beginPath():図形の作成を開始する関数
  • arc(中心のx座標, 中心のy座標, 半径, 0, Math.PI * 2):円を作成する関数
  • stroke()beginPath()で作成を開始した図形の輪郭を描画する関数
  • fill()beginPath()で作成を開始した図形の内部を描画する関数
  • clearRect(左上の点のx座標, 左上の点のy座標, 高さ, 幅):長方形領域に描画されている図形を消去する関数
改造の例
  • 縦長の長方形を表示するように改造してみる.
  • 以下の条件を満たすような円と長方形が表示されるように改造してみる.
    • 条件:長方形の頂点が円周上に配置される.

演習:サイコロを振るアプリケーションを作成する

プログラムと実行結果
解説

このプログラムでは,ボタンが押されるたびにサイコロが振られ,出た目が表示されます.

詳しい解説は省略します. これまでの内容を踏まえて,解読してみてください.

改造の例

サイコロの数を増やしてみる.

おすすめのプログラミング勉強法

最後に,私がおすすめするプログラミング勉強法を以下に示します.

SAMIT Online! 21.04とJumpakuの発表の様子

  • SAMIT Online! 21.04の全体

プログラミング合宿(Siv3D x オブジェクト指向エクササイズ)の宣伝

はじめに

本記事はSiv3D Advent Calendar 2020の8日目の記事です.

qiita.com

本記事では2020年12月26,27日に開催する以下のイベントの宣伝を行います.

connpass.com

また,本イベントのターゲット,意気込み,企画について述べます.

プログラミング合宿(Siv3D x オブジェクト指向エクササイズ)の宣伝

2020年12月26,27日にオンラインで「プログラミング合宿(Siv3D x オブジェクト指向エクササイズ)」を開催します. 本イベントでは,2日間の合宿で「オブジェクト指向エクササイズ(https://www.altus5.co.jp/blog/programming/2019/09/24/object-oriented-programming-exercise/)」の9つのルールを守りながら,「Siv3D(https://siv3d.github.io/ja-jp/)」を利用したグラフィカルなアプリケーションの開発を行います.興味のある方は是非上のURLから登録してみてください.

本イベントのターゲット

本イベントは,元々メインターゲットとして私の所属する大学の学生を想定してましたが,学外からの参加についても拒むつもりはありませんでした. 学内からの参加も学外からの参加も歓迎します.

本イベントへの意気込み

私は本イベントが,次のような体験ができるイベントになればと良いなと考えています.

  • プログラミングが好きな人達との交流.
  • Siv3Dを利用した,グラフィカルなアプリケーションの作成.
  • オブジェクト指向エクササイズを通じた,コードの書き方についての考察.

本イベントの企画について

私が所属するプログラミングサークルでは毎年春と夏に合宿が開かれゲーム制作をしたり,コンテストを開いたり,遊んだりしていました. しかし,今年は新型コロナウイルス感染症への対応でサークル活動ができません. それでも,プログラミングの楽しさを誰かと共有したいと考えた私は,春に「室工大生がオンラインでプログラミングの勉強をする会」を開催しました.

室工大生がオンラインでプログラミングの勉強をする会 - connpass

しかしながら,この勉強会は基本的に教えるのがメインの一方的なものだったこともあり,なかなか盛り上がらなかった気がしています.

もっと賑やかに交流できるイベントを開催したいと思い,今回のイベントを企画しました.

本イベントは以下の流れで企画が進みました.

  • 10月2日:ちうたさん,sakaki_tohruさん,kazuma_3339さんに「プログラミング合宿がしたい」と声を掛けた.
  • 10月7日:3人の協力が得られることとなり,合宿で取り組む内容が大まかに定まった.
  • 10月8日:イベント開催の日時が大まかに定まった.
  • 10月18日:合宿で取り組む内容が具体的に定まった.
  • 10月27日:開催日時と2日間の詳細な予定,主催者の役割分担が定まった.
  • 11月3日:connpassでイベントページを公開した.
  • 11月7日:@Reputeless さんに宣伝していただいた.
  • 12月8日:Siv3D Advent Calendar 2020の8日目の記事として本記事を公開した.

まとめ

  • 2020年12月26,27日にオンラインでプログラミング合宿(Siv3D x オブジェクト指向エクササイズ)を開催します.
  • プログラミングに興味のある人達が互いに交流できるイベントになれば良いなと考えています.
  • 興味のある方は是非参加してみてください.

リンク

点とベクトルと座標変換

はじめに

研究室で座標変換について説明する機会が何回かありました. 本記事ではそこで説明した内容をまとめます.

本記事ではまず,「点」と「ベクトル」を定義します. 次に,「座標」と「座標系」を定義します. そして,行列を用いた座標変換について解説します.

点とベクトル

定義

点とは位置を持つものです. 以下では点を太字の文字(例えば, 𝐚 )で表すことにします.

ベクトルとは向きと大きさをものです. 以下ではベクトルを矢印のついた文字(例えば, v )で表すことにします.

以下に点とベクトルの例を示します.

点とベクトルの例
点とベクトルの例

演算

ベクトルの実数倍

ベクトル v の実数 kkv は次のようなベクトルを表します.

  • k>0 の場合: v と同じ向きで大きさを |k| 倍にしたベクトル
  • k<0 の場合: v と逆の向きで大きさを |k| 倍にしたベクトル
  • k=0 の場合:大きさが0のベクトル
ベクトルの和

ベクトル u とベクトル v の和 u+v は次のようなベクトルを表します.

  • u の終点と v の始点を一致させるように uv を平行移動させたときに, u の始点から v の終点へ向かうベクトル
点の平行移動

𝐚 のベクトル v による平行移動 𝐚+v は次のような点を表します.

  • 𝐚 から v の方向に v の大きさの分だけ移動した先の点

以下に点とベクトルの演算の例を示します.

点とベクトルの演算の例
点とベクトルの演算の例

座標と座標系

点の位置を数値を用いて表現することを考えます. 座標系とは点の位置を数値を用いて表現するときに基準となるものです. 座標系は一つの点といくつかのベクトルで構成されます. 座標系を構成する点は原点を,ベクトルは座標軸を表します. ある点の座標とはその点の位置を表現する数値の組です.

具体的には,点 𝐨 とベクトル v0v1 で構成された座標系を (𝐨,v0,v1) とし,ある点 𝐚𝐨v0v1 と実数 a0a1 を用いて 𝐚=𝐨+a0v0+a1v1 と表せる時,座標系 (𝐨,v0,v1) を基準とした点 𝐚 の座標は (a0,a1) となります.

以下に座標系と座標の例を示します.

座標系と座標の例
座標系と座標の例

座標変換と座標変換行列

座標変換とは,ある座標系を基準とした点の座標を,別の座標系を基準とした座標として表現し直すことです. ここでは,行列を用いて座標変換を行う方法と,逆に座標変換前後の座標から座標変換で用いられた行列を求める方法を解説します.

行列を用いて座標変換を行う

以下の点と行列が与えられたとします.

  • 𝐚 :座標系 (𝐨,v0,v1) を基準とした座標が (a0,a1) である.
  • 行列 MM=(m00m01m02m10m11m12001)

この時, 𝐩=𝐨+m02v0+m12v1u0=(m00+m02)v0+(m10+m12)v1u1=(m01+m02)v0+(m11+m02)v1 を満たす別の座標系 (𝐩,u0,u1) を考え,その座標系を基準とした点 𝐚 の座標 (b0,b1) を次のように求めることができます. (b0b11)=M(a0a11)=(m00m01m02m10m11m12001)(a0a11)=(m00a0+m01a1+m02m10a0+m11a1+m121)

座標変換で用いられる行列を座標変換行列と呼びます.

以下に行列を用いて座標変換を行う例を示します.

行列を用いて座標変換を行う例
行列を用いて座標変換を行う例

座標変換行列を求める

ある2つの座標系 (𝐨,v0,v1)(𝐩,u0,u1) と以下の3点が与えられたとします.

  • 𝐚0
    座標系 (𝐨,v0,v1) を基準とした座標: (a00,a10)
    座標系 (𝐩,u0,u1) を基準とした座標: (b00,b10)
  • 𝐚1
    座標系 (𝐨,v0,v1) を基準とした座標: (a01,a11)
    座標系 (𝐩,u0,u1) を基準とした座標: (b01,b11)
  • 𝐚2
    座標系 (𝐨,v0,v1) を基準とした座標: (a02,a12)
    座標系 (𝐩,u0,u1) を基準とした座標: (b02,b12)

この時,座標系 (𝐨,v0,v1) を基準とした任意の点の座標を,座標系 (𝐩,u0,u1) を基準とした座標に変換する座標変換行列 M を次のように求めることができます.

まず, 𝐚0𝐚1𝐚2 を行列 M を用いてそれぞれ座標変換すると 𝐛0𝐛1𝐛2 となることから, (b00b101)=M(a00a101)(b01b111)=M(a01a111)(b02b121)=M(a02a121) が成り立つはずです. これらをまとめて (b00b01b02b10b11b12111)=M(a00a01a02a10a11a12111) と表すことができ,以下のように M について解くことで座標変換行列を求めることができます. M=(b00b01b02b10b11b12111)(a00a01a02a10a11a12111)1

以下に座標変換行列を求める例を示します.

座標変換行列を求める例
座標変換行列を求める例

まとめ

  • まず,「点」,「ベクトル」,「座標系」,「座標」を定義した.
  • 座標変換行列を用いて点を座標変換する方法について解説した.
  • 座標変換前後の点の座標から座標変換行列を求める方法について解説した.
  • 数式はMathMLで書いた.

Swingベースのシンプルなスケッチアプリ

概要

JavaFXjdkに同梱されなくなったため,今後,JVM上で動作するGUIアプリの開発は,Swingベースで行うことにしようと思います. そこで,シンプルなスケッチアプリを題材として,SwingベースのGUIアプリのテンプレートを作成しました. 本記事では,まずそのソースコードと動作例を示した上で,以下の点に焦点を当てて解説します.

  • ウィンドウの表示
  • イベントリスナの登録
  • 折れ線の描画

ソースコード

Kotlin

Java

動作例

f:id:Jumpaku:20200526184148p:plain
動作例

解説

プログラムを起動すると以下の流れで処理が実行されます.

  1. mainが実行される
  2. SwingUtilities.invokeLaterが実行される
  3. SwingSketchApprunが実行される

ウィンドウの表示

JFrameはウィンドウを表すクラスです. // ウィンドウの表示の部分ではJFrameインスタンスを生成してウィンドウを表示しています. 具体的には以下の項目を設定した後,setVisibletrueを渡すことでウィンドウが表示されます.

  • ウィンドウのタイトル:JFrameのコンストラクタに渡した文字列はウィンドウのタイトルとなります.
  • 閉じるボタンを押した時の動作:setDefaultCloseOperationJFrame.EXIT_ON_CLOSEを渡すとウィンドウの閉じるボタンを押した時にプログラムを終了します.
  • ウィンドウが持つコンテンツ:addはウィンドウにコンテンツを追加します.
  • ウィンドウのサイズ:packを呼び出すとウィンドウのサイズをコンテンツに応じて調整します.

イベントリスナの登録

アプリケーションにユーザの入力に応じた処理を実行させるためにはイベントリスナを登録する必要があります. イベントとはプログラムの状態の変化をトリガーとして生成されるオブジェクトです. 例えば,ユーザがマウスのボタンを押すことでプログラム内のマウス押下状態が変化した時やユーザがマウスドラッグすることでプログラム内のマウス位置が変化した時にはMouseEventクラスのインスタンスが生成されます. イベントリスナとはイベントが生成された時にそのイベントを引数にして実行されるメソッドまたはそのようなメソッドを持つクラスです.

// イベントリスナの登録の部分ではイベントリスナとしてMouseInputListenerインスタンスlistenerを生成し,これをpanelに登録しています. これにより,panelの上でユーザがマウスのボタンを押した時やマウスドラッグした時に,そのイベントに応じたlistenerのメソッドが実行されるようになります.

折れ線の描画

JPanelはコンテンツを追加できる汎用的なパネルを表すクラスです. JPanelpaintをオーバーライドすることで図形を描画することができます. ここではシンプルなスケッチを実現するためにユーザのドラッグにより入力された点列を折れ線として描画します. 具体的には// 折れ線の描画の部分で示すように,paintに引数として渡されるGraphics2Dインスタンスに対して,Point2Dのリストとして表された点列をLine2Dとして表される線分で繋いでいます.

Graphics2Dの使い方は以下の記事が参考になると思います. jumpaku.hatenablog.com