VOID D1PlayerFighter::update(AEHashedTable<AEPlatform>* platformTable) { if (!(isKeyPressed(D1Key::KEY_LEFT) && isKeyPressed(D1Key::KEY_RIGHT))) { FLOAT xSpeed = 0.0f; if (isKeyPressed(D1Key::KEY_LEFT)) { xSpeed = -1.0f; } else if (isKeyPressed(D1Key::KEY_RIGHT)) { xSpeed = 1.0f; } else { xSpeed = 0.0f; } setVx(xSpeed); } FLOAT ySpeed = (isKeyPressed(D1Key::KEY_UP) ? -1.0f : 0.0f) + (isKeyPressed(D1Key::KEY_DOWN) ? 1.0f : 0.0f); setVy(ySpeed); attackTimer--; if (attackTimer == 25 || attackTimer == 15 || attackTimer == 5) { shoot(8.0f); shoot(-8.0f); } if (hpValue <= 0 && action < D1PlayerFighter::ACTION_KILLED) { changeAction(D1PlayerFighter::ACTION_KILLED); AESpriteAttachment* attachedShadow = attachmentTable->getItem(0); if (attachedShadow) attachedShadow->getSprite()->remove(); } D1Sprite::update(platformTable); }
/** Function that takes in the size of the available area to move, and changes the alien's position by its velocity. Then sets velocity to a random number for the next time move is called. lifetime_ is decremented each time the alien moves this way. When lifetime_ = 0, the velocity stays constant and no longer sets randomly. When the alien's position is off-screen, its offScreen flag is set to true. @param windowMaxX the width of the space the Alien can move in and be considered on screen @param windowMaxY the height of the space the Alien can move in and be considered on screen */ void Alien::move(int windowMaxX, int windowMaxY){ // updates x, y positions based on velocities x_ += velocityX_; y_ += velocityY_; setPos(x_,y_); // check whether offScreen if ( (x_+width_)< 0 || (y_+height_)< 0 || (x_ > windowMaxX ) || ( y_ > windowMaxY ) ) offScreen = true; // checks whether appropriate to change velocity if (lifeTime_ != 0 && !dead && !offScreen ) { int mag = rand()%3; switch(mag) { case 0: // move NE setVx(rand()%randFactor_); setVy(rand()%randFactor_); break; case 1: // move NW setVx(- rand()%randFactor_); setVy(rand()%randFactor_); break; case 2: // move SW setVx(- rand()%randFactor_); setVy(- rand()%randFactor_); break; case 3: // move SE setVx(rand()%randFactor_); setVy(- rand()%randFactor_); break; } lifeTime_--; // decrement amount of times allowed to move randomly } }
void OpticalFlowTransitionModel::predict(vector<Sample>& samples, const Mat& image, const optional<Sample>& target) { points.clear(); forwardPoints.clear(); backwardPoints.clear(); forwardStatus.clear(); error.clear(); squaredDistances.clear(); correctFlowCount = 0; // build pyramid of the current image cv::buildOpticalFlowPyramid(makeGrayscale(image), currentPyramid, windowSize, maxLevel, true, BORDER_REPLICATE, BORDER_REPLICATE); if (previousPyramid.empty() || !target) { // optical flow cannot be computed if there is no previous pyramid or no current target swap(previousPyramid, currentPyramid); return fallback->predict(samples, image, target); } // compute grid of points at target location for (auto point = templatePoints.begin(); point != templatePoints.end(); ++point) points.push_back(Point2f(target->getWidth() * point->x + target->getX(), target->getHeight() * point->y + target->getY())); // compute forward and backward optical flow cv::calcOpticalFlowPyrLK(previousPyramid, currentPyramid, points, forwardPoints, forwardStatus, error, windowSize, maxLevel); cv::calcOpticalFlowPyrLK(currentPyramid, previousPyramid, forwardPoints, backwardPoints, backwardStatus, error, windowSize, maxLevel); swap(previousPyramid, currentPyramid); // compute flow and forward-backward-error vector<Point2f> flows; flows.reserve(points.size()); squaredDistances.reserve(points.size()); for (unsigned int i = 0; i < points.size(); ++i) { flows.push_back(forwardPoints[i] - points[i]); if (forwardStatus[i] && backwardStatus[i]) { Point2f difference = backwardPoints[i] - points[i]; squaredDistances.push_back(make_pair(difference.dot(difference), i)); } } if (squaredDistances.size() < points.size() / 2) // the flow for more than half of the points could not be computed return fallback->predict(samples, image, target); // find the flows with the least forward-backward-error (not more than 1 pixel) float maxError = 1 * 0.5f; vector<float> xs, ys; sort(squaredDistances.begin(), squaredDistances.end(), [](pair<float, int> lhs, pair<float, int> rhs) { return lhs.first < rhs.first; }); xs.reserve(squaredDistances.size()); ys.reserve(squaredDistances.size()); for (correctFlowCount = 0; correctFlowCount < squaredDistances.size(); ++correctFlowCount) { if (squaredDistances[correctFlowCount].first > maxError) break; int index = squaredDistances[correctFlowCount].second; xs.push_back(flows[index].x); ys.push_back(flows[index].y); } if (correctFlowCount < points.size() / 2) // to little correct correspondences return fallback->predict(samples, image, target); // compute median flow (only change in position for now) sort(xs.begin(), xs.end()); sort(ys.begin(), ys.end()); float medianX = xs[xs.size() / 2]; float medianY = ys[ys.size() / 2]; Point2f medianFlow(medianX, medianY); // compute ratios of point distances in previous and current image vector<float> squaredRatios; squaredRatios.reserve(correctFlowCount * (correctFlowCount - 1) / 2); for (unsigned int i = 0; i < correctFlowCount; ++i) { for (unsigned int j = i + 1; j < correctFlowCount; ++j) { Point2f point1 = points[squaredDistances[i].second]; Point2f forwardPoint1 = forwardPoints[squaredDistances[i].second]; Point2f point2 = points[squaredDistances[j].second]; Point2f forwardPoint2 = forwardPoints[squaredDistances[j].second]; Point2f differenceBefore = point1 - point2; Point2f differenceAfter = forwardPoint1 - forwardPoint2; float squaredDistanceBefore = differenceBefore.dot(differenceBefore); float squaredDistanceAfter = differenceAfter.dot(differenceAfter); squaredRatios.push_back(squaredDistanceAfter / squaredDistanceBefore); } } // compute median ratio to complete the median flow sort(squaredRatios.begin(), squaredRatios.end()); float medianRatio = sqrt(squaredRatios[squaredRatios.size() / 2]); // predict samples according to median flow and random noise for (auto sample = samples.begin(); sample != samples.end(); ++sample) { int oldX = sample->getX(); int oldY = sample->getY(); float oldSize = sample->getSize(); // change position according to median flow double newX = oldX + medianX; double newY = oldY + medianY; double newSize = oldSize * medianRatio; // add noise to position double positionDeviation = scatter * sample->getSize(); newX += positionDeviation * generator(); newY += positionDeviation * generator(); newSize *= pow(2, scatter * generator()); // round to integer sample->setX((int)(newX + 0.5)); sample->setY((int)(newY + 0.5)); sample->setSize((int)(newSize + 0.5)); // compute change sample->setVx(sample->getX() - oldX); sample->setVy(sample->getY() - oldY); sample->setVSize(sample->getSize() / oldSize); } }