From 13c9c8d99e461d069526c93aea435e2be9a6ad00 Mon Sep 17 00:00:00 2001 From: RandomityGuy <31925790+RandomityGuy@users.noreply.github.com> Date: Tue, 16 Jul 2024 18:47:39 +0530 Subject: [PATCH] some optimizations --- src/DtsObject.hx | 104 ++++++++----- src/DynamicPolygon.hx | 339 +++++++++-------------------------------- src/InstanceManager.hx | 35 +++-- src/Util.hx | 11 +- src/dts/Sequence.hx | 1 + src/gui/PlayGui.hx | 18 ++- 6 files changed, 180 insertions(+), 328 deletions(-) diff --git a/src/DtsObject.hx b/src/DtsObject.hx index d85266ab..84c8bf49 100644 --- a/src/DtsObject.hx +++ b/src/DtsObject.hx @@ -1,5 +1,6 @@ package src; +import h3d.prim.DynamicPrimitive; import h3d.scene.MultiMaterial; import shaders.EnvMap; import h3d.shader.CubeMap; @@ -52,13 +53,6 @@ var dtsMaterials = [ "pball-round-bottm" => {friction: 0.5, restitution: 0.0, force: 15.0} ]; -typedef GraphNode = { - var index:Int; - var node:Node; - var children:Array; - var parent:GraphNode; -} - typedef MaterialGeometry = { var vertices:Array; var normals:Array; @@ -66,12 +60,15 @@ typedef MaterialGeometry = { var indices:Array; } -typedef SkinMeshData = { +@:structInit +@:publicFields +class SkinMeshData { var meshIndex:Int; - var vertices:Array; - var normals:Array; + var vertices:Array; // Turn THIS into a FloatBuffer + var normals:Array; // SAME HERE var indices:Array; var geometry:Object; + var primitives:Array; } @:publicFields @@ -88,7 +85,7 @@ class DtsObject extends GameObject { var matNameOverride:Map = new Map(); var sequenceKeyframeOverride:Map = new Map(); - var lastSequenceKeyframes:Map = new Map(); + var lastSequenceKeyframes:Array = []; var graphNodes:Array = []; var dirtyTransforms:Array = []; @@ -272,22 +269,39 @@ class DtsObject extends GameObject { var vertices = mesh.vertices.map(v -> new Vector(-v.x, v.y, v.z)); var vertexNormals = mesh.normals.map(v -> new Vector(-v.x, v.y, v.z)); var geometry = this.generateMaterialGeometry(mesh, vertices, vertexNormals); + var prims = []; for (k in 0...geometry.length) { if (geometry[k].vertices.length == 0) continue; - var poly = new DynamicPolygon(geometry[k].vertices.map(x -> x.toPoint())); - poly.normals = geometry[k].normals.map(x -> x.toPoint()); - poly.uvs = geometry[k].uvs; + var poly = new DynamicPolygon(); + poly.addPoints(geometry[k].vertices.map(x -> x.toPoint())); + poly.addNormals(geometry[k].normals.map(x -> x.toPoint())); + poly.addUVs(geometry[k].uvs); var obj = new MultiMaterial(poly, [materials[k]], skinObj); + + prims.push(poly); + } + var flatVerts = []; + var flatNormals = []; + for (v in vertices) { + flatVerts.push(v.x); + flatVerts.push(v.y); + flatVerts.push(v.z); + } + for (n in vertexNormals) { + flatNormals.push(n.x); + flatNormals.push(n.y); + flatNormals.push(n.z); } skinMeshData = { meshIndex: i, - vertices: vertices, - normals: vertexNormals, + vertices: flatVerts, + normals: flatNormals, indices: [], - geometry: skinObj + geometry: skinObj, + primitives: prims }; var idx = geometry.map(x -> x.indices); for (indexes in idx) { @@ -310,12 +324,17 @@ class DtsObject extends GameObject { vertices: [], normals: [], indices: [], - geometry: skinObj + geometry: skinObj, + primitives: [] }; } } } + for (seq in this.dts.sequences) { + lastSequenceKeyframes.push(0); + } + if (!this.isInstanced) { for (i in 0...this.materials.length) { var info = this.materialInfos.get(this.materials[i]); @@ -807,7 +826,8 @@ class DtsObject extends GameObject { if (this.currentOpacity == 0) return; - for (sequence in this.dts.sequences) { + for (i in 0...this.dts.sequences.length) { + var sequence = this.dts.sequences[i]; if (!this.showSequences) break; if (!this.hasNonVisualSequences) @@ -824,9 +844,9 @@ class DtsObject extends GameObject { var scales:Array = null; var actualKeyframe = this.sequenceKeyframeOverride.exists(sequence) ? this.sequenceKeyframeOverride.get(sequence) : ((completion * sequence.numKeyFrames) % sequence.numKeyFrames); - if (this.lastSequenceKeyframes.get(sequence) == actualKeyframe) + if (lastSequenceKeyframes[i] == actualKeyframe) continue; - lastSequenceKeyframes.set(sequence, actualKeyframe); + lastSequenceKeyframes[i] = actualKeyframe; var keyframeLow = Math.floor(actualKeyframe); var keyframeHigh = Math.ceil(actualKeyframe) % sequence.numKeyFrames; @@ -931,8 +951,8 @@ class DtsObject extends GameObject { var mesh = this.dts.meshes[info.meshIndex]; for (i in 0...info.vertices.length) { - info.vertices[i].set(0, 0, 0); - info.normals[i].set(0, 0, 0); + info.vertices[i] = 0; + info.normals[i] = 0; } var boneTransformations = []; @@ -966,34 +986,42 @@ class DtsObject extends GameObject { Util.m_matF_x_vectorF(mat, vec2); vec2.load(vec2.multiply(mesh.weights[i])); - info.vertices[vIndex].load(info.vertices[vIndex].add(vec)); - info.normals[vIndex].load(info.normals[vIndex].add(vec2)); + info.vertices[3 * vIndex] = info.vertices[3 * vIndex] + vec.x; + info.vertices[3 * vIndex + 1] = info.vertices[3 * vIndex + 1] + vec.y; + info.vertices[3 * vIndex + 2] = info.vertices[3 * vIndex + 2] + vec.z; + info.normals[3 * vIndex] = info.normals[3 * vIndex] + vec2.x; + info.normals[3 * vIndex + 1] = info.normals[3 * vIndex + 1] + vec2.y; + info.normals[3 * vIndex + 2] = info.normals[3 * vIndex + 2] + vec2.z; } - for (i in 0...info.normals.length) { - var norm = info.normals[i]; + for (i in 0...Std.int(info.normals.length / 3)) { + var norm = new Vector(info.normals[3 * i], info.normals[3 * i + 1], info.normals[3 * i + 2]); var len2 = norm.dot(norm); - if (len2 > 0.01) + if (len2 > 0.01) { norm.normalize(); + + info.normals[3 * i] = norm.x; + info.normals[3 * i + 1] = norm.y; + info.normals[3 * i + 2] = norm.z; + } } var meshIndex = 0; - var mesh:Mesh = cast info.geometry.children[meshIndex]; - var prim:DynamicPolygon = cast mesh.primitive; + var prim = info.primitives[meshIndex]; var pos = 0; for (i in info.indices) { - if (pos >= prim.points.length) { + if (pos >= Std.int(prim.points.length / 3)) { meshIndex++; - mesh.primitive = prim; - mesh = cast info.geometry.children[meshIndex]; - prim = cast mesh.primitive; + prim = info.primitives[meshIndex]; pos = 0; } - var vertex = info.vertices[i]; - var normal = info.normals[i]; - prim.points[pos].load(vertex.toPoint()); - prim.normals[pos].load(normal.toPoint()); // .normalized(); + prim.points[3 * pos] = info.vertices[3 * i]; + prim.points[3 * pos + 1] = info.vertices[3 * i + 1]; + prim.points[3 * pos + 2] = info.vertices[3 * i + 2]; + prim.normals[3 * pos] = info.normals[3 * i]; + prim.normals[3 * pos + 1] = info.normals[3 * i + 1]; + prim.normals[3 * pos + 2] = info.normals[3 * i + 2]; if (prim.buffer != null) { prim.dirtyFlags[pos] = true; } diff --git a/src/DynamicPolygon.hx b/src/DynamicPolygon.hx index 4f4ba1af..162c7ea1 100644 --- a/src/DynamicPolygon.hx +++ b/src/DynamicPolygon.hx @@ -12,37 +12,62 @@ import h3d.col.Point; To update points/normals/uvs, just change the points/normals/uvs array and set dirtyFlags[i] to true for all index of changed points/normals/uvs where i is index of point and call flush(); */ class DynamicPolygon extends MeshPrimitive { - public var points:Array; - public var normals:Array; - public var uvs:Array; - public var idx:hxd.IndexBuffer; + public var points:Array; + public var normals:Array; + public var uvs:Array; // A list of bools having the same length as points/normals/uv and each bool corresponds to point/normal/uv having the same index as the bool // Basically this is just used to tell apart vertices that changed so it will be flushed, it will be created after alloc has been called public var dirtyFlags:Array; - var vbuf:FloatBuffer; + var buf:FloatBuffer; - @:s var scaled = 1.; - @:s var translatedX = 0.; - @:s var translatedY = 0.; - @:s var translatedZ = 0.; + var bounds:h3d.col.Bounds; - public function new(points, ?idx) { - this.points = points; - this.idx = idx; + public function new() {} + + public function addPoints(points:Array) { + this.points = []; + for (p in points) { + this.points.push(p.x); + this.points.push(p.y); + this.points.push(p.z); + } + } + + public function addUVs(uvs:Array) { + this.uvs = []; + for (uv in uvs) { + this.uvs.push(uv.u); + this.uvs.push(uv.v); + } + } + + public function addNormals(normals:Array) { + this.normals = []; + for (n in normals) { + this.normals.push(n.x); + this.normals.push(n.y); + this.normals.push(n.z); + } } override function getBounds() { - var b = new h3d.col.Bounds(); - for (p in points) - b.addPoint(p); - return b; + if (bounds == null) { + var b = new h3d.col.Bounds(); + var i = 0; + while (i < points.length) { + b.addPoint(new h3d.col.Point(points[i], points[i + 1], points[i + 2])); + i += 3; + } + bounds = b; + } + return bounds; } public function flush() { var alloc = hxd.impl.Allocator.get(); - var vsize = points.length; + var vsize = Std.int(points.length / 3); if (vsize == 0) { if (buffer != null) { alloc.disposeBuffer(buffer); @@ -64,22 +89,19 @@ class DynamicPolygon extends MeshPrimitive { buffer = alloc.allocBuffer(hxd.Math.imax(0, vsize), 8, Dynamic); var off = 0; - for (k in 0...points.length) { + for (k in 0...Std.int(points.length / 3)) { if (dirtyFlags[k]) { - var p = points[k]; - vbuf[off++] = p.x; - vbuf[off++] = p.y; - vbuf[off++] = p.z; + buf[off++] = points[k * 3]; + buf[off++] = points[k * 3 + 1]; + buf[off++] = points[k * 3 + 2]; if (normals != null) { - var n = normals[k]; - vbuf[off++] = n.x; - vbuf[off++] = n.y; - vbuf[off++] = n.z; + buf[off++] = normals[k * 3]; + buf[off++] = normals[k * 3 + 1]; + buf[off++] = normals[k * 3 + 2]; } if (uvs != null) { - var uv = uvs[k]; - vbuf[off++] = uv.u; - vbuf[off++] = uv.v; + buf[off++] = uvs[k * 2]; + buf[off++] = uvs[k * 2 + 1]; } dirtyFlags[k] = false; } else { @@ -91,9 +113,7 @@ class DynamicPolygon extends MeshPrimitive { } } - buffer.uploadVector(vbuf, 0, vsize); - if (idx != null) - indexes = h3d.Indexes.alloc(idx); + buffer.uploadVector(buf, 0, vsize); } override function alloc(engine:h3d.Engine) { @@ -117,146 +137,41 @@ class DynamicPolygon extends MeshPrimitive { size += 2; } - vbuf = new hxd.FloatBuffer(); - for (k in 0...points.length) { - var p = points[k]; - vbuf.push(p.x); - vbuf.push(p.y); - vbuf.push(p.z); + buf = new hxd.FloatBuffer(); + for (k in 0...Std.int(points.length / 3)) { + buf.push(points[k * 3]); + buf.push(points[k * 3 + 1]); + buf.push(points[k * 3 + 2]); if (normals != null) { - var n = normals[k]; - vbuf.push(n.x); - vbuf.push(n.y); - vbuf.push(n.z); + buf.push(normals[k * 3]); + buf.push(normals[k * 3 + 1]); + buf.push(normals[k * 3 + 2]); } if (uvs != null) { - var t = uvs[k]; - vbuf.push(t.u); - vbuf.push(t.v); + buf.push(uvs[k * 2]); + buf.push(uvs[k * 2 + 1]); } dirtyFlags.push(false); } + var flags:Array = []; - if (idx == null) - flags.push(Triangles); + flags.push(Triangles); if (normals == null) flags.push(RawFormat); flags.push(Dynamic); + buffer = allocator.allocBuffer(hxd.Math.imax(0, vertexCount()), 8, Dynamic); // h3d.Buffer.ofFloats(buf, size, flags); - buffer.uploadVector(vbuf, 0, points.length); + buffer.uploadVector(buf, 0, Std.int(points.length / 3)); for (i in 0...names.length) addBuffer(names[i], buffer, positions[i]); - if (idx != null) - indexes = h3d.Indexes.alloc(idx); - } - - public function getDrawBuffer(vertices:Int) { - if (vbuf == null) - vbuf = hxd.impl.Allocator.get().allocFloats(vertices * 8) - else - vbuf.grow(vertices * 8); - return vbuf; - } - - public function unindex() { - if (idx != null && points.length != idx.length) { - var p = []; - var used = []; - for (i in 0...idx.length) - p.push(points[idx[i]].clone()); - if (normals != null) { - var n = []; - for (i in 0...idx.length) - n.push(normals[idx[i]].clone()); - normals = n; - } - if (uvs != null) { - var t = []; - for (i in 0...idx.length) - t.push(uvs[idx[i]].clone()); - uvs = t; - } - points = p; - idx = null; - } - } - - public function translate(dx, dy, dz) { - translatedX += dx; - translatedY += dy; - translatedZ += dz; - for (p in points) { - p.x += dx; - p.y += dy; - p.z += dz; - } - } - - public function scale(s:Float) { - scaled *= s; - for (p in points) { - p.x *= s; - p.y *= s; - p.z *= s; - } - } - - public function addNormals() { - // make per-point normal - normals = new Array(); - for (i in 0...points.length) - normals[i] = new Point(); - var pos = 0; - for (i in 0...triCount()) { - var i0, i1, i2; - if (idx == null) { - i0 = pos++; - i1 = pos++; - i2 = pos++; - } else { - i0 = idx[pos++]; - i1 = idx[pos++]; - i2 = idx[pos++]; - } - var p0 = points[i0]; - var p1 = points[i1]; - var p2 = points[i2]; - // this is the per-face normal - var n = p1.sub(p0).cross(p2.sub(p0)); - // add it to each point - normals[i0].x += n.x; - normals[i0].y += n.y; - normals[i0].z += n.z; - normals[i1].x += n.x; - normals[i1].y += n.y; - normals[i1].z += n.z; - normals[i2].x += n.x; - normals[i2].y += n.y; - normals[i2].z += n.z; - } - // normalize all normals - for (n in normals) - n.normalize(); - } - - public function addUVs() { - uvs = []; - for (i in 0...points.length) - uvs[i] = new UV(points[i].x, points[i].y); - } - - public function uvScale(su:Float, sv:Float) { - if (uvs == null) - throw "Missing UVs"; - var m = new Map(); - for (t in uvs) { - if (m.exists(t)) - continue; - m.set(t, true); - t.u *= su; - t.v *= sv; + if (indexes == null && Std.int(points.length / 3) > 65535) { + var indices = new haxe.io.BytesOutput(); + for (i in 0...Std.int(points.length / 3)) + indices.writeInt32(i); + indexes = new h3d.Indexes(indices.length >> 2, true); + indexes.uploadBytes(indices.getBytes(), 0, indices.length >> 2); } } @@ -264,27 +179,11 @@ class DynamicPolygon extends MeshPrimitive { var n = super.triCount(); if (n != 0) return n; - return Std.int((idx == null ? points.length : idx.length) / 3); + return Std.int(points.length / 3); } override function vertexCount() { - return points.length; - } - - override function getCollider():h3d.col.Collider { - var vertexes = new haxe.ds.Vector(points.length * 3); - var indexes = new haxe.ds.Vector(idx.length); - var vid = 0; - for (p in points) { - vertexes[vid++] = p.x; - vertexes[vid++] = p.y; - vertexes[vid++] = p.z; - } - for (i in 0...idx.length) - indexes[i] = idx[i]; - var poly = new h3d.col.Polygon(); - poly.addBuffers(vertexes, indexes); - return poly; + return Std.int(points.length / 3); } override function render(engine:h3d.Engine) { @@ -298,94 +197,4 @@ class DynamicPolygon extends MeshPrimitive { else engine.renderMultiBuffers(bufs, engine.mem.triIndexes, 0, triCount()); } - - #if hxbit - override function customSerialize(ctx:hxbit.Serializer) { - ctx.addInt(points.length); - for (p in points) { - ctx.addDouble(p.x); - ctx.addDouble(p.y); - ctx.addDouble(p.z); - } - if (normals == null) - ctx.addInt(0); - else { - ctx.addInt(normals.length); - for (p in normals) { - ctx.addDouble(p.x); - ctx.addDouble(p.y); - ctx.addDouble(p.z); - } - } - if (tangents == null) - ctx.addInt(0); - else { - ctx.addInt(tangents.length); - for (p in tangents) { - ctx.addDouble(p.x); - ctx.addDouble(p.y); - ctx.addDouble(p.z); - } - } - if (uvs == null) - ctx.addInt(0); - else { - ctx.addInt(uvs.length); - for (uv in uvs) { - ctx.addDouble(uv.u); - ctx.addDouble(uv.v); - } - } - if (idx == null) - ctx.addInt(0); - else { - ctx.addInt(idx.length); - for (i in idx) - ctx.addInt(i); - } - if (colors == null) - ctx.addInt(0); - else { - ctx.addInt(colors.length); - for (c in colors) { - ctx.addDouble(c.x); - ctx.addDouble(c.y); - ctx.addDouble(c.z); - } - } - } - - override function customUnserialize(ctx:hxbit.Serializer) { - points = [ - for (i in 0...ctx.getInt()) - new h3d.col.Point(ctx.getDouble(), ctx.getDouble(), ctx.getDouble()) - ]; - normals = [ - for (i in 0...ctx.getInt()) - new h3d.col.Point(ctx.getDouble(), ctx.getDouble(), ctx.getDouble()) - ]; - tangents = [ - for (i in 0...ctx.getInt()) - new h3d.col.Point(ctx.getDouble(), ctx.getDouble(), ctx.getDouble()) - ]; - uvs = [for (i in 0...ctx.getInt()) new UV(ctx.getDouble(), ctx.getDouble())]; - if (normals.length == 0) - normals = null; - if (uvs.length == 0) - uvs = null; - var nindex = ctx.getInt(); - if (nindex > 0) { - idx = new hxd.IndexBuffer(); - idx.grow(nindex); - for (i in 0...nindex) - idx[i] = ctx.getInt(); - } - colors = [ - for (i in 0...ctx.getInt()) - new h3d.col.Point(ctx.getDouble(), ctx.getDouble(), ctx.getDouble()) - ]; - if (colors.length == 0) - colors = null; - } - #end } diff --git a/src/InstanceManager.hx b/src/InstanceManager.hx index 67b3eba1..8ceb41ac 100644 --- a/src/InstanceManager.hx +++ b/src/InstanceManager.hx @@ -38,6 +38,7 @@ class MeshBatchInfo { class MeshInstance { var emptyObj:Object; var gameObject:GameObject; + var visibleTicks:Int = 10; public function new(eo, go) { this.emptyObj = eo; @@ -127,22 +128,28 @@ class InstanceManager { // for (frustum in renderFrustums) { // if (frustum.hasBounds(objBounds)) { - tmpBounds.load(minfo.baseBounds); - tmpBounds.transform(inst.emptyObj.getAbsPos()); + if (inst.visibleTicks == 0) { + tmpBounds.load(minfo.baseBounds); + tmpBounds.transform(inst.emptyObj.getAbsPos()); - if (cameraFrustrums == null && !renderFrustum.hasBounds(tmpBounds)) - continue; - - if (cameraFrustrums != null) { - var found = false; - for (frustrum in cameraFrustrums) { - if (frustrum.hasBounds(tmpBounds)) { - found = true; - break; - } - } - if (!found) + if (cameraFrustrums == null && !renderFrustum.hasBounds(tmpBounds)) continue; + + if (cameraFrustrums != null) { + var found = false; + for (frustrum in cameraFrustrums) { + if (frustrum.hasBounds(tmpBounds)) { + found = true; + break; + } + } + if (!found) + continue; + } + + inst.visibleTicks = 10; + } else { + inst.visibleTicks = inst.visibleTicks - 1; } if (inst.gameObject.currentOpacity == 1) diff --git a/src/Util.hx b/src/Util.hx index cd70bb16..90c732db 100644 --- a/src/Util.hx +++ b/src/Util.hx @@ -370,15 +370,12 @@ class Util { return str; } - public static function m_matF_x_vectorF(matrix:Matrix, v:Vector) { - var m = matrix.clone(); - m.transpose(); - + public static inline function m_matF_x_vectorF(m:Matrix, v:Vector) { var v0 = v.x, v1 = v.y, v2 = v.z; - var vresult_0 = m._11 * v0 + m._12 * v1 + m._13 * v2; - var vresult_1 = m._21 * v0 + m._22 * v1 + m._23 * v2; - var vresult_2 = m._31 * v0 + m._23 * v1 + m._33 * v2; + var vresult_0 = m._11 * v0 + m._21 * v1 + m._31 * v2; + var vresult_1 = m._12 * v0 + m._22 * v1 + m._32 * v2; + var vresult_2 = m._13 * v0 + m._23 * v1 + m._33 * v2; v.set(vresult_0, vresult_1, vresult_2); } diff --git a/src/dts/Sequence.hx b/src/dts/Sequence.hx index 8e81be70..187a24e9 100644 --- a/src/dts/Sequence.hx +++ b/src/dts/Sequence.hx @@ -30,6 +30,7 @@ class Sequence { var priority:Int; var flags:Int; var dirtyFlags:Int; + var lastSequenceKeyframe:Float; public function new() {} diff --git a/src/gui/PlayGui.hx b/src/gui/PlayGui.hx index d8594628..97899571 100644 --- a/src/gui/PlayGui.hx +++ b/src/gui/PlayGui.hx @@ -80,6 +80,11 @@ class PlayGui { var powerupImageSceneTargetBitmap:Bitmap; var powerupImageObject:DtsObject; + var blastBarTile:h2d.Tile; + var blastBarGreenTile:h2d.Tile; + var blastBarGrayTile:h2d.Tile; + var blastBarChargedTile:h2d.Tile; + var RSGOCenterText:Anim; var helpTextForeground:GuiText; @@ -609,6 +614,11 @@ class PlayGui { blastFrame.position = new Vector(0, 0); blastFrame.extent = new Vector(120, 28); blastBar.addChild(blastFrame); + + blastBarTile = ResourceLoader.getResource("data/ui/game/blastbar.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastBarGreenTile = ResourceLoader.getResource("data/ui/game/blastbar_bargreen.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastBarGrayTile = ResourceLoader.getResource("data/ui/game/blastbar_bargray.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastBarChargedTile = ResourceLoader.getResource("data/ui/game/blastbar_charged.png", ResourceLoader.getImage, this.imageResources).toTile(); } public function setBlastValue(value:Float) { @@ -618,21 +628,21 @@ class PlayGui { } if (value <= 1) { if (blastFill.extent.y == 16) { // Was previously charged - blastFrame.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastFrame.bmp.tile = blastBarTile; } var oldVal = blastFill.extent.x; blastFill.extent = new Vector(Util.lerp(0, 110, value), 17); if (oldVal < 22 && blastFill.extent.x >= 22) { - blastFill.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar_bargreen.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastFill.bmp.tile = blastBarGreenTile; MarbleGame.instance.touchInput.blastbutton.setEnabled(true); } if (oldVal >= 22 && blastFill.extent.x < 22) { - blastFill.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar_bargray.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastFill.bmp.tile = blastBarGrayTile; MarbleGame.instance.touchInput.blastbutton.setEnabled(false); } } else { blastFill.extent = new Vector(0, 16); // WE will just use this extra number to store whether it was previously charged or not - blastFrame.bmp.tile = ResourceLoader.getResource("data/ui/game/blastbar_charged.png", ResourceLoader.getImage, this.imageResources).toTile(); + blastFrame.bmp.tile = blastBarChargedTile; MarbleGame.instance.touchInput.blastbutton.setEnabled(true); } this.blastBar.render(scene2d);