青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

天行健 君子當自強而不息

Controlling Players and Characters(41)

 

download source and solution

 

Demonstrating Characters with the Chars Demo

All your hard work is about to pay off with a demonstration of the character and
spell controllers seen in this chapter.

Upon executing the program, you see the scene shown in following snap.

In the Chars demo, you take control of the PC, using the arrow keys to turn and
move him. The controls are straightforward—use the space bar to interact with the
closest character (either to speak to an NPC or to attack a monster). Pressing the
number keys 1 through 3 casts a few spells at the closest monster.

Each character in the game demonstrates a single artificial intelligence. Speaking
to another character conveys which artificial intelligence a particular character uses
(except for monsters, which either stand still or follow the player character). It’s
best to quickly dispatch the monsters before they take your player character out.

Everything in the Chars demo has been explained in this chapter. A script class
determines which characters to place in the map during startup (as detailed in the
startup script) and what each character does or says when spoken to.

The demo’s action template, default.mla, contains a number of script actions that
directly modify a character’s type, artificial intelligence, position, and direction.
Adding characters to the world is as easy as using an add character script action,
and from there, you modify the character’s attributes accordingly.

As for the main application, the system core’s cApp class is being used to
control the flow of the demo; each frame update is regulated to 33-millisecond
lapses, giving a 30-frames-per-second update rate. At each and every frame, keyboard
input is read in and stored, waiting to be used during the PC update function.
A fixed camera renders out the action, with each character fully animated
inside a single level (both characters and the level represented by meshes).

The code to the demo is well commented, so enjoy exploring it, and find out how
quickly you can create characters running around in your game project. Be sure to
check out the scripts and script action template using the Mad Lib Script editor, as
well as the items and character definitions using the MIL and MCL Editors.

 

Main Routine Source:

WinMain.h:

#ifndef WIMMAIN_H
#define WINMAIN_H

#include "core_framework.h"
#include "core_input.h"
#include "text_window.h"
#include "char_ics.h"
#include "char.h"
#include "script.h"
#include "spell.h"

class cApp;

/*************************************************************************************************/

class cGameCharController : public cCharController
{
private:
    cApp*   m_app;

private:    
    
virtual void pc_update(sCharacter* character, long elapsed,
                           
float* x_move, float* y_move, float* z_move);

    
virtual bool validate_move(sCharacter* character, 
                               
float* x_move, float* y_move, float* z_move);

public:
    
void set_data(cApp* app)
    {
        m_app = app;
    }
};

/*************************************************************************************************/

class cGameScript : public cScript
{
    friend cApp;

private:
    BOOL                    m_flags[256];

    cApp*                   m_app;

    cInputDevice*           m_keyboard;    
    cGameCharController*    m_gc_controller;
    
    
long                    m_num_route_points;
    sRoutePoint*            m_route;

    cTextWindow             m_text_window;

    ID3DXFont*              m_font;

    
//////////////////////////////////////////////////////////////////////////////////
    
public:
    cGameScript()
    {
        m_app           = NULL;
        m_keyboard      = NULL;        
        m_gc_controller = NULL;
        m_route         = NULL;
        m_font          = NULL;

        ZeroMemory(m_flags, 
sizeof(m_flags));
    }

