AS3: Camera-Drag is jerking - actionscript-3

I have a big problem because I need to move my camera by dragging the mouse (finger on mobile) to a position you want.
The code itself works fine but I have a bad jerking while dragging.
My Code:
if(_drag)
{
var mousePos:Point = new Point(_gameRef._stage.mouseX, _gameRef._stage.mouseY);
var localPos:Point = _gameRef.MainElement.globalToLocal(mousePos);
var diffX:Number = MathHelper.Difference(_prevMPosX, localPos.x);
var diffY:Number = MathHelper.Difference(_prevMPosY, localPos.y);
// Add the position changes for the camera
if(localPos.x < _prevMPosX)
_gameRef.CamController.x += diffX;
if(localPos.x > _prevMPosX)
_gameRef.CamController.x -= diffX;
if(localPos.y < _prevMPosY)
_gameRef.CamController.y += diffY;
if(localPos.y > _prevMPosY)
_gameRef.CamController.y -= diffY;
// change the previous mouse position to the current
_prevMPosX = localPos.x;
_prevMPosY = localPos.y;
e.updateAfterEvent();
}
The funny thing is that when I change the + to - and opposite then it works without jerking (but it doesn't feel natural so it's not the solution to my problem).
Thanks a lot!

Alright, the fault was to use the local coordinates.
No I've made every dependency from my global stage coordinates and it works without any jerking!

Related

Moving Object to another Objects position

Hey everyone so I am having some trouble trying to get this to work correctly. I have a MC Object called character and another called "points". I have a container object called planetContainer I add the character to the planetContainer the character is rotating around the planets that are also added to the container. The main issue I am having is when the points power up is activated I want the points to move off the other planets and to the charactercenter position. It was working perfect but had to update some code and remove the Points out of the planetContainer and attach them to the planets instead. I know I might have to use localToGlobal but not too sure.
Here is how I setup the character:
private function newCounterClockWise():void
{
planetContainer.addChild(character);
character.rotation = (Math.atan2(character.y - planetHit.y, character.x - planetHit.x) * 180 / Math.PI);
}
How the points are added to the Planets:
private function addPoints():void
{
points = new mcPoints();
var planetPosition:Point = planetContainer.parent.localToGlobal(new Point(0, 0));
points.x = planetPosition.x;
points.y = planetPosition.y;
outerPlanets.addChild(points);
aPointsArray.push(points);
}
Now this is the main function that handles the points to move to the character but it is not working correctly. The points move but they move off the screen or cause the game to kinda tweak out and do different things. Also the "magnetHandler(); is in my EnterFRame Event:
private function magnetHandler():void
{
for (var i:int = 0; i < aPointsArray.length; i++)
{
var currentPoints:mcPoints = aPointsArray[i];
var characterPosition:Point = planetContainer.parent.globalToLocal(new Point(character.x, character.y));
if (currentPoints.hitTestObject(playScreen.mcPointsHit))
{
trace("POINTS MID STAGE");
currentPoints.x -= (currentPoints.x - characterPosition.x);
currentPoints.y -= (currentPoints.y - characterPosition.y);
//currentPoints.x = character.x;
//currentPoints.y = character.y;
//TweenMax.to(currentPoints, 0.5, {x:characterGlobalPosition.x, y:characterGlobalPosition.y , ease:Power1.easeInOut } );
}
}
}
Can anyone see what I am doing wrong?
It's a hard to understand your question fully (or to understand why you're putting things that relate to each other in separate containers), but likely this line is where it's falling down:
var characterPosition:Point = planetContainer.parent.globalToLocal(new Point(character.x, character.y));
What you want to do, is get the characters x/y coordinates in the currentPoints parent space. To do that, you would do something like this:
//first, find the global position of character:
var globalCharacterPoint:Point = character.localToGlobal(new Point());
//then, convert that to the currentPoints parent local space:
var localCharacterPoint:Point = currentPoints.parent.globalToLocal(globalCharacterPoint);
Also, in this code of yours:
points = new mcPoints();
var planetPosition:Point = planetContainer.parent.localToGlobal(new Point(0, 0));
points.x = planetPosition.x;
points.y = planetPosition.y;
You are getting the global space of the planetContainer's parent, which is probably NOT what you want. You likely want:
planetContainer.localToGlobal(new Point()); //this gives you the global location of the planet container's top left corner
And, since you're adding the points object to outerPlanets, you probably want to convert to its local space (unless it's positioned at 0,0 globally - then it doesn't especially matter).
var outerPoint:Point = outerPlanets.globalToLocal(planetPosition);
points.x = outerPoint.x;
points.y = outerPoint.y;
Needless to say, for games it's best to have everything in the global coordinate space unless it's truly encapsulated assets (like smoke on a rocket etc.)

