Javascript Mouse Position location? - javascript

Im trying to build a game the objective is to hit the enimies that come out from the water by clicking on them, I have been trying to get a water jet come out of a statues mouth (which has sort of been succesful and can be seen here: http://mckenziedave.co.uk/client_files/html5_game/) however it is slighty off, I believe this is because of the game being within the game screen (div id="gamefiled"). How can I take this into factor within the JS script (script below)
var flame,
sourceX = 780,
sourceY = 215;
window.onload = function() {
flame = document.getElementById('flame');
game.addEventListener('click', function(e) {
var targetX = e.pageX,
targetY = e.pageY,
deltaX = targetX - sourceX,
deltaY = targetY - sourceY,
rad = Math.atan2(deltaY, deltaX),
deg = rad * (180 / Math.PI),
length = Math.sqrt(deltaX*deltaX+deltaY*deltaY);
fire(deg,length);
}, false);
};
function fire(deg,length) {
flame.style.opacity = 1;
flame.style.transform = 'rotate(' + deg + 'deg)'
flame.style.width = length + 'px';
setTimeout(function() {
flame.style.opacity = 0;
},780);
};
Cheers

You have to determine the offset of the div id="gamefiled", relative to the browser window in your click event and substract it from the mouse position.

I've tried playing your game and I clicked some crabs but no hits. This is probably a math error since players play the game on different resolutions on different devices. Not to mention the pixel size problem where PCs, tablets and phones don't have universal pixel sizes.
Have you tried obtaining coordinates like this:
http://www.w3schools.com/jsref/event_clientx.asp
var x = event.clientX;
var y = event.clientY;
For drawing lines (precise) I'd recommend something like a Bresenham algorithm but this is just my opinion.
You can also try a much more simple solution like this:
http://www.w3schools.com/tags/canvas_lineto.asp
You can use canvas for drawing lines like so:
function drawLine (x_start, y_start, x_end, y_end) {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.moveTo(x_start, y_start);
ctx.lineTo(x_end, y_end);
//set line width and color
ctx.lineWidth = 10;
ctx.strokeStyle = '#000';
ctx.stroke();
}
I rewrote this solution from w3schools.com.

Related

How to fix HTML canvas element and its coordinates across different screen sizes?

I've spent the past two weeks making a game with a few friends using the HTML canvas tag and JavaScript. None of us have any prior experience with a project of this scale, so considerations of browser/screen-size compatibility wasn't on our minds. The game runs and looks fine on our laptops (all have similar screen sizes), but it looked bad when we sent a link to another friend whose screen size differs greatly from what we had in mind.
To discuss the layout of the game in greater detail, it's set up with the canvas element acting as the actual game with a series of divs sitting below the canvas to represent things like a dialogue box or the pause menu (only one of these divs is shown at a time with the others being hidden).
The game is gridbased in that every object, from the wall tiles to enemies, has a size relative to some constant blockWidth (defined below) which itself is relative to the desired amount of squares on-screen, numSquares (also defined below).
Changing the canvas's height and width properties in JavaScript did successfully fix a ratio of the canvas size and ensure that the wall and floor textures loaded in their proper place. The player and other NPCs, however, appear at odd places onscreen, sometimes not showing up onload at all.
I'm not quite sure what to attribute this problem to, but I think it has something to do with canvas' coordinate system not mixing well with the admittedly poorly executed block system we put in place.
//some relevant misc variables
var numSquares = 30;
const blockWidth = 1132 / numSquares * 0.75;
screen.width = 1132;
screen.height = 600;
//some relevant player variables
stats.x = 678;
stats.y = 600;
stats.width = blockWidth * 3 * 0.37;
stats.height = blockWidth * 3;
Again, I suspect that the problem has something to do with the fact that the tiles that render correctly (i.e. wall and floor textures) have their coordinates in terms of blockWidth whereas the tiles that render incorrectly (i.e. the player) have their coordinates as regular numbers.
Is there a way to go about adjusting our game for different monitor sizes other than revamping the entire coordinate system?
try this meta which will solve cross platform screen (laptop, Computer, Tab, Mobile)problem:
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
Your main problem is using hard coded values for your variables. If stats.x = 678;and your screen is 480px wide (for example), the stats will fall out the screen.
Also: screen.width and screen.height is a hardcoded number. Probably what you need is something like: screen.width = window.innerWidth and screen.height = window.innerHeight
What I'm missing from your relevant misc variables: In your code you have this:
var numSquares = 30;
const blockWidth = 1132 / numSquares * 0.75;
Where 1132 is in fact the screen.width. This means that you don't have a grid as you say. This means you have only 1 (one) row of squares. Alternatively you have 30 squares per row, and in this case you have a grid.
Also, it would be nice to see how you draw your grid. I would do it like this:
for (let y = 0; y < ch; y += cw / numSquares) {
for (let x = 0; x < cw; x += cw / numSquares) {
let o = { x: x, y: y, w: blockWidth, h: blockWidth };
drawRect(o);
}
}
Where drawRect is a custom function to draw a rect. Since your blockWidth = screen.width / numSquares * 0.75; I'm assuming you let a gap between rects, but this is assuming.
As I've commented before you can't give your stats hard coded values. You will need to calculate these values in function of your grid cells. For example your stats.x may be the x of the 5'th column of your grid and the stats.y may be the y of the 3-rd row. But this is again assuming and I may be wrong.
Next comes a code example. Please take a look and let me know if this is what you need.
const screen = document.getElementById("canvas");
const ctx = screen.getContext("2d");
let cw = (screen.width = window.innerWidth);
let ch = (screen.height = window.innerHeight);
let stats = {};
let numSquares = 30;
let blockWidth;
generateGrid();
function Init() {
// a function to re-generate the grid and re-draw the stats when screen.width and/or screen.height changed
cw = screen.width = window.innerWidth;
ch = screen.height = window.innerHeight;
generateGrid();
drawStats(5, 3);
}
// recalculate everything on resize
setTimeout(function() {
Init();
addEventListener("resize", Init, false);
}, 15);
// some useful functions
function drawRect(o) {
ctx.beginPath();
ctx.fillStyle = "rgba(0,0,0,.05)";
ctx.fillRect(o.x, o.y, o.w, o.h);
}
function drawStats(x, y) {
stats.x = x * cw / numSquares;
stats.y = y * cw / numSquares;
stats.width = blockWidth * 3 * 0.37;
stats.height = blockWidth * 3;
ctx.fillStyle = "red";
ctx.beginPath();
ctx.fillRect(stats.x, stats.y, stats.width, stats.height);
}
function generateGrid() {
blockWidth = cw / numSquares * 0.75;
for (let y = 0; y < ch; y += cw / numSquares) {
for (let x = 0; x < cw; x += cw / numSquares) {
let o = { x: x, y: y, w: blockWidth, h: blockWidth };
drawRect(o);
}
}
}
*{margin:0;padding:0}
<canvas id="canvas"></canvas>
If this is not what you need, please update your question, and add more explanations and more code.

Rotating One Object Around Another In createJS/easelJS

In easelJS, what is the best way to rotate an object around another? What I'm trying to accomplish is a method to rotate the crosshair around the circle pictured below, just like a planet orbits the sun:
I've been able to rotate objects around their own center point, but am having a difficult time devising a way to rotate one object around the center point of a second object. Any ideas?
Might make sense to wrap content in a Container. Translate the coordinates so the center point is where you want it, and then rotate the container.
To build on what Lanny is suggesting, there may be cases where you don't want to rotate the entire container. An alternative would be to use trigonometric functions and an incrementing angle to calculate the x/y position of the crosshair. You can find the x/y by using an angle (converted to radians) and Math.cos(angleInRadians) for x and Math.sin(angleInRadians) for y, the multiply by the radius of the orbit.
See this working example for reference.
Here's a complete snippet.
var stage = new createjs.Stage("stage");
var angle = 0;
var circle = new createjs.Shape();
circle.graphics.beginFill("#FF0000").drawEllipse(-25, -25, 50, 50).endFill();
circle.x = 100;
circle.y = 100;
var crosshair = new createjs.Shape();
crosshair.graphics.setStrokeStyle(2).beginStroke("#FF0000").moveTo(5, 0).lineTo(5, 10).moveTo(0, 5).lineTo(10, 5).endStroke();
stage.addChild(circle);
stage.addChild(crosshair);
createjs.Ticker.addEventListener("tick", function(){
angle++;
if(angle > 360)
angle = 1;
var rads = angle * Math.PI / 180;
var x = 100 * Math.cos(rads);
var y = 100 * Math.sin(rads);
crosshair.x = x + 100;
crosshair.y = y + 100;
stage.update();
});
Put another point respect to origin point with the same direction
var one_meter = 1 / map_resolution;
// get one meter distance from pointed points
var extra_x = one_meter * Math.cos(temp_rotation);
var extra_y = one_meter * Math.sin(-temp_rotation);
var new_x = mapXY.x + extra_x;
var new_y = mapXY.y + extra_y;
var home_point = new createjs.Shape().set({ x: new_x, y: new_y });
home_point.graphics.beginFill("Blue").drawCircle(0, 0, 10);
stage.addChild(home_point);
stage.update();

How to add the vertical parallel lines in the rectangle?

I want to add the vertical lines when I draw rectangle. The no of lines is dependent on the user and can be read from the text box.
I know the logic but somehow I am not able to get the answer.
I am calculating the width of the rectangle and then diving the width on the basis of no of vertical lines.
Click the checkbox near rectangle and draw using mouse down events
Please let me know where I am going wrong.
function PlotPitch()
{
var iPatches = document.getElementById('txtPatchCount').value;
var iTop = mySel.y;
var iBottom = mySel.y + mySel.h;
var iLeft = mySel.x;
var iX = iLeft;
canvas = document.getElementById('canvas2');
context = canvas.getContext('2d');
for (var iPatch=1; iPatch<iPatches; ++iPatch) {
iX = iLeft + iPatch*mySel.w/iPatches;
context.moveTo(iX, iTop);
context.lineTo(iX, iBottom);
}
context.lineWidth=0.25;
context.stroke();
}
http://jsfiddle.net/K5wcs/4/
If I am adding this the code is breaking and I am not able to draw anything.
What you should do if you have 'strange' behaviour is to separate concerns, so in this case that could be by creating a function that you test separately, which draws the lines, then once it's tested ok, plug it in code by just calling the function. You should find quickly.
So begin by testing this :
function drawLines(Context, mySel, iPatches) {
var iTop = mySel.y;
var iBottom = mySel.y + mySel.h;
var iLeft = mySel.x;
var iX = iLeft;
var colWidth = mySel.w/iPatches ;
for (var iPatch=1; iPatch<iPatches; ++iPatch) {
iX += colWidth;
Context.moveTo(iX, iTop);
Context.lineTo(iX, iBottom);
}
Context.lineWidth=0.25;
Context.stroke();
}
Good luck.

Rotate links along a circle

I'm trying to make a website with links rotating around a circle. (Something like this) http://i.imgur.com/i9DzASw.jpg?1 with the different images and texts leading to different urls. The image is one unified image that also rotates as the user scrolls. Is there anyway I can do this? Also is there a way to make the page height infinite so that the user never gets to the bottom of the page as they scroll? Thanks!
Here's the jsfiddle and the code that allows for the rotation of the image.
http://jsfiddle.net/kDSqB/135/
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height();
$(window).scroll(function () {
$cog.css({
'transform': 'rotate(' + ($body.scrollTop() / bodyHeight * 30000) + 'deg)'
});
});
http://jsfiddle.net/Fezjh/1/
I have coloured the div to make it easier to understand how to do it - but you need to think carefully about compatiblity issues (older browsers etc.)
Just remove the background colour to get your desired effect.
A better way would be to split the image into divs and put those divs up against each other.
check http://www.gdrtec.co.uk - you will notice 4 images butted up against each other form the start menu - it would be easy to rotate the containing div and everything will still work as it should.
The code below is just for demonstration purposes and should be replaced with more robust solution.
$('#link1').click(function(){
alert("openURL");
});
Also consider making sure people don't have to rely on javascript for your site to work.
See this : http://jsfiddle.net/F8GTP/, and this final version : http://jsfiddle.net/MjnxP/.
Use WheelEvent like this for infinite scroll :
var $cog = $('#cog'),
$body = $(document.body),
bodyHeight = $body.height(),
rotate = 1;
var wheelEvent = function (event) {
var delta = 0;
if (event.wheelDelta) { delta = event.wheelDelta/120; } else if (event.detail) { delta = -event.detail/3; }
if (delta) {
rotate += delta * 1.12; //<== Increase speed.
console.log(rotate, delta);
$cog.css({ 'transform': 'rotate(' + rotate + 'deg)'});
}
if (event.preventDefault) { event.preventDefault(); }
event.returnValue = false;
};
window.onmousewheel = wheelEvent;
if (window.addEventListener) { window.addEventListener('DOMMouseScroll', wheelEvent, false); }
For detect link use canvas with "collision image", and this is final version :
$cog.click(function(e) {
if (rotate !== lastrotate) {
//http://creativejs.com/2012/01/day-10-drawing-rotated-images-into-canvas/
context.save();
context.translate((image.width/2), (image.height/2));
context.rotate(rotate * Math.PI/180);
context.drawImage(image, -(image.width/2), -(image.height/2));
context.restore();
lastrotate = rotate;
}
var x = e.pageX, y = e.pageY;
console.log(x, y);
var color = context.getImageData(x, y, 1, 1).data;
// context.fillRect(x-5, y-5, 1+10, 1+10); <== See cursor position
if (color[0] == 255 && color[1] == 255 && color[2] == 255) { //white = rgb(255, 255, 255);
alert("click");
}
});
function setPixel(imageData, x, y, r, g, b, a) {
index = (x + y * imageData.width) * 4;
imageData.data[index+0] = r;
imageData.data[index+1] = g;
imageData.data[index+2] = b;
imageData.data[index+3] = a;
}
var canvas = document.getElementById('canvas'),
context = canvas.getContext('2d'),
image = new Image(),
lastrotate = null;
image.onload = function(){
canvas.width = image.width;
canvas.height = image.height;
context.drawImage(image, 0, 0, image.width, image.height);
};
// http://i.imgur.com/UfjbW5l.png I use base64 for get image because else console return security error with "getImageData".
image.src = "data:image/png;base64,iVBORw0K...";
For "image.src", use your image in YOUR DOMAIN or use Base64 else this script return security error for convert image to base64 see : http://www.base64-image.de/.
If position of cog isn't (0, 0) replace actual line to this line :
var x_pos = 200, y_pos = 200; // No use .position() or .offset() for get this, or use parent element position.
var x = e.pageX - x_pos, y = e.pageY - y_pos;

Multiple rotation of the camera

I'm trying to do some simple camera rotation in WebGL app(using lesson 10 from Learning WebGL), but I'm definetly doing something wrong.. I mean the horizontal movement of camera seems good,movement with WASD seems also OK, but when I'm adding the vertical movement, in some points of the map, something goes wrong and the map starts to incline. Where is my mistake? (demo is here)
what I'm doing is:
function handleMouseMove(event) {
var canvas = document.getElementById("quak-canvas");
var newX = event.clientX;
var newY = event.clientY;
var newRotationMatrix = mat4.create();
mat4.identity(newRotationMatrix);
var deltaY = newY - lastMouseY;
mat4.rotate(newRotationMatrix, degToRad(deltaY / 40), [1, 0, 0]);
var deltaX = newX - lastMouseX;
horizontalAngle = (event.pageX/(canvas.width/2))*180;
mat4.rotate(newRotationMatrix, degToRad(deltaX / 3.75), [0, 1, 0]);
mat4.multiply(newRotationMatrix, moonRotationMatrix, moonRotationMatrix);
lastMouseX = newX
lastMouseY = newY;
window.moveBy(10, 10);
}
I think there is some translate is missing or something like, but I have tried some combinations but it wasn't successfull..
Thanks a lot
Serhiy.
First off, let me say that you're demo actually looks okay to me. Maybe it's a side effect of the dampened vertical rotation, but I don't see anything that looks too terribly off. Your code looks okay too for the most part. I think the core of your problem may be the matrix multiply at the end. The fact that you're always building off the previous frame's results can lead to some complications.
In my FPS movement code I re-calculate the view matrix every frame like so:
var viewMat = mat4.create();
mat4.identity(viewMat);
mat4.rotateX(viewMat, xAngle); // X angle comes from Y mouse movement
mat4.rotateY(viewMat, yAngle); // Y angle comes from X mouse movement
mat4.translate(viewMat, position);
The position is calculated when WASD are pressed like so:
var dir = vec3.create();
if (pressedKeys['W']) { dir[2] -= speed; }
if (pressedKeys['S']) { dir[2] += speed; }
if (pressedKeys['A']) { dir[0] -= speed; }
if (pressedKeys['D']) { dir[0] += speed; }
if (pressedKeys[32]) { dir[1] += speed; } // Space, moves up
if (pressedKeys[17]) { dir[1] -= speed; } // Ctrl, moves down
// Create an inverted rotation matrix to transform the direction of movement by
var cam = mat4.create();
mat4.identity(cam);
mat4.rotateY(cam, -yAngle);
mat4.rotateX(cam, -xAngle);
// Move the camera in the direction we are facing
mat4.multiplyVec3(cam, dir);
vec3.add(position, dir);
Hopefully that helps you get a working solution for your own code!

Categories