How to move the stage within a class in Actionscript3? - class

Okay so I know how to move the stage within the actual .fla file by modifying this.x and this.y variables in the layer 1 actionscript.
But within the document class- public class Starlight extends MovieClip, it does not seem to work no matter what i try and my research lead me to this use code instead:
for( i = 0; i < stage.numChildren; i ++){
stage.getChildAt(i).x -= player.speedx * player.bounceSpeed;
stage.getChildAt(i).y -= player.speedy * player.bounceSpeed;
}
I do realize that its hacky and slower as compared to actually moving the stage itself. And i'm not sure what's going to happen if another object that moves comes into the stage because technically this code is unnaturally altering the x,y of everything in the stage.
Any help appreciated!!
Cheers
Edit: Tried this--
var stage2:Sprite = new Sprite();
stage2.x = stage.stageWidth / 2;
stage2.y = stage.stageHeight / 2;
stage2.width = 4000;
stage2.height = 4000;
addChild(stage2);
for (i = 1; i < 50; i ++)
{
var asteroid:Asteroid = new Asteroid();
asteroid.x = Math.round(Math.random() * stage.stageWidth * 4);
asteroid.y = Math.round(Math.random() * stage.stageHeight * 4);
stage2.addChild(asteroid);
collisionList.addItem(asteroid);
asteroids.push(asteroid);
}

Woah, don't move the stage!
Create a MovieClip or a Sprite and stick everything in there, then it's just a case of moving that object.
var stage2:Sprite = new Sprite();
stage2.addChild(something);
stage2.addChild(somethingElse);
stage2.x = 10;
stage2.y = 10;

Related

GraphicsBuffer's GetData always returning 0s

I'm trying to clone a mesh using GraphicsBuffer because its read/write option is false, and I can't change that. This is my current code:
public static bool Run(Mesh sourceMesh, out Mesh generatedMesh)
{
GraphicsBuffer sourceDataBuffer = sourceMesh.GetVertexBuffer(0);
GraphicsBuffer sourceIndexBuffer = sourceMesh.GetIndexBuffer();
var vertexCount = sourceDataBuffer.count;
var indexCount = sourceIndexBuffer.count;
byte[] sourceData = new byte[vertexCount * (sourceDataBuffer.stride / sizeof(byte))];
byte[] sourceIndex = new byte[(int)(indexCount * ((float)sourceIndexBuffer.stride / sizeof(byte)))];
sourceDataBuffer.GetData(sourceData);
sourceIndexBuffer.GetData(sourceIndex);
var attributes = sourceMesh.GetVertexAttributes();
generatedMesh = new Mesh();
generatedMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
generatedMesh.SetVertexBufferParams(vertexCount, attributes);
generatedMesh.SetVertexBufferData(sourceData, 0, 0, sourceData.Length);
generatedMesh.SetIndexBufferParams(indexCount, sourceMesh.indexFormat);
generatedMesh.SetIndexBufferData(sourceIndex, 0, 0, sourceIndex.Length);
generatedMesh.subMeshCount = sourceMesh.subMeshCount;
for (int i = 0; i < sourceMesh.subMeshCount; i++)
{
var subMeshDescriptor = sourceMesh.GetSubMesh(i);
generatedMesh.SetSubMesh(i, subMeshDescriptor);
}
sourceDataBuffer.Release();
sourceIndexBuffer.Release();
generatedMesh.RecalculateBounds();
return true; // No error
}
It works like a charm in my test project. But when I try to clone things in my main project, GetData(sourceData) and GetData(sourceIndex) both return arrays of 0s. What could be causing that? Could it be because of the read/write being disabled?
Edit: The problem only happens in bundles with non-readable meshes. I thought GraphicsBuffer should work with them, but it doesn't.

What's the best way to save terraindata to file in Runtime?

