| /* |
| * Copyright (C) 2013 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except |
| * in compliance with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software distributed under the License |
| * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express |
| * or implied. See the License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| #include "Boid.h" |
| |
| Boid::Boid(float x, float y) : |
| mPosition(x, y) { |
| } |
| |
| void Boid::flock(const Boid* boids[], int numBoids, int index, float limitX, float limitY) { |
| // Reset the acceleration. |
| mAcceleration.mX = 0; |
| mAcceleration.mY = 0; |
| Vector2D separation; |
| int separationCount = 0; |
| Vector2D alignment; |
| int alignmentCount = 0; |
| Vector2D cohesion; |
| int cohesionCount = 0; |
| for (int i = 0; i < numBoids; i++) { |
| if (i != index) { |
| const Boid* b = boids[i]; |
| float dist = mPosition.distance(b->mPosition); |
| if (dist != 0) { |
| // Separation. |
| if (dist < DESIRED_BOID_DIST) { |
| Vector2D tmp = mPosition.copy(); |
| tmp.sub(b->mPosition); |
| tmp.normalize(); |
| tmp.scale(1.0f / dist); |
| separation.add(tmp); |
| separationCount++; |
| } |
| if (dist < NEIGHBOUR_RADIUS) { |
| // Alignment. |
| alignment.add(b->mVelocity); |
| alignmentCount++; |
| // Cohesion. |
| cohesion.add(b->mPosition); |
| cohesionCount++; |
| } |
| } |
| } |
| } |
| |
| if (separationCount > 0) { |
| separation.scale(1.0f / separationCount); |
| separation.scale(SEPARATION_WEIGHT); |
| mAcceleration.add(separation); |
| } |
| if (alignmentCount > 0) { |
| alignment.scale(1.0f / alignmentCount); |
| alignment.limit(MAX_FORCE); |
| alignment.scale(ALIGNMENT_WEIGHT); |
| mAcceleration.add(alignment); |
| } |
| if (cohesionCount > 0) { |
| cohesion.scale(1.0f / cohesionCount); |
| cohesion.scale(COHESION_WEIGHT); |
| Vector2D desired = cohesion.copy(); |
| desired.sub(mPosition); |
| float d = desired.magnitude(); |
| if (d > 0) { |
| desired.normalize(); |
| desired.scale(MAX_SPEED * ((d < 100.0f) ? d / 100.0f : 1)); |
| desired.sub(mVelocity); |
| desired.limit(MAX_FORCE); |
| mAcceleration.add(desired); |
| } |
| } |
| |
| mVelocity.add(mAcceleration); |
| mVelocity.limit(MAX_SPEED); |
| mPosition.add(mVelocity); |
| // Wrap around. |
| if (mPosition.mX < -limitX) { |
| mPosition.mX = limitX; |
| } else if (mPosition.mX > limitX) { |
| mPosition.mX = -limitX; |
| } |
| if (mPosition.mY < -limitY) { |
| mPosition.mY = limitY; |
| } else if (mPosition.mY > limitY) { |
| mPosition.mY = -limitY; |
| } |
| } |