|
|
|
|
@@ -10,6 +10,25 @@ var cur = {};
|
|
|
|
|
cur.images = [];
|
|
|
|
|
cur.samplers = [];
|
|
|
|
|
|
|
|
|
|
function full_upload(mesh)
|
|
|
|
|
{
|
|
|
|
|
var cmds = render._main.acquire_cmd_buffer();
|
|
|
|
|
render._main.upload(cmds, [mesh.pos, mesh.uv, mesh.color, mesh.indices]);
|
|
|
|
|
cmds.submit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function queue_sprite_mesh(queue)
|
|
|
|
|
{
|
|
|
|
|
var sprites = queue.filter(x => x.type === 'sprite');
|
|
|
|
|
var mesh = render._main.make_sprite_mesh(sprites);
|
|
|
|
|
for (var i = 0; i < sprites.length; i++) {
|
|
|
|
|
sprites[i].mesh = mesh;
|
|
|
|
|
sprites[i].first_index = i*6;
|
|
|
|
|
sprites[i].num_indices = 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
full_upload(mesh);
|
|
|
|
|
}
|
|
|
|
|
function bind_pipeline(pass, pipeline)
|
|
|
|
|
{
|
|
|
|
|
make_pipeline(pipeline)
|
|
|
|
|
@@ -82,6 +101,16 @@ sprite_pipeline.target = {
|
|
|
|
|
depth: "d32 float s8"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
sprite_pipeline.blend = {
|
|
|
|
|
enabled:true,
|
|
|
|
|
src_rgb: "src_alpha", // zero/one/src_color/one_minus_src_color/dst_color/one_minus_dst_color/src_alpha/one_minus_src_alpha/dst_alpha/one_minus_dst_alpha/constant_color/one_minus_constant_color/src_alpha_saturate
|
|
|
|
|
dst_rgb: "one_minus_src_alpha",
|
|
|
|
|
op_rgb: "add", // add/sub/rev_sub/min/max
|
|
|
|
|
src_alpha: "one",
|
|
|
|
|
dst_alpha: "one_minus_src_alpha",
|
|
|
|
|
op_alpha: "add"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var dbgline_pipeline = Object.create(base_pipeline);
|
|
|
|
|
dbgline_pipeline.vertex = "dbgline.vert.hlsl"
|
|
|
|
|
dbgline_pipeline.fragment = "dbgline.frag.hlsl"
|
|
|
|
|
@@ -354,10 +383,9 @@ function upload_model(model)
|
|
|
|
|
var bufs = [];
|
|
|
|
|
for (var i in model) {
|
|
|
|
|
if (typeof model[i] !== 'object') continue;
|
|
|
|
|
if (i === 'indices') model[i].index = true;
|
|
|
|
|
bufs.push(model[i]);
|
|
|
|
|
}
|
|
|
|
|
tbuffer = render._main.upload(this, bufs, tbuffer);
|
|
|
|
|
render._main.upload(this, bufs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function bind_model(pass,pipeline,model)
|
|
|
|
|
@@ -391,27 +419,31 @@ function bind_mat(pass, pipeline, mat)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function group_sprites_by_texture(sprites)
|
|
|
|
|
function group_sprites_by_texture(sprites, mesh)
|
|
|
|
|
{
|
|
|
|
|
if (sprites.length === 0) return;
|
|
|
|
|
var groups = [];
|
|
|
|
|
var lasttex = sprites[0].image;
|
|
|
|
|
var group = [];
|
|
|
|
|
var first = 0;
|
|
|
|
|
for (var i = 0; i < sprites.length; i++) {
|
|
|
|
|
if (lasttex !== sprites[i].image) {
|
|
|
|
|
groups.push({image:lasttex, num_indices:(i-first)*6, first_index:first*6});
|
|
|
|
|
lasttex = sprites[i].image;
|
|
|
|
|
first = i;
|
|
|
|
|
group = [];
|
|
|
|
|
sprites[i].mesh = mesh;
|
|
|
|
|
sprites[i].first_index = i*6;
|
|
|
|
|
sprites[i].num_indices = 6;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
var groups = [];
|
|
|
|
|
var group = {image:sprites[0].image, first_index:0};
|
|
|
|
|
var count = 1;
|
|
|
|
|
for (var i = 1; i < sprites.length; i++) {
|
|
|
|
|
if (sprites[i].image === group.image) {
|
|
|
|
|
count++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
group.push(sprites[i])
|
|
|
|
|
group.num_indices = count*6;
|
|
|
|
|
var newgroup = {image:sprites[i].image, first_index:group.first_index+group.num_indices};
|
|
|
|
|
group = newgroup;
|
|
|
|
|
groups.push(group);
|
|
|
|
|
count=1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
groups.push({
|
|
|
|
|
image:lasttex,num_indices:(sprites.length-first)*6,first_index:first*6
|
|
|
|
|
})
|
|
|
|
|
group.num_indices = count*6;
|
|
|
|
|
|
|
|
|
|
return groups;
|
|
|
|
|
}
|
|
|
|
|
@@ -464,36 +496,49 @@ function render_camera(cmds, camera)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (render_queue.length == 0) return;
|
|
|
|
|
var spritemesh = render._main.make_sprite_mesh(render_queue);
|
|
|
|
|
queue_sprite_mesh(render_queue);
|
|
|
|
|
|
|
|
|
|
cmds.upload_model(spritemesh);
|
|
|
|
|
var pass = cmds.render_pass(camera.target);
|
|
|
|
|
var camera = prosperon.camera;
|
|
|
|
|
|
|
|
|
|
var draw_cmds = group_sprites_by_texture(render_queue);
|
|
|
|
|
for (var group of draw_cmds) {
|
|
|
|
|
var pipeline = sprite_pipeline;
|
|
|
|
|
var mesh = spritemesh;
|
|
|
|
|
var img = group.image;
|
|
|
|
|
img.sampler = std_sampler;
|
|
|
|
|
bind_pipeline(pass, pipeline);
|
|
|
|
|
bind_mat(pass, pipeline, {diffuse:img});
|
|
|
|
|
bind_model(pass,pipeline,spritemesh);
|
|
|
|
|
var camslot = get_pipeline_ubo_slot(pipeline, 'TransformBuffer');
|
|
|
|
|
if (typeof camslot !== 'undefined')
|
|
|
|
|
cmds.camera(camera, pass, undefined, camslot);
|
|
|
|
|
var modelslot = get_pipeline_ubo_slot(pipeline, "model");
|
|
|
|
|
if (typeof modelslot !== 'undefined') {
|
|
|
|
|
var ubo = ubo_obj_to_array(pipeline, 'model', sprite_model_ubo);
|
|
|
|
|
cmds.push_vertex_uniform_data(modelslot, ubo);
|
|
|
|
|
var pipeline;
|
|
|
|
|
var mesh;
|
|
|
|
|
var img;
|
|
|
|
|
var modelslot;
|
|
|
|
|
|
|
|
|
|
for (var group of render_queue) {
|
|
|
|
|
if (pipeline != group.pipeline) {
|
|
|
|
|
pipeline = group.pipeline;
|
|
|
|
|
bind_pipeline(pass, pipeline);
|
|
|
|
|
|
|
|
|
|
var camslot = get_pipeline_ubo_slot(pipeline, 'TransformBuffer');
|
|
|
|
|
if (typeof camslot !== 'undefined')
|
|
|
|
|
cmds.camera(camera, pass, undefined, camslot);
|
|
|
|
|
|
|
|
|
|
modelslot = get_pipeline_ubo_slot(pipeline, "model");
|
|
|
|
|
if (typeof modelslot !== 'undefined') {
|
|
|
|
|
var ubo = ubo_obj_to_array(pipeline, 'model', sprite_model_ubo);
|
|
|
|
|
cmds.push_vertex_uniform_data(modelslot, ubo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pass.draw_indexed(group.num_indices, 1, mesh.first_index, 0, 0);
|
|
|
|
|
|
|
|
|
|
if (mesh != group.mesh) {
|
|
|
|
|
mesh = group.mesh;
|
|
|
|
|
bind_model(pass,pipeline,mesh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (img != group.image) {
|
|
|
|
|
img = group.image;
|
|
|
|
|
img.sampler = std_sampler;
|
|
|
|
|
bind_mat(pass,pipeline,{diffuse:img});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pass.draw_indexed(group.num_indices, 1, group.first_index, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pass.end();
|
|
|
|
|
|
|
|
|
|
render_queue = [];
|
|
|
|
|
spritemesh = undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function mode_rect(src,dst,mode = "stretch")
|
|
|
|
|
@@ -573,6 +618,7 @@ var quad_model;
|
|
|
|
|
|
|
|
|
|
render.init = function () {
|
|
|
|
|
shader_type = render._main.shader_format()[0];
|
|
|
|
|
prosperon.font = render.get_font('fonts/c64.ttf', 8);
|
|
|
|
|
|
|
|
|
|
std_sampler = render._main.make_sampler({
|
|
|
|
|
min_filter: "nearest",
|
|
|
|
|
@@ -624,14 +670,11 @@ function draw_sprites()
|
|
|
|
|
var sparray = layer[img];
|
|
|
|
|
if (sparray.length === 0) continue;
|
|
|
|
|
var geometry = render._main.make_sprite_mesh(sparray);
|
|
|
|
|
render.geometry(sparray[0], geometry);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render.circle = function render_circle(pos, radius, color, inner_radius = 1) {
|
|
|
|
|
check_flush();
|
|
|
|
|
|
|
|
|
|
if (inner_radius >= 1) inner_radius = inner_radius / radius;
|
|
|
|
|
else if (inner_radius < 0) inner_radius = 1.0;
|
|
|
|
|
|
|
|
|
|
@@ -656,58 +699,6 @@ render.poly = function render_poly(points, color, transform) {
|
|
|
|
|
render.draw(buffer);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var nextflush = undefined;
|
|
|
|
|
function flush() {
|
|
|
|
|
nextflush?.();
|
|
|
|
|
nextflush = undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If flush_fn was already on deck, it does not flush. Otherwise, flushes and then sets the flush fn
|
|
|
|
|
function check_flush(flush_fn) {
|
|
|
|
|
if (!nextflush) nextflush = flush_fn;
|
|
|
|
|
else if (nextflush !== flush_fn) {
|
|
|
|
|
nextflush();
|
|
|
|
|
nextflush = flush_fn;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render.flush = check_flush;
|
|
|
|
|
render.forceflush = function forceflush()
|
|
|
|
|
{
|
|
|
|
|
if (nextflush) nextflush();
|
|
|
|
|
nextflush = undefined;
|
|
|
|
|
cur.shader = undefined;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var poly_cache = [];
|
|
|
|
|
var poly_idx = 0;
|
|
|
|
|
var poly_ssbo;
|
|
|
|
|
|
|
|
|
|
function poly_e() {
|
|
|
|
|
var e;
|
|
|
|
|
poly_idx++;
|
|
|
|
|
if (poly_idx > poly_cache.length) {
|
|
|
|
|
e = {
|
|
|
|
|
transform: os.make_transform(),
|
|
|
|
|
color: Color.white,
|
|
|
|
|
};
|
|
|
|
|
poly_cache.push(e);
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
var e = poly_cache[poly_idx - 1];
|
|
|
|
|
e.transform.unit();
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function flush_poly() {
|
|
|
|
|
if (poly_idx === 0) return;
|
|
|
|
|
render.use_shader(queued_shader, queued_pipe);
|
|
|
|
|
var base = render.make_particle_ssbo(poly_cache.slice(0, poly_idx), poly_ssbo);
|
|
|
|
|
render.use_mat({baseinstance:base});
|
|
|
|
|
render.draw(shape.quad, poly_ssbo, poly_idx);
|
|
|
|
|
poly_idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// render.line has uv and can be texture mapped; dbg_line is hardware standard lines
|
|
|
|
|
render.line = function render_line(points, color = Color.white, thickness = 1, pipe = base_pipeline) {
|
|
|
|
|
// render._main.line(points, color);
|
|
|
|
|
@@ -755,21 +746,22 @@ render.rectangle = function render_rectangle(rect, color = Color.white, pipe = b
|
|
|
|
|
render._main.fillrect(rect,color);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
render.text = function text(text, rect, font = cur_font, size = 0, color = Color.white, wrap = 0, pipe = base_pipeline) {
|
|
|
|
|
// if (typeof font === 'string')
|
|
|
|
|
// font = render.get_font(font)
|
|
|
|
|
// var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font);
|
|
|
|
|
// render._main.geometry(font.texture, mesh);
|
|
|
|
|
render.text = function text(text, rect, font = prosperon.font, size = 0, color = Color.white, wrap = 0, pipeline = sprite_pipeline) {
|
|
|
|
|
if (typeof font === 'string')
|
|
|
|
|
font = render.get_font(font)
|
|
|
|
|
var mesh = os.make_text_buffer(text, rect, 0, color, wrap, font);
|
|
|
|
|
full_upload(mesh)
|
|
|
|
|
|
|
|
|
|
render_queue.push({
|
|
|
|
|
type: 'text',
|
|
|
|
|
text,
|
|
|
|
|
rect,
|
|
|
|
|
font,
|
|
|
|
|
size,
|
|
|
|
|
color,
|
|
|
|
|
wrap,
|
|
|
|
|
pipe
|
|
|
|
|
type: 'geometry',
|
|
|
|
|
mesh: mesh,
|
|
|
|
|
image: font,
|
|
|
|
|
texture:font.texture,
|
|
|
|
|
pipeline,
|
|
|
|
|
first_index:0,
|
|
|
|
|
num_indices:mesh.indices.length
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (typeof font === 'string')
|
|
|
|
|
@@ -781,8 +773,6 @@ render.text = function text(text, rect, font = cur_font, size = 0, color = Color
|
|
|
|
|
if (rect.anchor_y)
|
|
|
|
|
pos.y -= rect.anchor_y*(font.ascent-font.descent);
|
|
|
|
|
os.make_text_buffer(str, pos, size, color, wrap, font); // this puts text into buffer
|
|
|
|
|
cur_font = font;
|
|
|
|
|
check_flush(render.flush_text);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var tttsize = render.text_size;
|
|
|
|
|
@@ -793,34 +783,6 @@ render.text_size = function(str, font, ...args)
|
|
|
|
|
return tttsize(str,font, ...args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lasttex = undefined;
|
|
|
|
|
var img_cache = [];
|
|
|
|
|
var img_idx = 0;
|
|
|
|
|
|
|
|
|
|
function flush_img() {
|
|
|
|
|
if (img_idx === 0) return;
|
|
|
|
|
render.use_shader(spritessboshader);
|
|
|
|
|
var startidx = render.make_sprite_ssbo(img_cache.slice(0, img_idx), sprite_ssbo);
|
|
|
|
|
render.use_mat({baseinstance:startidx});
|
|
|
|
|
cur.images = [lasttex];
|
|
|
|
|
render.draw(shape.quad, sprite_ssbo, img_idx);
|
|
|
|
|
lasttex = undefined;
|
|
|
|
|
img_idx = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function img_e() {
|
|
|
|
|
img_idx++;
|
|
|
|
|
if (img_idx > img_cache.length) {
|
|
|
|
|
var e = {
|
|
|
|
|
transform: os.make_transform(),
|
|
|
|
|
shade: Color.white,
|
|
|
|
|
};
|
|
|
|
|
img_cache.push(e);
|
|
|
|
|
return e;
|
|
|
|
|
}
|
|
|
|
|
return img_cache[img_idx - 1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var stencil_write = {
|
|
|
|
|
compare: "always",
|
|
|
|
|
fail_op: "replace",
|
|
|
|
|
@@ -850,7 +812,6 @@ render.stencil_writer = stencil_writer;
|
|
|
|
|
// objects by default draw where the stencil buffer is 0
|
|
|
|
|
render.fillmask = function fillmask(ref)
|
|
|
|
|
{
|
|
|
|
|
render.forceflush();
|
|
|
|
|
var pipe = stencil_writer(ref);
|
|
|
|
|
render.use_shader('screenfill.cg', pipe);
|
|
|
|
|
render.draw(shape.quad);
|
|
|
|
|
@@ -907,27 +868,11 @@ render.tile = function tile(image, rect = [0,0], color = Color.white)
|
|
|
|
|
|
|
|
|
|
var size = [rect.width ? rect.width : image_size.x, rect.height ? rect.height : image_size.y];
|
|
|
|
|
|
|
|
|
|
if (!lasttex) {
|
|
|
|
|
check_flush(flush_img);
|
|
|
|
|
lasttex = tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lasttex !== tex) {
|
|
|
|
|
flush_img();
|
|
|
|
|
lasttex = tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render._main.tile(image.texture, rect, image.rect, 1);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render.geometry = function geometry(material, geometry)
|
|
|
|
|
{
|
|
|
|
|
render._main.geometry(material.diffuse.texture, geometry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// queues to be flushed later
|
|
|
|
|
render.image = function image(image, rect = [0,0], rotation = 0, color = Color.white, pipeline = base_pipeline) {
|
|
|
|
|
render.image = function image(image, rect = [0,0], rotation = 0, color = Color.white, pipeline = sprite_pipeline) {
|
|
|
|
|
if (!image) throw Error ('Need an image to render.')
|
|
|
|
|
if (typeof image === "string")
|
|
|
|
|
image = game.texture(image);
|
|
|
|
|
@@ -937,6 +882,7 @@ render.image = function image(image, rect = [0,0], rotation = 0, color = Color.w
|
|
|
|
|
var T = os.make_transform();
|
|
|
|
|
T.rect(rect);
|
|
|
|
|
render_queue.push({
|
|
|
|
|
type: 'sprite',
|
|
|
|
|
transform: T,
|
|
|
|
|
color: color,
|
|
|
|
|
image:image,
|
|
|
|
|
@@ -949,71 +895,16 @@ render.images = function images(image, rects)
|
|
|
|
|
if (!image) throw Error ('Need an image to render.');
|
|
|
|
|
if (typeof image === "string") image = game.texture(image);
|
|
|
|
|
for (var rect of rects) render.image(image,rect);
|
|
|
|
|
return;
|
|
|
|
|
var tex = image.texture;
|
|
|
|
|
if (!tex) return;
|
|
|
|
|
|
|
|
|
|
var image_size = calc_image_size(image);
|
|
|
|
|
|
|
|
|
|
if (!lasttex) {
|
|
|
|
|
check_flush(flush_img);
|
|
|
|
|
lasttex = tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lasttex !== tex) {
|
|
|
|
|
flush_img();
|
|
|
|
|
lasttex = tex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// rects = rects.flat();
|
|
|
|
|
var rect = rects[0];
|
|
|
|
|
var size = [rect.width ? rect.width : image_size.x, rect.height ? rect.height : image_size.y];
|
|
|
|
|
var offset = size.scale([rect.anchor_x, rect.anchor_y]);
|
|
|
|
|
for (var rect of rects) {
|
|
|
|
|
var e = img_e();
|
|
|
|
|
var pos = [rect.x,rect.y].sub(offset);
|
|
|
|
|
e.transform.trs(pos, undefined, size);
|
|
|
|
|
e.image = image;
|
|
|
|
|
e.shade = Color.white;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// slice is given in pixels
|
|
|
|
|
render.slice9 = function slice9(image, rect = [0,0], slice = 0, color = Color.white) {
|
|
|
|
|
render.image(image,rect,undefined,color); return;
|
|
|
|
|
if (typeof image === 'string')
|
|
|
|
|
image = game.texture(image);
|
|
|
|
|
|
|
|
|
|
rect.width ??= image.texture.width;
|
|
|
|
|
rect.height ??= image.texture.height;
|
|
|
|
|
slice = clay.normalizeSpacing(slice);
|
|
|
|
|
|
|
|
|
|
render.image(image,rect,undefined,color);
|
|
|
|
|
render._main.slice9(image.texture, rect, slice);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var textssbos = [];
|
|
|
|
|
var tdraw = 0;
|
|
|
|
|
var cur_font = undefined;
|
|
|
|
|
|
|
|
|
|
render.flush_text = function flush_text() {
|
|
|
|
|
if (!render.textshader) return;
|
|
|
|
|
tdraw++;
|
|
|
|
|
if (textssbos.length < tdraw) textssbos.push(render.make_textssbo());
|
|
|
|
|
|
|
|
|
|
var textssbo = textssbos[tdraw - 1];
|
|
|
|
|
var amt = render.flushtext(textssbo); // load from buffer into ssbo
|
|
|
|
|
|
|
|
|
|
if (amt === 0) {
|
|
|
|
|
tdraw--;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render.use_shader(render.textshader);
|
|
|
|
|
render.use_mat({ text: cur_font.texture });
|
|
|
|
|
render.draw(shape.quad, textssbo, amt);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var fontcache = {};
|
|
|
|
|
var datas= [];
|
|
|
|
|
@@ -1034,6 +925,8 @@ render.get_font = function get_font(path,size)
|
|
|
|
|
return fontcache[fontstr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
render.doc = "Draw shapes in screen space.";
|
|
|
|
|
render.cross.doc = "Draw a cross centered at pos, with arm length size.";
|
|
|
|
|
render.arrow.doc = "Draw an arrow from start to end, with wings of length wingspan at angle wingangle.";
|
|
|
|
|
@@ -1296,7 +1189,6 @@ try {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
try { prosperon.appupdate(dt); } catch(e) { console.error(e) }
|
|
|
|
|
|
|
|
|
|
input.procdown();
|
|
|
|
|
try {
|
|
|
|
|
update_emitters(dt * game.timescale);
|
|
|
|
|
|