Libgdx and Box2d / Particles are not following bodies - libgdx

i'll just cut to the chase.
So i'm making this game where you should kill other objects with your spells i've created bullets and their bodies we're all good it's working.
But i wanted to make it look special and "magiclike" so i decided to use particles. I've made the particles and put and made them follow the bullet bodies with this code:
for (Bullet bullet : bullets) {
bullet.update(dt);
if (!bullet.destroyed){
fireFx.start();
fireFx.setPosition(bullet.getPosition().x, bullet.getPosition().y);
fireFx.update(dt);
}
}
but there's a problem when i fire multiple bullets particles are just dissappearing from the all of the first bullets i fired and just appears on the last one. Can someone lead me on this one please ?
-----------------EDIT-----------------
Now i've got another problem that when bullet collides with something it gets destroyed and render method stops working but i want it to keep rendering till the animation is over. Like i don't want them to disappear suddenly here is my code for this:
for(int i = 0; i<bullets.size; i++){
if(!bullets.get(i).destroyed && !bullets.get(i).fireFx.isComplete())
bullets.get(i).fireFx.draw(game.batch);
}
fireFx.isComplete() is not working correctly what is the reason ?

The issue is that you're updating a single particle to have the coordinates of all the bullets in a list, and effectively keeping the coordinates of the last bullet in the list. You could maintain a Map that maps Bullets onto Particles, but I would instantiate a fireFx object when a Bullet is created and add it to the Bullet object. Then, in the Bullet#update method you can call the particle update method:
public void update(float dt) {
[...]
if ( !this.isDestroyed()) {
[...]
this.fireFx.start();
this.fireFx.setPosition(this.getPosition().x, this.getPosition().y);
this.fireFx.update(dt);
[...]
}
[...]
}

Related

Rotating a Model in Away3D

Here's what i want to do:
I want to load a model (most likely .3ds) into my .swf and be able to rotate it with the mouse.
This works fine at first glance, but there's problem, the rotations 'switch' over. Or to say it differently:
Imagine we have a model in the shape of a pipe.
If we drag the mouse to the right, the model rotates along its X-Axis to the left, mouse to the left, X-Axis rotation to the right, moving the mouse up, Y-Axis rotation downward, mouse down, Y-Axis rotation upward.
Now, lets say we turn the pipe to the right or left, until we face the (former) 'backside' of the pipe, and then we move the mouse down. The model will rotate downward instead of upward.
I hope you understand what i mean with this. I've been looking around for a good while now and never found a satisfying solution. There was talk about quaternions, but i can't grasp them.
Another suggestion i read somewhere is the following:
create a Matrix3D object, apply rotation on it, then multiply it with the desired Matrix3D of my 3d-Model.
I tried to do it, but the result stays the same, the directions of rotation switches depending on what side i'm facing.
private function update(e:Event):void
{
xCalc = (0.3*(stage.mouseX - lastMouseX));
yCalc = (0.3*(stage.mouseY - lastMouseY));
if(move)
{
var objTransform:Matrix3D = new Matrix3D();
objTransform.prependRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.prependRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = multiply3DMatrices(mesh.transform, objTransform);
}
lastMouseX = stage.mouseX;
lastMouseY = stage.mouseY;
view.render();
}
multiply3DMatrices simply multiplies two 4x4 Matrices together.
objC is the ObjectContainer3D that holds my model. For some reason i cannot rotate it properly, unless i manipulate the rotationX/Y/Z properties.
mesh is the mesh inside of the Model (which is very simple, a single mesh).
Also, i'm aware that i could try another Framework for this (like papervision) but this project requires me to use Away3D.
Solved it by myself, the problem was that i created a new Matrix3D Object every time. The fixed code looks like this:
private function update(e:Event):void
{
...
if(move)
{
var objTransform:Matrix3D = mesh.transform;
objTransform.appendRotation(xCalc, Vector3D.Y_Axis, objC.pivotPoint);
objTransform.appendRotation(yCalc, Vector3D.X_Axis, objC.pivotPoint);
mesh.transform = objTransform;
}
...
}
And yes, the user bwroga was actually right, i should've used appendRotation instead of prependRotation, as well.

nested collision starling as3

