Converting complicated trigonometry from AS2 to AS3 - actionscript-3

I'm trying to make a game, following this tutorial.
The issue comes from the fact that I am using ActionScript 3.0 whereas the tutorial was written using ActionScript 2.0.
Regarding the sight of the enemy, I have turned this code:
onClipEvent (enterFrame) {
dist_x = _root.hero._x-_x;
dist_y = _root.hero._y-_y;
dist = Math.sqrt(dist_x*dist_x+dist_y*dist_y);
angle = Math.atan(dist_y/dist_x)/(Math.PI/180);
if (dist_x<0) {
angle += 180;
}
if (dist_x>=0 && dist_y<0) {
angle += 360;
}
wall_collision = 0;
for (x=1; x<=dist; x++) {
point_x = _x+x*Math.cos(angle*Math.PI/180);
point_y = _y+x*Math.sin(angle*Math.PI/180);
if (_root.wall.hitTest(point_x, point_y, true)) {
wall_collision = 100;
break;
}
}
_root.line._x = _x;
_root.line._y = _y;
_root.line._rotation = angle;
_root.line._alpha = 100-wall_collision;
}
Into that:
// calculate rotation based on target
_dx = this.x - _root.hero.x;
_dy = this.y - _root.hero.y;
// which way to rotate
_rotateTo = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (_rotateTo > barrel.rotation + 90) _rotateTo -= 360;
if (_rotateTo < barrel.rotation - 90) _rotateTo += 360;
// ease rotation
_trueRotation = (_rotateTo - barrel.rotation) / _rotateSpeedMax;
// update rotation
barrel.rotation += _trueRotation;
wall_collision = 0;
OuterLoop: for (var xi=1; xi<=_dx; xi++)
{
var point_x:Number = this.x + xi*Math.cos(_rotateTo);
var point_y:Number = this.y + xi*Math.sin(_rotateTo);
if(_root.wall.hitTestPoint(point_x, point_y, true))
{
trace("HIT");
wall_collision = 100;
break OuterLoop;
}
}
_root.sight.x = this.x;
_root.sight.y = this.y;
_root.sight.rotation += _trueRotation;
_root.sight.alpha = 100 - wall_collision;
But the it does not work.
The rotation do work fine, but the whole "alpha = 0 if player is behind a wall" does not work.
Please help me resolving the issue.

Try the following:
// calculate rotation based on target
_dx = _root.hero.x-this.x;
_dy = _root.hero.y-this.y;
// The full distance is missing from your AS3 code
_dist = Math.sqrt(_dx*_dx+_dy*_dy);
// Return the old good approach for finding angle
angle = Math.atan(_dy/_dx)/(Math.PI/180);
if (_dx<0) {
_angle += 180;
}
if (_dx>=0 && _dy<0) {
_angle += 360;
}
wall_collision = 0;
OuterLoop: for (var xi=1; xi<=_dist; xi++)
{
var point_x:Number = this.x + xi*Math.cos(_angle*Math.PI/180);
var point_y:Number = this.y + xi*Math.sin(_angle*Math.PI/180);
if(_root.wall.hitTestPoint(point_x, point_y, true))
{
trace("HIT");
wall_collision = 100;
break OuterLoop;
}
}
_root.sight.x = this.x;
_root.sight.y = this.y;
_root.sight.rotation = _angle;
// Alpha changed from [0, 100] scale to [0, 1] scale.
_root.sight.alpha = (100 - wall_collision) * 0.01;
Information on alpha in ActionScript 3.0.