    ~cGameScript()
    {
        delete[] m_route;
    }

    
void set_data(cApp* app, cInputDevice* keyboard, cGameCharController* gc_controller, ID3DXFont* font)
    {
        m_app           = app;
        m_keyboard      = keyboard;
        m_gc_controller = gc_controller;
        m_font          = font;

        m_text_window.create(m_font);
    }

    
//////////////////////////////////////////////////////////////////////////////////

private:
    
virtual void release()
    {
        delete[] m_route;
        m_route = NULL;

        m_num_route_points = 0;
    }

    
virtual sScriptInfo* process(sScriptInfo* info)
    {
        
switch(info->action_index)
        {
        
case 0:  return script_end(info);
        
case 1:  return script_if_flag_then(info);
        
case 2:  return script_else(info);
        
case 3:  return script_endif(info);
        
case 4:  return script_set_flag(info);
        
case 5:  return script_show_msg(info);
        
case 6:  return script_add_char(info);
        
case 7:  return script_remove_char(info);
        
case 8:  return script_show_char_msg(info);
        
case 9:  return script_set_char_type(info);
        
case 10: return script_set_char_ai(info);
        
case 11: return script_set_char_distance(info);
        
case 12: return script_set_char_bound(info);
        
case 13: return script_set_target_char(info);
        
case 14: return script_set_no_target(info);
        
case 15: return script_create_route(info);
        
case 16: return script_add_point(info);
        
case 17: return script_assign_route(info);
        
case 18: return script_move_char(info);
        
case 19: return script_set_char_script(info);
        }

        
return NULL;    // error executing
    }

    
//////////////////////////////////////////////////////////////////////////////////

private:

    sScriptInfo* script_end(sScriptInfo* info)
    {
        
return NULL;    // force end of processing
    }

    sScriptInfo* script_else(sScriptInfo* info)
    {
        
return info->next;
    }

    sScriptInfo* script_endif(sScriptInfo* info)
    {
        
return info->next;
    }

    sScriptInfo* script_set_flag(sScriptInfo* info)
    {
        m_flags[info->entries[0].long_value % 256] = info->entries[1].bool_value;

        
return info->next;
    }

    sScriptInfo* script_add_char(sScriptInfo* info)
    {
        m_gc_controller->add_char(info->entries[0].long_value,
                                  info->entries[1].long_value,
                                  info->entries[2].selection,
                                  info->entries[3].selection,
                                  info->entries[4].float_value,
                                  info->entries[5].float_value,
                                  info->entries[6].float_value,
                                  info->entries[7].float_value);

        
return info->next;
    }

    sScriptInfo* script_remove_char(sScriptInfo* info)
    {
        m_gc_controller->remove(info->entries[0].long_value);

        
return info->next;
    }

    sScriptInfo* script_set_char_type(sScriptInfo* info)
    {
        m_gc_controller->set_char_type(info->entries[0].long_value, info->entries[1].selection);

        
return info->next;
    }

    sScriptInfo* script_set_char_ai(sScriptInfo* info)
    {
        m_gc_controller->set_char_ai(info->entries[0].long_value, info->entries[1].selection);

        
return info->next;
    }

    sScriptInfo* script_set_char_distance(sScriptInfo* info)
    {
        m_gc_controller->set_char_distance(info->entries[0].long_value, info->entries[1].float_value);

        
return info->next;
    }

    sScriptInfo* script_set_char_bound(sScriptInfo* info)
    {
        m_gc_controller->set_char_bound(info->entries[0].long_value,
                                        info->entries[1].float_value,
                                        info->entries[2].float_value,
                                        info->entries[3].float_value,
                                        info->entries[4].float_value,
                                        info->entries[5].float_value,
                                        info->entries[6].float_value);

        
return info->next;
    }

    sScriptInfo* script_set_target_char(sScriptInfo* info)
    {
        m_gc_controller->set_target_char(info->entries[0].long_value, info->entries[1].long_value);

        
return info->next;
    }

    sScriptInfo* script_set_no_target(sScriptInfo* info)
    {
        m_gc_controller->set_target_char(info->entries[0].long_value, -1);

        
return info->next;
    }

    sScriptInfo* script_create_route(sScriptInfo* info)
    {
        delete[] m_route;
        m_route = NULL;

        m_num_route_points = 0;

        m_num_route_points = info->entries[0].long_value;
        m_route = 
new sRoutePoint[m_num_route_points];

        
return info->next;
    }

    sScriptInfo* script_add_point(sScriptInfo* info)
    {
        
long route_index = info->entries[0].long_value;

        m_route[route_index].pos_x = info->entries[1].float_value;
        m_route[route_index].pos_y = info->entries[2].float_value;
        m_route[route_index].pos_z = info->entries[3].float_value;

        
return info->next;
    }

