view Renderer/Test/collision_effect.cc @ 1479:163220e54cc0 draft

remove hard code for TaskLog
author Daichi TOMA <toma@cr.ie.u-ryukyu.ac.jp>
date Tue, 24 Jul 2012 17:15:15 +0900
parents 5f12d99e95ac
children
line wrap: on
line source

#include <math.h>
#include <stdlib.h>
#include "SceneGraphRoot.h"
#include "MainLoop.h"
#include "collision_effect.h"


// prototype
static void ball_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h);
static void ball_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h, SceneGraphPtr tree);
static void jump_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h);
static void fall_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h);
static void effect_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h);
static const float ball_radius = 88.0f;
static const float target_radius = 88.0f;
static int targetID;//targetのオブジェクトのIDを保存
/*
 * 変数stat でボールの状態を表す。
 * 0:地上
 * 1:ジャンプ
 * 2:左方向へジャンプ
 * 3:右方向へジャンプ
 */
static int stat;

static void
ball_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
{
  SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_;
  Pad *pad = sgroot->getController();
  const float player_speed = 24.0f;


  if ( pad->up.isPush() || pad->up.isHold()) {
    if ( pad->left.isPush() || pad->left.isHold() ){
      stat = 2;
    }else if ( pad->right.isPush() || pad->right.isHold() ){
      stat = 3;
    }
    node->set_move_collision(jump_move,ball_collision);
  }
  if ( pad->left.isPush() || pad->left.isHold() ) {
    node->xyz[0] -= player_speed;
  }else if ( pad->right.isPush() || pad->right.isHold() ) {
    node->xyz[0] += player_speed;
  }else if ( pad->down.isPush() || pad->down.isHold() ) {
    // node->xyz[1] += player_speed;
  }
  
}

static void
jump_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
{
  float vy = 0.0f;
  const float g = 9.8f;
  const float player_speed = 30.0f;
  float dt = 2.0f;//frame rate 

  if ( stat == 2 ){
    node->xyz[0] -= player_speed;
  }else if ( stat == 3 ){
    node->xyz[0] += player_speed;
  }
  
  vy += g * dt;
  node->xyz[1] -= vy * dt;
  
  if ( node->xyz[1] < 0 ){
    node->set_move_collision(fall_move,ball_collision);
  }
  
}


static void fall_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
{
  float vy = 0.0f;
  const float g = -9.8f;
  const float dt = 2.0f;//frame rate
  const float player_speed = 30.0f;

  if ( stat == 2 ){
    node->xyz[0] -= player_speed;
  }else if ( stat == 3 ){
    node->xyz[0] += player_speed;
  }
  vy += g * dt;
  node->xyz[1] -= vy * dt;
  if (node->xyz[1] >= screen_h/2){
    node->xyz[1] = screen_h/2;
    node->set_move_collision(ball_move,ball_collision);
  }
}

static void 
effect_move(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h)
{
  node->remove();
}


static void
ball_collision(SceneGraphPtr node, void *sgroot_, int screen_w, int screen_h,
	       SceneGraphPtr tree)
{
  SceneGraphRoot *sgroot = (SceneGraphRoot *)sgroot_;
  SceneGraphIteratorPtr it = sgroot->getIterator(tree);
  
  float x_distance,y_distance,distance;
  
  float target_speed = 48.0f;
  

  //IDが"target"のSceneGraphまですすめる
  it->next(targetID);
  
  //targetのシーングラフを取得  
  SceneGraphPtr target = it->get();
  x_distance = node->xyz[0] - target->xyz[0];
  y_distance = node->xyz[1] - target->xyz[1];
  
  //二点間の距離を求める
  distance = hypotf(x_distance,y_distance);
  
  //二点間の距離が2つの半径の合計以下なら、衝突
  if(distance <= (ball_radius + target_radius)){
    
    
    /* 
     * 交点でエフェクト発生
     * 接点の座標を(x,y)としたとき、
     * (x - target->xyz[0]) : (x_distance) = target_radius : distance
     * (x - target->xyz[0]) = (target_radius / distance)*(x_distance)
     * 同様に、
     * (y - target->xyz[1]) = (target_radius / distance)*(y_distance)
     */
    
    float rate = target_radius / distance;
    float x = rate * x_distance + target->xyz[0];
    float y = rate * y_distance + target->xyz[1];

    SceneGraphPtr effect = sgroot->createSceneGraph("BLAST3");
    effect->set_move_collision(effect_move);
    node->addBrother(effect);
    
    //点(x,y)にエフェクト
    effect->xyz[0] = x;
    effect->xyz[1] = y;
    effect->xyz[3] = -30.0f;

    if (node->xyz[1] > target->xyz[1]){
      //上からぶつかられた場合はのけぞりを大きく
      target_speed += ball_radius;
    }
    
    if ( node->xyz[0] > target->xyz[0] ){
      //右からぶつかられた場合
      target->xyz[0] -= target_speed;
    } else{
      //左からぶつかられた場合
      target->xyz[0] += target_speed;
    }
  } 
}

MainLoopPtr 
collision_effect::init(Viewer *sgroot, int screen_w, int screen_h)
{
    sgroot->OnLightSysSwitch();
    
    //ライト設置
    SceneGraphPtr light = sgroot->getLight(0);
    sgroot->OnLightSwitch(0);
    light->xyz[0] = screen_w / 2;
    light->xyz[1] = screen_h / 2;
    light->xyz[2] = -100;
    
    SceneGraphPtr root = sgroot->createSceneGraph();
    
    //effectのシーングラフ作成
    sgroot->createFromXMLfile("xml_file/blast.xml");

    //ボールのシーングラフ作成
    SceneGraphPtr ball;
    sgroot->createFromXMLfile("xml_file/ball.xml");
    ball = sgroot->createSceneGraph("Ball");

    
    // ball_moveは最初、絶対地上にいるのでstatを0(地上判定)に更新
    stat = 0;
    
    //初期化
    ball->xyz[0] = screen_w;
    ball->xyz[1] = screen_h/2;
    ball->xyz[2] = 60.0f;

    //rootの子に追加
    root->addChild(ball);


    //targetのシーングラフ作成
    SceneGraphPtr target = sgroot->createSceneGraph("Ball");
    //IDの登録
    targetID = target->sgid;
    
    target->xyz[0] = screen_w/2;
    target->xyz[1] = screen_h/2;
    target->xyz[2] = 60.f;


    //ボールの動きと当たり判定をセット
    ball->set_move_collision(ball_move, ball_collision);

    root->addChild(target);

    sgroot->setSceneData(root);
    return sgroot;
}

extern Application *
application() {
    return new collision_effect();
}

const char *usr_help_str = "Usage: ./test_nogl [OPTION]\n";

extern int init(TaskManager *manager, int argc, char *argv[]);
extern void task_initialize();
static void TMend(TaskManager *manager);

int
TMmain(TaskManager *manager, int argc, char *argv[])
{
    task_initialize();
    manager->set_TMend(TMend);
    return init(manager, argc, argv);

}

void
TMend(TaskManager *manager)
{
    printf("test_nogl end\n");
}

/* end */