In my world’s update function.
Collision / World Class
Since it seems like nobody knows how to solve my problem (so far), could anyone tell me, how they would do it? Let’s say, you have a bullet, and a spinning square. If bullet hits the square, it triggers the new world to initialize. How do I do that, apart from my noobish technique?
Sry for the double post.
As @justinwolf already pointed out, the error you get on line 89 (Cannot access a property or method of a null object reference.
) most probably indicates that your _bullet
var is null
at some point.
To fix it you can try to also test for its existence in the if
condition:
if (_bullet != null && _bullet.collide("pill", _bullet.x, _bullet.y)
this is the bullet’s class:
public function Bullet(posx:int, posy:int)
{
graphic = new Image(BULLET_ART);
collidable = true;
x = posx;
y = posy;
setHitbox(10, 10, 5, 5);
type = "bullet";
}
I can’t see why is it working. It doesn’t make any sense.
var bullet:Bullet = new Bullet(x - 3, y);
if (Input.released(Key.S))
{
world.add(bullet);
bullet.fire(0, 5);
}
if (Input.released(Key.W))
{
world.add(bullet);
bullet.fire(0, -5);
}
if (Input.released(Key.A))
{
world.add(bullet);
bullet.fire(-5, 0);
}
if (Input.released(Key.D))
{
world.add(bullet);
bullet.fire(5, 0);
}
if (bullet.collide("pill", bullet.x, bullet.y))
{
FP.world = new Menu1;
}
well, it’s still not working.
Hmm. Post the entire source of your world class so I can further examine what could be happening.
package
{
import Enemy.BackdropBG;
import Enemy.blue_block;
import Enemy.Pill;
import Enemy.Snow;
import Enemy.WallOne;
import net.flashpunk.Entity;
import net.flashpunk.FP;
import net.flashpunk.graphics.Image;
import net.flashpunk.graphics.Text;
import net.flashpunk.tweens.misc.VarTween;
import net.flashpunk.World;
/**
* ...
* @author PawelBetkowski
*/
public class LevelOne extends World
{
[Embed(source="../assets/redbg.png")]
protected const LEVEL_ONE_BG:Class;
protected var _timeLeft:Number = 0;
protected var _levelCount:Text;
protected var _instruction:Text;
var bullet:Bullet;
private var _pill:Pill;
public function LevelOne()
{
super();
}
override public function begin():void
{
Text.font = "czcionkaDWA";
_levelCount = new Text("1/20", 710, 510);
_levelCount.size = 50;
_levelCount.color = 0xFFFFFF;
_instruction = new Text("He has to stop, he has to make pills disappear");
_instruction.size = 50;
_instruction.color = 0xFFFFFF;
_instruction.centerOrigin();
FP.screen.color = 0xFFFFFF;
add(new BackdropBG());
addGraphic(_levelCount);
addGraphic(_instruction, 0, FP.halfWidth, 40);
// Gracz
add(new Player(400, 300))
add(new Pill(400, 400));
//Walls
add(new WallOne(364, 332));
add(new WallOne(402, 332));
add(new WallOne(332, 300));
add(new WallOne(436, 300));
add(new WallOne(300, 268));
add(new WallOne(468, 268));
add(new WallOne(268, 236));
add(new WallOne(500, 236));
add(new blue_block(400, 200));
}
override public function update():void
{
super.update();
if (bullet.collide("pill", bullet.x, bullet.y))
{
FP.world = new Menu1;
}
}
}
}
Okay, various problems I can see.
- Define your
bullet
object asprivate var bullet:Bullet;
-
bullet
never actually gets set or created in your World class, as you stated before. Where are you running the functions that check for your Input?
It looks like you’re going about this in an unusual way that’s likely making it a lot harder for yourself.
In my player’s update. Because the bullet is being created where player’s x and y is.
Let’s just remove that bullet collision check from your world completely. You should handle its collision inside your actual Bullet
class, in its own update loop. So inside your Bullet
class’ update, add:
if (collide("pill", x, y)) FP.world = new Menu1;
However, I imagine you’ll have some other problems because according to your code you’re constantly creating a new bullet every update tick, assuming that this post is all contained within your update. You’ll want to move the var bullet:Bullet = new Bullet(x-3, y);
line inside each Input check so that new bullets only get created when you release one of the appropriate keys:
var bullet:Bullet;
if (Input.released(Key.S))
{
bullet = new Bullet(x-3, y);
world.add(bullet);
bullet.fire(0, 5);
}
if (Input.released(Key.W))
{
bullet = new Bullet(x-3, y);
world.add(bullet);
bullet.fire(0, -5);
}
if (Input.released(Key.A))
{
bullet = new Bullet(x-3, y);
world.add(bullet);
bullet.fire(-5, 0);
}
if (Input.released(Key.D))
{
bullet = new Bullet(x-3, y);
world.add(bullet);
bullet.fire(5, 0);
}
See, the problem is, I only want the bullet to get me to the next world in this level. In next level, it might be 3 pills destroyed, in the next one, it might be something else. That’s why I thought I need to do it in the world’s update.
Even if I write this in bullet’s update:
if (collide(“pill”, x, y)) FP.world = new Menu1;
it’s not working.
Is there no way I can create an event inside of the world’s function using entity’s properties?
This is a good thing for inheritance to handle. Create a Base World Class (Lets call it BaseWorld) that defines a base function:
public class BaseWorld
{
public function destroyedAPill(): void { }
}
Then you want to extend (or inherit from) that class in all your level worlds;
public class MyWorldClass extends BaseWorld
{
// ...
}
You can use something like (FP.world as BaseWorld).myFunction();
to call myFunction() in any world that extends BaseWorld. So, something like (FP.world as BaseWorld).destroyedAPill();
, which calls destroyedAPill in your current world (as long as it extends BaseWorld!), a function you might define like so (in your actual world class):
public override function destroyedAPill(): void
{
// We destroyed a pill. In this world, we want to advance straight away!
FP.world = new World2; // when you make World2, make sure to remember to extend BaseWorld!
}
Remember you have to define the base function in BaseWorld!
So how does it work? When you do (FP.world as BaseWorld).myFunction();
you’re saying ‘We know that FP.world, the current world, extends BaseWorld. Anything that extends BaseWorld definitely has the myFunction() function, because BaseWorld has that function. We want to call the version of that function that corresponds with whatever world is currently active’. This is powerful. This means that every world can define its own ‘override’ of destroyedAPill and handle it differently. They could change the world. They could check if 3 pills have been destroyed. They could create new pills; they could print some text to the screen! Whatever you want to do in each world.
Another way to handle this would be to simply have a counter in the world - make a public variable called ‘pillsNeeded’, then you can do (FP.world as MyWorldName).pillsNeeded
within any Entity class to get the number of pills needed to advance. Not as exciting as inheritance… but maybe a bit easier (but definitely not as flexible either!)
should the BaseWorld extend World or should it be an empty class?
@Ultima2876, you inspire me. I can feel it will work.
but there’s a problem,
if (_bullet.collide("pill", _bullet.x, _bullet.x))
{
(FP.world as BaseWorld).DestroyedPill();
}
still cannot access that property in the first line.
Is this even the correct way to handle entity’s collision in world class?
Maybe because my bullet is created when player fires, and it’s written in player’s entity and not in the world itself?
So I did it the easier way with the var and stuff, and it works! Thank you so much @Ultima2876!
One question tho, when I write this:
FP.world = new Level2();
it works, but when I write this:
var newWorld:World = new Menu1();
var oldView:Image = FP.screen.capture();
oldView.relative = false;
var e:Entity = newWorld.addGraphic(oldView, -200);
var fader:VarTween = new VarTween(function():void { newWorld.remove(e);}, ONESHOT);
fader.tween(oldView, "alpha", 0, 2);
newWorld.addTween(fader, true);
FP.world = newWorld;
It doesn’t. Anyone knows why?
EDIT: And now, It works once, then I run program again, and it doesn’t. What is going on.