2023-11-07 12:45:52 -06:00
var actor = { } ;
2023-11-29 12:40:13 -06:00
actor . spawn = function ( script , config ) {
if ( typeof script !== 'string' ) return ;
var padawan = Object . create ( actor ) ;
compile _env ( script , padawan , "script" ) ;
2023-11-07 12:45:52 -06:00
2023-11-29 12:40:13 -06:00
if ( typeof config === 'object' )
Object . merge ( padawan , config ) ;
2023-11-29 17:31:41 -06:00
padawan . padawans = [ ] ;
padawan . timers = [ ] ;
padawan . master = this ;
Object . hide ( padawan , "master" , "timers" ) ;
this . padawans . push ( padawan ) ;
2023-11-29 12:40:13 -06:00
return padawan ;
} ;
actor . die = function ( actor ) {
} ;
2023-11-29 17:31:41 -06:00
actor . timers = [ ] ;
actor . kill = function ( ) {
this . timers . forEach ( t => t . kill ( ) ) ;
this . master . remove ( this ) ;
this . padawans . forEach ( p => p . kill ( ) ) ;
this . _ _dead _ _ = true ;
2023-11-29 12:40:13 -06:00
} ;
2023-11-29 17:31:41 -06:00
actor . toJSON = function ( ) {
if ( this . _ _dead _ _ ) return undefined ;
return this ;
}
2023-11-29 12:40:13 -06:00
actor . delay = function ( fn , seconds ) {
2023-11-29 17:31:41 -06:00
var t = Object . create ( timer ) ;
t . remain = seconds ;
t . kill = ( ) => {
timer . kill . call ( t ) ;
this . timers . remove ( t ) ;
}
t . fire = ( ) => {
if ( this . _ _dead _ _ ) return ;
fn ( ) ;
t . kill ( ) ;
} ;
Register . appupdate . register ( t . update , t ) ;
2023-11-29 12:40:13 -06:00
this . timers . push ( t ) ;
return function ( ) { t . kill ( ) ; } ;
} ;
actor . clock = function ( fn ) { } ;
2023-11-29 17:31:41 -06:00
actor . master = undefined ;
actor . padawans = [ ] ;
actor . remaster = function ( to ) {
this . master . padawans . remove ( this ) ;
this . master = to ;
to . padawans . push ( this ) ;
} ;
2023-11-27 14:29:55 -06:00
2023-09-08 12:35:06 -05:00
var gameobject = {
2023-11-29 12:40:13 -06:00
full _path ( ) {
return this . path _from ( Primum ) ;
} ,
2023-10-17 12:22:06 -05:00
path _from ( o ) {
var p = this . toString ( ) ;
var c = this . level ;
while ( c && c !== o && c !== Primum ) {
p = c . toString ( ) + "." + p ;
c = c . level ;
}
if ( c === Primum ) p = "Primum." + p ;
return p ;
} ,
2023-10-06 12:38:49 -05:00
clear ( ) {
2023-10-16 09:40:43 -05:00
for ( var k in this . objects ) {
Log . info ( ` Killing ${ k } ` ) ;
this . objects [ k ] . kill ( ) ;
} ;
2023-10-06 12:38:49 -05:00
this . objects = { } ;
} ,
2023-11-07 12:45:52 -06:00
delay ( fn , seconds ) {
2023-11-17 15:16:13 -06:00
var t = timer . delay ( fn . bind ( this ) , seconds , false ) ;
2023-11-29 12:40:13 -06:00
var killfn = function ( ) { t . kill ( ) ; } ;
this . timers . push ( killfn ) ;
return killfn ;
2023-11-17 15:16:13 -06:00
} ,
tween ( prop , values , def ) {
var t = Tween . make ( this , prop , values , def ) ;
t . play ( ) ;
var k = function ( ) { t . pause ( ) ; }
this . timers . push ( k ) ;
return k ;
} ,
cry ( file ) {
2023-11-27 14:29:55 -06:00
var p = Sound . play ( file , Sound . bus . sfx ) ;
var killfn = p . kill . bind ( p ) ;
2023-11-27 17:04:04 -06:00
p . end = killfn ;
2023-11-27 14:29:55 -06:00
this . timers . push ( killfn ) ;
return killfn ;
2023-11-07 12:45:52 -06:00
} ,
2023-11-06 07:05:27 -06:00
set max _velocity ( x ) { cmd ( 151 , this . body , x ) ; } ,
get max _velocity ( ) { return cmd ( 152 , this . body ) ; } ,
set max _angularvelocity ( x ) { cmd ( 154 , this . body , Math . deg2rad ( x ) ) ; } ,
get max _angularvelocity ( ) { return Math . rad2deg ( cmd ( 155 , this . body ) ) ; } ,
set torque ( x ) { if ( ! ( x >= 0 && x <= Infinity ) ) return ; cmd ( 153 , this . body , x ) ; } ,
2023-10-06 12:38:49 -05:00
gscale ( ) { return cmd ( 103 , this . body ) ; } ,
2023-11-14 09:20:09 -06:00
sgscale ( x ) {
if ( typeof x === 'number' )
2023-11-15 16:42:39 -06:00
x = [ x , x ] ;
cmd ( 36 , this . body , x )
2023-11-14 09:20:09 -06:00
} ,
2023-10-06 12:38:49 -05:00
get scale ( ) {
if ( ! this . level ) return this . gscale ( ) ;
2023-11-15 16:42:39 -06:00
return this . gscale ( ) . map ( ( x , i ) => x / this . level . gscale ( ) [ i ] ) ;
2023-10-06 12:38:49 -05:00
} ,
2023-09-21 08:38:23 -05:00
set scale ( x ) {
2023-11-15 16:42:39 -06:00
if ( typeof x === 'number' )
x = [ x , x ] ;
if ( this . level ) {
var g = this . level . gscale ( ) ;
x = x . map ( ( y , i ) => y * g [ i ] ) ;
}
2023-11-14 09:20:09 -06:00
2023-11-15 16:42:39 -06:00
var pct = x . map ( function ( y , i ) { return y / this . gscale ( ) [ i ] ; } , this ) ;
2023-09-21 08:38:23 -05:00
2023-11-15 16:42:39 -06:00
this . sgscale ( x ) ;
/* TRANSLATE ALL SUB OBJECTS */
2023-09-21 08:38:23 -05:00
} ,
2023-10-04 17:57:37 -05:00
set pos ( x ) {
2023-11-29 12:40:13 -06:00
if ( ! this . level )
this . set _worldpos ( x ) ;
else
this . set _worldpos ( this . level . this2world ( x ) ) ;
2023-10-04 17:57:37 -05:00
} ,
2023-10-05 13:33:43 -05:00
2023-10-02 07:58:17 -05:00
get pos ( ) {
2023-10-26 11:48:02 -05:00
if ( ! this . level ) return this . worldpos ( ) ;
2023-11-15 16:42:39 -06:00
return this . level . world2this ( this . worldpos ( ) ) ;
2023-10-02 07:58:17 -05:00
} ,
2023-11-21 01:07:50 -06:00
get draw _layer ( ) { return cmd ( 171 , this . body ) ; } ,
set draw _layer ( x ) { cmd ( 172 , this . body , x ) ; } ,
2023-11-15 16:42:39 -06:00
2023-10-04 17:57:37 -05:00
get elasticity ( ) { return cmd ( 107 , this . body ) ; } ,
set elasticity ( x ) { cmd ( 106 , this . body , x ) ; } ,
2023-10-02 07:58:17 -05:00
2023-10-04 17:57:37 -05:00
get friction ( ) { return cmd ( 109 , this . body ) ; } ,
set friction ( x ) { cmd ( 108 , this . body , x ) ; } ,
set mass ( x ) { set _body ( 7 , this . body , x ) ; } ,
get mass ( ) {
if ( ! ( this . phys === Physics . dynamic ) )
return this . _ _proto _ _ . mass ;
return q _body ( 5 , this . body ) ;
} ,
2023-11-06 07:05:27 -06:00
set gravity ( x ) { cmd ( 158 , this . body , x ) ; } ,
get gravity ( ) { return cmd ( 159 , this . body ) ; } ,
2023-11-20 07:49:14 -06:00
set _gravity ( x ) { cmd ( 167 , this . body , x ) ; } ,
set timescale ( x ) { cmd ( 168 , this . body , x ) ; } ,
get timescale ( ) { return cmd ( 169 , this . body ) ; } ,
2023-10-04 17:57:37 -05:00
2023-11-29 17:31:41 -06:00
set phys ( x ) { console . warn ( ` Setting phys to ${ x } ` ) ; set _body ( 1 , this . body , x ) ; } ,
2023-10-04 17:57:37 -05:00
get phys ( ) { return q _body ( 0 , this . body ) ; } ,
get velocity ( ) { return q _body ( 3 , this . body ) ; } ,
set velocity ( x ) { set _body ( 9 , this . body , x ) ; } ,
2023-11-29 12:40:13 -06:00
get damping ( ) { return cmd ( 157 , this . body ) ; } ,
2023-11-20 07:49:14 -06:00
set _damping ( x ) { cmd ( 156 , this . body , x ) ; } ,
2023-10-04 17:57:37 -05:00
get angularvelocity ( ) { return Math . rad2deg ( q _body ( 4 , this . body ) ) ; } ,
set angularvelocity ( x ) { set _body ( 8 , this . body , Math . deg2rad ( x ) ) ; } ,
2023-10-02 17:03:01 -05:00
worldpos ( ) { return q _body ( 1 , this . body ) ; } ,
set _worldpos ( x ) {
2023-11-15 16:42:39 -06:00
var poses = this . objects . map ( x => x . pos ) ;
2023-10-02 07:58:17 -05:00
set _body ( 2 , this . body , x ) ;
2023-11-15 16:42:39 -06:00
this . objects . forEach ( ( o , i ) => o . set _worldpos ( this . this2world ( poses [ i ] ) ) ) ;
2023-09-25 16:34:48 -05:00
} ,
2023-09-14 17:37:04 -05:00
2023-10-05 17:30:17 -05:00
worldangle ( ) { return Math . rad2deg ( q _body ( 2 , this . body ) ) % 360 ; } ,
2023-10-26 11:48:02 -05:00
sworldangle ( x ) { set _body ( 0 , this . body , Math . deg2rad ( x ) ) ; } ,
2023-10-05 17:30:17 -05:00
get angle ( ) {
if ( ! this . level ) return this . worldangle ( ) ;
return this . worldangle ( ) - this . level . worldangle ( ) ;
} ,
2023-09-21 08:38:23 -05:00
set angle ( x ) {
var diff = x - this . angle ;
2023-10-05 13:33:43 -05:00
var thatpos = this . pos ;
2023-09-21 08:38:23 -05:00
this . objects . forEach ( function ( x ) {
2023-10-05 17:30:17 -05:00
x . rotate ( diff ) ;
var opos = x . pos ;
var r = Vector . length ( opos ) ;
var p = Math . rad2deg ( Math . atan2 ( opos . y , opos . x ) ) ;
2023-09-21 08:38:23 -05:00
p += diff ;
p = Math . deg2rad ( p ) ;
2023-10-05 17:30:17 -05:00
x . pos = [ r * Math . cos ( p ) , r * Math . sin ( p ) ] ;
2023-10-26 11:48:02 -05:00
} ) ;
2023-11-29 12:40:13 -06:00
if ( this . level )
set _body ( 0 , this . body , Math . deg2rad ( x - this . level . worldangle ( ) ) ) ;
else
set _body ( 0 , this . body , x ) ;
2023-10-05 17:30:17 -05:00
} ,
rotate ( x ) {
2023-10-26 11:48:02 -05:00
this . sworldangle ( this . worldangle ( ) + x ) ;
2023-09-21 08:38:23 -05:00
} ,
2023-10-02 17:03:01 -05:00
2023-10-10 17:37:58 -05:00
spawn _from _instance ( inst ) {
2023-10-11 17:22:41 -05:00
return this . spawn ( inst . ur , inst ) ;
2023-10-10 17:37:58 -05:00
} ,
2023-10-11 17:22:41 -05:00
2023-10-10 17:37:58 -05:00
spawn ( ur , data ) {
2023-09-19 12:35:12 -05:00
if ( typeof ur === 'string' )
ur = prototypes . get _ur ( ur ) ;
2023-10-02 07:58:17 -05:00
if ( ! ur ) {
2023-10-18 17:20:23 -05:00
Log . error ( "Failed to make UR from " + ur ) ;
2023-10-02 07:58:17 -05:00
return undefined ;
}
2023-10-10 17:37:58 -05:00
var go = ur . make ( this , data ) ;
2023-10-26 11:48:02 -05:00
Object . hide ( this , go . toString ( ) ) ;
2023-10-02 07:58:17 -05:00
return go ;
2023-09-19 12:35:12 -05:00
} ,
2023-10-10 17:37:58 -05:00
/* Reparent 'this' to be 'parent's child */
2023-10-04 17:57:37 -05:00
reparent ( parent ) {
if ( this . level === parent )
2023-10-10 17:37:58 -05:00
return ;
this . level ? . remove _obj ( this ) ;
2023-10-04 17:57:37 -05:00
this . level = parent ;
2023-10-10 17:37:58 -05:00
function unique _name ( list , obj ) {
var str = obj . toString ( ) . replaceAll ( '.' , '_' ) ;
var n = 1 ;
var t = str ;
2023-10-17 12:22:06 -05:00
while ( t in list ) {
2023-10-10 17:37:58 -05:00
t = str + n ;
n ++ ;
}
return t ;
} ;
2023-10-17 12:22:06 -05:00
var name = unique _name ( parent , this . ur ) ;
2023-10-10 17:37:58 -05:00
parent . objects [ name ] = this ;
2023-10-17 12:22:06 -05:00
parent [ name ] = this ;
2023-10-10 17:37:58 -05:00
this . toString = function ( ) { return name ; } ;
2023-10-04 17:57:37 -05:00
} ,
2023-10-10 17:37:58 -05:00
2023-10-04 17:57:37 -05:00
remove _obj ( obj ) {
2023-10-10 17:37:58 -05:00
if ( this [ obj . toString ( ) ] === this . objects [ obj . toString ( ) ] )
delete this [ obj . toString ( ) ] ;
delete this . objects [ obj . toString ( ) ] ;
2023-10-17 12:22:06 -05:00
delete this [ obj . toString ( ) ] ;
2023-10-04 17:57:37 -05:00
} ,
2023-10-10 17:37:58 -05:00
components : { } ,
objects : { } ,
2023-10-04 17:57:37 -05:00
level : undefined ,
2023-11-06 07:05:27 -06:00
get _moi ( ) { return q _body ( 6 , this . body ) ; } ,
set _moi ( x ) {
if ( x <= 0 ) {
Log . error ( "Cannot set moment of inertia to 0 or less." ) ;
return ;
}
set _body ( 13 , this . body , x ) ;
} ,
2023-10-04 17:57:37 -05:00
2023-10-26 11:48:02 -05:00
pulse ( vec ) { set _body ( 4 , this . body , vec ) ; } ,
shove ( vec ) { set _body ( 12 , this . body , vec ) ; } ,
2023-11-06 07:05:27 -06:00
shove _at ( vec , at ) { set _body ( 14 , this . body , vec , at ) ; } ,
2023-10-26 11:48:02 -05:00
world2this ( pos ) { return cmd ( 70 , this . body , pos ) ; } ,
this2world ( pos ) { return cmd ( 71 , this . body , pos ) ; } ,
2023-11-16 09:27:04 -06:00
dir _world2this ( dir ) { return cmd ( 160 , this . body , dir ) ; } ,
dir _this2world ( dir ) { return cmd ( 161 , this . body , dir ) ; } ,
2023-10-26 11:48:02 -05:00
set layer ( x ) { cmd ( 75 , this . body , x ) ; } ,
2023-11-07 17:24:26 -06:00
get layer ( ) { cmd ( 77 , this . body ) ; } ,
2023-10-26 11:48:02 -05:00
alive ( ) { return this . body >= 0 ; } ,
in _air ( ) { return q _body ( 7 , this . body ) ; } ,
2023-10-04 17:57:37 -05:00
hide ( ) { this . components . forEach ( function ( x ) { x . hide ( ) ; } ) ; this . objects . forEach ( function ( x ) { x . hide ( ) ; } ) ; } ,
show ( ) { this . components . forEach ( function ( x ) { x . show ( ) ; } ) ; this . objects . forEach ( function ( x ) { x . show ( ) ; } ) ; } ,
get _relangle ( ) {
if ( ! this . level ) return this . angle ;
return this . angle - this . level . angle ;
} ,
width ( ) {
var bb = this . boundingbox ( ) ;
return bb . r - bb . l ;
} ,
height ( ) {
var bb = this . boundingbox ( ) ;
return bb . t - bb . b ;
} ,
2023-10-09 13:03:12 -05:00
move ( vec ) {
this . pos = this . pos . add ( vec ) ;
} ,
rotate ( amt ) {
this . angle += amt ;
} ,
2023-10-04 17:57:37 -05:00
/* Make a unique object the same as its prototype */
revert ( ) {
2023-11-29 12:40:13 -06:00
// var keys = Object.samenewkeys(this, this.__proto__);
// keys.unique.forEach(x => delete this[x]);
// keys.same.forEach(x => this[x] = this.__proto__[x]);
2023-10-30 17:41:32 -05:00
var jobj = this . json _obj ( ) ;
2023-11-16 09:27:04 -06:00
var lobj = this . level . _ _proto _ _ . objects [ this . toString ( ) ] ;
2023-10-30 17:41:32 -05:00
delete jobj . objects ;
Object . keys ( jobj ) . forEach ( function ( x ) {
2023-11-16 09:27:04 -06:00
if ( lobj && x in lobj )
this [ x ] = lobj [ x ] ;
else
this [ x ] = this . _ _proto _ _ [ x ] ;
2023-10-30 17:41:32 -05:00
} , this ) ;
2023-10-10 17:37:58 -05:00
this . sync ( ) ;
2023-10-04 17:57:37 -05:00
} ,
check _registers ( obj ) {
Register . unregister _obj ( obj ) ;
if ( typeof obj . update === 'function' )
Register . update . register ( obj . update , obj ) ;
if ( typeof obj . physupdate === 'function' )
Register . physupdate . register ( obj . physupdate , obj ) ;
if ( typeof obj . collide === 'function' )
obj . register _hit ( obj . collide , obj ) ;
if ( typeof obj . separate === 'function' )
obj . register _separate ( obj . separate , obj ) ;
if ( typeof obj . draw === 'function' )
Register . draw . register ( obj . draw , obj ) ;
if ( typeof obj . debug === 'function' )
Register . debug . register ( obj . debug , obj ) ;
2023-11-07 12:45:52 -06:00
if ( typeof obj . gui === 'function' )
Register . gui . register ( obj . gui , obj ) ;
2023-11-22 03:51:43 -06:00
for ( var k in obj ) {
if ( ! k . startswith ( "on_" ) ) continue ;
var signal = k . fromfirst ( "on_" ) ;
Event . observe ( signal , obj , obj [ k ] ) ;
} ;
2023-10-04 17:57:37 -05:00
obj . components . forEach ( function ( x ) {
if ( typeof x . collide === 'function' )
register _collide ( 1 , x . collide , x , obj . body , x . shape ) ;
} ) ;
} ,
2023-11-29 12:40:13 -06:00
2023-11-15 16:42:39 -06:00
flipx ( ) { return this . scale . x < 0 ; } ,
flipy ( ) { return this . scale . y < 0 ; } ,
mirror ( plane ) {
this . scale = Vector . reflect ( this . scale , plane ) ;
} ,
2023-10-04 17:57:37 -05:00
save : true ,
selectable : true ,
ed _locked : false ,
2023-11-29 12:40:13 -06:00
disable ( ) { this . components . forEach ( function ( x ) { x . disable ( ) ; } ) ; } ,
enable ( ) { this . components . forEach ( function ( x ) { x . enable ( ) ; } ) ; } ,
sync ( ) {
this . components . forEach ( function ( x ) { x . sync ( ) ; } ) ;
this . objects . forEach ( function ( x ) { x . sync ( ) ; } ) ;
} ,
2023-10-04 17:57:37 -05:00
2023-09-19 12:35:12 -05:00
/* Bounding box of the object in world dimensions */
boundingbox ( ) {
var boxes = [ ] ;
boxes . push ( { t : 0 , r : 0 , b : 0 , l : 0 } ) ;
for ( var key in this . components ) {
if ( 'boundingbox' in this . components [ key ] )
boxes . push ( this . components [ key ] . boundingbox ( ) ) ;
}
2023-09-29 13:16:59 -05:00
for ( var key in this . objects )
boxes . push ( this . objects [ key ] . boundingbox ( ) ) ;
2023-09-19 12:35:12 -05:00
if ( boxes . empty ) return cwh2bb ( [ 0 , 0 ] , [ 0 , 0 ] ) ;
var bb = boxes [ 0 ] ;
boxes . forEach ( function ( x ) {
bb = bb _expand ( bb , x ) ;
} ) ;
var cwh = bb2cwh ( bb ) ;
if ( ! bb ) return ;
if ( this . flipx ) cwh . c . x *= - 1 ;
if ( this . flipy ) cwh . c . y *= - 1 ;
cwh . c = cwh . c . add ( this . pos ) ;
bb = cwh2bb ( cwh . c , cwh . wh ) ;
return bb ? bb : cwh2bb ( [ 0 , 0 ] , [ 0 , 0 ] ) ;
} ,
2023-10-02 17:03:01 -05:00
json _obj ( ) {
2023-10-05 17:30:17 -05:00
var d = ediff ( this , this . _ _proto _ _ ) ;
2023-10-09 18:10:10 -05:00
d ? ? = { } ;
var objects = { } ;
this . _ _proto _ _ . objects ? ? = { } ;
2023-10-10 17:37:58 -05:00
var curobjs = { } ;
for ( var o in this . objects )
curobjs [ o ] = this . objects [ o ] . instance _obj ( ) ;
var odiff = ediff ( curobjs , this . _ _proto _ _ . objects ) ;
if ( odiff )
d . objects = curobjs ;
2023-10-09 18:10:10 -05:00
2023-10-05 08:02:12 -05:00
delete d . pos ;
delete d . angle ;
delete d . velocity ;
delete d . angularvelocity ;
return d ;
2023-09-25 16:34:48 -05:00
} ,
2023-10-26 11:48:02 -05:00
2023-10-16 19:59:58 -05:00
transform _obj ( ) {
var t = this . json _obj ( ) ;
Object . assign ( t , this . transform ( ) ) ;
return t ;
} ,
2023-09-29 13:16:59 -05:00
2023-10-10 17:37:58 -05:00
instance _obj ( ) {
var t = this . transform _obj ( ) ;
t . ur = this . ur ;
return t ;
} ,
2023-10-02 07:58:17 -05:00
ur _obj ( ) {
var ur = this . json _obj ( ) ;
for ( var k in ur )
if ( ur [ k ] . ur )
delete ur [ k ] ;
return ur ;
} ,
2023-09-26 08:37:19 -05:00
make _ur ( ) {
var thisur = this . json _obj ( ) ;
2023-09-25 16:34:48 -05:00
thisur . pos = this . pos ;
thisur . angle = this . angle ;
2023-09-26 08:37:19 -05:00
return thisur ;
} ,
2023-09-26 13:34:02 -05:00
transform ( ) {
var t = { } ;
2023-10-02 07:58:17 -05:00
t . pos = this . pos . map ( Number . prec ) ;
t . angle = Number . prec ( this . angle ) ;
2023-09-26 13:34:02 -05:00
return t ;
} ,
2023-10-02 07:58:17 -05:00
phys _obj ( ) {
var phys = { } ;
phys . velocity = this . velocity . map ( Number . prec ) ;
phys . angularvelocity = Number . prec ( this . angularvelocity ) ;
return phys ;
} ,
2023-09-26 08:37:19 -05:00
dup ( diff ) {
2023-10-04 17:57:37 -05:00
var n = this . level . spawn ( this . _ _proto _ _ ) ;
2023-09-26 08:37:19 -05:00
Object . totalmerge ( n , this . make _ur ( ) ) ;
return n ;
2023-09-15 22:40:19 -05:00
} ,
2023-10-11 17:22:41 -05:00
2023-11-29 12:40:13 -06:00
kill ( ) {
this . timers . forEach ( t => t ( ) ) ;
if ( this . level ) {
this . level . remove _obj ( this ) ;
this . level = undefined ;
}
2023-09-14 17:37:04 -05:00
2023-11-29 12:40:13 -06:00
Player . do _uncontrol ( this ) ;
Register . unregister _obj ( this ) ;
2023-10-30 17:41:32 -05:00
2023-11-29 12:40:13 -06:00
if ( this . _ _proto _ _ . instances )
this . _ _proto _ _ . instances . remove ( this ) ;
2023-10-16 09:40:43 -05:00
2023-11-29 12:40:13 -06:00
for ( var key in this . components ) {
Register . unregister _obj ( this . components [ key ] ) ;
Log . info ( ` Destroying component ${ key } ` ) ;
this . components [ key ] . kill ( ) ;
this . components . gameobject = undefined ;
}
2023-09-14 17:37:04 -05:00
2023-11-29 12:40:13 -06:00
delete this . components ;
2023-11-29 17:31:41 -06:00
// q_body(8,this.body);
2023-10-04 08:18:09 -05:00
2023-11-29 12:40:13 -06:00
this . clear ( ) ;
2023-10-17 12:22:06 -05:00
2023-11-29 12:40:13 -06:00
if ( typeof this . stop === 'function' )
this . stop ( ) ;
} ,
2023-09-14 17:37:04 -05:00
2023-11-29 12:40:13 -06:00
up ( ) { return [ 0 , 1 ] . rotate ( Math . deg2rad ( this . angle ) ) ; } ,
down ( ) { return [ 0 , - 1 ] . rotate ( Math . deg2rad ( this . angle ) ) ; } ,
right ( ) { return [ 1 , 0 ] . rotate ( Math . deg2rad ( this . angle ) ) ; } ,
left ( ) { return [ - 1 , 0 ] . rotate ( Math . deg2rad ( this . angle ) ) ; } ,
2023-10-05 08:02:12 -05:00
2023-10-10 17:37:58 -05:00
make ( level , data ) {
2023-11-29 12:40:13 -06:00
// level ??= Primum;
2023-10-04 17:57:37 -05:00
var obj = Object . create ( this ) ;
2023-10-17 12:22:06 -05:00
obj . make = undefined ;
2023-10-10 17:37:58 -05:00
obj . level = level ;
2023-10-30 17:41:32 -05:00
if ( this . instances )
this . instances . push ( obj ) ;
2023-11-20 15:57:23 -06:00
2023-09-25 16:34:48 -05:00
obj . body = make _gameobject ( ) ;
2023-11-29 12:40:13 -06:00
2023-09-25 16:34:48 -05:00
obj . components = { } ;
2023-09-29 13:16:59 -05:00
obj . objects = { } ;
2023-11-17 15:16:13 -06:00
obj . timers = [ ] ;
2023-10-06 12:38:49 -05:00
obj . _ed = {
selectable : true ,
2023-10-26 11:48:02 -05:00
check _dirty ( ) {
this . urdiff = obj . json _obj ( ) ;
this . dirty = ! this . urdiff . empty ;
if ( ! obj . level ) return ;
var lur = ur [ obj . level . ur ] ;
if ( ! lur ) return ;
var lur = lur . objects [ obj . toString ( ) ] ;
var d = ediff ( this . urdiff , lur ) ;
if ( ! d || d . empty )
this . inst = true ;
else
this . inst = false ;
} ,
2023-10-06 12:38:49 -05:00
dirty : false ,
2023-10-26 11:48:02 -05:00
inst : false ,
urdiff : { } ,
namestr ( ) {
var s = obj . toString ( ) ;
if ( this . dirty )
if ( this . inst ) s += "#" ;
else s += "*" ;
return s ;
} ,
2023-10-06 12:38:49 -05:00
} ;
2023-11-29 12:40:13 -06:00
2023-10-05 17:30:17 -05:00
obj . ur = this . toString ( ) ;
2023-09-20 13:33:11 -05:00
cmd ( 113 , obj . body , obj ) ; // set the internal obj reference to this obj
2023-09-08 12:35:06 -05:00
2023-10-04 17:57:37 -05:00
for ( var prop in this ) {
var p = this [ prop ] ;
2023-09-21 12:50:39 -05:00
if ( typeof p !== 'object' ) continue ;
2023-10-05 13:33:43 -05:00
if ( typeof p . make === 'function' ) {
obj [ prop ] = p . make ( obj ) ;
2023-09-21 19:51:38 -05:00
obj . components [ prop ] = obj [ prop ] ;
2023-09-20 17:58:18 -05:00
}
2023-10-10 17:37:58 -05:00
} ;
2023-10-18 17:20:23 -05:00
2023-10-26 11:48:02 -05:00
if ( this . objects )
2023-10-11 17:22:41 -05:00
obj . make _objs ( this . objects ) ;
2023-10-09 18:10:10 -05:00
2023-10-18 17:20:23 -05:00
obj . level = undefined ;
obj . reparent ( level ) ;
2023-11-29 12:40:13 -06:00
Object . hide ( obj , 'ur' , 'body' , 'components' , 'objects' , '_ed' , 'level' , 'timers' ) ;
2023-10-18 17:20:23 -05:00
2023-10-05 13:33:43 -05:00
Object . dainty _assign ( obj , this ) ;
2023-10-10 17:37:58 -05:00
obj . sync ( ) ;
2023-10-04 17:57:37 -05:00
gameobject . check _registers ( obj ) ;
2023-10-02 17:03:01 -05:00
2023-10-30 17:41:32 -05:00
if ( data )
Object . dainty _assign ( obj , data ) ;
2023-11-06 07:05:27 -06:00
if ( typeof obj . warmup === 'function' ) obj . warmup ( ) ;
2023-10-11 17:22:41 -05:00
if ( Game . playing ( ) && typeof obj . start === 'function' ) obj . start ( ) ;
2023-10-23 08:08:11 -05:00
2023-09-08 12:35:06 -05:00
return obj ;
} ,
2023-10-09 18:10:10 -05:00
make _objs ( objs ) {
for ( var prop in objs ) {
2023-11-29 12:40:13 -06:00
Log . warn ( prop ) ;
2023-10-11 17:22:41 -05:00
var newobj = this . spawn _from _instance ( objs [ prop ] ) ;
2023-10-09 18:10:10 -05:00
if ( ! newobj ) continue ;
this . rename _obj ( newobj . toString ( ) , prop ) ;
}
} ,
2023-10-02 17:03:01 -05:00
rename _obj ( name , newname ) {
if ( ! this . objects [ name ] ) {
Log . warn ( ` No object with name ${ name } . Could not rename to ${ newname } . ` ) ;
return ;
}
2023-10-26 11:48:02 -05:00
if ( name === newname ) {
Object . hide ( this , name ) ;
return ;
}
2023-10-06 12:38:49 -05:00
if ( this . objects [ newname ] )
2023-10-02 17:03:01 -05:00
return ;
this . objects [ newname ] = this . objects [ name ] ;
2023-10-17 12:22:06 -05:00
this [ newname ] = this [ name ] ;
this [ newname ] . toString = function ( ) { return newname ; } ;
2023-10-26 11:48:02 -05:00
Object . hide ( this , newname ) ;
2023-10-02 17:03:01 -05:00
delete this . objects [ name ] ;
2023-10-17 12:22:06 -05:00
delete this [ name ] ;
2023-10-02 17:03:01 -05:00
return this . objects [ newname ] ;
} ,
2023-11-02 17:25:00 -05:00
add _component ( comp ) {
2023-11-29 12:40:13 -06:00
if ( typeof comp . make !== 'function' ) return ;
return { comp : comp . toString ( ) } ;
2023-11-02 17:25:00 -05:00
} ,
2023-09-08 12:35:06 -05:00
register _hit ( fn , obj ) {
if ( ! obj )
obj = this ;
Signal . obj _begin ( fn , obj , this ) ;
} ,
register _separate ( fn , obj ) {
if ( ! obj )
obj = this ;
Signal . obj _separate ( fn , obj , this ) ;
} ,
}
2023-11-29 12:40:13 -06:00
gameobject . body = make _gameobject ( ) ;
cmd ( 113 , gameobject . body , gameobject ) ;
Object . hide ( gameobject , 'timescale' ) ;
gameobject . spawn . doc = ` Spawn an entity of type 'ur' on this entity. Returns the spawned entity. ` ;
2023-09-20 13:33:11 -05:00
2023-10-23 08:08:11 -05:00
gameobject . doc = {
doc : "All objects in the game created through spawning have these attributes." ,
pos : "Position of the object, relative to its level." ,
angle : "Rotation of this object, relative to its level." ,
velocity : "Velocity of the object, relative to world." ,
angularvelocity : "Angular velocity of the object, relative to the world." ,
scale : "Scale of the object, relative to its level." ,
2023-11-15 16:42:39 -06:00
flipx : "Check if the object is flipped on its x axis." ,
flipy : "Check if the object is flipped on its y axis." ,
2023-10-23 08:08:11 -05:00
elasticity : ` When two objects collide, their elasticities are multiplied together. Their velocities are then multiplied by this value to find their resultant velocities. ` ,
friction : ` When one object touches another, friction slows them down. ` ,
2023-11-06 07:05:27 -06:00
gravity : 'True if this object should be affected by gravity.' ,
2023-10-23 08:08:11 -05:00
mass : ` The higher the mass of the object, the less forces will affect it. ` ,
phys : ` Set to 0, 1, or 2, representing static, kinematic, and dynamic. ` ,
worldpos : ` Function returns the world position of the object. ` ,
set _worldpos : ` Function to set the position of the object in world coordinates. ` ,
worldangle : ` Function to get the angle of the entity in the world. ` ,
rotate : ` Function to rotate this object by x degrees. ` ,
pulse : ` Apply an impulse to this body in world coordinates. Impulse is a short force. ` ,
shove : ` Apply a force to this body in world coordinates. Should be used over many frames. ` ,
2023-11-06 07:05:27 -06:00
shove _at : 'Apply a force to this body, at a position relative to itself.' ,
max _velocity : 'The max linear velocity this object can travel.' ,
max _angularvelocity : 'The max angular velocity this object can rotate.' ,
2023-10-23 08:08:11 -05:00
in _air : ` Return true if the object is in the air. ` ,
on _ground : ` Return true if the object is on the ground. ` ,
spawn : ` Create an instance of a supplied ur-type on this object. Optionally provide a data object to modify the created entity. ` ,
hide : ` Make this object invisible. ` ,
show : ` Make this object visible. ` ,
width : ` The total width of the object and all its components. ` ,
height : ` The total height of the object. ` ,
move : ` Move this object the given amount. ` ,
boundingbox : ` The boundingbox of the object. ` ,
dup : ` Make an exact copy of this object. ` ,
transform : ` Return an object representing the transform state of this object. ` ,
kill : ` Remove this object from the world. ` ,
level : "The entity this entity belongs to." ,
2023-11-07 12:45:52 -06:00
delay : 'Run the given function after the given number of seconds has elapsed.' ,
2023-11-17 15:16:13 -06:00
cry : 'Make a sound. Can only make one at a time.' ,
2023-10-23 08:08:11 -05:00
} ;
2023-09-12 17:19:46 -05:00
/* Default objects */
var prototypes = { } ;
2023-10-17 12:22:06 -05:00
prototypes . ur _ext = ".jso" ;
2023-09-12 17:19:46 -05:00
prototypes . ur = { } ;
prototypes . save _gameobjects = function ( ) { slurpwrite ( JSON . stringify ( gameobjects , null , 2 ) , "proto.json" ) ; } ;
2023-09-26 13:34:02 -05:00
/* Makes a new ur-type from disk. If the ur doesn't exist, it searches on the disk to create it. */
2023-09-12 17:19:46 -05:00
prototypes . from _file = function ( file )
{
2023-09-26 13:34:02 -05:00
var urpath = file ;
2023-09-26 08:37:19 -05:00
var path = urpath . split ( '.' ) ;
2023-09-26 13:34:02 -05:00
if ( path . length > 1 && ( path . at ( - 1 ) === path . at ( - 2 ) ) ) {
2023-09-27 17:40:04 -05:00
urpath = path . slice ( 0 , - 1 ) . join ( '.' ) ;
return prototypes . get _ur ( urpath ) ;
2023-09-26 13:34:02 -05:00
}
2023-10-04 17:57:37 -05:00
var upperur = gameobject ;
2023-09-26 13:34:02 -05:00
2023-09-26 08:37:19 -05:00
if ( path . length > 1 ) {
2023-11-20 07:49:14 -06:00
var upur = undefined ;
2023-09-26 08:37:19 -05:00
var upperpath = path . slice ( 0 , - 1 ) ;
2023-11-20 07:49:14 -06:00
while ( ! upur && upperpath ) {
upur = prototypes . get _ur ( upperpath . join ( '/' ) ) ;
upperpath = upperpath . slice ( 0 , - 1 ) ;
2023-09-26 13:34:02 -05:00
}
2023-11-20 07:49:14 -06:00
if ( upur ) upperur = upur ;
2023-09-26 08:37:19 -05:00
}
2023-09-12 17:19:46 -05:00
2023-10-10 17:37:58 -05:00
var newur = { } ;
2023-10-04 17:57:37 -05:00
2023-09-26 13:34:02 -05:00
file = file . replaceAll ( '.' , '/' ) ;
2023-09-12 17:19:46 -05:00
2023-10-17 12:22:06 -05:00
var jsfile = prototypes . get _ur _file ( urpath , prototypes . ur _ext ) ;
2023-09-29 08:27:34 -05:00
var jsonfile = prototypes . get _ur _file ( urpath , ".json" ) ;
2023-09-12 17:19:46 -05:00
2023-09-26 13:34:02 -05:00
var script = undefined ;
var json = undefined ;
2023-09-12 17:19:46 -05:00
2023-09-29 08:27:34 -05:00
if ( jsfile ) script = IO . slurp ( jsfile ) ;
2023-10-09 13:03:12 -05:00
try {
if ( jsonfile ) json = JSON . parse ( IO . slurp ( jsonfile ) ) ;
} catch ( e ) {
2023-10-10 17:37:58 -05:00
Log . warn ( ` Unable to create json from ${ jsonfile } ` ) ;
2023-10-09 13:03:12 -05:00
}
2023-09-19 17:37:54 -05:00
2023-09-26 13:34:02 -05:00
if ( ! json && ! script ) {
Log . warn ( ` Could not make ur from ${ file } ` ) ;
return undefined ;
}
if ( script )
compile _env ( script , newur , file ) ;
2023-09-19 17:37:54 -05:00
2023-09-26 13:34:02 -05:00
json ? ? = { } ;
Object . merge ( newur , json ) ;
2023-10-05 13:33:43 -05:00
Object . entries ( newur ) . forEach ( function ( [ k , v ] ) {
if ( Object . isObject ( v ) && Object . isObject ( upperur [ k ] ) )
v . _ _proto _ _ = upperur [ k ] ;
} ) ;
Object . values ( newur ) . forEach ( function ( v ) {
if ( typeof v !== 'object' ) return ;
if ( ! v . comp ) return ;
v . _ _proto _ _ = component [ v . comp ] ;
} ) ;
2023-10-04 17:57:37 -05:00
newur . _ _proto _ _ = upperur ;
newur . instances = [ ] ;
2023-10-05 17:30:17 -05:00
Object . hide ( newur , 'instances' ) ;
2023-10-04 17:57:37 -05:00
2023-09-26 13:34:02 -05:00
prototypes . list . push ( urpath ) ;
2023-09-26 08:37:19 -05:00
newur . toString = function ( ) { return urpath ; } ;
2023-09-26 13:34:02 -05:00
ur [ urpath ] = newur ;
2023-09-20 08:11:14 -05:00
2023-10-18 17:20:23 -05:00
return newur ;
2023-09-12 17:19:46 -05:00
}
prototypes . from _file . doc = "Create a new ur-type from a given script file." ;
prototypes . list = [ ] ;
prototypes . list _ur = function ( )
{
var list = [ ] ;
function list _obj ( obj , prefix )
{
prefix ? ? = "" ;
var list = [ ] ;
for ( var e in obj ) {
list . push ( prefix + e ) ;
list . concat ( list _obj ( obj [ e ] , e + "." ) ) ;
}
return list ;
}
return list _obj ( ur ) ;
}
2023-09-29 08:27:34 -05:00
prototypes . ur2file = function ( urpath )
{
return urpath . replaceAll ( '.' , '/' ) ;
}
2023-09-26 13:34:02 -05:00
prototypes . file2ur = function ( file )
2023-09-26 08:37:19 -05:00
{
2023-09-26 13:34:02 -05:00
file = file . strip _ext ( ) ;
2023-09-26 08:37:19 -05:00
file = file . replaceAll ( '/' , '.' ) ;
2023-09-26 13:34:02 -05:00
return file ;
2023-09-26 08:37:19 -05:00
}
2023-09-26 13:34:02 -05:00
/ * R e t u r n s a n u r , o r m a k e s i t , f o r a n y g i v e n t y p e o f p a t h
could be a file on a disk like ball / big . js
could be an ur path like ball . big
* /
2023-09-12 17:19:46 -05:00
prototypes . get _ur = function ( name )
{
2023-10-03 17:16:38 -05:00
if ( ! name ) {
Log . warn ( ` Can't get ur from an undefined. ` ) ;
return ;
}
2023-09-26 13:34:02 -05:00
var urpath = name ;
if ( urpath . includes ( '/' ) )
urpath = prototypes . file2ur ( name ) ;
if ( ! prototypes . ur [ urpath ] ) {
var ur = prototypes . from _file ( urpath ) ;
if ( ur )
return ur ;
else {
2023-09-26 08:37:19 -05:00
Log . warn ( ` Could not find prototype using name ${ name } . ` ) ;
return undefined ;
}
2023-09-12 17:19:46 -05:00
} else
2023-09-26 13:34:02 -05:00
return prototypes . ur [ urpath ] ;
2023-09-12 17:19:46 -05:00
}
2023-09-29 08:27:34 -05:00
prototypes . get _ur _file = function ( path , ext )
{
var urpath = prototypes . ur2file ( path ) ;
var file = urpath + ext ;
if ( IO . exists ( file ) ) return file ;
file = urpath + "/" + path . split ( '.' ) . at ( - 1 ) + ext ;
if ( IO . exists ( file ) ) return file ;
return undefined ;
}
2023-09-12 17:19:46 -05:00
prototypes . generate _ur = function ( path )
{
2023-10-17 12:22:06 -05:00
var ob = IO . glob ( "**" + prototypes . ur _ext ) ;
2023-09-26 13:34:02 -05:00
ob = ob . concat ( IO . glob ( "**.json" ) ) ;
ob = ob . map ( function ( path ) { return path . set _ext ( "" ) ; } ) ;
ob . forEach ( function ( name ) { prototypes . get _ur ( name ) ; } ) ;
2023-09-12 17:19:46 -05:00
}
var ur = prototypes . ur ;
2023-10-04 17:57:37 -05:00
prototypes . resavi = function ( ur , path )
{
2023-10-05 13:33:43 -05:00
if ( ! ur ) return path ;
if ( path [ 0 ] === '/' ) return path ;
2023-10-04 17:57:37 -05:00
2023-10-05 13:33:43 -05:00
var res = ur . replaceAll ( '.' , '/' ) ;
var dir = path . dir ( ) ;
if ( res . startsWith ( dir ) )
return path . base ( ) ;
return path ;
2023-10-04 17:57:37 -05:00
}
prototypes . resani = function ( ur , path )
{
if ( ! path ) return "" ;
2023-10-05 13:33:43 -05:00
if ( ! ur ) return path ;
if ( path [ 0 ] === '/' ) return path . slice ( 1 ) ;
var res = ur . replaceAll ( '.' , '/' ) ;
var restry = res + "/" + path ;
while ( ! IO . exists ( restry ) ) {
res = res . updir ( ) + "/" ;
if ( res === "/" )
return path ;
restry = res + path ;
}
return restry ;
2023-10-04 17:57:37 -05:00
}
2023-11-17 15:16:13 -06:00
prototypes . ur _dir = function ( ur )
{
var path = ur . replaceAll ( '.' , '/' ) ;
Log . warn ( path ) ;
Log . warn ( IO . exists ( path ) ) ;
Log . warn ( ` ${ path } does not exist; sending ${ path . dir ( ) } ` ) ;
}
prototypes . ur _json = function ( ur )
{
var path = ur . replaceAll ( '.' , '/' ) ;
if ( IO . exists ( path ) )
path = path + "/" + path . name ( ) + ".json" ;
else
path = path + ".json" ;
return path ;
}
prototypes . ur _stem = function ( ur )
{
var path = ur . replaceAll ( '.' , '/' ) ;
if ( IO . exists ( path ) )
return path + "/" + path . name ( ) ;
else
return path ;
}
prototypes . ur _file _exts = [ '.jso' , '.json' ] ;
prototypes . ur _folder = function ( ur )
{
var path = ur . replaceAll ( '.' , '/' ) ;
return IO . exists ( path ) ;
}
prototypes . ur _pullout _folder = function ( ur )
{
if ( ! prototypes . ur _folder ( ur ) ) return ;
var stem = prototypes . ur _stem ( ur ) ;
/ * p r o t o t y p e s . u r _ f i l e _ e x t s . f o r E a c h ( f u n c t i o n ( e ) {
var p = stem + e ;
if ( IO . exists ( p ) )
* /
}
prototypes . ur _pushin _folder = function ( ur )
{
}