2023-12-18 06:45:27 -06:00
/* All draw in screen space */
2023-05-27 10:13:20 -05:00
var Shape = {
2023-12-15 12:45:09 -06:00
circle ( pos , radius , color ) { cmd ( 115 , pos , radius , color ) ; } ,
2023-12-18 06:45:27 -06:00
point ( pos , size , color ) {
color ? ? = Color . blue ;
Shape . circle ( pos , size , color ) ;
} ,
2023-12-19 17:28:45 -06:00
/* size here is arm length - size of 2 is 4 height total */
cross ( pos , size , color , angle ) {
angle ? ? = 0 ;
color ? ? = Color . red ;
var a = [
pos . add ( [ 0 , size ] ) ,
pos . add ( [ 0 , - size ] )
] ;
var b = [
pos . add ( [ size , 0 ] ) ,
pos . add ( [ - size , 0 ] )
] ;
Shape . line ( a , color ) ;
Shape . line ( b , color ) ;
} ,
2023-12-18 06:45:27 -06:00
2023-12-19 17:28:45 -06:00
arrow ( start , end , color , wingspan , wingangle ) {
2023-12-18 06:45:27 -06:00
color ? ? = Color . red ;
2023-12-19 17:28:45 -06:00
wingspan ? ? = 4 ;
wingangle ? ? = 10 ;
var dir = end . sub ( start ) . normalized ( ) ;
var wing1 = [
Vector . rotate ( dir , wingangle ) . scale ( wingspan ) . add ( end ) ,
end
] ;
var wing2 = [
Vector . rotate ( dir , - wingangle ) . scale ( wingspan ) . add ( end ) ,
end
] ;
Shape . line ( [ start , end ] , color ) ;
Shape . line ( wing1 , color ) ;
Shape . line ( wing2 , color ) ;
2023-12-18 06:45:27 -06:00
} ,
poly ( points , color ) { cmd _points ( 0 , points , color ) ; } ,
2023-12-27 14:16:43 -06:00
rectangle ( lowerleft , upperright , color ) {
var pos = lowerleft . add ( upperright ) . map ( x => x / 2 ) ;
var wh = [ upperright . x - lowerleft . x , upperright . y - lowerleft . y ] ;
Shape . box ( pos , wh , color ) ;
} ,
2023-12-18 06:45:27 -06:00
box ( pos , wh , color ) {
color ? ? = Color . white ;
cmd ( 53 , pos , wh , color ) ;
} ,
line ( points , color , type , thickness ) {
thickness ? ? = 1 ;
type ? ? = 0 ;
color ? ? = Color . white ;
switch ( type ) {
case 0 :
cmd ( 83 , points , color , thickness ) ;
}
} ,
2023-05-27 10:13:20 -05:00
} ;
2023-04-22 16:44:26 -05:00
var Debug = {
2023-12-13 19:53:09 -06:00
fn _break ( fn , obj ) {
if ( typeof fn !== 'function' ) return ;
obj ? ? = globalThis ;
var newfn = function ( ) {
console . log ( "broke" ) ;
fn ( ) ;
} ;
obj [ fn . name ] = newfn ;
} ,
2023-05-16 13:31:19 -05:00
draw _grid ( width , span , color ) {
color = color ? color : Color . green ;
cmd ( 47 , width , span , color ) ;
2023-04-22 16:44:26 -05:00
} ,
2023-12-15 12:45:09 -06:00
coordinate ( pos , size , color ) { GUI . text ( JSON . stringify ( pos . map ( p => Math . round ( p ) ) ) , pos , size , color ) ; } ,
2023-06-06 15:49:55 -05:00
boundingbox ( bb , color ) {
2023-08-14 17:20:30 -05:00
color ? ? = Color . white ;
2023-06-06 15:49:55 -05:00
cmd _points ( 0 , bb2points ( bb ) , color ) ;
} ,
2023-04-22 16:44:26 -05:00
2023-12-18 06:45:27 -06:00
numbered _point ( pos , n , color ) {
color ? ? = Color . white ;
Shape . point ( pos , 3 , color ) ;
GUI . text ( n , pos . add ( [ 0 , 4 ] ) , 1 , color ) ;
2023-04-22 16:44:26 -05:00
} ,
phys _drawing : false ,
draw _phys ( on ) {
this . phys _drawing = on ;
cmd ( 4 , this . phys _drawing ) ;
} ,
draw _obj _phys ( obj ) {
cmd ( 82 , obj . body ) ;
} ,
register _call ( fn , obj ) {
2023-08-28 17:00:53 -05:00
Register . debug . register ( fn , obj ) ;
2023-04-22 16:44:26 -05:00
} ,
2023-12-18 06:45:27 -06:00
gameobject ( go ) { cmd ( 15 , go . body ) ; } ,
2023-08-17 20:13:17 -05:00
draw _bb : false ,
draw _gizmos : false ,
draw _names : false ,
draw ( ) {
if ( this . draw _bb )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) { Debug . boundingbox ( x . boundingbox ( ) , Color . Debug . boundingbox . alpha ( 0.05 ) ) ; } ) ;
2023-08-17 20:13:17 -05:00
2023-10-04 08:18:09 -05:00
if ( Game . paused ( ) ) GUI . text ( "PAUSED" , [ 0 , 0 ] , 1 ) ;
2023-08-17 20:13:17 -05:00
if ( this . draw _gizmos )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) {
2023-08-17 20:13:17 -05:00
if ( ! x . icon ) return ;
2023-10-26 11:48:02 -05:00
GUI . image ( x . icon , world2screen ( x . pos ) ) ;
2023-08-17 20:13:17 -05:00
} ) ;
if ( this . draw _names )
2023-11-29 12:40:13 -06:00
Game . all _objects ( function ( x ) {
2023-09-23 12:35:02 -05:00
GUI . text ( x , world2screen ( x . pos ) . add ( [ 0 , 32 ] ) , 1 , Color . Debug . names ) ;
2023-08-17 20:13:17 -05:00
} ) ;
2023-08-24 16:22:52 -05:00
2023-09-12 12:45:54 -05:00
if ( Debug . Options . gif . rec ) {
2023-10-26 11:48:02 -05:00
GUI . text ( "REC" , [ 0 , 40 ] , 1 ) ;
GUI . text ( Time . seconds _to _timecode ( Time . time - Debug . Options . gif . start _time , Debug . Options . gif . fps ) , [ 0 , 30 ] , 1 ) ;
2023-09-12 12:45:54 -05:00
}
2023-09-12 00:02:57 -05:00
2023-10-04 08:18:09 -05:00
GUI . text ( Game . playing ( ) ? "PLAYING"
2023-08-27 21:57:19 -05:00
: Game . stepping ( ) ?
"STEP" :
Game . paused ( ) ?
2023-08-28 17:00:53 -05:00
"PAUSED; EDITING" :
"EDIT" , [ 0 , 0 ] , 1 ) ;
2023-08-17 20:13:17 -05:00
} ,
} ;
2023-12-18 17:12:05 -06:00
Debug . assert = function ( b , str )
{
str ? ? = "" ;
if ( ! b ) {
console . error ( ` Assertion failed. ${ str } ` ) ;
Game . quit ( ) ;
}
}
2023-08-17 20:13:17 -05:00
Debug . Options = { } ;
Debug . Options . Color = {
set trigger ( x ) { cmd ( 17 , x ) ; } ,
set debug ( x ) { cmd ( 16 , x ) ; } ,
2023-04-22 16:44:26 -05:00
} ;
var Gizmos = {
pick _gameobject _points ( worldpos , gameobject , points ) {
2023-11-29 17:31:41 -06:00
var idx = Math . grab _from _points ( worldpos , points . map ( gameobject . this2world , gameobject ) , 25 ) ;
2023-12-18 06:45:27 -06:00
if ( idx === - 1 ) return undefined ;
return idx ;
2023-04-22 16:44:26 -05:00
} ,
} ;
2023-06-07 08:41:09 -05:00
var Profile = {
2023-09-11 02:46:12 -05:00
tick _now ( ) { return cmd ( 127 ) ; } ,
ns ( ticks ) { return cmd ( 128 , ticks ) ; } ,
us ( ticks ) { return cmd ( 129 , ticks ) ; } ,
ms ( ticks ) { return cmd ( 130 , ticks ) ; } ,
2023-12-18 06:45:27 -06:00
best _t ( ns ) {
var e = ns ;
var qq = 'ns' ;
if ( e > 1000 ) {
e /= 1000 ;
qq = 'us' ;
if ( e > 1000 ) {
e /= 1000 ;
qq = 'ms' ;
}
}
return {
time : e ,
unit : qq
} ;
} ,
2023-09-11 02:46:12 -05:00
cpu ( fn , times , q ) {
2023-06-07 08:41:09 -05:00
times ? ? = 1 ;
2023-12-18 06:45:27 -06:00
q ? ? = "unnamed" ;
2023-09-11 02:46:12 -05:00
var start = Profile . tick _now ( ) ;
2023-06-07 08:41:09 -05:00
for ( var i = 0 ; i < times ; i ++ )
fn ( ) ;
2023-12-18 06:45:27 -06:00
2023-09-11 02:46:12 -05:00
var elapsed = Profile . tick _now ( ) - start ;
2023-12-18 06:45:27 -06:00
var avgt = Profile . best _t ( elapsed / times ) ;
var totalt = Profile . best _t ( elapsed ) ;
console . say ( ` Profile [ ${ q } ]: ${ avgt . time . toFixed ( 3 ) } ${ avgt . unit } average [ ${ totalt . time . toFixed ( 3 ) } ${ totalt . unit } for ${ times } loops] ` ) ;
2023-06-07 08:41:09 -05:00
} ,
2023-08-17 20:13:17 -05:00
get fps ( ) { return sys _cmd ( 8 ) ; } ,
2023-06-07 08:41:09 -05:00
} ;
2023-04-22 16:44:26 -05:00
2023-12-18 06:45:27 -06:00
Profile . test = {
barecall ( ) { profile ( 0 ) ; } ,
unpack _num ( n ) { profile ( 1 , n ) ; } ,
unpack _array ( n ) { profile ( 2 , n ) ; } ,
pack _num ( ) { profile ( 3 ) ; } ,
pack _string ( ) { profile ( 6 ) ; } ,
unpack _string ( s ) { profile ( 4 , s ) ; } ,
unpack _32farr ( a ) { profile ( 5 , a ) ; } ,
} ;
2023-10-23 08:08:11 -05:00
Profile . cpu . doc = ` Output the time it takes to do a given function n number of times. Provide 'q' as "ns", "us", or "ms" to output the time taken in the requested resolution. ` ;
2023-08-28 17:00:53 -05:00
/* These controls are available during editing, and during play of debug builds */
2023-08-24 16:22:52 -05:00
var DebugControls = { } ;
2023-10-16 19:59:58 -05:00
DebugControls . toString = function ( ) { return "Debug" ; } ;
2023-08-24 16:22:52 -05:00
DebugControls . inputs = { } ;
DebugControls . inputs . f1 = function ( ) { Debug . draw _phys ( ! Debug . phys _drawing ) ; } ;
DebugControls . inputs . f1 . doc = "Draw physics debugging aids." ;
2023-09-20 08:11:14 -05:00
//DebugControls.inputs.f3 = function() { Debug.draw_bb = !Debug.draw_bb; };
//DebugControls.inputs.f3.doc = "Toggle drawing bounding boxes.";
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f4 = function ( ) {
2023-10-11 17:22:41 -05:00
// Debug.draw_names = !Debug.draw_names;
// Debug.draw_gizmos = !Debug.draw_gizmos;
2023-08-24 16:22:52 -05:00
} ;
DebugControls . inputs . f4 . doc = "Toggle drawing gizmos and names of objects." ;
2023-09-12 00:02:57 -05:00
Debug . Options . gif = {
2023-09-12 12:45:54 -05:00
w : 640 , /* Max width */
h : 480 , /* Max height */
stretch : false , /* True if you want to stretch */
2023-09-13 07:31:00 -05:00
cpf : 4 ,
2023-09-14 12:49:29 -05:00
depth : 16 ,
2023-09-12 00:02:57 -05:00
file : "out.gif" ,
rec : false ,
2023-09-12 12:45:54 -05:00
secs : 6 ,
start _time : 0 ,
fps : 0 ,
start ( ) {
var w = this . w ;
var h = this . h ;
if ( ! this . stretch ) {
var win = Window . height / Window . width ;
var gif = h / w ;
if ( gif > win )
h = w * win ;
else
w = h / win ;
}
cmd ( 131 , w , h , this . cpf , this . depth ) ;
this . rec = true ;
this . fps = ( 1 / this . cpf ) * 100 ;
this . start _time = Time . time ;
2023-09-13 07:31:00 -05:00
timer . oneshot ( this . stop . bind ( this ) , this . secs , this , true ) ;
2023-09-12 12:45:54 -05:00
} ,
stop ( ) {
if ( ! this . rec ) return ;
cmd ( 132 , this . file ) ;
this . rec = false ;
} ,
2023-09-12 00:02:57 -05:00
} ;
2023-09-12 12:45:54 -05:00
2023-09-25 12:29:04 -05:00
DebugControls . inputs . f8 = function ( ) {
var now = new Date ( ) ;
Debug . Options . gif . file = now . toISOString ( ) + ".gif" ;
Debug . Options . gif . start ( ) ;
} ;
DebugControls . inputs . f9 = function ( ) {
Debug . Options . gif . stop ( ) ;
}
2023-09-12 00:02:57 -05:00
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f10 = function ( ) { Time . timescale = 0.1 ; } ;
DebugControls . inputs . f10 . doc = "Toggle timescale to 1/10." ;
2023-08-27 21:57:19 -05:00
DebugControls . inputs . f10 . released = function ( ) { Time . timescale = 1.0 ; } ;
2023-08-24 16:22:52 -05:00
DebugControls . inputs . f12 = function ( ) { GUI . defaults . debug = ! GUI . defaults . debug ; Log . warn ( "GUI toggle debug" ) ; } ;
DebugControls . inputs . f12 . doc = "Toggle drawing GUI debugging aids." ;
DebugControls . inputs [ 'M-1' ] = Render . normal ;
Render . normal . doc = "Render mode for enabling all shaders and lighting effects." ;
DebugControls . inputs [ 'M-2' ] = Render . wireframe ;
Render . wireframe . doc = "Render mode to see wireframes of all models." ;
2023-08-17 20:13:17 -05:00
2023-08-28 17:00:53 -05:00
DebugControls . inputs [ 'C-M-f' ] = function ( ) { } ;
DebugControls . inputs [ 'C-M-f' ] . doc = "Enter camera fly mode." ;
2023-08-17 20:13:17 -05:00
var Time = {
set timescale ( x ) { cmd ( 3 , x ) ; } ,
2023-08-28 17:00:53 -05:00
get timescale ( ) { return cmd ( 121 ) ; } ,
2023-08-17 20:13:17 -05:00
set updateMS ( x ) { cmd ( 6 , x ) ; } ,
set physMS ( x ) { cmd ( 7 , x ) ; } ,
set renderMS ( x ) { cmd ( 5 , x ) ; } ,
2023-08-29 17:11:36 -05:00
2023-09-12 12:45:54 -05:00
get time ( ) { return cmd ( 133 ) ; } ,
seconds _to _timecode ( secs , fps )
{
var s = Math . trunc ( secs ) ;
secs -= s ;
var f = Math . trunc ( fps * secs ) ;
return ` ${ s } : ${ f } ` ;
} ,
2023-08-29 17:11:36 -05:00
pause ( ) {
2023-11-07 17:24:26 -06:00
Time . stash = Time . timescale ;
2023-08-29 17:11:36 -05:00
Time . timescale = 0 ;
} ,
play ( ) {
if ( ! Time . stash ) {
Log . warn ( "Tried to resume time without calling Time.pause first." ) ;
return ;
}
Time . timescale = Time . stash ;
} ,
2023-05-24 20:45:50 -05:00
} ;
2023-10-23 08:08:11 -05:00
Time . doc = { } ;
Time . doc . timescale = "Get and set the timescale. 1 is normal time; 0.5 is half speed; etc." ;
Time . doc . updateMS = "Set the ms per game update." ;
Time . doc . physMS = "Set the ms per physics update." ;
Time . doc . renderMS = "Set the ms per render update." ;
Time . doc . time = "Seconds elapsed since the game started." ;
Time . doc . pause = "Pause the game by setting the timescale to 0; remembers the current timescale on play." ;
Time . doc . play = "Resume the game after using Time.pause." ;
2023-08-28 17:00:53 -05:00
Player . players [ 0 ] . control ( DebugControls ) ;
Register . gui . register ( Debug . draw , Debug ) ;
2023-10-17 12:22:06 -05:00
2023-11-29 17:31:41 -06:00
var console = Object . create ( Log ) ;
2023-12-09 22:09:15 -06:00
console . log = function ( str )
{
console . say ( time . text ( time . now ( ) , 'yyyy-m-dd hh:nn:ss' ) + " " + str ) ;
}
2023-10-17 12:22:06 -05:00
console . clear = function ( )
{
cmd ( 146 ) ;
}
2023-10-23 08:08:11 -05:00
var API = { } ;
API . doc _entry = function ( obj , key )
{
var d = obj . doc ;
var doc = "" ;
var title = key ;
var o = obj [ key ] ;
if ( typeof o === 'undefined' && obj . impl && typeof obj . impl [ key ] !== 'undefined' )
o = obj . impl [ key ] ;
var t = typeof o ;
if ( t === 'object' && Array . isArray ( o ) ) t = 'array' ;
if ( t === 'function' ) {
title = o . toString ( ) . tofirst ( ')' ) + ")" ;
if ( o . doc ) doc = o . doc ;
t = "" ;
}
if ( t === 'undefined' ) t = "" ;
if ( t ) t = "**" + t + "**" ;
if ( ! doc ) {
if ( d && d [ key ] ) doc = d [ key ] ;
else return "" ;
}
return ` ### \` ${ title } \`
$ { t }
$ { doc }
` ;
}
API . print _doc = function ( name )
{
var obj = eval ( name ) ;
if ( ! obj . doc ) {
Log . warn ( ` Object has no doc sidecar. ` ) ;
return ;
}
var mdoc = "# " + name + " API #\n" ;
if ( obj . doc ? . doc ) mdoc += obj . doc . doc + "\n" ;
else if ( typeof obj . doc === 'string' ) mdoc += obj . doc + "\n" ;
for ( var key in obj ) {
if ( key === 'doc' ) continue ;
2023-10-26 11:48:02 -05:00
if ( key === 'toString' ) continue ;
2023-10-23 08:08:11 -05:00
mdoc += API . doc _entry ( obj , key ) ;
}
return mdoc ;
}