#include "gravityball.h" #include "deathball.h" #include #include GravityBall::GravityBall(FMOD::System* sound_sys, const char* fname, DeathBall* death_ball, int hit_points) { _audio_loop = new AudioLoop(sound_sys); _audio_loop->load_file(fname); _audio_loop->play(); _pos.x = 2 - 4 * float(rand()) / RAND_MAX; _pos.y = 0; _pos.z = 10 + 3 * float(rand()) / RAND_MAX; _type = Actor::gravityball; _sphere = new STShape("content/models/gravity_ball.obj");//STShapes::CreateSphere(1, STPoint3::Origin, 16, 16); _shatter_amount = 0; _shake_amount = 0; _sig_vol = 0; _is_dead = false; _is_exploding = false; _max_hit_points = _hit_points = hit_points; _death_ball = death_ball; string sound = "content/audio/shatter0.wav"; sound[21] = '0' + char(rand()%10); _shatter_loop = new AudioLoop(sound_sys); _shatter_loop->load_file(sound.c_str()); update(0); } GravityBall::~GravityBall() { delete(_sphere); delete(_audio_loop); delete(_shatter_loop); } void GravityBall::update(double tick_time) { _audio_loop->set_3D(_pos, STVector3::Zero); _shatter_loop->set_3D(_pos, STVector3::Zero); for (int i = -tick_time * SAMPLE_RATE; i < 0; i++) { _sig_vol = _sig_vol * .9999 + abs(_audio_loop->get_sample(i))/double(MAX_SAMPLE_VALUE) * .0001; } double d = (_pos - _death_ball->_pos).Length(); double mult = min(1.0, 20 * 1/d); _audio_loop->_volume = max(0.0, 1 - _shatter_amount) * mult; _shatter_loop->_volume = max(0.0, 1 - _shatter_amount) * mult; if (_shatter_amount > 2) { _is_dead = true; } if (_is_exploding) { shatter(tick_time); } } static void set_material() { GLfloat material_Ka[] = {0.0f, 0.2f, 0.4f, 1.0f}; GLfloat material_Kd[] = {0.4f, 0.4f, 0.5f, 1.0f}; GLfloat material_Ks[] = {0.0f, 1.0f, 1.0f, 1.0f}; ALPHA_HACK(1); GLfloat material_Se = 20.0f; glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, material_Ka); glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, material_Kd); glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, material_Ks); glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, material_Se); } void GravityBall::render(double tick_time) { if (_is_dead) return; set_material(); glPushMatrix(); glTranslatef(_pos.x, _pos.y, _pos.z); glScalef(3*_sig_vol + .1, 3*_sig_vol + .1, 3*_sig_vol + .1); ALPHA_HACK(1 - _shatter_amount); if (_shake_amount > 0) { STShape new_sphere = *_sphere; for (unsigned k = 0; k < new_sphere.GetNumFaces(); k++) { STShape::Face face = new_sphere.GetFace(k); STShape::Index i0 = face.GetIndex(0); STShape::Index i1 = face.GetIndex(1); STShape::Index i2 = face.GetIndex(2); STShape::Vertex v0 = new_sphere.GetVertex(i0); STShape::Vertex v1 = new_sphere.GetVertex(i1); STShape::Vertex v2 = new_sphere.GetVertex(i2); v0.position += _shake_amount * (.5 - rand() / double(RAND_MAX)) * v0.normal; v1.position += _shake_amount * (.5 - rand() / double(RAND_MAX)) * v1.normal; v2.position += _shake_amount * (.5 - rand() / double(RAND_MAX)) * v2.normal; new_sphere.SetVertex(i0, v0); new_sphere.SetVertex(i1, v1); new_sphere.SetVertex(i2, v2); } new_sphere.Draw(); } else { _sphere->Draw(); } ALPHA_HACK(1); glPopMatrix(); } void GravityBall::explode() { _is_exploding = true; _shatter_loop->play(); } void GravityBall::corrupt() { _hit_points--; if(_hit_points < 1) explode(); switch (rand()%3) { case 0: _audio_loop->glitch(); break; case 1: _audio_loop->stutter(); break; case 2: _audio_loop->scramble(); break; } _shake_amount = (1 - (double(_hit_points) / _max_hit_points)); } void GravityBall::shatter(double amount) { _shatter_amount += amount*2; amount = _shatter_amount; for (unsigned k = 0; k < _sphere->GetNumFaces(); k++) { STShape::Face face = _sphere->GetFace(k); STShape::Index i0 = face.GetIndex(0); STShape::Index i1 = face.GetIndex(1); STShape::Index i2 = face.GetIndex(2); STShape::Vertex v0 = _sphere->GetVertex(i0); STShape::Vertex v1 = _sphere->GetVertex(i1); STShape::Vertex v2 = _sphere->GetVertex(i2); v0.position += amount * (1 + rand() / double(RAND_MAX)) * v0.normal; v1.position += amount * (1 + rand() / double(RAND_MAX)) * v1.normal; v2.position += amount * (1 + rand() / double(RAND_MAX)) * v2.normal; _sphere->SetVertex(i0, v0); _sphere->SetVertex(i1, v1); _sphere->SetVertex(i2, v2); } }