///////////////////////// 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