Ejemplo n.º 1
0
void SDLMainLoop::initSDL() {
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) {
        LOG2(SDL, ERROR, "Can't init SDL: " << SDL_GetError());
    }
    
    if(TTF_Init() < 0) {
        LOG2(SDL, ERROR, "Can't init SDL_ttf: " << TTF_GetError());
    }
    
    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

    SDL_WM_SetCaption("HexRacer", NULL);
    
    int width = GET_SETTING("display.width", 0);
    int height = GET_SETTING("display.height", 0);
    int bpp = GET_SETTING("display.bpp", 0);
    
    sdl_init_flags = SDL_HWSURFACE | SDL_OPENGL | SDL_RESIZABLE;
    if(GET_SETTING("display.fullscreen", 0)) {
        sdl_init_flags |= SDL_FULLSCREEN;
    }
    
    SDL_SetVideoMode(width, height, bpp, sdl_init_flags);
    projector.setCurrentDimensions(Point2D(width, height));
}
Ejemplo n.º 2
0
void PhysicalPlayer::applyAcceleration(double acceleration) {
    if(!onGround) return;
    
    rigidBody->activate();
    
    double constant = GET_SETTING("physics.constant.accel", 1.0);
	double brakeConstant = GET_SETTING("physics.constant.brake", 5.0);
    
    btTransform transform = rigidBody->getWorldTransform();
    btMatrix3x3 matrix(transform.getRotation());
    Math::Point orientation = Converter::toPoint(matrix
        * Converter::toVector(Math::Point(0.0, 0.0, 1.0) * constant));
    
    //LOG(PHYSICS, "accel at " << Misc::Sleeper::getTimeMilliseconds());
    
    if(getSliding()) {
        constant *= GET_SETTING("physics.slipstate.accelfactor", 1.0);
    }
    
	if (acceleration >= 0.0 || getLinearVelocity().dotProduct(orientation) < 0.0) {
        double paintInfluence = (speedBoost - 1.0)
            * GET_SETTING("game.paint.boostinfluence", 1.0) + 1.0;
		applyForce(orientation * constant * acceleration * paintInfluence * traction);
	}
	else {
		applyForce(orientation * brakeConstant * acceleration * traction);
	}

	updatePhysicalInfo();
}
Ejemplo n.º 3
0
void FontManager::loadFonts() {
    TTF_Font *font = TTF_OpenFont(
        GET_SETTING("font", "data/gui/DejaVuSans.ttf").c_str(),
        GET_SETTING("font.size", 16));
    
    if(!font) {
        LOG2(GUI, ERROR, "Can't load normal font! "
            << GET_SETTING("font", "data/DejaVuSans.ttf"));
    }
    
    fontList["normal"] = font;
    currentKind = "normal";
}
Ejemplo n.º 4
0
void Suspension::calculateSuspensionForPlayer(Object::Player *player, double forceScale) {

	double front_sep = GET_SETTING("physics.wheel.frontsep", 0.4);
	double front_z = GET_SETTING("physics.wheel.frontz", 0.68);
	double back_sep = GET_SETTING("physics.wheel.backsep", 0.4);
	double back_z = GET_SETTING("physics.wheel.backz", -0.68);

    static const Math::Point suspensionPoint[] = {
        Math::Point(front_sep, -0.2 + 0.05,front_z),
        Math::Point(-front_sep, -0.2 + 0.05, front_z),
        Math::Point(-back_sep, -0.2 + 0.05, back_z),
        Math::Point(back_sep, -0.2 + 0.05, back_z),
    };

	// downward axis of suspension springs
    Math::Point axis = -player->getPhysicalObject()->getUpDirection();
    axis.normalize();
	double downFactor = calculateDownFactor(axis);
	player->getPhysicalObject()->setTraction(std::sqrt(downFactor));

    for(int wheel = 0; wheel < 4; wheel ++) {
        Math::Matrix matrix = player->getTransformation();
        
        // suspension attachment point in world space
        Math::Point point = matrix * suspensionPoint[wheel];
        
        // rotated but not translated suspension attachment point
        Math::Point forcePoint = suspensionPoint[wheel];
        forcePoint.setW(0.0);
        forcePoint = matrix * forcePoint;
        
        // create a Spring object
        Spring spring(point, axis);
        spring.setMinLength(
            GET_SETTING("physics.driving.minlength", 0.0));
        spring.setRestLength(
            GET_SETTING("physics.driving.restlength", 1.0));
        spring.setStretchLength(
            GET_SETTING("physics.driving.stretchlength", 1.0));
        
        // restore last frame's displacement in the Spring object
        spring.setLastDisplacement(
            player->getPhysicalObject()->getSpring(wheel));
        
        // calculate and apply actual force
        Displacement displacement = spring.doRaycast();
        double forceFactor = spring.calculateForceFactor(displacement);
		
        player->applyForce(axis * forceFactor * downFactor * forceScale, forcePoint);
        
        // record displacement for next time
        player->getPhysicalObject()->setSpring(wheel, displacement);
        
        // find the position of the wheel
        double down = displacement.getDisplacement();
        player->setSuspension(wheel,
            suspensionPoint[wheel]
                + Math::Point(0.0, -down - GET_SETTING("physics.wheel.diameter", 0.2), 0.0));
    }
}
Ejemplo n.º 5
0
void WeightedDriver::detectSittingStill() {
    Object::Player *player = getPlayer();

    // if sitting still for too long, request a warp
    intention.setReset(false);

    const Map::PathNode* last_pathnode = nearestPathNode;
    nearestPathNode = player->getPathTracker()->getCurrentNode();

    if (nearestPathNode != NULL && nearestPathNode == last_pathnode
            && player->getPhysicalObject()->getLinearSpeed() < 4.0) {
        unsigned long now = Misc::Sleeper::getTimeMilliseconds();

        if(!sittingStill) {
            sittingStill = true;
            sittingStillSince = now;
        }
        else if(sittingStillSince + GET_SETTING("ai.resettimer", 3000) < now) {
            LOG(PHYSICS, "Player " << player->getID() << " is trying to reset");

            intention.setReset(true);

            sittingStill = false;
        }
    }
    else sittingStill = false;
}
Ejemplo n.º 6
0
void PhysicalPlayer::applyTurning(double amount) {
    if(!onGround) return;
    
    rigidBody->activate();
    
    double constant = GET_SETTING("physics.constant.turn", 1.0);
    double centripetalConstant
        = GET_SETTING("physics.constant.centripetal", 1.0);
    //double leanConstant = GET_SETTING("physics.constant.lean", 1.0);
    
    Math::Matrix matrix = getTransformation();
    Math::Point forwardAxis = matrix * Math::Point(0.0, 0.0, 1.0, 0.0);
    Math::Point centripetalAxis = matrix * Math::Point(-1.0, 0.0, 0.0, 0.0);
    
    forwardAxis.normalize();
    centripetalAxis.normalize();
    
    double speed = getLinearVelocity().length();

	#if 0
    // turn in the opposite direction when travelling backwards
    if (getLinearVelocity().dotProduct(forwardAxis) < 0) {
        speed = -speed;
    }
	#endif

	double speedFactor = GET_SETTING("physics.turning.speedfactor", 0.5);
	double speedThreshhold = GET_SETTING("physics.turning.speedthreshhold", 15.0);
	double falloffFactor = GET_SETTING("physics.turning.fallofffactor", 0.25);

	double turning_factor = GET_SETTING("physics.turning.constant", 1.0);

	if (speed <= speedThreshhold) {
		turning_factor += sqrt(speed/speedThreshhold)*(speed*speedFactor);
	}
	else {
		turning_factor += (speedThreshhold*speedFactor)*(1.0/(1.0+(speed-speedThreshhold)*falloffFactor));
	}
	
	 // turn in the opposite direction when travelling backwards
    if (getLinearVelocity().dotProduct(forwardAxis) < 0) {
        turning_factor = -turning_factor;
    }
    
    if(getSliding()) {
        centripetalConstant *= GET_SETTING("physics.slipstate.centripetalfactor", 1.0);
        constant *= GET_SETTING("physics.slipstate.turnfactor", 1.0);
    }
    
    applyForce(centripetalAxis * centripetalConstant * turning_factor * amount);
    applyTorque(-getUpDirection() * constant * turning_factor * amount);
    
    // twist the car in response to a sharp turn
    //applyTorque(getFrontDirection() * leanConstant * turning_factor * amount);

	updatePhysicalInfo();
}
Ejemplo n.º 7
0
void Suspension::applyDragForce(Object::Player *player, double forceScale) {
    Physics::PhysicalPlayer *physicalPlayer = player->getPhysicalObject();
    Math::Point linearVelocity = physicalPlayer->getLinearVelocity();
    Math::Point angularVelocity = physicalPlayer->getAngularVelocity();
    
    double linear;
	double angular;
	double sideways;

	if (player->getOnGround()) {
		linear = GET_SETTING("physics.driving.lineardrag", 0.1)*player->getPhysicalObject()->getTraction();
		angular = GET_SETTING("physics.driving.angulardrag", 0.1)*player->getPhysicalObject()->getTraction();
		sideways = GET_SETTING("physics.driving.sidewaysdrag", 0.1)*player->getPhysicalObject()->getTraction();
	}
	else {
		linear = GET_SETTING("physics.driving.airlineardrag", 0.1);
		angular = GET_SETTING("physics.driving.airangulardrag", 0.1);
		sideways = GET_SETTING("physics.driving.airsidewaysdrag", 0.1);
	}

    Math::Point linearDrag = -linear * linearVelocity;
    Math::Point angularDrag = -angular * angularVelocity;
    
    physicalPlayer->applyForce(linearDrag * forceScale);
    physicalPlayer->applyTorque(angularDrag * forceScale);
    
    // sideways drag (prevent slipping)
    
    Math::Point sidewaysAxis = physicalPlayer->getRightDirection();
    double sidewaysSpeed = linearVelocity.dotProduct(sidewaysAxis);
    Math::Point sidewaysDrag = -sideways * sidewaysSpeed * sidewaysAxis;
    
    double enterSlipState = GET_SETTING("physics.slipstate.enter", 1.0);
    double exitSlipState = GET_SETTING("physics.slipstate.exit", 1.0);
    
    if(std::fabs(sidewaysSpeed) >= enterSlipState) {
        physicalPlayer->setSliding(true);
    }
    if(std::fabs(sidewaysSpeed) <= exitSlipState) {
        physicalPlayer->setSliding(false);
    }
    
    //LOG(PHYSICS, "sideways " << sidewaysSpeed << "\t" << physicalPlayer->getSliding());
    
    if(physicalPlayer->getSliding()) {
        sidewaysDrag *= GET_SETTING("physics.slipstate.sidewaysfactor", 1.0);
    }
    
    physicalPlayer->applyForce(sidewaysDrag*forceScale);
}
Ejemplo n.º 8
0
double Suspension::Spring::calculateForceFactor(
    const Displacement &thisDisplacement) {
    
    /*LOG(PHYSICS, "spring displacement: " << thisDisplacement.getDisplacement()
        << " (" << thisDisplacement.isOnGround() << ")");*/
    
    if(!thisDisplacement.isOnGround()) {
        return 0.0;
    }
    
    double displacement = thisDisplacement.getDisplacement();
    double displacementSpeed
        = lastDisplacement.getDisplacement() - displacement;
    if(!lastDisplacement.isOnGround()) {
        displacementSpeed = 0.0;  // no damping force when first hit the ground
    }
    
    double GRAVITY = GET_SETTING("physics.constant.gravity", 9.81);
    static const double VEHICLE_WEIGHT = 2.0;
    static const double NORMAL_FORCE = (GRAVITY * VEHICLE_WEIGHT) / 4.0;
    
    static const double K_FACTOR = 100.0;
    static const double INITIAL_K = (K_FACTOR / VEHICLE_WEIGHT / 4.0);
    static const double INITIAL_C = 2 * std::sqrt(INITIAL_K * VEHICLE_WEIGHT);
    
    double K = GET_SETTING("physics.driving.constant.k", 1.0) * INITIAL_K;
    double C = GET_SETTING("physics.driving.constant.c", 1.0) * INITIAL_C;
    
    //LOG(PHYSICS, "normal: " << -NORMAL_FORCE << ", -K*disp: " << -K*displacement);
    //LOG(PHYSICS, "C*disp: " << C*displacementSpeed);
    
    double factor
        = -NORMAL_FORCE + (K * displacement)
        + (-C * displacementSpeed);
    
    // prevent springs from sucking the ground in
    if(factor > 0.0) factor = 0.0;
    
    //LOG(PHYSICS, "factor: " << factor);
    
    //LOG(PHYSICS, "     " << -K*displacement << ", " << C*displacementSpeed);
    
    return factor;
}
Ejemplo n.º 9
0
	const std::list<BonusMessageQueue::BonusMessage>& BonusMessageQueue::getQueue() {

		unsigned long current_time = World::TimeElapsed::getInstance().getGameTime();
		int duration = GET_SETTING("hud.bonusmessages.appearduration", 2000);

		while (!messageQueue.empty() && (*messageQueue.begin()).appearTime+duration < current_time)
			messageQueue.pop_front();

		return messageQueue;
	}
