@akashic/akashic-engine
Advanced tools
Comparing version 3.0.3 to 3.0.4
# ChangeLog | ||
## 3.0.4 | ||
機能追加 | ||
* `g.Collision.intersectEntities()` を追加 | ||
* 同一シーン内の任意のエンティティ同士の矩形が重なっているかどうか判定することができます。 | ||
* `g.Collision.intersectLineSegments()` を追加 | ||
* 線分同士の衝突 (交差) を判定することができます。 | ||
仕様変更 | ||
* `g.Label` の生成時、 fontSize (`g.LabelParameterObject#fontSize`) プロパティを省略可能に | ||
* デフォルト値は `g.Label` の生成時に指定された font (`g.LabelParameterObject#font`) プロパティの font.size と同じ値になります | ||
## 3.0.3 | ||
@@ -4,0 +16,0 @@ * `g.Game#_reset()` 実行時に `g.Game#_moduleManager` を初期化する処理を追加 |
@@ -1,19 +0,45 @@ | ||
import { CommonArea } from "@akashic/pdi-types"; | ||
import { CommonArea, CommonOffset } from "@akashic/pdi-types"; | ||
import { E } from "./entities/E"; | ||
/** | ||
* オブジェクトの衝突を表す。 | ||
* - 矩形交差による衝突 | ||
* - 2点間の距離による衝突 | ||
* オブジェクトなどの衝突判定機能を提供する。 | ||
*/ | ||
export declare module Collision { | ||
/** | ||
* 二つのエンティティの衝突判定を行い、その結果を返す。 | ||
* | ||
* 回転・拡大されたエンティティや、親の異なるエンティティ同士も扱える汎用の衝突判定処理。 | ||
* ただし計算量が多いので、大量のエンティティ間のすべての衝突を確認するような状況では利用を避けることが望ましい。 | ||
* 親が同じで回転・拡大を行わないエンティティ同士の場合は、より軽量な Collision.intersectAreas() を利用すること。 | ||
* 親が同じで中心座標同士の距離だけで判定してよい場合は、より軽量な Collision.withinAreas() を利用すること。 | ||
* | ||
* 対象のエンティティの座標や大きさなどを変更した場合、 | ||
* この関数の呼び出し前にそのエンティティの modified() を呼び出しておく必要がある。 | ||
* | ||
* @param e1 衝突判定するエンティティ | ||
* @param e2 衝突判定するエンティティ | ||
* @param area1 e1 の当たり判定領域。省略された場合、`{ x: 0, y: 0, width: e1.width, hegiht: e1.height }` | ||
* @param area2 e2 の当たり判定領域。省略された場合、`{ x: 0, y: 0, width: e2.width, hegiht: e2.height }` | ||
*/ | ||
function intersectEntities(e1: E, e2: E, area1?: CommonArea | null, area2?: CommonArea | null): boolean; | ||
/** | ||
* 線分同士の衝突判定 (交差判定) を行い、その結果を返す。 | ||
* | ||
* @param {CommonOffset} p1 線分の端点の一つ | ||
* @param {CommonOffset} p2 線分の端点の一つ | ||
* @param {CommonOffset} q1 もう一つの線分の端点の一つ | ||
* @param {CommonOffset} q2 もう一つの線分の端点の一つ | ||
*/ | ||
function intersectLineSegments(p1: CommonOffset, p2: CommonOffset, q1: CommonOffset, q2: CommonOffset): boolean; | ||
/** | ||
* 矩形交差による衝突判定を行い、その結果を返す。 | ||
* 戻り値は、矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* @param {number} x1 t1-X | ||
* @param {number} y1 t1-Y | ||
* @param {number} width1 t1幅 | ||
* @param {number} height1 t1高さ | ||
* @param {number} x2 t2-X | ||
* @param {number} y2 t2-Y | ||
* @param {number} width2 t2幅 | ||
* @param {number} height2 t2高さ | ||
* 戻り値は、二つの矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* | ||
* @param {number} x1 t1のX座標 | ||
* @param {number} y1 t1のY座標 | ||
* @param {number} width1 t1の幅 | ||
* @param {number} height1 t1の高さ | ||
* @param {number} x2 t2のX座標 | ||
* @param {number} y2 t2のY座標 | ||
* @param {number} width2 t2の幅 | ||
* @param {number} height2 t2の高さ | ||
*/ | ||
@@ -24,2 +50,6 @@ function intersect(x1: number, y1: number, width1: number, height1: number, x2: number, y2: number, width2: number, height2: number): boolean; | ||
* 戻り値は、矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* | ||
* 特に、回転・拡大を利用していない、親が同じエンティティ同士の衝突判定に利用することができる。 | ||
* 条件を満たさない場合は `withinAreas()` や、より重いが正確な `intersectEntities()` の利用を検討すること。 | ||
* | ||
* @param {CommonArea} t1 矩形1 | ||
@@ -32,6 +62,6 @@ * @param {CommonArea} t2 矩形2 | ||
* 戻り値は、2点間の距離が閾値以内であるとき真、でなければ偽。 | ||
* @param {number} t1x t1-X | ||
* @param {number} t1y t1-X | ||
* @param {number} t2x t1-X | ||
* @param {number} t2y t1-X | ||
* @param {number} t1x 一点の X 座標 | ||
* @param {number} t1y 一点の Y 座標 | ||
* @param {number} t2x もう一点の X 座標 | ||
* @param {number} t2y もう一点の Y 座標 | ||
* @param {number} [distance=1] 衝突判定閾値 [pixel] | ||
@@ -38,0 +68,0 @@ */ |
@@ -5,6 +5,12 @@ "use strict"; | ||
var Util_1 = require("./Util"); | ||
// 外積の絶対値 | ||
function absCross(v1, v2) { | ||
return v1.x * v2.y - v1.y * v2.x; | ||
} | ||
// 二次元ベクトルの減算 | ||
function sub(v1, v2) { | ||
return { x: v1.x - v2.x, y: v1.y - v2.y }; | ||
} | ||
/** | ||
* オブジェクトの衝突を表す。 | ||
* - 矩形交差による衝突 | ||
* - 2点間の距離による衝突 | ||
* オブジェクトなどの衝突判定機能を提供する。 | ||
*/ | ||
@@ -14,12 +20,114 @@ var Collision; | ||
/** | ||
* 二つのエンティティの衝突判定を行い、その結果を返す。 | ||
* | ||
* 回転・拡大されたエンティティや、親の異なるエンティティ同士も扱える汎用の衝突判定処理。 | ||
* ただし計算量が多いので、大量のエンティティ間のすべての衝突を確認するような状況では利用を避けることが望ましい。 | ||
* 親が同じで回転・拡大を行わないエンティティ同士の場合は、より軽量な Collision.intersectAreas() を利用すること。 | ||
* 親が同じで中心座標同士の距離だけで判定してよい場合は、より軽量な Collision.withinAreas() を利用すること。 | ||
* | ||
* 対象のエンティティの座標や大きさなどを変更した場合、 | ||
* この関数の呼び出し前にそのエンティティの modified() を呼び出しておく必要がある。 | ||
* | ||
* @param e1 衝突判定するエンティティ | ||
* @param e2 衝突判定するエンティティ | ||
* @param area1 e1 の当たり判定領域。省略された場合、`{ x: 0, y: 0, width: e1.width, hegiht: e1.height }` | ||
* @param area2 e2 の当たり判定領域。省略された場合、`{ x: 0, y: 0, width: e2.width, hegiht: e2.height }` | ||
*/ | ||
function intersectEntities(e1, e2, area1, area2) { | ||
var lca = e1._findLowestCommonAncestorWith(e2); | ||
if (!lca) | ||
return false; | ||
var r1 = area1 | ||
? { left: area1.x, top: area1.y, right: area1.x + area1.width, bottom: area1.y + area1.height } | ||
: { left: 0, top: 0, right: e1.width, bottom: e1.height }; | ||
var r2 = area2 | ||
? { left: area2.x, top: area2.y, right: area2.x + area2.width, bottom: area2.y + area2.height } | ||
: { left: 0, top: 0, right: e2.width, bottom: e2.height }; | ||
var mat1 = e1._calculateMatrixTo(lca); | ||
var mat2 = e2._calculateMatrixTo(lca); | ||
// 座標系を合わせる: 共通祖先の座標系に合わせたそれぞれの四隅の点を求める。 | ||
var lt1 = mat1.multiplyPoint({ x: r1.left, y: r1.top }); | ||
var rt1 = mat1.multiplyPoint({ x: r1.right, y: r1.top }); | ||
var lb1 = mat1.multiplyPoint({ x: r1.left, y: r1.bottom }); | ||
var rb1 = mat1.multiplyPoint({ x: r1.right, y: r1.bottom }); | ||
var lt2 = mat2.multiplyPoint({ x: r2.left, y: r2.top }); | ||
var rt2 = mat2.multiplyPoint({ x: r2.right, y: r2.top }); | ||
var lb2 = mat2.multiplyPoint({ x: r2.left, y: r2.bottom }); | ||
var rb2 = mat2.multiplyPoint({ x: r2.right, y: r2.bottom }); | ||
// AABB で枝狩りする。(高速化だけでなく後続の条件を単純化するのにも必要である点に注意) | ||
var minX1 = Math.min(lt1.x, rt1.x, lb1.x, rb1.x); | ||
var maxX1 = Math.max(lt1.x, rt1.x, lb1.x, rb1.x); | ||
var minX2 = Math.min(lt2.x, rt2.x, lb2.x, rb2.x); | ||
var maxX2 = Math.max(lt2.x, rt2.x, lb2.x, rb2.x); | ||
if (maxX1 < minX2 || maxX2 < minX1) | ||
return false; | ||
var minY1 = Math.min(lt1.y, rt1.y, lb1.y, rb1.y); | ||
var maxY1 = Math.max(lt1.y, rt1.y, lb1.y, rb1.y); | ||
var minY2 = Math.min(lt2.y, rt2.y, lb2.y, rb2.y); | ||
var maxY2 = Math.max(lt2.y, rt2.y, lb2.y, rb2.y); | ||
if (maxY1 < minY2 || maxY2 < minY1) | ||
return false; | ||
// 二つの四角形それぞれのいずれかの辺同士が交差するなら衝突している。 | ||
if (Collision.intersectLineSegments(lt1, rt1, lt2, rt2) || | ||
Collision.intersectLineSegments(lt1, rt1, rt2, rb2) || | ||
Collision.intersectLineSegments(lt1, rt1, rb2, lb2) || | ||
Collision.intersectLineSegments(lt1, rt1, lb2, lt2) || | ||
Collision.intersectLineSegments(rt1, rb1, lt2, rt2) || | ||
Collision.intersectLineSegments(rt1, rb1, rt2, rb2) || | ||
Collision.intersectLineSegments(rt1, rb1, rb2, lb2) || | ||
Collision.intersectLineSegments(rt1, rb1, lb2, lt2) || | ||
Collision.intersectLineSegments(rb1, lb1, lt2, rt2) || | ||
Collision.intersectLineSegments(rb1, lb1, rt2, rb2) || | ||
Collision.intersectLineSegments(rb1, lb1, rb2, lb2) || | ||
Collision.intersectLineSegments(rb1, lb1, lb2, lt2) || | ||
Collision.intersectLineSegments(lb1, lt1, lt2, rt2) || | ||
Collision.intersectLineSegments(lb1, lt1, rt2, rb2) || | ||
Collision.intersectLineSegments(lb1, lt1, rb2, lb2) || | ||
Collision.intersectLineSegments(lb1, lt1, lb2, lt2)) { | ||
return true; | ||
} | ||
// そうでない場合、e1 が e2 を包含しているなら衝突している。 | ||
// ここで辺は交差していないので、e1 が e2 の頂点一つ (lt2) を包含しているなら、全体を包含している。 | ||
// cf. https://ksta.skr.jp/topic/diaryb09.html#040528 "各辺の内側判定による内外判定" | ||
var s1 = absCross(sub(lt1, rt1), sub(lt2, rt1)); | ||
if (s1 * absCross(sub(lb1, lt1), sub(lt2, lt1)) >= 0 && | ||
s1 * absCross(sub(rb1, lb1), sub(lt2, lb1)) >= 0 && | ||
s1 * absCross(sub(rt1, rb1), sub(lt2, rb1)) >= 0) { | ||
return true; | ||
} | ||
// そうでない場合、e2 が e1 を包含しているなら衝突している。 | ||
var s2 = absCross(sub(lt2, rt2), sub(lt1, rt2)); | ||
return (s2 * absCross(sub(lb2, lt2), sub(lt1, lt2)) >= 0 && | ||
s2 * absCross(sub(rb2, lb2), sub(lt1, lb2)) >= 0 && | ||
s2 * absCross(sub(rt2, rb2), sub(lt1, rb2)) >= 0); | ||
} | ||
Collision.intersectEntities = intersectEntities; | ||
/** | ||
* 線分同士の衝突判定 (交差判定) を行い、その結果を返す。 | ||
* | ||
* @param {CommonOffset} p1 線分の端点の一つ | ||
* @param {CommonOffset} p2 線分の端点の一つ | ||
* @param {CommonOffset} q1 もう一つの線分の端点の一つ | ||
* @param {CommonOffset} q2 もう一つの線分の端点の一つ | ||
*/ | ||
function intersectLineSegments(p1, p2, q1, q2) { | ||
// cf. https://ksta.skr.jp/topic/diaryb09.html#040518 | ||
var p = sub(p2, p1); | ||
var q = sub(q2, q1); | ||
return (absCross(sub(q1, p1), p) * absCross(sub(q2, p1), p) <= 0 && absCross(sub(p1, q1), q) * absCross(sub(p2, q1), q) <= 0 // 符号が違うことを積の符号で判定している | ||
); | ||
} | ||
Collision.intersectLineSegments = intersectLineSegments; | ||
/** | ||
* 矩形交差による衝突判定を行い、その結果を返す。 | ||
* 戻り値は、矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* @param {number} x1 t1-X | ||
* @param {number} y1 t1-Y | ||
* @param {number} width1 t1幅 | ||
* @param {number} height1 t1高さ | ||
* @param {number} x2 t2-X | ||
* @param {number} y2 t2-Y | ||
* @param {number} width2 t2幅 | ||
* @param {number} height2 t2高さ | ||
* 戻り値は、二つの矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* | ||
* @param {number} x1 t1のX座標 | ||
* @param {number} y1 t1のY座標 | ||
* @param {number} width1 t1の幅 | ||
* @param {number} height1 t1の高さ | ||
* @param {number} x2 t2のX座標 | ||
* @param {number} y2 t2のY座標 | ||
* @param {number} width2 t2の幅 | ||
* @param {number} height2 t2の高さ | ||
*/ | ||
@@ -33,2 +141,6 @@ function intersect(x1, y1, width1, height1, x2, y2, width2, height2) { | ||
* 戻り値は、矩形t1, t2が交差しているとき真、でなければ偽。 | ||
* | ||
* 特に、回転・拡大を利用していない、親が同じエンティティ同士の衝突判定に利用することができる。 | ||
* 条件を満たさない場合は `withinAreas()` や、より重いが正確な `intersectEntities()` の利用を検討すること。 | ||
* | ||
* @param {CommonArea} t1 矩形1 | ||
@@ -44,6 +156,6 @@ * @param {CommonArea} t2 矩形2 | ||
* 戻り値は、2点間の距離が閾値以内であるとき真、でなければ偽。 | ||
* @param {number} t1x t1-X | ||
* @param {number} t1y t1-X | ||
* @param {number} t2x t1-X | ||
* @param {number} t2y t1-X | ||
* @param {number} t1x 一点の X 座標 | ||
* @param {number} t1y 一点の Y 座標 | ||
* @param {number} t2x もう一点の X 座標 | ||
* @param {number} t2y もう一点の Y 座標 | ||
* @param {number} [distance=1] 衝突判定閾値 [pixel] | ||
@@ -50,0 +162,0 @@ */ |
@@ -369,4 +369,22 @@ import { CommonArea, CommonOffset, CommonRect, Renderer } from "@akashic/pdi-types"; | ||
/** | ||
* このエンティティの座標系を、指定された祖先エンティティ (またはシーン) の座標系に変換する行列を求める。 | ||
* | ||
* 指定されたエンティティが、このエンティティの祖先でない時、その値は無視される。 | ||
* 指定されたシーンが、このエンティティの属するシーン出ない時、その値は無視される。 | ||
* | ||
* @param target 座標系の変換先エンティティまたはシーン。省略した場合、このエンティティの属するシーン(グローバル座標系への変換行列になる) | ||
* @private | ||
*/ | ||
_calculateMatrixTo(target?: E | Scene): Matrix; | ||
/** | ||
* このエンティティと与えられたエンティティの共通祖先のうち、もっとも子孫側にあるものを探す。 | ||
* 共通祖先がない場合、 `undefined` を返す。 | ||
* | ||
* @param target このエンティティとの共通祖先を探すエンティティ | ||
* @private | ||
*/ | ||
_findLowestCommonAncestorWith(target: E): E | Scene | undefined; | ||
/** | ||
* @private | ||
*/ | ||
_calculateBoundingRect(m?: Matrix): CommonRect | undefined; | ||
@@ -373,0 +391,0 @@ /** |
@@ -589,3 +589,2 @@ "use strict"; | ||
var point = offset; | ||
// TODO: Scene#root が追加されたらループ継続判定文を書き換える | ||
for (var entity = this; entity instanceof E; entity = entity.parent) { | ||
@@ -602,3 +601,2 @@ point = entity.getMatrix().multiplyPoint(point); | ||
var matrix = new Matrix_1.PlainMatrix(); | ||
// TODO: Scene#root が追加されたらループ継続判定文を書き換える | ||
for (var entity = this; entity instanceof E; entity = entity.parent) { | ||
@@ -610,4 +608,39 @@ matrix.multiplyLeft(entity.getMatrix()); | ||
/** | ||
* このエンティティの座標系を、指定された祖先エンティティ (またはシーン) の座標系に変換する行列を求める。 | ||
* | ||
* 指定されたエンティティが、このエンティティの祖先でない時、その値は無視される。 | ||
* 指定されたシーンが、このエンティティの属するシーン出ない時、その値は無視される。 | ||
* | ||
* @param target 座標系の変換先エンティティまたはシーン。省略した場合、このエンティティの属するシーン(グローバル座標系への変換行列になる) | ||
* @private | ||
*/ | ||
E.prototype._calculateMatrixTo = function (target) { | ||
var matrix = new Matrix_1.PlainMatrix(); | ||
for (var entity = this; entity instanceof E && entity !== target; entity = entity.parent) { | ||
matrix.multiplyLeft(entity.getMatrix()); | ||
} | ||
return matrix; | ||
}; | ||
/** | ||
* このエンティティと与えられたエンティティの共通祖先のうち、もっとも子孫側にあるものを探す。 | ||
* 共通祖先がない場合、 `undefined` を返す。 | ||
* | ||
* @param target このエンティティとの共通祖先を探すエンティティ | ||
* @private | ||
*/ | ||
E.prototype._findLowestCommonAncestorWith = function (target) { | ||
var seen = {}; | ||
for (var p = this; p instanceof E; p = p.parent) { | ||
seen[p.id] = true; | ||
} | ||
var ret = target; | ||
for (; ret instanceof E; ret = ret.parent) { | ||
if (seen.hasOwnProperty(ret.id)) | ||
break; | ||
} | ||
return ret; | ||
}; | ||
/** | ||
* @private | ||
*/ | ||
E.prototype._calculateBoundingRect = function (m) { | ||
@@ -614,0 +647,0 @@ var matrix = this.getMatrix(); |
@@ -27,4 +27,5 @@ import { Glyph, Renderer } from "@akashic/pdi-types"; | ||
* に用いられている。 | ||
* @default LabelParameterObject#font.size | ||
*/ | ||
fontSize: number; | ||
fontSize?: number; | ||
/** | ||
@@ -90,2 +91,4 @@ * 文字列の描画位置。 | ||
* この値を変更した場合、 `this.invalidate()` を呼び出す必要がある。 | ||
* | ||
* @default Label#font.size | ||
*/ | ||
@@ -92,0 +95,0 @@ fontSize: number; |
@@ -36,3 +36,3 @@ "use strict"; | ||
_this.glyphs = new Array(param.text.length); | ||
_this.fontSize = param.fontSize; | ||
_this.fontSize = param.fontSize != null ? param.fontSize : param.font.size; | ||
_this.maxWidth = param.maxWidth; | ||
@@ -39,0 +39,0 @@ _this.widthAutoAdjust = param.widthAutoAdjust != null ? param.widthAutoAdjust : true; |
@@ -48,4 +48,4 @@ "use strict"; | ||
// それらは次のように表せる: | ||
// 1 0 -w sx 0 0 c -s 0 1 0 x-w | ||
// A = [ 0 1 -h] S = [ 0 sy 0] R = [ s c 0] T = [ 0 1 y-h] | ||
// 1 0 -w sx 0 0 c -s 0 1 0 x | ||
// A = [ 0 1 -h] S = [ 0 sy 0] R = [ s c 0] T = [ 0 1 y] | ||
// 0 0 1 0 0 1 0 0 1 0 0 1 | ||
@@ -52,0 +52,0 @@ // ここで sx, sy は scaleX, scaleY であり、c, s は cos(theta), sin(theta) |
@@ -129,3 +129,3 @@ import { CommonArea, CommonOffset, CommonSize, CompositeOperation, CompositeOperationString } from "@akashic/pdi-types"; | ||
/** | ||
* オブジェクトの回転。度数で指定する。 | ||
* オブジェクトの回転。度数 (時計回り) で指定する。 | ||
* 初期値は `0` である。 | ||
@@ -132,0 +132,0 @@ * `E` や `Camera2D` においてこの値を変更した場合、 `modified()` を呼び出す必要がある。 |
{ | ||
"name": "@akashic/akashic-engine", | ||
"version": "3.0.3", | ||
"version": "3.0.4", | ||
"description": "The core library of Akashic Engine", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
1254441
25063