2023-09-08 12:35:06 -05:00
function grab _from _points ( pos , points , slop ) {
var shortest = slop ;
var idx = - 1 ;
points . forEach ( function ( x , i ) {
if ( Vector . length ( pos . sub ( x ) ) < shortest ) {
shortest = Vector . length ( pos . sub ( x ) ) ;
idx = i ;
}
} ) ;
return idx ;
} ;
2023-11-07 12:45:52 -06:00
var actor = { } ;
actor . spawn = function ( ur , config ) { } ;
actor . die = function ( actor ) { } ;
actor . kill = function ( actor ) { } ;
actor . delay = function ( fn , seconds ) { } ;
actor . clock = function ( fn ) { } ;
2023-09-08 12:35:06 -05:00
var gameobject = {
2023-10-04 17:57:37 -05:00
impl : {
2023-10-17 12:22:06 -05:00
full _path ( ) {
return this . path _from ( Primum ) ;
} ,
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
timers : [ ] ,
delay ( fn , seconds ) {
var t = timer . oneshot ( fn , seconds , this , false ) ;
2023-11-08 01:39:10 -06:00
this . timers . push ( t ) ;
2023-11-07 12:45:52 -06:00
return function ( ) { t . kill ( ) ; } ;
} ,
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-10-26 11:48:02 -05:00
sgscale ( x ) { cmd ( 36 , this . body , x ) } ,
2023-10-06 12:38:49 -05:00
get scale ( ) {
if ( ! this . level ) return this . gscale ( ) ;
return this . gscale ( ) / this . level . gscale ( ) ;
} ,
2023-09-21 08:38:23 -05:00
set scale ( x ) {
2023-10-06 12:38:49 -05:00
if ( this . level )
x *= this . level . gscale ( ) ;
2023-10-26 11:48:02 -05:00
var pct = x / this . gscale ( ) ;
2023-09-21 08:38:23 -05:00
cmd ( 36 , this . body , x ) ;
2023-10-09 18:10:10 -05:00
this . objects ? . forEach ( function ( obj ) {
2023-10-26 11:48:02 -05:00
obj . sgscale ( obj . gscale ( ) * pct ) ;
2023-10-02 07:58:17 -05:00
obj . pos = obj . pos . scale ( pct ) ;
} ) ;
2023-09-21 08:38:23 -05:00
} ,
2023-09-14 17:37:04 -05:00
get flipx ( ) { return cmd ( 104 , this . body ) ; } ,
2023-09-21 08:38:23 -05:00
set flipx ( x ) {
cmd ( 55 , this . body , x ) ;
return ;
this . objects . forEach ( function ( obj ) {
obj . flipx = ! obj . flipx ;
2023-10-02 07:58:17 -05:00
var rp = obj . pos ;
2023-10-02 17:03:01 -05:00
obj . pos = [ - rp . x , rp . y ] . add ( this . worldpos ( ) ) ;
2023-09-21 08:38:23 -05:00
obj . angle = - obj . angle ;
} , this ) ;
} ,
2023-09-14 17:37:04 -05:00
get flipy ( ) { return cmd ( 105 , this . body ) ; } ,
2023-09-21 08:38:23 -05:00
set flipy ( x ) {
cmd ( 56 , this . body , x ) ;
return ;
this . objects . forEach ( function ( obj ) {
2023-10-02 07:58:17 -05:00
var rp = obj . pos ;
2023-10-02 17:03:01 -05:00
obj . pos = [ rp . x , - rp . y ] . add ( this . worldpos ( ) ) ;
2023-09-21 08:38:23 -05:00
obj . angle = - obj . angle ;
} , this ) ;
} ,
2023-10-04 17:57:37 -05:00
set pos ( x ) {
2023-10-26 11:48:02 -05:00
this . set _worldpos ( Vector . rotate ( x . scale ( this . level . gscale ( ) ) , Math . deg2rad ( this . level . worldangle ( ) ) ) . add ( this . level . worldpos ( ) ) ) ;
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-10-02 17:03:01 -05:00
var offset = this . worldpos ( ) . sub ( this . level . worldpos ( ) ) ;
2023-10-26 11:48:02 -05:00
offset = Vector . rotate ( offset , - Math . deg2rad ( this . level . angle ) ) ;
offset = offset . scale ( 1 / this . level . gscale ( ) ) ;
return offset ;
2023-10-02 07:58:17 -05: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-10-04 17:57:37 -05:00
set phys ( x ) { set _body ( 1 , this . body , x ) ; } ,
get phys ( ) { return q _body ( 0 , this . body ) ; } ,
2023-11-07 17:24:26 -06:00
// set mask(x) { cmd(41, this.body, x); },
// get mask() { return cmd(43, this.body); },
// set category(x) { cmd(40, this.body, x); },
// get category() { return cmd(42, this.body); },
2023-10-04 17:57:37 -05:00
get velocity ( ) { return q _body ( 3 , this . body ) ; } ,
set velocity ( x ) { set _body ( 9 , this . body , x ) ; } ,
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 ) {
var diff = x . sub ( this . worldpos ( ) ) ;
this . objects . forEach ( function ( x ) { x . set _worldpos ( x . worldpos ( ) . add ( diff ) ) ; } ) ;
2023-10-02 07:58:17 -05:00
set _body ( 2 , this . body , x ) ;
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 ) ;
// x.angle = x.angle + 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-09-21 08:38:23 -05:00
2023-10-05 17:30:17 -05:00
set _body ( 0 , this . body , Math . deg2rad ( x - this . level . worldangle ( ) ) ) ;
} ,
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
} ,
} ,
draw _layer : 1 ,
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 ) ; } ,
torque ( val ) { cmd ( 153 , this . body , val ) ; } ,
2023-10-26 11:48:02 -05:00
world2this ( pos ) { return cmd ( 70 , this . body , pos ) ; } ,
this2world ( pos ) { return cmd ( 71 , this . body , pos ) ; } ,
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 ) ; } ,
on _ground ( ) { return ! this . in _air ( ) ; } ,
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-10-30 17:41:32 -05:00
var jobj = this . json _obj ( ) ;
delete jobj . objects ;
Object . keys ( jobj ) . forEach ( function ( x ) {
this [ x ] = this . _ _proto _ _ [ x ] ;
} , 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-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-06 07:05:27 -06:00
pos : [ 0 , 0 ] ,
angle : 0 ,
velocity : [ 0 , 0 ] ,
angularvelocity : 0 ,
2023-11-02 17:25:00 -05:00
phys : Physics . static ,
2023-10-04 17:57:37 -05:00
flipx : false ,
flipy : false ,
scale : 1 ,
elasticity : 0.5 ,
friction : 1 ,
2023-11-06 07:05:27 -06:00
gravity : true ,
max _velocity : Infinity ,
max _angularvelocity : Infinity ,
2023-10-04 17:57:37 -05:00
mass : 1 ,
layer : 0 ,
2023-10-09 18:10:10 -05:00
worldpos ( ) { return [ 0 , 0 ] ; } ,
2023-10-23 08:08:11 -05:00
2023-10-04 17:57:37 -05:00
save : true ,
selectable : true ,
ed _locked : false ,
disable ( ) { this . components . forEach ( function ( x ) { x . disable ( ) ; } ) ; } ,
enable ( ) { this . components . forEach ( function ( x ) { x . enable ( ) ; } ) ; } ,
2023-10-10 17:37:58 -05:00
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
full _obj ( ) {
} ,
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-09-14 17:37:04 -05:00
kill ( ) {
if ( this . body === - 1 ) {
Log . warn ( ` Object is already dead! ` ) ;
return ;
}
2023-10-16 09:40:43 -05:00
2023-09-14 17:37:04 -05:00
2023-10-04 08:18:09 -05:00
// Register.endofloop(() => {
2023-10-16 09:40:43 -05:00
// cmd(2, this.body);
q _body ( 8 , this . body ) ;
2023-10-11 17:22:41 -05:00
Game . unregister _obj ( this ) ;
2023-11-08 01:39:10 -06:00
this . timers . forEach ( function ( t ) {
if ( ! t ) return ;
t . kill ( ) ;
} ) ;
2023-10-11 17:22:41 -05:00
if ( this . level ) {
2023-10-04 08:18:09 -05:00
this . level . remove _obj ( this ) ;
2023-10-11 17:22:41 -05:00
this . level = undefined ;
}
2023-09-14 17:37:04 -05:00
2023-10-29 16:39:45 -05:00
Player . do _uncontrol ( this ) ;
2023-09-14 17:37:04 -05:00
Register . unregister _obj ( this ) ;
2023-10-30 17:41:32 -05:00
if ( this . _ _proto _ _ . instances )
this . _ _proto _ _ . instances . remove ( this ) ;
2023-09-14 17:37:04 -05:00
this . body = - 1 ;
2023-10-16 09:40:43 -05:00
2023-09-14 17:37:04 -05:00
for ( var key in this . components ) {
Register . unregister _obj ( this . components [ key ] ) ;
2023-10-16 09:40:43 -05:00
Log . info ( ` Destroying component ${ key } ` ) ;
2023-09-14 17:37:04 -05:00
this . components [ key ] . kill ( ) ;
2023-10-11 17:22:41 -05:00
this . components . gameobject = undefined ;
2023-09-14 17:37:04 -05:00
}
2023-10-11 17:22:41 -05:00
delete this . components ;
2023-09-14 17:37:04 -05:00
2023-10-16 09:40:43 -05:00
this . clear ( ) ;
2023-10-04 08:18:09 -05:00
2023-09-25 16:34:48 -05:00
if ( typeof this . stop === 'function' )
this . stop ( ) ;
2023-10-04 08:18:09 -05:00
// });
2023-10-17 12:22:06 -05:00
2023-09-14 17:37:04 -05:00
} ,
up ( ) { return [ 0 , 1 ] . rotate ( Math . deg2rad ( this . angle ) ) ; } ,
2023-09-25 16:34:48 -05:00
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-09-20 13:33:11 -05: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-26 11:48:02 -05:00
// obj.toJSON = obj.transform_obj;
2023-10-30 17:41:32 -05:00
if ( this . instances )
this . instances . push ( obj ) ;
2023-10-18 17:20:23 -05:00
// Log.warn(`Made an object from ${this.toString()}`);
// Log.warn(this.instances.length);
2023-09-25 16:34:48 -05:00
obj . body = make _gameobject ( ) ;
obj . components = { } ;
2023-09-29 13:16:59 -05:00
obj . objects = { } ;
2023-10-10 17:37:58 -05:00
assign _impl ( obj , gameobject . impl ) ;
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 ,
model : Object . create ( this ) ,
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-10-05 17:30:17 -05:00
obj . ur = this . toString ( ) ;
2023-09-20 13:33:11 -05:00
Game . register _obj ( obj ) ;
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 ) ;
Object . hide ( obj , 'ur' , 'body' , 'components' , 'objects' , '_ed' , 'level' ) ;
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-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 ) {
if ( typeof comp [ 'comp' ] !== 'string' ) return ;
} ,
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-10-04 17:57:37 -05:00
gameobject . impl . 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." ,
flipx : "Set the object to be flipped on its x axis." ,
flipy : "Set the object to be flipped on its y axis." ,
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-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 ) {
var upperpath = path . slice ( 0 , - 1 ) ;
upperur = prototypes . get _ur ( upperpath . join ( '/' ) ) ;
2023-09-26 13:34:02 -05:00
if ( ! upperur ) {
Log . error ( ` Attempted to create an UR ${ urpath } , but ${ upperpath } is not a defined UR. ` ) ;
return undefined ;
}
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-10-18 17:20:23 -05:00
// var urs = urpath.split('.');
// var u = ur;
// for (var i = 0; i < urs.length; i++)
// u = u[urs[i]] = u[urs[i]] || newur;
//Object.dig(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 . from _obj = function ( name , obj )
{
2023-10-04 17:57:37 -05:00
var newur = Object . copy ( gameobject , obj ) ;
2023-10-02 07:58:17 -05:00
prototypes . ur [ name ] = newur ;
2023-10-06 12:38:49 -05:00
prototypes . list . push ( name ) ;
2023-10-02 07:58:17 -05:00
newur . toString = function ( ) { return name ; } ;
2023-09-12 17:19:46 -05:00
return prototypes . ur [ name ] ;
}
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 ;
prototypes . from _obj ( "camera2d" , {
2023-09-15 22:40:19 -05:00
phys : Physics . kinematic ,
2023-09-12 17:19:46 -05:00
speed : 300 ,
2023-11-08 01:39:10 -06:00
get zoom ( ) {
var z = Game . native . y / Window . dimensions . y ;
return cmd ( 135 ) / z ;
} ,
2023-09-12 17:19:46 -05:00
set zoom ( x ) {
2023-11-08 01:39:10 -06:00
x = Math . clamp ( x , 0.1 , 10 ) ;
var z = Game . native . y / Window . dimensions . y ;
z *= x ;
cmd ( 62 , z ) ;
2023-09-12 17:19:46 -05:00
} ,
2023-09-15 22:40:19 -05:00
2023-09-12 17:19:46 -05:00
speedmult : 1.0 ,
selectable : false ,
2023-09-18 21:55:37 -05:00
world2this ( pos ) { return cmd ( 70 , this . body , pos ) ; } ,
this2world ( pos ) { return cmd ( 71 , this . body , pos ) ; } ,
2023-09-12 17:19:46 -05:00
view2world ( pos ) {
2023-09-18 21:55:37 -05:00
return cmd ( 137 , pos ) ;
2023-09-12 17:19:46 -05:00
} ,
world2view ( pos ) {
2023-09-18 21:55:37 -05:00
return cmd ( 136 , pos ) ;
2023-09-12 17:19:46 -05:00
} ,
} ) ;
prototypes . from _obj ( "arena" , { } ) ;
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
}