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

天行健 君子當自強而不息

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>
            国产精品视频不卡| 久久久久久国产精品mv| 欧美永久精品| 午夜国产精品影院在线观看| 亚洲午夜高清视频| 欧美亚洲一区二区在线| 久久精品国产2020观看福利| 久久阴道视频| 欧美激情第9页| 日韩视频永久免费观看| 亚洲天堂av电影| 久久国产精品久久国产精品| 免费成人网www| 欧美日韩岛国| 国产亚洲成年网址在线观看| 亚洲大片在线观看| 一区二区三区精密机械公司 | 欧美激情视频在线播放 | 性久久久久久久| 久久夜色精品一区| 欧美久久婷婷综合色| 国产欧美精品xxxx另类| 亚洲第一福利视频| 一区二区三区欧美亚洲| 久久精品av麻豆的观看方式| 亚洲国产精品v| 国内自拍亚洲| 一区二区日韩伦理片| 久久精品国亚洲| 日韩一区二区电影网| 久久精品毛片| 国产精品久久久久久久久久久久久久 | 久久久久久久尹人综合网亚洲| 欧美国产乱视频| 亚洲欧美另类在线| 欧美剧在线观看| 狠狠色狠狠色综合人人| 亚洲淫性视频| 亚洲黄色高清| 裸体丰满少妇做受久久99精品| 欧美午夜精品理论片a级大开眼界| 黄色亚洲精品| 欧美一区二区精美| 一区二区三区四区五区精品| 免费观看亚洲视频大全| 国产一区二区三区丝袜| 中文一区二区在线观看| 亚洲丰满在线| 久久影视三级福利片| 国产色综合久久| 新67194成人永久网站| 99视频在线观看一区三区| 欧美高清在线视频| 亚洲国产清纯| 亚洲第一福利视频| 免费观看成人鲁鲁鲁鲁鲁视频| 国产日韩欧美亚洲一区| 午夜精品美女久久久久av福利| 99re在线精品| 欧美日韩免费观看一区| 99视频超级精品| 日韩午夜av| 欧美三级日本三级少妇99| 一级成人国产| 一区二区三区四区五区在线| 欧美日韩国产综合久久| 亚洲狼人精品一区二区三区| 欧美黄色免费| 欧美激情一级片一区二区| 日韩视频―中文字幕| 亚洲日本va午夜在线电影| 欧美日韩国产另类不卡| 亚洲一级黄色片| 亚洲午夜免费福利视频| 国产免费一区二区三区香蕉精| 欧美一级一区| 久久精品视频在线播放| 亚洲国内精品| 日韩一二三在线视频播| 国产精品一区二区三区四区五区| 欧美中在线观看| 久久亚洲综合网| 欧美日韩综合网| 欧美无砖砖区免费| 亚洲欧美日韩在线一区| 午夜精品在线| 亚洲人成人一区二区三区| 亚洲日本va午夜在线电影| 国产精品国色综合久久| 久久久蜜臀国产一区二区| 玖玖在线精品| 亚洲一区免费观看| 久久久水蜜桃av免费网站| 日韩视频久久| 亚洲欧美激情诱惑| 亚洲国产综合视频在线观看 | 亚洲你懂的在线视频| 国产主播一区二区| 最新国产の精品合集bt伙计| 国产精品网红福利| 亚洲国产精品一区二区www在线| 欧美色中文字幕| 欧美aⅴ99久久黑人专区| 欧美日韩在线播放三区四区| 久久久久久成人| 欧美日韩一区三区四区| 久久久久久综合网天天| 欧美日韩亚洲系列| 欧美aa在线视频| 国产麻豆精品久久一二三| 欧美激情aⅴ一区二区三区| 国产精品视频一二三| 最新成人av网站| 在线观看精品一区| 亚洲免费网址| 亚洲视频在线二区| 欧美成人伊人久久综合网| 欧美在线视频一区二区| 欧美二区在线播放| 免费成人在线视频网站| 国产精品久久久久久久久久久久久| 免费在线观看精品| 国产一区二区三区久久悠悠色av| 亚洲精品国产精品国自产在线| 激情久久中文字幕| 欧美亚洲日本网站| 欧美一区二区三区四区高清 | 羞羞答答国产精品www一本| 欧美成人午夜影院| 免费国产一区二区| 韩国av一区二区三区四区| 香蕉av777xxx色综合一区| 亚洲午夜91| 国产精品国产三级国产aⅴ入口| 亚洲国产第一页| 亚洲国产精品第一区二区三区| 久久精品久久综合| 老司机午夜精品| 影音先锋另类| 久久久久久久成人| 免费不卡中文字幕视频| 在线观看成人av| 久久蜜桃资源一区二区老牛| 久久五月婷婷丁香社区| 久久免费午夜影院| 亚洲国产小视频| 欧美亚洲一级| 久久精品国产成人| 国产一区二区三区久久| 欧美在线免费一级片| 久久精品亚洲一区二区| 国产日韩欧美精品一区| 久久精品国产欧美激情| 久久视频一区二区| 在线看欧美日韩| 欧美—级高清免费播放| 一区二区三区精品久久久| 午夜精品福利一区二区三区av | 国产中文一区二区| 久久久999精品免费| 欧美高清视频免费观看| 亚洲老司机av| 欧美午夜精品久久久久久孕妇| 亚洲网站在线| 久久在线视频| 日韩一级成人av| 国产精品久久久久99| 欧美主播一区二区三区| 亚洲国产激情| 亚洲欧美日韩国产综合在线| 国产一区二区三区高清播放| 另类亚洲自拍| 日韩视频国产视频| 久久久精品性| 9色精品在线| 国产午夜久久| 欧美日韩国产电影| 久久久九九九九| 一区二区av在线| 男人的天堂亚洲| 亚洲欧美另类国产| 亚洲高清久久网| 国产精一区二区三区| 女同一区二区| 欧美一级在线播放| 99精品99久久久久久宅男| 免费成人在线视频网站| 午夜日韩在线| 夜夜夜精品看看| 亚洲电影专区| 国产亚洲欧美一级| 国产精品99免费看| 免费欧美视频| 久久久久久久高潮| 亚洲欧美视频一区二区三区| 亚洲精品欧美专区| 欧美国产日韩一区二区在线观看| 亚洲欧美日韩综合| 一区二区三区久久精品| 亚洲国产另类 国产精品国产免费|