Scheduling a task with intervals-LibGdx - libgdx

I want to implement falling leaves in my game in particular intervals.
After 10 seconds of game starts,leaves has to fall.Then again leaves has to fall after 20 seconds and so on.
I have this method for the falling leaves of array;
private void updateFalls(float delta) {
for (Leaf l : leaves) {
l.moveLeavesDown(delta);
}
spawnleaves();
}
Is it possible to do with timer class?Is it possible to call this method inside timer with fixed intervals?
Any help would be appreciated.

You can use Timer in this way :
Timer timer=new Timer();
timer.scheduleTask(new Timer.Task() {
#Override
public void run() {
spawnLeaf();
}
},10,20); // --> 10 is your first delay and 20 is interval in sec.
I'm considering Leaf as a Sprite but it may be an Image or any other Entity.
Here is my spawnLeaf method :
Array<Sprite> leaves=new Array<Sprite>();
private void spawnLeaf(){
Sprite sprite=new Sprite(texture);
sprite.setPosition(MathUtils.random(Gdx.graphics.getWidth()),Gdx.graphics.getHeight());
leaves.add(sprite);
}
Draw and position update part of all leaves
spriteBatch.begin();
Iterator<Sprite> iter = leaves.iterator();
while (iter.hasNext()) {
Sprite spr = iter.next();
spr.draw(spriteBatch);
spr.setY(spr.getY()-50f*Gdx.graphics.getDeltaTime());
if (spr.getY()<0) {
iter.remove();
}
}
spriteBatch.end();
Timer has clear() and stop() method that help in removing all scheduled tasks and stops the timer respectively that may start again.

Related

Functions not doing anything

I have a gameObject called BounceBack that is supposed to bounce the ball back far away when they collide together.
public class BounceBack : MonoBehaviour
{
public GameObject Player;
public float force;
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag(Player.tag))
{
Player.GetComponent<PlayerController>().ForceBack(force);
}
}
}
The ball Player (ball) script:
public class PlayerController : MonoBehaviour
{
public int acceleration;
public int speedLimit;
public int sideSpeed;
public Text countText;
public Text winText;
public GameObject pickUp;
public GameObject finishLine;
//internal void ForceBack() //Not sure what it does and why it's there.
//{
// throw new NotImplementedException();
//}
private int count;
private Rigidbody rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
SetCount();
}
// Update is called once per frame
void FixedUpdate()
{
float moveHorizontal = Input.GetAxis("Horizontal") * sideSpeed * rb.velocity.magnitude / acceleration;
//float moveVertical = Input.GetAxis("Vertical") * acceleration;
if (rb.velocity.magnitude <= speedLimit)
{
rb.AddForce(0.0f, 0.0f, acceleration); // add vertical force
}
rb.AddForce(moveHorizontal, 0.0f, 0.0f); // add horizontal force
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag(pickUp.tag))
{
other.GetComponent<Rotate>().Disapear();
count++;
SetCount();
}
if (other.gameObject.CompareTag(finishLine.tag))
{
acceleration = 0;
sideSpeed = 0;
finishLine.GetComponent<GameEnd>().FadeOut();
if (count >= 2)
{
winText.GetComponent<WinTextFadeIn>().FadeIn("Vous avez remporté la partie!");
}
else
{
winText.GetComponent<WinTextFadeIn>().FadeIn("Vous avez perdu. Réesayer?");
}
}
}
private void SetCount()
{
countText.text = "Count : " + count.ToString();
}
public void ForceBack(float force)
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.AddForce(0.0f, 0.0f, -force, ForceMode.VelocityChange);
Debug.Log("Pass");
}
}
The AddForce function does not do anything. I tried with setActive(false) and it's not working either. The only thing that works is Debug.Log(). I'm not sure if the speedlimit and acceleration are interfering with the function.
EDIT: I'm not sure if the problem is from Unity but I can't access any variable of the class from the forceBack function inside the class.
EDIT2: I also tried to call the AddForce function directly in the Bounce Back script but it's not working either.
Player.GetComponent<Rigidbody>().AddForce(0.0f, 0.0f, -force, ForceMode.VelocityChange);
Player (Ball) Screenshot
Bounce Back Screenshot
So, a couple things:
1.) The physics system should already cause the ball to bounce if you've set up the colliders and rigidbodies properly. You should only need to do something like this if the ball should gain momentum when it bounces, which is unlikely. You should post screenshots of their inspectors if this answer doesn't help.
2.) On your rb.AddForce() call, you're applying a force in world-space, which may be the wrong direction to bounce. If you know the ball is oriented the way it's moving, then you can call AddRelativeForce with the same parameters. If the ball's orientation is not controlled, then you need to calculate the correct world-space direction to use before applying the force.
3.) Finally, just to confirm, the objects with BounceBack attached do have a non-zero value in the 'force' parameter in the inspector, right?

