private void RenderLayers(ACT.Frame frame) { // If current frame doesn't have layers, cleanup layer cache Layers.Values.ToList().ForEach(Renderer => Renderer.sprite = null); for (int i = 0; i < frame.layers.Length; i++) { var layer = frame.layers[i]; var sprite = sprites[layer.index]; Layers.TryGetValue(i, out var spriteRenderer); if (spriteRenderer == null) { var go = new GameObject($"Layer{i}"); spriteRenderer = go.AddComponent <SpriteRenderer>(); spriteRenderer.transform.SetParent(gameObject.transform, false); } CalculateSpritePositionScale(layer, sprite, out Vector3 scale, out Vector3 newPos, out Quaternion rotation); spriteRenderer.transform.localRotation = rotation; spriteRenderer.transform.localPosition = newPos; spriteRenderer.transform.localScale = scale; spriteRenderer.sprite = sprite; spriteRenderer.material.color = layer.color; if (!Layers.ContainsKey(i)) { Layers.Add(i, spriteRenderer); } } }
private void UpdateMesh(ACT.Frame frame) { // We need this mesh collider in order to have the raycast to hit the sprite MeshCache.TryGetValue(frame, out Mesh mesh); if (mesh == null) { mesh = SpriteMeshBuilder.BuildColliderMesh(frame, sprites); MeshCache.Add(frame, mesh); } meshCollider.sharedMesh = mesh; }
private static ACT.Frame[] ReadMotions(ACT act, MemoryStreamReader data) { var count = data.ReadUInt(); var motions = new ACT.Frame[count]; for (int i = 0; i < count; i++) { data.Seek(32, System.IO.SeekOrigin.Current); motions[i] = ReadLayers(act, data); } return(motions); }
private void PlaySound(ACT.Frame frame) { if (frame.soundId > -1 && frame.soundId < currentACT.sounds.Length) { var clipName = currentACT.sounds[frame.soundId]; if (clipName == "atk") { return; } var clip = FileManager.Load($"data/wav/{clipName}") as AudioClip; if (clip != null && AudioSource != null) { AudioSource.clip = clip; AudioSource.Play(); } } }
public static Mesh BuildColliderMesh(ACT.Frame motion, Sprite[] sprites) { meshBuildCount++; outNormals.Clear(); outVertices.Clear(); outTris.Clear(); outUvs.Clear(); outColors.Clear(); var mesh = new Mesh(); var tIndex = 0; var min = new Vector2(-0.2f, -0.2f); var max = new Vector2(0.2f, 0.2f); for (int i = 0; i < motion.layers.Length; i++) { var layer = motion.layers[i]; if (layer.index < 0) { continue; } var sprite = sprites[layer.index]; var verts = sprite.vertices; var uvs = sprite.uv; var rotation = Quaternion.Euler(0, 0, -layer.angle); var scale = new Vector3(layer.scale.x * (layer.isMirror ? -1 : 1), layer.scale.y, 1); var offsetX = (Mathf.RoundToInt(sprite.rect.width) % 2 == 1) ? 0.5f : 0f; var offsetY = (Mathf.RoundToInt(sprite.rect.height) % 2 == 1) ? 0.5f : 0f; for (var j = 0; j < verts.Length; j++) { var v = rotation * (verts[j] * scale); var vert = v + new Vector3(layer.pos.x - offsetX, -(layer.pos.y) + offsetY) / SPR.PIXELS_PER_UNIT; if (min.x > vert.x) { min.x = vert.x; } if (min.y > vert.y) { min.y = vert.y; } if (max.x < vert.x) { max.x = vert.x; } if (max.y < vert.y) { max.y = vert.y; } } } var xSize = max.x - min.x; var ySize = max.y - min.y; var xBoost = 0.1f; var yBoost = 0.1f; /** * This area is commented and the numbers below may look like * magic numbers, and indeed they are. The intention here is to * make the collider small, like 80% of the original size * and to not be below the ground */ //if (xSize < 0.5f) // xBoost += 0.2f; //if (xSize < 1f) // xBoost += 0.1f; //if (ySize < 0.5f) // yBoost += 0.2f; //if (ySize < 1f) // yBoost += 0.1f; min -= new Vector2(xBoost, yBoost); max += new Vector2(xBoost, yBoost); outVertices.Add(new Vector3(min.x, max.y) * 0.8f); outVertices.Add(new Vector3(max.x, max.y) * 0.8f); outVertices.Add(new Vector3(min.x, min.y * 0.1f) * 0.8f); outVertices.Add(new Vector3(max.x, min.y * 0.1f) * 0.8f); outTris.Add(tIndex); outTris.Add(tIndex + 1); outTris.Add(tIndex + 2); outTris.Add(tIndex + 1); outTris.Add(tIndex + 3); outTris.Add(tIndex + 2); mesh.vertices = outVertices.ToArray(); mesh.triangles = outTris.ToArray(); mesh.Optimize(); return(mesh); }
public static Mesh BuildSpriteMesh(ACT.Frame motion, Sprite[] sprites) { meshBuildCount++; outNormals.Clear(); outVertices.Clear(); outTris.Clear(); outUvs.Clear(); outColors.Clear(); var mesh = new Mesh(); var tIndex = 0; for (int i = 0; i < motion.layers.Length; i++) { var layer = motion.layers[i]; if (layer.index < 0) { continue; } var sprite = sprites[layer.index]; var verts = sprite.vertices; var uvs = sprite.uv; var rotation = Quaternion.Euler(0, 0, -layer.angle); var scale = new Vector3(layer.scale.x * (layer.isMirror ? -1 : 1), layer.scale.y, 1); var offsetX = (Mathf.RoundToInt(sprite.rect.width) % 2 == 1) ? 0.5f : 0f; var offsetY = (Mathf.RoundToInt(sprite.rect.height) % 2 == 1) ? 0.5f : 0f; for (var j = 0; j < verts.Length; j++) { var v = rotation * (verts[j] * scale); outVertices.Add(v + new Vector3(layer.pos.x - offsetX, (layer.pos.y) + offsetY) / SPR.PIXELS_PER_UNIT); outUvs.Add(uvs[j]); outColors.Add(layer.color); outNormals.Add(new Vector3(0, 0, -1)); } if (layer.isMirror) { outTris.Add(tIndex + 2); outTris.Add(tIndex + 1); outTris.Add(tIndex); outTris.Add(tIndex + 2); outTris.Add(tIndex + 3); outTris.Add(tIndex + 1); } else { outTris.Add(tIndex); outTris.Add(tIndex + 1); outTris.Add(tIndex + 2); outTris.Add(tIndex + 1); outTris.Add(tIndex + 3); outTris.Add(tIndex + 2); } tIndex += 4; } mesh.vertices = outVertices.ToArray(); mesh.uv = outUvs.ToArray(); mesh.triangles = outTris.ToArray(); mesh.colors = outColors.ToArray(); mesh.normals = outNormals.ToArray(); mesh.Optimize(); return(mesh); }