2024-04-14 14:53:41 -05:00
globalThis . entityreport = { } ;
2024-03-13 03:51:44 -05:00
function obj _unique _name ( name , obj ) {
2023-12-24 09:14:46 -06:00
name = name . replaceAll ( '.' , '_' ) ;
if ( ! ( name in obj ) ) return name ;
var t = 1 ;
var n = name + t ;
while ( n in obj ) {
t ++ ;
2024-03-13 03:51:44 -05:00
n = name + t ;
2023-12-24 09:14:46 -06:00
}
return n ;
}
2024-05-02 17:13:09 -05:00
function unique _name ( list , name = "new_object" ) {
var str = name . replaceAll ( '.' , '_' ) ;
var n = 1 ;
var t = str ;
while ( list . indexOf ( t ) !== - 1 ) {
t = str + n ;
n ++ ;
}
return t ;
} ;
var entity = {
2023-12-20 09:19:04 -06:00
get _comp _by _name ( name ) {
var comps = [ ] ;
for ( var c of Object . values ( this . components ) )
if ( c . comp === name ) comps . push ( c ) ;
2024-05-02 17:13:09 -05:00
2023-12-20 09:19:04 -06:00
if ( comps . length ) return comps ;
return undefined ;
} ,
2024-03-20 16:07:23 -05:00
2024-03-13 03:51:44 -05:00
path _from ( o ) {
var p = this . toString ( ) ;
var c = this . master ;
while ( c && c !== o && c !== world ) {
p = c . toString ( ) + "." + p ;
c = c . master ;
}
if ( c === world ) p = "world." + p ;
return p ;
} ,
2024-05-02 17:13:09 -05:00
full _path ( ) { return this . path _from ( world ) ; } ,
2024-03-13 03:51:44 -05:00
clear ( ) {
for ( var k in this . objects ) {
this . objects [ k ] . kill ( ) ;
} ;
this . objects = { } ;
} ,
2024-05-02 17:13:09 -05:00
sync ( ) {
this . components . forEach ( function ( x ) { x . sync ? . ( ) ; } ) ;
this . objects . forEach ( function ( x ) { x . sync ( ) ; } ) ;
} ,
2024-03-13 03:51:44 -05:00
delay ( fn , seconds ) {
2024-04-02 07:41:46 -05:00
var timers = this . timers ;
2024-03-21 21:07:24 -05:00
var stop = function ( ) {
2024-04-02 07:41:46 -05:00
timers . remove ( stop ) ;
2024-03-21 21:07:24 -05:00
execute = undefined ;
stop = undefined ;
2024-03-26 07:53:36 -05:00
rm ? . ( ) ;
2024-03-21 21:07:24 -05:00
rm = undefined ;
update = undefined ;
}
function execute ( ) {
2024-04-02 07:41:46 -05:00
fn ( ) ;
2024-03-21 21:07:24 -05:00
stop ? . ( ) ;
}
stop . remain = seconds ;
stop . seconds = seconds ;
2024-04-14 14:53:41 -05:00
stop . pct = function ( ) { return 1 - ( stop . remain / stop . seconds ) ; } ;
2024-03-21 21:07:24 -05:00
function update ( dt ) {
stop . remain -= dt ;
if ( stop . remain <= 0 ) execute ( ) ;
2024-03-15 10:51:04 -05:00
}
2024-03-21 21:07:24 -05:00
var rm = Register . update . register ( update ) ;
2024-04-02 07:41:46 -05:00
timers . push ( stop ) ;
2024-03-21 21:07:24 -05:00
return stop ;
2024-03-13 03:51:44 -05:00
} ,
2024-05-02 17:13:09 -05:00
2024-04-14 14:53:41 -05:00
cry ( file ) { return audio . cry ( file ) ; } ,
2024-04-09 08:01:54 -05:00
2024-05-02 17:13:09 -05:00
get pos ( ) { return this . transform . pos ; } ,
set pos ( x ) { this . transform . pos = x ; } ,
get angle ( ) { return this . transform . angle ; } ,
set angle ( x ) { this . transform . angle = x ; } ,
get scale ( ) { return this . transform . scale ; } ,
set scale ( x ) { this . transform . scale = x ; } ,
2024-04-07 13:16:54 -05:00
2024-05-02 17:13:09 -05:00
move ( vec ) { this . pos = this . pos . add ( vec ) ; } ,
rotate ( x ) { this . angle += x ; } ,
grow ( vec ) {
if ( typeof vec === 'number' ) vec = [ vec , vec ] ;
this . scale = this . scale . map ( ( x , i ) => x * vec [ i ] ) ;
2024-04-07 13:16:54 -05:00
} ,
2024-05-02 17:13:09 -05:00
/* Reparent 'this' to be 'parent's child */
reparent ( parent ) {
assert ( parent , ` Tried to reparent ${ this . toString ( ) } to nothing. ` ) ;
console . spam ( ` parenting ${ this . toString ( ) } to ${ parent . toString ( ) } ` ) ;
if ( this . master === parent ) {
console . warn ( "not reparenting ..." ) ;
console . warn ( ` ${ this . master } is the same as ${ parent } ` ) ;
return ;
}
var name = unique _name ( Object . keys ( parent ) , this . name ) ;
this . name = name ;
2024-04-07 13:16:54 -05:00
2024-05-02 17:13:09 -05:00
this . master ? . remove _obj ( this ) ;
this . master = parent ;
parent . objects [ this . guid ] = this ;
parent [ name ] = this ;
Object . hide ( parent , name ) ;
2024-04-07 13:16:54 -05:00
} ,
2024-05-02 17:13:09 -05:00
remove _obj ( obj ) {
delete this . objects [ obj . guid ] ;
delete this [ obj . name ] ;
Object . unhide ( this , obj . name ) ;
2024-04-09 08:01:54 -05:00
} ,
2024-04-07 13:16:54 -05:00
2024-04-01 17:58:29 -05:00
spawn ( text , config , callback ) {
2024-04-14 14:53:41 -05:00
var st = profile . now ( ) ;
2024-05-02 17:13:09 -05:00
var ent = Object . create ( entity ) ;
2024-05-12 18:36:14 -05:00
ent . transform = os . make _transform ( ) ;
2024-05-02 17:13:09 -05:00
2024-04-03 00:44:08 -05:00
ent . guid = prosperon . guid ( ) ;
2024-05-02 17:13:09 -05:00
2024-04-02 07:41:46 -05:00
ent . components = { } ;
ent . objects = { } ;
2024-04-01 17:58:29 -05:00
ent . timers = [ ] ;
2024-04-03 00:44:08 -05:00
2024-05-02 17:13:09 -05:00
if ( ! text )
ent . ur = emptyur ;
else if ( typeof text === 'object' && text ) { // assume it's an ur
2024-04-04 17:28:11 -05:00
ent . ur = text ;
2024-04-12 13:53:00 -05:00
text = ent . ur . text ;
config = [ ent . ur . data , config ] . filter ( x => x ) . flat ( ) ;
}
else {
2024-04-04 17:28:11 -05:00
ent . ur = getur ( text , config ) ;
2024-04-12 13:53:00 -05:00
text = ent . ur . text ;
config = [ ent . ur . data , config ] ;
}
2024-05-02 17:13:09 -05:00
2024-04-04 17:28:11 -05:00
if ( typeof text === 'string' )
2024-04-01 17:58:29 -05:00
use ( text , ent ) ;
2024-04-04 17:28:11 -05:00
else if ( Array . isArray ( text ) )
text . forEach ( path => use ( path , ent ) ) ;
2024-05-02 17:13:09 -05:00
2024-04-04 17:28:11 -05:00
if ( typeof config === 'string' )
2024-04-06 19:41:14 -05:00
Object . merge ( ent , json . decode ( Resources . replstrs ( config ) ) ) ;
2024-04-04 17:28:11 -05:00
else if ( Array . isArray ( config ) )
config . forEach ( function ( path ) {
2024-04-11 17:17:49 -05:00
if ( typeof path === 'string' ) {
console . info ( ` ingesting ${ path } ... ` ) ;
2024-04-06 19:41:14 -05:00
Object . merge ( ent , json . decode ( Resources . replstrs ( path ) ) ) ;
2024-04-11 17:17:49 -05:00
}
2024-04-04 17:28:11 -05:00
else if ( typeof path === 'object' )
2024-04-06 19:41:14 -05:00
Object . merge ( ent , path ) ;
2024-04-04 17:28:11 -05:00
} ) ;
2024-05-02 17:13:09 -05:00
2024-04-03 17:17:32 -05:00
ent . reparent ( this ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
for ( var [ prop , p ] of Object . entries ( ent ) ) {
if ( ! p ) continue ;
if ( typeof p !== 'object' ) continue ;
if ( component . isComponent ( p ) ) continue ;
if ( ! p . comp ) continue ;
ent [ prop ] = component [ p . comp ] . make ( ent ) ;
Object . merge ( ent [ prop ] , p ) ;
ent . components [ prop ] = ent [ prop ] ;
} ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
check _registers ( ent ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
if ( typeof ent . load === 'function' ) ent . load ( ) ;
2024-03-15 11:21:36 -05:00
if ( sim . playing ( ) )
2024-03-13 03:51:44 -05:00
if ( typeof ent . start === 'function' ) ent . start ( ) ;
2024-05-02 17:13:09 -05:00
Object . hide ( ent , 'ur' , 'components' , 'objects' , 'timers' , 'guid' , 'master' ) ;
2024-04-07 13:16:54 -05:00
2024-04-03 17:17:32 -05:00
ent . _ed = {
selectable : true ,
dirty : false ,
inst : false ,
2024-04-04 17:28:11 -05:00
urdiff : { }
2024-04-03 17:17:32 -05:00
} ;
2024-05-02 17:13:09 -05:00
2024-04-03 17:17:32 -05:00
Object . hide ( ent , '_ed' ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
ent . sync ( ) ;
2024-04-02 07:41:46 -05:00
2024-03-13 03:51:44 -05:00
if ( ! Object . empty ( ent . objects ) ) {
var o = ent . objects ;
delete ent . objects ;
2024-04-11 17:17:49 -05:00
ent . objects = { } ;
2024-03-13 03:51:44 -05:00
for ( var i in o ) {
2024-04-10 16:21:46 -05:00
console . info ( ` creating ${ i } on ${ ent . toString ( ) } ` ) ;
2024-04-04 17:28:11 -05:00
var newur = o [ i ] . ur ;
2024-03-13 03:51:44 -05:00
delete o [ i ] . ur ;
2024-04-04 17:28:11 -05:00
var n = ent . spawn ( ur [ newur ] , o [ i ] ) ;
ent . rename _obj ( n . toString ( ) , i ) ;
2024-03-13 03:51:44 -05:00
}
}
2024-04-03 00:44:08 -05:00
if ( ent . tag ) game . tag _add ( ent . tag , ent ) ;
2024-04-03 08:37:29 -05:00
if ( callback ) callback ( ent ) ;
2024-05-02 17:13:09 -05:00
2024-04-04 17:28:11 -05:00
ent . ur . fresh ? ? = json . decode ( json . encode ( ent ) ) ;
2024-04-09 08:01:54 -05:00
ent . ur . fresh . objects = { } ;
for ( var i in ent . objects )
ent . ur . fresh . objects [ i ] = ent . objects [ i ] . instance _obj ( ) ;
2024-05-02 17:13:09 -05:00
2024-04-14 14:53:41 -05:00
profile . addreport ( entityreport , ent . ur . name , st ) ;
2024-03-13 03:51:44 -05:00
return ent ;
} ,
2024-05-02 17:13:09 -05:00
disable ( ) { this . components . forEach ( function ( x ) { x . disable ( ) ; } ) ; } ,
enable ( ) { this . components . forEach ( function ( x ) { x . enable ( ) ; } ) ; } ,
2024-04-03 00:44:08 -05:00
this2screen ( pos ) { return game . camera . world2view ( this . this2world ( pos ) ) ; } ,
screen2this ( pos ) { return this . world2this ( game . camera . view2world ( pos ) ) ; } ,
2024-03-19 14:39:19 -05:00
2024-05-02 17:13:09 -05:00
/* Make a unique object the same as its prototype */
revert ( ) { Object . merge ( this , this . ur . fresh ) ; } ,
name : "new_object" ,
toString ( ) { return this . name ; } ,
2023-10-04 17:57:37 -05:00
width ( ) {
var bb = this . boundingbox ( ) ;
return bb . r - bb . l ;
} ,
2024-05-02 17:13:09 -05:00
2023-10-04 17:57:37 -05:00
height ( ) {
var bb = this . boundingbox ( ) ;
2024-03-13 03:51:44 -05:00
return bb . t - bb . b ;
2023-10-04 17:57:37 -05:00
} ,
2024-05-02 17:13:09 -05:00
2024-02-29 13:54:33 -06:00
flipx ( ) { return this . scale . x < 0 ; } ,
flipy ( ) { return this . scale . y < 0 ; } ,
2024-05-02 17:13:09 -05:00
2024-03-20 16:07:23 -05:00
mirror ( plane ) { this . scale = Vector . reflect ( this . scale , plane ) ; } ,
2024-03-13 03:51:44 -05:00
/* Bounding box of the object in world dimensions */
boundingbox ( ) {
var boxes = [ ] ;
boxes . push ( {
t : 0 ,
r : 0 ,
b : 0 ,
l : 0
} ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
for ( var key in this . components ) {
if ( 'boundingbox' in this . components [ key ] )
boxes . push ( this . components [ key ] . boundingbox ( ) ) ;
}
for ( var key in this . objects )
boxes . push ( this . objects [ key ] . boundingbox ( ) ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
var bb = boxes . shift ( ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
boxes . forEach ( function ( x ) { bb = bbox . expand ( bb , x ) ; } ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
bb = bbox . move ( bb , this . pos ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
return bb ? bb : bbox . fromcwh ( [ 0 , 0 ] , [ 0 , 0 ] ) ;
} ,
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
/* The unique components of this object. Its diff. */
2024-04-12 13:53:00 -05:00
json _obj ( depth = 0 ) {
2024-04-04 17:28:11 -05:00
var fresh = this . ur . fresh ;
2024-03-13 03:51:44 -05:00
var thiso = json . decode ( json . encode ( this ) ) ; // TODO: SLOW. Used to ignore properties in toJSON of components.
2024-04-03 17:17:32 -05:00
var d = ediff ( thiso , fresh ) ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
d ? ? = { } ;
2024-05-02 17:13:09 -05:00
2024-04-03 17:17:32 -05:00
fresh . objects ? ? = { } ;
2024-03-13 03:51:44 -05:00
var curobjs = { } ;
for ( var o in this . objects )
curobjs [ o ] = this . objects [ o ] . instance _obj ( ) ;
2024-05-02 17:13:09 -05:00
2024-04-03 17:17:32 -05:00
var odiff = ediff ( curobjs , fresh . objects ) ;
2024-03-13 03:51:44 -05:00
if ( odiff )
d . objects = curobjs ;
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
delete d . pos ;
delete d . angle ;
delete d . scale ;
delete d . velocity ;
delete d . angularvelocity ;
return d ;
} ,
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
/* The object needed to store an object as an instance of a master */
instance _obj ( ) {
var t = this . transform ( ) ;
2024-04-04 17:28:11 -05:00
t . ur = this . ur . name ;
2024-03-13 03:51:44 -05:00
return t ;
} ,
2024-05-02 17:13:09 -05:00
2024-03-13 03:51:44 -05:00
transform ( ) {
var t = { } ;
2024-04-09 16:48:15 -05:00
t . pos = this . get _pos ( this . master ) . map ( x => Math . places ( x , 0 ) ) ;
2024-04-09 08:01:54 -05:00
t . angle = Math . places ( this . get _angle ( this . master ) , 4 ) ;
2024-04-09 16:48:15 -05:00
t . scale = this . get _scale ( this . master ) . map ( x => Math . places ( x , 2 ) ) ; ;
2024-03-13 03:51:44 -05:00
return t ;
} ,
2024-05-02 17:13:09 -05:00
dup ( diff ) {
2024-04-04 17:28:11 -05:00
var n = this . master . spawn ( this . ur ) ;
2024-04-09 16:48:15 -05:00
Object . totalmerge ( n , this . transform ( ) ) ;
2024-03-13 03:51:44 -05:00
return n ;
} ,
2024-05-02 17:13:09 -05:00
2023-11-29 12:40:13 -06:00
kill ( ) {
2023-12-28 12:49:48 -06:00
if ( this . _ _kill ) return ;
this . _ _kill = true ;
2024-03-22 13:40:56 -05:00
console . spam ( ` Killing entity of type ${ this . ur } ` ) ;
2024-05-02 17:13:09 -05:00
2023-11-29 12:40:13 -06:00
this . timers . forEach ( t => t ( ) ) ;
2024-01-03 14:26:42 -06:00
this . timers = [ ] ;
2024-01-03 17:19:13 -06:00
Event . rm _obj ( this ) ;
2024-04-03 08:37:29 -05:00
input . do _uncontrol ( this ) ;
2024-05-02 17:13:09 -05:00
2024-02-29 13:54:33 -06:00
if ( this . master ) {
this . master . remove _obj ( this ) ;
this . master = undefined ;
2023-11-29 12:40:13 -06:00
}
2024-05-02 17:13:09 -05:00
2023-11-29 12:40:13 -06:00
for ( var key in this . components ) {
2024-03-13 03:51:44 -05:00
this . components [ key ] . kill ? . ( ) ;
2023-12-19 15:34:36 -06:00
this . components [ key ] . gameobject = undefined ;
2024-04-02 07:41:46 -05:00
this [ key ] . enabled = false ;
2023-12-18 17:12:05 -06:00
delete this . components [ key ] ;
2024-03-15 10:51:04 -05:00
delete this [ key ] ;
2023-11-29 12:40:13 -06:00
}
2024-04-02 07:41:46 -05:00
delete this . components ;
2024-05-02 17:13:09 -05:00
2023-11-29 12:40:13 -06:00
this . clear ( ) ;
2024-02-29 13:54:33 -06:00
if ( typeof this . stop === 'function' ) this . stop ( ) ;
2024-04-02 07:41:46 -05:00
2024-04-03 00:44:08 -05:00
game . tag _clear _guid ( this . guid ) ;
2024-04-02 07:41:46 -05:00
for ( var i in this ) {
if ( typeof this [ i ] === 'object' ) delete this [ i ] ;
if ( typeof this [ i ] === 'function' ) delete this [ i ] ;
}
2023-11-29 12:40:13 -06:00
} ,
2024-05-02 17:13:09 -05:00
2023-10-09 18:10:10 -05:00
make _objs ( objs ) {
for ( var prop in objs ) {
2024-02-29 13:54:33 -06:00
say ( ` spawning ${ json . encode ( objs [ prop ] ) } ` ) ;
var newobj = this . spawn ( objs [ prop ] ) ;
2023-10-09 18:10:10 -05:00
}
} ,
2024-05-02 17:13:09 -05:00
2023-10-02 17:03:01 -05:00
rename _obj ( name , newname ) {
if ( ! this . objects [ name ] ) {
2024-02-25 17:31:48 -06:00
console . warn ( ` No object with name ${ name } . Could not rename to ${ newname } . ` ) ;
2023-10-02 17:03:01 -05:00
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 ;
2024-05-02 17:13:09 -05:00
2023-10-02 17:03:01 -05:00
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 ] ;
} ,
2024-05-02 17:13:09 -05:00
2024-04-07 13:16:54 -05:00
add _component ( comp , data , name = comp . toString ( ) ) {
2023-11-29 12:40:13 -06:00
if ( typeof comp . make !== 'function' ) return ;
2024-02-29 13:54:33 -06:00
name = obj _unique _name ( name , this ) ;
2023-12-28 12:49:48 -06:00
this [ name ] = comp . make ( this ) ;
this [ name ] . comp = comp . toString ( ) ;
this . components [ name ] = this [ name ] ;
if ( data )
Object . assign ( this [ name ] , data ) ;
2023-12-24 09:14:46 -06:00
return this [ name ] ;
2023-11-02 17:25:00 -05:00
} ,
2024-05-02 17:13:09 -05:00
} ;
2024-03-20 16:07:23 -05:00
2024-05-02 17:13:09 -05:00
var gameobject = {
check _dirty ( ) {
this . _ed . urdiff = this . json _obj ( ) ;
this . _ed . dirty = ! Object . empty ( this . _ed . urdiff ) ;
return ; // TODO: IMPLEMENT
var lur = this . master . ur ;
if ( ! lur ) return ;
var lur = lur . objects [ this . toString ( ) ] ;
var d = ediff ( this . _ed . urdiff , lur ) ;
if ( ! d || Object . empty ( d ) )
this . _ed . inst = true ;
else
this . _ed . inst = false ;
} ,
namestr ( ) {
var s = this . toString ( ) ;
if ( this . _ed ? . dirty )
if ( this . _ed . inst ) s += "#" ;
else s += "*" ;
return s ;
} ,
urstr ( ) {
var str = this . ur . name ;
if ( this . _ed . dirty ) str = "*" + str ;
return str ;
} ,
/* pin this object to the to object */
pin ( to ) {
var p = joint . pin ( this , to ) ;
} ,
slide ( to , a = [ 0 , 0 ] , b = [ 0 , 0 ] , min = 0 , max = 50 ) {
var p = joint . slide ( this , to , a , b , min , max ) ;
p . max _force = 500 ;
p . break ( ) ;
} ,
pivot ( to , piv = this . pos ) {
var p = joint . pivot ( this , to , piv ) ;
} ,
/* groove is on to, from local points a and b, anchored to this at local anchor */
groove ( to , a , b , anchor = [ 0 , 0 ] ) {
var p = joint . groove ( to , this , a , b , anchor ) ;
} ,
damped _spring ( to , length = Vector . length ( this . pos , to . pos ) , stiffness = 1 , damping = 1 ) {
var dc = 2 * Math . sqrt ( stiffness * this . mass ) ;
var p = joint . damped _spring ( this , to , [ 0 , 0 ] , [ 0 , 0 ] , stiffness , damping * dc ) ;
} ,
damped _rotary _spring ( to , angle = 0 , stiffness = 1 , damping = 1 ) {
/* calculate actual damping value from the damping ratio */
/* damping = 1 is critical */
var dc = 2 * Math . sqrt ( stiffness * this . get _moi ( ) ) ; /* critical damping number */
/* zeta = actual/critical */
var p = joint . damped _rotary ( this , to , angle , stiffness , damping * dc ) ;
} ,
rotary _limit ( to , min , max ) {
var p = joint . rotary ( this , to , Math . turn2rad ( min ) , Math . turn2rad ( max ) ) ;
} ,
ratchet ( to , ratch ) {
var phase = this . angle - to . angle ;
var p = joint . ratchet ( this , to , phase , Math . turn2rad ( ratch ) ) ;
} ,
gear ( to , ratio = 1 , phase = 0 ) {
var phase = this . angle - to . angle ;
var p = joint . gear ( this , to , phase , ratio ) ;
} ,
motor ( to , rate ) {
var p = joint . motor ( this , to , rate ) ;
} ,
set _pos ( x , relative = world ) {
var newpos = relative . this2world ( x ) ;
var move = newpos . sub ( this . pos ) ;
this . rpos = newpos ;
this . objects . forEach ( x => x . move ( move ) ) ;
} ,
set _angle ( x , relative = world ) {
var newangle = relative . angle + x ;
var diff = newangle - this . angle ;
this . rangle = newangle ;
this . objects . forEach ( obj => {
obj . rotate ( diff ) ;
obj . set _pos ( Vector . rotate ( obj . get _pos ( obj . master ) , diff ) , obj . master ) ;
} ) ;
} ,
set _scale ( x , relative = world ) {
if ( typeof x === 'number' ) x = [ x , x , x ] ;
var newscale = relative . scale . map ( ( s , i ) => x [ i ] * s ) ;
var pct = this . scale . map ( ( s , i ) => newscale [ i ] / s ) ;
this . rscale = newscale ;
this . objects . forEach ( obj => {
obj . grow ( pct ) ;
obj . set _pos ( obj . get _pos ( obj . master ) . map ( ( x , i ) => x * pct [ i ] ) , obj . master ) ;
} ) ;
} ,
get _pos ( relative = world ) {
if ( relative === world ) return this . pos ;
return relative . world2this ( this . pos ) ;
//return this.pos.sub(relative.pos);
} ,
get _angle ( relative = world ) {
if ( relative === world ) return this . angle ;
return this . angle - relative . angle ;
} ,
get _scale ( relative = world ) {
if ( relative === world ) return this . scale ;
var masterscale = relative . scale ;
return this . scale . map ( ( x , i ) => x / masterscale [ i ] ) ;
} ,
in _air ( ) { return this . in _air ( ) ; } ,
/* Velocity and angular velocity of the object */
phys _obj ( ) {
var phys = { } ;
phys . velocity = this . velocity ;
phys . angularvelocity = this . angularvelocity ;
return phys ;
} ,
set category ( n ) {
if ( n === 0 ) {
this . categories = n ;
return ;
}
var cat = ( 1 << ( n - 1 ) ) ;
this . categories = cat ;
} ,
get category ( ) {
if ( this . categories === 0 ) return 0 ;
var pos = 0 ;
var num = this . categories ;
while ( num > 0 ) {
if ( num & 1 ) {
break ;
}
pos ++ ;
num >>>= 1 ;
}
return pos + 1 ;
2024-03-21 11:33:36 -05:00
}
2024-03-20 16:07:23 -05:00
}
2024-05-02 17:13:09 -05:00
entity . 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." ,
2024-02-29 13:54:33 -06:00
pos : "Position of the object, relative to its master." ,
angle : "Rotation of this object, relative to its master." ,
2023-10-23 08:08:11 -05:00
velocity : "Velocity of the object, relative to world." ,
angularvelocity : "Angular velocity of the object, relative to the world." ,
2024-02-29 13:54:33 -06:00
scale : "Scale of the object, relative to its master." ,
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." ,
2024-03-19 23:01:31 -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. ` ,
2023-10-23 08:08:11 -05:00
friction : ` When one object touches another, friction slows them down. ` ,
mass : ` The higher the mass of the object, the less forces will affect it. ` ,
2024-03-09 18:22:06 -06:00
phys : ` Set to 0, 1, or 2, representing dynamic, kinematic, and static. ` ,
2023-10-23 08:08:11 -05:00
worldpos : ` Function returns the world position of the object. ` ,
2024-04-07 13:16:54 -05:00
set _pos : ` Function to set the position of the object in world coordinates. ` ,
2023-10-23 08:08:11 -05:00
worldangle : ` Function to get the angle of the entity in the world. ` ,
rotate : ` Function to rotate this object by x degrees. ` ,
2023-12-18 17:12:05 -06:00
move : 'Move an object by x,y,z. If the first parameter is an array, uses up to the first three array values.' ,
2023-10-23 08:08:11 -05:00
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
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. ` ,
2024-02-29 13:54:33 -06:00
master : "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-12-24 09:14:46 -06:00
add _component : 'Add a component to the object by name.' ,
2024-01-01 07:44:43 -06:00
pin : 'Pin joint to another object. Acts as if a rigid rod is between the two objects.' ,
slide : 'Slide joint, similar to a pin but with min and max allowed distances.' ,
pivot : 'Pivot joint to an object, with the pivot given in world coordinates.' ,
groove : 'Groove joint. The groove is on to, from to local coordinates a and b, with this object anchored at anchor.' ,
damped _spring : 'Damped spring to another object. Length is the distance it wants to be, stiffness is the spring constant, and damping is the damping ratio. 1 is critical, < 1 is underdamped, > 1 is overdamped.' ,
damped _rotary _spring : 'Similar to damped spring but for rotation. Rest angle is the attempted angle.' ,
rotary _limit : 'Limit the angle relative to the to body between min and max.' ,
ratchet : 'Like a socket wrench, relative to to. ratch is the distance between clicks.' ,
gear : 'Keeps the angular velocity ratio of this body and to constant. Ratio is the gear ratio.' ,
2024-03-01 11:45:06 -06:00
motor : 'Keeps the relative angular velocity of this body to to at a constant rate. The most simple idea is for one of the bodies to be static, to the other is kept at rate.' ,
layer : 'Bitmask for collision layers.' ,
2024-03-21 21:07:24 -05:00
drawlayer : 'Layer for drawing. Higher numbers draw above lower ones.' ,
2024-04-03 08:37:29 -05:00
warp _filter : 'Bitmask for selecting what warps should affect this entity.' ,
2023-10-23 08:08:11 -05:00
} ;
2024-03-04 11:15:55 -06:00
global . ur = { } ;
2024-03-02 00:00:35 -06:00
2024-04-20 12:55:20 -05:00
if ( io . exists ( ` ${ io . dumpfolder } /ur.json ` ) )
ur = json . decode ( io . slurp ( ` ${ io . dumpfolder } /ur.json ` ) ) ;
2024-03-02 00:00:35 -06:00
else {
ur = { } ;
ur . _list = [ ] ;
}
2024-02-29 13:54:33 -06:00
/ * U R O B J E C T
ur {
name : fully qualified name of ur
text : file path to the script
data : file path to data
proto : resultant object of a freshly made entity
2023-11-17 15:16:13 -06:00
}
2024-02-29 13:54:33 -06:00
* /
2023-11-17 15:16:13 -06:00
2024-02-29 13:54:33 -06:00
/* Apply an ur u to an entity e */
/* u is given as */
2024-04-11 07:38:28 -05:00
function apply _ur ( u , ent ) {
2024-02-29 13:54:33 -06:00
if ( typeof u !== 'string' ) {
console . warn ( "Must give u as a string." ) ;
return ;
}
2024-03-13 03:51:44 -05:00
2024-02-29 13:54:33 -06:00
var urs = u . split ( '.' ) ;
2024-04-11 07:38:28 -05:00
if ( ! urs . every ( u => ur [ u ] ) ) {
console . error ( ` Attempted to make ur combo ${ u } but not every ur in the chain exists. ` ) ;
return ;
2024-02-29 13:54:33 -06:00
}
2024-04-11 07:38:28 -05:00
for ( var u of urs ) {
var text = u . text ;
var data = u . data ;
if ( typeof text === 'string' )
use ( text , ent ) ;
else if ( Array . isArray ( text ) )
text . forEach ( path => use ( path , ent ) ) ;
if ( typeof data === 'string' )
Object . merge ( ent , json . decode ( Resources . replstrs ( data ) ) ) ;
else if ( Array . isArray ( data ) ) {
2024-04-11 17:17:49 -05:00
data . forEach ( function ( path ) {
2024-04-11 07:38:28 -05:00
if ( typeof path === 'string' )
Object . merge ( ent , json . decode ( Resources . replstrs ( data ) ) ) ;
else if ( typeof path === 'object' )
Object . merge ( ent , path ) ;
} ) ;
}
2024-02-29 13:54:33 -06:00
}
2023-11-17 15:16:13 -06:00
}
2024-05-02 17:13:09 -05:00
var emptyur = {
name : "empty"
}
2024-04-04 17:28:11 -05:00
var getur = function ( text , data )
{
2024-05-02 17:13:09 -05:00
if ( ! text && ! data ) {
console . info ( 'empty ur' ) ;
return {
name : "empty"
} ;
}
2024-04-04 17:28:11 -05:00
var urstr = text + "+" + data ;
if ( ! ur [ urstr ] ) {
ur [ urstr ] = {
name : urstr ,
text : text ,
data : data
}
}
return ur [ urstr ] ;
}
2024-04-11 07:38:28 -05:00
var ur _from _file = function ( file ) {
var urname = file . name ( ) ;
if ( ur [ urname ] ) {
console . warn ( ` Tried to make another ur with the name ${ urname } from ${ file } , but it already exists. ` ) ;
return undefined ;
}
var newur = {
name : urname
} ;
ur [ urname ] = newur ;
ur . _list . push ( urname ) ;
return newur ;
}
2024-03-18 08:16:25 -05:00
game . loadurs = function ( ) {
2024-03-04 11:15:55 -06:00
ur = { } ;
ur . _list = [ ] ;
/* FIND ALL URS IN A PROJECT */
2024-04-04 17:28:11 -05:00
for ( var file of io . glob ( "**.ur" ) ) {
2024-04-11 07:38:28 -05:00
var newur = ur _from _file ( file ) ;
if ( ! newur ) continue ;
2024-04-12 13:53:00 -05:00
var uur = Resources . replstrs ( file ) ;
var urjson = json . decode ( uur ) ;
2024-04-11 07:38:28 -05:00
Object . assign ( newur , urjson ) ;
2024-04-04 17:28:11 -05:00
}
2024-04-11 07:38:28 -05:00
2024-04-14 14:53:41 -05:00
for ( var file of io . glob ( "**.jso" ) . filter ( f => ! ur [ f . name ( ) ] ) ) {
2024-03-04 11:15:55 -06:00
if ( file [ 0 ] === '.' || file [ 0 ] === '_' ) continue ;
2024-04-11 07:38:28 -05:00
var newur = ur _from _file ( file ) ;
if ( ! newur ) continue ;
2024-04-11 17:17:49 -05:00
newur . text = file ;
var data = file . set _ext ( ".json" ) ;
if ( io . exists ( data ) ) {
console . info ( ` Found matching json ${ data } for ${ file } ` ) ;
newur . data = data ;
}
2024-03-04 11:15:55 -06:00
}
2024-02-27 10:09:15 -06:00
2024-04-14 14:53:41 -05:00
for ( var file of io . glob ( "**.json" ) . filter ( f => ! ur [ f . name ( ) ] ) ) {
2024-03-04 11:15:55 -06:00
if ( file [ 0 ] === '.' || file [ 0 ] === '_' ) continue ;
2024-04-11 07:38:28 -05:00
var newur = ur _from _file ( file ) ;
if ( ! newur ) continue ;
Object . assign ( newur , {
data : file
} ) ;
2024-03-04 11:15:55 -06:00
}
2024-03-01 11:45:06 -06:00
} ;
2024-03-21 11:33:36 -05:00
2024-04-12 13:53:00 -05:00
game . ur = { } ;
game . ur . load = function ( str ) { }
game . ur . add _data = function ( str , data )
{
var nur = ur [ str ] ;
if ( ! nur ) {
console . warn ( ` Cannot add data to the ur ${ str } . ` ) ;
return ;
}
if ( ! Array . isArray ( ur . data ) ) {
var arr = [ ] ;
if ( ur . data ) arr . push ( ur . data ) ;
ur . data = arr ;
}
ur . data . push ( data ) ;
}
game . ur . save = function ( str )
{
var nur = ur [ str ] ;
if ( ! nur ) {
console . warn ( ` Cannot save ur ${ str } . ` ) ;
return ;
}
}
2024-05-02 17:13:09 -05:00
return { entity }