AS3 Change position of object in TileList

I am using a tileList in ActionScript 3 to display movieclips. However I have the problem that not all reference points of the movieclips are in the correct place. This leads to that these movieclips are shown partly outside of their cell in the tileList.
I have tried to adjust the x and y position of the movieClip before adding it to the tileList, but this did not change anything. Now I have tried to find if it is possible to change the x and y position of an object already in the tileList, but without finding any answers.
I hope that I have made my problem clear.
Thanks in advance!
EDIT:
This is the code I tried:
private function initTileList():void {
for(var i:int = 0; i < _movieClips.length; i++) {
changePos(_movieClips[i]);
tileList.addItem({label: _movieClips[i].name, source: _movieClips[i]});
}
}
private function changePos(mc:MovieClip):void {
if(MovieClip(mc).getRect(mc).x != 0) {
mc.x -= MovieClip(mc).getRect(stateMachineRef).x;
}
if(MovieClip(mc).getRect(mc).y != 0) {
mc.y -= MovieClip(mc).getRect(stateMachineRef).y;
}
}
I do not have any errors, it just doesn't affect the position of the object in the tileList.
Example of how the problem looks.
Hard to say where's the problem without knowing these things:
1. What tileList.AddItem() does exactly;
2. What is stateMachineRef
3. How MovieClips are loaded. If they are loaded from a network, that'll be a whole different story.
By the way, you don't have to cast MovieClip(mc) as mc is already a MovieClip. Also, there is no difference as to when you will correct the coordinates: before or after adding to the tileList. Should work either way.
So, given that information on your problem is not complete, I would just suggest you insure the following steps:
-We assume all tiles are displayed inside a tile container. It can be Stage or a MovieClip or any suitable DisplayObjectContainer, so let's call it just tileContainer from now on.
-We assume all tiles are of the same width and height. If you are not sure, you should check it again.
-We assume that each tile in the tileContainer is displayed at some regular grid coordinates. I.e. it conforms the following code:
for (var pos_y:int = 0; pos_y < GRID_SIZE_Y; pos_y++) {
for (var pos_x:int = 0; pos_x < GRID_SIZE_X; pos_x++) {
var tile:Tile = getNextTile(); // just get a tile from somewhere
tile.source.x = pos_x * TILE_WIDTH; // using your tile structure
tile.source.y = pos_y * TILE_HEIGHT;
tileContainer.addChild(tile.source);
}
}
Now I see your problem that some tiles are created in a way that they have their source movieclip coordinates shifted from (0,0). So they will not align with the grid.
What are you doing seems to be a proper way of aligning them but I don't know exactly what happens in your code so I'll just rewrite it:
function changePos(mc:MovieClip) {
var r:Rectangle = mc.getRect(mc);
mc.x -= r.x; // note you don't need any if's
mc.y -= r.y;
}
And in the above loop just add the changePos() AFTER setting the grid coordinates:
tile.source.x = pos_x * TILE_WIDTH;
tile.source.y = pos_y * TILE_HEIGHT;
changePos(tile.source);
tileContainer.addChild(tile.source);
If you're following all these steps, that's basically all you need and it will work for sure.

Rotating a canvas object around the mouse cursor

I am trying to replicate this effect: http://hakim.se/experiments/html5/trail/03/
I have this as a Particle constructor:
function Particle(x, y) {
this.x = x;
this.y = y;
this.radius = 4;
this.color = '#f0f';
this.speed = 15;
this.angle = 0;
}
And I'm using this loop to animate all particle instances:
for (var i = 0, len = particles.length; i < len; i++) {
var dx = mouse.x - particles[i].x,
dy = mouse.y - particles[i].y,
angle = Math.atan2(dy, dx);
particles[i].vx = Math.cos(angle) * particles[i].speed;
particles[i].vy = Math.sin(angle) * particles[i].speed;
particles[i].x += particles[i].vx;
particles[i].y += particles[i].vy;
particles[i].draw(ctx);
}
The particles follow the mouse, but reach the cursor and start flickering around it, which is not a desired behaviour. I'd like to circle around the cursor, as in the example.. The interesting part is that if I set the particle.speed to something like 30 and add 1000 to the angle, the particles rotate around the cursor, but really fast and ruin the effect...
You can see a live example here: http://codepen.io/gbnikolov/pen/EwafI
All suggestions are more then welcome, thanks in advance!
P.S. I know that the code for the pointed example is easily findable, but I'm relatively new to javascript and I'm not that good at reading other people code and can't quite understand the logic behind it..
Currently the target of your particles is the mouse cursor. But that's not the target you want. You want a target that's moving around your cursor. And you want for every particle a different target, so they don't hover all at the same place.
There are also some other things that the original does and you don't:
in the original, the particle speed depends on the distance to the target
it seems they can't change the direction instantly, but change the direction of their movement relatively slowly.

