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(); }
// 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); } } }
// 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); }
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*) ¶m_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); }
// 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; } } }
// 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); } }
// 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); } } }
// 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; }
// 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; }
// 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 }