My game lets the user modify the terrain at runtime, but now I need to save said terrain. I've tried to directly save the terrain's heightmap to a file, but this takes almost up to two minutes to write for this 513x513 heightmap.
What would be a good way to approach this? Is there any way to optimize the writing speed, or am I approaching this the wrong way?
public static void Save(string pathraw, TerrainData terrain)
{
//Get full directory to save to
System.IO.FileInfo path = new System.IO.FileInfo(Application.persistentDataPath + "/" + pathraw);
path.Directory.Create();
System.IO.File.Delete(path.FullName);
Debug.Log(path);
//Get the width and height of the heightmap, and the heights of the terrain
int w = terrain.heightmapWidth;
int h = terrain.heightmapHeight;
float[,] tData = terrain.GetHeights(0, 0, w, h);
//Write the heights of the terrain to a file
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
//Mathf.Round is to round up the floats to decrease file size, where something like 5.2362534 becomes 5.24
System.IO.File.AppendAllText(path.FullName, (Mathf.Round(tData[x, y] * 100) / 100) + ";");
}
}
}
As a sidenote, the Mathf.Round doesn't seem to influence the saving time too much, if at all.
You are making a lot of small individual File IO calls. File IO is always time consuming and expensive as it contains opening the file, writing to it, saving the file and closing the file.
Instead I would rather generate the complete string using e.g. a StringBuilder which is also more efficient than using something like
var someString
for(...)
{
someString += "xyz"
}
because the latter always allocates a new string.
Then use e.g. a FileStream and StringWriter.WriteAsync(string) for writing async.
Also rather use Path.Combine instead of directly concatenating string via /. Path.Combine automatically uses the correct connectors according to the OS it is used on.
And instead of FileInfo.Directory.Create rather use Directory.CreateDirectory which doesn't throw an exception if the directory already exists.
Something like
using System.IO;
...
public static void Save(string pathraw, TerrainData terrain)
{
//Get full directory to save to
var filePath = Path.Combine(Application.persistentDataPath, pathraw);
var path = new FileInfo(filePath);
Directory.CreateDirectory(path.DirectoryName);
// makes no sense to delete
// ... rather simply overwrite the file if exists
//File.Delete(path.FullName);
Debug.Log(path);
//Get the width and height of the heightmap, and the heights of the terrain
var w = terrain.heightmapWidth;
var h = terrain.heightmapHeight;
var tData = terrain.GetHeights(0, 0, w, h);
// put the string together
// StringBuilder is more efficient then using
// someString += "xyz" because latter always allocates a new string
var stringBuilder = new StringBuilder();
for (var y = 0; y < h; y++)
{
for (var x = 0; x < w; x++)
{
// also add the linebreak if needed
stringBuilder.Append(Mathf.Round(tData[x, y] * 100) / 100).Append(';').Append('\n');
}
}
using (var file = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write))
{
using (var streamWriter = new StreamWriter(file, Encoding.UTF8))
{
streamWriter.WriteAsync(stringBuilder.ToString());
}
}
}
You might want to specify how exactly the numbers shall be printed with a certain precision like e.g.
(Mathf.Round(tData[x, y] * 100) / 100).ToString("0.00000000");

Not getting frequency values in webaudio-api

I am using this spectrogram.js from github to plot spectrogram and obtain frequency values in real-time.
Github Repo
I have written this extra stopSong function:
function stopSong() {
var analyser = audioContext.createAnalyser();
var ctx = new AudioContext();
var osc = ctx.createOscillator();
osc.connect(ctx.destination);
osc.start(0);
spectro.stop();
var freqData= new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(freqData);
//var f = Math.round(freqData[1]);
// var text = f + ' Hz';
var idx = 0;
for (var j=0; j < analyser.frequencyBinCount; j++) {
if (freqData[j] > freqData[idx]) {
idx = j;
}
}
var frequency = idx * ctx.sampleRate / analyser.fftSize;
console.log(frequency);
//document.getElementById("frec").innerHTML = text;
}
But everytime i am running it it give 0 as output. Can anybody tell whats wrong with my code.
You need to connect the oscillator to the analyser:
oscillator.connect(analyser);
Also you might want to call getByteFrequencyData multiple times, maybe in requestAnimationFrame, or something like setTimeout.

Why my add Event listener doesn't work correctly?

Here is my code.
var _this = this;
var i = 0;
var object;
for (i=1 ; i <5 ; i++){
object = new lib.A ();
object.x = 50 * i;
object.y = 100;
_this.addChild (object);
object.on ("tick" , position , true)
}
function position(){
object.y += 1;
}
I have an object in the library and create and add to stage 4 number.
I want to move down all object with the addEventListener (tick), but it moves last object.
You need to reference the clicked object. In your code, the object variable changes in your for-loop, so at the end it is the last known value. Instead use the clicked target from the event (passed in the click handler):
function position(event){
event.currentTarget.y += 1;
}
Cheers,
I hope you have a stage somewhere in your code to depict the canvas, as in:
stage = new createjs.Stage("gameCanvas");
I think you're missing stage.update(event) as in:
function position(event){
//....update the poositions
stage.update(event);
}

How to call ImageView by objectName in QML

I am dynamically creating images in my QML. This is the code I am using:
for (var n = 0; n < 3 * numberOfTiles; n ++) {
var image = imageDefinition.createObject();
image.translationX = getX(n);
image.translationY = getY(n);
image.objectName = ("image"+n)
drawContainer.add(image);
}
Image creating works well, except I don't know how to call those images afterdawrds. I can't set them an ID, and I don't know if setting objectName like that works.
I don't get any errors, and if this work, how can I call "image3" from QML to move it? I don't want to use c++.
Found out a solution on my own. First I add this to have global access
property list<ImageView> images
And then I create images in array and copy them over
onCreationCompleted: {
//you need a tmp variable, since you can't do that with property variant
var imagesTmp = Array();
for (var n = 0; n < 3 * numberOfTiles; n ++) {
imagesTmp[n] = imageDefinition.createObject()
imagesTmp[n].translationX = getX(n);
imagesTmp[n].translationY = getY(n);
drawContainer.add(imagesTmp[n]);
}
images = imagesTmp;
images[3].translationX = 10; //as example, this works!
}
As it turns out images keeps reference to the image