I'm trying to convert one of the Paper.js library examples (http://paperjs.org/examples/smoothing/) from PaperScript to Javascript. Following the documentation, I have
Made the scope global
Installed the event handlers onFrame and onResize
Created a tool and installed the event handlers onMouseMove and onMouseDown
But the canvas is not shown. I only see a couple of small blue lines: AFAIK the problem lies in the view.onFrame() function, since commenting that out at least I can see the shape, but not interact with it. The JS console dosen't show any error. What is missing?
// Make the paper scope global, by injecting it into window
paper.install(window);
window.onload = function () {
// Setup directly from canvas id:
paper.setup('myCanvas');
// Create tool
tool = new Tool();
var width, height, center;
var points = 10;
var smooth = true;
var path = new Path();
var mousePos = view.center / 2;
var pathHeight = mousePos.y;
path.fillColor = 'black';
initializePath();
function initializePath() {
center = view.center;
width = view.size.width;
height = view.size.height / 2;
path.segments = [];
path.add(view.bounds.bottomLeft);
for (var i = 1; i < points; i++) {
var point = new Point(width / points * i, center.y);
path.add(point);
}
path.add(view.bounds.bottomRight);
path.fullySelected = true;
}
view.onFrame = function (event) {
pathHeight += (center.y - mousePos.y - pathHeight) / 10;
for (var i = 1; i < points; i++) {
var sinSeed = event.count + (i + i % 10) * 100;
var sinHeight = Math.sin(sinSeed / 200) * pathHeight;
var yPos = Math.sin(sinSeed / 100) * sinHeight + height;
path.segments[i].point.y = yPos;
}
if (smooth)
path.smooth({ type: 'continuous' });
}
tool.onMouseMove = function (event) {
mousePos = event.point;
}
tool.onMouseDown = function (event) {
smooth = !smooth;
if (!smooth) {
// If smooth has been turned off, we need to reset
// the handles of the path:
for (var i = 0, l = path.segments.length; i < l; i++) {
var segment = path.segments[i];
segment.handleIn = segment.handleOut = null;
}
}
}
// Reposition the path whenever the window is resized:
view.onResize = function (event) {
initializePath();
}
}
To try it: https://jsfiddle.net/1rtkbp9s/
Found the solution (credits to Stefan Krüger of the Paper.js Google Group):
var mousePos = view.center / 2;
Should have been:
var mousePos = view.center.divide(2);
The fact is that Math functions should be used instead of operators for Point and Size object... and I didn't realize that view.center IS a Point object: http://paperjs.org/reference/view/#center
Related
The Problem
I am creating a game using the HTML5 Canvas, the game has a main menu, the main menu has multiple buttons for you to choose. I am finding it difficult and confusing how I would, for example if the user presses the 'Play' button, to show the game. Here is an image of the main menu:
The Question
The question is how would I get from this page to another in my game?
I think you get the idea. I deliberately created the menu using the canvas, I know I could of made the menu using HTML for example but I cant as this is an example for students of what Canvas can do, whats good and bad etc.
The Code
<html>
<head>
<title>Sean Coyne</title>
</head>
<body onload="start_game()">
<body>
<div style id="canvas">
<canvas id="myCanvas" style="border:5px solid #410b11" height="320" width="480">
<p>Your browser does not support HTML5!</p>
</canvas>
<script type="text/javascript">
//Referencing the canvas
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var width = canvas.getAttribute('width');
var height = canvas.getAttribute('height');
//Finding the position of the mouse
var mouseX;
var mouseY;
//Images
var bgImage = new Image();
var logoImage = new Image();
var playImage = new Image();
var instructImage = new Image();
var settingsImage = new Image();
var aboutImage = new Image();
var peaceImage = new Image();
var backgroundY = 0;
var speed = 1;
//Arrays below used for mouse over function
var buttonX = [130,110,130,160];
var buttonY = [100,140,180,220];
var buttonWidth = [96,260,182,160];
var buttonHeight = [40,40,40,40];
var peaceX = [0,0];
var peaceY = [0,0];
var peaceWidth = 35;
var peaceHeight = 35;
var peaceVisible = false;
var peaceSize = peaceWidth;
var peaceRotate = 0;
var frames = 30;
var timerId = 0;
var fadeId = 0;
var time = 0.0;
peaceImage.src = "Images/peace.png";
bgImage.onload = function(){
context.drawImage(bgImage, 0, backgroundY);
};
bgImage.src = "Images/background.png";
logoImage.onload = function(){
context.drawImage(logoImage, 50, -10);
}
logoImage.src = "Images/logo.png";
playImage.onload = function(){
context.drawImage(playImage, buttonX[0], buttonY[0]);
}
playImage.src = "Images/play.png";
instructImage.onload = function(){
context.drawImage(instructImage, buttonX[1], buttonY[1]);
}
instructImage.src = "Images/instructions.png";
settingsImage.onload = function(){
context.drawImage(settingsImage, buttonX[2], buttonY[2]);
}
settingsImage.src = "Images/settings.png";
aboutImage.onload = function(){
context.drawImage(aboutImage, buttonX[3], buttonY[3]);
}
aboutImage.src = "Images/about.png";
timerId = setInterval("update()", 1000/frames);
canvas.addEventListener("mousemove", checkPos);
canvas.addEventListener("mouseup", checkClick);
function update() {
clear();
move();
draw();
}
function clear() {
context.clearRect(0, 0, width, height);
}
function move(){
backgroundY -= speed;
if(backgroundY == -1 * height){
backgroundY = 0;
}
if(peaceSize == peaceWidth){
peaceRotate = -1;
}
if(peaceSize == 0){
peaceRotate = 1;
}
peaceSize += peaceRotate;
}
function draw(){
context.drawImage(bgImage, 0, backgroundY);
context.drawImage(logoImage, 50,-10);
context.drawImage(playImage, buttonX[1], buttonY[0]);
context.drawImage(instructImage, buttonX[2], buttonY[1]);
context.drawImage(settingsImage, buttonX[2], buttonY[2]);
context.drawImage(aboutImage, buttonX[3], buttonY[3]);
if(peaceVisible == true){
context.drawImage(peaceImage, peaceX[0] - (peaceSize/2), peaceY[0], peaceSize, peaceHeight);
context.drawImage(peaceImage, peaceX[2] - (peaceSize/2), peaceY[2], peaceSize, peaceHeight);
}
}
function checkPos(mouseEvent){
if(mouseEvent.pageX || mouseEvent.pageY == 0){
mouseX = mouseEvent.pageX - this.offsetLeft;
mouseY = mouseEvent.pageY - this.offsetTop;
}else if(mouseEvent.offsetX || mouseEvent.offsetY == 0){
mouseX = mouseEvent.offsetX;
mouseY = mouseEvent.offsetY;
}
for(i = 0; i < buttonX.length; i++){
if(mouseX > buttonX[i] && mouseX < buttonX[i] + buttonWidth[i]){
if(mouseY > buttonY[i] && mouseY < buttonY[i] + buttonHeight[i]){
peaceVisible = true;
peaceX[0] = buttonX[i] - (peaceWidth/2) - 2;
peaceY[0] = buttonY[i] + 2;
peaceX[1] = buttonX[i] + buttonWidth[i] + (peaceWidth/2);
peaceY[1] = buttonY[i] + 2;
}
}else{
peaceVisible = false;
}
}
}
function checkClick(mouseEvent){
for(i = 0; i < buttonX.length; i++){
if(mouseX > buttonX[i] && mouseX < buttonX[i] + buttonWidth[i]){
if(mouseY > buttonY[i] && mouseY < buttonY[i] + buttonHeight[i]){
fadeId = setInterval("fadeOut()", 1000/frames);
clearInterval(timerId);
canvas.removeEventListener("mousemove", checkPos);
canvas.removeEventListener("mouseup", checkClick);
}
}
}
}
function fadeOut(){
context.fillStyle = "rgba(0,0,0, 0.2)";
context.fillRect (0, 0, width, height);
time += 0.1;
if(time >= 2){
clearInterval(fadeId);
time = 0;
timerId = setInterval("update()", 1000/frames);
canvas.addEventListener("mousemove", checkPos);
canvas.addEventListener("mouseup", checkClick);
}
}
</script>
</body>
</html>
What I usually do is have a switch statement inside the draw loop, and a state variable which holds the current game state (menu, playing, etc...).
Then, based on the current game state you only draw the objects required for the current scene.
Something like this:
var STATES = {
Menu: 0,
PauseMenu: 1,
Playing: 2
};
var currentState = STATES.Menu;
...
function draw() {
switch(currentState) {
case STATES.Menu:
// Draw buttons, etc..
break;
case STATES.Playing:
// Draw the game screen, the player, etc...
break;
}
}
When the user presses the Play button the only thing you have to do is:
function onPlayButtonClick() {
currentState = STATES.Playing;
// Starting the next frame the new state will be "magically" drawn
}
If you don't like the switch statement, you can create a State class that has a draw method. Then you can simply create new states, each with it's own drawing method and in the main draw loop only call the draw method of the current state.
Same goes for the update function, each state has it's own update function (in the main menu you update buttons or animate things, while playing the game you update the game world and run your physics). So, based on the current state your update function is actually different. It's up to you how you structure your code and how you call different functions based on the current state.
In each text option, you should create a smaller Canvas, only with the option text and add a 'click' event with the callbacks.
Tip: You don't need another page, just erase the main canvas and draw what you want.
I'm trying to build an animated graph with paper.js that can react to different input. So I want to smoothly animate one point vertically to a different point.
I've looked at different examples and the closest ones to mine is this one:
paper.tool.onMouseDown = function(event) {
x = event.event.offsetX;
y = event.event.offsetY;
paper.view.attach('frame', moveSeg);
}
var x;
var y;
function moveSeg(event) {
event.count = 1;
if(event.count <= 100) {
myPath.firstSegment.point._x += (x / 100);
myPath.firstSegment.point._y += (y / 100);
for (var i = 0; i < points - 1; i++) {
var segment = myPath.segments[i];
var nextSegment = segment.next;
var vector = new paper.Point(segment.point.x - nextSegment.point.x,segment.point.y - nextSegment.point.y);
vector.length = length;
nextSegment.point = new paper.Point(segment.point.x - vector.x,segment.point.y - vector.y);
}
myPath.smooth();
}
}
This Code animates one Point to the click position, but I couldn't change it to my needs.
What I need is:
var aim = [120, 100];
var target = aim;
// how many frames does it take to reach a target
var steps = 200;
// Segment I want to move
myPath.segments[3].point.x
And then I dont know how to write the loop that will produce a smooth animation.
example of the graph:
I worked out the answer. The following steps in paperscript:
Generate Path
Set aim for the point
OnFrame Event that does the moving (eased)
for further animations just change the currentAim variable.
var myPath = new Path({
segments: [[0,100],[50,100],[100,100]]});
// styling
myPath.strokeColor = '#c4c4c4'; // red
myPath.strokeWidth = 8;
myPath.strokeJoin = 'round';
myPath.smooth();
// where the middle dot should go
var currentAim = [100,100];
// Speed
var steps = 10;
//Animation
function onFrame(event) {
dX1 = (currentAim[0] - myPath.segments[1].point.x )/steps;
dY1 = (currentAim[1] - myPath.segments[1].point.y )/steps;
myPath.segments[1].point.x += dX1;
myPath.segments[1].point.y += dY1;
}
I have a snap svg animation which animates a bunch of circles, and draws a line between them if they are within a certain proximity of each other. However, I realize that there is a lot of optimizing I can do, but I'm not exactly sure how to do it. I feel like it would be useful to
have a good example of proximity detection in snap
have some more information on optimizing animations in snap svg. It hasn't been easy to find.
Here is a working example of the animation:
http://jsfiddle.net/heaversm/sbj4W/1/
and here are the things I believe can be optimized:
Each circle calls its own animation function - the circles have all been added to a group, and I'm guessing there is a way to apply random motion to all members of a group that is more performant than call a function for each and every element within the group.
for (var i=0; i<this.drawingConfig.circles.amount;i++){
...
this.animateSingle(circleShape);
}
The proximity function is awkward - for each circle, for each update cycle, I have to loop through an array of all the other circles and find out if the X and Y coordinates are close enough to draw a line to. Plus, that means you're getting duplicate lines, because each circle will draw a line to its neighbors, instead of having a single shared line between the two.
for (var i=0;i<circles.length;i++){
var nextCircle = circles[i].node;
var nextCircleX = nextCircle.cx.baseVal.value;
var distance = Math.abs(nextCircleX-thisCircleX);
var proximity = mainModule.drawingConfig.circles.proximity;
if (distance < proximity){
var nextCircleY = nextCircle.cy.baseVal.value;
var thisCircleY = shape.node.cy.baseVal.value;
var distanceY = Math.abs(nextCircleY - thisCircleY);
if (distanceY < proximity){
var line = mainModule.s.line(thisCircleX, thisCircleY, nextCircleX, nextCircleY).attr({stroke: '#a6a8ab', strokeWidth: '1px'});
mainModule.drawingConfig.circles.circleGroup.add(line);
}
}
}
Correspondingly, I each circle's animation function clears all the lines on the screen. Ideally all the circles would be sharing one update function, and in that function, you'd clear the lines.
Snap.animate(startX, animX, function (val) {
var lines = Snap.selectAll('line');
lines.remove();
...
}, mainModule.drawingConfig.circles.animTime);
Right now, I can tell the renderer can't keep up with all of the various animations / loops. Any help optimizing the above things (or anything else you can see that I'm doing weird, would be greatly appreciated.
I cleaned this up by running only one animation loop, on a timer every 10ms, and animated the position of the circles by just giving them a slope and, each update, continuing them further along that slope. You can see an updated fiddle here:
http://jsfiddle.net/heaversm/fJ6fj/
var mainModule = {
s: Snap("#svg"),
drawingConfig: {
circles: {
amount: 20,
sizeMin: 10,
sizeMax: 20,
proximity: 100,
circleGroup: null,
circleArray: [],
animTime: 2000
},
canvas: {
width: 800,
height: 600
}
},
init: function(){
//this.sizeCanvas();
this.makeCircles();
},
sizeCanvas: function(){
$('#svg').width(800).height(600);
},
makeCircles: function(){
this.drawingConfig.circles.circleGroup = this.s.g();
for (var i=0; i<this.drawingConfig.circles.amount;i++){
var circleX = this.randomNumber(0, this.drawingConfig.canvas.width);
var circleY = this.randomNumber(0, this.drawingConfig.canvas.height);
var circleRadius = this.randomNumber(this.drawingConfig.circles.sizeMin,this.drawingConfig.circles.sizeMax);
var circleFill = '#'+Math.floor(Math.random()*16777215).toString(16);
var circleShape = this.s.circle(circleX, circleY, circleRadius);
circleShape.attr({
fill: circleFill
});
this.drawingConfig.circles.circleGroup.add(circleShape);
var circleIncline = this.setIncline();
var circleObj = { incline: circleIncline, shape: circleShape };
this.drawingConfig.circles.circleArray.push(circleObj);
}
this.update();
},
setIncline: function(){
return { incX: this.randomNumber(-5,5), incY: this.randomNumber(-5,5) }
},
update: function(){
var lines = Snap.selectAll('line');
lines.remove();
for (var i=0; i<this.drawingConfig.circles.amount; i++){
var circle = this.drawingConfig.circles.circleArray[i];
var circleX = circle.shape.node.cx.animVal.value;
var circleY = circle.shape.node.cy.animVal.value;
this.move(circle,circleX,circleY);
for (var j=0;j<i;j++){
if (i != j){
var circle2 = this.drawingConfig.circles.circleArray[j];
var circle2X = circle2.shape.node.cx.animVal.value;
var circle2Y = circle2.shape.node.cy.animVal.value;
var dist = mainModule.distance(circleX,circleY,circle2X,circle2Y);
if (dist <= mainModule.drawingConfig.circles.proximity){ //
var lineWeight = 10/dist;
var line = mainModule.s.line(circleX, circleY, circle2X, circle2Y).attr({stroke: '#a6a8ab', strokeWidth: '1px'});
}
if (dist <= 10) { //collision
circle.incline = mainModule.setIncline();
circle2.incline = mainModule.setIncline();
}
}
}
}
setTimeout(function(){ mainModule.update(); },10);
},
distance: function(circleX,circleY,circle2X,circle2Y){
var distX = circle2X - circleX;
var distY = circle2Y - circleY;
distX = distX*distX;
distY = distY*distY;
return Math.sqrt(distX + distY);
},
move: function(circle,curX,curY){
if (curX > this.drawingConfig.canvas.width || curX < 0) {
circle.incline.incX = -circle.incline.incX;
}
if (curY > this.drawingConfig.canvas.height || curY < 0) {
circle.incline.incY = -circle.incline.incY;
}
curX = curX + circle.incline.incX;
curY = curY + circle.incline.incY;
if (curX > this.drawingConfig.canvas.width) {
curX = this.drawingConfig.canvas.width;
circle.incline = this.setIncline();
} else if (curX < 0) {
curX = 0;
circle.incline = this.setIncline();
}
if (curY > this.drawingConfig.canvas.height) {
curY = this.drawingConfig.canvas.height;
circle.incline = this.setIncline();
} else if (curY < 0) {
curY = 0;
circle.incline = this.setIncline();
}
circle.shape.attr({ cx: curX, cy: curY });
},
randomNumber: function(min,max){
return Math.floor(Math.random()*(max-min+1)+min);
},
getBounds: function(shape){
shapeBox = shape.node.getBoundingClientRect();
}
}
mainModule.init();
I'm writing a simple game in javascript and I'm wondering what the best way to handle collisions between the player and the world objects.
<script>
var isJumping = false;
var isFalling = false;
var w = 1;
var recwidth = 400;
var recheight = 400;
var xpos = 50;
var ypos = 279;
window.onload = function() {
var FPS = 30;
var ground = new myObject();
setInterval(function() {
clear();
draw();
ground.draw(0, 325);
ground.draw(125,325)
}, 1000/FPS);
};
function myObject(){
this.draw = function drawground(groundx, groundy){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
//context.fillRect(xpos,ypos,100,100);
var img=new Image()
img.src="ground.png"
img.onload = function() {
context.drawImage(img,groundx,groundy)}
}
};
function jump()
{
var t=.1;
isJumping=true;
var jumpint= setInterval(function() {
yup = 12*t-(5*t*t);
ypos= ypos - yup;
t = t + .1
if(yup < 0)
{
isJumping = false;
isFalling = true;
clearInterval(jumpint);
jumpint = 0;
fall();
return;
}
}, 20);
}
function fall()
{
t=.10
var fallint= setInterval(function() {
ydown = (5*t*t);
ypos= ypos + ydown;
t = t + .1
if(ypos > 275)
{
isFalling == false;
clearInterval(fallint);
fallint = 0;
return;
}
}, 20);
}
function changex(x){
xpos = xpos + (x);
//clear();
//draw();
}
function changey(y){
ypos = ypos + (y);
//clear();
//draw();
}
function draw(){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
var img=new Image()
img.src="character.png"
img.onload = function() {
context.drawImage(img,xpos,ypos)}
}
function clear(){
var canvas = document.getElementById('canvas')
var context = canvas.getContext('2d');
context.clearRect(0,0, canvas.width, canvas.height);
}
document.onkeydown = function(event) {
var keyCode;
if(event == null)
{
keyCode = window.event.keyCode;
}
else
{
keyCode = event.keyCode;
}
switch(keyCode)
{
// left
case 37:
//left
changex(-5);
break;
// up
case 38:
// action when pressing up key
jump();
break;
// right
case 39:
// action when pressing right key
changex(5);
break;
// down
case 40:
// action when pressing down key
changey(5);
break;
default:
break;
}
}
</script>
So, as you can see I'm creating two objects so far, and the player stops falling at any arbitrary point. I feel collisions at this stage wont be too difficult, but once I start adding more I feel it's going to get more difficult. I'm not going to be using the instance of the object with the same image for each instance of the object, so at some point I'm going to change the myobject function to be able to accept the image as a parameter, and then checking for collisions will be a bit more tricky. I also plan on making this into a side scroller, so once one end the map is hit it changes into the next area, which is going to cause performance issues. If I'm checking for collisions on every single object in the entire game every interval I imagine things are going to get slow. What is going to be the best way to limit the number of collisions checked? Obviously, if the object isn't on screen there is no need to check it, but is there a way to limit that. I'm thinking of making an array for every frame of the game, and filling that array with it's objects. Then, only check the array the of the frame the player is currently in. Is this feasible or still going to cause too many issues? Any help is greatly appreciated.
If you want pixel perfect collisions, I have some plain javascript code that worked for me with canvas2d rendering context.
function collide(sprite, sprite2, minOpacity=1) {
// Rectangular bounding box collision
if (sprite.x < sprite2.x + sprite2.width && sprite.x + sprite.width > sprite2.x && sprite.y < sprite2.y + sprite2.height && sprite.y + sprite.height > sprite2.y) {
// Finds the x and width of the overlapping area
var overlapX = (this.rect.x > other.rect.x) ? [this.rect.x, (other.rect.x + other.rect.width) - this.rect.x + 1] : [other.rect.x, (this.rect.x + this.rect.width) - other.rect.x + 1];
// Finds the y and height of the overlapping area
var overlapY = (this.rect.y + this.rect.height > other.rect.y + other.rect.height) ? [this.rect.y, (other.rect.y + other.rect.height) - this.rect.y + 1] : [other.rect.y, (this.rect.y + this.rect.height) - other.rect.y + 1];
// Creates a canvas to draw sprite.image to
var spriteImageCanvas = new OffscreenCanvas(overlapX[0] + overlapX[1], overlapY[0] + overlapY[1]);
var spriteImageCanvasContext = spriteImageCanvas.getContext("2d");
// Draws sprite.image to spriteImageCanvasContext
spriteImageCanvasContext.drawImage(this.image, sprite.x, sprite.y, sprite.width, sprite.height);
// Creates a canvas to draw sprite2.image to
var sprite2ImageCanvas = new OffscreenCanvas(overlapX[0] + overlapX[1], overlapY[0] + overlapY[1]);
var sprite2ImageCanvasContext = otherImageCanvas.getContext("2d");
// Draws sprite2.image to sprite2ImageCanvasContext
sprite2ImageCanvasContext.drawImage(sprite2.image, sprite2.x, sprite2.y, sprite2.width, sprite2.height);
// Loops through the x coordinates in the overlapping area
for (var x = overlapX[0]; x <= overlapX[0] + overlapX[1]; x++) {
// Loops through the y coordinates in the overlapping area
for (var y = overlapY[0]; y <= overlapY[0] + overlapY[1]; y++) {
if (/* Checks if the pixel at [x, y] in the sprite image has an opacity over minOpacity input */ thisImageCanvasContext.getImageData(x, y, 1, 1).data[3] >= minOpacity && /* Checks if the pixel at [x, y] in the sprite2 image has an opacity over minOpacity input */ otherImageCanvasContext.getImageData(x, y, 1, 1).data[3] >= minOpacity) {
return true;
};
};
};
};
}
Or if you just want rectangular collision, use the first if statement in the function.
I start on KineticJS (and on Canvas) and i'm creating a small game for learn...
Right now, I have just 2 layers :
First with a map composed by Kinetic.Image
Second with the last time who game as draw.
I want refresh display X time per second but after 20 or 30 times the game are really slow.. And it's the same when I flood event click ( who launch the draw function too)...
Moreover, i can see in the second layer : the old text are never clean, the new are added on top... :/
var stage;
var layers = {};
var CANEVAS_WIDTH = 800;
var CANEVAS_HEIGHT = 600;
var MAP_WIDTH = 10;
var MAP_HEIGHT = 10;
var MAPPING_WIDTH = 150;
var MAPPING_HEIGHT = 88;
var LEFT_X = 0;
var LEFT_Y = MAP_WIDTH*MAPPING_HEIGHT/2;
var TOP_X = MAP_WIDTH/2*MAPPING_WIDTH;
var TOP_Y = 0;
var VIEW_X = 0;
var VIEW_Y = 0;
var CURSOR_X = 6;
var CURSOR_Y = 0;
var images = {};
function loadImages(sources, callback)
{
var loadedImages = 0;
var numImages = 0;
// get num of sources
for (var src in sources)
numImages++;
for (var src in sources)
{
images[src] = new Image();
images[src].onload = function(){
if (++loadedImages >= numImages)
callback();
};
images[src].src = sources[src];
}
}
function getMouseInfo(mousePos)
{
var info = {screen_x : mousePos.x,
screen_y : mousePos.y,
mouse_x : mousePos.x+VIEW_X,
mouse_y : mousePos.y+VIEW_Y-LEFT_Y,
onMap : 0,
map_x : -1,
map_y : -1};
map_x = -(info.mouse_y - ((LEFT_Y * info.mouse_x) / TOP_X)) / MAPPING_HEIGHT;
map_y = -(-info.mouse_y - ((LEFT_Y * info.mouse_x) / TOP_X)) / MAPPING_HEIGHT;
if(map_x >= 0 && map_x < MAP_WIDTH && map_y >= 0 && map_y < MAP_HEIGHT)
{
info.map_y = parseInt(map_y);
info.map_x = parseInt(map_x);
info.onMap = 1;
}
return info;
}
function draw()
{
drawMap();
drawFPS();
stage.add(layers.mapLayer);
stage.add(layers.fpsLayer);
}
function drawFPS()
{
layers.fpsLayer.clear();
var fps = new Kinetic.Shape(function(){
var date = new Date();
var time = date.getTime();
var context = this.getContext();
context.beginPath();
context.font = "12pt Calibri";
context.fillStyle = "red";
context.fillText("FPS : "+time, 10, 20);
});
layers.fpsLayer.add(fps);
}
function drawMap()
{
var x=0,y=0;
layers.mapLayer.clear();
var s = new Kinetic.Shape(function(){
var context = this.getContext();
context.beginPath();
context.rect(0, 0, CANEVAS_WIDTH, CANEVAS_HEIGHT);
context.fillStyle = "#000";
context.fill();
context.closePath();
});
layers.mapLayer.add(s);
for(x=0; x<MAP_WIDTH; x++)
for(y=0;y<MAP_HEIGHT; y++)
{
var img = new Kinetic.Image({
image: ((x==CURSOR_X && y==CURSOR_Y)?images.testMapCursor:images.testMap)
});
img.x = x*MAPPING_WIDTH/2 + y*MAPPING_WIDTH/2 - VIEW_X;
img.y = (MAP_WIDTH-1)*MAPPING_HEIGHT/2 - x*MAPPING_HEIGHT/2 + y*MAPPING_HEIGHT/2 - VIEW_Y;
layers.mapLayer.add(img);
}
}
function changeCursorPosition(cursor_x, cursor_y)
{
CURSOR_X = cursor_x;
CURSOR_Y = cursor_y;
draw();
}
function initStage()
{
layers.mapLayer = new Kinetic.Layer();
layers.fpsLayer = new Kinetic.Layer();
draw();
}
/*
* INIT
*/
window.onload = function(){
stage = new Kinetic.Stage("container", <?=CANEVAS_WIDTH;?>, <?=CANEVAS_HEIGHT;?>);
stage.on("mousemove", function(){
var mouseInfo = getMouseInfo(stage.getMousePosition());
if(mouseInfo.onMap)
document.body.style.cursor = "pointer";
else
document.body.style.cursor = "default";
});
stage.on("mousedown", function(){
var mouseInfo = getMouseInfo(stage.getMousePosition());
if(mouseInfo.onMap)
changeCursorPosition(mouseInfo.map_x, mouseInfo.map_y);
});
var sources = {
testMap : "testMap.png",
testMapCursor : "testMapCursor.png"
};
loadImages(sources, initStage);
};
Sorry, my english are realy bad.
Thank all.
I know someone who is trying out KineticJS. I haven't used it myself, so I apologize that I cannot provide more specific help.
Unfortunately, it is very difficult to get good performance with canvas, and it depends greatly on the browser. Last I checked, Opera 12 and IE 9 performed significantly faster than other browsers, since their 2D rendering is 3D accelerated (using OpenGL and Direct3D, respectively)
I am not sure if this applies to KineticJS, but one technique you can use to improve performance with canvas is to use multiple canvas elements, and transform their positions rather than blitting on a single surface.
I've been pretty happy with the results I've gotten using Jeash, which is wired into NME's command-line tools. The development is similar to working with Flash, but it will create an HTML5 Canvas application using your code. The same application will also be able to publish to Windows, Mac, Linux, iOS, Android, webOS and Flash, as either native C++ and OpenGL, or as SWF bytecode. This gives you a lot of options for providing the best experience for each user.
http://www.haxenme.org