As per AS3 reference, alpha is from 0 to 1, not 0 to 100. That would suggest
`_root.sight.alpha = (100 - wall_collision)/100.0´
might work.

Can You try the following code. I have no prev exp with flash, but seems like You missed something.
The iterator xi should take values in range of distance, not only by one axis dx.
// calculate rotation based on target
_dx = this.x - _root.hero.x;
_dy = this.y - _root.hero.y;
// the iteration is by distance in original article mentioned so
// keep dist
//=================================
_dist = Math.sqrt(_dx*_dx+_dy*_dy);
// which way to rotate
_rotateTo = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (_rotateTo > barrel.rotation + 90) _rotateTo -= 360;
if (_rotateTo < barrel.rotation - 90) _rotateTo += 360;
// ease rotation
_trueRotation = (_rotateTo - barrel.rotation) / _rotateSpeedMax;
// update rotation
barrel.rotation += _trueRotation;
wall_collision = 0;
// xi iterations are to a distance
//== =======
OuterLoop: for (var xi=1; xi<=_dist; xi++)
{
var point_x:Number = this.x + xi*Math.cos(_rotateTo);
var point_y:Number = this.y + xi*Math.sin(_rotateTo);
if(_root.wall.hitTestPoint(point_x, point_y, true))
{
trace("HIT");
wall_collision = 100;
break OuterLoop;
}
}
_root.sight.x = this.x;
_root.sight.y = this.y;
_root.sight.rotation += _trueRotation;
// EDITED AFTER OTHERS SOLVED
// was
//_root.sight.alpha = 100 - wall_collision;
// should be:
// Alpha changed from [0, 100] scale to [0, 1] scale.
_root.sight.alpha = (100 - wall_collision) * 0.01;
// END OF SOLUTION
There is only slight modification to Your original code, marked by preceding //=====
EDIT:
And the winner is transparency range. Still, I do recommend to iterate to a distance, not to _dx.

Related

Actionscript 3.0 Mouse trail snake game logic

I am developing a game in actionscript 3.0 (adobe flash) similar to this https://www.tvokids.com/preschool/games/caterpillar-count. I have the code for dragging the head of the snake in the direction of the mouse. However, I do not know how do I add the body of the snake and make it follow the path of the head. Following is my code to drag movieclip in the direction of the mouse :
var _isActive = true;
var _moveSpeedMax:Number = 1000;
var _rotateSpeedMax:Number = 15;
var _decay:Number = .98;
var _destinationX:int = 150;
var _destinationY:int = 150;
var _dx:Number = 0;
var _dy:Number = 0;
var _vx:Number = 0;
var _vy:Number = 0;
var _trueRotation:Number = 0;
var _player;
var i;
createPlayer();
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
function createPlayer():void{
_player = new head();
_player.x = stage.stageWidth / 2;
_player.y = stage.stageHeight / 2;
stage.addChild(_player);
}
function onDown(e:MouseEvent):void{
_isActive = true;
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onMove(e:MouseEvent):void{
updatePosition(_player);
updateRotation(_player);
}
function onUp(e:MouseEvent):void{
_isActive = false;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMove);
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
}
function updatePosition(mc):void
{
// check if mouse is down
if (_isActive)
{
// update destination
_destinationX = stage.mouseX;
_destinationY = stage.mouseY;
// update velocity
_vx += (_destinationX - mc.x) / _moveSpeedMax;
_vy += (_destinationY - mc.y) / _moveSpeedMax;
}
else
{
// when mouse is not down, update velocity half of normal speed
_vx += (_destinationX - mc.x) / _moveSpeedMax * .25;
_vy += (_destinationY - mc.y) / _moveSpeedMax * .25;
}
// apply decay (drag)
_vx *= _decay;
_vy *= _decay;
// if close to target, slow down turn speed
if (getDistance(_dx, _dy) < 50)
{
_trueRotation *= .5;
}
// update position
mc.x += _vx;
mc.y += _vy;
}
function updateRotation(mc):void
{
// calculate rotation
_dx = mc.x - _destinationX;
_dy = mc.y - _destinationY;
// which way to rotate
var rotateTo:Number = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (rotateTo > mc.rotation + 180) rotateTo -= 360;
if (rotateTo < mc.rotation - 180) rotateTo += 360;
// ease rotation
_trueRotation = (rotateTo - mc.rotation) / _rotateSpeedMax;
// update rotation
mc.rotation += _trueRotation;
}
function getDistance(delta_x:Number, delta_y:Number):Number
{
return Math.sqrt((delta_x*delta_x)+(delta_y*delta_y));
}
function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
r += (2 * Math.PI);
}
return r;
}
function getDegrees(radians:Number):Number
{
return Math.floor(radians/(Math.PI/180));
}
The script below will not miraculously work on its own, however it has all the logic you need, well-explained. It makes a chain of any length follow its head by certain rules. I used the same principle here many years ago: http://delimiter.ru/games/25-lines/alone.html
// This one will represent the Mouse position.
var Rat:Sprite = new Sprite;
// The ordered list of chain elements.
// It all starts with the Mouse.
var Snake:Array = [Rat];
// Call this one each time you want to
// extend the snake with the piece of tail.
function addTail(aPiece:DisplayObject):void
{
// Get the last snake element.
var lastPiece:DisplayObject = Snake[Snake.length - 1];
// Sync the tail coordinates.
aPiece.x = lastPiece.x;
aPiece.y = lastPiece.y;
// Add the new piece to the snake.
Snake.push(aPiece);
}
// Add the pre-defined head as the first element.
addTail(SnakeHead);
// Now start following the Mouse.
addEventListener(Event.ENTER_FRAME, onFrame);
// Fires every frame and adjusts the whole snake, if needed.
function onFrame(e:Event):void
{
// Sync the attractor point with the Mouse.
Rat.x = mouseX;
Rat.y = mouseY;
// Now lets make each piece follow the previous piece,
// one by one, starting from the head, down to the tail.
for (var i:int = 1; i < Snake.length; i++)
{
followOne(Snake[i - 1], Snake[i]);
}
}
function followOne(A:DisplayObject, B:DisplayObject):void
{
// Think of these values as of vector
// pointing from B position to A position.
var dx:Number = A.x - B.x;
var dy:Number = A.y - B.y;
// Figure out the distance between the given pieces.
var aDist:Number = Math.sqrt(dx * dx + dy * dy);
// Do nothing if pieces are closer than 20 px apart.
// You can change this value to make snake shorter or longer.
if (aDist < 20)
{
return;
}
// This literally means "eat one tenth of the distance
// between me and the previous piece". If you want pieces
// to follow each other with more vigor, reduce this value,
// if you want the whole snake to slither smoothly, increase it.
B.x += dx / 10;
B.y += dy / 10;
// Rotate the B piece so it would look right into A's direction.
// Well, unless your pieces are round and look all the same.
B.rotation = Math.atan2(dy, dx) * 180 / Math.PI;
}

Setting a correct angular velocity to a canvas object

I am building a space shooter game and would like the ship to fire rockets at the direction of the cursor. Therefore, I grab the radian value of the angle it should fire at, multiply it by the ship's speed and set it's x and y velocities respectively.
I have this as a Bullet class:
function Bullet(x, y) {
this.x = x;
this.y = y;
this.rotation = 0;
this.width = 6;
this.height = 3;
this.color = utils.getRandomColor();
this.speed = 80;
}
And here is the function which updates the movement of all instances of the bullet class:
function drawBullet(bullet) {
var dx = mouse.x - bullet.x,
dy = mouse.y - bullet.y,
angle = Math.atan2(dy, dx);
bullet.vx = Math.cos(angle) * bullet.speed;
bullet.vy = Math.sin(angle) * bullet.speed;
bullet.x += bullet.vx;
bullet.y += bullet.vy;
bullet.draw(ctx);
}
It starts okay, going in the right direction and velocity and stuff. But as soon as it reaches the mouse, it stops dead there and starts flickering. NOW, I realise that this is because of the way I am getting the angle, using the mouse position as a value - the problem is that I can't figure out a way to use just the angle for the velocity, not the distance to the mouse position. So it doesn't slow down.
All suggestions are welcome, thanks in advance!
If you don't need homing missile type behavior just pass the mouse coordinates when you create the bullet.
Example:
new Bullet(shooterX, shooterY, mouseX, mouseY)
I included an over engineered stack snippet but the relevant part is below.
var Bullet = function(x,y,tx,ty){
this.speed = 15;
this.x = x;
this.y = y;
var radians = Math.atan2(ty-y, tx-x);
// we now have our velX and velY we can just refer to
this.velX = Math.cos(radians) * this.speed;
this.velY = Math.sin(radians) * this.speed;
}
Bullet.prototype.update = function(){
// just update by our previous calculated velX and velY.
this.x += this.velX;
this.y += this.velY;
};
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 250,
height = 250,
output = document.getElementById("radians"),
output2 = document.getElementById("degrees"),
cX = 0,
cY = 0,
mX = 0,
mY = 0,
bullets = [];
canvas.width = width;
canvas.height = height;
canvas.addEventListener("mousemove", function (e) {
mX = e.pageX;
mY = e.pageY;
});
var Ball = function (x, y, radius, color) {
this.x = x || 0;
this.y = y || 0;
this.radius = radius || 10;
// makes our x and y the center of the circle.
this.x = (this.x-this.radius/2);
this.y = (this.y-this.radius/2);
// how far out do we want the point
this.pointLength = 50;
this.px = 0;
this.py = 0;
this.color = color || "rgb(255,0,0)";
}
Ball.prototype.shoot = function(tx, ty){
bullets.push(new Bullet(this.x, this.y, tx, ty));
}
Ball.prototype.update = function (x, y) {
// get the target x and y
this.targetX = x;
this.targetY = y;
var x = this.x - this.targetX,
y = this.y - this.targetY,
radians = Math.atan2(y,x);
this.px = this.x - this.pointLength * Math.cos(radians);
this.py = this.y - this.pointLength * Math.sin(radians);
// -y will make 0 the top, y will 0 us at the bottom.
output.textContent = radians;
output2.textContent = radians/Math.PI * 180
};
Ball.prototype.render = function () {
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
ctx.strokeStyle = "rgb(0,0,255)";
ctx.beginPath();
ctx.moveTo(this.x, this.y);
ctx.lineTo(this.px, this.py);
ctx.closePath();
ctx.stroke();
};
var Bullet = function(x,y,tx,ty){
this.speed = 15;
this.x = x;
this.y = y;
var radians = Math.atan2(ty-y, tx-x);
this.velX = Math.cos(radians) * this.speed;
this.velY = Math.sin(radians) * this.speed;
}
Bullet.prototype.update = function(){
this.x += this.velX;
this.y += this.velY;
};
Bullet.prototype.render = function(){
ctx.fillStyle = '#000';
ctx.beginPath();
ctx.arc(this.x, this.y, 2, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
};
var ball1 = new Ball(width/2, height/2, 10);
canvas.addEventListener("click", function (e) {
ball1.shoot(e.pageX, e.pageY);
});
function render() {
ctx.clearRect(0, 0, width, height);
ball1.update(mX, mY);
ball1.render();
bullets.forEach(function(b){
b.update();
b.render();
});
requestAnimationFrame(render);
}
render();
ol{list-style:none;}
<canvas id="canvas"></canvas>
<div>
<ol>
<li>
<span>Radians : </span><span id="radians"></span>
</li>
<li>
<span>Degrees : </span><span id="degrees"></span>
</li>
</ol>
</div>
Add a new property on bullet that stores the angle of motion, initialize it to -1. Then, on the very first drawBullet call, check if it has been initialized first. If not, set the angle...
function Bullet(x, y) {
this.x = x;
this.y = y;
this.rotation = 0;
this.width = 6;
this.height = 3;
this.color = utils.getRandomColor();
this.speed = 80;
this.angle = -1; // New, angle property initialized to -1
}
function drawBullet(bullet) {
if (bullet.angle === -1) { // Only pull the mouse cursor and get an angle
var dx = mouse.x - bullet.x, // If it hasn't already done so.
dy = mouse.y - bullet.y,
angle = Math.atan2(dy, dx);
bullet.angle = angle;
}
bullet.vx = Math.cos(bullet.angle) * bullet.speed; // Re-use the angle value.
bullet.vy = Math.sin(bullet.angle) * bullet.speed;
bullet.x += bullet.vx;
bullet.y += bullet.vy;
bullet.draw(ctx);
}

AS3 Smooth Jumping

I would like to know how to make a smooth jump in my game. Its a 2D game and the code is really simple but I would want to know how to make it better for it to slow down when it gets to the max height and then smooth drop.
This is all I have for jumping:
Player.y -= 50;
Your best bet would be to use a physics engine (Box2d etc). If you don't want the overhead of one though (if the only thing you'd use it for is jumping and not collisions) then you just need to add some friction to your logic.
var friction :Number = .85; //how fast to slow down / speed up - the lower the number the quicker (must be less than 1, and more than 0 to work properly)
var velocity :Number = 50; //how much to move every increment, reset every jump to default value
var direction :int = -1; //reset this to -1 every time the jump starts
function jumpLoop(){ //lets assume this is running every frame while jumping
player.y += velocity * direction; //take the current velocity, and apply it in the current direction
if(direction < 0){
velocity *= friction; //reduce velocity as player ascends
}else{
velocity *= 1 + (1 - friction); //increase velocity now that player is falling
}
if(velocity < 1) direction = 1; //if player is moving less than 1 pixel now, change direction
if(player.y > stage.stageHeight - player.height){ //stage.stageheight being wherever your floor is
player.y = stage.stageHeight - player.height; //put player on the floor exactly
//jump is over, stop the jumpLoop
}
}
Copy/paste the following code... jump() can be replaced by jump2() (without bouncing effect). The jumping will be produced by the space bar:
const FA:Number = .99; // air resistance
const CR_BM:Number = .8; // bouncing coefficient
const µ:Number = .03; // floor friction
const LB:int = stage.stageHeight; // floor (bottom limit)
const G:int = 2.5; // gravity
const R:int = 50;
var ball:MovieClip = new MovieClip();
this.addChild(ball);
var ba:* = ball.graphics;
ba.beginFill(0xFFCC00);
ba.lineStyle(0, 0x666666);
ba.drawCircle(0, 0, R);
ba.endFill();
ball.vx = 2;
ball.vy = -30;
ball.r = R;
ball.x = 100;
ball.y = LB - R;
stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
function myKeyDown(e:KeyboardEvent):void {
if (e.keyCode == Keyboard.SPACE) {
ball.vy = -30;
addEventListener(Event.ENTER_FRAME, jump);
}
}
function jump(e:Event):void {
ball.vy = ball.vy + G;
ball.vx *= FA;
ball.vy *= FA;
ball.x += ball.vx;
ball.y += ball.vy;
if (ball.y > LB - ball.r) {
ball.y = LB - ball.r;
ball.vy = -1 * ball.vy * CR_BM;
ball.vx += ball.vx * - µ;
}
}
/*
function jump2(e:Event):void {
ball.vy = ball.vy + G;
ball.vx *= FA;
ball.vy *= FA;
ball.x += ball.vx;
ball.y += ball.vy;
if (ball.y > LB - ball.r) {
ball.y = LB - ball.r;
}
}
*/

As3: Math, I'm too stupid for this. (trigonometry)

Okay, so I made some ai where a guard is following my character.
I am using this code:
private function getDegrees(radians:Number):Number
{
//return Math.floor(radians/(Math.PI/180));
return radians / 0.01745 | 0;
}
private function getRadians(delta_x:Number, delta_y:Number):Number
{
var r:Number = Math.atan2(delta_y, delta_x);
if (delta_y < 0)
{
//r += (2 * Math.PI);
r += 6.283;
}
return r;
}
And then in the loop
if(isShooting)
{
// calculate rotation based on mouse X & Y
_dx = this.x - _root.assassin.x;
_dy = this.y - _root.assassin.y;
// which way to rotate
_rotateTo = getDegrees(getRadians(_dx, _dy));
// keep rotation positive, between 0 and 360 degrees
if (_rotateTo > this.rotation + 180) _rotateTo -= 360;
if (_rotateTo < this.rotation - 180) _rotateTo += 360;
// ease rotation
_trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;
// update rotation
this.rotation += _trueRotation;
gotoAndStop(5);
isWalking = false;
isStanding = false;
}
The thing is, the guard rotates weirdly, it's as if he isn't looking at the player. It's as if the player is somewhere else. Dunno, it just doesn't work.. I have no idea what is wrong with the code!
You should just compute the relative angle
_rotateTo = getDegrees(getRadians(_dx, _dy));
_trueRotation = (_rotateTo - this.rotation) / _rotateSpeedMax;
then normalize this to be as close to zero as possible
_trueRotation = (_trueRotation+900) %360 - 180;
and then cut this to the maximal rotation per step
_trueRotation = max(_trueRotation,_rotateSpeedMax* _timestep);
_trueRotation = min(_trueRotation,-_rotateSpeedMax*_timestep);
and use this then to update the forward direction
this.rotation += _trueRotation;
Speed usually is change per time, so there should be a multiplication with some time step for semantic consistency. Of course, you may have the time step equal to 1, or rotateSpeedMax is really a rotateMaxAngle (per step), then the multiplication with timestep can be removed.
To keep the rotation positive you should use modulus 360 like below for readability and (code) simplicity until and unless it's a clear performance issue: (I think this is right for AC3, just looked it up online quick)
_rotateTo = _rotateTo % 360;
The other possible issue is with how you define _dx and _dy. I'm guessing that the assassin is facing in the opposite direction as intended. The fix is to useI'm thinking it should either be:
_dx = _root.assassin.x - this.x;
_dy = _root.assassin.y - this.y;

Make a boundary in flash with as3

I have this code that generates circles and makes them float within the boundaries of the stage. Although it stays in the stage it also has some give and let's the circles push through a small amount which I like.
Is it possible to do this but with a custom shape and have the circles confined inside this shape?
Here is the code I have:
//number of balls
var numBalls:uint = 200;
var defaultBallSize:uint = 8;
var colors:Array = [0x79B718, 0x2D91A8, 0xB019BC, 0xF98715, 0xDB1616];
//init
makeDots();
function makeDots():void {
//create desired number of balls
for (var ballNum:uint=0; ballNum<numBalls; ballNum++){
var c1:Number = randomColor();
var c2:Number = randomColor();
//create ball
var thisBall:MovieClip = new MovieClip();
thisBall.graphics.beginFill(c1);
//thisBall.graphics.lineStyle(defaultBallSize, 0);
thisBall.graphics.drawCircle(defaultBallSize, defaultBallSize, defaultBallSize);
thisBall.graphics.endFill();
addChild(thisBall);
//coordinates
thisBall.x = Math.random() * stage.stageWidth;
thisBall.y = Math.random() * stage.stageHeight;
//percieved depth
thisBall.ballNum = ballNum;
thisBall.depth = ballNum/numBalls;
thisBall.scaleY = thisBall.scaleX =
////thisBall.alpha =
ballNum/numBalls;
//velocity
thisBall.vx = 0;
thisBall.vy = 0;
thisBall.vz = 0;
//ball animation
thisBall.addEventListener(Event.ENTER_FRAME, animateBall);
}
}
var dampen:Number = 0.90;
var maxScale:Number = 1.3;
var minScale:Number = .3;
var maxAlpha:Number = 1.3;
var minAlpha:Number = .3;
function animateBall(e:Event):void{
var thisBall:Object = e.target;
//apply randomness to velocity
thisBall.vx += Math.random() * 0.2 - 0.1;
thisBall.vy += Math.random() * 0.2 - 0.1;
thisBall.vz += Math.random() * 0.002 - 0.001;
thisBall.x += thisBall.vx;
thisBall.y += thisBall.vy;
//thisBall.scaleX = thisBall.scaleY += thisBall.vz;
//thisBall.alpha += thisBall.vz;
thisBall.vx *= dampen;
thisBall.vy *= dampen;
thisBall.vz *= dampen;
if(thisBall.x > stage.stageWidth) {
thisBall.x = 0 - thisBall.width;
}
else if(thisBall.x < 0 - thisBall.width) {
thisBall.x = stage.stageWidth;
}
if(thisBall.y > stage.stageHeight) {
thisBall.y = 0 - thisBall.height;
}
else if(thisBall.y < 0 - thisBall.height) {
thisBall.y = stage.stageHeight;
}
if (thisBall.scaleX > maxScale){
thisBall.scaleX = thisBall.scaleY = maxScale;
}
else if (thisBall.scaleX < minScale){
thisBall.scaleX = thisBall.scaleY = minScale;
}
if (thisBall.alpha > maxAlpha){
thisBall.alpha = maxAlpha;
}
else if (thisBall.alpha < minAlpha){
thisBall.alpha = minAlpha;
}
}
function randomColor():uint
{
return colors[int(Math.random()*colors.length)];
}
Code credit:
Originally from here: Circle Cube
Additional help here: Random colour within a list of pre-defined colours
Yes, you can. What is happening is that when each circle moves, it is checked to see if it is within the stage bounds on the x and y axis and is 'corrected' if it goes out. You can modify that part of the code that determines this to check if a circle is within your custom shape or not.
The complexity of this will depend on your custom shape as well as the method to go about detecting if a circle/object is within your custom shape.
The 'easiest custom shape' you could try would be a rectangle or square, since the stage is already a big rectangle. To start this, look through your given code to find the lines of code that limit the x and y position of the stage dimensions and change them to the dimensions of your custom rectangle/square. You may have to add in position offsets if your custom shape rectangle/square does not originate from 0, 0 like the stage. I suggest factoring this part out (which is actually basic collision detection) into a method if you want to experiment with other shapes.
Edit
I edited my answer to include the original code reworked to use a random square as the custom shape -the easiest shape to try as mentioned in my original answer. Hopefully you can compare the two and see the changes I made to try and figure out the logic behind it.
For a circle, or any other totally random shape, it would be a bit more difficult, but same idea/concept.
//number of balls
var numBalls:uint = 200;
var defaultBallSize:uint = 8;
var colors:Array = [0x79B718, 0x2D91A8, 0xB019BC, 0xF98715, 0xDB1616];
// new custom shape bounds, a square that is 200, 200 px and is at 175, 100 on the stage
var customSquare:Rectangle = new Rectangle(175, 100, 200, 200);
//init
makeDots();
function makeDots():void {
//create desired number of balls
for (var ballNum:uint=0; ballNum < numBalls; ballNum++){
var c1:Number = randomColor();
var c2:Number = randomColor();
//create ball
var thisBall:MovieClip = new MovieClip();
thisBall.graphics.beginFill(c1);
//thisBall.graphics.lineStyle(defaultBallSize, 0);
thisBall.graphics.drawCircle(defaultBallSize, defaultBallSize, defaultBallSize);
thisBall.graphics.endFill();
addChild(thisBall);
//coordinates - this part of the code is setting the initial positions of the circles based on the stage size
//thisBall.x = Math.random() * stage.stageWidth;
//thisBall.y = Math.random() * stage.stageHeight;
//
// changed so they use the "customSquare" rectangle instead, note that the custom shape has an x and y pos now that doesn't start at 0 (unlike the stage)
thisBall.x = (Math.random() * customSquare.width) + customSquare.x;
thisBall.y = (Math.random() * customSquare.height) + customSquare.y;
//percieved depth
thisBall.ballNum = ballNum;
thisBall.depth = ballNum / numBalls;
thisBall.scaleY = thisBall.scaleX = ballNum / numBalls;
//velocity
thisBall.vx = 0;
thisBall.vy = 0;
thisBall.vz = 0;
//ball animation
thisBall.addEventListener(Event.ENTER_FRAME, animateBall);
}
}
var dampen:Number = 0.90;
var maxScale:Number = 1.3;
var minScale:Number = .3;
var maxAlpha:Number = 1.3;
var minAlpha:Number = 0.3;
function animateBall(e:Event):void{
var thisBall:Object = e.target;
//apply randomness to velocity
/*thisBall.vx += Math.random() * 0.2 - 0.1;
thisBall.vy += Math.random() * 0.2 - 0.1;
thisBall.vz += Math.random() * 0.002 - 0.001;*/
// increased velocity ranges to add more speed to see the effects easier
thisBall.vx += Math.random() * 1.2 - 0.6;
thisBall.vy += Math.random() * 1.2 - 0.6;
thisBall.vz += Math.random() * 0.012 - 0.006;
thisBall.x += thisBall.vx;
thisBall.y += thisBall.vy;
//thisBall.scaleX = thisBall.scaleY += thisBall.vz;
//thisBall.alpha += thisBall.vz;
thisBall.vx *= dampen;
thisBall.vy *= dampen;
thisBall.vz *= dampen;
// =====================================================================================================================================
// this part of the code is determining if each ball is going outside of the bounds of the stage and repositioning them if they are
// this part is the 'collision detection', changed to use the bounds of the "customSquare" rectangle instead
//
// this part is detecting the position going out of bounds along the X axis
/*if(thisBall.x > stage.stageWidth) {
thisBall.x = 0 - thisBall.width;
} else if(thisBall.x < 0 - thisBall.width) {
thisBall.x = stage.stageWidth;
}*/
if(thisBall.x > (customSquare.width + customSquare.x)) {
thisBall.x = customSquare.x - thisBall.width;
} else if(thisBall.x < customSquare.x - thisBall.width) {
thisBall.x = customSquare.width + customSquare.x;
}
// this part is detecting the position going out of bounds along the Y axis
/*if(thisBall.y > stage.stageHeight) {
thisBall.y = 0 - thisBall.height;
} else if(thisBall.y < 0 - thisBall.height) {
thisBall.y = stage.stageHeight;
}*/
if(thisBall.y > (customSquare.height + customSquare.y)) {
thisBall.y = customSquare.y - thisBall.height;
} else if(thisBall.y < customSquare.y - thisBall.height) {
thisBall.y = customSquare.height + customSquare.y;
}
// =====================================================================================================================================
if (thisBall.scaleX > maxScale){
thisBall.scaleX = thisBall.scaleY = maxScale;
} else if (thisBall.scaleX < minScale){
thisBall.scaleX = thisBall.scaleY = minScale;
}
if (thisBall.alpha > maxAlpha){
thisBall.alpha = maxAlpha;
} else if (thisBall.alpha < minAlpha){
thisBall.alpha = minAlpha;
}
}
function randomColor():uint{ return colors[int(Math.random()*colors.length)]; }
Assuming all you are asking is for a border around the confined area, You could do something like:
var container:MovieClip = new MovieClip;
container.graphics.lineStyle(1,0,1);
container.graphics.drawRect(0, 0, container.width, container.height);
container.graphics.endFill();
addChild(container);
And Replace :
addChild(thisBall);
With :
container.addChild(thisBall);
From animating in flash I can tell you the flash-way of doing something like this is through layer masks. This should is possible in code too. Something loosely like this:
addChild(thisBall);
var layermask:Shape=new Shape();
addChild(layermask);
thisBall.mask=maskingShape;