void Framework::update(){ if ( !gStage ){ gPrimitiveRenderer = Scene::PrimitiveRenderer::create( 1000, 100 ); Pad::create(); gRobo[ 0 ] = new Robo( 0 ); gRobo[ 1 ] = new Robo( 1 ); gRobo[ 0 ]->setPosition( Vector3( 0.0, 0.0, 50.0 ) ); gRobo[ 0 ]->setAngleY( 180.0 ); gStage = new Stage(); gPlaying = true; } if ( gPlaying ){ gRobo[ 0 ]->update( gRobo[ 1 ] ); gRobo[ 1 ]->update( gRobo[ 0 ] ); ++gTime; } //0番ロボからカメラ行列ゲット Matrix44 pvm; pvm.setPerspectiveTransform( 45.f, static_cast< float >( width() ), static_cast< float >( height() ), 1.f, 10000.f ); Matrix34 vm; Vector3 eyePosition; gRobo[ 0 ]->getView( &vm, &eyePosition ); //ビュー行列はロボに作ってもらう pvm *= vm; //描画 //グローバルなライティング設定 Graphics::Manager gm = Graphics::Manager::instance(); gm.setProjectionViewMatrix( pvm ); gm.setEyePosition( eyePosition ); gm.setLightingMode( Graphics::LIGHTING_PER_PIXEL ); gm.setAmbientColor( gAmbient ); gm.setLightColor( 0, Vector3( 0.7f, 0.4f, 0.2f ) ); gm.enableDepthTest( true ); gm.enableDepthWrite( true ); Vector3 lightPos[ 4 ]; lightPos[ 0 ].set( 100000.f, 100000.f, 100000.f ); float lightIntensities[ 4 ]; lightIntensities[ 0 ] = lightPos[ 0 ].length(); //長さを強度にすれば、だいたいその距離で1になる //残り三つのライトは弾のところに置こうか。 //カメラに近い順に3つ選ぼう。 float nearestDistance[ 3 ]; int nearestIndex[ 3 ]; for ( int i = 0; i < 3; ++i ){ nearestDistance[ i ] = numeric_limits< float >::max(); nearestIndex[ i ] = -1; } //距離を測りながら最小を三つ取得 //100はロボあたりの弾の数の最大数。 for ( int i = 0; i < 2; ++i ){ for ( int j = 0; j < 100; ++j ){ const Vector3* p = gRobo[ i ]->getBulletPosition( j ); if ( p ){ Vector3 t; t.setSub( *p, eyePosition ); float d = t.squareLength(); if ( d < nearestDistance[ 0 ] ){ nearestDistance[ 2 ] = nearestDistance[ 1 ]; nearestDistance[ 1 ] = nearestDistance[ 0 ]; nearestDistance[ 0 ] = d; nearestIndex[ 2 ] = nearestIndex[ 1 ]; nearestIndex[ 1 ] = nearestIndex[ 0 ]; nearestIndex[ 0 ] = i * 100 + j; }else if ( d < nearestDistance[ 1 ] ){ nearestDistance[ 2 ] = nearestDistance[ 1 ]; nearestDistance[ 1 ] = d; nearestIndex[ 2 ] = nearestIndex[ 1 ]; nearestIndex[ 1 ] = i * 100 + j; }else if ( d < nearestDistance[ 2 ] ){ nearestDistance[ 2 ] = d; nearestIndex[ 2 ] = i * 100 + j; } } } } for ( int i = 0; i < 3; ++i ){ if ( nearestIndex[ i ] != -1 ){ int robo = nearestIndex[ i ] / 100; int bullet = nearestIndex[ i ] % 100; const Vector3* p = gRobo[ robo ]->getBulletPosition( bullet ); lightPos[ i + 1 ] = *p; if ( robo == 1 ){ gm.setLightColor( i + 1, Vector3( 1.f, 0.2f, 0.4f ) ); }else{ gm.setLightColor( i + 1, Vector3( 0.2f, 0.4f, 1.f ) ); } lightIntensities[ i + 1 ] = 10.f; }else{ lightIntensities[ i + 1 ] = 0.f; } } gm.setCullMode( Graphics::CULL_BACK ); //ライト設定 for ( int i = 0; i < 4; ++i ){ gm.setLightPosition( i, lightPos[ i ] ); gm.setLightIntensity( i, lightIntensities[ i ] ); } gStage->draw(); gRobo[ 0 ]->draw(); gRobo[ 1 ]->draw(); //以下フロントエンド描画 //モデル描x画でいじられたものを元に戻す gm.setDiffuseColor( Vector3( 1.f, 1.f, 1.f ) ); gm.setTransparency( 1.f ); gm.setLightingMode( Graphics::LIGHTING_NONE ); //必要な情報を抜いて int hp0 = gRobo[ 0 ]->getHitPoint(); int hp1 = gRobo[ 1 ]->getHitPoint(); int e0 = gRobo[ 0 ]->getEnergy(); bool lockOn0 = gRobo[ 0 ]->getLockOn(); //Zテスト無用。アルファブレンドON gPrimitiveRenderer.enableDepthTest( false ); gPrimitiveRenderer.enableDepthWrite( false ); gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); Vector2 p[ 4 ]; unsigned c1; unsigned c2; //体力バー背景 p[ 0 ].set( -0.9f, 0.95f ); p[ 1 ].set( -0.9f, 0.87f ); p[ 2 ].set( 0.1f, 0.95f ); p[ 3 ].set( 0.1f, 0.87f ); c1 = c2 = 0xff406080; drawRect( p, c1, c2 ); p[ 0 ].set( -0.9f, 0.85f ); p[ 1 ].set( -0.9f, 0.82f ); p[ 2 ].set( 0.1f, 0.85f ); p[ 3 ].set( 0.1f, 0.82f ); c1 = c2 = 0xff806040; drawRect( p, c1, c2 ); //体力バー本体 float length = static_cast< float >( hp0 ) / static_cast< float >( Robo::mMaxHitPoint ); p[ 0 ].set( -0.9f, 0.95f ); p[ 1 ].set( -0.9f, 0.87f ); p[ 2 ].set( -0.9f + length, 0.95f ); p[ 3 ].set( -0.9f + length, 0.87f ); c1 = 0xff882244; c2 = 0xff88ccff; drawRect( p, c1, c2 ); length = static_cast< float >( hp1 ) / static_cast< float >( Robo::mMaxHitPoint ); p[ 0 ].set( -0.9f, 0.85f ); p[ 1 ].set( -0.9f, 0.82f ); p[ 2 ].set( -0.9f + length, 0.85f ); p[ 3 ].set( -0.9f + length, 0.82f ); c1 = 0xffff4422; c2 = 0xffffcc88; drawRect( p, c1, c2 ); //武器エネルギー //背景 p[ 0 ].set( -0.1f, -0.7f ); p[ 1 ].set( -0.1f, -0.8f ); p[ 2 ].set( 0.1f, -0.7f ); p[ 3 ].set( 0.1f, -0.8f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); //本体 gPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算にしてみようかな length = 0.2f * static_cast< float >( e0 ) / static_cast< float >( Robo::mMaxEnergy ); p[ 0 ].set( -0.1f, -0.7f ); p[ 1 ].set( -0.1f, -0.8f ); p[ 2 ].set( -0.1f + length, -0.7f ); p[ 3 ].set( -0.1f + length, -0.8f ); c1 = 0x80ff0000; c2 = 0x80ffff00; drawRect( p, c1, c2 ); //レーダー gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //背景 p[ 0 ].set( 0.7f, 0.7f ); p[ 1 ].set( 0.7f, 0.9f ); p[ 2 ].set( 0.9f, 0.7f ); p[ 3 ].set( 0.9f, 0.9f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); gPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算にしてみようか //自分 Vector2 t; t.set( gRobo[ 0 ]->position()->x, gRobo[ 0 ]->position()->z ); //x.z t *= 0.002f; //+-50のステージを0.2の大きさに縮小するんだから、0.2/100で0.002 t += Vector2( 0.8f, 0.8f ); //(0.8,0.8)が中心なのだから、それを足す p[ 0 ].set( t.x - 0.005f, t.y - 0.005f ); p[ 1 ].set( t.x - 0.005f, t.y + 0.005f ); p[ 2 ].set( t.x + 0.005f, t.y - 0.005f ); p[ 3 ].set( t.x + 0.005f, t.y + 0.005f ); c1 = c2 = 0xcc0080ff; drawRect( p, c1, c2 ); //敵 t.set( gRobo[ 1 ]->position()->x, gRobo[ 1 ]->position()->z ); //x.z t *= 0.002f; //+-50のステージを0.2の大きさに縮小するんだから、0.2/100で0.002 t += Vector2( 0.8f, 0.8f ); //(0.8,0.8)が中心なのだから、それを足す p[ 0 ].set( t.x - 0.005f, t.y - 0.005f ); p[ 1 ].set( t.x - 0.005f, t.y + 0.005f ); p[ 2 ].set( t.x + 0.005f, t.y - 0.005f ); p[ 3 ].set( t.x + 0.005f, t.y + 0.005f ); c1 = c2 = 0xccff8000; drawRect( p, c1, c2 ); //ロックオンマーク if ( lockOn0 ){ gPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算にしてみようかな //敵ロボを座標変換してスクリーン座標に変換 Vector3 t = *gRobo[ 1 ]->position(); Vector4 p4; pvm.mul( &p4, t ); //XY座標はwで割れば出る。 float x = p4[ 0 ] / p4[ 3 ]; float y = p4[ 1 ] / p4[ 3 ]; //色は赤かなあ c1 = c2 = 0x80ff0000; //線4本でやろう。 p[ 0 ].set( x - 0.01f, y + 0.2f ); p[ 1 ].set( x - 0.01f, y + 0.1f ); p[ 2 ].set( x + 0.01f, y + 0.2f ); p[ 3 ].set( x + 0.01f, y + 0.1f ); drawRect( p, c1, c2 ); p[ 0 ].set( x - 0.01f, y - 0.2f ); p[ 1 ].set( x - 0.01f, y - 0.1f ); p[ 2 ].set( x + 0.01f, y - 0.2f ); p[ 3 ].set( x + 0.01f, y - 0.1f ); drawRect( p, c1, c2 ); p[ 0 ].set( x - 0.2f, y - 0.01f ); p[ 1 ].set( x - 0.2f, y + 0.01f ); p[ 2 ].set( x - 0.1f, y - 0.01f ); p[ 3 ].set( x - 0.1f, y + 0.01f ); drawRect( p, c1, c2 ); p[ 0 ].set( x + 0.2f, y - 0.01f ); p[ 1 ].set( x + 0.2f, y + 0.01f ); p[ 2 ].set( x + 0.1f, y - 0.01f ); p[ 3 ].set( x + 0.1f, y + 0.01f ); drawRect( p, c1, c2 ); } //時間制限 gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //もどして length = 1.9f * static_cast< float >( 60 * TIME_LIMIT - gTime ) / static_cast< float >( 60 * TIME_LIMIT ); p[ 0 ].set( -0.95f, -0.95f ); p[ 1 ].set( -0.95f, -0.9f ); p[ 2 ].set( 0.95f, -0.95f ); p[ 3 ].set( 0.95f, -0.9f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); p[ 0 ].set( -0.95f, -0.95f ); p[ 1 ].set( -0.95f, -0.9f ); p[ 2 ].set( -0.95f + length, -0.95f ); p[ 3 ].set( -0.95f + length, -0.9f ); gPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算? c1 = 0x80ff8888; c2 = 0x8088ffff; drawRect( p, c1, c2 ); if ( Input::Manager().keyboard().isTriggered( ' ' ) ){ gPlaying = !gPlaying; } if ( hp0 <= 0 || hp1 <= 0 || gTime >= 60 * TIME_LIMIT ){ gPlaying = false; DebugScreen::instance().draw( 20, 5, "Game Over. press FIRE" ); if ( Pad::instance()->isTriggered( Pad::FIRE, 0 ) ){ //セットしているものは後始末 gm.setVertexBuffer( 0 ); gm.setIndexBuffer( 0 ); gm.setTexture( 0 ); SAFE_DELETE( gRobo[ 0 ] ); SAFE_DELETE( gRobo[ 1 ] ); gRobo[ 0 ] = new Robo( 0 ); gRobo[ 1 ] = new Robo( 1 ); gRobo[ 0 ]->setPosition( Vector3( 0.f, 0.f, 50.f ) ); gRobo[ 0 ]->setAngleY( 180.0 ); gPlaying = true; gTime = 0; } } gPrimitiveRenderer.draw(); //足し終わったら描画 //終了判定(マウスで×ボタンが叩かれたか) if ( isEndRequested() ){ if ( gStage ){ Pad::destroy(); SAFE_DELETE( gRobo[ 0 ] ); SAFE_DELETE( gRobo[ 1 ] ); SAFE_DELETE( gStage ); //グローバルにあるものは勝手には消えないので開放 gPrimitiveRenderer.release(); } } }
void Framework::update(){ WindowCreator wc = WindowCreator::instance(); if ( gFirst ){ const char* filename = wc.commandLineString(); if ( filename && filename[ 0 ] != '\0' ){ load( filename ); } gFirst = false; }else{ //ドラッグアンドドロップを処理する int dropN = wc.droppedItemNumber(); if ( dropN > 0 ){ const char* filename = wc.droppedItem( 0 ); //0番以外無視 load( filename ); wc.clearDroppedItem(); //これを呼ぶとfilenameもこわれるので最後に。 } } //カメラ入力反映 Input::Manager im = Input::Manager::instance(); Input::Mouse mouse = im.mouse(); Input::Keyboard keyboard = im.keyboard(); if ( mouse.isOn( Input::Mouse::BUTTON_MIDDLE ) ){ Graphics::Manager().captureScreen( "capture.tga" ); } //ビュー行列を作ろう Vector3 eyePosition = gEyeTarget; eyePosition.z += gEyeDistance; Matrix34 rm; rm.setRotationY( gAngleY ); rm.rotateX( gAngleX ); Vector3 tv( 0.f, 0.f, 1.f ); rm.mul( &tv, tv ); eyePosition.setMadd( gEyeTarget, tv, gEyeDistance ); Matrix34 zrm; zrm.setRotationZ( gAngleZ ); Vector3 up( 0.f, 1.f, 0.f ); zrm.mul( &up, up ); Matrix34 vm; vm.setViewTransform( eyePosition, gEyeTarget, up ); if ( gContainer ){ float x = static_cast< float >( mouse.velocityX() ); float y = static_cast< float >( mouse.velocityY() ); if ( mouse.isOn( Input::Mouse::BUTTON_LEFT ) && mouse.isOn( Input::Mouse::BUTTON_RIGHT ) ){ //両ボタンでZ回転 gAngleZ -= 0.2f * x; gAngleZ -= 0.2f * y; }else if ( mouse.isOn( Input::Mouse::BUTTON_LEFT ) ){ //左ボタン回転 gAngleX -= 0.2f * y; if ( gAngleX > 89.9f ){ gAngleX = 89.9f; }else if ( gAngleX < -89.9f ){ gAngleX = -89.9f; } gAngleY -= 0.5f * x; }else if ( mouse.isOn( Input::Mouse::BUTTON_RIGHT ) ){ //右ボタン、注視点移動 Vector3 xv( vm.m00, vm.m01, vm.m02 ); xv *= x; Vector3 yv( vm.m10, vm.m11, vm.m12 ); yv *= y; gEyeTarget.madd( xv, -0.003f * gEyeDistance ); gEyeTarget.madd( yv, 0.003f * gEyeDistance ); } int w = mouse.wheel(); if ( w < 0 ){ gEyeDistance *= 0.9f; }else if ( w > 0 ){ gEyeDistance *= 1.1f; } } //透視変換行列 Matrix44 pm; pm.setPerspectiveTransform( 60.f, static_cast< float >( width() ), static_cast< float >( height() ), gEyeDistance * 0.01f, gEyeDistance * 10.f ); //次にPVを作る pm *= vm; if ( keyboard.isOn( 'G' ) ){ gAngleX = gAngleY = gAngleZ = 0.f; gEyeTarget = 0.f; } //ライトでもうごかそか Graphics::Manager gm = Graphics::Manager::instance(); gm.setProjectionViewMatrix( pm ); gm.setLightingMode( LIGHTING_PER_PIXEL ); gm.enableDepthTest( true ); gm.enableDepthWrite( true ); gm.setLightColor( 0, Vector3( 1.f, 1.f, 1.f ) ); //白 gm.setLightColor( 1, Vector3( 1.f, 0.7f, 0.7f ) ); //赤 gm.setLightColor( 2, Vector3( 0.7f, 1.f, 0.7f ) ); //緑 gm.setLightColor( 3, Vector3( 0.7f, 0.7f, 1.f ) ); //青 gm.setAmbientColor( Vector3( 0.2f, 0.2f, 0.2f ) ); gm.setEyePosition( eyePosition ); float t = gEyeDistance * 0.4f; float lightIntensity[ 4 ]; for ( int i = 0; i < 4; ++i ){ lightIntensity[ i ] = t; } Vector3 lightPositions[ 4 ]; for ( int i = 0; i < 4; ++i ){ float t = static_cast< float >( gCount * ( i + 1 ) ) / 5.f; float d = gEyeDistance * 2.f; lightPositions[ i ].set( sin( t )*cos( t ) * d, sin( t )*sin( t ) * d, cos( t ) * d ); lightPositions[ i ] += gEyeTarget; } for ( int i = 0; i < 4; ++i ){ gm.setLightPosition( i, lightPositions[ i ] ); gm.setLightIntensity( i, lightIntensity[ i ] ); } for ( int i = 0; i < gModels.size(); ++i ){ gModels[ i ].draw(); } //アニメ切り替え if ( keyboard.isTriggered( ' ' ) ){ if ( gContainer.animationNumber() > 0 ){ ++gAnimationIndex; if ( gAnimationIndex >= gContainer.animationNumber() ){ gAnimationIndex = 0; } for ( int i = 0; i < gTrees.size(); ++i ){ gTrees[ i ].setAnimation( gContainer.animation( gAnimationIndex ) ); } } } for ( int i = 0; i < gTrees.size(); ++i ){ gTrees[ i ].updateAnimation(); gTrees[ i ].draw(); } if ( isEndRequested() ){ gModels.clear(); gTrees.clear(); gContainer.release(); } ++gCount; }
void Framework::update(){ if ( gCount == 0 ){ //描画クラスを1000頂点、100バッチで初期化 gPrimitiveRenderer = PrimitiveRenderer::create( 1000, 100 ); //テクスチャロード gTexture = Texture::create( "test.tga" ); while ( !gTexture.isReady() ){ ; //ロード待ち } } //元の頂点配列 Vector3 p[ 4 ]; Vector2 t[ 4 ]; unsigned c[ 4 ]; //わかりやすいように色 p[ 0 ].set( -1.f, -1.f, 0.f ); p[ 1 ].set( -1.f, 1.f, 0.f ); p[ 2 ].set( 1.f, -1.f, 0.f ); p[ 3 ].set( 1.f, 1.f, 0.f ); t[ 0 ].set( 0.f, 0.f ); t[ 1 ].set( 0.f, 1.f ); t[ 2 ].set( 1.f, 0.f ); t[ 3 ].set( 1.f, 1.f ); c[ 0 ] = 0xffff0000; //赤 c[ 1 ] = 0xff00ff00; //緑 c[ 2 ] = 0xff0000ff; //青 c[ 3 ] = 0xffffffff; //白 //ワールド変換(Z回転) Matrix34 wm; wm.setRotationZ( gCount * 2.f ); //ビュー行列を作ろう Vector3 eyePosition; eyePosition.x = sin( gCount / 2.f ) * 4.f; eyePosition.z = cos( gCount / 2.f ) * 4.f; eyePosition.y = 1.f; Vector3 eyeTarget( 0.f, 0.f, 0.f ); Matrix34 vm; vm.setViewTransform( eyePosition, eyeTarget, Vector3( 0.f, 1.f, 0.f ) ); //透視変換行列 Matrix44 pm; pm.setPerspectiveTransform( 60.f, static_cast< float >( width() ), static_cast< float >( height() ), 1.f, 100.f ); //まずVWを作る vm *= wm; //次にPVWを作る pm *= vm; //行列セット gPrimitiveRenderer.setTransform( pm ); //テクスチャセット gPrimitiveRenderer.setTexture( gTexture ); gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //カウントで何を描くか変えてみよう if ( gCount % 300 > 200 ){ //三角形 gPrimitiveRenderer.addTriangle( p[ 0 ], p[ 1 ], p[ 2 ], t[ 0 ], t[ 1 ], t[ 2 ], c[ 0 ], c[ 1 ], c[ 2 ] ); gPrimitiveRenderer.addTriangle( p[ 3 ], p[ 1 ], p[ 2 ], t[ 3 ], t[ 1 ], t[ 2 ], c[ 3 ], c[ 1 ], c[ 2 ] ); }else if ( gCount % 300 > 100 ){ //線 //線を足す for ( int i = 0; i < 4; ++i ){ for ( int j = i + 1; j < 4; ++j ){ gPrimitiveRenderer.addLine( p[ i ], p[ j ], t[ i ], t[ j ], c[ i ], c[ j ] ); } } }else{ //点 gPrimitiveRenderer.addPoint( p[ 0 ], t[ 0 ], c[ 0 ] ); gPrimitiveRenderer.addPoint( p[ 1 ], t[ 1 ], c[ 1 ] ); gPrimitiveRenderer.addPoint( p[ 2 ], t[ 2 ], c[ 2 ] ); gPrimitiveRenderer.addPoint( p[ 3 ], t[ 3 ], c[ 3 ] ); } //スプライトとか書いてみようか。 //アルファブレンド有効化 gPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); Vector2 p2[ 2 ]; p2[ 0 ].set( 0.f, 0.f ); //左上 p2[ 1 ].set( 128.f, 256.f ); //右下 gPrimitiveRenderer.addRectangle( p2[ 0 ], p2[ 1 ], t[ 0 ], t[ 3 ], ( ( gCount % 256 ) << 24 ) | 0xffffff ); //足し終わったので描く gPrimitiveRenderer.draw(); DebugScreen() << frameRate(); ++gCount; if ( isEndRequested() ){ gPrimitiveRenderer.release(); //グローバルなので開放処理が必要 gTexture.release(); } }
void Framework::update(){ if ( !gDatabase ){ setFrameRate( 60 ); gDatabase = new GraphicsDatabase( "cube.txt" ); gModel = gDatabase->createModel( "cube" ); /*補間の方程式を解く。 p0 = a*t0^2 + b*t0 + c ...(0) p1 = a*t1^2 + b*t1 + c ...(1) 2a*t0 + b = v ...(2) まず一番式の形が単純な(2)を使ってb=の形にする。 b = v - 2a*t0 ...(3) 次に(1)-(0)でcを消す。 p1 - p0 = a(t1^2- t0^2) + b(t1 - t0) ...(4) (4)に(3)を代入してやる。 p1 - p0 = a(t1^2- t0^2) + (v-2a*t0)(t1 - t0) がんばって展開する。 p1 - p0 = a( t1^2 - t0^2 - 2*t0*t1 + 2*t0^2 ) + v(t1-t0) aで整理する a( t0^2 - 2*t0*t1 + t1^2 ) = (p1-p0) - v(t1-t0) ここでaの係数は(t0-t1)^2に因数分解できる。 aについて解けて、 a = ((p1-p0) - v(t1-t0)) / ( t0-t1 )^2 ...(5) 後は(3)を使ってbが出るし、(0)を使ってcも出る。 */ Vector3 v( 0.0, 0.0, 0.0 ); //第一区間の始点の傾きが0としようか。3つ計算するのでベクタ。 //以下XYZで別々の計算をするが、見やすいようにベクタクラスの計算関数は使わない。要素毎計算で行く。 for ( int i = 0; i < N-1; ++i ){ //点の数がNなんだから区間の数はN-1 //見やすいように定数を作る。 Vector3 p0 = gPoints[ i ]; Vector3 p1 = gPoints[ i + 1 ]; double t0 = gTimes[ i ]; double t02 = t0 * t0; double t1 = gTimes[ i + 1 ]; double t10 = t1 - t0; double t102 = t10 * t10; Vector3 a,b,c; //xyzで計算するから全部ベクタ //まずaを求める。 a.x = ( ( p1.x - p0.x ) - v.x*t10 ) / t102; a.y = ( ( p1.y - p0.y ) - v.y*t10 ) / t102; a.z = ( ( p1.z - p0.z ) - v.z*t10 ) / t102; //次がb b.x = v.x - 2.0 * a.x * t0; b.y = v.y - 2.0 * a.y * t0; b.z = v.z - 2.0 * a.z * t0; //最後にc c.x = p0.x - a.x*t02 - b.x*t0; c.y = p0.y - a.y*t02 - b.y*t0; c.z = p0.z - a.z*t02 - b.z*t0; //式を保存 gEquations[ i ][ 0 ] = a; gEquations[ i ][ 1 ] = b; gEquations[ i ][ 2 ] = c; //終点の傾きを計算 v.x = 2.0 * a.x * t1 + b.x; v.y = 2.0 * a.y * t1 + b.y; v.z = 2.0 * a.z * t1 + b.z; } } //ループ処理する。 double period = gTimes[ N - 1 ]; double quot = gT / period; int quotInt = static_cast< int >( quot ); gT -= static_cast< double >( quotInt ) * period; //区間を検索 int last = 0; for ( int i = 0; i < N; ++i ){ if ( gTimes[ i ] > gT ){ break; } last = i; } //式にぶちこんで値を出す Vector3 p; Vector3 a = gEquations[ last ][ 0 ]; Vector3 b = gEquations[ last ][ 1 ]; Vector3 c = gEquations[ last ][ 2 ]; Vector3 p0 = gPoints[ last ]; Vector3 p1 = gPoints[ last + 1 ]; p.x = ( ( a.x * gT ) + b.x ) * gT + c.x; p.y = ( ( a.y * gT ) + b.y ) * gT + c.y; p.z = ( ( a.z * gT ) + b.z ) * gT + c.z; //値が決まった。モデルにセット gModel->setPosition( p ); Matrix44 pm; pm.setPerspectiveTransform( 45.0, width(), height(), 1.0, 10000.0 ); Matrix34 vm; vm.setViewTransform( Vector3( 0.0, 30.0, 30.0 ), Vector3( 0.0, 0.0, 0.0 ) ); pm *= vm; gModel->draw( pm, Vector3( 0.0, 1.0, 0.0 ), Vector3( 1.0, 1.0, 1.0 ), Vector3( 0.2, 0.2, 0.2 ) ); gT += 1.0; if ( isEndRequested() ){ SAFE_DELETE( gModel ); SAFE_DELETE( gDatabase ); } }
void State::update(){ //自キャラの視線方向で一番近い敵キャラの同定 Vector2 eyeVector2(Math::cos(mRobo[0]->getAngleY()), Math::sin(mRobo[0]->getAngleY())); //zx平面上での自キャラの向き。大きさは1 Vector3 myPos3 = *mRobo[0]->position(); mAbleToSeeRoboIndex = 1; float ableToSeeRoboDistance = numeric_limits<float>::max(); for (int i = 1; i <= mStageID + 1; ++i){// 敵の数は mStageID + 1 if (mRobo[i]->getHitPoint() > 0){ Vector3 enemyPos3 = *mRobo[i]->position(); Vector2 enemyPos2; enemyPos2.y = enemyPos3.x; enemyPos2.x = enemyPos3.z; enemyPos2 *= 1.f / enemyPos2.length(); //大きさを1にする float dotProduct = eyeVector2.dot(enemyPos2); //大きさ1同士の内積なので、コサインを表す。 if (Math::cos(25.f) < dotProduct){ //視野角25*2=50°内にあるかチェック。画角は45°なので、少し広め。 Vector3 dir; dir.setSub(enemyPos3, myPos3); //自分と敵の位置の差ベクトル if (ableToSeeRoboDistance > dir.length()){ //前の敵キャラよりも近いなら ableToSeeRoboDistance = dir.length(); mAbleToSeeRoboIndex = i; } } } } // cout << mAbleToSeeRoboIndex << " hoge" << endl; if (mAbleToSeeRoboIndex == 1){//視線方向にいなかったら for (int i = 1; i <= mStageID+1; ++i){ if (mRobo[i]->getHitPoint() > 0){ mAbleToSeeRoboIndex = i; break; } } } // cout << mAbleToSeeRoboIndex << endl; mRobo[ 0 ]->update( mRobo[ mAbleToSeeRoboIndex ] ); for (int i = 1; i <= mStageID + 1; ++i){ mRobo[ i ]->update( mRobo[ 0 ] ); } ++mTime; Framework f = Framework::instance(); //0番ロボからカメラ行列ゲット Matrix44 pvm; pvm.setPerspectiveTransform( 45.f, //画角 static_cast< float >( f.width() ), //画面横幅 static_cast< float >( f.height() ), //画面縦幅 1.f, //ニアクリップ 10000.f ); //ファークリップ Matrix34 vm; Vector3 eyePosition; //視点の位置 mRobo[ 0 ]->getView( &vm, &eyePosition ); //ビュー行列はロボに作ってもらう pvm *= vm; //描画 //グローバルなライティング設定 Graphics::Manager gm = Graphics::Manager::instance(); gm.setProjectionViewMatrix( pvm ); gm.setEyePosition( eyePosition ); gm.setLightingMode( Graphics::LIGHTING_PER_PIXEL ); gm.setAmbientColor( mAmbient ); //環境光 gm.setLightColor( 0, Vector3( 0.7f, 0.4f, 0.2f ) ); gm.enableDepthTest( true ); //zテスト gm.enableDepthWrite( true ); Vector3 lightPos[ 4 ]; lightPos[ 0 ].set( 100000.f, 100000.f, 100000.f ); float lightIntensities[ 4 ]; //光強度 lightIntensities[ 0 ] = lightPos[ 0 ].length(); //長さを強度にすれば、だいたいその距離で1になる //ライトは最大4つ置ける //残り三つのライトは弾のところに置く。 //カメラに近い順に3つ選ぶことにする。 float nearestDistance[ 3 ]; int nearestIndex[ 3 ]; for ( int i = 0; i < 3; ++i ){ nearestDistance[ i ] = numeric_limits< float >::max(); nearestIndex[ i ] = -1; } //距離を測りながら最小を三つ取得 //100はロボあたりの弾の数の最大数。 for ( int i = 0; i <= mStageID + 1; ++i ){ for ( int j = 0; j < 100; ++j ){ const Vector3* p = mRobo[ i ]->getBulletPosition( j ); if ( p ){ Vector3 t; t.setSub( *p, eyePosition ); float d = t.squareLength(); if ( d < nearestDistance[ 0 ] ){ nearestDistance[ 2 ] = nearestDistance[ 1 ]; nearestDistance[ 1 ] = nearestDistance[ 0 ]; nearestDistance[ 0 ] = d; nearestIndex[ 2 ] = nearestIndex[ 1 ]; nearestIndex[ 1 ] = nearestIndex[ 0 ]; nearestIndex[ 0 ] = i * 100 + j; }else if ( d < nearestDistance[ 1 ] ){ nearestDistance[ 2 ] = nearestDistance[ 1 ]; nearestDistance[ 1 ] = d; nearestIndex[ 2 ] = nearestIndex[ 1 ]; nearestIndex[ 1 ] = i * 100 + j; }else if ( d < nearestDistance[ 2 ] ){ nearestDistance[ 2 ] = d; nearestIndex[ 2 ] = i * 100 + j; } } } } for ( int i = 0; i < 3; ++i ){ if ( nearestIndex[ i ] != -1 ){ int robo = nearestIndex[ i ] / 100; int bullet = nearestIndex[ i ] % 100; const Vector3* p = mRobo[ robo ]->getBulletPosition( bullet ); lightPos[ i + 1 ] = *p; if ( robo == 0 ){ gm.setLightColor( i + 1, Vector3( 0.2f, 0.4f, 1.f ) ); }else{ gm.setLightColor( i + 1, Vector3( 1.f, 0.2f, 0.4f ) ); } lightIntensities[ i + 1 ] = 10.f; }else{ lightIntensities[ i + 1 ] = 0.f; } } gm.setCullMode( Graphics::CULL_BACK ); //ライト設定 for ( int i = 0; i < 4; ++i ){ gm.setLightPosition( i, lightPos[ i ] ); gm.setLightIntensity( i, lightIntensities[ i ] ); } mStage->draw(); for (int i = 0; i <= mStageID+1; ++i){ //hpがノンゼロのもののみドロウする if (mRobo[i]->getHitPoint() > 0){ mRobo[ i ]->draw(); } } //以下フロントエンド描画 //モデル描画でいじられたものを元に戻す gm.setDiffuseColor( Vector3( 1.f, 1.f, 1.f ) ); gm.setTransparency( 1.f ); gm.setLightingMode( Graphics::LIGHTING_NONE ); //必要な情報を変数に収める int hp0 = mRobo[ 0 ]->getHitPoint(); int e0 = mRobo[ 0 ]->getEnergy(); bool lockOn0 = mRobo[ 0 ]->getLockOn(); //Zテスト無用。アルファブレンドON mPrimitiveRenderer.enableDepthTest( false ); mPrimitiveRenderer.enableDepthWrite( false ); mPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); Vector2 p[ 4 ]; unsigned c1; unsigned c2; //体力バー背景 p[ 0 ].set( -0.9f, 0.95f ); p[ 1 ].set( -0.9f, 0.87f ); p[ 2 ].set( 0.1f, 0.95f ); p[ 3 ].set( 0.1f, 0.87f ); c1 = c2 = 0xff406080; drawRect( p, c1, c2 ); //体力バー本体 float length = static_cast< float >( hp0 ) / static_cast< float >( Robo::mMaxHitPoint ); p[ 0 ].set( -0.9f, 0.95f ); p[ 1 ].set( -0.9f, 0.87f ); p[ 2 ].set( -0.9f + length, 0.95f ); p[ 3 ].set( -0.9f + length, 0.87f ); c1 = 0xff882244; c2 = 0xff88ccff; drawRect( p, c1, c2 ); drawRect( p, c1, c2 ); //武器エネルギー //背景 p[ 0 ].set( -0.1f, -0.7f ); p[ 1 ].set( -0.1f, -0.8f ); p[ 2 ].set( 0.1f, -0.7f ); p[ 3 ].set( 0.1f, -0.8f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); //本体 mPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算にしてみようかな length = 0.2f * static_cast< float >( e0 ) / static_cast< float >( Robo::mMaxEnergy ); p[ 0 ].set( -0.1f, -0.7f ); p[ 1 ].set( -0.1f, -0.8f ); p[ 2 ].set( -0.1f + length, -0.7f ); p[ 3 ].set( -0.1f + length, -0.8f ); c1 = 0x80ff0000; c2 = 0x80ffff00; drawRect( p, c1, c2 ); //レーダー mPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //背景 p[ 0 ].set( 0.7f, 0.7f ); p[ 1 ].set( 0.7f, 0.9f ); p[ 2 ].set( 0.9f, 0.7f ); p[ 3 ].set( 0.9f, 0.9f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); mPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算ブレンド //自分 Vector2 t; t.set( -mRobo[ 0 ]->position()->x, mRobo[ 0 ]->position()->z ); //x.z t *= 0.002f; //+-50のステージを0.2の大きさに縮小するので、0.2/100で0.002 t += Vector2( 0.8f, 0.8f ); //(0.8,0.8)が中心ゆえ、それを足す p[ 0 ].set( t.x - 0.005f, t.y - 0.005f ); p[ 1 ].set( t.x - 0.005f, t.y + 0.005f ); p[ 2 ].set( t.x + 0.005f, t.y - 0.005f ); p[ 3 ].set( t.x + 0.005f, t.y + 0.005f ); c1 = c2 = 0xcc0080ff; drawRect( p, c1, c2 ); //敵 for (int i = 1; i <= mStageID + 1; ++i){ if (mRobo[i]->getHitPoint() > 0){ t.set(-mRobo[i]->position()->x, mRobo[i]->position()->z); //x.z t *= 0.002f; //+-50のステージを0.2の大きさに縮小するので、0.2/100で0.002 t += Vector2(0.8f, 0.8f); //(0.8,0.8)が中心ゆえ、それを足す p[0].set(t.x - 0.005f, t.y - 0.005f); p[1].set(t.x - 0.005f, t.y + 0.005f); p[2].set(t.x + 0.005f, t.y - 0.005f); p[3].set(t.x + 0.005f, t.y + 0.005f); c1 = c2 = 0xccff8000; drawRect(p, c1, c2); } } //ロックオンマーク if ( lockOn0 ){ mPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算にする //敵ロボを座標変換してスクリーン座標に変換 Vector3 t = *mRobo[ mAbleToSeeRoboIndex ]->position(); Vector4 p4; pvm.mul( &p4, t ); //XY座標はwで割れば出る。 float x = p4[ 0 ] / p4[ 3 ]; float y = p4[ 1 ] / p4[ 3 ]; //色は赤 c1 = c2 = 0x80ff0000; //線4本を書く。 p[ 0 ].set( x - 0.01f, y + 0.2f ); p[ 1 ].set( x - 0.01f, y + 0.1f ); p[ 2 ].set( x + 0.01f, y + 0.2f ); p[ 3 ].set( x + 0.01f, y + 0.1f ); drawRect( p, c1, c2 ); p[ 0 ].set( x - 0.01f, y - 0.2f ); p[ 1 ].set( x - 0.01f, y - 0.1f ); p[ 2 ].set( x + 0.01f, y - 0.2f ); p[ 3 ].set( x + 0.01f, y - 0.1f ); drawRect( p, c1, c2 ); p[ 0 ].set( x - 0.2f, y - 0.01f ); p[ 1 ].set( x - 0.2f, y + 0.01f ); p[ 2 ].set( x - 0.1f, y - 0.01f ); p[ 3 ].set( x - 0.1f, y + 0.01f ); drawRect( p, c1, c2 ); p[ 0 ].set( x + 0.2f, y - 0.01f ); p[ 1 ].set( x + 0.2f, y + 0.01f ); p[ 2 ].set( x + 0.1f, y - 0.01f ); p[ 3 ].set( x + 0.1f, y + 0.01f ); drawRect( p, c1, c2 ); } //時間制限 mPrimitiveRenderer.setBlendMode( Graphics::BLEND_LINEAR ); //線形ブレンド length = 1.9f * static_cast< float >( 60 * mTimeLimit - mTime ) / static_cast< float >( 60 * mTimeLimit ); p[ 0 ].set( -0.95f, -0.95f ); p[ 1 ].set( -0.95f, -0.9f ); p[ 2 ].set( 0.95f, -0.95f ); p[ 3 ].set( 0.95f, -0.9f ); c1 = c2 = 0x80404040; drawRect( p, c1, c2 ); p[ 0 ].set( -0.95f, -0.95f ); p[ 1 ].set( -0.95f, -0.9f ); p[ 2 ].set( -0.95f + length, -0.95f ); p[ 3 ].set( -0.95f + length, -0.9f ); mPrimitiveRenderer.setBlendMode( Graphics::BLEND_ADDITIVE ); //加算 c1 = 0x80ff8888; c2 = 0x8088ffff; drawRect( p, c1, c2 ); mPrimitiveRenderer.draw(); //描画 //終了判定(マウスで×ボタンが叩かれたか) if ( f.isEndRequested() ){ if ( mStage ){ for (int i = 0; i <= mStageID + 1; ++i){ SAFE_DELETE( mRobo[ i ] ); } SAFE_DELETE( mStage ); } } }