LibGDX making a rectangle move on its own

public class gameMain implements Screen {
final main game;
SpriteBatch batch;
Texture img;
private Texture alexTexture;
private Rectangle alex;
private Texture cTex;
private Texture dropper;
private Texture ender;
private Texture partsImg;
private Texture toy;
private OrthographicCamera camera;
private Array<Rectangle> part; // ******
private long lastDropTime;
private int beltSpeed = 100; // ******
//Score Keeper
private int score;
private String scoreName;
//basically a create method
public gameMain(final main gam){
this.game = gam;
// load images into memory
dropper = new Texture("android/assets/dropper.png");
ender = new Texture("android/assets/endOfBelt.png");
partsImg = new Texture("android/assets/unmadeToyParts.png");
toy = new Texture("android/assets/toymade.png");
cTex = new Texture("android/assets/conveyerBeltBackground.png");
alexTexture = new Texture(Gdx.files.internal("android/assets/alexAlpha2.png"));
// set the game window resolution
camera = new OrthographicCamera();
camera.setToOrtho(false, 1080,720);
// Alex's position / hitbox
alex = new Rectangle();
alex.x = 250;
alex.y = 150;
alex.width = 126;
alex.height = 75;
// part stuff
part = new Array<Rectangle>();
spawnPart();
// score handler
score = 0;
scoreName = "Toys Made: ";
}
private void spawnPart(){ // *******
Rectangle parts = new Rectangle();
parts.x = 0;
parts.y = 210;
parts.width = 52;
parts.height = 60;
part.add(parts);
lastDropTime = TimeUtils.nanoTime();
} //********
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
// load alex sprite
game.batch.setProjectionMatrix(camera.combined);
// begin drawing to screen
game.batch.begin();
batch.draw(cTex, -5, 200); // draw conveyer background
batch.draw(dropper, 0, 210); // draw the dropper
batch.draw(ender, 600, 200); // draw the ender
game.batch.draw(alexTexture, alex.x, alex.y); // draw alex
for(Rectangle parts: part){
game.batch.draw(partsImg, parts.x, parts.y); // draw part
}
game.font.draw(game.batch, scoreName, 25, 100); // draw scoreboard
game.batch.end(); // end drawing to screen
//******************************************************************************
//HERE IS WHERE I AM TRYING TO PUT IT
part.x += beltspeed;
if (part.rectangle overlaps ender.rectangle){
despawn part;
}
//******************************************************************************
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void resize(int width, int height) {
}
#Override
public void dispose() {
}
}
Hello I am very new to LibGDX, and after doing some research I decided to make a game where you are a factory worker named Alex and you build toys. I will gladly take any feedback you have to make my code more orginized or work better. I highlighted everything I believe to be relevant to my question with some asterisks.
But my question is: How do you make a 'rectangle' such as my 'part' move on its own. I added a beltspeed and a spawn zone, and once the hitbox for it goes over the 'ender' hitbox I would like to despawn it.
Also I haven't gotten this far yet, but when the 'part' hitbox passes over 'Alex' hitbox I would like a little minigame to appear where you have to press up, down, left, right (randomly) to build the toy. If you have any suggestions on how I should handle that, I would be very appreciative.
"C:\Program Files\Java\jdk1.7.0_79\jre\bin\java" -Didea.launcher.port=7532 "-Didea.launcher.bin.path=C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_79\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_79\jre\lib\rt.jar;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\desktop;C:\Users\RAFiredog\Desktop\Intellij\AlexTheTemp\out\production\core;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx\1.9.2\e641cb91bec06bc64d9ddf7a7d7062caceec73cd\gdx-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d\1.9.2\b78eaa90aaaf7830e6dffff587ea6e859c2787b2\gdx-box2d-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype\1.9.2\3609253d14edb1b3ca5aacff4e06989edde75be4\gdx-freetype-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-lwjgl\1.9.2\d710a8704ed584ec2ba9ca52e3a6a5885dd759cc\gdx-backend-lwjgl-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-platform\1.9.2\dde4cf7e9ce61c24042f512203aed87657496639\gdx-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-box2d-platform\1.9.2\497cbfbf81e7e8b1e8433b19291c5af4bbc2ec66\gdx-box2d-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-tools\1.9.2\37d8e3009ae0febdf93717b21980c67c8cadac07\gdx-tools-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-freetype-platform\1.9.2\1e1afb0b6c9e8aeb7d495cb8f55c353d3da58cf0\gdx-freetype-platform-1.9.2-natives-desktop.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl\2.9.2\a9d80fe5935c7a9149f6584d9777cfd471f65489\lwjgl-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl_util\2.9.2\4b9e37300a87799856e0bd15ed81663cdb6b0947\lwjgl_util-2.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.jlayer\jlayer\1.0.1-gdx\7cca83cec5c1b2f011362f4d85aabd71a73b049d\jlayer-1.0.1-gdx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.jcraft\jorbis\0.0.17\8872d22b293e8f5d7d56ff92be966e6dc28ebdc6\jorbis-0.0.17.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\com.badlogicgames.gdx\gdx-backend-headless\1.9.2\813e6020de85cd831f02cb5e9060fd7ea8cb208e\gdx-backend-headless-1.9.2.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\510c7d317f5e9e700b9cfaac5fd38bdebf0702e0\lwjgl-platform-2.9.2-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d276cdf61fe2b516c7b7f4aa1b8dea91dbdc8d56\lwjgl-platform-2.9.2-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\org.lwjgl.lwjgl\lwjgl-platform\2.9.2\d55b46b40b40249d627a83a7f7f22649709d70c3\lwjgl-platform-2.9.2-natives-osx.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput\2.0.5\39c7796b469a600f72380316f6b1f11db6c2c7c4\jinput-2.0.5.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jutils\jutils\1.0.0\e12fe1fda814bd348c1579329c86943d2cd3c6a6\jutils-1.0.0.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\7ff832a6eb9ab6a767f1ade2b548092d0fa64795\jinput-platform-2.0.5-natives-linux.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\385ee093e01f587f30ee1c8a2ee7d408fd732e16\jinput-platform-2.0.5-natives-windows.jar;C:\Users\RAFiredog\.gradle\caches\modules-2\files-2.1\net.java.jinput\jinput-platform\2.0.5\53f9c919f34d2ca9de8c51fc4e1e8282029a9232\jinput-platform-2.0.5-natives-osx.jar;C:\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 2016.1.1\lib\idea_rt.jar" com.intellij.rt.execution.application.AppMain com.rafiredog.game.desktop.DesktopLauncher
Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.rafiredog.game.gameMain.render(gameMain.java:97)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.rafiredog.game.main.render(main.java:45)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:223)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:124)
Process finished with exit code 0
Lastly, I am now getting this error. I moved some code around near the 'batch.draw'. However that might not be the cause of the error? I am a little lost right now. But I will gladly screenshot what I have of the game now once the errors are resolved.
Thank you for any insight you have on fixing up this game.
You need to do game updates and then rendering on each cycle of the game loop. The game update part of your code can iterate through your objects to do stuff to them.
For example, your render method would look like this. You need to explicitly use an Iterator for your for loop because you otherwise could not remove items from the list while iterating.
#Override
public void render(float delta) {
//Update game
Iterator<Rectangle> iterator = parts.iterator();
while (iterator.hasNext()){
Rectangle part = iterator.next();
part.x += beltSpeed * delta; //distance = speed * time
if (part.rectangle.overlaps(ender.rectangle)){
iterator.remove(); //removes rectangle from the list
}
}
//This is also where you would update movement for anything else,
//such as a character jumping, or counting down a timer and spawning
//something when it reaches zero, for example.
//Draw everything
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
game.batch.setProjectionMatrix(camera.combined);
game.batch.begin();
//...
game.batch.end();
}
If you spawn and "despawn" a lot of objects, you will probably need to use pooling to avoid stutters from memory deallocation. You can do this by replacing new Rectangle() with Pools.obtain(Rectangle.class) and adding the line Pools.free(part) right after iterator.remove().
I also noticed you have counter-intuitive usage of the words "part" and "parts" by swapping plural and singular. Make sure that doesn't trip you up.
As for your NullPointerException, read here.
Piggy backing onto Tenfour04's answer and attempting to answer your question in the comments. I'd suggest looking at this link: https://github.com/libgdx/libgdx/wiki/The-life-cycle

