snake5 icon

SB3D - robot.sgs + player.sgs

snake5 | PRO | 11/05/14 10:00:14 AM UTC | 0 ⭐ | 911 👁️ | Never ⏰ | []
JavaScript |

16.54 KB

|

None

|

0 👍

/

0 👎

///////////////////////// robot.sgs //////////////////////////////
 
// ROBOT COMPONENT
// - physics
// - rendering
// - attachments
 
function Robot_init( core_mesh, pos )
{
    this.
    {
        attachments = [],
        inventory = [],
        position = vec3(pos.x,pos.y,pos.z),
        matrix = mat4(),
        
        movedir = vec2(0,0),
        turndir = vec2(1,0),
        elevation = 0.5,
        
        mi_core = mi_core = gSGR_Scene.createMeshInstance(),
        body = null,
    };
    
    this.matrix.scale(0.5,0.5,0.5).translate_v3( this.position );
    mi_core.matrix = this.matrix;
    mi_core.mesh = gSGR_GetMesh( core_mesh );
    
    sh_capsuleZ = Bullet_CreateSphereShape( 0.5 );
    rbci = Bullet_CreateRigidBodyCreationInfo();
    rbci.collisionShape = sh_capsuleZ;
    rbci.position = this.position;
    rbci.mass = 120;
    rbci.localInertia = sh_capsuleZ.calculateLocalInertia( 120 ) * vec3(0,0,1);
    rbci.friction = 0.1;
    this.body = body = Bullet_CreateRigidBody( rbci );
    body.activationState = Bullet_DISABLE_DEACTIVATION;
    body.linearDamping = 0.5;
    gSGR_BulletWorld.addRigidBody( body, 0x04 );
}
 
function Robot_destroy()
{
    gSGR_BulletWorld.removeRigidBody( this.body );
}
 
function Robot_tick( dt )
{
    movedir = this.movedir;
    this.body.clearForces();
    this.body.applyCentralImpulse( vec3(movedir.x,movedir.y,0) * 50 );
    
    this.position = this.body.position;
    this.mi_core.matrix = this.matrix = mat4().scale(0.5,0.5,0.5).rotate_quat( this.body.orientation.invert() ).translate_v3( this.position );
    foreach( atch : this.attachments )
    {
        atch.tick( this, dt );
    }
}
 
function Robot_setMoveDir( movedir ){ this.movedir = movedir; }
function Robot_setTurnDir( turndir ){ this.turndir = turndir; }
function Robot_setElevation( elev ){ this.elevation = elev; }
 
function Robot_addAttachment( code )
{
    atch_func = Robot_Attachments.(code);
    atch = this!atch_func();
    this.attachments.push( atch );
}
 
function Robot_dropAttachments( type )
{
    foreach( i, atch : this.attachments )
    {
        if( atch.type == type )
        {
        //  this!Robot_createAttachmentEntity( atch ); // TODO
            this.attachments[ i ] = null;
        }
    }
    this.attachments = array_filter( this.attachments );
}
 
function Robot_setAttachment( code )
{
    if( code.length > 0 )
        this!Robot_dropAttachments( code[0] );
    if( code.length > 1 )
        this!Robot_addAttachment( code );
}
 
 
 
 
 
global Robot_Attachments = {};
 