    sScriptInfo* script_assign_route(sScriptInfo* info)
    {
        m_gc_controller->set_char_route(info->entries[0].long_value, m_num_route_points, m_route);

        
return info->next;
    }

    sScriptInfo* script_move_char(sScriptInfo* info)
    {
        m_gc_controller->move_char(info->entries[0].long_value,
                                   info->entries[1].float_value,
                                   info->entries[2].float_value,
                                   info->entries[3].float_value);

        
return info->next;
    }

    sScriptInfo* script_set_char_script(sScriptInfo* info)
    {
        m_gc_controller->set_char_script(info->entries[0].long_value, info->entries[1].text);

        
return info->next;
    }
    
    
//////////////////////////////////////////////////////////////////////////////////

private:
    sScriptInfo* script_if_flag_then(sScriptInfo* info);
    sScriptInfo* script_show_msg(sScriptInfo* info);
    sScriptInfo* script_show_char_msg(sScriptInfo* info);

    
void render_scene_and_msg();
};

/*************************************************************************************************/

class cApp : public cFramework
{
    friend 
class cGameScript;
    friend 
class cGameCharController;

private:
    cCamera             m_camera;

    cInput              m_input;
    cInputDevice        m_keyboard;
    cInputDevice        m_mouse;

    cMesh               m_terrain_mesh;
    cObject             m_terrain_object;

    cGameCharController m_gc_controller;
    cSpellController    m_spell_controller;

    cGameScript         m_game_script;

    sItem               m_mil[1024];

    ID3DXFont*          m_font;

public:
    
bool init();
    
bool frame();

    
long get_input();

    
bool check_intersect(float x_start, float y_start, float z_start,
                         
float x_end,   float y_end,   float z_end);
};


#endif
 

WinMain.cpp:

#include "core_common.h"
#include "core_graphics.h"
#include "char.h"
#include "script.h"
#include "text_window.h"
#include "tool.h"
#include "WinMain.h"

#define PRESS_UP        1
#define PRESS_RIGHT     2
#define PRESS_DOWN      4
#define PRESS_LEFT      8
#define PRESS_SPACE     16
#define PRESS_1         32
#define PRESS_2         64
#define PRESS_3         128

#define CLIENT_WIDTH    800
#define CLIENT_HEIGHT   600

cApp g_app;

// Global names of character meshes
PCSTR g_char_mesh_names[] = {
    "..\\Data\\Warrior.x",  
// Mesh # 0
    "..\\Data\\Yodan.x"     // Mesh # 1
};

sCharAnimInfo g_char_anim_infos[] = {
    { "Idle",  
true  },
    { "Walk",  
true  },
    { "Swing", 
false },
    { "Spell", 
false },
    { "Swing", 
false },
    { "Hurt",  
false },
    { "Die",   
false },
    { "Idle",  
true  }
};

PCSTR g_spell_mesh_names[] = {
    "..\\Data\\Fireball.x",
    "..\\Data\\Explosion.x",
    "..\\Data\\Groundball.x",
    "..\\Data\\ice.x",
    "..\\Data\\bomb.x",
};

int WINAPI WinMain(HINSTANCE inst, HINSTANCE, LPSTR cmd_line, int cmd_show)
{        
    DWORD pos_x = (get_screen_width()  - CLIENT_WIDTH) / 2;
    DWORD pos_y = (get_screen_height() - CLIENT_HEIGHT) / 4;

    build_window(inst, "CharClass", "Characters Demo", 
                 WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
                 pos_x, pos_y, CLIENT_WIDTH, CLIENT_HEIGHT);
    
    g_app.run();

    
return 0;
}

/*************************************************************************************************/