Ejemplo n.º 10
0
void PaintSubsystem::playerErase(Object::Player* player) {

	if (GET_SETTING("game.paint.allowerase", true)) {

		std::vector<Math::HexHeightMap::LayeredHexIndex> changed_indices;
		paintManager->colorCellsInRadius(player->getPosition(), PAINTING_RADIUS, -1, false, &changed_indices);
		if (Bonus::GlobalBonusManager::getInstance())
			Bonus::GlobalBonusManager::getInstance()->getPlayerBonuses(player->getID()).playerErase(static_cast<int>(changed_indices.size()));

	}

}
Ejemplo n.º 11
0
void Suspension::checkForWheelsOnGround() {
    if(!GET_SETTING("physics.driving.enablesuspension", 0)) {
        return;
    }
    
    Object::WorldManager::PlayerIteratorType it
        = worldManager->getPlayerIterator();
    while(it.hasNext()) {
        Object::Player *player = it.next();
        
        int onGround = wheelsOnGround(player->getID());
        player->setOnGround(onGround > 2);
    }
}
Ejemplo n.º 12
0
void Suspension::applySuspension(double forceScale) {
    if(!GET_SETTING("physics.driving.enablesuspension", 0)) {
        return;
    }
    
    Object::WorldManager::PlayerIteratorType it
        = worldManager->getPlayerIterator();
    while(it.hasNext()) {
        Object::Player *player = it.next();
        
        applyDragForce(player, forceScale);
        calculateSuspensionForPlayer(player, forceScale);
    }
}
Ejemplo n.º 13
0
void SDLMainLoop::changeScreenModeHandler(Event::ChangeScreenMode *event) {
    int width = event->getWidth();
    int height = event->getHeight();
    int bpp = event->getBPP();
    bool fullscreen = event->getFullscreen();
    
#ifndef WIN32
    // special case: if just toggling fullscreen, and the operating system
    // supports it, can just call ToggleFullScreen instead of setting the mode
    if(width == GET_SETTING("display.width", 0)
        && height == GET_SETTING("display.height", 0)
        && bpp == GET_SETTING("display.bpp", 0)
        && fullscreen != GET_SETTING("display.fullscreen", 0)) {
        
        if(SDL_WM_ToggleFullScreen(SDL_GetVideoSurface())) return;
    }
#endif
    
    Settings::SettingsManager::getInstance()->set(
        "display.width", Misc::StreamAsString() << width);
    Settings::SettingsManager::getInstance()->set(
        "display.height", Misc::StreamAsString() << height);
    Settings::SettingsManager::getInstance()->set(
        "display.bpp", Misc::StreamAsString() << bpp);
    Settings::SettingsManager::getInstance()->set(
        "display.fullscreen", Misc::StreamAsString() << fullscreen);
    
    if(fullscreen) {
        sdl_init_flags |= SDL_FULLSCREEN;
    }
    else {
        sdl_init_flags &= ~SDL_FULLSCREEN;
    }
    
    SDL_SetVideoMode(width, height, bpp, this->sdl_init_flags);
    resizeGL(width, height);
}
Ejemplo n.º 14
0
void PhysicalPlayer::setData(const Math::Matrix &transform,
    const Math::Point &linearVelocity,
    const Math::Point &angularVelocity, bool interpolate) {
    
    Math::Point originalOrigin = getOrigin();
    
    rigidBody->setWorldTransform(
        Physics::Converter::toTransform(transform));
    rigidBody->setLinearVelocity(
        Physics::Converter::toVector(linearVelocity));
    rigidBody->setAngularVelocity(
        Physics::Converter::toVector(angularVelocity));
    
    Math::Point newOrigin = getOrigin();
    
    if(interpolate && GET_SETTING("network.interpolation.enable", 1)) {
        networkError += originalOrigin - newOrigin;
    }
    else {
        networkError = Math::Point(0.0, 0.0, 0.0);
    }

	updatePhysicalInfo();
}
Ejemplo n.º 15
0
void PaintSubsystem::calculateBoostSpeeds() {

    Object::WorldManager::PlayerIteratorType iterator
        = worldManager->getPlayerIterator();

    while(iterator.hasNext()) {
        Object::Player *player = iterator.next();

		player->setPaintType(getPainting(player->getID()));
        
        if(getPainting(player->getID()) == Event::TogglePainting::NOTHING) {

            double factor = paintManager->weightedCellsInRadius(
                player->getPosition(),
                PAINTING_RADIUS,
                player->getTeamID());

			factor *= GET_SETTING("game.paint.boostweightfactor", 2.0);
			factor += 1.0;
			factor = Math::bound(factor,
				GET_SETTING("game.paint.boostmin", 0.5),
				GET_SETTING("game.paint.boostmax", 1.5)
				);

			double max_boost_increase = GET_SETTING("game.paint.maxboostincrease", 0.01);
			double current_boost = player->getSpeedBoost();
			if (factor < current_boost+max_boost_increase)
	            player->setSpeedBoost(factor);
			else
				player->setSpeedBoost(current_boost+max_boost_increase);
        }
        else {
            // if painting or erasing, slow down the player no matter what
			if (getPainting(player->getID()) == Event::TogglePainting::PAINTING)
				player->setSpeedBoost(GET_SETTING("game.paint.paintingboost", 0.8));
			else
				player->setSpeedBoost(GET_SETTING("game.paint.erasingboost", 0.8));
        }
    }
}
Ejemplo n.º 16
0
Archivo: settings.c Proyecto: bradfa/gt
int gt_parse_settings(config_t *config)
{
	config_setting_t *node, *root, *elem;
	int i, len, ret;
	struct stat st;
	const char *filename;

	if (stat(GT_USER_SETTING_PATH, &st) == 0)
		filename = GT_USER_SETTING_PATH;
	else
		filename = GT_SETTING_PATH;

	ret = config_read_file(config, filename);
	if (ret == CONFIG_FALSE)
		return -1;

	root = config_root_setting(config);

#define GET_SETTING(name, field) do { \
	node = config_setting_get_member(root, name); \
	if (node) { \
		if (config_setting_type(node) != CONFIG_TYPE_STRING) { \
			fprintf(stderr, "%s:%d: Expected string\n", \
					config_setting_source_file(node), \
					config_setting_source_line(node)); \
			return -1; \
		} \
		gt_settings.field = config_setting_get_string(node); \
	} \
} while (0)

	GET_SETTING("default-udc", default_udc);
	GET_SETTING("configfs-path", configfs_path);
	GET_SETTING("default-template-path", default_template_path);
	GET_SETTING("default-gadget", default_gadget);

	node = config_setting_get_member(root, "lookup-path");
	if (node) {
		if (config_setting_is_aggregate(node) == CONFIG_FALSE) {
			fprintf(stderr, "%s:%d: Expected list\n",
					config_setting_source_file(node),
					config_setting_source_line(node));
			return -1;
		}

		len = config_setting_length(node);
		gt_settings.lookup_path = calloc(len + 1, sizeof(*gt_settings.lookup_path));
		for (i = 0; i < len; ++i) {
			elem = config_setting_get_elem(node, i);
			if (config_setting_type(elem) != CONFIG_TYPE_STRING) {
				fprintf(stderr, "%s:%d: Expected string\n",
					config_setting_source_file(elem),
					config_setting_source_line(elem));
				goto out;
			}
			gt_settings.lookup_path[i] = config_setting_get_string(elem);
		}
	}