function Robot_Attachments.EP1()
{
    EP1 =
    {
        type = "E",
        name = "EP1",
        fullname = "Elevation, propeller-based, v1",
        
        mi_stat = mi_stat = gSGR_Scene.createMeshInstance(),
        mi_rot = mi_rot = gSGR_Scene.createMeshInstance(),
    };
    
    mi_stat.mesh = gSGR_GetMesh( "sb_EP1_stat" );
    mi_rot.mesh = gSGR_GetMesh( "sb_EP1_rot" );
    
    function EP1.transform( mtx )
    {
        this.mi_stat.matrix = mat4().translate( 0, 0, -0.67 ).multiply( mtx );
        this.mi_rot.matrix = mat4().rotateZ( ftime() ).translate( 0, 0, -0.67 ).multiply( mtx );
    }
    
    global Robot_EP1_offsets = [ vec3( 0, 0, 0 ), vec3( -1, 0, 0 ), vec3( 1, 0, 0 ), vec3( 0, -1, 0 ), vec3( 0, 1, 0 ) ];
    function EP1.tick( robot, dt )
    {
        this.transform( robot.matrix );
        
        pow_dir = vec3( 0, 0, -5 -15 * robot.elevation );
        pow_pos = robot.position + vec3( 0, 0, -0.17 );
        avgdist = 0;
        foreach( off : Robot_EP1_offsets )
        {
            (rr,cs,rn,rp) = gSGR_BulletWorld.rayTestClosest( pow_pos, pow_pos + pow_dir, 0x01, 0x01 );
            avgdist += rr ?? 1.0;
        }
        powermul = 0.2 - avgdist / Robot_EP1_offsets.size;
        
    //  htdiff = 5 - robot.body.position.z;
    //  robot.body.applyCentralImpulse( vec3(0,0,htdiff) * 50 - robot.body.linearVelocity * 0.9 );
        
        if( powermul > 0 )
            robot.body.applyCentralImpulse( -pow_dir * powermul * 2000 * dt - robot.body.linearVelocity * 0.99 );
    //  if( powermul > 0 )
    //      robot.body.applyCentralForce( -pow_dir * ( 120 + powermul * 50 ) );
    }
    
    return EP1;
}
 
function Robot_Attachments.SP1()
{
    SP1 =
    {
        type = "S",
        name = "SP1",
        fullname = "Steering, propeller-based, v1",
        
        mi_statL = mi_statL = gSGR_Scene.createMeshInstance(),
        mi_statR = mi_statR = gSGR_Scene.createMeshInstance(),
        mi_rotL = mi_rotL = gSGR_Scene.createMeshInstance(),
        mi_rotR = mi_rotR = gSGR_Scene.createMeshInstance(),
    };
    
    mi_statL.mesh = gSGR_GetMesh( "sb_SP1_lft" );
    mi_statR.mesh = gSGR_GetMesh( "sb_SP1_rgt" );
    mi_rotR.mesh = mi_rotL.mesh = gSGR_GetMesh( "sb_SP1_rot" );
    
    function SP1.transform( mtx )
    {
        this.mi_statL.matrix = mat4().translate( 1.90796, 0.12344, 0.04181 ).multiply( mtx );
        this.mi_rotL.matrix = mat4().rotateY( ftime() ).translate( 1.96693, 0.12344, 0.04181 ).multiply( mtx );
        this.mi_statR.matrix = mat4().translate( -1.90796, 0.12344, 0.04181 ).multiply( mtx );
        this.mi_rotR.matrix = mat4().rotateY( ftime() ).translate( -1.90796, 0.12344, 0.04181 ).multiply( mtx );
    }
    
    function SP1.tick( robot, dt )
    {
        this.transform( robot.matrix );
        
        vcur = vec2( robot.body.orientation.invert().mat3.transform( vec3(0,-1,0) ) );
        vtgt = robot.turndir;
        powermul = acos( min( 1, vec2_dot( vcur, vtgt ) ) ) * if( vcur.x * vtgt.y - vtgt.x * vcur.y > 0, 1, -1 );
        robot.body.applyTorqueImpulse( vec3(0,0,powermul*3 - robot.body.angularVelocity.z * 0.99) );
    }
    
    return SP1;
}
 
