So I have been searching for a way to have a background orbit around a centerpoint. I came across the greensock blitmask that does an amazing job of wrapping the bitmap data to do infinte scrolling effects. However, I can't figure out a way to use this blitmask to rotate the bitmap data and still have the wrapping effect. Below is a link to my SWF.
The image that moves is the one that I wish to wrap and have the infinite scrolling effect. The problem is dealing with repositioning after the image has moved off the screen since it has been rotated.
EDIT: I totally forgot about this issue and decided put it on the backburner for my game since it was taking too long to figure. I recently returned to this concept because I had an idea to make it work. Below is a link to the .SWF that shows what I was trying to accomplish. Though this example works, I dont feel its the best solution.
"WASD" control movement
Orbiting Background
I used some trigonometry to calculate the distance a star is from the player. If that star is beyond that distance, reposition it using it's angle * -1. The code for this is under the link.
var travelVal:Number = 0;
var turnVal:Number = 0;
var currentChild:DisplayObject;
var currentStar:Star;
var childIndex:int = 0;
var angle:Number = 0;
var distance:Number = 0;
if (controller.isKeyDown(Keyboard.A))
{
turnVal += TURN_SPEED;
}
if (controller.isKeyDown(Keyboard.D))
{
turnVal -= TURN_SPEED;
}
if (controller.isKeyDown(Keyboard.W))
{
travelVal += PLAYER_SPEED;
}
if (controller.isKeyDown(Keyboard.S))
{
travelVal -= PLAYER_SPEED
}
for (childIndex = 0; childIndex < numChildren; childIndex++)
{
currentChild = getChildAt(childIndex);
//if (currentChild != player && currentChild != debugOutput && currentChild != blackBkgd)
if(currentChild is Star)
{
currentStar = currentChild as Star;
//move this child based on the travel value
currentChild.y += travelVal * currentStar.speed;
//calculate the orbiting
distance = Math2.distanceBetweenObjects(player, currentChild);
angle = Math.atan2(currentChild.y - player.y, currentChild.x - player.x);
if (distance > STAGE_WIDTH ) angle = angle * -1;
//get orginal angle in radians
//angle = Math.atan2(currentChild.y - player.y , currentChild.x - player.x);
angle = Math2.radiansToDegress(angle);
angle += turnVal;
//currentStar.rotation = angle;
angle = Math2.degreesToRadians(angle);
currentChild.x = player.x + (distance * Math.cos(angle));
currentChild.y = player.y + (distance * Math.sin(angle));
}
}
In order to rotate around a certain centerpoint, you first translate by (-centerpoint.x,-centerpoint.y), then rotate around (0,0) and then translate back by (centerpoint.x,centerpoint.y).
Related
i'm trying to create a minigame with circles rotating around circles
however, i have a problem when i shoot the circle and it hits the second circle it doesnt continue the angle but "jumping" to the other side i'm sure it something with the angle var that should reset or something. can you help me im getting nervous around here... :(
check the example
This is my code for the enter frame function that deals with the circles
public function UpdateCircles(e:Event):void
{
for (var i:int = 0; i < EnemySpriteVector.length; i++)
{
EnemySpriteVector[i].rotation += EnemySpriteVector[i].enemyspeed;
}
var rad:Number = angle * (Math.PI / 180); // Converting Degrees To Radians
if (IsplayerShoot)
{
playerSprite.x += Math.cos(rad) * PlayerCircleShootSpeed;
playerSprite.y += Math.sin(rad) * PlayerCircleShootSpeed;
for (var j:int = 0; j < EnemySpriteVector.length; j++)
{
if (EnemySpriteVector[j].hitTestPoint(playerSprite.x,playerSprite.y) && (EnemySpriteVector[j].IsCircleHit == false))
{
trace("hit");
EnemySpriteVector[j].IsCircleHit = true;
removeChild(EnemySpriteVector[0]);
EnemySpriteVector.splice(0, 1);
var EnemySprite:Sprite = new EnemySpriteClass();
EnemySpriteVector.push(EnemySprite);
addChild(EnemySprite);
EnemySprite.x = Math.random() * stage.stageWidth;
EnemySprite.y = Math.random() * stage.stageHeight;
IsplayerShoot = false;
}
}
}
else
{
playerSprite.x = EnemySpriteVector[0].x + EnemySpriteVector[0].radius * Math.cos(rad); // Position The Orbiter Along x-axis
playerSprite.y = EnemySpriteVector[0].y + EnemySpriteVector[0].radius * Math.sin(rad); // Position The Orbiter Along y-axis
angle += EnemySpriteVector[0].enemyspeed; // Object will orbit clockwise
playerSprite.rotation = (Math.atan2(playerSprite.y - EnemySpriteVector[0].y, playerSprite.x - EnemySpriteVector[0].x) * 180 / Math.PI); //only rotates the player circle itself
}
}
Looks like when the pink circle hits the green one it simply continues its rotation from where it left of. A quick solution would be to add 180 degrees to the angle. Keep in mind this will only work for static objects. If you want a more dynamic environment I would recommend using vectors (linear algebra). Vector math is really easy to understand and it hides a lot of complex trigonometry. You can start here :)
private function scrollStage():void
{
if (lastPosX != lastPosX)
{
canScrollStage = false;
}
else
if (lastPosX == lastPosX)
{
canScrollStage = true;
}
if (canScrollStage)
{
if (rightKey)
{
//move background left
//something.x +=(stage.stageWidth * 0.5) - character.x * 2;
}
else
if (leftKey)
{
//move backgrounf Roight
}
for (var b:int = 0; b < childrenOnStage; b++)
{
if (getChildAt(b).name == "enemy")
{
getChildAt(b).x +=(stage.stageWidth * 0.5) - character.x
}
}
ground.x += (stage.stageWidth * 0.5) - character.x
}
else
{
//move the background
}
// do this last, everything moves around object
character.x = stage.stageWidth * 0.5;
lastPosX = character.x;
}
Someone told me to move the objects around the player and then update the players x position.
This is what I've done by looking at a tutorial ("Cartoon Smart");
In my player class I have a reset function.
private var xSpeed:int;
private var resetPos:Point;
public function player()
{
addEventListener(Event.ADDED_TO_STAGE, onAdd)
}
private function onAdd(e: Event): void
{
xSpeed = 3;
resetPos = new Point(x, y);
}
public function reset():void
{
x = resetPos.x;
y = resetPos.y;
//trace(resetPos);
//trace(resetPos + "player");
}
When the player falls to death this function is called
private function playerFalls():void
{
if (character.y > stage.stageHeight)
{
//take life away and go back to check point or back to reset
character.x = stage.stageWidth * 0.5;
character.y = 20;
//goblin1.reset();
//goblin2.reset();
//goblin3.reset();
//stage.x = stage.stageWidth * 0.5;
//canScrollStage = false;
}
}
if I use
character.x = stage.stageWidth * 0.5;
Then my character ends up in the middle, but it will end up in the middle since the scroll function dictates the player to be in the center always.
character.x = (stage.stageWidth * 0.5) - 400;// moves him back
but if character falls off left of the screen then he is moved back.
Any one have a solution for this please?
My question is, I want to reset the player's x position to 300 and y position to 10;
But I can't do this because the stage shifts and the co ordinate system changes.
In order for the player to go back to the original coordinate of the stage, the stage must scroll.
That's my idea, or perhaps the ground and enemies must do the opposite?
I sincerely apologize for the late answer. Okay, so your saying that when the character falls you don't want the screen to scroll all the way back to the character's start position. What you need to do is find the start positions of your character and ground (as well as any other layers such as backgrounds etc). Then wherever your fall function comes into place simply set the character and background positions to their starting coordinates.
function fall(){
char.x=charStartX;
char.y=charStartY;
ground.x=groundStartX;
ground.y=groundStartY;
//etc
}
For example, let's say you have a check point. If player hits check point charResetPoint = 100. If player falls then set it's x pos to charResetPoint
But I can't move the players x position because it will always be stage.stageWidth/2 due to my code.
So in theory it will be difficult to make a resetPoint, because when I add goblin 1.x , it's x pos is 900, if I scroll right goblon1 x pos will change. Everythings x pos changes and so does the stages.
I can't get a grasp on the concept, sortlry
I'd like to move an AS 3 movieclip randomly. This is what I currently have, bound to the ENTER_FRAME event. This obviously moves the movieclip from the left upper to the right lower edge, so I need some kind of switch to add/substract the target positions.
function movePsycho(e:Event):void {
e.target.y += Math.random()*2;
e.target.x += Math.random()*2;
if (e.target.y >= stage.height || e.target.x >= stage.width)
e.target.removeEventListener(Event.ENTER_FRAME, movePsycho);
}
You don't need add/substract thing. You just have to make sure not only you get positive values out of your random, but negatives too, so it runs to all sides.
Try changing your random generating lines to this:
e.target.y += Math.random()*10 - 5;
e.target.x += Math.random()*10 - 5;
This will work if you want to make it move in a 5px radius.
I just realized you may want to generate a new random point on the screen, then move to that point and when your object reaches the destination generate another random point to go to. So if that's the case, try this:
mc.addEventListener(Event.ENTER_FRAME, onFrame);
var dirX:int = mc.x;
var dirY:int = mc.y;
function generateRandomPoint():void
{
dirX = Math.random() * stage.stageWidth;
dirY = Math.random() * stage.stageHeight;
}
function onFrame(e:Event):void
{
mc.x += (dirX - mc.x) * 0.1;
mc.y += (dirY - mc.y) * 0.1;
if(Math.abs(dirX - mc.x) < 1 || Math.abs(dirY - mc.y) < 1)
generateRandomPoint();
}
i don't know actionscript but you may find help with this
http://www.actionscript.org/forums/showthread.php3?t=270725
I'm making a simulation of a flying arrow, but it doesn't look very natural.
Here's a screenshot:
The anchor of the arrow movieclip is at the front of the arrow like you can see, but if I replace it to the middle, it still doesn't look perfect, does anyone have any experience with something like this?
Here's my code too:
//...
//'math' isn't the default 'Math' class, it calculates some physics stuff.
private function updateArrow()
{
var y0:Number = 50;
var v:Number = 100;
var angle:Number = math.getRadians(45);
if(!arrowstartposition)
{
arrowstartposition = activearrow.x;
arrowdistance = math.calcDistance(y0,v,angle);
}
var currentdistance:Number = Math.abs(activearrow.x - arrowstart);
if(currentdistance <= arrowdistance)
{
var currentvelocity:Number = math.calcVelocity(currentdistance, v, angle);
var addvalue:int = 1; //Math.round(currentvelocity / 4);
activearrow.x += addvalue;
currentdistance += addvalue;
var arrowheight:Number = math.calcHeight(currentdistance,y0,v,angle);
var vx:Number = v * Math.cos(angle);
var vy:Number = - (v * Math.sin(angle) - 9.81 * (currentdistance / arrowdistance) * math.calcTimeOfFlight(y0, v, angle));
var currentangle:Number = Math.atan2(vy,vx);
activearrow.y = y0 - arrowheight;
activearrow.rotation = math.getDegrees(currentangle);
}
else
{
arrowstart = undefined;
arrowdistance = undefined;
activearrow = null;
}
}
I think your center of gravity is off. The arrowhead isn't going to be where the center of the gravity is for the arrow. Otherwise it wouldn't fly very well. The center of gravity of the arrow will be tangential to the parabola of flight. So it will rotate around that center of gravity. Try moving it more towards the center of the arrow and it will start to look more natural. If you still have trouble. Try throwing just a stone and get that looking natural. Then add back in the arrow. If it looks good as a stone, then looks bad as an arrow you know the motion is correct, but arrow is off.
I have this code that I found online that does an infinite rotating gallery, now my problem is that on enter frame it jumps and too fast. I want it to be as fast at after you hover out of the logo.
Here is the code:
//Import TweenMax
import com.greensock.TweenMax;
//Save the horizontal center
var centerX:Number = stage.stageWidth / 2;
//Save the width of the whole gallery
var galleryWidth:Number = infiniteGallery.width;
//Speed of the movement (calculated by the mouse position in the moveGallery() function)
var speed:Number = 0;
//Add an ENTER_FRAME listener for the animation
addEventListener(Event.ENTER_FRAME, moveGallery);
function moveGallery(e:Event):void {
//Calculate the new speed
speed = -(0.02 * (mouseX - centerX));
//Update the x coordinate
infiniteGallery.x+=speed;
//Check if we are too far on the right (no more stuff on the left edge)
if (infiniteGallery.x>0) {
//Update the gallery's coordinates
infiniteGallery.x= (-galleryWidth/2);
}
//Check if we are too far on the left (no more stuff on the right edge)
if (infiniteGallery.x<(-galleryWidth/2)) {
//Update the gallery's coordinates
infiniteGallery.x=0;
}
}
and here is the demo ยป
The speed of the scroller is based on three things:
1- The frame rate. The ENTER_FRAME event handler gets called on every frame, thus is directly influenced by the frame rate.
2- The speed damping number. In your case this is equal to 0.02. If you want to slow down the scrolling, make this a smaller number. Try 0.01 for half the speed.
3- The distance of the mouse pointer to the center x coordinate of your stage. The difference between the mouse pointer and the center of your stage is multiplied by your speed damping number. If you want the movement to stop when you are at or around the center change you code as follows:
var buffer:Number = 50;
function moveGallery(e:Event):void {
var diff = mouseX - centerX;
if (Math.abs(diff) > buffer)
speed = -(0.02 * (diff + (diff > 0 ? -buffer : buffer)));
else
speed = 0;
AS REQUESTED:
var centerX:Number = stage.stageWidth / 2;
var galleryWidth:Number = infiniteGallery.width;
var speed:Number = 0;
addEventListener(Event.ENTER_FRAME, moveGallery);
var buffer:Number = 100;
function moveGallery(e:Event):void {
var diff = mouseX - centerX;
if (Math.abs(diff) > buffer)
speed = -(0.02 * (diff + (diff > 0 ? -buffer : buffer)));
else
speed = 0;
infiniteGallery.x += speed;
if (infiniteGallery.x>0) {
infiniteGallery.x = -galleryWidth / 2;
}
if (infiniteGallery.x < -galleryWidth / 2) {
infiniteGallery.x = 0;
}
}