#undef GET_SETTING

	return 0;
out:
	free(gt_settings.lookup_path);
	return -1;
}
Ejemplo n.º 17
0
double Suspension::calculateDownFactor(const Math::Point& axis) {
	return Math::maximum(GET_SETTING("physics.driving.mindownfactor", 0.1), -axis.normalized().getY());
}
Ejemplo n.º 18
0
void PathingUpdater::update() {
    if(!GET_SETTING("game.enablepathing", true)) {
        return;
    }
    
    Object::WorldManager::PlayerIteratorType iterator = worldManager->getPlayerIterator();
    while (iterator.hasNext()) {
        Object::Player* player = iterator.next();
        
        // Raycast downward to find the update point
        Math::Point origin_pos = player->getPosition();
        Math::Point dir_pos = origin_pos;
        dir_pos.setY(dir_pos.getY() - VEHICLE_PATH_RAY_MAX_HEIGHT);
        
        Math::Point update_pos;
        
        Physics::PhysicsWorld *physicsWorld
            = Physics::PhysicsWorld::getInstance();
        
        // Update if the player is above the track
        if(physicsWorld->raycastPoint(origin_pos, dir_pos, &update_pos)) {
            if(!player->getPathTracker()) continue;  // no path tracker
            if(!player->getPathTracker()->atLeastOneNode()) continue;
            
            player->getPathTracker()->update(update_pos);
            
            // Start a new lap for the player if they have crossed the finish plane
            if (player->getPathTracker()->readyforNewLap() &&
                raceManager->getBoundingPlane().pointInside(origin_pos)) {
                    player->getPathTracker()->startNewLap();
                    LOG(WORLD, "Player: " << player->getID()
                        << " has finished lap "
                        << player->getPathTracker()->getNumLaps());

				if (!player->getPathTracker()->getFinished()
					&& player->getPathTracker()->getNumLaps() >= raceManager->getNumLapsToWin()
					&& !GET_SETTING("internal.practicemode", false) ) {
                    
                    player->getPathTracker()->setFinished(true);
                    
                    Map::PlayerTimes::getInstance().setFinished(
                        player->getID(),
						World::TimeElapsed::getInstance().getGameTime());

					if (Bonus::GlobalBonusManager::getInstance())
						Bonus::GlobalBonusManager::getInstance()->getPlayerBonuses(player->getID()).playerFinish(player->getPathTracker()->getRanking());

				}
                
                if(playerManager->getPlayer() == player) {
                    EMIT_EVENT(new Event::PlayerProgressEvent(
                        player->getPathTracker()->getNumLaps(),
                        player->getPathTracker()->getLapProgress(),
						raceManager->getNumLapsToWin()
						)
						);
                }
            }
        }
        
        warpDetector->checkForWarping(player);
    }

	raceManager->updatePlayerRankings(worldManager.get());
}
Ejemplo n.º 19
0
const World::PlayerIntention &WeightedDriver::getAction() {
    Object::Player *player = getPlayer();
    const Map::PathNode *current = player->getPathTracker()->getCurrentNode();

    Map::PathNode *next;
    Map::PathNode *next2;
    Map::PathNode *previous;

    // find the next node
    if (current->getProgress() < player->getPathTracker()->getLapProgress()) {
        int random = player->getID() % current->getNextNodes().size();
        current = current->getNextNodes()[random];
    }

    previous = current->getPreviousNodes()[0];

    int random = player->getID() % current->getNextNodes().size();
    next = current->getNextNodes()[random];
    random = player->getID() % next->getNextNodes().size();
    next2 = next->getNextNodes()[random];


    // calculate various vectors
    Math::Point playerFacing = player->getPhysicalObject()->getFrontDirection();
    Math::Point playerRight = player->getPhysicalObject()->getRightDirection();

    Math::Point playerPos = player->getPosition();

    double playerSpeed = player->getPhysicalObject()->getLinearSpeed();

    double beeline_u = 1.0-Math::bound(
                           playerPos.distance(current->getPosition())*GET_SETTING("ai.pathlookaheadfactor", 0.1),
                           0.0, 1.0);

    Math::Point beelinePoint = next->getPosition()*(1.0-beeline_u)+next2->getPosition()*beeline_u;
    Math::Point beelineDirection = (beelinePoint-playerPos).normalized();

    Math::Point pathDirection = (current->getPosition() - previous->getPosition()).normalized() * 0.5
                                + (next->getPosition() - current->getPosition()).normalized() * 0.5;
    pathDirection.normalize();

    // compute error due to being far away from this path edge
    double pathTurnSign = -Math::sign(playerRight.dotProduct(pathDirection));

    double distanceOff = player->getPathTracker()->getProgressPosition().distance(playerPos);
    distanceOff *= GET_SETTING("ai.pathdistancefactor", 1.0);

    double angleTurnSign = -Math::sign(playerRight.dotProduct(beelineDirection));

    double beelineAngle = Math::Geometry::vectorTo2DAngle(beelineDirection, Math::Y_AXIS);
    double facingAngle = Math::Geometry::vectorTo2DAngle(playerFacing, Math::Y_AXIS);

    double ccwAngle = std::fabs(beelineAngle-facingAngle);
    double cwAngle = std::fabs(Math::minimum(beelineAngle, facingAngle)+((PI*2.0)-Math::maximum(beelineAngle, facingAngle)));
    double offAngle = Math::minimum(ccwAngle, cwAngle);

    double offAngleFactor = (offAngle/PI) - GET_SETTING("ai.minangleoffset", 0.1);
    double angleFactor;

    if (offAngleFactor < 0.0) {
        offAngleFactor = 0.0;
        angleFactor = 0.0;
    }
    else
        angleFactor = offAngleFactor*GET_SETTING("ai.pathanglefactor", 1.0);


    // compute error due to facing in the wrong direction
    //double beelineAngle = playerRight.dotProduct(beelineDirection);

    double slowDownFactor = playerSpeed-GET_SETTING("ai.minslowdownspeed", 10.0);
    if (slowDownFactor < 0.0)
        slowDownFactor = 0.0;
    else
        slowDownFactor *= GET_SETTING("ai.angleslowdownfactor", 1.0);

    intention.setTurn(Math::bound((pathTurnSign * distanceOff) + (angleTurnSign * angleFactor), -1.0, 1.0));
    intention.setAccel(Math::bound(2.0-(offAngleFactor*slowDownFactor), -1.0, 1.0));

    detectSittingStill();
    detectPaintAhead();

    return intention;
}
Ejemplo n.º 20
0
void WeightedDriver::detectPaintAhead() {

    if (!paintManager)
        return;

    double paintLookAhead = GET_SETTING("ai.paintlookahead", 2.0);
    double minLookAhead = GET_SETTING("ai.minlookahead", 2.0);

    Math::Point headingDir = getPlayer()->getPhysicalObject()->getLinearVelocity()*paintLookAhead;
    double dist = getPlayer()->getPhysicalObject()->getLinearSpeed()*headingDir.length();

    if (dist < minLookAhead) {
        headingDir /= dist;
        headingDir *= minLookAhead;
    }

    Math::Point paintQueryPoint = getPlayer()->getPosition()+headingDir;

    double paintScore = paintManager->weightedCellsInRadius(paintQueryPoint, PAINTING_RADIUS, getPlayer()->getTeamID());

    bool considering_change = false;
    bool change_to_paint = false;
    bool change_to_erase = false;

    double paintThresh = GET_SETTING("ai.stoppaintingthreshhold", 1.2);
    double eraseThresh =  GET_SETTING("ai.starterasingthreshhold", 0.9);

    bool allow_overwrite = GET_SETTING("game.paint.allowoverwrite", false);
    bool allow_erase = GET_SETTING("game.paint.allowerase", true);

    if (!intention.getPaint()) {
        //Not painting: Change to painting
        if ((allow_overwrite || paintScore > eraseThresh) && paintScore < paintThresh) {
            considering_change = true;
            change_to_paint = true;
        }
    }

    if (!considering_change && !intention.getErase()) {
        //Not erasing: Change to erasing
        if (allow_erase && paintScore <= eraseThresh) {
            considering_change = true;
            change_to_erase = true;
        }
    }

    if (!considering_change && intention.getPaint() ) {
        //Is painting: Change to not painting
        considering_change = (paintScore >= paintThresh);
    }

    unsigned long now = Misc::Sleeper::getTimeMilliseconds();

    if (considering_change) {

        if (paintSwitchTime + GET_SETTING("ai.paintswitchdelay", 500) < now) {

            if (change_to_paint) {
                intention.setPaint(true);
                intention.setErase(false);
            }
            else if (change_to_erase) {
                intention.setPaint(false);
                intention.setErase(true);
            }
            else {
                intention.setPaint(false);
                intention.setErase(false);
            }

            paintSwitchTime = now;
        }

    }
    else
        paintSwitchTime = now;

}