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 어군 알고리즘 에 관 한 자 료 는 저희 의 다른 관련 글 을 주목 해 주 십시오!

좋은 웹페이지 즐겨찾기