質問
マウスがウィンドウの外側の端に到達すると、ビューが動き回るゲームが必要です(多くのRTSゲームと同様)。 MouseMotionListenerを使用すると、かなりのオーバーヘッドが発生することを読みました。
おそらく、ゲームウィンドウ(JPanel)内に、ゲームプレイに影響を与えないが、マウスがMouseAdapter.mouseEntered()/ mouseExited()を介して内部コンポーネントを離れるときに登録する2番目の透明コンポーネントを持つ方法がありますか?
boolean mouseOnScreen;
boolean mouseWithinInnerComponent; //is (10 <= mouse.x <= screenWidth - 10) && (10 <= mouse.y <= screenHeight)
if(mouseOnScreen && !mouseWithinInnerComponent)
{
//do something...
}
マウスがエッジまたはコーナーにあるかどうかを検出できる画面の周りに境界線を形成するために、上記のコンポーネントの4つをコーナーでオーバーラップさせる必要なく、どのスクリーン境界が交差したかを判断する方法がわかりません。これはかなり高価だと思います(ゲームの実行中に各コンポーネントをチェックする必要があります)...
boolean mouseOnScreen;
boolean mouseWithinTopComponent; //is (0 <= mouse.y <= 10)
boolean mouseWithinBottomComponent; //is (screenHeight - 10 <= mouse.y <= screenHeight)
boolean mouseWithinLeftComponent; //is (0 <= mouse.x <= 10)
boolean mouseWithinRightComponent; //is (screenWidth - 10 <= mouse.x <= screenWidth)
if(mouseOnScreen)
{
if(!mouseWithinBottomComponent)
{
//move view up
}
if(!mouseWithinTopComponent)
{
//move view down
}
if(!mouseWithinLeftComponent)
{
//move view right
}
if(!mouseWithinRightComponent)
{
//move view left
}
}
MouseMotionListenerには正確にどのくらいのオーバーヘッドがありますか?ゲームウィンドウの境界に沿って検出する必要がある場合、これまたは同様の方法はおそらくより効率的でしょうか?
注:これは、ウィンドウモードおよびフルスクリーンアプリケーションで使用されます。
解決
MouseMotionListener
を使用して必要なものを実装しました。オーバーヘッドが追加されると思う理由がよくわかりません... 1つ追加して、各メソッドにコンソールへの印刷(遅い)を要求し、マウスを動かしてみると、かなりきびきびしていることがわかります。ユーザーの観点から。
実装は、スクロールペイン、長方形の領域、タイマー、および MouseMotionListener
の4つの主要部分で構成されています。
最初に、 JScollPane
を拡張する AutoScrollPane
というパネルを作成しました。 JScrollPane
であっても、スクロールバーを非表示にすることができます。これにより、マップ上でビューポートを移動するための機能や、RTSゲームのような類似の機能を活用できます。
第二に、スクロール領域については、実際には8があります:n、ne、e、se、s、sw、w、nw(つまり、「北」、北東」など)斜めスクロール。単純に Rectangle
として実装します。それらは画面などには描画されません。適切なサイズで、ウィンドウの領域に一致する座標を使用して、クラス内に8つの長方形をインスタンス化します。実際にウィンドウのサイズ変更を許可しているので、必要に応じて長方形のサイズを変更します。
第三に、オンとオフを切り替えることができるタイマーがあります。オンにすると、すべての「ティック」 Runnable
を生成します。この Runnableの
ジョブは、パネルのビューポートを適切な方向に一定距離スクロールします。各 Runnable
はSwingイベントキューに渡されます。
最後に、 MouseMotionListener
があります。それは、マウスの入力、終了、および移動イベントをインターセプトすることです。イベントを受け取るたびに、現在のマウスの位置と、長方形の1つと交差するかどうかを確認します。どの長方形に基づいて、スクロールする方向を選択します。マウスが前のイベントのスクロール領域にあったかどうかを追跡します。この情報に基づいて、スクロールを開始するのか、スクロールを停止するのか、または発生していることをそのまま継続させるのかを判断します。マウスがペインの外に出たらスクロールを停止したかったので、exit / enterイベントを使用しました。とにかく、スクロールを開始するために、リスナーはスクロールする方向と距離を節約し、タイマーに開始を指示します。スクロールを停止する時間になると(マウスがスクロール領域を出るときなど)、タイマーに停止するよう指示します。
スムーズなスクロールのために適切なタイマーの粒度とスクロール距離を選択するのに時間がかかりましたが、かなりうまく機能します。この概要が助けになることを願っています。
他のヒント
早すぎる最適化がソフトウェア開発のすべての悪の根源であると主張したのは、マーティン・ファウラーだったと思います。 MouseMotionListenerを試してみて、ゲームのパフォーマンスに影響することがわかった場合にのみ最適化を検討してください。
MouseMotionListenerには何も問題はありません。オーバーヘッドについて読むと、おそらく1つの特定の例でした
どのプログラミング言語でもできることはすべて、悪いことも間違っていることもあります。
リスナーで何をするかに注意を払えば、すべてうまくいくはずです