Пример #1
1
bool NickScene::onInitialize()
{
    Vector3 nodeCenter = Vector3(0.0f, 0.0f, 0.0f);
    
	//-----------------------------------------------------------------
	// create the initial platform which has a button that user can hit
    // to turn the globe on
	//-----------------------------------------------------------------
	m_graph->pushNode();
	{
        nodeCenter = Vector3(0.0f, 100.0f, 300.0f);
        
        //start position Waypoint this is where the player starts/resets
        m_WPstart  = new Start(this, "Objects/goal.obj", 0.125f);
        if ( !m_WPstart->initialize(new LightShader(0.2f, 1.0, 8, RAND_COLOR))) { GLOG("ERROR: could not create OBJmodel\n"); return false; }
        m_WPstart->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 10.0f));
        m_WPstart->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(m_WPstart);

		// create a platform
		Platform *platform = new Platform(this, Vector3(40.0f, 1.0f, 40.0f));
		if ( !platform->initialize(new LightShader(0.2f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize initial platform\n"); return false; }
		platform->setPosition(nodeCenter + Vector3(0.0f, -0.5f, 0.0f));
		platform->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(platform);
    }
	m_graph->popNode();
	
    
    //-----------------------------------------------------------------
	// create long platform that has cannons shooting at it
	//-----------------------------------------------------------------
	m_graph->pushNode();
	{
        nodeCenter += Vector3(0.0f, -30.0f, -130.0f);
        
		// create a platform
		Platform *platform = new Platform(this, Vector3(10.0f, 1.0f, 220.0f));
		if ( !platform->initialize(new LightShader(0.3f, 1.0f, 8, RAND_LIGHT_COLOR))) { GLOG("WARNING: Could not initialize cannon platform\n"); }
		platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
		platform->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(platform);
        
        bool rightSide = false;
        for (int i = 0; i < 10; i++) {
            float cannonZ = (platform->getSize().z * 0.5f) - 50.0f - (i * 15.0f);
            float fireTime = 0.4f + RANDF(1.0f);
            
            // add a cannon aiming at the platform
            Cannon *cannon = new Cannon(this, Vector3(3.0f, 3.0f, 6.0f), 120.0f, fireTime);
            if (!cannon->initialize(new LightShader(0.1f, 1.0f, 8, Color(0.1f, 0.8f, 0.2f)))) { GLOG("WARNING: could not initialize first cannon\n"); }
            float cannonX = rightSide ? 20.0f : -20.0f;
            cannon->setPosition(nodeCenter + Vector3(cannonX, 10.0f, cannonZ));
            float yaw = rightSide ? 90.0f : -90.0f;
            cannon->setOrientation(yaw, -20.0f, 0.0f);
            cannon->addToDynamicWorld(m_dynamicsWorld);
            m_graph->attach(cannon);
            rightSide = !rightSide;
            
            m_cannons.push_back(cannon);
        }
        
        // create a button that will stop the cannons
        NickButton *stop_cannon_button = new NickButton(this, &NickScene::stopCannonsHit, Vector3(8.0f, 0.5f, 4.0f));
        if (!stop_cannon_button->initialize(new LightShader(0.3f, 1.0f, 8, RAND_COLOR))) { GLOG("ERROR: could not create stop_cannon_button\n"); }
		stop_cannon_button->setPosition(nodeCenter + Vector3(0.0f, stop_cannon_button->getSize().y, -105.0f));
		stop_cannon_button->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(stop_cannon_button);
    }
	m_graph->popNode();
    
    
    //-----------------------------------------------------------------
	// create platform after the cannon platform, which just has cube pyramid
    // that covers a gap to the next platform
	//-----------------------------------------------------------------
	m_graph->pushNode();
	{
        nodeCenter += Vector3(0.0f, 0.0f, -120.0f);
        
        // create a checkpoint now that user has gotten through cannons
        NickCheckPoint *cp = new NickCheckPoint(this, "Objects/goal.obj", 0.125f);
		if ( !cp->initialize(new LightShader(0.2f, 1.0, 8, RAND_COLOR))) { GLOG("ERROR: could not create OBJmodel\n"); return false; }
		cp->setPosition(nodeCenter + Vector3(8.0f, 0.5f, 0.0f));
		m_allCheckpoints.push_back(cp);
		cp->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(cp);
        cp->attachParticleSystem(new WaypointParticleSystem(200));
        
		// create a platform
		Platform *platform = new Platform(this, Vector3(50.0f, 1.0f, 12.0f));
		if ( !platform->initialize(new LightShader(0.2f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize gap platform\n"); return false; }
		platform->setPosition(nodeCenter + Vector3(25.0f, -0.5f, 0.0f));
		platform->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(platform);
        
        // cube pyramid right before gap
        m_graph->pushNode();
		Vector3 cubeSize = Vector3(1.5f, 1.5f, 0.5f);
		Vector3 startPoint = nodeCenter + Vector3(49.0f, cubeSize.y / 2.0f, -5.0f);
		CubeGroups::createCubePyramid(this, 7, startPoint, cubeSize, 0.1f, 90.0f);
		m_graph->popNode();
        
        // create a second platform after gap
		platform = new Platform(this, Vector3(20.0f, 1.0f, 10.0f));
		if ( !platform->initialize(new LightShader(0.2f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize 2nd gap platform\n"); return false; }
		platform->setPosition(nodeCenter + Vector3(65.0f, -0.5f, 0.0f));
		platform->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(platform);
    }
	m_graph->popNode();
    
    
    // create a conveyor to take player up to next section
    Conveyor *conveyor1 = new Conveyor(this, Vector3(10.0f, 1.0f, 80.0f), 2.5f );
    if ( !conveyor1->initialize(new LightTexScrollShader(0.3f, 1.0f, 4, Color(1.0f, 1.0f, 1.0f), Vector3(0.0f, -1.0f, 0.0f), conveyor1->getSpeed() * 0.5f, 3.0f))) { GLOG("ERROR: Could not initialize conveyor1\n"); return false; }
    conveyor1->setPosition(nodeCenter + Vector3(85.0f, 2.0f, -35.0f));
    conveyor1->setOrientation(180.0f, 5.0f, 0.0f);
    conveyor1->loadTexture("Textures/conveyor.tga");
    conveyor1->addToDynamicWorld(m_dynamicsWorld);
    m_graph->attach(conveyor1);
    
    
    //-----------------------------------------------------------------
	// create seemingly random small platform that user has to jump between
	//-----------------------------------------------------------------
	m_graph->pushNode();
	{
        nodeCenter += Vector3(85.0f, 5.0f, -85.0f);
        
        float lastZ = 0.0f;
        for (int i = 0; i < 20; i++) {
            Vector3 position = Vector3(-10.0f + RANDF(20.0f), -2.0f + RANDF(4.0f), lastZ - (5.0f + RANDF(5.0f)));
            
            Platform *platform = new Platform(this, Vector3(4.0f + RANDF(5.0f), 1.0f + RANDF(2.0f), 4.0f + RANDF(5.0f)));
            if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize sparse platform\n"); return false; }
            platform->setPosition(nodeCenter + position);
            platform->addToDynamicWorld(m_dynamicsWorld);
            m_graph->attach(platform);
            
            lastZ = position.z - platform->getSize().z * 0.5f;
        }
        
        nodeCenter.z += lastZ - 10.0f;
        
        // larger platform at the end of the small platforms
        Platform *platform = new Platform(this, Vector3(15.0f, 1.0f, 15.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize post-sparse platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
        
        // create a checkpoint now that user has gotten through sparse platforms
        NickCheckPoint *cp = new NickCheckPoint(this, "Objects/goal.obj", 0.125f);
		if ( !cp->initialize(new LightShader(0.2f, 1.0, 8, RAND_COLOR))) { GLOG("ERROR: could not create OBJmodel\n"); return false; }
		cp->setPosition(nodeCenter + Vector3(0.0f, 0.5f, 0.0f));
		m_allCheckpoints.push_back(cp);
		cp->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(cp);
        cp->attachParticleSystem(new WaypointParticleSystem(200));
    }
    m_graph->popNode();
    
    
    //-----------------------------------------------------------------
    // create a slanted platform that drops down onto a large trampoline
    //-----------------------------------------------------------------
    m_graph->pushNode();
    {
        nodeCenter += Vector3(-25.0f, -5.0f, -10);
        
        // angled platform down to trampoline
        Platform *platform = new Platform(this, Vector3(30.0f, 1.0f, 15.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize slanted1 platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
        platform->setOrientation(0.0f, 0.0f, -20.0f);
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
        
        // create large trampoline to bounce off
        Trampoline *tramp = new Trampoline(this, 80.0f, 50.0f);
        if ( !tramp->initialize(new TrampolineShader()) ) { GLOG("ERROR: Could not initialize large trampoline\n"); return false; }
        tramp->setPosition(nodeCenter + Vector3(-30.0f, -75.0f, 0.0f));
        tramp->loadTexture("Textures/trampoline.tga");
        tramp->addToDynamicWorld(m_dynamicsWorld);
        registerForSimulationTicks(tramp);
        m_graph->attach(tramp);
        
        // angled trampoline up on other side of trampoline
        platform = new Platform(this, Vector3(30.0f, 1.0f, 15.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize slanted2 platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(-70.0f, -15.0f, 0.0f));
        platform->setOrientation(0.0f, 0.0f, 20.0f);
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
    }
    m_graph->popNode();
    
    
    //-----------------------------------------------------------------
    // create a row of trampolines that takes you towards the globe
    //-----------------------------------------------------------------
    m_graph->pushNode();
    {
        nodeCenter += Vector3(-105.0f, -10.0f, -20.0f);
        
        // platform before trampolines
        Platform *platform = new Platform(this, Vector3(20.0f, 1.0f, 50.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize pre-tramp platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
        
        nodeCenter += Vector3(0.0f, 0.0f, -15.0f);
        
        // create 4 trampolines in a line at alternating angles
        float sign = -1.0f;
        for (int i = 0; i < 4; i++) {
            // first trampoline
            Trampoline *tramp = new Trampoline(this, 10.0f, 15.0f);
            if ( !tramp->initialize(new TrampolineShader()) ) { GLOG("ERROR: Could not initialize an angled tramp\n"); return false; }
            tramp->setPosition(nodeCenter + Vector3(sign * 6.0, 0.0f, -30.0f + (i * -15.0f)));
            sign *= -1.0f;
            tramp->setRoll(sign * 30.0f);
            tramp->loadTexture("Textures/trampoline.tga");
            tramp->addToDynamicWorld(m_dynamicsWorld);
            registerForSimulationTicks(tramp);
            m_graph->attach(tramp);
        }
        
        // platform after trampolines
        platform = new Platform(this, Vector3(50.0f, 1.0f, 20.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize after tramp platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(-25.0f, 0.0f, -100.0f));
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
        
        // create a checkpoint now that user has gotten through trampolines
        NickCheckPoint *cp = new NickCheckPoint(this, "Objects/goal.obj", 0.125f);
		if ( !cp->initialize(new LightShader(0.1f, 1.0, 8, RAND_COLOR))) { GLOG("ERROR: could not create OBJmodel\n"); return false; }
		cp->setPosition(nodeCenter + Vector3(-10.0f, 1.0f, -100.0f));
		m_allCheckpoints.push_back(cp);
		cp->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(cp);
        cp->attachParticleSystem(new WaypointParticleSystem(200));
    }
    m_graph->popNode();
    
    
    //-----------------------------------------------------------------
    // create a row of trampolines that takes you towards the globe
    //-----------------------------------------------------------------
    m_graph->pushNode();
    {
        nodeCenter += Vector3(-50.0f, 0.0f, -170.0f);
        
        // create a conveyor to take player past fire breathers
        Conveyor *conveyor1 = new Conveyor(this, Vector3(15.0f, 1.0f, 100.0f), 2.5f );
        if ( !conveyor1->initialize(new LightTexScrollShader(0.3f, 1.0f, 4, Color(1.0f, 1.0f, 1.0f), Vector3(0.0f, -1.0f, 0.0f), conveyor1->getSpeed() * 0.5f, 3.0f))) { GLOG("ERROR: Could not initialize conveyor1\n"); return false; }
        conveyor1->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
        conveyor1->setOrientation(180.0f, 0.0f, 0.0f);
        conveyor1->loadTexture("Textures/conveyor.tga");
        conveyor1->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(conveyor1);
        
        // create a fire breathing hydralisk
        FireBreather *fireBreather = new FireBreather(this, 15.0f, 5.0f, 2.0f);
        if ( !fireBreather->initialize(new LightTexShader(0.2f, 1.0, 8, Color(1.0f, 1.0f, 1.0f)))) { GLOG("ERROR: could not create fire breather\n"); return false; }
        fireBreather->setPosition(nodeCenter + Vector3(-20.0f, 5.0f, 15.0f));
        fireBreather->setOrientation(-90.0f, 0.0f, 0.0f);
        fireBreather->loadTexture("Textures/hydralisk.tga");
        fireBreather->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(fireBreather);
        fireBreather->attachParticleSystem(new FireParticleSystem(500));
        
        // create a fire breathing hydralisk
        fireBreather = new FireBreather(this, 15.0f, 5.0f, 2.0f);
        if ( !fireBreather->initialize(new LightTexShader(0.2f, 1.0, 8, Color(1.0f, 1.0f, 1.0f)))) { GLOG("ERROR: could not create fire breather\n"); return false; }
        fireBreather->setPosition(nodeCenter + Vector3(20.0f, 5.0f, -10.0f));
        fireBreather->setOrientation(90.0f, 0.0f, 0.0f);
        fireBreather->loadTexture("Textures/hydralisk.tga");
        fireBreather->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(fireBreather);
        fireBreather->attachParticleSystem(new FireParticleSystem(500));
    }
    m_graph->popNode();
    
    
    //-----------------------------------------------------------------
    // create platform that has cannon which shoots globe
    //-----------------------------------------------------------------
    m_graph->pushNode();
    {
        nodeCenter += Vector3(20.0f, 0.0f, -65.0f);
        
        // platform after fire breathers
        Platform *platform = new Platform(this, Vector3(15.0f, 1.0f, 30.0f));
        if ( !platform->initialize(new LightShader(0.3f, 0.8f, 8, RAND_COLOR))) { GLOG("ERROR: Could not initialize fire platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
        platform->setOrientation(30.0f, 0.0f, 0.0f);
        platform->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(platform);
        
        // create a button that will shoot the cannon at globe
        NickButton *globe_shoot_button = new NickButton(this, &NickScene::shootGlobeHit, Vector3(10.0f, 0.5f, 6.0f));
        if (!globe_shoot_button->initialize(new LightShader(0.3f, 1.0f, 8, RAND_COLOR))) { GLOG("ERROR: could not create globe_button\n"); return false; }
		globe_shoot_button->setPosition(nodeCenter + Vector3(5.0f, globe_shoot_button->getSize().y + 0.25f, -8.0f));
        globe_shoot_button->setOrientation(30.0f, 0.0f, 0.0f);
		globe_shoot_button->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(globe_shoot_button);
        
        m_globeCannon = new Cannon(this, Vector3(5.0f, 5.0f, 10.0f), 80.0f);
        if (!m_globeCannon->initialize(new LightShader(0.1f, 1.0f, 8, Color(0.1f, 0.8f, 0.2f)))) { GLOG("WARNING: could not initialize first cannon\n"); }
        m_globeCannon->setPosition(nodeCenter + Vector3(-0.0f, 2.0f, -40.0f));
        m_globeCannon->setOrientation(260.0f, 0.0f, 0.0f);
        m_globeCannon->addToDynamicWorld(m_dynamicsWorld);
        m_graph->attach(m_globeCannon);
    }
    m_graph->popNode();
    
    //-----------------------------------------------------------------
	// create the ending platform that has the globe and waypoint on it
	//-----------------------------------------------------------------
    m_graph->pushNode();
    {
        nodeCenter = Vector3(0.0f, 30.0f, -600.0f);
        
        //// create a platform
		Platform *platform = new Platform(this, Vector3(70.0f, 2.0f, 70.0f));
		if ( !platform->initialize(new LightShader(0.2f, 1.0f, 4, RAND_COLOR))) { GLOG("ERROR: Could not initialize ending platform\n"); return false; }
        platform->setPosition(nodeCenter + Vector3(0.0f, 0.0f, 0.0f));
		platform->addToDynamicWorld(m_dynamicsWorld);
		m_graph->attach(platform);
        
        // create a fracture globe that explodes
        Sphere *globe = new Sphere(this, 20.0f);
        if ( !globe->initialize(new LightTexScrollShader(1.0f, 0.2f, 2, Color(1.0f, 1.0f, 1.0f, 1.0f), Vector3(1.0f, 0.0f, 0.0f), 0.001f))) { GLOG("ERROR: could not initialize globe.\n"); return false; }
        globe->setPosition(nodeCenter + Vector3(0.0f, 30.0f, 0.0f));
        globe->setOrientation(0.0f, -90.0f, 0.0f);
        globe->loadTexture("Textures/earth.tga");
        m_globeFracture = new FractureObject(globe, "Textures/voronoi_fracure.tga", 80.0f);
        if ( !m_globeFracture->addToScene(this) ) { GLOG("ERROR: could not add globe fracture to scene.\n"); return false; }
    }
    m_graph->popNode();
    
    
    // create a particle system
    ParticleSystem *m_particleSystem = new StarryParticleSystem(2000);
    m_particleSystem->startSystem();
    m_graph->attach(m_particleSystem);
    
    m_playerParticleSystem = new PlayerParticleSystem(300);
    m_playerParticleSystem->startSystem();
    m_graph->attach(m_playerParticleSystem);
    
    
	// create the player and return result
	return resetPlayer();
}
Пример #2
0
// Create the teleport effect
void create_teleport_effect(int x, int y) {

	// Add the big glow particle
	VECT pos(x + 0.5f, 0.5f, y + 0.5f);
	VECT dir = 0.0f;
	float c1[4] = { 1.0f, 1.0f, 0.3f, 1.0f };
	float c2[4] = { 1, 1, 0, 0 };
//	float c1[4] = { 0.3f, 0.8f, 1.0f, 1.0f };
//	float c2[4] = { 0, 0, 1, 0 };
	add_particle(pos, dir, 60, 2.0f, 1.0f, c1, c2, part_glow);

	// Create those "fire lines"
	for(int f=0; f < RAND(5,6); f++) {
	    // Choose the direction
		VECT dir;
		dir.x = RANDF(-0.5f, 0.5f);
		dir.y = RANDF(0.05f, 0.5f);
		dir.z = RANDF(-0.5f, 0.5f);
		normalize(dir);

		// Create the particles
		int max = RAND(25, 50);
		for(int i=0; i < max; i++) {
			VECT p(x + 0.5f, 0.0f, y + 0.5f);
			p += (dir * (float)i * 0.1f);
			VECT d = 0.0f;
			float s = (float)i / (float)max;
			add_particle(p, d, RAND(40,80), 0.5f * (1.0f-s), 0.00f, c1, c2, part_glow);
		}

	}

}
Пример #3
0
// The lightning effect
void draw_lightning(VECT pos1, VECT pos2, float noise1, float noise2) {

	glDisable(GL_DEPTH_TEST);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
	BIND_TEXTURE(0);

	// Draw two bolts
	float color[4] = { .5f, .8f, 1, 1 };
	light_bolt(pos1, pos2, 15, noise1, 5, 0, color);		// noise: 0.35f

	float color2[4] = { .2f, .6f, 1, 1 };
	light_bolt(pos1, pos2, 10, noise2, 3, 1, color2);		// noise: 0.20f

	// Draw the end point glows
	BIND_TEXTURE(part_glow);
	glColor4f(.4f, .8f, 1, RANDF(.5f,1));
	glPushMatrix();
	glTranslatef(pos1.x, pos1.y, pos1.z);
	// Negate the camera rotation
	glRotatef(45.0f, 0,1,0);
	glRotatef(-30.0f, 1,0,0);
	glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f(1,1); glVertex3f( 1.2f,  1.2f,  1.2f);
		glTexCoord2f(0,1); glVertex3f(-1.2f,  1.2f,  1.2f);
		glTexCoord2f(1,0); glVertex3f( 1.2f, -1.2f, -1.2f);
		glTexCoord2f(0,0); glVertex3f(-1.2f, -1.2f, -1.2f);
	glEnd();
	glPopMatrix();

/*	glPushMatrix();
	glTranslatef(pos2.x, pos2.y, pos2.z);
	// Negate the camera rotation
	glRotatef(45.0f, 0,1,0);
	glRotatef(-30.0f, 1,0,0);
	glBegin(GL_TRIANGLE_STRIP);
		glTexCoord2f(1,1); glVertex3f( 1.2f,  1.2f,  1.2f);
		glTexCoord2f(0,1); glVertex3f(-1.2f,  1.2f,  1.2f);
		glTexCoord2f(1,0); glVertex3f( 1.2f, -1.2f, -1.2f);
		glTexCoord2f(0,0); glVertex3f(-1.2f, -1.2f, -1.2f);
	glEnd();
	glPopMatrix();
*/
	glEnable(GL_DEPTH_TEST);
}
Пример #4
0
void execute(cl_device_id device, cl_context context, cl_command_queue queue)
{
    cl_int err;

    cl_program program;
    cl_kernel kernel;

    char *source;
    size_t length;

    size_t global_size[] = {NUM_WORLDS, ROBOTS_PER_WORLD};
    size_t local_size[] = {1, ROBOTS_PER_WORLD};

    cl_uint ann_param_size = ANN_PARAM_SIZE;
    cl_float targets_distance = TARGETS_DISTANCE;
    cl_uint save = 0;

    unsigned int i, j, k;

    char *param_list = (char*) malloc(NUM_WORLDS * ANN_PARAM_SIZE);
    for (i=0; i<NUM_WORLDS; i++)
    {
        for (j=0; j < ANN_PARAM_SIZE; j++)
        {
            param_list[(i*ANN_PARAM_SIZE)+j] = params[j];
        }
    }

    cl_float4 *random_positions = (cl_float4*) malloc(NUM_WORLDS * ROBOTS_PER_WORLD * 10 * sizeof(cl_float4));
    for (i=0; i<NUM_WORLDS; i++)
    {
        for (j=0; j < ROBOTS_PER_WORLD; j++)
        {
            for (k=0; k < 10; k++)
            {
                random_positions[i*(ROBOTS_PER_WORLD*10)+j*10+k].s0 = RANDF();
                random_positions[i*(ROBOTS_PER_WORLD*10)+j*10+k].s1 = RANDF();
                random_positions[i*(ROBOTS_PER_WORLD*10)+j*10+k].s2 = RANDF();
                random_positions[i*(ROBOTS_PER_WORLD*10)+j*10+k].s3 = RANDF();
            }
        }
    }

    char build_options[4096];
    sprintf(
        build_options,
        "-I\"%s\" -DNUM_WORLDS=%d -DROBOTS_PER_WORLD=%d -DTIME_STEP=%f -DTA=%d -DTB=%d -DWORLDS_PER_LOCAL=%d -DROBOTS_PER_LOCAL=%d",
        "/home/buratti/srs2d/srs2d/kernels", NUM_WORLDS, ROBOTS_PER_WORLD, TIME_STEP, TA, TB, (int) local_size[0],  (int) local_size[1]
    );

    // load source code from file
    length = load_source("../srs2d/kernels/physics.cl", &source);
    assert(length > 0, -1, "load_source()");

    // create and build program
    program = clCreateProgramWithSource(context, 1, (const char **) &source, &length, &err);
    assert(err == CL_SUCCESS, err, "clCreateProgramWithSource()");

    err = clBuildProgram(program, 0, NULL, (const char*) build_options, NULL, NULL);
    if ((err != CL_SUCCESS) && (err == CL_BUILD_PROGRAM_FAILURE))
    {
        cl_build_status build_status;
        char *build_log;
        size_t build_log_size;

        err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(cl_build_status), &build_status, NULL);
        assert(err == CL_SUCCESS, err, "clGetProgramBuildInfo()");

        err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &build_log_size);
        assert(err == CL_SUCCESS, err, "clGetProgramBuildInfo()");

        build_log = (char *) malloc(build_log_size+1);

        err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, build_log_size, build_log, NULL);
        assert(err == CL_SUCCESS, err, "clGetProgramBuildInfo()");

        build_log[build_log_size] = '\0';

        fprintf(stderr, "BUILD LOG:\n%s\n\n", build_log);

        free(build_log);
        exit(EXIT_FAILURE);
    }

    // create buffers
    cl_mem worlds_buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(world_t) * NUM_WORLDS, NULL, &err);
    assert(err == CL_SUCCESS, err, "clCreateBuffer()");

    cl_mem param_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_char) * ANN_PARAM_SIZE * NUM_WORLDS, NULL, &err);
    assert(err == CL_SUCCESS, err, "clCreateBuffer()");

    cl_mem random_positions_buffer = clCreateBuffer(context, CL_MEM_READ_ONLY, sizeof(cl_float4) * 10 * ROBOTS_PER_WORLD * NUM_WORLDS, NULL, &err);
    assert(err == CL_SUCCESS, err, "clCreateBuffer()");

    cl_mem fitness_buffer = clCreateBuffer(context, CL_MEM_WRITE_ONLY, sizeof(cl_float) * NUM_WORLDS, NULL, &err);
    assert(err == CL_SUCCESS, err, "clCreateBuffer()");

    // copy host mem to buffers
    err = clEnqueueWriteBuffer(queue, param_buffer, CL_TRUE, 0, sizeof(cl_char) * ANN_PARAM_SIZE * NUM_WORLDS, param_list, 0, NULL, NULL);
    assert(err == CL_SUCCESS, err, "clEnqueueWriteBuffer()");

    err = clEnqueueWriteBuffer(queue, random_positions_buffer, CL_TRUE, 0, sizeof(cl_float4) * 10 * ROBOTS_PER_WORLD * NUM_WORLDS, random_positions, 0, NULL, NULL);
    assert(err == CL_SUCCESS, err, "clEnqueueWriteBuffer()");

    // execute simulate kernel
    kernel = clCreateKernel(program, "simulate", &err);
    assert(err == CL_SUCCESS, err, "clCreateKernel()");

    err = CL_SUCCESS;
    err |= clSetKernelArg(kernel, 0, sizeof(cl_mem), (void*) &worlds_buffer);
    err |= clSetKernelArg(kernel, 1, sizeof(cl_float), (void*) &targets_distance);
    err |= clSetKernelArg(kernel, 2, sizeof(cl_mem), (void*) &param_buffer);
    err |= clSetKernelArg(kernel, 3, sizeof(cl_uint), (void*) &ann_param_size);
    err |= clSetKernelArg(kernel, 4, sizeof(cl_mem), (void*) &random_positions_buffer);
    err |= clSetKernelArg(kernel, 5, sizeof(cl_mem), (void*) &fitness_buffer);
    err |= clSetKernelArg(kernel, 6, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 7, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 8, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 9, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 10, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 11, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 12, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 13, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 14, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 15, sizeof(cl_mem), NULL);
    err |= clSetKernelArg(kernel, 16, sizeof(cl_uint), (void*) &save);
    assert(err == CL_SUCCESS, err, "clSetKernelArg()");

    // execute kernel
    err = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, global_size, local_size, 0, NULL, NULL);
    assert(err == CL_SUCCESS, err, "clEnqueueNDRangeKernel()");

    // copy results from device
    float *fitness = (float *) malloc(NUM_WORLDS * sizeof(cl_float));
    err = clEnqueueReadBuffer(queue, fitness_buffer, CL_TRUE, 0, NUM_WORLDS * sizeof(cl_float), fitness, 0, NULL, NULL);
    assert(err == CL_SUCCESS, err, "clEnqueueReadBuffer()");

    for (i=0; i<NUM_WORLDS; i++)
        printf("fitness[%d] = %f\n", i, fitness[i]);

    err = CL_SUCCESS;
    err |= clReleaseMemObject(worlds_buffer);
    err |= clReleaseMemObject(param_buffer);
    err |= clReleaseMemObject(fitness_buffer);
    assert(err == CL_SUCCESS, err, "clReleaseMemObject()");

    err = clReleaseKernel(kernel);
    assert(err == CL_SUCCESS, err, "clReleaseKernel()");

    err = clReleaseProgram(program);
    assert(err == CL_SUCCESS, err, "clReleaseProgram()");

    free(param_list);
    free(fitness);
    free(source);
}
Пример #5
0
// Move the enemy
void ENEMY::move() {
	// Advance the animation
	if(!chase && !burning)
		anim += 0.10f;
	else
		anim += 0.20f;
	if((int)anim > 3 || kicked)
		anim = 0.0f;

	// Advance the dying animation if we're actually dying
	if(dying) {
		die_anim -= 0.03f;

		// Create the blue "burning down" effect
		float px = get_real_x();
		float py = get_real_y();
		for(int f=0; f < RAND(2,10); f++) {
			float rnd = RANDF(-0.3f, 0.3f);
			VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py);
			pos.x += rnd;
			pos.z -= rnd;
			if(pos.y < 0.0f)
				pos.y = 0.0f;
			if(turning)
				pos.y += (turning_raise * 0.85f);
			VECT dir = 0.0f;
			float c1[4] = { 0.1f, 0.7f, 1, 1 };
			float c2[4] = { 0.1f, 0.7f, 1, 0 };
			add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star);
		}

		if(die_anim < 0.0f) {
			die_anim = 0.0f;
			alive = false;
		}

		return;
	}


	// Create some particle fire from the burning enemies
	if(burning) {
		VECT ppos(get_real_x(), 0.5f, get_real_y());
		create_fire(ppos);
	}

	// Advance the turning animation
	if(turning) {
		// Raise up
		if(turning == 1) {
			turning_raise += 0.035f;
			if(turning_raise >= 1.0f) {
				turning_raise = 1.0f;
				turning++;
			}
		}
		// Turn
		else if(turning == 2) {
			turning_counter++;
			if(turning_counter == 5) {
				dir = nextdir;
				nextdir = dir + 1;
				if(nextdir > DIR_W)
					nextdir = DIR_N;
			}
			else if(turning_counter == 10) {
				dir = nextdir;
				turning++;
			}
		}
		// Go down
		else if(turning == 3) {
			turning_raise -= 0.035f;
			if(turning_raise <= 0.0f) {
				turning_raise = 0.0f;
				turning = 0;
			}
		}

		// Check the collision between the player #1
		if(p1.alive && !p1.jumping) {
			float dx = get_real_x() - p1.get_real_x();
			float dy = get_real_y() - p1.get_real_y();
			if(dx*dx + dy*dy <= 0.9f) {
				// Collision happened!

				// Kill the player and die
				p1.die();
				die();
			}
		}

		// Check the collision between the player #2
		if(alive && two_players && p2.alive && !p2.jumping) {
			float dx = get_real_x() - p2.get_real_x();
			float dy = get_real_y() - p2.get_real_y();
			if(dx*dx + dy*dy <= 0.9f) {
				// Collision happened!

				// Kill the player and die
				p2.die();
				die();
			}
		}

		return;
	}


	// If there is the lightning special power in progress, don't move the enemies which are
	// suffering from the lightning strikes
	if(special_power_pause && which_special_power == BLUE_POWER_LIGHTNING) {
		// Check if we're a target
		for(int f=0; f<ENEMY_AMOUNT; f++) {
			if(sp_lightning.targets[f] == this) {
				anim += 0.30f;
				if((int)anim > 3)
					anim = 0.0f;
				return;
			}
		}
	}

	// Don't move if the level is finished
	if(level_pause)
		return;


	// Check the traps
	if(traplist.size() > 0) {
		list<TRAP>::iterator t;
		for(t = traplist.begin(); t != traplist.end(); ++t) {
			if(x == (*t).x && y == (*t).y) {
				die();
				return;
			}
		}
	}


	// Handle the burning, that is run around aimlessly
	if(burning) {
		if(!kicked) {
			// Reduce the burning time
			burn_time--;
			if(burn_time == 0) {
				die();
				return;
			}

			// Choose a random direction
			if(RAND(0,100) > 50 && offset == 0.0f) {
				if(RAND(0,100) > 50)
					dir++;
				else
					dir--;
				if(dir > DIR_W)
					dir = DIR_N;
				else if(dir < DIR_N)
					dir = DIR_W;
			}

			// Move one step
			if(tx == x && ty == y) {
				offset = 0.0f;

				// Don't stop until there's a wall.
				switch(dir) {
					default:
					case DIR_N: tx = x; ty = y - 1; break;
					case DIR_E: tx = x + 1; ty = y; break;
					case DIR_S: tx = x; ty = y + 1; break;
					case DIR_W: tx = x - 1; ty = y; break;
				}

				// Check if the target is passable?
				if(map_solid(tx, ty)) {
					// Stop and choose a new dir
					tx = x;
					ty = y;

					dir += RAND(-1,1);
					if(dir < DIR_N)
						dir = DIR_W;
					else if(dir > DIR_W)
						dir = DIR_N;
					return;
				}

			}

			// Move towards the target tile
			if(offset < 1.0f && (tx != x || ty != y)) {
				offset += speed;

				// Check the collision between the player #1
				if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
					float dx = get_real_x() - p1.get_real_x();
					float dy = get_real_y() - p1.get_real_y();
					if(dx*dx + dy*dy <= 0.9f) {
						// Collision happened!

						// Turn around and run
						tx = x;
						ty = y;
						offset = 0.0f;
						dir += 2;
						if(dir > DIR_W)
							dir -= 4;
					}
				}

				// Check the collision between the player #2
				if(two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
					float dx = get_real_x() - p2.get_real_x();
					float dy = get_real_y() - p2.get_real_y();
					if(dx*dx + dy*dy <= 0.9f) {
						// Collision happened!

						// Turn around and run
						tx = x;
						ty = y;
						offset = 0.0f;
						dir += 2;
						if(dir > DIR_W)
							dir -= 4;
					}
				}

				// Check the collision between the potato men
				if(potatoman.collide_with(this) && !kicked) {
					// Potatoman "kicked" us
					potatoman.kick(this);
				}


				// If we're reached the target tile, move again
				if(offset >= 1.0f) {
					x = tx;
					y = ty;
					offset = 0.0f;
				}
			}
		}

		// Check collisions with other enemies and spread the fire
		bool burnt_somebody = false;
		list<ENEMY>::iterator e;
		for(e = enemylist.begin(); e != enemylist.end(); ++e) {
			if(this != &(*e) && !(*e).burning) {
				// Check the distance
				float dx = get_real_x() - (*e).get_real_x();
				float dy = get_real_y() - (*e).get_real_y();
				if(dx*dx + dy*dy <= 0.9f) {
					// Burn the other enemy
					(*e).burning = true;
					(*e).burn_time = enemy_burn_time;
					(*e).speed += 0.06f;
					burnt_somebody = true;
				}
			}
		}

		// Play the burning sound
		if(burnt_somebody)
			play_sound(SND_WILDFIRE, false);

		if(!kicked)
			return;
	}


	// Not burning below here

	// Choose a random destination
	if(path_pos == -1) {
		// Choose a valid target
		int dx = RAND(0, MAP_W-1);
		int dy = RAND(0, MAP_H-1);
		while(map_solid(dx, dy) || dx == x || dy == y) {
			dx = RAND(0, MAP_W-1);
			dy = RAND(0, MAP_H-1);
		}

		// Calculate the path
		if(pf.find_path(x, y, dx, dy) == PATH_FAILED) {
			// Well, tough luck. We'll just wait and try again later.
			return;
		}

		// Now we've got a nice path for us!
		path_pos = 0;
		offset = 0.0f;
		tx = pf.path[0].x;
		ty = pf.path[0].y;
		dir = get_dir(tx - x, ty - y);
		look_player();
	}

	// Move one step
	if(tx == x && ty == y && path_pos > -1) {
		offset = 0.0f;

		// Follow the path if we're not chasing
		if(chase == 0 && !kicked) {
			path_pos++;
			tx = pf.path[path_pos].x;
			ty = pf.path[path_pos].y;
			dir = get_dir(tx - x, ty - y);
			look_player();
		}
		else if(chase && !kicked) {
			// We are chasing. Don't stop until there's a wall.
			switch(dir) {
				default:
				case DIR_N: tx = x; ty = y - 1; break;
				case DIR_E: tx = x + 1; ty = y; break;
				case DIR_S: tx = x; ty = y + 1; break;
				case DIR_W: tx = x - 1; ty = y; break;
			}

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				// Stop and choose a new path
				tx = x;
				ty = y;

				path_pos = -1;
				chase = 0;
				speed -= 0.03f;
			}
		}
		else if(kicked) {
			// Potatoman has kicked us. "Fly" straight until we hit a wall.
			switch(dir) {
				default:
				case DIR_N: tx = x; ty = y - 1; break;
				case DIR_E: tx = x + 1; ty = y; break;
				case DIR_S: tx = x; ty = y + 1; break;
				case DIR_W: tx = x - 1; ty = y; break;
			}

			// Check for the wall
			if(map_solid(tx, ty)) {
				die();
				return;
			}
		}
	}

	// Move towards the target tile
	if(offset < 1.0f && (tx != x || ty != y) && path_pos > -1) {
		offset += speed;

		// Check the collision between the player #1
		if(p1.alive && !p1.jumping && !(using_special_power == 1 && which_special_power == BLUE_POWER_TELEPORT)) {
			float dx = get_real_x() - p1.get_real_x();
			float dy = get_real_y() - p1.get_real_y();
			if(dx*dx + dy*dy <= 0.9f) {
				// Collision happened!

				// Kill the player and die
				p1.die();
				die();
			}
		}

		// Check the collision between the player #2
		if(alive && two_players && p2.alive && !p2.jumping && !(using_special_power == 2 && which_special_power == BLUE_POWER_TELEPORT)) {
			float dx = get_real_x() - p2.get_real_x();
			float dy = get_real_y() - p2.get_real_y();
			if(dx*dx + dy*dy <= 0.9f) {
				// Collision happened!

				// Kill the player and die
				p2.die();
				die();
			}
		}


		// Check the collision between the potato men
		if(potatoman.collide_with(this) && !kicked) {
			// Potatoman "kicked" us
			potatoman.kick(this);
		}


		// If we're reached the target tile, move again
		if(offset >= 1.0f) {
			x = tx;
			y = ty;
			offset = 0.0f;

			// If this is the final destination, stay put and choose a new path
			// on the next cycle
			if(x == pf.dx && y == pf.dy && !chase && !kicked)
				path_pos = -1;
		}
	}

}
Пример #6
0
// Create some particle fire
void create_fire(VECT pos) {
	VECT ppos = pos;

	// Create some particle fire
	for(int i=0; i<RAND(3,7); i++) {
		ppos = pos;
		ppos.x += RANDF(-0.4f, 0.4f);
		ppos.y += RANDF(-0.3f, 0.3f);
		ppos.z += RANDF(-0.4f, 0.4f);
		VECT dir(RANDF(-0.01f,0.01f), RANDF(0.05f,0.15f), RANDF(-0.01f,0.01f));
		float c1[4] = { 1, 0.5f, 0.1f, 1 };
		float c2[4] = { 1, 0.1f, 0.1f, 0.1f };
		add_particle(ppos, dir, RAND(20,35), 0.3f, 0.1f, c1, c2, part_fire);
	}

	// Create smoke
	if(RAND(0,100) > 50) {
		pos.y += 0.2f;
		pos.x += RANDF(-0.3f, 0.3f);
		pos.y += RANDF(0.1f, 0.5f);
		pos.z += RANDF(-0.3f, 0.3f);
		VECT dir(RANDF(-0.01f,0.01f), RANDF(0.05f,0.1f), RANDF(-0.01f,0.01f));
		float c1[4] = { 0.5f, 0.1f, 0.1f, 1 };
		float c2[4] = { 0.1f, 0.1f, 0.1f, 0 };
		add_particle(pos, dir, RAND(20,35), 0.2f, 0.4f, c1, c2, part_smoke, true);
	}
}
Пример #7
0
// Create an explosion to a tile
void create_explosion(int x, int y, int type) {
	int p;
	if(type == EXP_BOMB_NORMAL) {
		for(p = 0; p < RAND(20,40); p++) {
			// Add the explosion flames
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.01f, 0.01f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.01f, 0.01f);
			float c1[4] = { 1, 0.3f, 0.2f, 1 };
			float c2[4] = { 1, 0, 0, 0 };
			add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo);
		}
		for(p = 0; p < RAND(10,30); p++) {
			// Add the sparks
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.05f, 0.05f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.05f, 0.05f);
			float c1[4] = { 1, 0.7f, 0.3f, 1 };
			float c2[4] = { 0, 0, 1, 0 };
			add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark);
		}
	}

	if(type == EXP_BOMB_FLOWER) {
		for(p = 0; p < RAND(10,30); p++) {
			// Add the explosion flames
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.01f, 0.01f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.01f, 0.01f);
			float c1[4] = { 0.5f, 0, 1, 1 };
			float c2[4] = { 0.2f, 1, 0.2f, 0 };
			add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo);
		}
		for(p = 0; p < RAND(1,5); p++) {
			// Add the flowers
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.05f, 0.05f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.05f, 0.05f);
			float c1[4] = { 1, 1, 1, 1 };
			float c2[4] = { 1, 1, 1, 0 };
			add_particle(pos, dir, RAND(50,100), 0.5f, 0.1f, c1, c2, part_flower, true);
		}
	}

	else if(type == EXP_BOMB_CENTER) {
		for(p = 0; p < RAND(30,70); p++) {
			// Add the explosion flames
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.01f, 0.01f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.01f, 0.01f);
			float c1[4] = { 1, 0.7f, 0.3f, 1 };
			float c2[4] = { 1, 0, 0, 0 };
			add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo);
		}
		for(p = 0; p < RAND(10,40); p++) {
			// Add the sparks
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.05f, 0.05f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.05f, 0.05f);
			float c1[4] = { 1, 0.7f, 0.3f, 1 };
			float c2[4] = { 0, 0, 1, 0 };
			add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark);
		}
	}

	else if(type == EXP_BOMB_CENTER_FLOWER) {
		for(p = 0; p < RAND(20,30); p++) {
			// Add the explosion flames
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.01f, 0.01f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.01f, 0.01f);
			float c1[4] = { 0.3f, 1, 0.3f, 1 };
			float c2[4] = { .5f, 0, 1, 0 };
			add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo);
		}
		for(p = 0; p < RAND(1,5); p++) {
			// Add the flowers
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.05f, 0.05f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.05f, 0.05f);
			float c1[4] = { 1, 1, 1, 1 };
			float c2[4] = { 1, 1, 1, 0 };
			add_particle(pos, dir, RAND(50,100), 0.5f, 0.1f, c1, c2, part_flower, true);
		}
	}

	else if(type == EXP_NAPALM) {
		for(p = 0; p < RAND(20,50); p++) {
			// Add the explosion flames
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.01f, 0.01f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.01f, 0.01f);
			float c1[4] = { 1, 0.3f, 0.2f, 1 };
			float c2[4] = { 1, 0, 0, 0 };
			add_particle(pos, dir, RAND(10,60), 0.2f, 0.8f, c1, c2, part_explo);
		}
		for(p = 0; p < RAND(10,30); p++) {
			// Add the sparks
			VECT pos(x + 0.5f, 0.0f, y + 0.5f);
			VECT dir;
			dir.x = RANDF(-0.05f, 0.05f);
			dir.y = RANDF(0.0f, 0.1f);
			dir.z = RANDF(-0.05f, 0.05f);
			float c1[4] = { 1, 0.7f, 0.3f, 1 };
			float c2[4] = { 0, 0, 1, 0 };
			add_particle(pos, dir, RAND(20,70), 0.05f, 0.01f, c1, c2, part_spark);
		}
	}
}
Пример #8
0
// Helper function for the lightning effect.
// Creates an recursive lightning bolt
void light_bolt(VECT pos1, VECT pos2, int points, float noise, float thickness, int level, float color[4]) {
	if(level > 6)
		return;			// Don't recurse too deeply

	// Create the points array
	VECT *point = new VECT[points];
	if(!point)
		return;

	// Define the end points
	point[0] = pos1;
	point[points-1] = pos2;

	// Compute the direction from pos1 to pos2
	VECT dir = pos2 - pos1;
	float dist = vector_length(dir);
	float step = dist / points;
	normalize(dir);

	// Make a straight line between pos1 and pos2, and randomize it a bit
	for(int f=1; f < points-1; f++) {
		point[f] = point[f-1] + step * dir;

		point[f].x += RANDF(-noise, noise);
		point[f].y += RANDF(-noise, noise);
		point[f].z += RANDF(-noise, noise);

		// Create some recursive bolts
		if(RAND(0,100) > 45) {
			// Choose a destination which isn't too close to the original point
			VECT dest;
			dest.x = RANDF(-noise,noise);
			dest.y = RANDF(-noise,noise);
			dest.z = RANDF(-noise,noise);
			bool ok = false;
			while(!ok) {
				float bdist = vector_length(VECT(dest - point[f]));
				float rad = noise * 0.5f;
				if(bdist > rad) {
					// Also try to steer the bolts towards the ground
					if((point[f].y + dest.y) < point[f].y)
						ok = true;
					else
						ok = false;
				}
				if(!ok) {
					dest.x = RANDF(-noise,noise);
					dest.y = RANDF(-noise,noise);
					dest.z = RANDF(-noise,noise);
				}
			}

			dest *= RANDF(3.0f, 7.0f);
			light_bolt(point[f], point[f] + dest, int(points * 0.65f), noise * 0.5f, thickness * 0.5f, level + 1, color);
		}
	}

	glColor4fv(color);
	glLineWidth(thickness);
	glBegin(GL_LINE_STRIP);
	for(int f=0; f<points; f++) {
	//for(int f=0; f<points-1; f++) {
		glVertex3f(point[f].x, point[f].y, point[f].z);
		//glVertex3f(point[f+1].x, point[f+1].y, point[f+1].z);
	}
	glEnd();

	// Draw some glows
	if(level == 0) {
		BIND_TEXTURE(part_glow);
		glColor4f(.4f, .8f, 1, RANDF(.15f,.25f));
		for(int f=0; f<points; f++) {
			glPushMatrix();
			glTranslatef(point[f].x, point[f].y, point[f].z);
			// Negate the camera rotation
			glRotatef(45.0f, 0,1,0);
			glRotatef(-30.0f, 1,0,0);
			glBegin(GL_TRIANGLE_STRIP);
				glTexCoord2f(1,1); glVertex3f( 1,  1,  1);
				glTexCoord2f(0,1); glVertex3f(-1,  1,  1);
				glTexCoord2f(1,0); glVertex3f( 1, -1, -1);
				glTexCoord2f(0,0); glVertex3f(-1, -1, -1);
			glEnd();
			glPopMatrix();
		}
		BIND_TEXTURE(0);
	}

	delete [] point;
}
Пример #9
0
// Show a menu. Returns the action taken.
int show_menu(int menu_id) {
	// Initialize
	int action = 0;
	int menu_item = MENU_START;
	back_anim = 0.0f;
	bx_roll = RANDF(0,1);
	by_roll = RANDF(0,1);
	bx_roll_dir = RANDF(-0.001f,0.001f);
	by_roll_dir = RANDF(-0.001f,0.001f);
	mid_fade_amount = 0.0f;
	mid_fade_dir = 1;
	mid_state = 1;
	mid_state_wait = WAIT_BEFORE_FADE_IN * FADE_WAIT_FACTOR;
	memset(key, 0, sizeof(key));
	setting_key = false;
	key_to_set = NULL;
	whose_keys = 0;
	prev_key = 0;

	// Load the hiscores
	hiscore_1.load(get_hiscore_location(1));
	hiscore_2.load(get_hiscore_location(2));

	// Fade in
	fading = 1;
	fade_amount = 1.0f;

	SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);


	// Menu loop
	bool menu_loop = true;
	timer_count = 0;
	while(menu_loop) {
		// Handle events
		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
				case SDL_QUIT:		// Quit
					menu_loop = false;
					action = MENU_EXIT;
					break;

				case SDL_KEYDOWN:
					// Update the 'key' array
					if(setting_key == false)
						key[event.key.keysym.sym] = 1;
					// Set the key if it's not ESC, F12, F1
					else if(setting_key == true && event.key.keysym.sym != SDLK_ESCAPE && event.key.keysym.sym != SDLK_F12 && event.key.keysym.sym != SDLK_F1) {
						(*key_to_set) = event.key.keysym.sym;
						setting_key = false;
					}
					// ESC pressed -> cancel the key setting
					else if(setting_key == true && event.key.keysym.sym == SDLK_ESCAPE) {
						(*key_to_set) = prev_key;
						setting_key = false;
					}
					break;

				case SDL_KEYUP:
					// Update the 'key' array
					key[event.key.keysym.sym] = 0;
					break;
			}
		}

		while(timer_count > 0) {
			// Fade
			if(fading) {
				if(fading == 1) {
					// Fade in
					fade_amount -= 0.015f;
					if(fade_amount <= 0.0f) {
						fading = 0;
						fade_amount = 0.0f;
					}
				}
				else if(fading == 2) {
					// Fade out
					fade_amount += 0.015f;
					if(fade_amount >= 1.0f) {
						fading = 0;
						fade_amount = 1.0f;
						menu_loop = false;
					}
				}
			}

			// Take a screenshot?
			if(key[SDLK_F12])
				save_screenshot();

			// Handle the cursor movement
			if(key[SDLK_UP] || (key[SDLK_LEFT] && menu_item != MENU_MUSICVOL && menu_item != MENU_SOUNDVOL)) {
				play_sound(SND_MENU1, false);
				menu_item--;
				if(menu_id == MENU_ID_MAIN) {
					if(menu_item < MENU_START)
						menu_item = MENU_EXIT;
				}
				else if(menu_id == MENU_ID_START) {
					if(menu_item < MENU_SINGLEPLAY)
						menu_item = MENU_MULTIPLAY;
				}
				else if(menu_id == MENU_ID_OPTIONS) {
					if(menu_item < MENU_WHOSEKEYS)
						menu_item = MENU_CANCEL;
				}
			}

			if(key[SDLK_DOWN] || (key[SDLK_RIGHT] && menu_item != MENU_MUSICVOL && menu_item != MENU_SOUNDVOL)) {
				play_sound(SND_MENU1, false);
				menu_item++;
				if(menu_id == MENU_ID_MAIN) {
					if(menu_item > MENU_EXIT)
						menu_item = MENU_START;
				}
				else if(menu_id == MENU_ID_START) {
					if(menu_item > MENU_MULTIPLAY)
						menu_item = MENU_SINGLEPLAY;
				}
				else if(menu_id == MENU_ID_OPTIONS) {
					if(menu_item > MENU_CANCEL)
						menu_item = MENU_WHOSEKEYS;
				}
			}

			// Handle the ESC pressings
			if(key[SDLK_ESCAPE]) {
				play_sound(SND_MENU2, false);
				// In the main menu -> exit, otherwise return to the main menu
				if(menu_id == MENU_ID_MAIN) {
					action = MENU_EXIT;
					fading = 2;		// Fade out
				}
				if(menu_id == MENU_ID_START) {
					menu_id = MENU_ID_MAIN;
					menu_item = MENU_START;
				}
				if(menu_id == MENU_ID_OPTIONS) {
					menu_id = MENU_ID_MAIN;
					menu_item = MENU_OPTIONS;

					mid_fade_amount = 0.0f;
					mid_fade_dir = 1;
					mid_state = 1;
					mid_state_wait = WAIT_BEFORE_FADE_IN * FADE_WAIT_FACTOR;

					// Restore the settings
					load_config(get_config_location(), &config);
					Mix_Volume(-1,config.sound_vol);
					Mix_VolumeMusic(config.music_vol);
				}
			}

			// Handle the item selection
			if(key[SDLK_RETURN] || key[SDLK_KP_ENTER] || key[SDLK_SPACE]) {
				play_sound(SND_MENU2, false);
				switch(menu_item) {
					// MAIN MENU items
					case MENU_START:			// Start menu
						menu_id = MENU_ID_START;
						menu_item = MENU_SINGLEPLAY;
						break;
					case MENU_OPTIONS:			// Options menu
						menu_id = MENU_ID_OPTIONS;
						menu_item = MENU_WHOSEKEYS;
						break;
					case MENU_EXIT:				// Exit the game
						action = MENU_EXIT;
						fading = 2;				// Fade out
						break;

					// START MENU items
					case MENU_SINGLEPLAY:		// Start a single player game
						action = MENU_SINGLEPLAY;
						fading = 2;				// Fade out;
						break;
					case MENU_MULTIPLAY:		// Start a two player game
						action = MENU_MULTIPLAY;
						fading = 2;				// Fade out
						break;

					// OPTIONS MENU items
					case MENU_WHOSEKEYS:		// Toggle the player whose keys we're setting
						if(whose_keys == 0)
							whose_keys = 1;
						else if(whose_keys == 1)
							whose_keys = 0;
						break;
					case MENU_MOVSTYLE:			// Toggle the moving style
						if(config.moving_style[whose_keys] == 1)
							config.moving_style[whose_keys] = 2;
						else if(config.moving_style[whose_keys] == 2)
							config.moving_style[whose_keys] = 1;
						break;
					case MENU_KEYUP:			// Set the key up
						key_to_set = &(config.key_up[whose_keys]);
						setting_key = true;
						prev_key = config.key_up[whose_keys];
						config.key_up[whose_keys] = -1;
						break;

					case MENU_KEYDOWN:			// Set the key down
						key_to_set = &(config.key_down[whose_keys]);
						setting_key = true;
						prev_key = config.key_down[whose_keys];
						config.key_down[whose_keys] = -1;
						break;

					case MENU_KEYLEFT:			// Set the key left
						key_to_set = &(config.key_left[whose_keys]);
						setting_key = true;
						prev_key = config.key_left[whose_keys];
						config.key_left[whose_keys] = -1;
						break;

					case MENU_KEYRIGHT:			// Set the key right
						key_to_set = &(config.key_right[whose_keys]);
						setting_key = true;
						prev_key = config.key_right[whose_keys];
						config.key_right[whose_keys] = -1;
						break;

					case MENU_KEYBOMB:			// Set the key bomb
						key_to_set = &(config.key_shoot[whose_keys]);
						setting_key = true;
						prev_key = config.key_shoot[whose_keys];
						config.key_shoot[whose_keys] = -1;
						break;

					case MENU_KEYSPECIAL:		// Set the key special
						key_to_set = &(config.key_special[whose_keys]);
						setting_key = true;
						prev_key = config.key_special[whose_keys];
						config.key_special[whose_keys] = -1;
						break;

					case MENU_PERSPECTIVE:		// Toggle the perspective mode
						config.perspective_mode = !config.perspective_mode;
						break;

					case MENU_OK:				// Save the changes
						menu_id = MENU_ID_MAIN;
						menu_item = MENU_OPTIONS;

						mid_fade_amount = 0.0f;
						mid_fade_dir = 1;
						mid_state = 1;
						mid_state_wait = WAIT_BEFORE_FADE_IN * FADE_WAIT_FACTOR;

						save_config(get_config_location(true), &config);
						break;

					case MENU_CANCEL:			// Cancel the changes
						menu_id = MENU_ID_MAIN;
						menu_item = MENU_OPTIONS;

						mid_fade_amount = 0.0f;
						mid_fade_dir = 1;
						mid_state = 1;
						mid_state_wait = WAIT_BEFORE_FADE_IN * FADE_WAIT_FACTOR;

						// Restore the settings
						load_config(get_config_location(), &config);
						Mix_Volume(-1,config.sound_vol);
						Mix_VolumeMusic(config.music_vol);
				}
			}

			// Check the volume level sliders
			if(menu_item == MENU_MUSICVOL) {
				if(key[SDLK_LEFT]) {
					config.music_vol -= 10;
					if(config.music_vol < 0)
						config.music_vol = 0;
					// Update the volume levels
					Mix_VolumeMusic(config.music_vol);
				}
				if(key[SDLK_RIGHT]) {
					config.music_vol += 10;
					if(config.music_vol > 255)
						config.music_vol = 255;
					// Update the volume levels
					Mix_VolumeMusic(config.music_vol);
				}
			}
			if(menu_item == MENU_SOUNDVOL) {
				if(key[SDLK_LEFT]) {
					config.sound_vol -= 10;
					if(config.sound_vol < 0)
						config.sound_vol = 0;
					// Update the volume levels
					Mix_Volume(-1,config.sound_vol);
					play_sound(SND_MENU1, false);
				}
				if(key[SDLK_RIGHT]) {
					config.sound_vol += 10;
					if(config.sound_vol > 255)
						config.sound_vol = 255;
					// Update the volume levels
					Mix_Volume(-1,config.sound_vol);
					play_sound(SND_MENU1, false);
				}
			}


			// Clear the key array
			memset(key, 0, sizeof(key));

			// Animate the background
			back_anim = add_angle(back_anim, 2.0f);
			bx_roll += bx_roll_dir;
			if(bx_roll > 1.0f)
				bx_roll -= 1.0f;
			else if(bx_roll < 0.0f)
				bx_roll += 1.0f;

			by_roll += by_roll_dir;
			if(by_roll > 1.0f)
				by_roll -= 1.0f;
			else if(by_roll < 0.0f)
				by_roll += 1.0f;

			// Handle the hiscores/credits
			if(menu_id == MENU_ID_MAIN || menu_id == MENU_ID_START) {
				if(mid_state_wait > 0)
					mid_state_wait--;
				else if(mid_state_wait == 0) {
					// Fade either in or out
					if(mid_fade_dir == 1) {
						if(mid_fade_amount < 1.0f)
							mid_fade_amount += FADE_STEP;
						if(mid_fade_amount >= 1.0f) {
							// Wait a bit before fading out
							mid_fade_dir = 2;
							mid_state_wait = WAIT_BEFORE_FADE_OUT * FADE_WAIT_FACTOR;
						}
					}
					else if(mid_fade_dir == 2) {
						if(mid_fade_amount > 0.0f)
							mid_fade_amount -= FADE_STEP;
						if(mid_fade_amount <= 0.0f) {
							// Wait a bit before changing the state and fading in
							mid_fade_dir = 1;
							mid_state_wait = WAIT_BEFORE_FADE_IN * FADE_WAIT_FACTOR;
							mid_state++;
							if(mid_state > 3)
								mid_state = 1;
						}
					}
				}
			}

			timer_count--;
		}


		// Draw the menu
		draw_menu(menu_id, menu_item, -1, fade_amount, NULL);

		// Flush and swap the buffers
		glFlush();
		SDL_GL_SwapBuffers();

	}

	SDL_EnableKeyRepeat(0,0);
	return action;
}
Пример #10
0
// Move the player
void PLAYER::move() {
#ifndef EDITOR
	int who = (this == &p1) ? 1 : 2;
	int who2 = who-1; 	// Used for array indices

	// Reduce the icon alpha
	if(p_icon_alpha[who2]) {
		p_icon_alpha[who2] -= 0.005f;
		if(p_icon_alpha[who2] < 0.0f)
			p_icon_alpha[who2] = 0.0f;
	}

	// If we're dead, reduce the death counter and respawn
	if(!alive) {
		death_counter--;
		if(death_counter == 0) {
			// Respawn to a block
			int ox, oy;
			get_respawn_position((int)get_real_x(), (int)get_real_y(), ox, oy);

			int odir = dir;
			//clear();
			alive = true;
			x = ox;
			y = oy;
			dir = odir;
			nextdir = dir;
			tx = x;
			ty = y;
			walking = false;
			jumping = false;
			dying = false;
			offset = 0.0f;
			create_teleport_effect(x, y);
			show_icon(who2);

			// Play the appear sound
			play_sound(SND_APPEAR, false);

		}
		return;
	}

	// Advance the dying animation if we're actually dying
	if(dying) {
		die_anim -= 0.03f;

		// Create the blue "burning down" effect
		float px = get_real_x();
		float py = get_real_y();
		for(int f=0; f < RAND(2,10); f++) {
			float rnd = RANDF(-0.3f, 0.3f);
			VECT pos(px, 2*size - 0.05f - (2.5f*size*(1-die_anim)), py);
			pos.x += rnd;
			pos.z -= rnd;
			if(pos.y < 0.0f)
				pos.y = 0.0f;
			VECT dir = 0.0f;
			float c1[4] = { 0.1f, 0.7f, 1, 1 };
			float c2[4] = { 0.1f, 0.7f, 1, 0 };
			add_particle(pos, dir, RAND(20,35), 0.1f, 0.4f, c1, c2, part_star);
		}

		if(die_anim < 0.0f) {
			die_anim = 0.0f;
			alive = false;

			// Explode the player bombs
			if(num_bombs > 0) {
				list<BOMB>::iterator b;
				for(b = bomblist.begin(); b != bomblist.end(); ++b)
					if((*b).owner == who && (*b).time > 1)
						(*b).time = 1;		// Makes the bomb explode on the next cycle
			}
		}

		return;
	}


	// Jumping stuff
	if(jumping) {
		jump_pos += jump_speed;
		if(jump_pos >= 1.0f) {
			jump_pos = 1.0f;

			// We're now on the target tile
			x = jump_tx;
			y = jump_ty;
			tx = x;
			ty = y;
			offset = 0.0f;
			jumping = false;
		}

		// Create some particles if we're teleporting
		if(in_teleport && jumping) {
			VECT pos(get_real_x(), 0.25f, get_real_y());
			pos += jump_dir * jump_pos * jump_dist;
			pos.y += jump_height * SIN(180.0f * jump_pos);

			VECT dir;
			for(int f=0; f<5; f++) {
				VECT ppos = pos + VECT(RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f),RANDF(-0.5f,0.5f));
				dir.x = dir.y = dir.z = 0.0f;
				float c1[4] = { 0.3, 0.7f, 1, 1 };
				float c2[4] = { 0, 0, 1, 0 };

				add_particle(ppos, dir, RAND(10,30), 0.1f, 0.3f, c1, c2, part_teleport);
			}
		}


		// This is a dirty hack. Read the comments from the beginning of this file.
		if(map[jump_tx][jump_ty][1] && jump_pos > 0.9f) {
			players_on_block_x[who2] = jump_tx;
			players_on_block_y[who2] = jump_ty;
		}

		return;
	}

	// This is a dirty hack. Read the comments from the beginning of this file.
	if(map[x][y][1]) {
		players_on_block_x[who2] = x;
		players_on_block_y[who2] = y;
		//return;
	}
	else {
		players_on_block_x[who2] = -1;
	}

	// Don't move if we're using the napalm or the teleport power
	if(using_special_power && (which_special_power == RED_POWER_NAPALM))
		return;
	if(using_special_power == who && (which_special_power == BLUE_POWER_TELEPORT))
		return;

	// Don't move if the level is finished
	if(level_pause)
		return;


	// Advance the animation
	anim += 0.20f;
	if((int)anim > 3)
		anim = 0.0f;

	// Advance the turning animation
	if(turning) {
		turning_counter++;
		if(turning_counter == 5) {
			dir = nextdir;
			nextdir = dir + 1;
			if(nextdir > DIR_W)
				nextdir = DIR_N;
		}
		else if(turning_counter == 10) {
			dir = nextdir;
			turning = false;
		}
	}


	if(!walking && ((config.moving_style[who2] == MOV_RELATIVE && !key[config.key_up[who2]]) || (config.moving_style[who2] == MOV_ABSOLUTE && !key[config.key_up[who2]] && !key[config.key_down[who2]] && !key[config.key_left[who2]] && !key[config.key_right[who2]])))
		anim = 0.0f;

	// Check if we're on a block
	bool on_block = false;
	if(map_solid(x,y))
		on_block = true;

	// Don't move if we're using the flower power (absolute)
	if(on_block && config.moving_style[who2] == MOV_ABSOLUTE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0))
		return;


	// Check for turning input
	if(key[config.key_left[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[0] && !turning) {
				// Turn left
				nextdir = dir - 1;
				if(nextdir < DIR_N)
					nextdir = DIR_W;

				if(!walking)
					dir = nextdir;

				turn_key_down[0] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_W;
			walking = true;
			offset = 0.0f;

			tx = x - 1;
			ty = y;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[0] = false;

	if(key[config.key_right[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[1] && !turning) {
				// Turn right
				nextdir = dir + 1;
				if(nextdir > DIR_W)
					nextdir = DIR_N;

				if(!walking)
					dir = nextdir;

				turn_key_down[1] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_E;
			walking = true;
			offset = 0.0f;

			tx = x + 1;
			ty = y;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[1] = false;

	// Check for 180 degree turning
	if(key[config.key_down[who2]]) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			if(!turn_key_down[2] && !turning && !walking && !key[config.key_up[who2]]) {
				nextdir = dir + 1;
				if(nextdir > DIR_W)
					nextdir = DIR_N;
				turning = true;
				turning_counter = 0;

				turn_key_down[2] = true;
			}
		}
		else if(config.moving_style[who2] == MOV_ABSOLUTE && !walking) {
			// Absolute moving
			dir = DIR_S;
			walking = true;
			offset = 0.0f;

			tx = x;
			ty = y + 1;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}
	else
		turn_key_down[2] = false;

	// Don't move if we're using the flower power (relative)
	if(on_block && config.moving_style[who2] == MOV_RELATIVE && (p1.num_flower_bombs > 0 || p2.num_flower_bombs > 0))
		return;

	// Check for walking input
	if(key[config.key_up[who2]] && !walking && !turning) {
		if(config.moving_style[who2] == MOV_RELATIVE) {
			// Relative moving
			walking = true;
			offset = 0.0f;

			dir = nextdir;

			switch(dir) {
				default:
				case DIR_N: tx = x; ty = y - 1; break;
				case DIR_E: tx = x + 1; ty = y; break;
				case DIR_S: tx = x; ty = y + 1; break;
				case DIR_W: tx = x - 1; ty = y; break;
			}

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
		else {
			// Absolute moving
			dir = DIR_N;
			walking = true;
			offset = 0.0f;

			tx = x;
			ty = y - 1;

			// Check if the target is passable?
			if(map_solid(tx, ty)) {
				tx = x;
				ty = y;
				walking = false;
			}

			if(on_block) {
				// We're on a block, jump down from it
				jump(tx, ty, 2.0f, 0.05f);
				tx = x;
				ty = y;
				anim = 0;
				on_block = true;

				// Play the jumping sound
				if(jumping)
					play_sound(SND_JUMP, false);
			}
		}
	}


	// Move towards the target tile
	if(offset < 1.0f && (tx != x || ty != y)) {
		offset += 0.1f;

		// If we're reached the target tile, move again
		if(offset >= 1.0f) {
			x = tx;
			y = ty;
			offset = 0.0f;
			walking = false;

			in_teleport = 0;
		}
	}

	// Reload the weapons
	if(reload > 0)
		reload--;

	// Dropping bombs
	if(key[config.key_shoot[who2]] && reload == 0 && num_bombs < 3 && !on_block && !icon_menu.wait) {
		reload = 30;

		// Plant the bomb
		add_bomb(x, y, BTYP_NORMAL, who);
		num_bombs++;

		// Play the sound
		play_sound(SND_BOMB, false);
	}


	// Invoke the special powers
	if(key[config.key_special[who2]]) {
		open_icon_menu(who, on_block);
		show_icon(0);
		show_icon(1);
	}

#endif
}