I'm using canvas to generate random colored objects with an interval. What I want to do is, to fade the objects into whiteness just like they're fading into fog.
I want to achieve this without needing to redraw every object in every frame. Instead, I'm putting white layers between objects (with small opacity) so that it gives the efect of fade out.
Here is my current approach:
http://jsfiddle.net/zettam/pUVkA/26/
var cvas = document.getElementById("ctxt");
var cx = cvas.getContext("2d");
function randomColor(num) {
return Math.floor(Math.random() * num);
}
setInterval(function() {
var r = randomColor(255);
var g = randomColor(255);
var b = randomColor(255);
cx.fillStyle = "rgba(" + r + "," + g + "," + b + ",1.0)";
cx.fillRect(200*Math.random(), 200*Math.random(), 300*Math.random(), 300*Math.random());
}, 200);
setInterval(function() {
cx.fillStyle = "rgba(255,255,255,0.025)"
cx.fillRect(0, 0, 500, 500);
}, 20);
Asyou can see, the objects never fade out to fully white, but instead, they stay at somewhere gray.
How can I achieve what I need without having to re-draw everything every frame ?
Thanks.
The opacity setting in cx.fillStyle = "rgba(255,255,255,0.025)" is not working when less than 0.1. (some calculation problem with that function?)
Try setting it to 0.1 instead of 0.025 and change the Interval to something higher to compensate like 50 ?
Try this: http://jsfiddle.net/pUVkA/31/
It's a compromise between the two methods. As #Josh mentioned, the canvas compositing code has a problem with completely overlaying with an opacity less than 0.1.
var cvas = document.getElementById("ctxt"),
cx = cvas.getContext("2d"),
lFade = new Date(),
lBox = new Date(),
lClear = new Date();
function randomColor(num) {
return Math.floor(Math.random() * num);
}
(function draw(){
var now = new Date();
if (now - lFade > 20){
cx.fillStyle = "rgba(255,255,255,0.025)"
cx.fillRect(0, 0, 500, 500);
lFade = now;
}
if (now - lClear > 800){
cx.fillStyle = "rgba(255,255,255,0.1)"
cx.fillRect(0, 0, 500, 500);
lClear = now;
}
if (now - lBox > 200){
var r = randomColor(255);
var g = randomColor(255);
var b = randomColor(255);
cx.fillStyle = "rgba(" + r + "," + g + "," + b + ",1.0)";
cx.fillRect(200*Math.random(), 200*Math.random(), 300*Math.random(), 300*Math.random());
lBox = now;
}
setTimeout(draw, 1000/60);
})();
Related
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D':
The canvas has been tainted by cross-origin data
I am getting above error only in chrome. My code(following) works fine in mozilla. I have not corss domain issue. So why could i get above error in chrome?
var wheel_canvas, wheel_context, can_w, can_h, wheel_grd;
var LARGE_RADIUS = 160;
var SMALL_RADIUS = 120;
var wheel_canvas = document.getElementById('wheel_canvas');
var wheel_context = wheel_canvas.getContext('2d');
var can_w = $(wheel_canvas).width();
var can_h = $(wheel_canvas).height();
var centerX = can_w / 2, centerY = can_h / 2;
var wheel_grd = null;
test('#FF0000');
function test(hex)
{
$('#clrpicker').css({'left': 210, 'top': 210 });
inverted = hexBW(hex);
$('#color_val_show').val(hex);
current_color_hex_val_selected = hex;
$('#color_val_show').css({'color':inverted,'background':hex});
fillGradientCirle(hex);
}
function fillGradientCirle(hex)
{
wheel_context.rect(0, 0, can_w, can_h);
wheel_grd = wheel_context.createLinearGradient(1, 1, 0, can_w, can_h);
wheel_grd.addColorStop(1, '#ffffff');
wheel_grd.addColorStop(0.5, hex);
wheel_grd.addColorStop(0, '#000000');
wheel_context.fillStyle = wheel_grd;
wheel_context.beginPath();
wheel_context.arc(centerX, centerY, LARGE_RADIUS, 0, 2 * Math.PI);
wheel_context.fill();
}
$(wheel_canvas).click(function (e)
{
$.event.fix(e);
x = e.pageX;
y = e.pageY;
can_p = $(this).offset();
x = x - $(document).scrollLeft() - can_p.left;
// Fixed typo
y = y - $(document).scrollTop() - can_p.top;
if (Math.sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)) < SMALL_RADIUS) return; // Precaution
$('#wheel_picker').css({ 'left': x-8 + 'px', 'top': y-8 + 'px' });
var data = wheel_context.getImageData(x, y, 1, 1).data;
pixelData = data;
rgbString = 'rgb(' + pixelData[0] + ', ' + pixelData[1] + ', ' + pixelData[2] + ')';
hex = rgb2hex(rgbString);
inverted = hexBW(hex);
$('#color_val_show').val(hex);
current_color_hex_val_selected = hex;
$('#color_val_show').css({'color':inverted,'background':hex});
$('#feedback').html("Coordinates : " + x + "," + y + " Color: " + hex);
});
If this is all the code and you don't use any cross-origin images then the only error that stand out is this line:
wheel_grd = wheel_context.createLinearGradient(1, 1, 0, can_w, can_h);
This should only have four arguments not five. The last argument may trip out Chrome in some way.
Try by changing it to:
// x0 y0 x1 y1
wheel_grd = wheel_context.createLinearGradient(1, 0, can_w, can_h);
Other errors you can consider looking at:
You are declaring the variables twice - the first var line in the example code is unnecessary
You are reading CSS size of canvas element, not its bitmap size (they are not the same).
To read proper dimension of canvas (unless you intended to read the CSS size for some reason) you need to use the following instead:
var can_w = wheel_canvas.width; //$(wheel_canvas).width();
var can_h = wheel_canvas.height; //$(wheel_canvas).height();
or if you insist on using jQuery:
var can_w = $(wheel_canvas).prop('width');
var can_h = $(wheel_canvas).prop('height');
Hope this helps!
For testing, you can also use --allow-file-access-from-files as a command-line argument to Chrome; this will allow you to use local files.
I draw varicolored canvas and on click redraw it and draw black rectangles. But rectangles does not remove! What I'm doing wrong?
Demo:
http://jsfiddle.net/82nnJ/
function draw_palette() {
$c = document.getElementById('palette');
$ctx = $c.getContext('2d');
var size = 256;
$ctx.clearRect(0, 0, size, size); //
var r = 255;
var a = 255;
for (var g = 0; g < size; g++) {
for (var b = 0; b < size; b++) {
$ctx.fillStyle = "rgba(" + r + ", " + g + ", " + b + ", " + (a/255) + ")";
$ctx.fillRect(g, b, 1, 1);
}
}
}
jQuery(document).ready(function() {
draw_palette();
$('#palette').click(function(e) {
draw_palette();
var x = e.pageX - $(this).position().left;
var y = e.pageY - $(this).position().top;
var radius = 5;
$ctx.rect(x-radius, y-radius, 2*radius+1, 2*radius+1);
$ctx.strokeStyle = 'black';
$ctx.stroke();
});
});
There should be beginPath and closePath methods.
$ctx.beginPath();
$ctx.rect(x-radius, y-radius, 2*radius+1, 2*radius+1);
$ctx.strokeStyle = 'black';
$ctx.stroke();
$ctx.closePath();
I just solved a similar issue. I have a chart that was programmed in javascript on the web-side and a server transmitting data to the chart. Used websockets to update the chart on a realtime basis.
Basically in the onmessage event the Canvas object was destroyed and constructed using the DOM. With the previous object destroyed this ensures that it repaints correctly.
Here's what I did...
var c = document.getElementsByName("myCanvas")[0];
if (c != null)
{
c.remove();
}
var c = document.createElement("canvas");
c.setAttribute("name", "myCanvas");
c.setAttribute("width", 900);
c.setAttribute("height", 600);
c.setAttribute("style", "border:1px solid #d3d3d3");
var ctx = c.getContext("2d");
document.body.append(c);
I am working on a breakout type game with dynamically-created squares. When a brick gets hit, I fire off a removeMC function that is supposed to turn it white and make it shrink down in size. However, sometimes the squares just turn white instead of tweening down. I have included the script for the removeMV function as well as the function that creates the squares. Arg1 is the square to be removed. I apologize for the bad naming conventions, but the fire got corrupted and had to be recovered with a decompiler.
This is the removeMC function
public function removeMC(arg1:flash.display.Sprite):*
{
this.score --;
this.uiBar.txtScore.text=this.score;
var loc1:*=new flash.geom.ColorTransform();
loc1.color = 0xffffFF;
arg1.transform.colorTransform = loc1;
TweenMax.to(arg1, 0.4, {colorTransform:{tint:0x0000ff, tintAmount:1}});
var loc2:*=this.ballMC.x - this.ballMC.x % 30;
var loc3:*=this.ballMC.y - this.ballMC.y % 30;
arg1.scaleY = arg1.scaleY * -1;
// trace("Ball x:" + this.ballMC.x + " ballY:" + this.ballMC.y + " block x:" + loc2 + " block y:" + loc3);
var loc4:*=new fl.transitions.Tween(arg1, "width", null, 30, 0, 0.5, true);
var loc5:*=new fl.transitions.Tween(arg1, "height", null, 30, 0, 0.5, true);
var loc6:*=new fl.transitions.Tween(arg1, "x", null, 0, loc2, 0.5, true);
var loc7:*=new fl.transitions.Tween(arg1, "y", null, 0, loc3, 0.5, true);
this.brickArray.splice(this.indexSearch(this.brickArray, arg1), 1);
arg1.x+=3000;//failsafe to remove the squares. doesn't work
arg1.y+=3000;
return;
}
This is the function that creates the squares. Arg 1 and arg2 are the width and height in squares
public function createImgNodeGrid(arg1:int=1, arg2:int=1, arg3:Number=0):void
{
var loc6:*=0;
var loc7:*=null;
var loc8:*=null;
var loc9:*=null;
var loc10:*=null;
var loc1:*=this._img.width / arg1;
var loc2:*=this._img.height / arg2;
var loc3:*=arg1 * arg2;
this._imgNodes = [];
var loc4:*=0;
var loc5:*=0;
while (loc5 < arg1)
{
loc6 = 0;
while (loc6 < arg2)
{
loc7 = new flash.geom.Rectangle(loc5 * loc1, loc6 * loc2, loc1, loc2);
loc8 = new flash.display.BitmapData(loc1, loc2, true);
loc8.copyPixels(this._img.bitmapData, loc7, this.zero);
loc9 = new flash.display.Bitmap(loc8);
loc9.x = loc5 * (loc1 + arg3);
loc9.y = loc6 * (loc2 + arg3);
var loc11:*;
this._imgNodes[loc11 = loc4++] = loc9;
loc10 = new flash.display.Sprite();
loc10.mouseChildren = false;
this.brickArray.push(loc10);
loc10.addChild(loc9);
this._tiledImg.addChild(loc10);
++loc6;
}
++loc5;
}
return;
}
I may miss the mark here as its quite hard to read that lot, however, this is my suggestion for your removeMc function. I noticed you have TweenMax, so I would utilise that as opposed to the flash tweener class.
public function removeMC(arg1:flash.display.Sprite):*
{
this.score --;
this.uiBar.txtScore.text=this.score;
var loc1:*=new flash.geom.ColorTransform();
loc1.color = 0xffffFF;
arg1.transform.colorTransform = loc1;
var loc2:*=this.ballMC.x - this.ballMC.x % 30;
var loc3:*=this.ballMC.y - this.ballMC.y % 30;
TweenMax.to(arg1, 0.4, {scaleY:0, scaleX:0, x:loc2, y:loc3, colorTransform:{tint:0x0000ff, tintAmount:1}, onComplete:tweenComplete(arg1)});
// trace("Ball x:" + this.ballMC.x + " ballY:" + this.ballMC.y + " block x:" + loc2 + " block y:" + loc3);
this.brickArray.splice(this.indexSearch(this.brickArray, arg1), 1);
return;
}
private function tweenComplete(square:Sprite):void
{
this.removeChild(square);
}
That should result in the square shrinking to 0 size and becoming white at the same time. Then once it completes it will remove the child completely.
I'm a bit new to canvas and such so forgive if it's a trivial question.
I'd like to be able to animate an object following a path (defined as bezier path) but I'm not sure how to do it.
I've looked at Raphael but I can't work out how to follow the path over time.
Cake JS looked promising in the demo, but I'm really struggling the documentation, or lack thereof in this case.
Has anyone got some working example of this?
Use the code on my website from this related question, but instead of changing the .style.left and such in the callback, erase and re-draw your canvas with the item at the new location (and optionally rotation).
Note that this uses SVG internally to easily interpolate points along a bézier curve, but you can use the points it gives you for whatever you want (including drawing on a Canvas).
In case my site is down, here's a current snapshot of the library:
function CurveAnimator(from,to,c1,c2){
this.path = document.createElementNS('http://www.w3.org/2000/svg','path');
if (!c1) c1 = from;
if (!c2) c2 = to;
this.path.setAttribute('d','M'+from.join(',')+'C'+c1.join(',')+' '+c2.join(',')+' '+to.join(','));
this.updatePath();
CurveAnimator.lastCreated = this;
}
CurveAnimator.prototype.animate = function(duration,callback,delay){
var curveAnim = this;
// TODO: Use requestAnimationFrame if a delay isn't passed
if (!delay) delay = 1/40;
clearInterval(curveAnim.animTimer);
var startTime = new Date;
curveAnim.animTimer = setInterval(function(){
var now = new Date;
var elapsed = (now-startTime)/1000;
var percent = elapsed/duration;
if (percent>=1){
percent = 1;
clearInterval(curveAnim.animTimer);
}
var p1 = curveAnim.pointAt(percent-0.01),
p2 = curveAnim.pointAt(percent+0.01);
callback(curveAnim.pointAt(percent),Math.atan2(p2.y-p1.y,p2.x-p1.x)*180/Math.PI);
},delay*1000);
};
CurveAnimator.prototype.stop = function(){
clearInterval(this.animTimer);
};
CurveAnimator.prototype.pointAt = function(percent){
return this.path.getPointAtLength(this.len*percent);
};
CurveAnimator.prototype.updatePath = function(){
this.len = this.path.getTotalLength();
};
CurveAnimator.prototype.setStart = function(x,y){
var M = this.path.pathSegList.getItem(0);
M.x = x; M.y = y;
this.updatePath();
return this;
};
CurveAnimator.prototype.setEnd = function(x,y){
var C = this.path.pathSegList.getItem(1);
C.x = x; C.y = y;
this.updatePath();
return this;
};
CurveAnimator.prototype.setStartDirection = function(x,y){
var C = this.path.pathSegList.getItem(1);
C.x1 = x; C.y1 = y;
this.updatePath();
return this;
};
CurveAnimator.prototype.setEndDirection = function(x,y){
var C = this.path.pathSegList.getItem(1);
C.x2 = x; C.y2 = y;
this.updatePath();
return this;
};
…and here's how you might use it:
var ctx = document.querySelector('canvas').getContext('2d');
ctx.fillStyle = 'red';
var curve = new CurveAnimator([50, 300], [350, 300], [445, 39], [1, 106]);
curve.animate(5, function(point, angle) {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillRect(point.x-10, point.y-10, 20, 20);
});
In action: http://jsfiddle.net/Z2YSt/
So, here is the verbose version:
t being any number between 0 and 1 representing time; the p0, p1, p2, p3 objects are the start point, the 1st control point, the 2nd control point an the end point respectively:
var at = 1 - t;
var green1x = p0.x * t + p1.x * at;
var green1y = p0.y * t + p1.y * at;
var green2x = p1.x * t + p2.x * at;
var green2y = p1.y * t + p2.y * at;
var green3x = p2.x * t + p3.x * at;
var green3y = p2.y * t + p3.y * at;
var blue1x = green1x * t + green2x * at;
var blue1y = green1y * t + green2y * at;
var blue2x = green2x * t + green3x * at;
var blue2y = green2y * t + green3y * at;
var finalx = blue1x * t + blue2x * at;
var finaly = blue1y * t + blue2y * at;
Here is a ball using <canvas> following a path in JSfiddle
The names of the variables come from this gif wich is the best explication for bezier curves: http://en.wikipedia.org/wiki/File:Bezier_3_big.gif
A short version of the code, inside a function ready to copy/paste:
var calcBezierPoint = function (t, p0, p1, p2, p3) {
var data = [p0, p1, p2, p3];
var at = 1 - t;
for (var i = 1; i < data.length; i++) {
for (var k = 0; k < data.length - i; k++) {
data[k] = {
x: data[k].x * at + data[k + 1].x * t,
y: data[k].y * at + data[k + 1].y * t
};
}
}
return data[0];
};
Related stuff:
http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html
http://13thparallel.com/archive/bezier-curves/
http://gsgd.co.uk/sandbox/jquery/easing/jquery.easing.1.3.js
http://www.youtube.com/watch?v=hUCT4b4wa-8
I wouldn't use Canvas for this unless you really have to. SVG has animation along a path built in. Canvas requires quite a bit of math to get it working.
Here's one example of SVG animating along a path.
Here's some discussion about it for raphael: SVG animation along path with Raphael
Please note that Raphael uses SVG and not HTML5 Canvas.
One way to animate along a bezier path in Canvas is to continuously bisect the bezier curve, recoring the midpoints until you have a lot of points (say, 50 points per curve) that you can animate the object along that list of points. Search for bisecting beziers and similar queries for the related math on that.
I've read a number of similar questions to this on here, but unfortunately none of them seem to give the exact answer I'm after, or they might but the maths is beyond me!
I'm creating a game where you have a cannon at the left edge of the screen. I want to be able to fire a cannonball from the cannon in an arc so that it intersects where the mouse pointer is on the screen.
I've seen a few examples that move a projectile in an arc from point a to point b, but what I need is for the cannonball to first move along the axis of the cannon itself, it's no good if the ball leaves the end of the cannon at a different angle to which the cannon is pointing.
The only force acting on the ball will be gravity and it's starting velocity.
Also to complicate matters, I need the cannons angle to change according to how far away the mouse pointer is from the end of the cannon, so if the pointer is far away than the cannon will point upwards say at an angle of 45 degrees, but if the pointer is very close to the end of the cannon then the cannon will point directly at the pointer, this I've more or less already got working by just getting the distance between them and then dividing it by a number and subtracting it from the rotation value of the cannon, but it's a bit of a rough way of doing it.
EDIT
Using the code below I've managed to the line in the screen shot below. But as you can see it's not the trajectory I need, I need something more like the red line I've put in.
And here's how I've implemented the code (probably wrongly)
public class GameTurretLine2
{
var rt:Object = null;
var lineMc:MovieClip = new MovieClip();
var myTurret:GameMainGun = null;
var pta:Point = new Point(0,0);
var ptb:Point = new Point(0,0);
var ptc:Point = new Point(0,0);
var ptd:Point = new Point(0,0);
public function GameTurretLine2(rt2,turret)
{
rt = rt2;
myTurret = turret;
lineMc.graphics.lineStyle(2, 0x55aa00);
mainLoop();
rt.rt.GameLayers.turretLineMc.addChild(lineMc);
}
function mainLoop()
{
lineMc.graphics.clear();
//get points
var turretEnd:Object = myTurret.rt.Useful.localToGlobalXY(myTurret.mC.turret.firePoint);
var turretStart:Object = myTurret.rt.Useful.localToGlobalXY(myTurret.mC.turret);
var mousePos:Point = new Point(myTurret.rt.rt.mouseX,myTurret.rt.rt.mouseY);
var inbetween:Point = new Point(0,0);
//start
pta.x = turretStart.newX;
pta.y = turretStart.newY;
//mouse end
ptd.x = mousePos.x;
ptd.y = mousePos.y;
// The cannon's angle:
// make the cannon's angle some inverse factor
// of the distance between the mouse and cannon tip
var dist:Number = myTurret.rt.Useful.getDistance(turretEnd.newX, turretEnd.newY, mousePos.x, mousePos.y);
var cAng:Number = dist * (180/Math.PI);
var ptbc:Point = new Point((ptd.x - pta.x) *.5,0);
ptbc.y = Math.tan(cAng) * ptbc.x;
//ptb = new Point(ptbc.x - ptbc.x * .15, ptbc.y);
ptb = new Point(turretEnd.newX, turretEnd.newY);
ptc = new Point(ptbc.x + ptbc.x * .5, ptbc.y);
// create the Bezier:
var bz:BezierSegment = new BezierSegment(pta,ptb,ptc,ptd);
trace(bz);
// define the distance between points that you want to draw
// has to be between 0 and 1.
var stepVal:Number = .1;
var curPt:Point = pta;
//draw circles
lineMc.graphics.drawCircle(pta.x, pta.y, 4);
lineMc.graphics.drawCircle(ptb.x, ptb.y, 4);
lineMc.graphics.drawCircle(ptc.x, ptc.y, 4);
lineMc.graphics.drawCircle(ptd.x, ptd.y, 4);
lineMc.graphics.lineStyle(2, 0x0000ff);
//step along the curve to draw it
for(var t:Number = 0;t < 1;t+=stepVal){
lineMc.graphics.moveTo(curPt.x, curPt.y);
curPt = bz.getValue(t);
trace("curPt = " + curPt.x + "," + curPt.y);
lineMc.graphics.lineTo(curPt.x, curPt.y);
}
trace("pta = " + pta.x + "," + pta.y);
trace("ptb = " + ptb.x + "," + ptb.y);
trace("ptc = " + ptc.x + "," + ptc.y);
trace("ptd = " + ptd.x + "," + ptd.y);
}
}
Also for some strange reason, the line created by the code flips, from how it is in the screen shot to an indented code (y flipped) just by moving the mouse a tiny amount, so as you move the mouse the line jumps everywhere.
One method is to create a Bezier curve.
This sounds like a workable solution because you essentially want the curve to always fit under some triangle. If this triangle defines the control points for a Bezier curve, you can make that match pretty closely the arc of a cannonball under gravity (it's not a perfect representation of gravity). One side-effect of this method is that the (inversed) height can define the force of the cannonball.
You can use the fl.motion.BezierSegment to create a curve and step along it. Paste this code into an FLA:
import fl.motion.BezierSegment;
var mySprite:Sprite = new Sprite();
addChild(mySprite);
mySprite.graphics.lineStyle(2, 0x55aa00);
// End point of the cannon:
var pta:Point = new Point(0, 100);
mySprite.graphics.drawCircle(pta.x, pta.y, 4);
trace("pta = " + pta.x + "," + pta.y);
// mouse point
// var ptd:Point = new Point(mouseX, mouseY);
// for testing:
var ptd:Point = new Point(200,100);
mySprite.graphics.drawCircle(ptd.x, ptd.y, 4);
trace("ptd = " + ptd.x + "," + ptd.y);
// The cannon's angle:
// make the cannon's angle some inverse factor
// of the distance between the mouse and cannon tip
// var dx:Number = ptd.x-pta.x;
// var dy:Number = ptd.y-pta.y;
// var dist:Number = Math.sqrt(dx * dx + dy * dy);
var cAng:Number = 30 * /(180/Math.PI);
// point the cannon in the correct direction here, however you are intending to do that.
// triangulate the cannon pt and mouse pt assuming the cannon's angle for both:
// *** NOTE: for simplicity, this assumes a straight line on the x-plane. ***
var ptbc:Point = new Point((ptd.x - pta.x) *.5,0);
ptbc.y = Math.tan(cAng) * ptbc.x;
trace("ptbc = " + ptbc.x + "," + ptbc.y);
// to adjust the curve:
var ptb:Point = new Point(ptbc.x - ptbc.x * .15, ptbc.y);
var ptc:Point = new Point(ptbc.x + ptbc.x * .5, ptbc.y);
mySprite.graphics.drawCircle(ptb.x, ptb.y, 4);
mySprite.graphics.drawCircle(ptc.x, ptc.y, 4);
// create the Bezier:
var bz:BezierSegment = new BezierSegment(pta,ptb,ptc,ptd);
trace(bz);
// define the distance between points that you want to draw
// has to be between 0 and 1.
var stepVal:Number = .1;
var curPt:Point = pta;
mySprite.graphics.lineStyle(2, 0x0000ff);
//step along the curve to draw it
for(var t:Number = 0;t < 1;t+=stepVal){
mySprite.graphics.moveTo(curPt.x, curPt.y);
curPt = bz.getValue(t);
trace("curPt = " + curPt.x + "," + curPt.y);
mySprite.graphics.lineTo(curPt.x, curPt.y);
}
mySprite.x = stage.stageWidth/2-mySprite.width/2;
mySprite.y = stage.stageHeight/2-mySprite.height/2;
As is, this code is not attached directly to the mouse, so you will have to use your own MouseEvent and AdjustCannonEvent to run this code. (Also, make sure to see the note in the code.)