How to make a movieclip appear and reappear in the same location?

Well, I'm working on a shooting game in which I have to click enemies to make two counters count the number of hits I get. In this case the enemies are ghosts and I tried making some kind of animation when they are shot so the animation replaces them after I click on them.
However I can't seem to make them reappear again in the same location, it's a very simple drawing made with the shape and drawing tools of Flash CS5.
The code I use in this case for the shooting part is this one:
function disparar (event:MouseEvent):void{
contar +=1;
disparos.text = contar.toString();
var destino1:Boolean = this.mira.hitTestObject(this.FRojo)
if (destino1 == true){
cuenta +=1;
aciertos.text = cuenta.toString();
this.FRojo.visible = false;
colorante.color = 0xFF0000;
this.bang.transform.colorTransform = colorante;
this.bang.x = this.FRojo.x;
this.bang.y = this.FRojo.y;
this.bang.scaleX = this.FRojo.scaleX;
this.bang.scaleY = this.FRojo.scaleY;
this.bang.play();
this.FRojo.visible = true;
}
In fact you can see the whole file in here, it's very simple, but I can't seem to make the movieclip either disappear and reappear or make the animation that follows reappear each time I hit one of the ghosts. Could anyone help me with this? I'd really appreciate the help.
You're hiding the movie clip by setting this.FRojo.visible = false; and then setting it back to true pretty much right after so it never hides.
Try replacing this.FRojo.visible = true;
with
setTimeout(function(){FRojo.visible = true;}, 1000);
That will make it reappear after 1 second (1000 milliseconds).
So remove this and make sure each one is FRojo, FAzul and FMorado.
If you use a tweening library like greensock you can do some cool fades rather than it just reappearing.
EDIT
You have another error inside your BANG movie clip. On frame 10 replace
this.bang.x = 50;
this.bang.y = 10;
this.bang.scaleX = 1;
this.bang.scaleY = 1;
with
this.x = 50;
this.y = 10;
this.scaleX = 1;
this.scaleY = 1;

How to make smooth moving using as3?

I have loaded some images through XML and attached into dynamically created MovieClips named mc0,mc1,mc2...etc.
_loader.removeEventListener(ProgressEvent.PROGRESS, onLoadingAction);
count++;
var img:Bitmap = Bitmap(e.target.content);
img.cacheAsBitmap = true;
img.smoothing = true;
img.alpha = 0;
TweenLite.to(MovieClip(my_mc.getChildByName("mc"+count)).addChild(img),1, {alpha:1,ease:Quint.easeIn});
and within ENTER_FRAME handler
for (i=0; i < mc.numChildren; i++)
{
my_mc.getChildAt(i).x -= Math.round((mouseX-stage.stageWidth/2)*.006);
}
Everthing works fine. But it is shaking so that it was not looking good.
How do I achieve smooth movement?
One solution I've used is to round the (x,y) position to the closest integer. No matter that you've added smoothing to your bitmap and cached it, rounding could make it feel less choppy and way smoother.
Another thing you need to be careful is the dimensions of the images. Images that have an odd dimension won't be smoothed the same way as images with even dimensions. Check how to workaround this in my blog post Flash Smoothing Issue.
Since Flash has a variable frame rate (in the sense that it will drop frames), one shouldn't depend on the entering of a frame as a unit of action. Rather, it would be wiser to calculate the elapsed time explicitly.
For instance, in the enter frame handler:
var currentTime:Number = (new Date()).time;
for (i=0; i < mc.numChildren; i++)
{
my_mc.getChildAt(i).x -= speed * (currentTime - lastTime); // speed is in px/ms
}
lastTime = currentTime;
where you have the variable lastTime declared somewhere in a persistent scope:
var lastTime:Number = (new Date()).time;
I don't know if this addresses what you are calling "shaking", but it's at least something to consider.