Libgdx Sound when it has finished - libgdx

This current code when it is the upright state it runs the bass sound repeatedly until it starts distorting the sound and running poorly. How would i dispose of the sound when it has finished running and stopping it run multiple times as i would like the sound only to play once when it has gone into this upright state. Thanks alex.
public void determineState(){
accelX = Gdx.input.getAccelerometerX();
accelY = Gdx.input.getAccelerometerY();
accelZ = Gdx.input.getAccelerometerZ();
state = "NULL";
if(accelX < 1 && accelX > -1){
if(accelY > -1 && accelY < 1){
if(accelZ > 9 && accelZ < 11){
state = "UPRIGHT";
}
}
}
}
public void playSound(String soundString){
System.out.println(soundString);
if(soundString != "null"){
sound = Gdx.audio.newSound(Gdx.files.internal(soundString + ".wav"));
long id = sound.play();
sound.setVolume(id, 3);
}else if (soundString == "null"){
}
}

You should not create a new sound and dispose it every time you want it to play. This is wasting time reloading it over and over. Store your loaded sounds in an array, or load them with an AssetManager and get the references from there.
Your playSound method would look something like this:
public void playSound (String soundFileName){
sound = assetManager.get(soundFileName, Sound.class);
sound.play();
}
By the way, it doesn't make sense to set volume to 3 since it's on a 0-1 scale.
If you want something to happen only one time when a state changes, than call that method when the state changes, not on every frame as it seems you are doing.
i.e. do this:
//...
if(accelZ > 9 && accelZ < 11){
state = "UPRIGHT";
playSound("uprightStateChange.wav");
}

Related

as3 adding sound to everytime player reaches new level

How would I add a sound effect every time a player enters a new level? I'm trying to figure this out for a project that is due tonight and I've been working on it for weeks and my project uses differ classes for different aspects of the project.
Level class code:
package {
public class LevelData {
public var backgroundImage:String;
public var pointsToReachNextLevel:Number;
public var enemySpawnRate:Number;
public var levelNum:Number;
public function LevelData(levelNumber:Number) {
levelNum = levelNumber;
if ( levelNumber % 2 == 1 )
{
backgroundImage = "Cosmic";
pointsToReachNextLevel = 150;
enemySpawnRate = 0.05;
}
else if ( levelNumber == 2 )
{
backgroundImage = "Mystic";
pointsToReachNextLevel = 350;
enemySpawnRate = 0.1;
}
else if ( levelNumber == 3 )
{
backgroundImage = "Cosmic";
pointsToReachNextLevel = 600;
enemySpawnRate = 0.15;
}
else if ( levelNumber == 4 )
{
backgroundImage = "Mystic";
pointsToReachNextLevel = 5820; // roughly 3 minutes enemies stop appearing
enemySpawnRate = 0.6 - ( 2 / levelNumber );
}
}
}
}
snippet from Engine class:
public function setBackgroundImage(): void //background change
{
if (currentLevelData.backgroundImage == "Cosmic") {
backgroundContainer.addChild(new CosmicBackground());
} else if (currentLevelData.backgroundImage == "Mystic")
{
backgroundContainer.addChild(new MysticBackground());
}
}
There are multiple ways of playing sounds in Flash. Honestly, the most reliable approach for use with code is to write a dedicated class for yourself, implementing SoundChannel, that manages all sound loading, playback, and transformation (volume, pan, etc.) It takes a bit of work, but it pays off in the long run.
Of course, it would seem you're on a tighter deadline than that. If you need a quick-and-dirty fix for this, here it is.
Add your sound to the Flash library. (This should speed things up, otherwise you have to load it from an external file constantly.)
Set up the sound in your library to be accessible from ActionScript 3. Here's an answer detailing how to do that. For this, I'll call it "sndLevelUp."
Create an instance of your sound at the top of your class: var levelUp:sndLevelUp = new sndLevelUp();
Play the sound every time the player levels up. levelUp.play();
If you have more time, you may want to set up a SoundChannel, which gives you more control over playback, volume, and panning. Otherwise, this is the fast way to do it.

Flash sprite gets faster as time elapses

