This commit is contained in:
devil 2023-05-21 15:53:32 +08:00
parent 7bff1c70f1
commit e199970fb5
169 changed files with 11582 additions and 0 deletions
.DS_Store
.creator
.gitignore
assets

BIN
.DS_Store vendored Normal file

Binary file not shown.

@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://docs.cocos.com/creator/manual/en/scripting/setup.html#custom-script-template

@ -0,0 +1,5 @@
{
"image": {
"type": "sprite-frame"
}
}

24
.gitignore vendored Normal file

@ -0,0 +1,24 @@
#///////////////////////////
# Cocos Creator 3D Project
#///////////////////////////
library/
temp/
local/
build/
profiles/
native
#//////////////////////////
# NPM
#//////////////////////////
node_modules/
#//////////////////////////
# VSCode
#//////////////////////////
.vscode/
#//////////////////////////
# WebStorm
#//////////////////////////
.idea/

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

12
assets/Scripts.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "823bea19-caeb-456d-aff2-883004ae2bf0",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

BIN
assets/Scripts/.DS_Store vendored Normal file

Binary file not shown.

12
assets/Scripts/RVO.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "7a699aa3-3f5a-41b9-87db-13203bc13a10",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

557
assets/Scripts/RVO/Agent.ts Normal file

@ -0,0 +1,557 @@
import { KeyValuePair, Line, Obstacle, RVOMath, Vector2 } from "./Common";
import { Simulator } from "./Simulator";
export class Agent {
agentNeighbors_: KeyValuePair<number, Agent>[] = [];
obstaclNeighbors_: KeyValuePair<number, Obstacle>[] = [];
orcaLines_: Line[] = [];
position_: Vector2 = new Vector2(0, 0);
prefVelocity_: Vector2 = new Vector2(0, 0);
velocity_: Vector2 = new Vector2(0, 0);
id: number = 0;
maxNeighbors_: number = 0;
maxSpeed_: number = 0.0;
private _neighborDist: number = 0.0;
public get neighborDist(): number {
return this._neighborDist;
}
public set neighborDist(value: number) {
this._neighborDist = value;
}
radius_: number = 0.0;
timeHorizon: number = 0.0;
timeHorizonObst: number = 0.0;
newVelocity_: Vector2 = new Vector2(0, 0);
mass: number = 1;
computeNeighbors(sim: Simulator) {
this.obstaclNeighbors_.length = 0;
let rangeSq = (this.timeHorizonObst * this.maxSpeed_ + this.radius_) ** 2;
sim.kdTree.computeObstacleNeighbors(this, rangeSq);
this.agentNeighbors_.length = 0;
if (this.maxNeighbors_ > 0) {
rangeSq = this.neighborDist ** 2;
rangeSq = sim.kdTree.computeAgentNeighbors(this, rangeSq);
}
}
/* Search for the best new velocity. */
computeNewVelocity(dt: number) {
this.orcaLines_.length = 0;
let orcaLines = this.orcaLines_;
let invTimeHorizonObst = 1.0 / this.timeHorizonObst;
/* Create obstacle ORCA lines. */
for (let i = 0; i < this.obstaclNeighbors_.length; ++i) {
let obstacle1 = this.obstaclNeighbors_[i].value;
let obstacle2 = obstacle1.next;
let relativePosition1 = obstacle1.point.minus(this.position_);
let relativePosition2 = obstacle2.point.minus(this.position_);
/*
* Check if velocity obstacle of obstacle is already taken care of by
* previously constructed obstacle ORCA lines.
*/
let alreadyCovered = false;
for (let j = 0; j < orcaLines.length; ++j) {
if (RVOMath.det(relativePosition1.scale(invTimeHorizonObst).minus(orcaLines[j].point), orcaLines[j].direction) - invTimeHorizonObst * this.radius_ >= -RVOMath.RVO_EPSILON
&& RVOMath.det(relativePosition2.scale(invTimeHorizonObst).minus(orcaLines[j].point), orcaLines[j].direction) - invTimeHorizonObst * this.radius_ >= -RVOMath.RVO_EPSILON) {
alreadyCovered = true;
break;
}
}
if (alreadyCovered) {
continue;
}
/* Not yet covered. Check for collisions. */
let distSq1 = RVOMath.absSq(relativePosition1);
let distSq2 = RVOMath.absSq(relativePosition2);
let radiusSq = RVOMath.sqr(this.radius_);
let obstacleVector = obstacle2.point.minus(obstacle1.point);
let s = relativePosition1.scale(-1).multiply(obstacleVector) / RVOMath.absSq(obstacleVector);
let distSqLine = RVOMath.absSq(relativePosition1.scale(-1).minus(obstacleVector.scale(s)));
let line = new Line();
if (s < 0 && distSq1 <= radiusSq) {
/* Collision with left vertex. Ignore if non-convex. */
if (obstacle1.convex) {
line.point = new Vector2(0, 0);
line.direction = RVOMath.normalize(new Vector2(-relativePosition1.y, relativePosition1.x));
orcaLines.push(line);
}
continue;
}
else if (s > 1 && distSq2 <= radiusSq) {
/* Collision with right vertex. Ignore if non-convex
* or if it will be taken care of by neighoring obstace */
if (obstacle2.convex && RVOMath.det(relativePosition2, obstacle2.direction) >= 0) {
line.point = new Vector2(0, 0);
line.direction = RVOMath.normalize(new Vector2(-relativePosition2.y, relativePosition2.x));
orcaLines.push(line);
}
continue;
}
else if (s >= 0 && s <= 1 && distSqLine <= radiusSq) {
/* Collision with obstacle segment. */
line.point = new Vector2(0, 0);
line.direction = obstacle1.direction.scale(-1);
orcaLines.push(line);
continue;
}
/*
* No collision.
* Compute legs. When obliquely viewed, both legs can come from a single
* vertex. Legs extend cut-off line when nonconvex vertex.
*/
let leftLegDirection: Vector2, rightLegDirection: Vector2;
if (s < 0 && distSqLine <= radiusSq) {
/*
* Obstacle viewed obliquely so that left vertex
* defines velocity obstacle.
*/
if (!obstacle1.convex) {
/* Ignore obstacle. */
continue;
}
obstacle2 = obstacle1;
let leg1 = Math.sqrt(distSq1 - radiusSq);
leftLegDirection = (new Vector2(relativePosition1.x * leg1 - relativePosition1.y * this.radius_, relativePosition1.x * this.radius_ + relativePosition1.y * leg1)).scale(1 / distSq1);
rightLegDirection = (new Vector2(relativePosition1.x * leg1 + relativePosition1.y * this.radius_, -relativePosition1.x * this.radius_ + relativePosition1.y * leg1)).scale(1 / distSq1);
}
else if (s > 1 && distSqLine <= radiusSq) {
/*
* Obstacle viewed obliquely so that
* right vertex defines velocity obstacle.
*/
if (!obstacle2.convex) {
/* Ignore obstacle. */
continue;
}
obstacle1 = obstacle2;
let leg2 = Math.sqrt(distSq2 - radiusSq);
leftLegDirection = (new Vector2(relativePosition2.x * leg2 - relativePosition2.y * this.radius_, relativePosition2.x * this.radius_ + relativePosition2.y * leg2)).scale(1 / distSq2);
rightLegDirection = (new Vector2(relativePosition2.x * leg2 + relativePosition2.y * this.radius_, -relativePosition2.x * this.radius_ + relativePosition2.y * leg2)).scale(1 / distSq2);
}
else {
/* Usual situation. */
if (obstacle1.convex) {
let leg1 = Math.sqrt(distSq1 - radiusSq);
leftLegDirection = (new Vector2(relativePosition1.x * leg1 - relativePosition1.y * this.radius_, relativePosition1.x * this.radius_ + relativePosition1.y * leg1)).scale(1 / distSq1);
}
else {
/* Left vertex non-convex; left leg extends cut-off line. */
leftLegDirection = obstacle1.direction.scale(-1);
}
if (obstacle2.convex) {
let leg2 = Math.sqrt(distSq2 - radiusSq);
rightLegDirection = (new Vector2(relativePosition2.x * leg2 + relativePosition2.y * this.radius_, -relativePosition2.x * this.radius_ + relativePosition2.y * leg2)).scale(1 / distSq2);
}
else {
/* Right vertex non-convex; right leg extends cut-off line. */
rightLegDirection = obstacle1.direction;
}
}
/*
* Legs can never point into neighboring edge when convex vertex,
* take cutoff-line of neighboring edge instead. If velocity projected on
* "foreign" leg, no constraint is added.
*/
let leftNeighbor = obstacle1.previous;
let isLeftLegForeign = false;
let isRightLegForeign = false;
if (obstacle1.convex && RVOMath.det(leftLegDirection, leftNeighbor.direction.scale(-1)) >= 0.0) {
/* Left leg points into obstacle. */
leftLegDirection = leftNeighbor.direction.scale(-1);
isLeftLegForeign = true;
}
if (obstacle2.convex && RVOMath.det(rightLegDirection, obstacle2.direction) <= 0.0) {
/* Right leg points into obstacle. */
rightLegDirection = obstacle2.direction;
isRightLegForeign = true;
}
/* Compute cut-off centers. */
let leftCutoff = obstacle1.point.minus(this.position_).scale(invTimeHorizonObst);
let rightCutoff = obstacle2.point.minus(this.position_).scale(invTimeHorizonObst);
let cutoffVec = rightCutoff.minus(leftCutoff);
/* Project current velocity on velocity obstacle. */
/* Check if current velocity is projected on cutoff circles. */
let t = (obstacle1 == obstacle2) ? 0.5 : this.velocity_.minus(leftCutoff).multiply(cutoffVec) / RVOMath.absSq(cutoffVec);
let tLeft = this.velocity_.minus(leftCutoff).multiply(leftLegDirection);
let tRight = this.velocity_.minus(rightCutoff).multiply(rightLegDirection);
if ((t < 0.0 && tLeft < 0.0) || (obstacle1 == obstacle2 && tLeft < 0.0 && tRight < 0.0)) {
/* Project on left cut-off circle. */
let unitW = RVOMath.normalize(this.velocity_.minus(leftCutoff));
line.direction = new Vector2(unitW.y, -unitW.x);
line.point = leftCutoff.plus(unitW.scale(this.radius_ * invTimeHorizonObst));
orcaLines.push(line);
continue;
}
else if (t > 1.0 && tRight < 0.0) {
/* Project on right cut-off circle. */
let unitW = RVOMath.normalize(this.velocity_.minus(rightCutoff));
line.direction = new Vector2(unitW.y, -unitW.x);
line.point = rightCutoff.plus(unitW.scale(this.radius_ * invTimeHorizonObst));
orcaLines.push(line);
continue;
}
/*
* Project on left leg, right leg, or cut-off line, whichever is closest
* to velocity.
*/
let distSqCutoff = ((t < 0.0 || t > 1.0 || obstacle1 == obstacle2) ? Infinity : RVOMath.absSq(this.velocity_.minus(cutoffVec.scale(t).plus(leftCutoff))));
let distSqLeft = ((tLeft < 0.0) ? Infinity : RVOMath.absSq(this.velocity_.minus(leftLegDirection.scale(tLeft).plus(leftCutoff))));
let distSqRight = ((tRight < 0.0) ? Infinity : RVOMath.absSq(this.velocity_.minus(rightLegDirection.scale(tRight).plus(rightCutoff))));
if (distSqCutoff <= distSqLeft && distSqCutoff <= distSqRight) {
/* Project on cut-off line. */
line.direction = obstacle1.direction.scale(-1);
let aux = new Vector2(-line.direction.y, line.direction.x);
line.point = aux.scale(this.radius_ * invTimeHorizonObst).plus(leftCutoff);
orcaLines.push(line);
continue;
}
else if (distSqLeft <= distSqRight) {
/* Project on left leg. */
if (isLeftLegForeign) {
continue;
}
line.direction = leftLegDirection;
let aux = new Vector2(-line.direction.y, line.direction.x);
line.point = aux.scale(this.radius_ * invTimeHorizonObst).plus(leftCutoff);
orcaLines.push(line);
continue;
}
else {
/* Project on right leg. */
if (isRightLegForeign) {
continue;
}
line.direction = rightLegDirection.scale(-1);
let aux = new Vector2(-line.direction.y, line.direction.x);
line.point = aux.scale(this.radius_ * invTimeHorizonObst).plus(rightCutoff);
orcaLines.push(line);
continue;
}
}
let numObstLines = orcaLines.length;
let invTimeHorizon = 1.0 / this.timeHorizon;
/* Create agent ORCA lines. */
for (let i = 0; i < this.agentNeighbors_.length; ++i) {
let other = this.agentNeighbors_[i].value;
let relativePosition = other.position_.minus(this.position_);
// mass
let massRatio = (other.mass / (this.mass + other.mass));
let neighborMassRatio = (this.mass / (this.mass + other.mass));
let velocityOpt = (massRatio >= 0.5 ? (this.velocity_.minus(this.velocity_.scale(massRatio)).scale(2)) : this.prefVelocity_.plus(this.velocity_.minus(this.prefVelocity_).scale(massRatio * 2)));
let neighborVelocityOpt = (neighborMassRatio >= 0.5 ? other.velocity_.scale(2).scale(1 - neighborMassRatio) : (other.prefVelocity_.plus(other.velocity_.minus(other.prefVelocity_).scale(2 * neighborMassRatio))));
let relativeVelocity = velocityOpt.minus(neighborVelocityOpt);//this.velocity.minus(other.velocity);
let distSq = RVOMath.absSq(relativePosition);
let combinedRadius = this.radius_ + other.radius_;
let combinedRadiusSq = RVOMath.sqr(combinedRadius);
let line = new Line();
let u: Vector2;
if (distSq > combinedRadiusSq) {
/* No collision. */
let w = relativeVelocity.minus(relativePosition.scale(invTimeHorizon)); // Vector
/* Vector from cutoff center to relative velocity. */
let wLengthSq = RVOMath.absSq(w);
let dotProduct1 = w.multiply(relativePosition);
if (dotProduct1 < 0.0 && RVOMath.sqr(dotProduct1) > combinedRadiusSq * wLengthSq) {
/* Project on cut-off circle. */
let wLength = Math.sqrt(wLengthSq);
let unitW = w.scale(1 / wLength);
line.direction = new Vector2(unitW.y, -unitW.x);
u = unitW.scale(combinedRadius * invTimeHorizon - wLength);
}
else {
/* Project on legs. */
let leg = Math.sqrt(distSq - combinedRadiusSq);
if (RVOMath.det(relativePosition, w) > 0.0) {
/* Project on left leg. */
let aux = new Vector2(relativePosition.x * leg - relativePosition.y * combinedRadius, relativePosition.x * combinedRadius + relativePosition.y * leg);
line.direction = aux.scale(1 / distSq);
}
else {
/* Project on right leg. */
let aux = new Vector2(relativePosition.x * leg + relativePosition.y * combinedRadius, -relativePosition.x * combinedRadius + relativePosition.y * leg);
line.direction = aux.scale(-1 / distSq);
}
let dotProduct2 = relativeVelocity.multiply(line.direction);
u = line.direction.scale(dotProduct2).minus(relativeVelocity);
}
}
else {
/* Collision. Project on cut-off circle of time timeStep. */
let invTimeStep = 1.0 / dt;
/* Vector from cutoff center to relative velocity. */
let w = relativeVelocity.minus(relativePosition.scale(invTimeStep));
let wLength = RVOMath.abs(w);
let unitW = w.scale(1 / wLength);
line.direction = new Vector2(unitW.y, -unitW.x);
u = unitW.scale(combinedRadius * invTimeStep - wLength);
}
// line.point = u.scale(0.5).plus(this.velocity);
line.point = velocityOpt.plus(u.scale(massRatio));
orcaLines.push(line);
}
let lineFail = this.linearProgram2(orcaLines, this.maxSpeed_, this.prefVelocity_, false, this.newVelocity_);
if (lineFail < orcaLines.length) {
this.linearProgram3(orcaLines, numObstLines, lineFail, this.maxSpeed_, this.newVelocity_);
}
}
insertAgentNeighbor(agent: Agent, rangeSq: number) {
if (this != agent) {
let distSq = RVOMath.absSq(this.position_.minus(agent.position_));
if (distSq < rangeSq) {
if (this.agentNeighbors_.length < this.maxNeighbors_) {
this.agentNeighbors_.push(new KeyValuePair(distSq, agent));
}
let i = this.agentNeighbors_.length - 1;
while (i != 0 && distSq < this.agentNeighbors_[i - 1].key) {
this.agentNeighbors_[i] = this.agentNeighbors_[i - 1];
--i;
}
this.agentNeighbors_[i] = new KeyValuePair<number, Agent>(distSq, agent);
if (this.agentNeighbors_.length == this.maxNeighbors_) {
rangeSq = this.agentNeighbors_[this.agentNeighbors_.length - 1].key;
}
}
}
return rangeSq;
}
insertObstacleNeighbor(obstacle: Obstacle, rangeSq: number) {
let nextObstacle = obstacle.next;
let distSq = RVOMath.distSqPointLineSegment(obstacle.point, nextObstacle.point, this.position_);
if (distSq < rangeSq) {
this.obstaclNeighbors_.push(new KeyValuePair<number, Obstacle>(distSq, obstacle));
let i = this.obstaclNeighbors_.length - 1;
while (i != 0 && distSq < this.obstaclNeighbors_[i - 1].key) {
this.obstaclNeighbors_[i] = this.obstaclNeighbors_[i - 1];
--i;
}
this.obstaclNeighbors_[i] = new KeyValuePair<number, Obstacle>(distSq, obstacle);
}
}
update(dt: number) {
this.velocity_.copy(this.newVelocity_);
this.position_.copy(this.position_.plus(this.velocity_.scale(dt)));
};
linearProgram1(lines: Line[], lineNo: number, radius: number, optVelocity: Vector2, directionOpt: boolean, result: Vector2) {
let dotProduct = lines[lineNo].point.multiply(lines[lineNo].direction);
let discriminant = RVOMath.sqr(dotProduct) + RVOMath.sqr(radius) - RVOMath.absSq(lines[lineNo].point);
if (discriminant < 0.0) {
/* Max speed circle fully invalidates line lineNo. */
return false;
}
let sqrtDiscriminant = Math.sqrt(discriminant);
let tLeft = -dotProduct - sqrtDiscriminant;
let tRight = -dotProduct + sqrtDiscriminant;
for (let i = 0; i < lineNo; ++i) {
let denominator = RVOMath.det(lines[lineNo].direction, lines[i].direction);
let numerator = RVOMath.det(lines[i].direction, lines[lineNo].point.minus(lines[i].point));
if (Math.abs(denominator) <= RVOMath.RVO_EPSILON) {
/* Lines lineNo and i are (almost) parallel. */
if (numerator < 0.0) {
return false;
}
else {
continue;
}
}
let t = numerator / denominator;
if (denominator >= 0.0) {
/* Line i bounds line lineNo on the right. */
tRight = Math.min(tRight, t);
}
else {
/* Line i bounds line lineNo on the left. */
tLeft = Math.max(tLeft, t);
}
if (tLeft > tRight) {
return false;
}
}
if (directionOpt) {
if (optVelocity.multiply(lines[lineNo].direction) > 0.0) {
// Take right extreme
result.copy(lines[lineNo].point.plus(lines[lineNo].direction.scale(tRight)));
}
else {
// Take left extreme.
result.copy(lines[lineNo].point.plus(lines[lineNo].direction.scale(tLeft)));
}
}
else {
// Optimize closest point
let t = lines[lineNo].direction.multiply(optVelocity.minus(lines[lineNo].point));
if (t < tLeft) {
result.copy(lines[lineNo].point.plus(lines[lineNo].direction.scale(tLeft)));
}
else if (t > tRight) {
result.copy(lines[lineNo].point.plus(lines[lineNo].direction.scale(tRight)));
}
else {
result.copy(lines[lineNo].point.plus(lines[lineNo].direction.scale(t)));
}
}
return true;
}
linearProgram2(lines: Line[], radius: number, optVelocity: Vector2, directionOpt: boolean, result: Vector2) {
// directionOpt 第一次为false第二次为truedirectionOpt主要用在 linearProgram1 里面
if (directionOpt) {
/*
* Optimize direction. Note that the optimization velocity is of unit
* length in this case.
*/
result.copy(optVelocity.scale(radius));
}
else if (RVOMath.absSq(optVelocity) > RVOMath.sqr(radius)) {
/* Optimize closest point and outside circle. */
result.copy(RVOMath.normalize(optVelocity).scale(radius));
}
else {
/* Optimize closest point and inside circle. */
result.copy(optVelocity);
}
for (let i = 0; i < lines.length; ++i) {
if (RVOMath.det(lines[i].direction, lines[i].point.minus(result)) > 0.0) {
/* Result does not satisfy constraint i. Compute new optimal result. */
let tempResult = result.clone();
if (!this.linearProgram1(lines, i, radius, optVelocity, directionOpt, result)) {
result.copy(tempResult);
return i;
}
}
}
return lines.length;
}
linearProgram3(lines: Line[], numObstLines: number, beginLine: number, radius: number, result: Vector2) {
let distance = 0.0;
// 遍历所有剩余ORCA线
for (let i = beginLine; i < lines.length; ++i) {
// 每一条 ORCA 线都需要精确的做出处理distance 为 最大违规的速度
if (RVOMath.det(lines[i].direction, lines[i].point.minus(result)) > distance) {
/* Result does not satisfy constraint of line i. */
//std::vector<Line> projLines(lines.begin(), lines.begin() + numObstLines);
let projLines = []; // new List<Line>();
// 1.静态阻挡的orca线直接加到projLines中
for (let ii = 0; ii < numObstLines; ++ii) {
projLines.push(lines[ii]);
}
// 2.动态阻挡的orca线需要重新计算line从第一个非静态阻挡到当前的orca线
for (let j = numObstLines; j < i; ++j) {
let line = new Line();
let determinant = RVOMath.det(lines[i].direction, lines[j].direction);
if (Math.abs(determinant) <= RVOMath.RVO_EPSILON) {
/* Line i and line j are parallel. */
if (lines[i].direction.multiply(lines[j].direction) > 0.0) {
/* Line i and line j point in the same direction. */
continue;
}
else {
/* Line i and line j point in opposite direction. */
line.point = lines[i].point.plus(lines[j].point).scale(0.5);
}
}
else {
line.point = lines[i].point.plus(lines[i].direction.scale(RVOMath.det(lines[j].direction, lines[i].point.minus(lines[j].point)) / determinant));
}
line.direction = RVOMath.normalize(lines[j].direction.minus(lines[i].direction));
projLines.push(line);
}
let tempResult = result.clone();
if (this.linearProgram2(projLines, radius, new Vector2(-lines[i].direction.y, lines[i].direction.x), true, result) < projLines.length) {
/* This should in principle not happen. The result is by definition
* already in the feasible region of this linear program. If it fails,
* it is due to small floating point error, and the current result is
* kept.
*/
result.copy(tempResult);
}
distance = RVOMath.det(lines[i].direction, lines[i].point.minus(result));
}
}
}
}

