CocosCreator 게임 의 어군 알고리즘 을 자세히 알 아 보기
최근 에 CocosCreator 를 배우 고 싶 어서 편집기 다운로드,시작.
다 들 아시 다시 피 쓰 면서 배 우 는 것 이 가장 빠 른 학습 방법 입 니 다.데모 연습 가 를 써 야 합 니 다.그럼 무엇 을 써 야 합 니까?듣자니 지금《묵 새우 올챙이》가 매우 인기 가 있다 고 하 던 데,베 끼 는 것 을 어떻게 베 끼 는 것 이 라 고 할 수 있 겠 는가?비슷 한 게임 하나 써 주세요!
(에서 물고기의 위치 가 고정 되 고 일정한 수량 에 도달 하면 게이머 들 이 업 그 레이 드 됩 니 다.한 무리의 물고기 가 나타 나 지 않 습 니 다.본 프로젝트 는 사실 그것 과 달리 진화 하지 않 고 한 무리의 물고기 가 있 을 것 입 니 다.모든 물고기 도 고정된 위치 가 아니 라 자신의 운동 논리 가 있 습 니 다.사실은 다른 게임 과 더욱 비슷 하지만 저 는 뭐라고 부 르 는 지 모 릅 니 다.)
효과 표시:
본문
우선 전체 유저 플레이어:
사진 자원 은 CocosCreator 공식 Demo 의 사진 을 사용 하여 공식 Demo 에 따라 배 웠 습 니 다.물고기 찾기 가 귀 찮 은 사진 은 바로 사진 을 가 져 와 서 사 용 했 습 니 다.이 프로젝트 는 현재 두 장의 사진 만 사 용 했 습 니 다.
플레이어 가 있 으 면 플레이어 제어 스 크 립 트 를 써 야 합 니 다.한 방향 을 클릭 하면 플레이 어 는 계속 이 방향 으로 이동 합 니 다.그러면 우 리 는 먼저 게이머 가 클릭 한 위 치 를 얻 은 다음 에 player 가 이동 하 는 방향 을 계산 해 야 합 니 다.우 리 는 이것 을 GameManager 에 쓰 기 때문에 새로운 스 크 립 트 GameManager 를 만 듭 니 다.이 스 크 립 트 는 Canvas 에 걸 려 있 습 니 다.
먼저 두 개의 변 수 를 정의 합 니 다.게이머 노드 와 방향 벡터:
@property(cc.Node)
player: cc.Node = null;
ir: cc.Vec2 = cc.Vec2.ZERO;
방향 가 져 오 는 방법:
getClickDir(event) {
let pos: cc.Vec2 = event.getLocation();
//
let localPos = this.node.convertToNodeSpaceAR(pos);
let playerPos: cc.Vec2 = new cc.Vec2(
this.player.position.x,
this.player.position.y
);
let len = localPos.sub(playerPos).mag();
this.dir.x = localPos.sub(playerPos).x / len;
this.dir.y = localPos.sub(playerPos).y / len;
}
이 방법 은 onMouse Down 과 onMouse Move 에서 호출 합 니 다:
onMouseDown(event) {
if (event.getButton() == cc.Event.EventMouse.BUTTON_LEFT) {
this.getClickDir(event);
}
}
onMouseMove(event) {
if (event.getButton() == cc.Event.EventMouse.BUTTON_LEFT) {
this.getClickDir(event);
}
}
onLoad() {
cc.director.getCollisionManager().enabled = true;
cc.director.getPhysicsManager().enabled = true;
this.node.on(cc.Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
this.node.on(cc.Node.EventType.MOUSE_MOVE, this.onMouseMove, this);
}
onDestroy() {
this.node.off(cc.Node.EventType.MOUSE_DOWN, this.onMouseDown, this);
this.node.off(cc.Node.EventType.MOUSE_MOVE, this.onMouseMove, this);
}
방향 벡터 가 있 으 면 유 저 를 이동 시 킬 수 있 습 니 다.FishPlayer 스 크 립 트 를 새로 만 듭 니 다.게이머 들 이 뛰 어 다 니 지 못 하 게 하기 위해 서,우 리 는 먼저 벽 을 빌 드 합 니 다:
벽 에 물리 적 충돌 체 추가:
그리고 FishPlayer 스 크 립 트 를 시작 할 수 있 습 니 다.먼저 사용 할 변 수 를 정의 하 십시오.
@property(cc.Node)
camera: cc.Node = null;
@property(cc.Node)
gameManager: cc.Node = null;
game: GameManager;
speed: number = 170;
velocity: cc.Vec3 = cc.Vec3.ZERO;
onLoad()에서 game 에 값 을 부여 합 니 다:
onLoad() {
this.game = this.gameManager.getComponent("GameManager");
}
방사선 을 통 해 경 계 를 측정 하여 유저 가 이동 할 수 있 는 지 여 부 를 판단 하 는 방법:
canMove() {
var flag: boolean = true;
//
var pos = this.node.convertToWorldSpaceAR(cc.Vec3.ZERO);
var endPos = pos.add(this.node.up.mul(40));
var hit: cc.PhysicsRayCastResult[] = cc.director
.getPhysicsManager()
.rayCast(
new cc.Vec2(pos.x, pos.y),
new cc.Vec2(endPos.x, endPos.y),
cc.RayCastType.All
);
if (hit.length > 0) {
flag = false;
}
return flag;
}
update 에서 유저 이동 제어:
update(dt) {
if (this.game.dir.mag() < 0.5) {
this.velocity = cc.Vec3.ZERO;
return;
}
let vx: number = this.game.dir.x * this.speed;
let vy: number = this.game.dir.y * this.speed;
this.velocity = new cc.Vec3(vx, vy);
//
if (this.canMove()) {
this.node.x += vx * dt;
this.node.y += vy * dt;
}
//
this.camera.setPosition(this.node.position);
//
let hudu = Math.atan2(this.game.dir.y, this.game.dir.x);
let angle = hudu * (180 / Math.PI);
angle = 360 - angle + 90;
this.node.angle = -angle;
}
유저 의 이동 논 리 를 다 썼 습 니 다.다음은 물고기 떼 를 쓰 겠 습 니 다.FishGroupManager 스 크 립 트 와 FishGroup 스 크 립 트 를 새로 만 듭 니 다.FishGroupManager 는 Canvas 에 걸 려 있 고 FishGroup 은 player 에 걸 려 있 습 니 다.
FishGroupManager 에서 정적 fishGroups 변 수 를 정의 하여 모든 Group 을 관리 합 니 다(장면 에 여러 명의 게이머,여러 개의 물고기 떼 가 있 을 수 있 기 때문에 지금 은 한 명의 게이머 만 있 습 니 다.여 기 는 편리 한 후에 확장 할 수 있 습 니 다).
static fishGroups: FishGroup[]; //
그룹 을 그룹 에 추가 하 는 정적 방법:
static AddGroup(group: FishGroup) {
if (this.fishGroups == null) this.fishGroups = new Array();
if (this.fishGroups.indexOf(group) == -1) this.fishGroups.push(group);
}
그룹 을 가 져 오 는 정적 방법(색인 에 따라 가 져 오기):
static GetFishGroup(index: number) {
for (var i = 0; i < this.fishGroups.length; i++)
if (this.fishGroups[i].groupID == index) return this.fishGroups[i];
}
FishGroupManager 가 다 썼 습 니 다.그 다음 에 FishGroup 을 쓰 겠 습 니 다.위 에 사 용 된 groupID 를 정의 하고 물고기 떼 배열 도 있 습 니 다.
groupID: number = 0; // id
fishArr: cc.Component[] = new Array<cc.Component>();
onLoad 에서 자신 을 fishGroups 에 추가 합 니 다:
onLoad() {
FishGroupManager.AddGroup(this);
}
지금 은 물고기 떼 가 생 겼 지만 안에 물고기 한 마리 도 없 기 때문에 우 리 는 물고 기 를 잡 는 방법 이 필요 하 다.
catchFish(fish) {
this.fishArr.push(fish);
}
사용 할 인 자 를 더 정의 하면 FishGroup 이 끝 납 니 다.
keepMinDistance: number = 80;
keepMaxDistance: number = 100;
keepWeight: number = 1; //
moveWeight: number = 0.8; //
다음은 중요 한 장면 이다.물고기 떼 속 의 다른 작은 물고기 들 의 운동 논리 다.player 를 직접 복사 해서 마 운 트 된 FishPlayer 와 FishGroup 스 크 립 트 를 제거 하고 fish 라 고 명명 합 니 다.이것 이 바로 우리 의 작은 물고기 입 니 다.미리 만 듭 니 다.그리고 FishBehaviour 스 크 립 트 를 새로 만 듭 니 다.이 스 크 립 트 는 player 와 일반 물고기 에 걸 려 있 습 니 다.
먼저'물고기 잡기'기능 을 실현 하고 플레이어 가 물고기 에 게 다가 가면 작은 물고기 가 잡 혀 이 플레이어 물고기 떼 의 일원 이 된다.
관련 변수 정의:
@property(cc.Node)
gameManager: cc.Node = null;
game: GameManager;
isPicked: boolean = false;
pickRadius: number = 50; //
groupId: number = -1; // id
myGroup: FishGroup;
마찬가지 로,onLoad()에서 game 에 값 을 부여 합 니 다:
onLoad() {
this.game = this.gameManager.getComponent(GameManager);
}
플레이어 와 의 거 리 를 판단 하 는 방법:
getPlayerDistance() {
let dist = this.node.position.sub(this.game.player.position).mag();
return dist;
}
물고기 떼 를 넣 는 방법:
onPicked() {
// group
this.groupId = this.game.player.getComponent(FishGroup).groupID;
this.myGroup = FishGroupManager.GetFishGroup(this.groupId);
if (this.myGroup != null) {
this.myGroup.catchFish(this);
this.isPicked = true;
}
}
update 에서 호출:
update(dt) {
if (this.isPicked) {
//
}
else {
if (this.getPlayerDistance() < this.pickRadius) {
this.onPicked();
}
}
}
OK,이제 작은 물고기 가 물고기 떼 에 들 어 갔 는데 어떻게 물고기 떼 를 따라 다 니 지?여 기 는 주로 두 가지 점 이 있다.
1.작은 물고 기 는 주변'이웃 물고기'와 함께 이동한다
2.작은 물고기 사이 에는 거 리 를 두 어야 지 너무 붐 비지 않 는 다
그래서 우 리 는 작은 물고기 주위 의 일정한 범위 내 에서 물고기 떼 의 운동 벡터 의 평균 치 를 계산 해 야 한다.이것 도 부족 하 다.'붐 비 는'지 판단 해 야 한다.'붐 비 는'지 여 부 는 멀리 떨 어 진 추 세 를 증가 하고 너무 멀 면 가 까 운 추 세 를 증가 하 며 가중치 를 곱 하면 우리 가 원 하 는 벡터 를 얻 을 수 있다.코드 는 다음 과 같다.
정의 변수:
moveSpeed: number = 170;
rotateSpeed: number = 40; //
neighborRadius: number = 500; // 500
speed: number = 0;
currentSpeed: number = 0;
myMovement: cc.Vec3 = cc.Vec3.ZERO;
평균 벡터 구하 기:
GetGroupMovement() {
var v1: cc.Vec3 = cc.Vec3.ZERO;
var v2: cc.Vec3 = cc.Vec3.ZERO;
for (var i = 0; i < this.myGroup.fishArr.length; i++) {
var otherFish: FishBehaviour = this.myGroup.fishArr[i].getComponent(
FishBehaviour
);
var dis = this.node.position.sub(otherFish.node.position); //
//
if (dis.mag() > this.neighborRadius) {
continue;
}
var v: cc.Vec3 = cc.Vec3.ZERO;
// ,
if (dis.mag() > this.myGroup.keepMaxDistance) {
v = dis.normalize().mul(1 - dis.mag() / this.myGroup.keepMaxDistance);
}
// ,
else if (dis.mag() < this.myGroup.keepMinDistance) {
v = dis.normalize().mul(1 - dis.mag() / this.myGroup.keepMinDistance);
} else {
continue;
}
v1 = v1.add(v); //
v2 = v2.add(otherFish.myMovement); //
}
//
v1 = v1.normalize().mul(this.myGroup.keepWeight);
v2 = v2.normalize().mul(this.myGroup.moveWeight);
var ret = v1.add(v2);
return ret;
}
이제 update 를 보완 할 수 있 습 니 다:
update(dt) {
//
if (this.isPicked) {
var direction = cc.Vec3.ZERO;
if (this.node.name != "player") {
direction = direction.add(this.GetGroupMovement());
}
this.speed = cc.misc.lerp(this.speed, this.moveSpeed, 2 * dt);
this.Drive(direction, this.speed, dt); //
}
//
else {
if (this.getPlayerDistance() < this.pickRadius) {
this.onPicked();
}
}
}
드라이브()방법:
Drive(direction: cc.Vec3, spd: number, dt) {
var finialDirection: cc.Vec3 = direction.normalize();
var finialSpeed: number = spd;
var finialRotate: number = 0;
var rotateDir: number = cc.Vec3.dot(finialDirection, this.node.right);
var forwardDir: number = cc.Vec3.dot(finialDirection, this.node.up);
if (forwardDir < 0) {
rotateDir = Math.sign(rotateDir);
}
//
if (forwardDir < 0.98) {
finialRotate = cc.misc.clampf(
rotateDir * 180,
-this.rotateSpeed,
this.rotateSpeed
);
}
finialSpeed *= cc.misc.clamp01(direction.mag());
finialSpeed *= cc.misc.clamp01(1 - Math.abs(rotateDir) * 0.8);
if (Math.abs(finialSpeed) < 0.01) {
finialSpeed = 0;
}
//
if (this.canMove()) {
this.node.x += this.node.up.x * finialSpeed * dt;
this.node.y += this.node.up.y * finialSpeed * dt;
}
//
var angle1 = finialRotate * 8 * dt;
var angle2 = this.node.angle - angle1;
this.node.angle = angle2 % 360;
this.currentSpeed = finialSpeed;
this.myMovement = direction.mul(finialSpeed);
}
canMove() {
var flag: boolean = true;
//
var pos = this.node.convertToWorldSpaceAR(cc.Vec3.ZERO);
var endPos = pos.add(this.node.up.mul(40));
var hit: cc.PhysicsRayCastResult[] = cc.director
.getPhysicsManager()
.rayCast(
new cc.Vec2(pos.x, pos.y),
new cc.Vec2(endPos.x, endPos.y),
cc.RayCastType.All
);
if (hit.length > 0) {
flag = false;
}
return flag;
}
이상 은 바로 CocosCreator 게임 의 어군 알고리즘 에 대한 상세 한 내용 입 니 다.CocosCreator 어군 알고리즘 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 해 주 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【JavaScript】 볼록함 그라함 스캔을 구현, 애니메이션화한다! ? 【canvas】볼록포를 시각화해 본다. — s-yoshiki | 스크립트 카스 (@s_yoshiki_dev) JavaScript에서 그레이엄 스캔에 의해 정렬되어 가는 애니메이션을 구현했다. 아래쪽에서 데모로 소개. 참고 Java...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.