function Robot_Attachments.WT1()
{
    WT1 =
    {
        type = "W",
        name = "WT1",
        fullname = "Weapon, turret, v1",
        
        mi_stat = mi_stat = gSGR_Scene.createMeshInstance(),
        mi_rot = mi_rot = gSGR_Scene.createMeshInstance(),
    };
    
    mi_stat.mesh = gSGR_GetMesh( "sb_WT1_stat" );
    mi_rot.mesh = gSGR_GetMesh( "sb_WT1_rot" );
    
    function WT1.transform( mtx )
    {
        this.mi_stat.matrix = mat4().translate( 0, -0.40267, 0.63235 ).multiply( mtx );
        this.mi_rot.matrix = mat4().translate( 0, -0.22267, 1.03222 ).multiply( mtx );
    }
    
    function WT1.tick( robot, dt )
    {
        this.transform( robot.matrix );
    }
    
    return WT1;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
///////////////////////// player.sgs //////////////////////////
 
function ENTITY_CREATE_player( params )
{
    Player =
    {
        direction = @params.direction.normalized || vec3( 0, 1, 0 ),
        camera = null,
        cam_angle = 0.0,
        cam_zangle = 0.0,
        cam_ignoreOnce = true,
        move_noclip = false,
        
        health = 20,
        
        hint_text = null,
        hint_time = 0,
        use_info = [],
        use_index = null,
        
        tgt_elevation = 0.5,
        elev_change_timeout = 0,
    };
    Player.cam_angle = vec2(Player.direction.x,Player.direction.y).angle;
    
    Player!Robot_init( "sb_core", params.position );
    Player!Robot_addAttachment( "EP1" );
    Player!Robot_addAttachment( "SP1" );
    Player!Robot_addAttachment( "WT1" );
    
    gSGR_Actions.add_action( "move_fwd" );
    gSGR_Actions.add_action( "move_lft" );
    gSGR_Actions.add_action( "move_bwd" );
    gSGR_Actions.add_action( "move_rgt" );
    gSGR_Actions.add_action( "enable_noclip" );
    gSGR_Actions.add_action( "elev_raise" );
    gSGR_Actions.add_action( "elev_lower" );
    gSGR_Actions.add_action( "use" );
    
    gSGR_Actions.add_default_binding( "move_fwd", SDLK_W );
    gSGR_Actions.add_default_binding( "move_lft", SDLK_A );
    gSGR_Actions.add_default_binding( "move_bwd", SDLK_S );
    gSGR_Actions.add_default_binding( "move_rgt", SDLK_D );
//  gSGR_Actions.add_default_binding( "elev_raise", "scrollup" );
//  gSGR_Actions.add_default_binding( "elev_lower", "scrolldown" );
    gSGR_Actions.add_default_binding( "elev_raise", SDLK_UP );
    gSGR_Actions.add_default_binding( "elev_lower", SDLK_DOWN );
    gSGR_Actions.add_default_binding( "use", SDLK_E );
    gSGR_Actions.add_default_binding( "enable_noclip", SDLK_N );
    
    Player.ui_font = SS_CreateFont( "fonts/gauge-heavy.ttf", gSGR_Window.height / 30 );
    Player.ui_font_2 = SS_CreateFont( "fonts/gauge-heavy.ttf", gSGR_Window.height / 50 );
    
    function Player.added()
    {
        this.camera = camera = SS3D_CreateCamera();
        gSGR_Scene.camera = camera;
        global PLAYER = this;
        
        this.camera.angle = 90;
        this.camera.znear = 0.01;
        this.camera.zfar = 1000;
    }
    
    function Player.removed()
    {
        global PLAYER = null;
        this!Robot_destroy();
    }
    
    function Player.serialize()
    {
        innerdata =
        {
            cam_angle = this.cam_angle,
            cam_zangle = this.cam_zangle,
            cam_ignoreOnce = this.cam_ignoreOnce,
            move_noclip = this.move_noclip,
            
            health = this.health,
        };
        p = this.position;
        return "player", { x = p.x, y = p.y, z = p.z, direction = this.direction }, innerdata;
    }
    
    function Player.can_reuse( type, params, data )
    {
        return type == "player";
    }
    
    function Player.unserialize( data )
    {
        this.
        {
            cam_angle = data.cam_angle,
            cam_zangle = data.cam_zangle,
            cam_ignoreOnce = data.cam_ignoreOnce,
            move_noclip = data.move_noclip,
            
            health = data.health,
        };
    }
    
    function Player.updateHint( text )
    {
        this.hint_text = text;
        this.hint_time = 2.1;
    }
    
    function Player.updateDirection( mmspeed )
    {
        joyviewaxis = vec2( toreal( @gSGR_Keys[ "joyaxis2" ] ), toreal( @gSGR_Keys[ "joyaxis4" ] ) );
        viewmove = gSGR_MouseMove + joyviewaxis * 5;
        
        if( viewmove.length && !current_cutscene )
        {
            if( !this.cam_ignoreOnce && !Game.PrevPaused )
            {
                this.cam_angle -= viewmove.x * mmspeed;
                this.cam_zangle -= viewmove.y * mmspeed;
            }
            else this.cam_ignoreOnce = false;
        }
        
        
        this.cam_zangle = clamp( this.cam_zangle, -M_PI*0.49, M_PI*0.49 );
        
        cos_angle = cos( this.cam_angle );
        sin_angle = sin( this.cam_angle );
        cos_zangle = cos( this.cam_zangle );
        sin_zangle = sin( this.cam_zangle );
        this.direction = vec3( cos_angle * cos_zangle, sin_angle * cos_zangle, sin_zangle );
    }
    
    function Player.updateNoclip( dt )
    {
        this.updateDirection( 0.02 );
        cos_angle = cos( this.cam_angle );
        sin_angle = sin( this.cam_angle );
        cos_zangle = cos( this.cam_zangle );
        sin_zangle = sin( this.cam_zangle );
        dir = this.direction;
        right = vec3( sin_angle, -cos_angle, 0 );
        speed = 10;
    //  if( gSGR_Actions.get( "move_faster" ) ) speed *= 5;
        if( gSGR_Actions.get( "move_fwd" ) ) this.position += dir * dt * speed;
        if( gSGR_Actions.get( "move_bwd" ) ) this.position -= dir * dt * speed;
        if( gSGR_Actions.get( "move_rgt" ) ) this.position += right * dt * speed;
        if( gSGR_Actions.get( "move_lft" ) ) this.position -= right * dt * speed;
    }
    
    function Player.updateMovement( dt )
    {
        if( this.health <= 0 )
            return;
        
        this.updateDirection( 0.01 );
        
        this!Robot_setTurnDir( vec2(this.direction.x,this.direction.y) );
        
        speed = 2000;
        
        cos_angle = cos( this.cam_angle );
        sin_angle = sin( this.cam_angle );
        fwdir = vec2( cos_angle, sin_angle );
        right = vec2( sin_angle, -cos_angle );
        
        if( !current_cutscene )
        {
            movedir = vec2(0,0);
            if( gSGR_Actions.get( "move_fwd" ) ) movedir += fwdir;
            if( gSGR_Actions.get( "move_bwd" ) ) movedir -= fwdir;
            if( gSGR_Actions.get( "move_rgt" ) ) movedir += right;
            if( gSGR_Actions.get( "move_lft" ) ) movedir -= right;
            if( @gSGR_Keys[ "joyaxis0" ] ) movedir += right * gSGR_Keys[ "joyaxis0" ];
            if( @gSGR_Keys[ "joyaxis1" ] ) movedir -= fwdir * gSGR_Keys[ "joyaxis1" ];
            movedir = movedir.normalized;
            
            this!Robot_setMoveDir( movedir );
        }
    }
    
    function Player.updateCamera()
    {
        if( current_cutscene )
            return;
        
        this.camera.position = this.position - this.direction * 2 + vec3(0,0,0.3);
        this.camera.direction = this.direction;
        this.camera.aspect = gSGR_Window.width / gSGR_Window.height;
    }
    
    function Player.hit()
    {
        this.health -= 2;
    }
    
    function Player.isInAction()
    {
        foreach( osc : Game.OverlayScreens )
            if( @osc.wdi )
                return true;
        return false;
    }
    
    function Player.updateUseInfo()
    {
        this.use_info = use_info = QueryInteractive( 10 );
        best_idx = null;
        best_q = 99999;
        foreach( i, ui_item : use_info )
        {
            dist = ( ui_item.pos - this.position ).length;
            if( dist < 2 )
            {
                cur_q = ui_item.area + ui_item.dist + dist;
                if( cur_q < best_q )
                {
                    best_q = cur_q;
                    best_idx = i;
                }
            }
        }
        this.use_index = best_idx;
    }
    
    function Player.tick( dt )
    {
        this!Robot_tick( dt );
        
        if( this.health > 0 )
            this.updateUseInfo();
        
        in_action = this.isInAction();
        if( !in_action )
        {
            if( gSGR_Actions.is_pressed( "enable_noclip" ) )
                this.move_noclip = !this.move_noclip;
            
            if( gSGR_Actions.is_pressed( "use" ) || ( (@gSGR_Keys[ "joybtn0" ]) && !(@gSGR_PrevKeys[ "joybtn0" ]) ) )
            {
                if( this.use_index !== null )
                {
                    ent = this.use_info[ this.use_index ].ent;
                    if( @ent.interact )
                        ent.interact();
                }
            }
        }
        
        if( this.elev_change_timeout > 0 )
            this.elev_change_timeout -= dt;
        else if( !in_action )
        {
            if( gSGR_Actions.get( "elev_raise" ) || gSGR_Actions.get( "elev_lower" ) || @gSGR_Keys[ "joyhatup" ] || @gSGR_Keys[ "joyhatdn" ] )
            {
                this.tgt_elevation += 0.05 * ( !!gSGR_Actions.get( "elev_raise" ) - !!gSGR_Actions.get( "elev_lower" ) + !!(@gSGR_Keys[ "joyhatup" ]) - !!(@gSGR_Keys[ "joyhatdn" ]) );
                this.elev_change_timeout = 0.2;
            }
            this!Robot_setElevation( this.tgt_elevation );
        }
        
        if( !in_action )
        {
            if( this.move_noclip )
                this.updateNoclip( dt );
            else
                this.updateMovement( dt );
        }
        
        p = this.position;
        
        if( @gSGR_Keys[ SDLK_0 ] )
            this.health = 0;
        
        if( this.health <= 0 )
        {
            this.death_timeout -= dt;
            if( this.death_timeout <= 0 )
            {
                Game.SetPaused( true );
                Game.OverlayScreens.push( PauseScreen );
            }
        }
        
        this.updateCamera();
        
        if( this.hint_time > 0 )
            this.hint_time -= dt;
    }
    
    function Player.draw_ui()
    {
        W = gSGR_Window.width;
        H = gSGR_Window.height;
        
        if( current_cutscene || mission_complete )
            return;
        
        if( this.hint_time > 0 )
        {
            SS_DrawTextRect( this.hint_text, this.ui_font, color(1,clamp(this.hint_time,0,1)), DT_CENTER | DT_VCENTER, W*1/4, W*3/4, H*2/4, H*3/4 );
        }
        
        if( intlist = this.use_info )
        {
            bsz = ceil( min( W, H ) / 60 );
            sqsz = ceil( min( W, H ) / 300 );
            hsqsz = sqsz / 2;
            foreach( idx, intitem : intlist )
            {
                aabb = intitem.aabb;
                
                if( this.use_index === idx ){ cr = 0.9; cg = 0.1; cb = 0.0; ca = 0.8; }
                else { cr = 0.3; cg = 0.7; cb = 0.9; ca = 0.8; }
                
                SS_DrawColorRect( aabb.x1 - hsqsz + 1, aabb.y1 - hsqsz + 1, aabb.x1 + bsz + hsqsz + 1, aabb.y1 + hsqsz + 1, 0.1, 0.1, 0.1, 0.8 );
                SS_DrawColorRect( aabb.x1 - hsqsz + 1, aabb.y1 + hsqsz + 1, aabb.x1 + hsqsz + 1, aabb.y1 + bsz + hsqsz + 1, 0.1, 0.1, 0.1, 0.8 );
                SS_DrawColorRect( aabb.x2 - bsz - hsqsz + 1, aabb.y2 - hsqsz + 1, aabb.x2 + hsqsz + 1, aabb.y2 + hsqsz + 1, 0.1, 0.1, 0.1, 0.8 );
                SS_DrawColorRect( aabb.x2 - hsqsz + 1, aabb.y2 - bsz - hsqsz + 1, aabb.x2 + hsqsz + 1, aabb.y2 - hsqsz + 1, 0.1, 0.1, 0.1, 0.8 );
                SS_DrawTextLine_BL( intitem.name, this.ui_font_2, aabb.x1 + 1, aabb.y1 - 1, color(0.1,0.1,0.1,0.8) );
                
                text = intitem.name;
                if( this.use_index === idx )
                {
                    SS_DrawColorRect( aabb.x1, aabb.y1, aabb.x2, aabb.y2, cr, cg, cb, 0.3 );
                    text = "[Press Button 1] " $ text;
                }
                SS_DrawColorRect( aabb.x1 - hsqsz, aabb.y1 - hsqsz, aabb.x1 + bsz + hsqsz, aabb.y1 + hsqsz, cr, cg, cb, ca );
                SS_DrawColorRect( aabb.x1 - hsqsz, aabb.y1 + hsqsz, aabb.x1 + hsqsz, aabb.y1 + bsz + hsqsz, cr, cg, cb, ca );
                SS_DrawColorRect( aabb.x2 - bsz - hsqsz, aabb.y2 - hsqsz, aabb.x2 + hsqsz, aabb.y2 + hsqsz, cr, cg, cb, ca );
                SS_DrawColorRect( aabb.x2 - hsqsz, aabb.y2 - bsz - hsqsz, aabb.x2 + hsqsz, aabb.y2 - hsqsz, cr, cg, cb, ca );
                
                SS_DrawTextLine_BL( text, this.ui_font_2, aabb.x1, aabb.y1 - 2, color(0.9,0.9,0.9,0.8) );
                
        //      SS_DrawColorRect( aabb.x1, aabb.y1, aabb.x2, aabb.y2, 0.2, 0.4, 0.6, 0.5 );
            }
    //      SS_DrawTextLine( "Press E to "$act, this.ui_font, W - unit*20, unit*3, color(1,1) );
        }
        
        unit = H / 30;
        SS_DrawTextLine( "HEALTH: " $ string_repeat( "|", max( 0, this.health ) ), this.ui_font, unit*3, unit*3, color(1,1) );
        
        SS_DrawTextLine( "ELEVATION: " $ string_repeat( "|", 20 ), this.ui_font, unit*3, unit*5, color(0.1,1) );
        SS_DrawTextLine( "ELEVATION: " $ string_repeat( "|", max( 0, this.tgt_elevation * 20 ) ), this.ui_font, unit*3, unit*5, color(0.3,0.6,0.9,1) );
        
    //  rr = gSGR_BulletWorld.rayTestClosest( this.position, this.position + this.direction * 5 );
    //  SS_DrawTextLine( "RAYCAST: "$rr, gSGR_DefaultFont, 100, 100, color(1,1) );
        
        if( time_since_saved < 3 )
        {
            SS_DrawTextLine( "Game saved!", this.ui_font, W / 3, unit, color(1,1-time_since_saved/3) );
        }
        
        if( max_see_time > 0 )
        {
            text = if( max_see_time >= 1, "TURRET ALERT!", "TURRET ALERT" );
            SS_DrawTextLine( text, this.ui_font, W / 2 - unit * 4, unit * 3, color(1,0.1,0.05,1) );
        }
    }
    
    return Player;
}

Comments