@ -0,0 +1,12 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "99d7f5fd-fae6-4106-ba7a-93c1e298d001",
"files": [],
"subMetas": {},
"userData": {
"moduleId": "project:///assets/Scripts/GameCore/RVO2/Agent.js",
"simulateGlobals": []
}
}

@ -0,0 +1,117 @@
import { Vec2 } from "cc";
export class Vector2 {
x = 0;
y = 0;
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
plus(vector: Vector2) {
return new Vector2(this.x + vector.x, this.y + vector.y);
}
minus(vector: Vector2) {
return new Vector2(this.x - vector.x, this.y - vector.y);
}
multiply(vector: Vector2) {
return this.x * vector.x + this.y * vector.y;
}
scale(k: number) {
return new Vector2(this.x * k, this.y * k);
}
copy(v: Vector2 | Vec2) {
this.x = v.x;
this.y = v.y;
return this;
}
clone() {
return new Vector2(this.x, this.y);
}
substract(out: Vector2, other: Vector2) {
out.x -= other.x;
out.y -= other.y;
return out;
}
lengthSqr() {
return this.x ** 2 + this.y ** 2;
}
}
export class Obstacle {
next: Obstacle;
previous: Obstacle;
direction: Vector2;
point: Vector2;
id: number;
convex: boolean;
}
export class Line {
point: Vector2;
direction: Vector2;
}
export class KeyValuePair<K, V> {
key: K;
value: V;
constructor(key: K, value: V) {
this.key = key;
this.value = value;
}
}
export class RVOMath {
static RVO_EPSILON = 0.00001;
static absSq(v: Vector2) {
return v.multiply(v);
};
static normalize(v: Vector2) {
return v.scale(1 / RVOMath.abs(v)); // v / abs(v)
};
static distSqPointLineSegment(vector1: Vector2, vector2: Vector2, vector3: Vector2) {
let aux1 = vector3.minus(vector1);
let aux2 = vector2.minus(vector1);
let r = aux1.multiply(aux2) / RVOMath.absSq(aux2);
if (r < 0) {
return RVOMath.absSq(aux1);
}
else if (r > 1) {
return RVOMath.absSq(vector3.minus(vector2));
}
else {
return RVOMath.absSq(vector3.minus(vector1.plus(aux2.scale(r))));
}
};
static sqr(p: number) {
return p * p;
};
static det(v1: Vector2, v2: Vector2) {
return v1.x * v2.y - v1.y * v2.x;
};
static abs(v: Vector2) {
return Math.sqrt(RVOMath.absSq(v));
};
static leftOf(a: Vector2, b: Vector2, c: Vector2) {
return RVOMath.det(a.minus(c), b.minus(a));
};
}

@ -0,0 +1,12 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "b21abffd-42c6-4d43-bbe0-0edd2fb59f53",
"files": [],
"subMetas": {},
"userData": {
"moduleId": "project:///assets/Scripts/GameCore/RVO2/Common.js",
"simulateGlobals": []
}
}

@ -0,0 +1,236 @@
import { Vec2 } from "cc";
import { Agent } from "./Agent";
import { Obstacle, RVOMath, Vector2 } from "./Common";
import { KdTree } from "./kdtree";
export class Simulator {
private agentId: number = 0;
private agentIdLst: number[] = [];
aid2agent: { [key: string]: Agent } = Object.create(null);
obstacles: Obstacle[] = [];
kdTree: KdTree = new KdTree();
defaultAgent: Agent; // Agent
time: number = 0.0;
private static _inst: Simulator;
static get instance(): Simulator {
if (!Simulator._inst) {
Simulator._inst = new Simulator();
}
return Simulator._inst;
}
getAgent(idx: number) {
return this.aid2agent[this.agentIdLst[idx]];
}
getAgentByAid(aid: number) {
return this.aid2agent[aid];
}
getGlobalTime() {
return this.time;
};
getNumAgents() {
// console.log("getNumAgents ::", this.agentIdLst.length, this.agentIdLst)
return this.agentIdLst.length;
};
getAgentAidByIdx(idx: number) {
return this.agentIdLst[idx]
}
setAgentPrefVelocity(aid: number, velocity: Vector2 | Vec2) {
this.aid2agent[aid].prefVelocity_.copy(velocity);
}
getAgentPosition(aid: number) {
if (this.aid2agent[aid]) {//为什么移除了 还会进入这个aid的检测
return this.aid2agent[aid].position_;
}
return null
}
getAgentPrefVelocity(aid: number) {
return this.aid2agent[aid].prefVelocity_;
}
getAgentVelocity(aid: number) {
return this.aid2agent[aid].velocity_;
}
getAgentRadius(aid: number) {
return this.aid2agent[aid].radius_;
}
getAgentOrcaLines(aid: number) {
return this.aid2agent[aid].orcaLines_;
}
/**
*
* @param position
* @param radius
* @param maxSpeed
* @param velocity 线()
* @param mass
* @returns
*/
addAgent(position: Vector2 | Vec2, radius: number = null, maxSpeed: number = null, velocity: Vector2 = null, mass: number = null) {
if (!this.defaultAgent) {
throw new Error("no default agent");
}
let agent = new Agent();
agent.position_.copy(position);
agent.maxNeighbors_ = this.defaultAgent.maxNeighbors_;
agent.maxSpeed_ = maxSpeed || this.defaultAgent.maxSpeed_;
agent.neighborDist = this.defaultAgent.neighborDist;
agent.radius_ = radius || this.defaultAgent.radius_;
agent.timeHorizon = this.defaultAgent.timeHorizon;
agent.timeHorizonObst = this.defaultAgent.timeHorizonObst;
agent.velocity_.copy(velocity || this.defaultAgent.velocity_);
agent.id = this.agentId++;
if (mass && mass >= 0) {
agent.mass = mass
}
this.aid2agent[agent.id] = agent;
this.agentIdLst.push(agent.id);
return agent.id;
}
removeAgent(aid: number) {
if (this.hasAgent(aid)) {
let idx = this.agentIdLst.indexOf(aid);
if (idx >= 0) {
// this.agentIdLst.splice(idx, 1) //用高效伪移除
this.agentIdLst[idx] = this.agentIdLst[this.agentIdLst.length - 1];
this.agentIdLst.length--;
}
delete this.aid2agent[aid];
}
}
hasAgent(aid: number) {
return !!this.aid2agent[aid];
}
setAgentMass(agentNo: number, mass: number) {
this.aid2agent[agentNo].mass = mass;
}
getAgentMass(agentNo: number) {
return this.aid2agent[agentNo].mass;
}
setAgentRadius(agentNo: number, radius: number) {
this.aid2agent[agentNo].radius_ = radius;
}
/**
*
* @param neighborDist
* @param maxNeighbors
* @param timeHorizon
* @param timeHorizonObst RTS游戏中
* @param radius ORCA时的小球的半径
* @param maxSpeed
* @param velocity
*/
setAgentDefaults(neighborDist: number, maxNeighbors: number, timeHorizon: number, timeHorizonObst: number, radius: number, maxSpeed: number, velocity: Vector2) {
if (!this.defaultAgent) {
this.defaultAgent = new Agent();
}
this.defaultAgent.maxNeighbors_ = maxNeighbors;
this.defaultAgent.maxSpeed_ = maxSpeed;
this.defaultAgent.neighborDist = neighborDist;
this.defaultAgent.radius_ = radius;
this.defaultAgent.timeHorizon = timeHorizon;
this.defaultAgent.timeHorizonObst = timeHorizonObst;
this.defaultAgent.velocity_ = velocity;
}
run(dt: number) {
this.kdTree.buildAgentTree(this.getNumAgents());
let agentNum = this.agentIdLst.length;
for (let i = 0; i < agentNum; i++) {
this.aid2agent[this.agentIdLst[i]].computeNeighbors(this);
this.aid2agent[this.agentIdLst[i]].computeNewVelocity(dt);
}
for (let i = 0; i < agentNum; i++) {
this.aid2agent[this.agentIdLst[i]].update(dt);
}
this.time += dt;
}
addObstacle(vertices: Vector2[]) {
if (vertices.length < 2) {
return -1;
}
let obstacleNo = this.obstacles.length;
for (let i = 0; i < vertices.length; ++i) {
let obstacle = new Obstacle();
obstacle.point = vertices[i];
if (i != 0) {
obstacle.previous = this.obstacles[this.obstacles.length - 1];
obstacle.previous.next = obstacle;
}
if (i == vertices.length - 1) {
obstacle.next = this.obstacles[obstacleNo];
obstacle.next.previous = obstacle;
}
obstacle.direction = RVOMath.normalize(vertices[(i == vertices.length - 1 ? 0 : i + 1)].minus(vertices[i]));
if (vertices.length == 2) {
obstacle.convex = true;
}
else {
obstacle.convex = (RVOMath.leftOf(vertices[(i == 0 ? vertices.length - 1 : i - 1)], vertices[i], vertices[(i == vertices.length - 1 ? 0 : i + 1)]) >= 0);
}
obstacle.id = this.obstacles.length;
this.obstacles.push(obstacle);
}
return obstacleNo;
}
processObstacles() {
this.kdTree.buildObstacleTree();
};
queryVisibility(point1: Vector2, point2: Vector2, radius: number) {
return this.kdTree.queryVisibility(point1, point2, radius);
};
getObstacles() {
return this.obstacles;
}
clear() {
this.agentIdLst.length = 0;
this.agentId = 0;
this.aid2agent = Object.create(null);
this.defaultAgent = null;
this.kdTree = new KdTree();
this.obstacles.length = 0;
}
}

@ -0,0 +1,12 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "c9717561-2e5e-441e-b1de-1b3ca6ee543f",
"files": [],
"subMetas": {},
"userData": {
"moduleId": "project:///assets/Scripts/GameCore/RVO2/Simulator.js",
"simulateGlobals": []
}
}