I am trying to make my first game in Flash, and it will be called Pedestrian Run. The rock here will come towards the player and it should be going at one consistent speed, however, every time it resets back to the starting point, it gets faster and faster. Is there any way to fix this, because I cannot for the life of me figure this out. Any help is appreciated. Here is the code on pastebin:
Pedestrian Run Code
I think the setTimeout in a recursive function is a very bad idea and it's what's probably causing your problem. Use the ENTER FRAME event for the game loop.
#Iansen is correct, your issue is caused by the setTimeout continually being called.
In your moveRock() you have a setTimeout to moveRock. Your setTimeouts are accumulating and that is why you are seeing the translation increase.
It would be best if you used a timer instead, like so:
In your class level variables:
private var moveTimer:Timer;
In your init() add this:
moveTimer = new Timer(25,0);
moveTimer.addEventListener( TimerEvent.TIMER, moveRock );
//you can call the moveTimer.start() anywhere you want, but this is fine
moveTimer.start();
Then your moveRock and spawnRock should look like this:
private function moveRock( e:TimerEvent ):void {
rock.x -= 15;
if (rock.x == char.x || rock.x == 0) {
removeChild(rock);
spawnRock();
}
}
private function spawnRock():void {
addChild(rock);
rock.x = 750;
rock.y = 520;
}
It also worth noting that the removeChild and addChild is pretty wasteful here in your current code and you'd be fine with just the moveRock() slightly altered:
private function moveRock( e:TimerEvent ):void {
rock.x -= 15;
if (rock.x == char.x || rock.x == 0) {
rock.x = 750;
rock.y = 520;
}
}
Don't use a constant value for your rock.x update. Use a variable and update it every time you "reset".
Notice in the example below, I'm updating after you despawn your previous rock.
private var speed:Number = 15;
function moveRock():void {
rock.x -= speed;
if (rock.x == char.x || rock.x == 0) {
this.removeChild(rock);
speed += 1;
spawnRock();
}
setTimeout(moveRock, 25);
}

AS3 Memory Management reverse engineering

Has anyone figured out how AS3 actually handles garbage collection? I'm having so many issues releasing memory in a game I'm developing.
Made a small demo:
public class MemoryTesting extends Sprite
{
static protected var list:Array = null;
public function onKeyDown(event:KeyboardEvent):void {
if( event.keyCode == 65 ){ //A key - adds memory
if( list == null ){
list = [];
for( var index:int = 0; index < 10000000; ++index ){
list.push(new Matrix3D());
}
}
}
else{ //Any other key removes memory.
if( list ){
var size:int = list.length;
for( var index:int = 0; index < size; ++index ){
list.pop();
}
list.length = 0;
list = null;
}
System.gc();
}
}
}
Running Flash Player Debugger stand-alone 11.4r402 in Windows 7. Watching the Task Manager, with no keys pressed, the debugger sits idle at 11,000 K.
Pressing a (adding 10Mil Matrix3D classes) takes it up to 962,000 K.
Pressing another key (removing references to the Matrices and nulling the array) depends on how many times I press it.
The first time we call GC - drops to 255,000 K.
The second GC call - 92,000 K.
Third - 52,000 K.
Forth - 42,000 K.
Fifth - 39,000 K.
Sixth & any consecutive times after sits at 38,000 K.
I hear people talking about the GC waiting for "opportune times" to collect. But this is an empty application, not even a enter_frame event and there is no amount of time you can leave it idle for it to remove the remaining 27,000 K (38,000 - 11,000).
Sitting at the new low, if we re-add the matrices we move back up to 975,000 K.
That is to say, 13,000 K more than the first time. If I repeat this add/remove, it stays the same, going back up to 975,000 K and down to 38,000 K.
Remember, there is nothing going on in this application. My actual application has 650mb of raw bitmap data, let alone 100mb of SWF to parse and 500mb of XML classes that I only use in initialisation code.
I've read multiple times that even calling GC manually is bad, let alone 6 times. But none of the Matrix3D's will be released if I don't.
How does anyone handle this? Shall I just call GC 6 times at the end of initialisation?
Edit:
I was testing in release mode for differences and whether, without the System.gc() call, that if it doesn't free the memory from flash, at the least re-uses it properly. It does eventually, but with a new, higher footprint. With a full list sits at 990,000 K, clearing it takes it to 1,050,000 K.
This is for data that initially cost us 962,000 K RAM. That's 90MB of weird internal flash GC memory. Let alone ignoring that it won't ever give the memory back to the OS (without the explicit GC calls).
Actionscript's GC is weird, nothing to say,
If you'll try to use something like this, it helps (I just tested and GC clears out the memory on the very first try (key click)), Just changed Array to Vector to test more quicker, just the same should happen with Array too. My enviroment is FlashCC in this case.
package
{
import flash.display.Sprite;
import flash.events.KeyboardEvent;
import flash.geom.Matrix3D;
import flash.net.LocalConnection;
import flash.system.System;
import flash.utils.setTimeout;
public class MemoryTesting extends Sprite
{
var list:Vector.<Matrix3D> = null;
function MemoryTesting()
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
public function onKeyDown(event:KeyboardEvent):void
{
var matrx:Matrix3D;
var index:int
if (event.keyCode == 13)
{
trace(System.totalMemory, "starting to fill...")
if (list == null)
{
list = new Vector.<Matrix3D>
for (index = 0; index < 1000000; ++index)
{
matrx = new Matrix3D();
list.push(matrx);
}
}
trace(System.totalMemory, " done...")
}
else
{
if (list)
{
trace(System.totalMemory, " preparing to delete...")
list.splice(0, list.length);
list = null;
}
//force GC to work normally, it really helps (at least in my case)
try
{
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
}
catch (e:*)
{
}
setTimeout(function()
{
trace(System.totalMemory, " deleted")
}, 50)
}
}
}
}
This strange snippet really helps on most cases
try {
new LocalConnection().connect('foo');
new LocalConnection().connect('foo');
} catch (e:*) {}
Here is the freat article:
http://gskinner.com/blog/archives/2006/08/as3_resource_ma_2.html