void cGameCharController::pc_update(sCharacter* character, long elapsed,
                                    
float* x_move, float* y_move, float* z_move)
{
    
if(character->id != CHAR_PC)
        
return;

    
float speed = elapsed/1000.0f * get_speed(character);

    
// rotate character

    
long action = m_app->get_input();    

    
if(action & PRESS_RIGHT)
    {
        character->direction += (elapsed/1000.0f * 8);
        character->action = CHAR_MOVE;
    }

    
if(action & PRESS_LEFT)
    {
        character->direction -= (elapsed/1000.0f * 8);
        character->action = CHAR_MOVE;
    }

    
// walk forward
    if(action & PRESS_UP)
    {
        *x_move = sin(character->direction) * speed;
        *z_move = cos(character->direction) * speed;
        
        character->action = CHAR_MOVE;
    }

    sCharacter* char_ptr;
    
float x_diff, y_diff, z_diff, dist;

    
// attack a nearby monster or process NPC script
    if(action & PRESS_SPACE)
    {
        
for(char_ptr = get_root_char(); char_ptr != NULL; char_ptr = char_ptr->next)
        {
            
// only check other characters
            if(char_ptr->id == character->id)
                
continue;
            
            x_diff = fabs(char_ptr->pos_x - character->pos_x);
            y_diff = fabs(char_ptr->pos_y - character->pos_y);
            z_diff = fabs(char_ptr->pos_z - character->pos_z);

            dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

            
// only check characters within 1000.0 units distance
            if(dist > 10000.0f)
                
continue;
            
            
if(char_ptr->script_filename[0])
                m_app->m_game_script.execute(char_ptr->script_filename);
            
else
            {
                
// turn toward victim
                x_diff = char_ptr->pos_x - character->pos_x;
                z_diff = char_ptr->pos_z - character->pos_z;

                character->direction = atan2(x_diff, z_diff);

                character->victim  = char_ptr;
                char_ptr->attacker = character;

                m_app->m_gc_controller.set_char_action(character, CHAR_ATTACK, 0);
            }

            
break;
        }
    }

    
long spell_index = 0;

    
// cast spells
    if(action & PRESS_1 || action & PRESS_2 || action & PRESS_3)
    {
        
// get spell index to cast
        if(action & PRESS_1)    spell_index = 0;
        
if(action & PRESS_2)    spell_index = 1;
        
if(action & PRESS_3)    spell_index = 2;

        
float spell_max_dist = m_app->m_spell_controller.get_spell(spell_index)->max_dist;

        
// search for closest monster
        for(char_ptr = get_root_char(); char_ptr != NULL; char_ptr = char_ptr->next)
        {
            
if(char_ptr->type == CHAR_MONSTER)
            {
                x_diff = fabs(char_ptr->pos_x - character->pos_x);
                y_diff = fabs(char_ptr->pos_y - character->pos_y);
                z_diff = fabs(char_ptr->pos_z - character->pos_z);

                dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;

                
if(dist <= (spell_max_dist * spell_max_dist))
                {
                    character->spell_index = spell_index;
                    character->target_type = CHAR_MONSTER;
                    character->target_x    = char_ptr->pos_x;
                    character->target_y    = char_ptr->pos_y;
                    character->target_z    = char_ptr->pos_z;

                    
// turn toward victim
                    x_diff = char_ptr->pos_x - character->pos_x;
                    z_diff = char_ptr->pos_z - character->pos_z;
                    character->direction = atan2(x_diff, z_diff);

                    m_app->m_gc_controller.set_char_action(character, CHAR_SPELL, 0);
                    
break;
                }
            }
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////

bool cGameCharController::validate_move(sCharacter* character, 
                                        
float* x_move, float* y_move, float* z_move)
{
    
// check against terrain mesh for collision
    
    
return ! m_app->check_intersect(character->pos_x, character->pos_y + 2.0f, character->pos_z,
        *x_move + character->pos_x, *y_move + character->pos_y + 2.0f, *z_move + character->pos_z);   
}

/*************************************************************************************************/

void cGameScript::render_scene_and_msg()
{
    clear_display(0, 1.0);

    
if(begin_display_scene())
    {
        enable_zbuffer();            

        g_app.m_terrain_object.render();
        g_app.m_gc_controller.render(-1, NULL, 0);
        g_app.m_spell_controller.render(NULL, 0);

        m_text_window.render(NULL, 0);

        end_display_scene();
    }

    present_display();
}

///////////////////////////////////////////////////////////////////////////////////

sScriptInfo* cGameScript::script_if_flag_then(sScriptInfo* info)
{
    
bool skip;

    
// see if a flag matches second entry
    if(m_flags[info->entries[0].long_value % 256] == info->entries[1].bool_value)
        skip = 
false;
    
else
        skip = 
true;

    
// At this point, Skip states if the script actions need to be skipped due to a conditional 
    // if..then statement.
    // 
    // Actions are further processed if skip = false, looking for an else to flip the skip mode, 
    // or an endif to end the conditional block.
    
    info = info->next;

    
while(info)
    {
        
if(info->action_index == 2)         // if else, flip skip mode.
            skip = !skip;   
        
else if(info->action_index == 3)    // break on end if
            return info->next;

        
// Process script function in conditional block, making sure to skip actions when condition not met.
        if(skip)
            info = info->next;
        
else
        {
            
if((info = process(info)) == NULL)
                
return NULL;
        }
    }

    
return NULL;    // end of script reached
}

///////////////////////////////////////////////////////////////////////////////////

sScriptInfo* cGameScript::script_show_msg(sScriptInfo* info)
{
    m_text_window.set_text(info->entries[0].text, COLOR_WHITE);
    m_text_window.move(10, 10, CLIENT_WIDTH-20, 0, -1, -1, COLOR_BLACK, COLOR_ARGENTINE);

    render_scene_and_msg();

    
// wait for a key press

    m_keyboard->acquire();
    m_keyboard->m_locks[KEY_SPACE] = 
true;
    m_keyboard->set_key_state(KEY_SPACE, 
false);
    
    
while(1)
    {
        m_keyboard->read();

        
if(m_keyboard->get_key_state(KEY_SPACE))
            
break;
    }

    m_keyboard->m_locks[KEY_SPACE] = 
true;
    m_keyboard->set_key_state(KEY_SPACE, 
false);

    
return info->next;
}

///////////////////////////////////////////////////////////////////////////////////

sScriptInfo* cGameScript::script_show_char_msg(sScriptInfo* info)
{
    D3DXMATRIX mat_world, mat_view, mat_proj;

    D3DXMatrixIdentity(&mat_world);
    get_display_view_matrix(&mat_view);
    get_display_proj_matrix(&mat_proj);    

    D3DVIEWPORT9 viewport;
    get_display_viewport(&viewport);    

    
// get the character's coordinates

    
float max_y;
    sCharacter* character = m_gc_controller->get_char(info->entries[1].long_value);

    character->
object.get_bounds(NULL, NULL, NULL, NULL, &max_y, NULL, NULL);

    
// project the 3D coordinates in 2D coordinates

    D3DXVECTOR3 target_vec;
    D3DXVECTOR3 source_vec(character->pos_x, character->pos_y + max_y, character->pos_z);

    D3DXVec3Project(&target_vec, &source_vec, &viewport, &mat_proj, &mat_view, &mat_world);

    m_text_window.set_text(info->entries[0].text, D3DCOLOR_RGBA(255, 255, 0, 255));
    m_text_window.move(10, 10, CLIENT_WIDTH-20, 0, target_vec.x, target_vec.y, 
                       D3DCOLOR_RGBA(0, 30, 60, 255), COLOR_ARGENTINE);

    
// display the window while waiting for a keypress

    m_keyboard->acquire();
    m_keyboard->m_locks[KEY_SPACE] = 
true;
    m_keyboard->set_key_state(KEY_SPACE, 
false);
    
    
while(1)
    {
        m_keyboard->read();

        
if(m_keyboard->get_key_state(KEY_SPACE))
            
break;

        render_scene_and_msg();
    }

    m_keyboard->m_locks[KEY_SPACE] = 
true;
    m_keyboard->set_key_state(KEY_SPACE, 
false);   

    
return info->next;
}

/*************************************************************************************************/

bool cApp::init()
{
    create_display(g_hwnd, CLIENT_WIDTH, CLIENT_HEIGHT, 16, 
truetrue);
    set_perspective(D3DX_PI/4, 1.3333f, 1.0f, 10000.0f);

    create_font(&m_font, "Arial", 16, 
truefalse);

    m_input.create(g_hwnd, get_window_inst());
    m_keyboard.create_keyboard(&m_input);
    m_mouse.create_mouse(&m_input, 
true);

    m_terrain_mesh.load("..\\Data\\World.x", "..\\Data\\");
    m_terrain_object.create(&m_terrain_mesh);

    
// load the master item list

    ZeroMemory(m_mil, 
sizeof(m_mil));

    FILE* fp;
    
if((fp = fopen("..\\Data\\Default.mil", "rb")) == NULL)
        
return false;

    fread(m_mil, 1, 
sizeof(m_mil), fp);
    fclose(fp);

    m_spell_controller.init("..\\Data\\Default.msl",
                            array_num(g_spell_mesh_names), g_spell_mesh_names,
                            "..\\Data\\");

    m_gc_controller.init(m_font, "..\\Data\\Default.mcl",
                         m_mil, m_spell_controller.get_spell_list(),
                         array_num(g_char_mesh_names), g_char_mesh_names,
                         "..\\Data\\", "..\\Data\\",
                         array_num(g_char_anim_infos), g_char_anim_infos);

    m_spell_controller.attach(&m_gc_controller);
    m_gc_controller.attach(&m_spell_controller);

    m_gc_controller.set_data(
this);

    
// add the character player
    m_gc_controller.add_char(0, 0, CHAR_PC, CHAR_STAND, 0.0f, 0.0f, 0.0f, 3.14f);

    
// process the startup script
    m_game_script.set_data(this, &m_keyboard, &m_gc_controller, m_font);
    m_game_script.execute("..\\Data\\Startup.mls");

    
return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

bool cApp::frame()
{
    
static DWORD update_counter = timeGetTime();

    
// lock to 30fps
    if(timeGetTime() < update_counter + 33)
        
return true;

    update_counter = timeGetTime();

    m_keyboard.acquire();
    m_keyboard.read();

    
// exit if ESC pressed
    if(m_keyboard.get_key_state(KEY_ESC))
        
return false;

    m_gc_controller.update(33);
    m_spell_controller.update(33);

    m_camera.point(0.0f, 700.0f, -700.0f, 0.0f, 0.0f, 0.0f);
    set_display_camera(&m_camera);
    
    clear_display(0, 1.0f);

    
if(begin_display_scene())
    {
        enable_zbuffer();

        m_terrain_object.render();
        m_gc_controller.render(-1, NULL, 0);
        m_spell_controller.render(NULL, 0);

        
static sCharacter* character = m_gc_controller.get_char(0);

        
char stats[128];

        sprintf(stats, "HP: %ld / %ld\r\nMP: %ld / %ld",
                character->health_points, character->char_def.health_points,
                character->mana_points, character->char_def.mana_points);

        draw_font(m_font, stats, 2, 2, 0, 0, COLOR_WHITE, DT_LEFT);

        end_display_scene();
    }

    present_display();

    
return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

long cApp::get_input()
{
    
long action = 0;

    
if(m_keyboard.get_key_state(KEY_UP) || m_keyboard.get_key_state(KEY_W))
        action |= PRESS_UP;

    
if(m_keyboard.get_key_state(KEY_RIGHT) || m_keyboard.get_key_state(KEY_D))
        action |= PRESS_RIGHT;

    
if(m_keyboard.get_key_state(KEY_DOWN) || m_keyboard.get_key_state(KEY_S))
        action |= PRESS_DOWN;

    
if(m_keyboard.get_key_state(KEY_LEFT) || m_keyboard.get_key_state(KEY_A))
        action |= PRESS_LEFT;

    
if(m_keyboard.get_key_state(KEY_SPACE))
    {
        action |= PRESS_SPACE;
        m_keyboard.m_locks[KEY_SPACE] = 
true;
        m_keyboard.set_key_state(KEY_SPACE, 
false);
    }

    
if(m_keyboard.get_key_state(KEY_1))
    {
        action |= PRESS_1;
        m_keyboard.m_locks[KEY_1] = 
true;
        m_keyboard.set_key_state(KEY_1, 
false);
    }

    
if(m_keyboard.get_key_state(KEY_2))
    {
        action |= PRESS_2;
        m_keyboard.m_locks[KEY_2] = 
true;
        m_keyboard.set_key_state(KEY_2, 
false);
    }
    
    
if(m_keyboard.get_key_state(KEY_3))
    {
        action |= PRESS_3;
        m_keyboard.m_locks[KEY_3] = 
true;
        m_keyboard.set_key_state(KEY_3, 
false);
    }

    
return action;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////

bool cApp::check_intersect(float x_start, float y_start, float z_start,
                           
float x_end,   float y_end,   float z_end)
{
    
for(sMeshInfo* mesh_info = m_terrain_mesh.get_root_mesh(); mesh_info != NULL; mesh_info = mesh_info->m_next)
    {
        
if(is_ray_intersect_mesh(mesh_info->m_d3d_mesh, x_start, y_start, z_start, x_end, y_end, z_end, NULL))        
            
return true;        
    }
    
    
return false;
}

posted on 2007-12-04 21:05 lovedday 閱讀(496) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


公告

導航

統計

常用鏈接

隨筆分類(178)

3D游戲編程相關鏈接

搜索

最新評論

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美国产精品中文字幕| 亚洲欧洲午夜| 久久免费高清| 亚洲国产日韩欧美综合久久| 亚洲精品免费在线观看| 欧美日韩久久久久久| 亚洲欧美精品在线| 蜜桃久久精品一区二区| 亚洲区国产区| 国产精品午夜春色av| 欧美在线三区| 亚洲高清二区| 亚洲欧美国产另类| 在线观看亚洲精品| 欧美新色视频| 久久久久久午夜| 一本色道久久综合亚洲91| 久久国产黑丝| 日韩午夜在线视频| 国产欧美日韩亚州综合| 你懂的网址国产 欧美| 一本色道久久综合亚洲二区三区 | 亚洲免费在线播放| 激情六月婷婷久久| 国产精品都在这里| 免费观看日韩av| 亚洲综合色网站| 欧美电影美腿模特1979在线看| 亚洲一区在线视频| 亚洲国产成人久久综合一区| 国产精品乱人伦一区二区| 快射av在线播放一区| 亚洲一区二区三区久久| 亚洲国产精品久久久久婷婷老年| 欧美中文在线观看| 亚洲视频中文字幕| 亚洲高清不卡在线| 国产麻豆精品在线观看| 欧美日韩成人| 久热精品在线视频| 欧美在线日韩| 亚洲男人av电影| 99国产麻豆精品| 亚洲国产日韩欧美在线图片 | 亚洲日本成人网| 久久久成人网| 亚洲欧美www| 夜夜嗨av一区二区三区中文字幕 | 99视频在线精品国自产拍免费观看 | 亚洲欧美在线磁力| 99精品国产高清一区二区| 一区二区在线视频播放| 国产视频久久久久| 国产精品私房写真福利视频| 欧美日韩国产综合在线| 欧美激情久久久| 美日韩精品视频| 久久久亚洲人| 久久九九久精品国产免费直播| 亚洲综合社区| 亚洲欧美中文日韩在线| 亚洲综合视频在线| 亚洲自拍偷拍麻豆| 亚洲免费视频观看| 亚洲欧美国产精品专区久久| 亚洲图片欧美一区| 亚洲一区欧美激情| 亚洲综合欧美| 午夜一级久久| 久久国产综合精品| 久久久久久久久久久久久9999| 久久成人资源| 久久人体大胆视频| 美女主播一区| 欧美日韩国产色综合一二三四| 欧美日韩国产在线播放| 欧美人成在线| 欧美精品亚洲一区二区在线播放| 欧美韩国一区| 国产精品国色综合久久| 国产乱码精品一区二区三区五月婷| 国产精品一区视频| 国内精品久久久久影院色| 在线激情影院一区| 9l国产精品久久久久麻豆| 一区二区三区波多野结衣在线观看| 中国日韩欧美久久久久久久久| 亚洲视频一二| 久久国产日韩| 欧美丰满少妇xxxbbb| 亚洲麻豆国产自偷在线| 亚洲图中文字幕| 欧美在线视频一区二区三区| 蜜桃av一区| 欧美视频二区36p| 国产日韩专区在线| 在线观看日韩www视频免费| 亚洲国产一区二区三区在线播 | 中文亚洲字幕| 欧美亚洲日本网站| 欧美夫妇交换俱乐部在线观看| 亚洲精品欧美日韩专区| 亚洲欧美国产视频| 久久综合给合久久狠狠狠97色69| 欧美日韩国产美| 国内精品**久久毛片app| 亚洲精品视频一区二区三区| 亚洲欧美区自拍先锋| 久久久亚洲欧洲日产国码αv | 一区二区不卡在线视频 午夜欧美不卡在 | 夜色激情一区二区| 久久精品国产久精国产一老狼 | 亚洲国产综合91精品麻豆| 一区二区三区三区在线| 久久久亚洲成人| 99精品热视频| 美女脱光内衣内裤视频久久影院 | 国产一区二区高清| 99亚洲伊人久久精品影院红桃| 久久精品国产一区二区三| 亚洲国产日韩综合一区| 欧美在线1区| 国产精品第一区| 亚洲欧洲日本一区二区三区| 久久精品国产综合| 一本久道久久综合婷婷鲸鱼| 蜜臀久久久99精品久久久久久| 国产欧美精品一区| 日韩视频免费在线| 老司机久久99久久精品播放免费 | 亚洲免费在线视频| 欧美国产日韩在线| 激情欧美一区| 久久riav二区三区| 99视频一区二区三区| 欧美成人国产va精品日本一级| 国内精品一区二区三区| 亚洲欧美日韩国产精品 | 亚洲天堂av在线免费观看| 欧美成年人视频网站| 激情丁香综合| 久久激情五月婷婷| 亚洲一区二区三区涩| 欧美人成在线视频| 亚洲精品美女在线观看播放| 免费一级欧美片在线观看| 香蕉精品999视频一区二区| 国产精品成人在线观看| 99亚洲一区二区| 亚洲人成网站色ww在线| 免费看成人av| 亚洲激情综合| 欧美二区不卡| 欧美不卡在线视频| 亚洲精选在线观看| 亚洲国产精品激情在线观看| 欧美va亚洲va香蕉在线| 亚洲国产一区在线观看| 欧美激情精品久久久久久久变态| 噜噜爱69成人精品| 亚洲高清免费| 欧美护士18xxxxhd| 欧美阿v一级看视频| 日韩午夜激情av| 亚洲日本欧美| 欧美日韩午夜剧场| 亚洲女爱视频在线| 亚洲欧美日韩国产另类专区| 国产精品视频专区| 久久精品国产69国产精品亚洲| 欧美在线一级视频| 精品电影一区| 亚洲电影免费观看高清| 欧美精品在线免费观看| 亚洲午夜国产一区99re久久 | 欧美日韩国产成人| 亚洲欧美久久久久一区二区三区| 欧美在线免费观看| 一区二区三区精品视频在线观看| 欧美日本久久| 亚洲视频电影图片偷拍一区| 在线视频欧美日韩| 国产精品久久久久久久久久久久久久 | 欧美福利在线观看| 亚洲图片在线观看| 亚洲欧美一区二区三区在线| 国产一区二区三区免费不卡| 欧美成人亚洲成人| 欧美日韩国产成人| 久久成人综合视频| 麻豆av福利av久久av| 一区二区三区不卡视频在线观看| 亚洲综合色自拍一区| 亚洲电影在线| 一区二区欧美在线| 黑人巨大精品欧美黑白配亚洲| 亚洲激情在线| 国产精品日韩欧美大师| 女人香蕉久久**毛片精品| 欧美麻豆久久久久久中文|