@ -0,0 +1,391 @@
import { RVOMath, Obstacle, Vector2 } from "./Common";
import { Simulator } from "./Simulator";
import { Agent } from "./Agent";
class FloatPair {
a: number;
b: number;
constructor(a: number, b: number) {
this.a = a;
this.b = b;
}
lessThan(rhs: FloatPair) {
return this.a < rhs.a || !(rhs.a < this.a) && this.b < rhs.b;
}
lessEqualThan(rhs: FloatPair) {
return (this.a == rhs.a && this.b == rhs.b) || this.lessThan(rhs);
}
bigThan(rhs: FloatPair) {
return !this.lessEqualThan(rhs);
}
bigEqualThan(rhs: FloatPair) {
return !this.lessThan(rhs);
}
}
class AgentTreeNode {
begin: number;
end: number;
left: number;
right: number;
maxX: number;
maxY: number;
minX: number;
minY: number;
}
class ObstacleTreeNode {
obstacle: Obstacle;
left: ObstacleTreeNode;
right: ObstacleTreeNode;
}
export class KdTree {
/**
* The maximum size of an agent k-D tree leaf.
*/
MAX_LEAF_SIZE = 10;
agents: Agent[] = null;
agentTree: AgentTreeNode[] = [];
obstacleTree: ObstacleTreeNode = null;
buildAgentTree(agentNum: number) {
if (!this.agents || this.agents.length != agentNum) {
this.agents = new Array<Agent>(agentNum);
for(let i = 0; i < this.agents.length; i++) {
this.agents[i] = Simulator.instance.getAgent(i);
}
this.agentTree = new Array<AgentTreeNode>(2 * this.agents.length);
for (let i = 0; i < this.agentTree.length; i++) {
this.agentTree[i] = new AgentTreeNode();
}
}
if (this.agents.length != 0) {
this.buildAgentTreeRecursive(0, this.agents.length, 0);
}
}
buildObstacleTree() {
this.obstacleTree = new ObstacleTreeNode();
let obstacles = new Array<Obstacle>(Simulator.instance.obstacles.length);
for(let i = 0; i < obstacles.length; i++) {
obstacles[i] = Simulator.instance.obstacles[i];
}
this.obstacleTree = this.buildObstacleTreeRecursive(obstacles);
}
computeAgentNeighbors(agent: Agent, rangeSq: number) {
return this.queryAgentTreeRecursive(agent, rangeSq, 0);
}
computeObstacleNeighbors(agent: Agent, rangeSq: number) {
this.queryObstacleTreeRecursive(agent, rangeSq, this.obstacleTree);
}
queryVisibility (q1: Vector2, q2: Vector2, radius: number) {
return this.queryVisibilityRecursive(q1, q2, radius, this.obstacleTree);
}
buildAgentTreeRecursive(begin: number, end: number, node: number) {
this.agentTree[node].begin = begin;
this.agentTree[node].end = end;
this.agentTree[node].minX = this.agentTree[node].maxX = this.agents[begin].position_.x;
this.agentTree[node].minY = this.agentTree[node].maxY = this.agents[begin].position_.y;
for (let i = begin + 1; i < end; ++i) {
this.agentTree[node].maxX = Math.max(this.agentTree[node].maxX, this.agents[i].position_.x);
this.agentTree[node].minX = Math.min(this.agentTree[node].minX, this.agents[i].position_.x);
this.agentTree[node].maxY = Math.max(this.agentTree[node].maxY, this.agents[i].position_.y);
this.agentTree[node].minY = Math.min(this.agentTree[node].minY, this.agents[i].position_.y);
}
if (end - begin > this.MAX_LEAF_SIZE) {
// no leaf node
let isVertical = (this.agentTree[node].maxX - this.agentTree[node].minX) > (this.agentTree[node].maxY - this.agentTree[node].minY);
let splitValue = 0.5 * (isVertical ? this.agentTree[node].maxX + this.agentTree[node].minX : this.agentTree[node].maxY + this.agentTree[node].minY);
let left = begin;
let right = end;
while (left < right) {
while (left < right && (isVertical ? this.agents[left].position_.x : this.agents[left].position_.y) < splitValue) {
++left;
}
while (right > left && (isVertical ? this.agents[right - 1].position_.x : this.agents[right - 1].position_.y) >= splitValue) {
--right;
}
if (left < right) {
let tmp = this.agents[left];
this.agents[left] = this.agents[right - 1];
this.agents[right - 1] = tmp;
++left;
--right;
}
}
let leftSize = left - begin;
if (leftSize == 0) {
++leftSize;
++left;
++right;
}
this.agentTree[node].left = node + 1;
this.agentTree[node].right = node + 2 * leftSize;
this.buildAgentTreeRecursive(begin, left, this.agentTree[node].left);
this.buildAgentTreeRecursive(left, end, this.agentTree[node].right);
}
}
buildObstacleTreeRecursive(obstacles: Obstacle[]) {
if (obstacles.length == 0) {
return null;
}
else {
let node = new ObstacleTreeNode();
let optimalSplit = 0;
let minLeft = obstacles.length;
let minRight = minLeft;
for (let i = 0; i < obstacles.length; ++i) {
let leftSize = 0;
let rightSize = 0;
let obstacleI1 = obstacles[i];
let obstacleI2 = obstacleI1.next;
for (let j = 0; j < obstacles.length; j++) {
if (i == j) {
continue;
}
let obstacleJ1 = obstacles[j];
let obstacleJ2 = obstacleJ1.next;
let j1LeftOfI = RVOMath.leftOf(obstacleI1.point, obstacleI2.point, obstacleJ1.point);
let j2LeftOfI = RVOMath.leftOf(obstacleI1.point, obstacleI2.point, obstacleJ2.point);
if (j1LeftOfI >= -RVOMath.RVO_EPSILON && j2LeftOfI >= -RVOMath.RVO_EPSILON) {
++leftSize;
}
else if (j1LeftOfI <= RVOMath.RVO_EPSILON && j2LeftOfI <= RVOMath.RVO_EPSILON) {
++rightSize;
}
else {
++leftSize;
++rightSize;
}
let fp1 = new FloatPair(Math.max(leftSize, rightSize), Math.min(leftSize, rightSize));
let fp2 = new FloatPair(Math.max(minLeft, minRight), Math.min(minLeft, minRight));
if (fp1.bigEqualThan(fp2)) {
break;
}
}
let fp1 = new FloatPair(Math.max(leftSize, rightSize), Math.min(leftSize, rightSize));
let fp2 = new FloatPair(Math.max(minLeft, minRight), Math.min(minLeft, minRight));
if (fp1.lessThan(fp2)) {
minLeft = leftSize;
minRight = rightSize;
optimalSplit = i;
}
}
{
/* Build split node. */
let leftObstacles: Obstacle[] = [];
for (let n = 0; n < minLeft; ++n) leftObstacles.push(null);
let rightObstacles: Obstacle[] = [];
for (let n = 0; n < minRight; ++n) rightObstacles.push(null);
let leftCounter = 0;
let rightCounter = 0;
let i = optimalSplit;
let obstacleI1 = obstacles[i];
let obstacleI2 = obstacleI1.next;
for (let j = 0; j < obstacles.length; ++j) {
if (i == j) {
continue;
}
let obstacleJ1 = obstacles[j];
let obstacleJ2 = obstacleJ1.next;
let j1LeftOfI = RVOMath.leftOf(obstacleI1.point, obstacleI2.point, obstacleJ1.point);
let j2LeftOfI = RVOMath.leftOf(obstacleI1.point, obstacleI2.point, obstacleJ2.point);
if (j1LeftOfI >= -RVOMath.RVO_EPSILON && j2LeftOfI >= -RVOMath.RVO_EPSILON) {
leftObstacles[leftCounter++] = obstacles[j];
}
else if (j1LeftOfI <= RVOMath.RVO_EPSILON && j2LeftOfI <= RVOMath.RVO_EPSILON) {
rightObstacles[rightCounter++] = obstacles[j];
}
else {
/* Split obstacle j. */
let t = RVOMath.det(obstacleI2.point.minus(obstacleI1.point), obstacleJ1.point.minus(obstacleI1.point)) /
RVOMath.det(obstacleI2.point.minus(obstacleI1.point), obstacleJ1.point.minus(obstacleJ2.point));
let splitpoint = obstacleJ1.point.plus( (obstacleJ2.point.minus(obstacleJ1.point)).scale(t) );
let newObstacle = new Obstacle();
newObstacle.point = splitpoint;
newObstacle.previous = obstacleJ1;
newObstacle.next = obstacleJ2;
newObstacle.convex = true;
newObstacle.direction = obstacleJ1.direction;
newObstacle.id = Simulator.instance.obstacles.length;
Simulator.instance.obstacles.push(newObstacle);
obstacleJ1.next = newObstacle;
obstacleJ2.previous = newObstacle;
if (j1LeftOfI > 0.0) {
leftObstacles[leftCounter++] = obstacleJ1;
rightObstacles[rightCounter++] = newObstacle;
}
else {
rightObstacles[rightCounter++] = obstacleJ1;
leftObstacles[leftCounter++] = newObstacle;
}
}
}
node.obstacle = obstacleI1;
node.left = this.buildObstacleTreeRecursive(leftObstacles);
node.right = this.buildObstacleTreeRecursive(rightObstacles);
return node;
}
}
}
queryAgentTreeRecursive(agent: Agent, rangeSq: number, node: number) {
if (this.agentTree[node].end - this.agentTree[node].begin <= this.MAX_LEAF_SIZE) {
for (let i = this.agentTree[node].begin; i < this.agentTree[node].end; ++i) {
rangeSq = agent.insertAgentNeighbor(this.agents[i], rangeSq);
}
}
else {
let distSqLeft = RVOMath.sqr(Math.max(0, this.agentTree[this.agentTree[node].left].minX - agent.position_.x)) +
RVOMath.sqr(Math.max(0, agent.position_.x - this.agentTree[this.agentTree[node].left].maxX)) +
RVOMath.sqr(Math.max(0, this.agentTree[this.agentTree[node].left].minY - agent.position_.y)) +
RVOMath.sqr(Math.max(0, agent.position_.y - this.agentTree[this.agentTree[node].left].maxY));
let distSqRight = RVOMath.sqr(Math.max(0, this.agentTree[this.agentTree[node].right].minX - agent.position_.x)) +
RVOMath.sqr(Math.max(0, agent.position_.x - this.agentTree[this.agentTree[node].right].maxX)) +
RVOMath.sqr(Math.max(0, this.agentTree[this.agentTree[node].right].minY - agent.position_.y)) +
RVOMath.sqr(Math.max(0, agent.position_.y - this.agentTree[this.agentTree[node].right].maxY));
if (distSqLeft < distSqRight) {
if (distSqLeft < rangeSq) {
rangeSq = this.queryAgentTreeRecursive(agent, rangeSq, this.agentTree[node].left);
if (distSqRight < rangeSq) {
rangeSq = this.queryAgentTreeRecursive(agent, rangeSq, this.agentTree[node].right);
}
}
}
else {
if (distSqRight < rangeSq) {
rangeSq = this.queryAgentTreeRecursive(agent, rangeSq, this.agentTree[node].right);
if (distSqLeft < rangeSq) {
rangeSq = this.queryAgentTreeRecursive(agent, rangeSq, this.agentTree[node].left);
}
}
}
}
return rangeSq;
}
// pass ref range
queryObstacleTreeRecursive(agent: Agent, rangeSq: number, node: ObstacleTreeNode) {
if (node == null) {
return rangeSq;
}
else {
let obstacle1 = node.obstacle;
let obstacle2 = obstacle1.next;
let agentLeftOfLine = RVOMath.leftOf(obstacle1.point, obstacle2.point, agent.position_);
rangeSq = this.queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0 ? node.left : node.right));
let distSqLine = RVOMath.sqr(agentLeftOfLine) / RVOMath.absSq(obstacle2.point.minus(obstacle1.point));
if (distSqLine < rangeSq)
{
if (agentLeftOfLine < 0)
{
/*
* Try obstacle at this node only if is on right side of
* obstacle (and can see obstacle).
*/
agent.insertObstacleNeighbor(node.obstacle, rangeSq);
}
/* Try other side of line. */
this.queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0 ? node.right : node.left));
}
return rangeSq;
}
}
queryVisibilityRecursive(q1: Vector2, q2: Vector2, radius: number, node: ObstacleTreeNode) {
if (node == null) {
return true;
}
else {
let obstacle1 = node.obstacle;
let obstacle2 = obstacle1.next;
let q1LeftOfI = RVOMath.leftOf(obstacle1.point, obstacle2.point, q1);
let q2LeftOfI = RVOMath.leftOf(obstacle1.point, obstacle2.point, q2);
let invLengthI = 1.0 / RVOMath.absSq(obstacle2.point.minus(obstacle1.point));
if (q1LeftOfI >= 0 && q2LeftOfI >= 0)
{
return this.queryVisibilityRecursive(q1, q2, radius, node.left) && ((RVOMath.sqr(q1LeftOfI) * invLengthI >= RVOMath.sqr(radius) && RVOMath.sqr(q2LeftOfI) * invLengthI >= RVOMath.sqr(radius)) || this.queryVisibilityRecursive(q1, q2, radius, node.right));
}
else if (q1LeftOfI <= 0 && q2LeftOfI <= 0)
{
return this.queryVisibilityRecursive(q1, q2, radius, node.right) && ((RVOMath.sqr(q1LeftOfI) * invLengthI >= RVOMath.sqr(radius) && RVOMath.sqr(q2LeftOfI) * invLengthI >= RVOMath.sqr(radius)) || this.queryVisibilityRecursive(q1, q2, radius, node.left));
}
else if (q1LeftOfI >= 0 && q2LeftOfI <= 0)
{
/* One can see through obstacle from left to right. */
return this.queryVisibilityRecursive(q1, q2, radius, node.left) && this.queryVisibilityRecursive(q1, q2, radius, node.right);
}
else
{
let point1LeftOfQ = RVOMath.leftOf(q1, q2, obstacle1.point);
let point2LeftOfQ = RVOMath.leftOf(q1, q2, obstacle2.point);
let invLengthQ = 1.0 / RVOMath.absSq(q2.minus(q1));
return (point1LeftOfQ * point2LeftOfQ >= 0 && RVOMath.sqr(point1LeftOfQ) * invLengthQ > RVOMath.sqr(radius) && RVOMath.sqr(point2LeftOfQ) * invLengthQ > RVOMath.sqr(radius) && this.queryVisibilityRecursive(q1, q2, radius, node.left) && this.queryVisibilityRecursive(q1, q2, radius, node.right));
}
}
}
}

@ -0,0 +1,12 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "a7ee4e36-baac-4720-ba0f-7f779a7fd328",
"files": [],
"subMetas": {},
"userData": {
"moduleId": "project:///assets/Scripts/GameCore/RVO2/kdtree.js",
"simulateGlobals": []
}
}