Removing all rectangles in rectangle array(LIBGDX)

Hi guys so I created a simple game with a flying helicopter in which you need to dodge the missiles. I want to remove all missiles that are created in the screen if gameOver boolean is true. What is happening is it's only removed if the helicopter dies because of hitting the missile, but if it dies by hitting the ground the "game over" message shows but the missiles are not removed!
I tried using
if(heliR.overlaps(missiles)){gameOver=true; Iter.remove; }
But like what I said all missiles are only removed if I died by hitting missile, can anyone help me in this?
Here is my code:
#Override
public void create()
{
batch = new SpriteBatch();
camera=new OrthographicCamera();
camera.setToOrtho(false,800,480);
restart=TimeUtils.nanoTime();
click=TimeUtils.nanoTime();
//fonts
font=new BitmapFont();
font1=new BitmapFont();
font2=new BitmapFont();
font.setColor(Color.RED);
font1.setColor(Color.BLACK);
font2.setColor(Color.WHITE);
font.setScale(3);
font1.setScale(1);
font2.setScale(2);
//score
points=0;
lastScore=TimeUtils.nanoTime();
//background
Texture texture=new Texture(Gdx.files.internal("background.png"));
background=new TextureRegion(texture,0,0,800,480);
//logo
logo=new Texture(Gdx.files.internal("logo.png"));
logoR=new Rectangle();
logoR.x=230;
logoR.y=240;
logoR.width=230;
logoR.height=100;
//helicopter
heli=new Texture(Gdx.files.internal("helicopter.png"));
heliR=new Rectangle();
heliR.x=280;
heliR.y=400;
heliR.width=heli.getWidth()-15;
heliR.height=heli.getHeight()-15;
//Sounds
heliSound=Gdx.audio.newSound(Gdx.files.internal("helicopter.wav"));
heliLanding=Gdx.audio.newSound(Gdx.files.internal("helicopter_landing.wav"));
collision=Gdx.audio.newSound(Gdx.files.internal("collision.wav"));
//missile
missileImg=new Texture(Gdx.files.internal("missile.png"));
missiles=new Array<Rectangle>();
}
public void spawnMissile(){
Rectangle missile=new Rectangle();
missile.y=MathUtils.random(60,400);
missile.x=mX;
missile.width=missileImg.getWidth()-15;
missile.height=missileImg.getHeight()-10;
missiles.add(missile);
lastMissile=TimeUtils.nanoTime();
velocity=250;
}
#Override
public void render()
{
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
batch.begin();
batch.draw(background,backGroundX-800,0,800,480);
batch.draw(background,backGroundX,0,800,480);
batch.draw(heli,heliR.x,heliR.y);
if(justStart==false && gameOver==false){
font2.draw(batch,"Points:"+points,345,480);}
//missile
for(Rectangle missile: missiles){
batch.draw(missileImg,missile.x,missile.y);
}
//game over
if(gameOver==true){
heliR.y=250;
heliR.x=330;
font.draw(batch,"Game Over",280,400);
font1.draw(batch,"[Long press on the screen to restart]",275,230);
font1.draw(batch,"Your points:"+points,348,250);
if(Gdx.input.isTouched()){
longClick+=1;
if(longClick==35){
gameOver=false;
points=0;
longClick=0;
heliR.y=300;
heliR.x=30;
}
}else{
if(TimeUtils.nanoTime()- click > 2000000){longClick=0;}
}
}
//starting game
if(justStart==true){
heliR.y=250;
heliR.x=330;
font2.draw(batch,"Touch the screen to start",230,230);
batch.draw(logo,logoR.x,logoR.y);
font1.draw(batch,"Developed by:Monzterr",5,15);
if(Gdx.input.isTouched()){
justStart=false;
heliR.y=300;
heliR.x=30;
}
}
batch.end();
//game physics
if(justStart==false&&gameOver==false){
//missile
if(TimeUtils.nanoTime()-lastMissile > 1000000000){spawnMissile();}
Iterator <Rectangle> iter=missiles.iterator();
while(iter.hasNext()){
Rectangle missile= iter.next();
missile.x-=velocity*Gdx.graphics.getDeltaTime();
if(missile.x<=-10){iter.remove();}
if(missile.overlaps(heliR)){
gameOver=true;
collision.play();
}
if(gameOver==true){
iter.remove();
}
}
//background
backGroundX= backGroundX-100*Gdx.graphics.getDeltaTime();
if(backGroundX<=0){
backGroundX=800;
}
//score
if(TimeUtils.nanoTime()-lastScore>2000000000){
points=points+1;
lastScore=TimeUtils.nanoTime();
}
//gravity
if(Gdx.input.isTouched()){
heliR.y+=5;
//heliLanding.play();
}else{
heliR.y-=5;
//heliLanding.pause();
}
}
//borders
if(heliR.y>=400){
heliR.y=250;
}
if(heliR.y<=56){
heliR.y=56;
gameOver=true;
mX=800;
collision.play();
}
}
#Override
public void dispose()
{
}
#Override
public void resize(int width, int height)
{
}
#Override
public void pause()
{
}
#Override
public void resume()
{
}
Sorry for messy code I just started learning programming last week.
You are checking if gameOver == true twice - one on the (almost) beginning of the render() method
//game over
if(gameOver==true){
heliR.y=250;
...
and second time under following condition
//game physics
if(justStart==false&&gameOver==false){
...
but you are removing iterator only in the second one
if(gameOver==true){
iter.remove();
}
fixing it should fix your problem. Consider also do you need two checks if gameOver is true (I believe you not - you can handle both situations in the first one)
You are changing gameOver to true in the middle of looping through all your enemies, and only removing them from within the loop, so only the enemies after the one that caused the game over will be removed. Replace iter.remove() with break (to jump out of the loop which is now unnecessary to finish). And then add a line after the loop:
if (gameOver) missiles.clear();
This removes everything from the array.

object's stage reference lost when re-instantiated after being removed from memory & displaylist

I'm building a game. When you die or win a level you're prompted to continue or return to the main menu. If you chose to go to the main menu you can start a new game. When you start a new game, the game is object is created again & it's children have lost their reference to the stage. I'm not sure why this is happening and I've spent over a week trying to figure out why. Here's some code (and descriptions of the code) from the game that should hopefully provide enough insight as to why the problem may be occurring:
if the "new game" button is clicked on the startMenu the NavigationEvent.START event is dispatched. a LevelEvent.COMPLETE event is dispatched by WeeBeeGame when the level is completed.
public class DocumentClass extends MovieClip {
public var startMenu:StartMenuGenerator = new StartMenuGenerator();
public var weeBeeGame:WeeBeeGame;
public var youWonBox:YouWonBox = new YouWonBox();
public function DocumentClass() {
// constructor code
addChild(startMenu);
startMenu.addEventListener(NavigationEvent.START, startGameHandler);
}
public function startGameHandler(e:NavigationEvent) : void {
this.removeChild(startMenuBG);
removeChild(startMenu);
weeBeeGame = new WeeBeeGame();
this.addChild(weeBeeGame);
weeBeeGame.addEventListener(LevelEvent.COMPLETE, levelCompleteHandler);
}
public function levelCompleteHandler(e:LevelEvent) : void {
youWonBox.x = this.stage.stageWidth/2;
youWonBox.y = this.stage.stageHeight/2;
addChild(youWonBox);
youWonBox.addEventListener(MouseEvent.CLICK, mouseClickHandler);
}
private function mouseClickHandler(e:MouseEvent) : void {
if(e.target.name === "mainmenubtn"){
mainmenuHandler();
}
}
private function continueHandler() : void {
youWonBox.removeEventListener(MouseEvent.CLICK, mouseClickHandler);
}
private function mainmenuHandler() : void {
youWonBox.removeEventListener(MouseEvent.CLICK, mouseClickHandler);
WeeBeeGame.collisionDOC.removeChildren();
removeChild(weeBeeGame);
weeBeeGame = null;
this.addChild(startMenuBG);
addChild(startMenu);
removeChild(youWonBox);
}
}
the code that dispatches a LevelEvent.COMPLETE event is not shown but it dispatches when the level is complete. collisionDOC needs to be static because it's needed in a lot of other classes and holds the display objects needed for a 3rd party pixel-level collision detection.
public class WeeBeeGame extends MovieClip {
public var bee: Bee;
public var beeHurt:BeeHurt;
public var spawningDaemon:SpawningDaemon;
public static var collisionDOC:DisplayObjectContainer;
public function WeeBeeGame() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true);
}
private function addedToStageHandler(e:Event) : void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
collisionDOC = new MovieClip();
addChild(collisionDOC);
bee = new Bee();
collisionDOC.addChild(bee);
beeHurt = new BeeHurt(bee.x, bee.y);
addChild(beeHurt);
beeHurt.visible = false;
spawningDaemon = new SpawningDaemon(currentLevel);
this.addEventListener(LevelEvent.COMPLETE, levelCompleteHandler, false, 0, true);
}
private function levelCompleteHandler(e:LevelEvent) : void {
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
}
the first line to throw a 1009 error (Cannot access a property or method of a null object reference) is the line containing stage.mouseX because the stage reference is null.
public class Bee extends MovieClip {
public function Bee() {
this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
private function addedToStageHandler(e:Event) : void {
this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
this.x = this.stage.stageWidth / 2;
this.y = this.stage.stageHeight - this.stage.stageHeight / 9;
this.addEventListener(Event.ENTER_FRAME, enterFrameHandler, false, 0, true);
}
private function enterFrameHandler(e:Event) : void {
if(stage == null){
trace('stage is null' + stage.mouseX);
}
}
}
When the swf is first opened and a new WeeBeeGame is created its children have references to the stage. But when WeeBeeGame and it's children are removed from the display list and memory they lose reference and even if they're re-instantiated their references are still lost. How do I fix this? I'm very confused. Thank you all!!
ENTER_FRAME handlers continue to execute even when the display object is removed form the stage. So when you removeChild(weeBeeGame) those ENTER_FRAME handlers are still trying to access stage.mouseX each frame. You need to stop the ENTER_FRAME handlers.
Probably the easiest fix is to add an Event.REMOVED_FROM_STAGE handler to remove the Event.ENTER_FRAME handlers.
A better fix IMO is to not add any ENTER_FRAME handlers from your game objects, but rather expose a public function like update() which gets called from a single ENTER_FRAME handler in your WeeBeeGame when the game is running. Then to stop the game completely you can stop all updates by simply removing that single ENTER_FRAME handler. This is a common practice.

Actionscript 3.0...Preloader not working....Stuck in frame 0?

I'm trying to make my first preloader come to fruition on my game. I've done quite a bit of experimenting and here's what I've found.
First off, when I simulate my file, I am simply getting a blank white screen until the file...or actually just a large image I'm using att the moment...is fully loaded. I used the Bandwidth Profiler to check what was going on. It is loading at a proper rate and I can see the loading percentage increasing. Unfortunately my loader just doesn't appear, and the weird thing is it says it's in frame 0. I have no idea why it is telling me this.
What I've done to try and fix it. I've made sure that EVERY movieclip in my game has the box for exporting on first frame is unchecked, EXCEPT my preloader, so that shouldn't be the problem. I also created a blank .fla file and simply imported my preloader into it and ran it. Surprisingly, it worked! (once again, just loaded a large image). I didn't change anything....all the same names and stuff. I have no idea why that one would work and this one wouldn't.
My timeline basically is the following: Two layers: First layer first frame actions says stop();. I would assume my preloader should load on the first frame like I've told it too. Once finished loading, it runs through the timeline to frame 3, where my main game should start running since I also put in the actions of frame 3. Second layer second frame I have a MovieClip that contains the image that I want it to load.
Here is my document class
package com.classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.display.Sprite;
import flash.events.Event;
public class DocumentClass extends MovieClip
{
private var preloader:ThePreloader;
public static var enemyList1:Array = new Array();
// moved stickobject1 to a class variable.
private var stickobject1:Stickman2;
private var scoreHud:ScoreHud;
public function DocumentClass() : void
{
preloader = new ThePreloader(390, this.loaderInfo);
stage.addChild(preloader);
preloader.addEventListener("loadComplete", loadAssets);
preloader.addEventListener("preloaderFinished", showSponsors);
var bg1:background1 = new background1();
stage.addChild(bg1);
stickobject1 = new Stickman2(stage);
stage.addChild(stickobject1);
stickobject1.x=50;
stickobject1.y=300;
//running a loop now.... so we can keep creating enemies randomly.
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
stickobject1.addEventListener("hit", stickobject1Hit, false, 0, true);
scoreHud = new ScoreHud(stage); //create our HUD
stage.addChild(scoreHud); //and display it.
}
private function loadAssets(e:Event) : void
{
this.play();
}
private function showSponsors(e:Event) : void
{
stage.removeChild(preloader);
trace("show sponsors");
}
//our loop function
private function loop(e:Event) : void
{
//run if condition is met.
if (Math.floor(Math.random() * 40) == 5)
{
//create our enemyObj1
var enemyObj1:Enemy1 = new Enemy1(stage, stickobject1);
//listen for enemyObj1 being removed from stage
enemyObj1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemyObj1, false, 0, true);
enemyObj1.addEventListener("killed", enemy1Killed, false, 0, true);
enemyList1.push(enemyObj1);
stage.addChild(enemyObj1);
}
}
private function enemy1Killed(e:Event) : void
{
scoreHud.updateKills(1); //add 1 to enemy kills
scoreHud.updateScore(e.currentTarget.points); //add that points variable we created earlier
}
private function stickobject1Hit(e:Event) : void
{
scoreHud.updateHits(1); //add 1 to number of hits
}
private function removeEnemyObj1(e:Event)
{
enemyList1.splice(enemyList1.indexOf(e.currentTarget), 1);
}
}
}
and here is my "ThePreloader" class
package com.classes
{
import flash.display.LoaderInfo;
import flash.display.MovieClip;
import flash.events.*;
public class ThePreloader extends MovieClip
{
private var fullWidth:Number; //the width of our mcPreloaderBar at 100%
public var ldrInfo:LoaderInfo;
public function ThePreloader(fullWidth:Number = 0, ldrInfo:LoaderInfo = null)
{
this.fullWidth = fullWidth;
this.ldrInfo = ldrInfo;
addEventListener(Event.ENTER_FRAME, checkLoad);
}
private function checkLoad (e:Event) : void
{
if (ldrInfo.bytesLoaded == ldrInfo.bytesTotal && ldrInfo.bytesTotal != 0)
{
//loading complete
dispatchEvent(new Event("loadComplete"));
phaseOut();
}
updateLoader(ldrInfo.bytesLoaded / ldrInfo.bytesTotal);
}
private function updateLoader(num:Number) : void
{
//num is a number between 0 and 1
mcPreloaderBar.width = num * fullWidth;
}
private function phaseOut() : void
{
removeEventListener(Event.ENTER_FRAME, checkLoad);
phaseComplete();
}
private function phaseComplete() : void
{
//go on to the next phase
dispatchEvent(new Event("preloaderFinished"));
}
}
}
My main confusion is why the Bandwidth Profiler is telling me I'm stuck in frame 0 and until it's pretty much 100% loaded. Thus, not ever displaying the preloader....thank you!
I think your preloader should be listening to LoaderInfo's progress event. Since, you have stopped execution, I don't think ENTER_FRAME would get called for you.
Also, AFAIR, single frame movie are treated specially by the player and player sends ENTER_FRAME periodically for them. Probably, that is the reason you test application worked out.