What is causing this glitch?

I am currently coding a game, and have encountered an annoying glitch. Occasionally, when you kill an enemy in game, it will drop extra currency, and another enemy onscreen will be removed from the enemylist. However, this second enemy, the one removed from the enemylist, will still be on screen, and will still shoot at the player. Below are code snippets from the collision formula, the enemies destruction sequence, and the bullet hitcheck sequence.
Collision formula:
public function testCollision(enemy:Entity):Boolean{
var eX:Number = enemy.collision.xPos
var eY:Number = enemy.collision.yPos
var eSL:Number = enemy.collision.SideLength/2
if(eX-xPos<(SideLength/2)+eSL && eY-yPos<(SideLength/2)+eSL && eX-xPos>-(SideLength/2)-eSL && eY-yPos>-(SideLength/2)-eSL){
return true
}else{
return false
}
}
Enemy destruction sequence:
if(deathVar){
view.transparency -= 1/20
if(view.transparency<0.1){
var cur = new PixelCurrency(2)
cur.collision.xPos = collision.xPos
cur.collision.yPos = collision.yPos
entityCreated.dispatch(cur)
destroy()
}
}
Bullet hitcheck:
for each (var enemy:Entity in Game.entities){
if(enemy.allies == Pixapocalypse.EnemyFaction){
if(collision.testCollision(enemy)){
if(enemy.life){
enemy.life.changeHealth(-2)
this.sound.playSound(new basicHitSound())
this.destroy()
break
}
else{
}
}
}
}
If you need any extra info, please tell me, I am greatly appreciative of your help.
What happens when Enemy.life < 0 ?

Instantiate Class at Specific Time

I am trying to make a simple game using libgdx. One thing that I am stuck with is making enemies spawn at specific times. If I do something like
if (t == 10)
new Enemy();
I might miss this specific time or maybe spawn the same enemy twice. What I have right now is something like
float t = 0
float timeElapsed = 0;
update (float delta) {
timeElapsed += getDeltaTime();
if (timeElapsed > 0.1) {
t++;
timeElapsed = 0;
}
}
This gives me the approximate elapsed time in tenths of seconds for t, but it really doesn't feel like the way I should be doing this.
I have a solution I use in my games that might be useful. I actually created a Timer class:
public class Timer
{
protected float remaining;
protected float interval;
public Timer(float interval)
{
this.interval = interval;
this.remaining = interval;
}
public boolean hasTimeElapsed() { return (remaining < 0.0F); }
public void reset() { remaining = interval; }
public void reset(float interval) {
this.interval = interval;
this.remaining = interval;
}
public void update(float delta) { remaining -= delta; }
}
You initialize the Timer to a certain time period, then in your update(delta) method you call Timer.update(delta) on all your Timers, then check if any of the timers have elapsed by calling Timer.hasTimeElapsed().
In your case, you only need one Timer object, since the enemies are spawned in sequence. Once you spawn an enemy, you reset the Timer (changing the spawn period if you want) and wait for it to go off again.
You can also modify the Timer object to use the subject-observer pattern in order to trigger callbacks when a timer goes off. This is useful if you have logic that needs to know when a timed event occurs, but the logic does not have direct access to the delta time.
Also, if you have a slow frame with eg. getDeltaTime() = 0.2, the enemy's spawn will be delayed.
The simplest way that comes to mind is to get rid of t - compare directly against timeElapsed, and keep track of the object references to know whether you've spawned each enemy. ie.
if (enemy1 == NULL && elapsedTime > 10) {
enemy1 = new Enemy();
}
if (enemy2 == NULL && elapsedTime > 30) {
enemy2 = new Enemy();
}
For a more scalable approach, you could create a linked list of spawn times, and when you spawn an enemy advance the list pointer. That way you only have to compare against one time (the spawn-time on the current list node) per frame.
Addendum: it's rarely a good idea to use == in the context of floating point numbers. See http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html for gory details.
Why do you increment t and then you spawn enemies based on t value. Why don't you do it like this ?
final float step = 0.1f;
float timeElapsed = 0f;
update (float delta) {
timeElapsed += delta;
while (timeElapsed > step){
timeElapsed-=step;
createEnemy();
}
}
With this approach, when your game lags and you get delta lets say 0.5f and you step is 0.1, you will create 5 enemies. I don't know if you want or don't want this beviour