12
assets/Scripts/Test.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "5180adb3-56df-4480-bc8e-b139f7d65ac4",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,211 @@
import { instantiate, Intersection2D, Node, NodePool, Prefab, Rect, resources, UITransform, Vec3, view } from "cc";
import ArrayUtil from "../core/utils/ArrayUtil";
import { monsterCtl } from "./monsterCtl";
import Game from "./Test2";
interface MonsterPool {
name: string;
pool: NodePool;
}
export default class MonsterFactory {
private static instance: MonsterFactory = null;
public static get Instance(): MonsterFactory {
if (this.instance == null)
this.instance = new MonsterFactory();
return this.instance;
}
MonsterPoolList: Array<MonsterPool> = new Array<MonsterPool>();
monsterParent: Node;
monsterDataCountList = {}; //每种怪物的数量数据
monsterAllList: Array<monsterCtl> = new Array<monsterCtl>(); //所有的怪物;
screenMonsterAllList: Array<monsterCtl> = new Array<monsterCtl>(); //屏幕里面的怪物;
arrayMonsterList: Array<Array<monsterCtl>> = new Array<Array<monsterCtl>>();
currenTime = -30;
currentIndex = 0;//当前刷新到了第几次
weekCount = 0; //第几次循环
constructor() {
// this.monsterParent = find("Canvas/Game/monsterCtl");
this.monsterParent = Game.Instance.monsterRootNode
}
getMonsterCountByName(name) {
let index = 0;
for (let i = 0; i < this.monsterAllList.length; i++) {
if (this.monsterAllList[i].node.name == name) {
index++;
}
}
return index;
}
clear() {
this.currenTime = -30;
this.currentIndex = 0;
this.weekCount = 0;
for (let i = 0; i < this.monsterAllList.length; i++) {
let monsterCtl = this.monsterAllList[i];
this.recoverNode(monsterCtl.node);
i--;
}
this.monsterDataCountList = {};
this.monsterAllList = new Array<monsterCtl>();
this.arrayMonsterList = new Array<Array<monsterCtl>>();
this.screenMonsterAllList = new Array<monsterCtl>()
}
update(dt) {
}
creatorMonsterByName(name, pos: Vec3, call?) {
let pool: NodePool = this.getEfPoolByName(name);
let node: Node = pool.get();
if (this.monsterDataCountList[name] == null) {
this.monsterDataCountList[name] = 0;
}
this.monsterDataCountList[name]++;
let resetNode = (ef: Node) => {
ef.parent = this.monsterParent;
ef.active = true;
ef.setPosition(pos.x, pos.y);
call && call(ef);
let mstCtl = ef.getComponent(monsterCtl)
if (mstCtl) {
mstCtl.reuse()
this.monsterAllList.push(mstCtl);
} else {
console.error("monster has none monster ctl...")
}
};
if (node == null) {
resources.load("prefab/monster/" + name, Prefab, (err, resPrefab) => {
node = instantiate(resPrefab)
resetNode(node)
})
}
else {
// console.log("从缓存池创建...")
resetNode(node);
}
}
getEfPoolByName(name) {
let efPool: NodePool = null;
for (let i = 0; i < this.MonsterPoolList.length; i++) {
if (name == this.MonsterPoolList[i].name) {
efPool = this.MonsterPoolList[i].pool;
break
}
}
if (efPool == null) {
efPool = new NodePool();
this.MonsterPoolList.push({
name: name,
pool: efPool
})
}
return efPool;
}
/**
*
* @param node
*/
recoverNode(node) {
let name = node.name;
if (this.monsterDataCountList[node.name]) {
this.monsterDataCountList[node.name]--;
}
for (let i = 0; i < this.MonsterPoolList.length; i++) {
if (name == this.MonsterPoolList[i].name) {
node.active = false;
this.MonsterPoolList[i].pool.put(node);
let com = node.getComponent(monsterCtl);
let index = this.monsterAllList.indexOf(com);
if (index != -1) {
ArrayUtil.fastRemoveAt(this.monsterAllList, index)
// this.monsterAllList.splice(index, 1);
}
break;
}
}
}
/**
*
* @param node
*/
getInViewMonster(node: Node = null) {
let tNode = node ? node : Game.Instance.Player.node
this.screenMonsterAllList = [];
this.arrayMonsterList = new Array<Array<monsterCtl>>();
let pos = tNode.getComponent(UITransform).convertToWorldSpaceAR(new Vec3());
let v2 = view.getViewportRect();
let realView = new Vec3(v2.width, v2.height, 0);
let allRect = new Rect(pos.x - realView.x / 2, pos.y - realView.y / 2, realView.x, realView.y);
let cutRectMonterList = new Array<monsterCtl>();
this.arrayMonsterList.push(cutRectMonterList);
for (let j = 0; j < this.monsterAllList.length; j++) {
let monsterCtl = this.monsterAllList[j];
let monsterRect = monsterCtl.getCircle(true);
//顺便获取屏幕里面的怪
if (Intersection2D.rectCircle(allRect, monsterRect.pos, monsterRect.radius)) {
this.screenMonsterAllList.push(monsterCtl);
}
}
}
cutRectCount = 2;
getCutRectList(node) {
this.screenMonsterAllList = [];
this.arrayMonsterList = new Array<Array<monsterCtl>>();
let pos = node.getComponent(UITransform).convertToWorldSpaceAR(new Vec3());
let v2 = view.getViewportRect();
let realView = new Vec3(v2.width, v2.height, 0);
let allRect = new Rect(pos.x - realView.x / 2, pos.y - realView.y / 2, realView.x, realView.y);
let rect1 = new Rect(pos.x - realView.x, pos.y, realView.x, realView.y);
let rect2 = new Rect(pos.x, pos.y, realView.x, realView.y);
let rect3 = new Rect(pos.x - realView.x, pos.y - realView.y, realView.x, realView.y);
let rect4 = new Rect(pos.x, pos.y - realView.y, realView.x, realView.y);
let rectList = [rect1, rect2, rect3, rect4];
for (let i = 0; i < rectList.length; i++) {
let rect = rectList[i];
let cutRectMonterList = new Array<monsterCtl>();
this.arrayMonsterList.push(cutRectMonterList);
for (let j = 0; j < this.monsterAllList.length; j++) {
let monsterCtl = this.monsterAllList[j];
let monsterRect = monsterCtl.getCircle();
// let result = rect.intersects(monsterRect);
// rect.polygonCircle
let result = Intersection2D.rectCircle(rect, monsterRect.pos, monsterRect.radius)
//改为矩形圆形判断
if (result) {
cutRectMonterList.push(monsterCtl);
monsterCtl.cutRectMonterList = cutRectMonterList;
}
//顺便获取屏幕里面的怪
if (i == 0) {
if (Intersection2D.rectCircle(allRect, monsterRect.pos, monsterRect.radius)) {
this.screenMonsterAllList.push(monsterCtl);
}
}
}
}
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "411ec7f5-0831-42e0-92ab-00f47d9173c5",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,90 @@
import { Camera, Component, dynamicAtlasManager, Node, _decorator } from 'cc';
import WaveMng from '../logics/mng/WaveMng';
import { player } from '../rolectl/player';
import { Vector2 } from '../RVO/Common';
import { Simulator } from '../RVO/Simulator';
import { monsterCtl } from './monsterCtl';
const { ccclass, property } = _decorator;
// 关闭web的动态合图
// dynamicAtlasManager.enabled = false
export default class Game {
public limitMonst: number = 400
private static instance: Game = null;
public static get Instance(): Game {
if (this.instance == null)
this.instance = new Game();
return this.instance;
}
private _Player: player;
public get Player(): player {
return this._Player;
}
public set Player(value: player) {
this._Player = value;
}
private _monsterRootNode: Node;
public get monsterRootNode(): Node {
return this._monsterRootNode;
}
public set monsterRootNode(value: Node) {
this._monsterRootNode = value;
}
private _camera: Camera;
public get camera(): Camera {
return this._camera;
}
public set camera(value: Camera) {
this._camera = value;
}
}
@ccclass('Test2')
export class Test2 extends Component {
@property(Camera)
camera: Camera;
@property(Node)
avatarLayer: Node;
@property(player)
player: player
onEnable() {
Game.Instance.Player = this.player
Game.Instance.monsterRootNode = this.avatarLayer
Game.Instance.camera = this.camera// this.node.getComponent(this.camera)
}
onDisable() {
}
_bigRedBall: Node
start() {
// let simulator = Simulator.instance;
Simulator.instance.setAgentDefaults(60, 3, 1, 0.1, 14, 80, new Vector2(0, 0));
}
_framTimes = 0
_dt: number = 0
update(dt: number) {
//测试怪物生成RVO
this._dt += dt
if (this._dt > 0.5) {
this._dt = 0
this.getComponent(WaveMng).createMonster()
}
// 更新逻辑坐标
Simulator.instance.run(dt);
this._framTimes = 0
for (let index = 0; index < Game.Instance.Player.monsterList.length; index++) {
const monster = Game.Instance.Player.monsterList[index];
monster.getComponent(monsterCtl).moveByRvo()
}
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "1928e6fa-5abf-447e-9276-7b784ea79f1d",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,206 @@
import { Component, Vec2, Vec3, _decorator, v2, v3 } from 'cc';
import { RVOMath } from '../RVO/Common';
import { Simulator } from '../RVO/Simulator';
import Util from '../core/utils/Util';
import MonsterFactory from './MonsterFactory';
import Game from './Test2';
import { monsterEffectCtl } from './monsterEffectCtl';
const { ccclass, property } = _decorator;
@ccclass('monsterCtl')
export class monsterCtl extends Component {
private _hp: number = 5;
public get hp(): number {
return this._hp;
}
public set hp(value: number) {
this._hp = value;
}
// private state : number =
//测试受击
// hurtCoolTime = 0.15;
// hurtTime = 0.2;
hurtCoolTime = 0.15;
hurtTime = 0.2;
private _hit: boolean = false
private _hitPow: number = 3 //受击系数 系数越高 反弹力度越大
private orScale: Vec3 = v3(1, 1, 1)
public cutRectMonterList = []
private _agentHandleId: number = -1; //RVOid
public get agentHandleId(): number {
return this._agentHandleId;
}
public set agentHandleId(value: number) {
this._agentHandleId = value;
}
start() {
this.orScale = this.node.scale
this._effectCtl = this.node.getComponent(monsterEffectCtl)
}
_effectCtl: monsterEffectCtl
reuse() {
this._hit = false
this.hurtTime = 0
this._effectCtl = this.node.getComponent(monsterEffectCtl)
if (this._effectCtl)
this._effectCtl.reuse()
}
/**
*
*/
getRect() {
let agent = Simulator.instance.getAgentByAid(this.agentHandleId)
if (agent) {
return agent.radius_
}
}
_tmpV2: Vec2 = new Vec2()
getCircle(world: boolean = false) {
let agent = Simulator.instance.getAgentByAid(this.agentHandleId)
if (agent) {
if (world) {
return { pos: Util.v3t2(this.node.worldPosition, this._tmpV2), radius: agent.radius_ }
} else {
return { pos: Util.v3t2(this.node.position, this._tmpV2), radius: agent.radius_ }
}
} else {
console.error("monster Circle error...")
return null
}
}
_frames: number = 0
update(deltaTime: number) {
this.hurtTime -= deltaTime
if (this._hit) {//设置 反向并且衰减的 线速度
this.setPreferredVelocities(this._hitPow)//this._hitPow * this.hurtTime / this.hurtCoolTime
if (this.hurtTime <= 0) {
this._hit = false
}
} else {
if (this._frames++ > 8) {
this._frames = 0
this.setPreferredVelocities()//设置追踪主角的线速度
//确定朝向
}
}
}
/**
* 线
*/
_tmpScale: Vec3 = new Vec3()
setPreferredVelocities(hitPow: number = null) {
if (this.agentHandleId < 0) {
return
}
this._tmpScale = this.node.getScale()
let agentAid = this.agentHandleId
let agent = Simulator.instance.getAgentByAid(agentAid)
let agentPos = Simulator.instance.getAgentPosition(agentAid)
let moveTarget: Vec2 = v2(Game.Instance.Player.node.getPosition().x, Game.Instance.Player.node.getPosition().y)
//受击状态的线速度处理
if (hitPow) {
if (agent && agentPos) {
let goalVector: Vec2 = moveTarget.subtract2f(agentPos.x, agentPos.y)// this.goals[i].minus(Simulator.instance.getAgentPosition(agentAid));
goalVector = goalVector.normalize().multiplyScalar(agent.maxSpeed_ * -hitPow);
Simulator.instance.setAgentPrefVelocity(agentAid, goalVector);
}
return
}
if (agent && agentPos) {
let goalVector: Vec2 = moveTarget.subtract2f(agentPos.x, agentPos.y)// this.goals[i].minus(Simulator.instance.getAgentPosition(agentAid));
if (goalVector.lengthSqr() > 1.0) {
goalVector = goalVector.normalize().multiplyScalar(agent.maxSpeed_);
}
if (goalVector.lengthSqr() < RVOMath.RVO_EPSILON) {
Simulator.instance.setAgentPrefVelocity(agentAid, Vec2.ZERO);
}
else {
Simulator.instance.setAgentPrefVelocity(agentAid, goalVector);
//这个会导致抖动呀 宝贝...
// let angle = Math.random() * 2.0 * Math.PI;
// let dist = Math.random() * 0.0001;
// Simulator.instance.setAgentPrefVelocity(i,
// Simulator.instance.getAgentPrefVelocity(i).plus(new Vector2(Math.cos(angle), Math.sin(angle)).scale(dist)));
}
if (goalVector.x > 0) {
this.node.setScale(this._tmpScale.set(Math.abs(this._tmpScale.x), this._tmpScale.y, this._tmpScale.z))
} else {
this.node.setScale(this._tmpScale.set(-Math.abs(this._tmpScale.x), this._tmpScale.y, this._tmpScale.z))
}
} else {
console.error("RVO异常::", agent, agentPos, agentAid)
}
// }
}
/**
* Simulator run执行完毕
*/
moveByRvo() {
// console.log("p::", p, Simulator.instance.getAgentPosition(this.agentHandleId))
let p = Simulator.instance.getAgentPosition(this.agentHandleId);
this.node.setPosition(p.x, p.y)
}
/**
* ...
*/
hurtAction() {
let randEfIdx = Math.random()
let mstEffectCtl = this.node.getComponent(monsterEffectCtl)
if (mstEffectCtl) {
if (randEfIdx > 0.5) {
mstEffectCtl.playHit()
} else {
mstEffectCtl.playFroze()
}
}
}
hurt(): boolean {
// if (!this.)
if (this.hurtTime > 0) { //受击冷却中
return
}
this.hurtTime = this.hurtCoolTime
this._hp--
if (this._hp <= 0) {
this.rmMonster()
return true
} else {
this.hurtAction()
this._hit = true
return false
}
}
rmMonster() {
this._effectCtl.disove(() => {
if (this.agentHandleId >= 0) {
Simulator.instance.removeAgent(this.agentHandleId)
// console.log("移除RVO对象::", this.agentHandleId)
}
MonsterFactory.Instance.recoverNode(this.node)
})
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "cc093bda-87cd-4315-9b9e-178cd9fe6791",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,136 @@
import { Component, Material, Sprite, UIOpacity, Vec4, _decorator, color, math, tween } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('monsterEffectCtl')
export class monsterEffectCtl extends Component {
_mt: Material = null
_spCmp: Sprite = null
private _hited: boolean;
private _froze: boolean;
private _optCmp: UIOpacity = null;
start() {
this._spCmp = this.node.getComponent(Sprite)
// this._optCmp = this.node.addComponent(UIOpacity)
// this._mt = this.node.getComponent(Sprite).getMaterialInstance(0)//这个打断合批...
}
reuse() {
this.start()
// this._hited = this._froze = false
// this._frozeDt = this._hitDt = 0
// this._mt = this.node.getComponent(Sprite).getMaterialInstance(0)
//关闭蓝色内发光 关闭闪白
this._spCmp.color = color(255, 255, 255, 1)
}
/**
*
*/
_showHitTotalTime: number = 0.15
playHit() {
//方式一 setProperty 打断合批
//需要放开 start()中的 this._mt = this.node.getComponent(Sprite).getMaterialInstance(0)
// tween(this._mt).to(this._showHitTotalTime, {}, {
// onUpdate(target: Material, ratio) {
// target.setProperty("hitwhit", ratio)
// },
// }).call(() => {
// this._mt.setProperty("hitwhit", 0.0)
// }).start()
//方式二 占用alpha通道
let tSpCmp = this._spCmp // this.node.getComponent(Sprite)
tSpCmp.color = color(255, 255, 255, 1)
let tmpColor: math.Color = color(255, 255, 255, 244)
tween(tSpCmp).to(this._showHitTotalTime, {}, {
onUpdate(target: Sprite, ratio) {
tmpColor = color(255, 255, 255, 255 * ratio)
target.color = tmpColor
},
}).call(() => {
tmpColor = color(255, 255, 255, 1)
tSpCmp.color = tmpColor
}).start()
}
/**
* ()
*/
frozeColor: Vec4 = Vec4.ZERO;
_showFrozeTime: number = 10
_frozeDt: number = 0
playFroze() {
//占用r通道 r在0~25.5之间 开启蓝色内光
let tSpCmp = this._spCmp
let tmpColor: math.Color = null
tSpCmp.color = color(1, tSpCmp.color.g, tSpCmp.color.b, tSpCmp.color.a)
tween(tSpCmp).to(this._showFrozeTime, {}, {}).call(() => {
tmpColor = color(255, 255, 255, tSpCmp.color.a)
tSpCmp.color = tmpColor
}).start()
}
/**
*
*/
_disoveTime: number = 1
disove(cb?: Function) {
//占用g通道
let tSpCmp = this._spCmp
tSpCmp.color = color(this._spCmp.color.r, 1, this._spCmp.color.b, this._spCmp.color.a)
let tmpColor: math.Color = null
tween(tSpCmp).to(this._disoveTime, {}, {
onUpdate(target: Sprite, ratio) {
tmpColor = color(255, 254 * ratio, 255, 255)
target.color = tmpColor
},
}).call(() => {
if (cb) {
cb()
}
// tmpColor = color(255, 255, 255, 1)
// tSpCmp.color = tmpColor
}).start()
}
/**
*
*
*
*/
_hitDt: number
update(dt: number) {
// this._mt = this.node.getComponent(Sprite).getMaterial(0)
// if (this._hited) {
// this._hitDt += dt
// let percent = this._hitDt / this._showHitTotalTime
// percent = Math.min(Math.max(percent, 0.), 1.)
// this._mt.setProperty("hitwhit", percent)
// if (percent >= 1) {
// this._hitDt = 0
// this._hited = false
// this._mt.setProperty("hitwhit", 0.0)
// }
// }
// if (this._froze) {
// this._frozeDt += dt
// this._mt.setProperty("glowColor", this.frozeColor)
// if (this._frozeDt > this._showFrozeTime) {
// this._frozeDt = 0
// this._mt.setProperty("glowColor", Vec4.ZERO)
// this._froze = false
// }
// }
// console.log("this.mt::" , this._mt)
// this.node.getComponent(Sprite).setMaterial(this._mt,0)
}
}

@ -0,0 +1 @@
{"ver":"4.0.23","importer":"typescript","imported":true,"uuid":"eb420a22-bf96-4b6c-b2d9-8bab34bd9a58","files":[],"subMetas":{},"userData":{}}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "a55debe1-4d5f-40e9-9995-8b241ef205c2",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,32 @@
import { Camera, Component, Node, Vec3, _decorator } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('camerafollow')
export class camerafollow extends Component {
offset: Vec3 = new Vec3();
camera: Camera;
@property(Node) folNode: Node = null
start() {
this.camera = this.node.getComponent(Camera);
this.gameStart()
}
gameStart() {
Vec3.subtract(this.offset, this.node.position, this.folNode.position);
}
_tmpV3: Vec3 = new Vec3()
update(deltaTime: number) {
// if (Game.Instance.gameState != GameState.GAME_PLAY || Game.Instance.player == null)
// return;
let targetPos = this._tmpV3;
targetPos = Vec3.add(targetPos, this.offset, this.folNode.position);
Vec3.lerp(targetPos, this.node.position, targetPos, 0.1);
this.node.setPosition(targetPos);
}
clear() {
this.node.position = new Vec3(0, 0, 0);
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "ff6d36e8-a512-4150-9bd8-a29280339aa8",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "36e78f36-d62f-40f9-901c-ea51d2e40bb2",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,170 @@
import { Rect, _decorator } from "cc";
const { ccclass } = _decorator;
@ccclass("QuadTree")
export default class QuadTree {
nodes = [];
objects = []; //該容器的物體集合
max_levels: number; // 最大深度
max_objects: number; // 該容器最大容量
level: number; //當前深度
bounds: Rect = null; // 容器範圍(Rect)
constructor(boundary, level) {
this.max_objects = 4;
this.max_levels = 4;
this.level = level || 0;
this.bounds = boundary;
this.objects = [];
this.nodes = [];
}
insert(pRect) {
var i = 0, indexes;
//if we have subnodes, call insert on matching subnodes
if (this.nodes.length) {
indexes = this.getIndex(pRect);
for (i = 0; i < indexes.length; i++) {
this.nodes[indexes[i]].insert(pRect);
}
return;
}
//otherwise, store object here
this.objects.push(pRect);
//max_objects reached
if (this.objects.length > this.max_objects && this.level < this.max_levels) {
//split if we don't already have subnodes
if (!this.nodes.length) {
this.split();
}
//add all objects to their corresponding subnode
for (i = 0; i < this.objects.length; i++) {
indexes = this.getIndex(this.objects[i]);
for (var k = 0; k < indexes.length; k++) {
this.nodes[indexes[k]].insert(this.objects[i]);
}
}
//clean up this node
this.objects = [];
}
}
split() {
var nextLevel = this.level + 1,
subWidth = this.bounds.width / 2,
subHeight = this.bounds.height / 2,
x = this.bounds.x,
y = this.bounds.y;
//top right node
this.nodes[0] = new QuadTree({
x: x + subWidth,
y: y,
width: subWidth,
height: subHeight
}, nextLevel);
//top left node
this.nodes[1] = new QuadTree({
x: x,
y: y,
width: subWidth,
height: subHeight
}, nextLevel);
//bottom left node
this.nodes[2] = new QuadTree({
x: x,
y: y + subHeight,
width: subWidth,
height: subHeight
}, nextLevel);
//bottom right node
this.nodes[3] = new QuadTree({
x: x + subWidth,
y: y + subHeight,
width: subWidth,
height: subHeight
}, nextLevel);
}
getIndex(pRect) {
var indexes = [],
verticalMidpoint = this.bounds.x + (this.bounds.width / 2),
horizontalMidpoint = this.bounds.y + (this.bounds.height / 2);
var startIsNorth = pRect.y < horizontalMidpoint,
startIsWest = pRect.x < verticalMidpoint,
endIsEast = pRect.x + pRect.width > verticalMidpoint,
endIsSouth = pRect.y + pRect.height > horizontalMidpoint;
//top-right quad
if (startIsNorth && endIsEast) {
indexes.push(0);
}
//top-left quad
if (startIsWest && startIsNorth) {
indexes.push(1);
}
//bottom-left quad
if (startIsWest && endIsSouth) {
indexes.push(2);
}
//bottom-right quad
if (endIsEast && endIsSouth) {
indexes.push(3);
}
return indexes;
}
retrieve(pRect) {
var indexes = this.getIndex(pRect),
returnObjects = this.objects;
//if we have subnodes, retrieve their objects
if (this.nodes.length) {
for (var i = 0; i < indexes.length; i++) {
returnObjects = returnObjects.concat(this.nodes[indexes[i]].retrieve(pRect));
}
}
//remove duplicates
returnObjects = returnObjects.filter(function (item, index) {
return returnObjects.indexOf(item) >= index;
});
return returnObjects;
}
objLen() {
if (this.nodes.length > 0) {
let len = 0;
for (let node of this.nodes) {
len += node.objLen();
}
return len;
} else {
//console.log('this.objects.length------',this.objects.length)
return this.objects.length;
}
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "469a12f5-f4ff-4458-94aa-0a440aaa114b",
"files": [],
"subMetas": {},
"userData": {}
}

12
assets/Scripts/conf.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "898d135e-bd05-458a-9341-3330818414fa",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

12
assets/Scripts/core.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "ac65df09-c708-442b-aecb-03ab39ca0520",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "83df4394-0767-4beb-b866-a462e2cdc935",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "208bfb92-0ad4-43a2-aee6-f6ac8ade12f1",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "52f9fe41-4b8f-4a28-a615-9738f52a1974",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "c447163d-4e7c-4993-ae73-1daf18176e15",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,139 @@
import ArrayUtil from "../utils/ArrayUtil";
interface EventInfo {
func: Function;
target: any;
}
class EventInfoList {
infos: EventInfo[] = null;
constructor() {
this.infos = [];
}
has(cb: Function, target: any) {
if (this.infos.length <= 0) {
return false;
}
for (let i = 0; i < this.infos.length; i++) {
if (this.infos[i].func === cb && this.infos[i].target === target) {
return true;
}
}
return false;
}
/**
*
* @param cb
* @param target
*/
add(cb: Function, target: any) {
if (this.has(cb, target)) {
console.log('event repeat--------')
return;
}
let info = Object.create(null);
info.func = cb;
info.target = target;
this.infos.push(info);
}
/**移除指定 */
remove(cb: Function, target: any) {
if (this.infos.length <= 0) {
return;
}
for (let i = 0; i < this.infos.length; i++) {
if (this.infos[i].func === cb && this.infos[i].target === target) {
ArrayUtil.fastRemoveAt(this.infos, i);
break;
}
}
}
/**移除目标所有 */
removeByTarget(target: any) {
if (this.infos.length <= 0) {
return;
}
for (let i = 0; i < this.infos.length; i++) {
if (this.infos[i].target === target) {
ArrayUtil.fastRemoveAt(this.infos, i);
i--;
}
}
}
/**移除所有 */
removeAll() {
this.infos.forEach(info => {
info.func = null;
info.target = null;
})
this.infos = [];
}
}
export class EventManager {
private _evtMap: { [k: string]: EventInfoList } = Object.create(null);
on(evtType: string, cb: Function, target?: any) {
let list = this._evtMap[evtType];
if (!list) {
list = new EventInfoList();
this._evtMap[evtType] = list;
}
list.add(cb, target);
}
emit(evtType: string, ...params: any) {
let list = this._evtMap[evtType];
if (!list || list.infos.length <= 0) {
return;
}
for (let i = 0; i < list.infos.length; i++) {
let info = list.infos[i];
if (info.func) {
info.func.apply(info.target, params);
}
}
}
/**移除 指定*/
off(evtType: string, cb: Function, target?: any) {
let list = this._evtMap[evtType];
if (!list) return;
list.remove(cb, target);
}
/**事件名或目标移除 */
offByKeyOrTarget(key: string | Object) {
let list: EventInfoList = null;
if (typeof key == 'string') {
list = this._evtMap[key];
if (list) {
list.removeAll();
}
} else {
for (let k in this._evtMap) {
list = this._evtMap[k];
list.removeByTarget(key);
}
}
}
}
/**
* [1] Class member could be defined like this.
* [2] Use `property` decorator if your want the member to be serializable.
* [3] Your initialization goes here.
* [4] Your update function goes here.
*
* Learn more about scripting: https://docs.cocos.com/creator/3.4/manual/zh/scripting/
* Learn more about CCClass: https://docs.cocos.com/creator/3.4/manual/zh/scripting/ccclass.html
* Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.4/manual/zh/scripting/life-cycle-callbacks.html
*/

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "8069a6da-1c33-4e0f-bd20-cbe42cdf93c0",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "a60ec33d-05ca-4c72-af63-b9114ccf5f19",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "592a89e6-ccc0-4774-9ee7-9ae076b12106",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "51ab9e9b-4ad5-4d65-aa54-46a3cdddf83d",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "c84048a4-78cc-469b-b4de-3eacd1548372",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "226f498a-54ae-42df-a53b-444ed7d701dc",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,120 @@
/*
* @Author: dgflash
* @Date: 2021-08-11 16:41:12
* @LastEditors: dgflash
* @LastEditTime: 2022-01-24 15:00:52
*/
/**
*
*/
export default class ArrayUtil {
/** 去重 */
public static noRepeated(arr: any[]) {
var res = [arr[0]];
for (var i = 1; i < arr.length; i++) {
var repeat = false;
for (var j = 0; j < res.length; j++) {
if (arr[i] == res[j]) {
repeat = true;
break;
}
}
if (!repeat) {
res.push(arr[i]);
}
}
return res;
}
/**
*
* @param array
*/
public static copy2DArray(array: any[][]): any[][] {
let newArray: any[][] = [];
for (let i = 0; i < array.length; i++) {
newArray.push(array[i].concat());
}
return newArray;
}
/**
* Fisher-Yates Shuffle
* @param array
*/
public static fisherYatesShuffle(array: any[]): any[] {
let count = array.length;
while (count) {
let index = Math.floor(Math.random() * count--);
let temp = array[count];
array[count] = array[index];
array[index] = temp;
}
return array;
}
/**
*
* @param array
*/
public static confound(array: []): any[] {
let result = array.slice().sort(() => Math.random() - .5);
return result;
}
/**
*
* @param array
*/
public static flattening(array: any[]) {
for (; array.some(v => Array.isArray(v));) { // 判断 array 中是否有数组
array = [].concat.apply([], array); // 压扁数组
}
return array;
}
/** 删除数组中指定项 */
public static removeItem(array: any[], item: any) {
var temp = array.concat();
for (let i = 0; i < temp.length; i++) {
const value = temp[i];
if (item == value) {
array.splice(i, 1);
break;
}
}
}
/**
*
* @param array1 1
* @param array2 2
*/
public static combineArrays(array1: any[], array2: any[]): any[] {
let newArray = [...array1, ...array2];
return newArray;
}
/**
*
* @param array
*/
public static getRandomValueInArray(array: any[]): any {
let newArray = array[Math.floor(Math.random() * array.length)];
return newArray;
}
/**
*
* @param array
* @param idx
* @returns
*/
public static fastRemoveAt(array: any[],idx:number){
let len = array.length-1; //1
if(idx > len) return;
array[idx] = array[len];
array.length = len;
}
}

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "b65cfca1-1091-485a-adbf-aadd39753a50",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,116 @@
export class MathUtil {
/**
*
*/
public static deg2Rad: number = Math.PI / 180;
/**
*
*/
public static rad2Deg: number = 180 / Math.PI;
/**
*
*/
public static sign(x: number) {
if (x > 0) {
return 1;
}
if (x < 0) {
return -1;
}
return 0;
}
/** 随时间变化进度值 */
public static progress(start: number, end: number, t: number) {
return start + (end - start) * t;
}
/**
*
* @param numStart
* @param numEnd
* @param t
*/
public static lerp(numStart: number, numEnd: number, t: number): number {
if (t > 1) {
t = 1;
}
else if (t < 0) {
t = 0
}
return numStart * (1 - t) + (numEnd * t);
}
/**
*
* @param angle1
* @param angle2
* @param t
*/
public static lerpAngle(current: number, target: number, t: number): number {
current %= 360;
target %= 360;
var dAngle: number = target - current;
if (dAngle > 180) {
target = current - (360 - dAngle);
}
else if (dAngle < -180) {
target = current + (360 + dAngle);
}
return (MathUtil.lerp(current, target, t) % 360 + 360) % 360;
}
/**
*
* @param current
* @param target
* @param speed
*/
public static angleTowards(current: number, target: number, speed: number): number {
current %= 360;
target %= 360;
var dAngle: number = target - current;
if (dAngle > 180) {
target = current - (360 - dAngle);
}
else if (dAngle < -180) {
target = current + (360 + dAngle);
}
var dir = target - current;
if (speed > Math.abs(dir)) {
return target;
}
return ((current + speed * Math.sign(dir)) % 360 + 360) % 360;
}
public static clamp(value: number, minLimit: number, maxLimit: number) {
if (value < minLimit) {
return minLimit;
}
if (value > maxLimit) {
return maxLimit;
}
return value;
}
/**
*
* @param value
*/
public static probability(value: number) {
return Math.random() < value;
}
}

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "2df4c13d-eb96-4b3c-bf18-ba3367cc6022",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,231 @@
// Learn TypeScript:
// - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
// - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
// - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html
import { v2, v3, Vec2, Vec3 } from "cc";
export default class Util {
static simpleV2(value, out?: Vec2) {
if (out) {
out.set(value, value)
return out
}
return v2(value, value)
}
static simpleV3(value, out?: Vec3) {
if (out) {
out.set(value, value, value)
return out
}
return v3(value, value, value)
}
static v2t3(v2Data: Vec2, out?: Vec3) {
if (!out) {
return v3(v2Data.x, v2Data.y, 1)
} else {
out.x = v2Data.x
out.y = v2Data.y
out.z = 1
return out
}
}
static v3t2(v3Data: Vec3, out?: Vec2) {
if (!out) {
return v2(v3Data.x, v3Data.y)
} else {
out.x = v3Data.x
out.y = v3Data.y
return out
}
}
/**
* return min - max min和max
* @param min
* @param max
*/
static randomNumber(min: number, max: number) {
if (min == max) {
return min
}
return Math.floor(Math.random() * (max - min + 1) + min)
}
static findArrNullIdx(arr: any[]) {
if (arr.length == 0) return 0;
for (let i = 0; i < arr.length; i++) {
if (!arr[i]) {
return i;
}
}
return -1;
}
//分割number字符串 返回number 数组
public static splitNumber(str: number | string, Separator: string = ',') {
if (!str) return [];
if (typeof str == 'number') {
return [str];
}
return str.split(Separator).map((s_num, idx) => {
return Number(s_num);
})
}
/**
* @param weights
* @returns
*/
static weightRandomIdx(weights: number[]) {
if (weights.length <= 1) {
return 0;
}
let tw: number = 0;
for (let i = 0; i < weights.length; i++) {
tw += weights[i];
}
let rw = Math.random() * tw;
let sw: number = 0, ew: number = 0;
for (let i = 0; i < weights.length; i++) {
ew = sw + weights[i];
if (sw < rw && rw <= ew) {
return i;
}
sw = ew;
}
return 0;
}
/**小数去0 */
public static numMoveZoro(num: string) {
if (num.indexOf('.') < 0) {
return num;
}
num = num.replace(/0+?$/g, '')
if (num[num.length - 1] == '.') {
num = num.replace(/[.$]/, '');
}
return num;
}
/**
*
* @param num h:f:s
*/
public static secondFormat(num: number) {
let str = '';
let h: number = Math.floor(num / 3600)
num -= h * 3600;
let f: number = Math.floor(num / 60)
num -= f * 60;
num = Math.floor(num)
// str += (h<10?'0' + h:h);
// str += ':';
str += (f < 10 ? '0' + f : f);
str += ':';
str += (num < 10 ? '0' + num : num);
return str;
}
/**日期展示 */
public static getDateStr(time: number, format: number = 1) {
let date = new Date(time);
let y = date.getFullYear(), m = date.getMonth() + 1,
d = date.getDate(), h = date.getHours(), mn = date.getMinutes();
let mnStr = '' + mn;
if (mn < 10) mnStr = '0' + mn;
if (format == 1) {
return `${y}/${m}/${d} ${h}:${mnStr}`;
} else {
return `${y}${m}${d}${h}:${mnStr}`;
}
}
static generatorCallBack(len: number, callBack: Function, ...params: any) {
function* gen() {
for (let i = 0; i < len; i++) {
yield callBack(i, ...params)
}
}
return this.exeGenerator(gen(), 10);
}
static exeGenerator(generator: Generator, duration: number) {
return new Promise((resolve, reject) => {
let gen = generator
let execute = () => {
let startTime = new Date().getTime()
for (let iter = gen.next(); ; iter = gen.next()) {
if (iter == null || iter.done) {
resolve(null)
return
}
if (new Date().getTime() - startTime > duration) {
setTimeout(() => {
execute()
}, duration)
return
}
}
}
execute()
})
}
/**
*
* @param src_obj
* @param dst_obj
*/
static copyObj(src_obj: any, dst_obj: any) {
if (typeof dst_obj === "object") {
for (var key in dst_obj) {
if (typeof dst_obj[key] === "object") {
src_obj[key] != null && Util.copyObj(src_obj[key], dst_obj[key]);
} else if (typeof dst_obj[key] != "function") {
src_obj[key] != null && (dst_obj[key] = src_obj[key]);
}
}
} else {
console.log("can not copy the value type");
}
}
/**
*
* @param obj
* @returns
*/
static cloneObj(obj: any) {
var new_obj;
if (obj != null && (obj.constructor === Object || obj.constructor === Array)) {
new_obj = new obj.constructor();
for (var key in obj) {
new_obj[key] = Util.cloneObj(obj[key]);
}
} else {
new_obj = obj;
}
return new_obj;
}
}

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "75224168-75d8-4cf6-bad8-d73031b24457",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "7a60fd5f-89a1-4ee2-8dfa-68a14995f68c",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "3df89b31-a5ec-4394-bbbd-d80e4c3b0b53",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,34 @@
import { Component, _decorator } from "cc";
const { ccclass, property } = _decorator;
/**
*
*/
@ccclass
export default class SortMng extends Component {
private _frameCount: number = 0;
update(dt) {
if (++this._frameCount % 6 == 0) {
this._frameCount = 0
this.sortChildrenByY();
}
}
private sortChildrenByY() {
let listToSort = this.node.children.slice();
listToSort.sort(function (a, b) {
return b.getPosition().y - a.getPosition().y;
});
// console.log("排序::" , listToSort.length)
for (let i = 0; i < listToSort.length; ++i) {
let node = listToSort[i];
if (node.active) {
node.setSiblingIndex(i + 1);
}
}
}
}

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "b52c9552-a69e-490e-957e-eb0e6f08087a",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,126 @@
import { Component, Rect, UITransform, v2, v3, Vec2, Vec3, view, _decorator } from "cc";
import QuadTree from "../../common/QuadTree";
import Util from "../../core/utils/Util";
import { Simulator } from "../../RVO/Simulator";
import { monsterCtl } from "../../Test/monsterCtl";
import MonsterFactory from "../../Test/MonsterFactory";
import Game from "../../Test/Test2";
const { ccclass, property } = _decorator;
/**
*/
@ccclass("WaveMng")
export default class WaveMng extends Component {
public quadTree: QuadTree = null;
private _wHalf: number = 0;
private _hHalf: number = 0;
monsterPrefab: Array<string> = ["A", "B", "C"];
// monsterPrefab: Array<string> = ["A"];
update() {
this.rebuildTree()
}
rebuildTree() {
if (!Game.Instance.camera) {
return
}
let rect = view.getViewportRect()
this.quadTree = new QuadTree(rect, 0);
Game.Instance.Player.monsterList.forEach(enm => {
let rect = enm.getComponent(UITransform).getBoundingBoxToWorld()
let treeObj = { x: rect.x, y: rect.y, height: rect.height, width: rect.width, rect: rect, collider: enm }
this.quadTree.insert(treeObj)
})
}
/**
*/
_tmpV2: Vec2 = new Vec2()
_tmpV3: Vec3 = new Vec3()
createMonster() {
// if (Game.Instance.Player.monsterList.length <= 0) {
// return
if (Game.Instance.Player.monsterList.length >= Game.Instance.limitMonst) {
return
}
// if (this.node.getComponent(WaveMng)) {
let posArray = this.getPos(0, Math.random() * 20 + 10)
let speedCfg = [120, 80 , 80]
let radiusCfg = [20, 18, 18]
let maxHp = 4
// return
for (let idx = 0; idx < posArray.length; idx++) {
let prefabIdx = Math.floor(Math.random() * this.monsterPrefab.length)
let prefabName: string = this.monsterPrefab[prefabIdx]// Math.random() > 0.5 ? this.sphereRed : this.sphereBlue
let speed = speedCfg[prefabIdx]
let radius = radiusCfg[prefabIdx]
let mass = 1
let sacle = 0.5
let checkDis = radius * 2
let hp = Math.floor(Math.random() * maxHp)
if (prefabIdx != 0) {
sacle = 0.5
}
let p = posArray[idx]
let agentId = Simulator.instance.addAgent(Util.v3t2(p, this._tmpV2), radius, speed, null, mass);
let agentObj = Simulator.instance.getAgentByAid(agentId)
agentObj.neighborDist = checkDis //动态修改每个agent的巡视范围
MonsterFactory.Instance.creatorMonsterByName(prefabName, p, (node) => {
node.getComponent(monsterCtl).agentHandleId = agentId
node.getComponent(monsterCtl).hp = hp
node.setScale(Util.simpleV3(sacle, this._tmpV3))
Game.Instance.Player.monsterList.push(node)
})
}
}
/**
*
* @param checkRect
*/
getTreeColliderList(checkRect: Rect) {
if (this.quadTree) {
return this.quadTree.retrieve(checkRect)
}
return []
}
_tmpPosVe3: Array<Vec3> = []
getPos(type: number, numbs: number) {
this._tmpPosVe3.length = 0
const size = view.getVisibleSize();
this._wHalf = size.width * 0.25 + 300 + Math.random() * 300;
this._hHalf = size.height * 0.25 + 200 + Math.random() * 200;
let len = numbs
var w = this._wHalf;//椭圆长
var h = this._hHalf; //椭圆高
var angle = 360 / len;
var x, y;
const point = Game.Instance.Player.node.getPosition();
for (let i = 0; i < len; i++) {
// Mathf.Deg2Rad 单位角度的弧 相当于 1° 的弧度
x = w * Math.cos(i * (angle / 180) * Math.PI);
y = h * Math.sin(i * (angle / 180) * Math.PI);
this._tmpPosVe3.push(v3(x + point.x, y + point.y, 1))
}
return this._tmpPosVe3
}
protected onEnable(): void {
}
protected onDisable(): void {
}
}

@ -0,0 +1,11 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "044954b5-0556-4284-bbdd-f0362ec09a7d",
"files": [],
"subMetas": {},
"userData": {
"simulateGlobals": []
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "7e2691b1-d8ca-4638-b82f-078495072927",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "131cd532-4953-4327-91e0-a3b80ee3e5d2",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "da6ceaaa-4625-4dae-b727-9ae8531388b7",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

12
assets/Scripts/mng.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "a8db4dac-3dca-4f08-b580-72ba8ee0e7bb",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

451
assets/Scripts/mng/wave.ts Normal file

@ -0,0 +1,451 @@
// import { Component, v2, Vec2, view, _decorator } from 'cc';
// import { app } from '../../app';
// import ItemHelper from '../common/ItemHelper';
// import QuadTree from '../common/QuadTree ';
// import { JsonModule } from '../conf/ClientConfigMgr';
// import Util from '../core/utils/Util';
// import Enemy from '../logics/Enemy';
// const { ccclass, property } = _decorator;
// interface IWaveData { //波次数据
// id: number;
// tm: number;
// curTm: number;
// }
// interface IFbMonsterData { //需要创建怪物数据
// pos: Vec2;
// mid: number;
// fid: number;
// }
// @ccclass('NewComponent')
// export class NewComponent extends Component {
// private _enemyList: Enemy[] = null;
// private _target: any = null;
// private _fbArr: IWaveData[] = [];
// private _cTime: number;
// private _createList: IFbMonsterData[] = null; //创建怪物列表
// public checkEnemys: Enemy[] = [];
// public quadTree: QuadTree = null;
// private _wHalf: number = 0;
// private _hHalf: number = 0;
// initial() {
// this._target = app.gameMgr.camera;
// this._fbArr = [];
// this._enemyList = [];
// this._createList = [];
// this._cTime = 0;
// const size = view.getVisibleSize();
// this._wHalf = size.width * 0.25 + 50;
// this._hHalf = size.height * 0.25 + 50;
// // if(ItemHelper.isDoubleMode()){
// // this.startWaves();
// // }
// }
// startWaves() {
// let cfg;
// if (ItemHelper.isDoubleMode()) { //双人模式
// cfg = app.confMgr.conf.fbconfig.getConfById(420001);
// } else { //单人模式
// if (app.dataMgr.battleData.player1.trySuperSkill != null) { //超武试用
// cfg = app.confMgr.conf.fbconfig.getConfById(410001);
// } else {
// let fbConfs = app.confMgr.conf.fbconfig.getConfArr();
// cfg = fbConfs[0];
// }
// }
// this._fbArr.push({ id: cfg.id, tm: cfg.fresh_cd, curTm: 0 });
// }
// gameUpdate(dt) {
// // this._fbArr.forEach(f => {
// // f.curTm += dt;
// // })
// // for (let i = 0; i < this._fbArr.length; i++) {
// // let fb = this._fbArr[i];
// // if (fb.curTm > fb.tm) {
// // ArrayUtil.fastRemoveAt(this._fbArr, i);
// // this.freshCreateWave(fb);
// // break;
// // }
// // }
// let rect = view.getVisibleSize() // app.gameMgr.camera.getViewRect();
// this.quadTree = new QuadTree(rect, 0);
// this.checkEnemys = [];
// this._enemyList.forEach(enemy => {
// enemy.gameUpdate(dt);
// if (!enemy.isDie && enemy.inView) {
// this.checkEnemys.push(enemy);
// this.quadTree.insert(enemy.getCollisionData());
// }
// })
// // console.log('this._enemyList---------',this._enemyList.length,this.checkEnemys.length,this.quadTree.objLen())
// //逐帧创建怪物
// if (this._createList.length > 0) {
// this._cTime += dt;
// if (this._cTime >= 0.01) {
// this._cTime = 0;
// this.createEnemy();
// }
// }
// }
// protected onEnable(): void {
// // systemEvent.on(EventName.gm_create_enemy, this.gmCreateEnemy, this);
// }
// protected onDisable(): void {
// // systemEvent.off(EventName.gm_create_enemy, this.gmCreateEnemy, this);
// }
// gmCreateEnemy(enemyId, count, type) {
// console.log("gmCreateEnemy :: ", enemyId, count, type)
// let obj = Object.create(null);
// obj.id = Math.random() > 0.5 ? 400001 : 400001;
// obj.monster_id = enemyId;
// obj.monster_num = count;
// obj.fresh_site = type;
// if (type == 20) {
// //椭圆
// this.initEllipseEnemys(obj);
// } else if (type == 21) {
// //生成圆形
// this.initCircleEnemy(obj);
// }
// else {
// //范围随机生成
// this.initEnemys(obj);
// }
// }
// /**触发去创建一波 */
// freshCreateWave(fb: { id: number, tm: number, curTm: number }) {
// // let fbconf = app.confMgr.conf.fbconfig.getConfById(fb.id);
// // if (!fbconf) {
// // return;
// // }
// // let nextIdStr: string = fbconf.next_id;
// // if (nextIdStr) {
// // let ids = Util.splitNumber(nextIdStr);
// // for (let i = 0; i < ids.length; i++) {
// // let conf = app.confMgr.conf.fbconfig.getConfById(ids[i]);
// // this._fbArr.push({ id: conf.id, tm: conf.fresh_cd, curTm: 0 });
// // }
// // }
// // console.log('timeToFreshWave--------', fbconf.id)
// // if (fbconf.fresh_site == 20) {
// // this.initEllipseEnemys(fbconf);
// // } else {
// // this.initEnemys(fbconf);
// // }
// }
// /**椭圆包围圈 */
// private initEllipseEnemys(fbconf: JsonModule.IFbconfig) {
// const mIds = Util.splitNumber(fbconf.monster_id);
// const nums = Util.splitNumber(fbconf.monster_num);
// let midArr: number[] = [];
// for (let i = 0; i < nums.length; i++) {
// let l = nums[i], mid = mIds[i];
// for (let j = 0; j < l; j++) {
// midArr.push(mid);
// }
// }
// let len = midArr.length;
// var w = this._wHalf;//椭圆长
// var h = this._hHalf; //椭圆高
// var angle = 360 / len;
// var x, y;
// const point = this._target.node.getPosition();
// for (let i = 0; i < len; i++) {
// // Mathf.Deg2Rad 单位角度的弧 相当于 1° 的弧度
// x = w * Math.cos(i * (angle / 180) * Math.PI);
// y = h * Math.sin(i * (angle / 180) * Math.PI);
// let obj: IFbMonsterData = Object.create(null);
// obj.pos = v2(x + point.x, y + point.y);
// obj.mid = midArr[i];
// obj.fid = fbconf.id;
// this._createList.push(obj)
// }
// }
// /**圆形包围圈 */
// private initCircleEnemy(fbconf: JsonModule.IFbconfig) {
// const mIds = Util.splitNumber(fbconf.monster_id);
// const nums = Util.splitNumber(fbconf.monster_num);
// let midArr: number[] = [];
// for (let i = 0; i < nums.length; i++) {
// let l = nums[i], mid = mIds[i];
// for (let j = 0; j < l; j++) {
// midArr.push(mid);
// }
// }
// let len = midArr.length;
// const point = this._target.node.getPosition();
// const averageAngle = 360 / len;
// let a = 0;
// for (let i = 0; i < len; i++) {
// let r = this._hHalf + 10;//半径
// let pos = v2();
// pos.x = point.x + Math.sin(a * Math.PI / 180) * r;
// pos.y = point.y + Math.cos(a * Math.PI / 180) * r;
// a += averageAngle;
// let obj: IFbMonsterData = Object.create(null);
// obj.pos = pos;
// obj.mid = midArr[i];
// obj.fid = fbconf.id;
// this._createList.push(obj)
// }
// }
// /**方形 随机生成怪物 */
// private initEnemys(fbconf: JsonModule.IFbconfig) {
// const mIds = Util.splitNumber(fbconf.monster_id);
// const nums = Util.splitNumber(fbconf.monster_num);
// let midArr: number[] = [];
// for (let i = 0; i < nums.length; i++) {
// let l = nums[i], mid = mIds[i];
// for (let j = 0; j < l; j++) {
// midArr.push(mid);
// }
// }
// //计算四边平均怪物数量
// let total = midArr.length;
// let m_idx: number = 0;
// const means = [];
// if (total < 4) {
// for (let i = 0; i < total; i++) {
// means.push(1);
// }
// } else {
// const mean = Math.floor(total / 4);
// for (let i = 0; i < 4; i++) {
// total -= mean;
// means.push(mean);
// }
// for (let i = 0; i < total; i++) {
// means[i] += 1;
// }
// }
// const point = this._target.node.getPosition();
// const state = fbconf.fresh_site > 0 ? fbconf.fresh_site : 1;
// const xMin = point.x - this._wHalf / state;// / 1//Util.randomNumber(1,fbconf.fresh_site);
// const xMax = point.x + this._wHalf / state;// / 1//Util.randomNumber(1,fbconf.fresh_site);
// const yMin = point.y - this._hHalf / state;// / 1//Util.randomNumber(1,fbconf.fresh_site);
// const yMax = point.y + this._hHalf / state;// / 1//Util.randomNumber(1,fbconf.fresh_site);
// const tmpRects = [
// new Vec2(xMin, yMin),
// new Vec2(xMin, yMax),
// new Vec2(xMax, yMax),
// new Vec2(xMax, yMin)];
// for (let i = 0; i < means.length; i++) {
// const num = means[i];
// let pjs = i % 2 == 0 ? (yMax - yMin) : (xMax - xMin);
// pjs /= num;
// for (let j = 0; j < num; j++) {
// const val = j * pjs;
// const pos: Vec2 = tmpRects[i].clone();
// if (i == 0) {
// pos.y = Util.randomNumber(pos.y, pos.y + val);
// if (state != 1) {
// pos.x = Util.randomNumber(pos.x, pos.x + val)
// }
// // pos.x /= fbconf.fresh_site;
// // if(num > 4) {
// // pos.x -= Math.abs(Util.randomNumber(pos.x, pos.x - 100));
// // }
// } else if (i == 1) {
// pos.x = Util.randomNumber(pos.x, pos.x + val);
// if (state != 1)
// pos.y = Util.randomNumber(pos.y, pos.y + val);
// // pos.y /= fbconf.fresh_site;
// // if(num > 4){
// // pos.y += Util.randomNumber(pos.y, pos.y + 100);
// // }
// } else if (i == 2) {
// pos.y = Util.randomNumber(pos.y, pos.y - val);
// if (state != 1)
// pos.x = Util.randomNumber(pos.x, pos.x - val);
// // pos.x /= fbconf.fresh_site;
// // if(num > 4){
// // pos.x += Util.randomNumber(pos.x, pos.x + 100);
// // }
// } else {
// pos.x = Util.randomNumber(pos.x, pos.x - val);
// if (state != 1)
// pos.y = Util.randomNumber(pos.y, pos.y - val);
// // pos.x -= val;
// // pos.y /= fbconf.fresh_site;
// // if(num > 4){
// // pos.y -= Math.abs(Util.randomNumber(pos.y, pos.y - 100));
// // }
// }
// let obj: IFbMonsterData = Object.create(null);
// obj.pos = pos;
// obj.mid = midArr[m_idx++];
// obj.fid = fbconf.id;
// this._createList.push(obj);
// }
// }
// }
// /**方形 队列生成怪物 */
// private initEnemy(fbconf: JsonModule.IFbconfig) {
// const mIds = Util.splitNumber(fbconf.monster_id);
// const nums = Util.splitNumber(fbconf.monster_num);
// let midArr: number[] = [];
// for (let i = 0; i < nums.length; i++) {
// let l = nums[i], mid = mIds[i];
// for (let j = 0; j < l; j++) {
// midArr.push(mid);
// }
// }
// //计算四边平均怪物数量
// let total = midArr.length;
// let m_idx: number = 0;
// const means = [];
// if (total < 4) {
// for (let i = 0; i < total; i++) {
// means.push(1);
// }
// } else {
// const mean = Math.floor(total / 4);
// for (let i = 0; i < 4; i++) {
// total -= mean;
// means.push(mean);
// }
// for (let i = 0; i < total; i++) {
// means[i] += 1;
// }
// }
// const point = this._target.node.getPosition();
// const xMin = point.x - this._wHalf;
// const xMax = point.x + this._wHalf;
// const yMin = point.y - this._hHalf;
// const yMax = point.y + this._hHalf;
// const tmpRects = [
// new Vec2(xMin, yMin),
// new Vec2(xMin, yMax),
// new Vec2(xMax, yMax),
// new Vec2(xMax, yMin)];
// for (let i = 0; i < means.length; i++) {
// const num = means[i];
// let pjs = i % 2 == 0 ? (yMax - yMin) : (xMax - xMin);
// pjs /= num;
// for (let j = 0; j < num; j++) {
// const val = j * pjs;
// const pos: Vec2 = tmpRects[i].clone();
// if (i == 0) {
// pos.y += val;
// if (num > 4) {
// pos.x -= Math.abs(Util.randomNumber(pos.x, pos.x - 100));
// }
// } else if (i == 1) {
// pos.x += val;
// if (num > 4) {
// pos.y += Util.randomNumber(pos.y, pos.y + 100);
// }
// } else if (i == 2) {
// pos.y -= val;
// if (num > 4) {
// pos.x += Util.randomNumber(pos.x, pos.x + 100);
// }
// } else {
// pos.x -= val;
// if (num > 4) {
// pos.y -= Math.abs(Util.randomNumber(pos.y, pos.y - 100));
// }
// }
// let obj: IFbMonsterData = Object.create(null);
// obj.pos = pos;
// obj.mid = midArr[m_idx++];
// obj.fid = fbconf.id;
// this._createList.push(obj);
// }
// }
// }
// /**创建一个怪物 */
// private createEnemy() {
// // let cmonster: IFbMonsterData = this._createList.shift();
// // let mCfg = app.confMgr.conf.monster.getConfById(cmonster.mid);
// // resLoader.loadRes<Prefab>(BoundNameEnum.subBattle, `monster/${mCfg.model_id}`).then(prefab => {
// // let node: Node = instantiate(prefab);
// // this.node.addChild(node);
// // node.setPosition(cmonster.pos);
// // let enemy: Enemy = node.getComponent(Enemy);
// // enemy.initial(this.findTarget(cmonster.pos), cmonster);
// // this._enemyList.push(enemy);
// // })
// }
// /**找玩家中一个 */
// findTarget(pos: Vec2) {
// // let p1 = app.gameMgr.player, p2 = app.gameMgr.player2;
// // if (!p2) return p1;
// // return Math.abs(pos.x - p1.node.x) < Math.abs(pos.x - p2.node.x) ? p1 : p2;
// }
// public getEnemyList() {
// return this._enemyList;
// }
// /** 怪物回收*/
// public recycleEnemy(enemy: Enemy) {
// for (let i = this._enemyList.length - 1; i >= 0; i--) {
// const tmpEnemy = this._enemyList[i];
// if (tmpEnemy == enemy) {
// enemy.node.destroy();
// this._enemyList.splice(i, 1);
// break;
// }
// }
// //没有怪物了,但是还未到刷怪时间,强制下一波
// if (this._enemyList.length == 0 && this._fbArr.length > 0) {
// this._fbArr.sort((fa, fb) => {
// return (fa.tm - fa.curTm) - (fb.tm - fa.curTm);
// })
// let fb = this._fbArr[0];
// fb.curTm = fb.tm;
// }
// }
// }

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "9786456a-0efa-4c51-9a38-a5715e2597b0",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "ad30184e-02c7-41ef-801c-a74d7eca701b",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,239 @@
import { Component, instantiate, Node, Prefab, tween, UITransform, v2, v3, Vec2, Vec3, _decorator } from 'cc';
import WaveMng from '../logics/mng/WaveMng';
import { monsterCtl } from '../Test/monsterCtl';
import { snakebody } from './snakebody';
const { ccclass, property } = _decorator;
@ccclass('player')
export class player extends Component {
@property(Prefab) bodyPrefab: Prefab = null
@property(Node) tmpWeapen: Node = null
@property(WaveMng) waveMng: WaveMng = null
_tmpV2: Vec2 = new Vec2()
_tmpV3: Vec3 = new Vec3(0, 1, 0)
_tmpV32: Vec3 = new Vec3()
dir: Vec3 = new Vec3(0, 1, 0)
bodyNum: number = 8
sectionLen: number = 38
speed: number = 3
snakeArray: Node[];
//蛇头走过的点数量
headPointsNum: number = 0
// record all points
pointsArray = [];
_isMove: boolean = false
monsterList: Array<Node> = []
start() {
this.tmpWeapen.active = false
this.headPointsNum = 0
this.snakeArray = [];
this.pointsArray = []
this.snakeArray.push(this.node);
this.initSnake()
}
initSnake() {
this.rotateHead()
// return
for (let i = 1; i <= this.bodyNum; i++) {
this.getNewBody(i);
this.recordPoints()
}
console.log("初始化的节点...", this.pointsArray.length, this._recordTimes)
this._recordTimes = 0
}
rotateHead(headPos: Vec2 = null) {
if (!headPos) {
headPos = new Vec2(this.dir.x, this.dir.y)
}
let angle = v2(1, 0).signAngle(headPos) * 180 / Math.PI;
this.node.angle = angle - 90;
}
getNewBody(bodyIdx: number) {
// console.log("this.snakeArray.length ::", this.snakeArray.length)
let newBody = instantiate(this.bodyPrefab);
let snakeCtl = newBody.getComponent(snakebody)
snakeCtl.snakeBodyIdx = 0
snakeCtl.preSnakeBody = this.snakeArray[this.snakeArray.length - 1]
// set new body's position //这是第一个蛇身
if (this.snakeArray.length == 1) {
let dir = this.dir.normalize()
let pos = this.node.getPosition().subtract(dir.multiplyScalar(this.sectionLen))
newBody.setPosition(pos);
}
else {
let lastBody = this.snakeArray[this.snakeArray.length - 1];
let lastBOBody = this.snakeArray[this.snakeArray.length - 2];
lastBody.getPosition(this._tmpV32)
lastBOBody.getPosition(this._tmpV3)
let dir = this._tmpV3.subtract(this._tmpV32).normalize();
let tmpPos = lastBody.getPosition().subtract(dir.multiplyScalar(this.sectionLen))
// console.log("tmpPos ::", tmpPos, this.snakeArray.length)
newBody.setPosition(tmpPos);
}
this.node.parent.insertChild(newBody, 0)
this.snakeArray.push(newBody);
//修改蛇身zidx
// newBody.setSiblingIndex(zIdx)
}
/**
*
*/
_tmpDir: Vec3 = new Vec3()
_recordTimes: number = 0
recordPoints(idx: number = null) {
// record points between bodies (head is a special body)
if (!idx) {
idx = this.snakeArray.length - 1
}
let len = 0;
let index = 0;
this._recordTimes++
let pointNum = Math.ceil(this.sectionLen / this.speed) //当前速度移动完一节身体需要的坐标点数
let lastBody: Node = this.snakeArray[idx];
let lastBOBody: Node = this.snakeArray[idx - 1];
let dir: Vec3 = lastBOBody.getPosition().subtract(lastBody.getPosition()).normalize();
for (let pIdx = 0; pIdx < pointNum; pIdx++) {
len += this.speed;
this._tmpDir = dir.clone()
let pos: Vec3 = lastBody.getPosition().add(this._tmpDir.multiplyScalar(len));
this.pointsArray.splice(index, 0, pos); // 每次从数组头部插入(pointNum个)坐标
index += 1;
}
}
changeSpeed(sp: number) {
this.speed = sp
this.pointsArray = []
this.headPointsNum = 0
for (let i = 1; i <= this.bodyNum; i++) {
if (this.snakeArray[i].getComponent(snakebody))
this.snakeArray[i].getComponent(snakebody).reset()
this.recordPoints(i)
}
}
_time: number = 0
_hasChan: boolean = false
update(deltaTime: number) {
// return
this._time += deltaTime
if (this._time > 0.5) {
this.checkAtt()
this._time = 0
// this.changeSpeed(6)
}
this._tmpV2.set(this.dir.x, this.dir.y)
this.rotateHead(this._tmpV2)
if (this.dir && this._isMove) {
this.move()
}
}
getTmpAttBox(){
let rect = this.node.getComponent(UITransform).getBoundingBoxToWorld()
//稍微扩大点
let biger:number = 100
rect.x -= biger
rect.y -= biger
rect.width += 2 * biger
rect.height += 2 * biger
return rect
}
/**
*
*/
checkAtt() {
this.tmpWeapen.setPosition(this.node.getPosition())
this.tmpWeapen.scale = Vec3.ZERO
this.tmpWeapen.active = true
tween(this.tmpWeapen).to(0.2, { scale: v3(1, 1, 1) }).call(() => {
this.tmpWeapen.active = false
}).start()
let killArray = []
// console.log("this.monsterList::", this.monsterList.length)
let checkRect = this.getTmpAttBox() //this.node.getComponent(UITransform).getBoundingBoxToWorld()
let checkList = this.waveMng.getTreeColliderList(checkRect)
// console.log("checkList::", checkList)
for (let searchIdx = 0; searchIdx < checkList.length; searchIdx++) {
if (this.node.getPosition().subtract(checkList[searchIdx].collider.getPosition()).lengthSqr() < 22500) {
killArray.push(checkList[searchIdx].collider)
}
}
for (let rmIdx = killArray.length - 1; rmIdx >= 0; rmIdx--) {
let tMonsterCtl: monsterCtl = killArray[rmIdx].getComponent(monsterCtl)
let uuid = tMonsterCtl.node.uuid
if (tMonsterCtl.hurt()) {
for (let idx = 0; idx < this.monsterList.length; idx++) {
if (this.monsterList[idx].uuid == uuid) {
this.monsterList.splice(idx, 1)
}
}
}
}
}
setDir(dir) {
// return
this.dir = dir
}
move(dir: Vec3 = null) {
// return
if (!dir) {
dir = this.dir
}
let moveV2 = dir.normalize().multiplyScalar(this.speed)
// console.log("蛇头移动距离...", moveV2.length())
//最后动蛇头
// this.node.getPosition(this._tmpV3)
this.node.setPosition(this.node.getPosition().add(moveV2))
this.pointsArray.push(this.node.getPosition());
this.headPointsNum += 1;
//从第一个蛇身开始运动
let lastPosIdx = -1
for (let i = 1; i < this.snakeArray.length; i++) {
let num = Math.floor((this.pointsArray.length - this.headPointsNum) / (this.snakeArray.length - 1) * (this.snakeArray.length - 1 - i));
let posIdx = num + this.snakeArray[i].getComponent(snakebody).snakeBodyIdx
this.snakeArray[i].setPosition(this.pointsArray[posIdx]);
this.snakeArray[i].getComponent(snakebody).addIdx();
lastPosIdx = posIdx
// console.log("use idx :: ", num + this.snakeArray[i].getComponent(snakebody).snakeBodyIdx)
}
// console.log("this.pointsArray::", this.pointsArray)
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "39b2efb2-9835-4908-b520-6d72d1e9a275",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,136 @@
import { Component, EventTouch, Input, Node, Vec2, Vec3, _decorator } from 'cc';
import Game from '../Test/Test2';
const { ccclass, property } = _decorator;
const TOUCH_RADIUS = 180;
const ROLE_MOVE_FRAME = 0.2;
const _tempPos = new Vec3();
const _tempDelta = new Vec2();
const Horizontal = new Vec2(1, 0);
const MOVE_DELTA = 0.2;
@ccclass('rolejoystick')
export class rolejoystick extends Component {
@property(Node)
ctrlSprite: Node = null!;
@property(Node)
moveTagSp: Node = null!;
@property(Node)
role: Node = null!;
@property(Vec3)
originPos = new Vec3();
private _isTouch = false;
private _touchPos = new Vec2();
private _startPos = new Vec2();
private _movePos = new Vec2();
private _animComp: Animation = null!;
private _animState = 'idle';
// _tempPos: Vec3 = new Vec3()
start() {
this.ctrlSprite.setPosition(this.originPos);
// _tempPos.set(0, 90, 0);
// this.role.eulerAngles = _tempPos;
// this._animComp = this.role.getComponentInChildren(Animation)!;
this.node.on(Input.EventType.TOUCH_START, this.touchStart, this);
this.node.on(Input.EventType.TOUCH_MOVE, this.touchMove, this);
this.node.on(Input.EventType.TOUCH_END, this.touchEnd, this);
}
onDestroy() {
this.node.off(Input.EventType.TOUCH_START, this.touchStart, this);
this.node.off(Input.EventType.TOUCH_MOVE, this.touchMove, this);
this.node.off(Input.EventType.TOUCH_END, this.touchEnd, this);
}
touchStart(touch: EventTouch) {
// this.changeState('cocos_anim_run');
// touch.getUI
touch.getUILocation(this._startPos);
const distance = this._startPos.length();
console.error("joystick::", touch, distance)
// if (distance < TOUCH_RADIUS) {
this._touchPos.set(this._startPos);
this._movePos.set(this._startPos);
_tempPos.set(this.ctrlSprite.position);
this.ctrlSprite.setWorldPosition(this._startPos.x, this._startPos.y, _tempPos.z);
this._isTouch = true;
// }
}
touchMove(touch: EventTouch) {
if (!this._isTouch) {
return;
}
touch.getUILocation(this._movePos);
Vec2.subtract(_tempDelta, this._movePos, this._startPos);
// 计算角色的整体旋转值
// const deltaRadian = _tempDelta.angle(Horizontal);
// const angle = deltaRadian * 180 / Math.PI;
// const rot = this.role.eulerAngles;
// _tempPos.set(rot.x, 90 + (Math.sign(_tempDelta.y)) * angle, rot.z);
// this.role.eulerAngles = _tempPos;
// 重新规划移动方向值
// _tempDelta.multiply2f(MOVE_DELTA, MOVE_DELTA);
// Vec2.add(this._movePos, this._startPos, _tempDelta);
const distance = _tempDelta.length();
// 是否超出限制半径
if (distance > TOUCH_RADIUS) {
const radian = _tempDelta.angle(Horizontal);
// console.log("radian::", radian)
const x = Math.cos(radian) * TOUCH_RADIUS;
let y = Math.sin(radian) * TOUCH_RADIUS;
if (this._startPos.y >= this._movePos.y) {
y = -y
}
this._movePos.set(x, y).add(this._startPos);
}
// this.ctrlSprite.setWorldPosition(this._movePos.x, this._movePos.y, 0);
this.moveTagSp.setWorldPosition(this._movePos.x, this._movePos.y, 0);
this._touchPos.set(this._movePos);
}
touchEnd(touch: EventTouch) {
this._isTouch = false;
// this.changeState('cocos_anim_idle');
// this.ctrlSprite.setPosition(this.originPos);
// this.moveTagSp.setPosition(this.originPos)
}
changeState(name: string) {
if (this._animState === name) {
return;
}
// this._animComp.play(name);
// this._animState = name;
}
update() {
if (!this._isTouch) {
Game.Instance.Player._isMove = false
return;
}
// _tempPos.set(0, 0, ROLE_MOVE_FRAME);
// this.role.translate(_tempPos);
if (Game.Instance.Player) {
Game.Instance.Player._isMove = true
Game.Instance.Player.setDir(this.moveTagSp.getPosition().subtract(this.ctrlSprite.getPosition()).normalize())
}
// Game.Instance.Player.move(this.moveTagSp.getPosition().subtract(this.ctrlSprite.getPosition()).normalize())
// Game.
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "dd6eec7f-57ad-46f6-b5fc-7a4907cdc2e1",
"files": [],
"subMetas": {},
"userData": {}
}

@ -0,0 +1,66 @@
import { Component, Node, Vec3, _decorator } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('snakebody')
export class snakebody extends Component {
speed: number = 3
private _preSnakeBody: Node = null;
public get preSnakeBody(): Node {
return this._preSnakeBody;
}
public set preSnakeBody(value: Node) {
this._preSnakeBody = value;
}
private _snakeBodyIdx: number = 0;
public get snakeBodyIdx(): number {
return this._snakeBodyIdx;
}
public set snakeBodyIdx(value: number) {
this._snakeBodyIdx = value;
}
reset() {
this.snakeBodyIdx = 0
}
addIdx() {
this.snakeBodyIdx++
}
/**
* dir
*/
_tmpVec: Vec3 = new Vec3(0, 1, 0)
getPreDir() {
// return this.preSnakeBody.getPosition().subtract(this.node.getPosition()).normalize()
// return this.preSnakeBody.getPosition().subtract(this.node.getPosition())
console.log("this.preSnakeBody.getPosition() ::", this.preSnakeBody.getPosition())
return this.node.getPosition().subtract(this.preSnakeBody.getPosition())
}
start() {
}
update(deltaTime: number) {
}
_tmpV3: Vec3 = new Vec3()
move(length: number = null) {
let moveV2 = this.getPreDir()//.multiplyScalar(1 / this.speed)
// console.log("蛇身移动的距离...", moveV2.length())
Vec3.lerp(this._tmpV3, this.node.getPosition(), this.preSnakeBody.getPosition().add(moveV2), 0.5)
console.log("........:", moveV2, this._tmpV3)
this.node.setPosition(this._tmpV3)
// this.node.setPosition(this.node.getPosition().add(moveV2))
}
}

@ -0,0 +1,9 @@
{
"ver": "4.0.23",
"importer": "typescript",
"imported": true,
"uuid": "285cabaf-7adc-4f7c-9950-771d5e8abc2d",
"files": [],
"subMetas": {},
"userData": {}
}

12
assets/Scripts/ui.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "69be3a35-cbac-416c-9ed9-30a19ee1a670",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

12
assets/animation.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "ee1ea724-146d-41c2-bfb1-0987716e332e",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,88 @@
[
{
"__type__": "cc.AnimationClip",
"_name": "monster_0",
"_objFlags": 0,
"__editorExtras__": {
"embeddedPlayerGroups": []
},
"_native": "",
"sample": 4,
"speed": 1,
"wrapMode": 2,
"enableTrsBlending": false,
"_duration": 1.25,
"_hash": 500763545,
"_tracks": [
{
"__id__": 1
}
],
"_exoticAnimation": null,
"_events": [],
"_embeddedPlayers": []
},
{
"__type__": "cc.animation.ObjectTrack",
"_binding": {
"__type__": "cc.animation.TrackBinding",
"path": {
"__id__": 2
}
},
"_channel": {
"__id__": 4
}
},
{
"__type__": "cc.animation.TrackPath",
"_paths": [
{
"__id__": 3
},
"spriteFrame"
]
},
{
"__type__": "cc.animation.ComponentPath",
"component": "cc.Sprite"
},
{
"__type__": "cc.animation.Channel",
"_curve": {
"__id__": 5
}
},
{
"__type__": "cc.ObjectCurve",
"_times": [
0,
0.25,
0.5,
0.75,
1
],
"_values": [
{
"__uuid__": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "c0d07a24-a091-4225-8876-c69d520ef479@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "8b8e7ea8-69ee-44ce-831b-ab570e83a271@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "11127c25-31b7-49c5-9bf5-9ac030ca13eb@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "c2706816-4f7f-43d5-bf5f-c5f42328efc0@f9941",
"__expectedType__": "cc.SpriteFrame"
}
]
}
]

@ -0,0 +1,13 @@
{
"ver": "2.0.3",
"importer": "animation-clip",
"imported": true,
"uuid": "3732ff9b-e2c3-49ce-90e9-ada8be3cb96f",
"files": [
".cconb"
],
"subMetas": {},
"userData": {
"name": "monster_0"
}
}

@ -0,0 +1,88 @@
[
{
"__type__": "cc.AnimationClip",
"_name": "monster_1",
"_objFlags": 0,
"__editorExtras__": {
"embeddedPlayerGroups": []
},
"_native": "",
"sample": 4,
"speed": 1,
"wrapMode": 2,
"enableTrsBlending": false,
"_duration": 1.25,
"_hash": 500763545,
"_tracks": [
{
"__id__": 1
}
],
"_exoticAnimation": null,
"_events": [],
"_embeddedPlayers": []
},
{
"__type__": "cc.animation.ObjectTrack",
"_binding": {
"__type__": "cc.animation.TrackBinding",
"path": {
"__id__": 2
}
},
"_channel": {
"__id__": 4
}
},
{
"__type__": "cc.animation.TrackPath",
"_paths": [
{
"__id__": 3
},
"spriteFrame"
]
},
{
"__type__": "cc.animation.ComponentPath",
"component": "cc.Sprite"
},
{
"__type__": "cc.animation.Channel",
"_curve": {
"__id__": 5
}
},
{
"__type__": "cc.ObjectCurve",
"_times": [
0,
0.25,
0.5,
0.75,
1
],
"_values": [
{
"__uuid__": "fd098eb2-c17a-44f9-b3b5-84e4de3a0a24@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "35e74055-4977-4ab5-9fd2-cd5032652ef1@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "67783030-db2f-449e-bc2b-ed77d4655024@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "1267c1fd-bfa8-49ac-b628-27b56bcbe2da@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "cd61c842-1375-4520-88e9-57082fb22906@f9941",
"__expectedType__": "cc.SpriteFrame"
}
]
}
]

@ -0,0 +1,13 @@
{
"ver": "2.0.3",
"importer": "animation-clip",
"imported": true,
"uuid": "b56c7e2b-40cd-4383-b119-1923658d8346",
"files": [
".cconb"
],
"subMetas": {},
"userData": {
"name": "monster_1"
}
}

@ -0,0 +1,93 @@
[
{
"__type__": "cc.AnimationClip",
"_name": "nvwushen",
"_objFlags": 0,
"__editorExtras__": {
"embeddedPlayerGroups": []
},
"_native": "",
"sample": 4,
"speed": 1,
"wrapMode": 2,
"enableTrsBlending": false,
"_duration": 1.5,
"_hash": 500763545,
"_tracks": [
{
"__id__": 1
}
],
"_exoticAnimation": null,
"_events": [],
"_embeddedPlayers": []
},
{
"__type__": "cc.animation.ObjectTrack",
"_binding": {
"__type__": "cc.animation.TrackBinding",
"path": {
"__id__": 2
}
},
"_channel": {
"__id__": 4
}
},
{
"__type__": "cc.animation.TrackPath",
"_paths": [
{
"__id__": 3
},
"spriteFrame"
]
},
{
"__type__": "cc.animation.ComponentPath",
"component": "cc.Sprite"
},
{
"__type__": "cc.animation.Channel",
"_curve": {
"__id__": 5
}
},
{
"__type__": "cc.ObjectCurve",
"_times": [
0,
0.25,
0.5,
0.75,
1,
1.25
],
"_values": [
{
"__uuid__": "9692ee99-e3c7-4f0c-880d-a032db0e6b67@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "3ef20986-f554-4baf-86e2-d0b932033888@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "1faee88b-b515-42df-8125-81a93776030e@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "7124ab51-3354-481b-b436-7aa7a308b6c0@f9941",
"__expectedType__": "cc.SpriteFrame"
},
{
"__uuid__": "8d901387-39c2-4630-a746-acebb4a6d7b1@f9941",
"__expectedType__": "cc.SpriteFrame"
}
]
}
]

@ -0,0 +1,13 @@
{
"ver": "2.0.3",
"importer": "animation-clip",
"imported": true,
"uuid": "9ed9e8c3-7532-447e-97d3-bc1ae4e19f22",
"files": [
".cconb"
],
"subMetas": {},
"userData": {
"name": "nvwushen"
}
}

12
assets/res.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "be13c1c7-cbfa-4c9e-a904-fa1cb22f01ae",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

12
assets/res/shader.meta Normal file

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "a4806935-3922-4d1a-b5e4-061a8719221b",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

15
assets/resources.meta Normal file

@ -0,0 +1,15 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "ef14c052-6303-4e90-b227-5eb038495010",
"files": [],
"subMetas": {},
"userData": {
"isBundle": true,
"bundleName": "resources",
"priority": 8,
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "5dccb540-29c6-4f42-ab7e-be8d6ea855bc",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "810304bb-6659-4736-b0a4-484b1e72dabe",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "2ad25d4a-d6d6-4a16-bd14-28825d065813",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

Binary file not shown.

After

(image error) Size: 16 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "9692ee99-e3c7-4f0c-880d-a032db0e6b67",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_0": {
"ver": "1.0.4",
"uuid": "1a1caed4-600f-4403-abed-8ac79fede4a9",
"rawTextureUuid": "9692ee99-e3c7-4f0c-880d-a032db0e6b67",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": -3,
"offsetY": 0,
"trimX": 4,
"trimY": 2,
"width": 113,
"height": 148,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "9692ee99-e3c7-4f0c-880d-a032db0e6b67@6c48a",
"displayName": "nws-move_0",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "9692ee99-e3c7-4f0c-880d-a032db0e6b67",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "9692ee99-e3c7-4f0c-880d-a032db0e6b67@f9941",
"displayName": "nws-move_0",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "9692ee99-e3c7-4f0c-880d-a032db0e6b67@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "9692ee99-e3c7-4f0c-880d-a032db0e6b67@f9941"
}
}

Binary file not shown.

After

(image error) Size: 17 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_12": {
"ver": "1.0.4",
"uuid": "a1fedad8-7b9d-4cfe-9932-28a657e172da",
"rawTextureUuid": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 4,
"offsetY": -2.5,
"trimX": 9,
"trimY": 5,
"width": 117,
"height": 147,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496@6c48a",
"displayName": "nws-move_12",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496@f9941",
"displayName": "nws-move_12",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "2c08ba63-fa76-4d1d-8fdb-a35c63ff0496@f9941"
}
}

Binary file not shown.

After

(image error) Size: 17 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "3ef20986-f554-4baf-86e2-d0b932033888",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_16": {
"ver": "1.0.4",
"uuid": "dd5dab88-cbab-4001-864c-8ff5a4d3ab49",
"rawTextureUuid": "3ef20986-f554-4baf-86e2-d0b932033888",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 3,
"offsetY": -2,
"trimX": 11,
"trimY": 5,
"width": 111,
"height": 146,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "3ef20986-f554-4baf-86e2-d0b932033888@6c48a",
"displayName": "nws-move_16",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "3ef20986-f554-4baf-86e2-d0b932033888",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "3ef20986-f554-4baf-86e2-d0b932033888@f9941",
"displayName": "nws-move_16",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "3ef20986-f554-4baf-86e2-d0b932033888@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "3ef20986-f554-4baf-86e2-d0b932033888@f9941"
}
}

Binary file not shown.

After

(image error) Size: 16 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "1faee88b-b515-42df-8125-81a93776030e",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_20": {
"ver": "1.0.4",
"uuid": "a4d80f83-9414-4cbc-8393-6beb9f22b7d8",
"rawTextureUuid": "1faee88b-b515-42df-8125-81a93776030e",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": 2,
"offsetY": -4,
"trimX": 10,
"trimY": 9,
"width": 111,
"height": 142,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "1faee88b-b515-42df-8125-81a93776030e@6c48a",
"displayName": "nws-move_20",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "1faee88b-b515-42df-8125-81a93776030e",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "1faee88b-b515-42df-8125-81a93776030e@f9941",
"displayName": "nws-move_20",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "1faee88b-b515-42df-8125-81a93776030e@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "1faee88b-b515-42df-8125-81a93776030e@f9941"
}
}

Binary file not shown.

After

(image error) Size: 17 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "7124ab51-3354-481b-b436-7aa7a308b6c0",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_4": {
"ver": "1.0.4",
"uuid": "34e741ac-4bbd-4088-ba83-7a2c5d7a86f8",
"rawTextureUuid": "7124ab51-3354-481b-b436-7aa7a308b6c0",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": -3,
"offsetY": -4,
"trimX": 2,
"trimY": 9,
"width": 117,
"height": 142,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "7124ab51-3354-481b-b436-7aa7a308b6c0@6c48a",
"displayName": "nws-move_4",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "7124ab51-3354-481b-b436-7aa7a308b6c0",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "7124ab51-3354-481b-b436-7aa7a308b6c0@f9941",
"displayName": "nws-move_4",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "7124ab51-3354-481b-b436-7aa7a308b6c0@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "7124ab51-3354-481b-b436-7aa7a308b6c0@f9941"
}
}

Binary file not shown.

After

(image error) Size: 16 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "8d901387-39c2-4630-a746-acebb4a6d7b1",
"files": [
".json",
".png"
],
"subMetas": {
"nws-move_8": {
"ver": "1.0.4",
"uuid": "6793e976-588c-41f3-874a-ead93444eeb1",
"rawTextureUuid": "8d901387-39c2-4630-a746-acebb4a6d7b1",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": -1,
"offsetY": -6.5,
"trimX": 3,
"trimY": 14,
"width": 119,
"height": 137,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "8d901387-39c2-4630-a746-acebb4a6d7b1@6c48a",
"displayName": "nws-move_8",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "8d901387-39c2-4630-a746-acebb4a6d7b1",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "8d901387-39c2-4630-a746-acebb4a6d7b1@f9941",
"displayName": "nws-move_8",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 127,
"height": 152,
"rawWidth": 127,
"rawHeight": 152,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-63.5,
-76,
0,
63.5,
-76,
0,
-63.5,
76,
0,
63.5,
76,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
152,
127,
152,
0,
0,
127,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-63.5,
-76,
0
],
"maxPos": [
63.5,
76,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "8d901387-39c2-4630-a746-acebb4a6d7b1@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "8d901387-39c2-4630-a746-acebb4a6d7b1@f9941"
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "9dee460c-9dae-42dc-a051-924054b702e0",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

@ -0,0 +1,12 @@
{
"ver": "1.1.0",
"importer": "directory",
"imported": true,
"uuid": "7fd210cf-8857-4015-84ee-ac4a02cfc757",
"files": [],
"subMetas": {},
"userData": {
"compressionType": {},
"isRemoteBundle": {}
}
}

Binary file not shown.

After

(image error) Size: 9.3 KiB

@ -0,0 +1,162 @@
{
"ver": "1.0.25",
"importer": "image",
"imported": true,
"uuid": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a",
"files": [
".json",
".png"
],
"subMetas": {
"ygw-animation_0": {
"ver": "1.0.4",
"uuid": "8717716c-bf93-4cfb-bfaf-f157b1cfaf90",
"rawTextureUuid": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a",
"trimType": "auto",
"trimThreshold": 1,
"rotated": false,
"offsetX": -1.5,
"offsetY": -14.5,
"trimX": 3,
"trimY": 29,
"width": 105,
"height": 81,
"rawWidth": 114,
"rawHeight": 110,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"subMetas": {},
"importer": "*",
"imported": false,
"files": [],
"userData": {},
"displayName": "",
"id": "",
"name": ""
},
"6c48a": {
"importer": "texture",
"uuid": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a@6c48a",
"displayName": "ygw-animation_0",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "clamp-to-edge",
"wrapModeT": "clamp-to-edge",
"imageUuidOrDatabaseUri": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a",
"isUuid": true,
"visible": false,
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
},
"f9941": {
"importer": "sprite-frame",
"uuid": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a@f9941",
"displayName": "ygw-animation_0",
"id": "f9941",
"name": "spriteFrame",
"userData": {
"trimType": "none",
"trimThreshold": 1,
"rotated": false,
"offsetX": 0,
"offsetY": 0,
"trimX": 0,
"trimY": 0,
"width": 114,
"height": 110,
"rawWidth": 114,
"rawHeight": 110,
"borderTop": 0,
"borderBottom": 0,
"borderLeft": 0,
"borderRight": 0,
"packable": true,
"pixelsToUnit": 100,
"pivotX": 0.5,
"pivotY": 0.5,
"meshType": 0,
"vertices": {
"rawPosition": [
-57,
-55,
0,
57,
-55,
0,
-57,
55,
0,
57,
55,
0
],
"indexes": [
0,
1,
2,
2,
1,
3
],
"uv": [
0,
110,
114,
110,
0,
0,
114,
0
],
"nuv": [
0,
0,
1,
0,
0,
1,
1,
1
],
"minPos": [
-57,
-55,
0
],
"maxPos": [
57,
55,
0
]
},
"isUuid": true,
"imageUuidOrDatabaseUri": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a@6c48a",
"atlasUuid": ""
},
"ver": "1.0.11",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "sprite-frame",
"fixAlphaTransparencyArtifacts": true,
"hasAlpha": true,
"redirect": "3b94c7fc-ac9b-47d7-9aca-37fc7683996a@f9941"
}
}

Binary file not shown.

After

(image error) Size: 8.4 KiB

Some files were not shown because too many files have changed in this diff Show More