I am using starling and tweenMax frameworks in my project.
The trouble I am running into is this:
For the purpose of animating along different paths, I am using tweenmax.
There is one _leaderEnemy that animates along a path and I am pushing several other _shooterEnemy (they are of the same class) into it.
public function createEnemies(enemyNo:int, path:Array, offset:int):void
{
for(var i:uint=1;i<=enemyNo;i++){
if (i==1){
_leaderCount++;
_leaderEnemy = new ShooterEnemy();
_leaderEnemy.x=600;
_leaderEnemy.y=300;
_leaderEnemy.name="_shooterEnemy"+_leaderCount;
this.addChild(_leaderEnemy);
leaderEnemyArray.push(_leaderEnemy);
}
else
{
_leaderCount++;
_shooterEnemy= new ShooterEnemy();
_shooterEnemy.x=0;
_shooterEnemy.y=(offset*(i-1));
_shooterEnemy.name="_shooterEnemy"+_leaderCount;
trace("no: "+_shooterEnemy.name);
leaderEnemyArray.push(_shooterEnemy);
_leaderEnemy.addChild(_shooterEnemy);
}
}
Now I want to check for collision using starling between each of the _leaderEnemy and the _shooterEnemy inside it with _shooterHero.
Running this array successfully checks collision with the whole group i.e. _leaderEnemy but not the individual ones inside it.
Technically, I should be able to do this just by:
var Track:Object;
for(var i:uint=0;i<leaderEnemyArray.length;i++) {
Track=leaderEnemyArray[i];
if (Track.bounds.intersects(_shooterHero.bounds)){
Track.rotation=deg2rad(70);
}
}
It may be something stupid I am doing. But I have not been able to solve this.
Any help on this would be appreciated.
Some other questions I have:
Can I check for collision with _shooterHero from inside the _shooterEnemy's class?
I have tried:
if (this.bounds.intersects(stage.getChildByName("_hero"))){
}
although it did not work.
Can I check for collision of one Enemy with everything on stage, so I can assign individual functions for his each contact?
For example: hit with hero: die; hit with another enemy: turn around
If you need more info, I will be happy to provide it.
Thank You.
Can I check for collision of one Enemy with everything on stage, so I can assign individual functions for his each contact? For example: hit with hero: die; hit with another enemy: turn around
Of course you can. You should! This is approximatively how collision engines works.
Running this array successfully checks collision with the whole group i.e. _leaderEnemy but not the individual ones inside it.
Nope. It won't work. Because the bounds property use the parent coordinates.
Meaning you can intersect each child display (of same container) with each other.
But you shouldn't intersect a child display of A with a child display of B.
Except if you convert every bounds coordinates (which are local) to global.
http://doc.starling-framework.org/core/starling/display/DisplayObject.html#localToGlobal()
Using Track.bounds.intersects is one way of checking collosions. Another would be to use hitTest method of starling.displayDisplayObject
You could also check the distance of your hero and other enemies calculated by a pythagorean theorem type calculation.
Are you checking enemies against each other? If you have many enemies you might want to look into "flocking" algorithms. Keith Petes covers this subject nicely in his book Advanced Actionscript Animation.

Flash: AS3 – Bring symbol to front on rollover within movie

I have created a map of Europe in Flash using AS3. I am an absolute beginner. Each country has been converted into a movie (using lasso tool). These movies are on one layer (with slight outline visible) on main timeline. On the other main timeline layer is the original outline map of Europe.
I have managed to make it so when a country is rolled over, a box tweens in scale to full size (to later insert text in).
I need to make it so that when each country is rolled over, that country's text box (which appears on Roll_Over) comes 'to the front'.
At the moment a couple of countries' text boxes work perfectly (ie: filled with white and completely visible), but most are either buried beneath the main map, or threading randomly through the faint movie clip outlines (which are at the front).
I'm guessing that this has to do with the display list. The countries that work perfectly are probably at the top. But how do I make it so that the country rolled over immediately goes to the top and returns on Roll_Out?
This would complete my map so any help would be VERY MUCH appreciated.
I have used following code:
//FRAME ONE
this.stop();
movieClip_6.addEventListener(MouseEvent.ROLL_OVER, fl_MouseOverHandler_15);
function fl_MouseOverHandler_15(event:MouseEvent):void
{
gotoAndPlay(2);
}
movieClip_6.addEventListener(MouseEvent.ROLL_OUT, fl_MouseOutHandler_67);
function fl_MouseOutHandler_67(event:MouseEvent):void
{
gotoAndStop(1);
}
//SECTION BELOW IS MY PROBLEM
movieclip_6.addEventListener(MouseEvent.ROLL_OVER,Rollover,false,0,true);
function Rollover(event:MouseEvent): void
{
setChildIndex(MovieClip(e.target),this.numChildren-1);
}
Many thanks in advance.
You can try calling addChild() again to the DisplayObject/Movieclip to bring it to the front. Instead of:
setChildIndex(MovieClip(e.target),this.numChildren-1);
Try going:
addChild(MovieClip(e.target));
You can use "layers" to bring objects in front of another.
constructor:
//Create the front layer
var frontLayer:Sprite = new Sprite();
//put all text boxes into front layer
frontLayer.addChild(textbox1); //etc...
//Add layer to mc
addChild(frontLayer);
rollover pops up:
textbox1.visible = true;
pop down:
textbox1.visible = false;

Random position without overlapping

How to stop MCs from overlapping each other?
private function loadWishes():void {
for (i; i<myXMLList.length(); i++) {
cBox=new MovieClip();
checkOverlap(cBox);
addChild(cBox);
commentArray.push(cBox);
}
}
private function checkOverlap(wishB:MovieClip) {
wishB.x=Math.random()*stage.stageWidth;
wishB.y=Math.random()*stage.stageHeight;
for (var i:uint=0; i<commentArray.length; i++) {
if (wishB.hitTestObject(commentArray[i])) {
checkOverlap(wishB);
return false;
}
trace(commentArray.length);
}
}
This doesn't seems to be working cause the amount of it checking whether MC is overlapping is about the amount of MC on stage. how to make it keep checking till everything's fine?
The code you have here should work in general for preventing overlapping (though you should be careful - in a worst-case scenario this code might loop infinitely if the clips are too big or the stage is too small).
However, your problem is that you're calling this code on newly-created MovieClip objects, which are empty - so they can never overlap. Presumably you're adding in some child contents to the clips later, and at that point they overlap. So the fix is, you should populate the clips first, before checking if they overlap, or alternately, if you know the size of the clips, then instead of calling hitTestObject you could manually check whether the clip's position is too close to other clips.

Movieclip stacking in Actionscript

I'm building a game of which the interface is one of the first items to load on screen. Sound button, pause and all the bits -
During the game - all manor of things are dynamically added and removed to the stage. Therefore my interface goes behind my game scene.
How do I ensure the movieclip always stays on top?
Can I override the addChild of my Document Class and every time a new child is added, I restack the interface to the top?
You can use setChildIndex to rearrange objects that are already contained within a MovieClip or Sprite. For example, if you have an object called container, which contains a redBall, blueBall and many other ball objects, you can use the following to make sure redBall is behind everything else:
container.setChildIndex(redBall, 0);
Equally you can make sure that blueBall will be displayed infront of everything else using:
container.setChildIndex(blueBall, container.numChildren-1);
addChildAt will sort you out for adding children straight into their correct position, and setChildIndex will allow you to re-position objects already placed. Hope that helps.
debu
Look into addChildAt, it allows you to specify the index that the new object should be added too.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObjectContainer.html#addChildAt%28%29
A good strategy is to keep all interface elements in one parent Sprite/MovieClip, and all game assets in another. (With the interface one on top)
With your guys suggestion I made this, apparently, if you addChild an object already on the screen, it's simply reindex'd to the top. Does this look ok?
private var topLevelChildrenArray:Array = [];
public function addTopLevelChild(child:DisplayObject):DisplayObject
{
topLevelChildrenArray.push(child)
return this.addChildAt( child, this.numChildren - 1 );
}
override public function addChild(child:DisplayObject):DisplayObject
{
this.addChildAt(child, this.numChildren);
for each(var topChild:DisplayObject in topLevelChildrenArray)
{
super.addChild(topChild);
}
return child
}