I have created the following code to make the player move towards the mouse, JSFiddle
Code
var mouseX = 0, mouseY = 0;
$(document).mousemove(function(event) {
mouseX = event.pageX;
mouseY = event.pageY;
});
$(function(){
var $map = $(".map");
var $player = $('.player');
var centerPlayerX = $player.offset().left + $player.width() / 2;
var centerPlayerY = $player.offset().top + $player.height() / 2;
var movingInterval;
$('.map').on('mousedown', function(event){
movingInterval = setInterval(function(){
var clickedPosX = mouseX,
clickedPosY = mouseY;
var currentMapPositionX = parseFloat($map.css("background-position-x"));
var currentMapPositionY = parseFloat($map.css("background-position-y"));
var moveMapX = currentMapPositionX - clickedPosX/100 + centerPlayerX/100;
var moveMapY = currentMapPositionY - clickedPosY/100 + centerPlayerY/100;
$map.css({ "background-position-x": `${moveMapX}px`, "background-position-y": `${moveMapY}px` });
var angle = getDirection(centerPlayerX, clickedPosY, clickedPosX, centerPlayerY);
$player.find('.ship').css('transform', 'rotate('+angle+'deg)');
}, 10);
}).on('mouseup', function() {
clearInterval(movingInterval);
});;
});
function getDirection(x1, y1, x2, y2){
var dx = x2 - x1;
var dy = y2 - y1;
return Math.atan2(dx, dy) / Math.PI * 180;
}
Problem
var moveMapX = currentMapPositionX - clickedPosX/100 + centerPlayerX/100;
var moveMapY = currentMapPositionY - clickedPosY/100 + centerPlayerY/100;
Problem is that I want to move the player at a set speed (px*ps). Currently the player will increase in speed when the player moves his mouse further away from the image. I currently have no idea on how I would move the player at a set speed. Therefore I would need to remove clickedPosY/X somehow and change it to a static speed but the image should still move towards were the mouse is, which is the problem.
So, let's assume you have a speed constant; what you want to do is to project the speed constant along the movement vector. The easiest way to do that is to scale the components of the offset to the click position by the ratio of the speed to the distance between the click point and the movement base:
var distanceX = clickedPosX - centerPlayerX;
var distanceY = clickedPosY - centerPlayerY;
var magnitude = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
var deltaX = distanceX * speed / magnitude;
var deltaY = distanceY * speed / magnitude;
var moveMapX = currentMapPositionX - deltaX;
var moveMapY = currentMapPositionY - deltaY;
Updated fiddle
Related
i have a canvas, inside of which i have a board/grid. When a user highlights their mouse over an intersection of the grid, i want it to show where their game peice will go. This worked perfectly fine when the board was the exact size of the canvas. I made it abit smaller by x all the way round.
So as you can see in the picture below, the green shows the canvas and the grid is the board. I put my cursor at the very bottom right corner of the green to show when it triggers. The only one that works fine is the middle one because regardless how big i make the board, the middle will always be the middle.
Any easy fix would just be to make the area with the mouseover event, the dimensions of the board instead of the canvas but the event listener is on the canvas. My code is below the image
Variables:
var canvas = document.getElementById("game-canvas");
var context = canvas.getContext("2d");
var boardSize = 13;
var border = canvas.width / 20;
var boardWidth = canvas.width - (border * 2);
var boardHeight = canvas.height - (border * 2);
var cellWidth = boardWidth / (boardSize - 1);
var cellHeight = boardHeight / (boardSize - 1);
var lastX;
var lastY;
Mouse over event:
canvas.addEventListener('mousemove', function(evt)
{
var position = getGridPoint(evt);
if ((position.x != lastX) || (position.y != lastY))
{
placeStone((position.x * cellWidth) + border, (position.y * cellWidth) + border, 'rgba(0, 0, 0, 0.2)');
}
lastX = position.x;
lastY = position.y;
});
Gets the point on the grid and converts that into a number 0 - 13 (in this case)
function getGridPoint(evt)
{
var rect = canvas.getBoundingClientRect();
var x = Math.round((evt.clientX-rect.left)/(rect.right-rect.left)*boardWidth);
var y = Math.round((evt.clientY-rect.top)/(rect.bottom-rect.top)*boardHeight);
var roundX = Math.round(x / cellWidth);
var roundY = Math.round(y / cellHeight);
return {
x: roundX,
y: roundY
};
}
And finally draws the piece on the board:
function placeStone(x, y, color)
{
var radius = cellWidth / 2;
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = color;
context.fill();
context.lineWidth = 5;
}
I left a couple bits out like how the grid refreshs so its not a string of circles following your mouse and stuff, to keep it as short as i can, im hoping its just a simple asnwer and nobody needs to recreate it but if you do i can include the function that refreshes the grid and draws everything. Thankyou for any advice
To get the position relative to a box
// just as an example w,h are width and height
const box = { x : 10, y : 10, w : 100, h : 100 };
// mouse is the mouse coords and relative to the topleft of canvas (0,0);
var mouse.box = {}
mouse.box.x = mouse.x - box.x;
mouse.box.y = mouse.y - box.y;
Negative values for mouse.box x,y and values greater than box width and height have mouse outside.
For more convenience you can get the mouse normalize pos in the box
mouse.box.nx = mouse.box.x / box.w;
mouse.box.ny = mouse.box.y / box.h;
The coords for nx,ny are in the range 0-1 when inside or on the edge of the box;
If you want to have grid positions then define the grid
box.gridW = 10; // grid divisions width
box.gridH = 10; // grid divisions height
Then getting the grid pos of mouse
mouse.box.gx = Math.floor(mouse.box.nx * box.gridW);
mouse.box.gy = Math.floor(mouse.box.ny * box.gridH);
const ctx = canvas.getContext("2d");
const box = { x : 50,y : 10, w : 200, h : 200, gridW : 10, gridH : 10}
function drawGrid(){
var sx = box.w / box.gridW;
var sy = box.h / box.gridH;
var bx = box.x;
var by = box.y;
for(var y = 0; y < box.gridH; y ++){
for(var x = 0; x < box.gridW; x ++){
ctx.strokeRect(x * sx + bx, y * sx + by,sx,sy);
}
}
if(mouse.box){
if(mouse.box.nx >= 0 && mouse.box.nx <= 1 &&
mouse.box.ny >= 0 && mouse.box.ny <= 1){
ctx.fillRect(mouse.box.gx * sx + bx, mouse.box.gy * sx + by,sx,sy);
}
}
}
const mouse = {};
canvas.addEventListener("mousemove",(e)=>{
mouse.x = e.pageX;
mouse.y = e.pageY;
});
function updateMouse(){
if(!mouse.box){
mouse.box = {};
}
mouse.box.x = mouse.x - box.x;
mouse.box.y = mouse.y - box.y;
mouse.box.nx = mouse.box.x / box.w;
mouse.box.ny = mouse.box.y / box.h;
mouse.box.gx = Math.floor(mouse.box.nx * box.gridW);
mouse.box.gy = Math.floor(mouse.box.ny * box.gridH);
var p = 20;
ctx.fillText("x : " + mouse.x,box.x+box.w+10,p); p+= 14;
ctx.fillText("y : " + mouse.y,box.x+box.w+10,p); p+= 20;
ctx.fillText("Box relative",box.x+box.w+10,p); p+= 14;
ctx.fillText("x : " + mouse.box.x,box.x+box.w+10,p); p+= 14;
ctx.fillText("y : " + mouse.box.y,box.x+box.w+10,p); p+= 14;
ctx.fillText("nx : " + mouse.box.nx,box.x+box.w+10,p); p+= 14;
ctx.fillText("ny : " + mouse.box.ny,box.x+box.w+10,p); p+= 14;
ctx.fillText("gx : " + mouse.box.gx,box.x+box.w+10,p); p+= 14;
ctx.fillText("gy : " + mouse.box.gy,box.x+box.w+10,p); p+= 14;
}
function mainLoop(time){
if(canvas.width !== innerWidth || canvas.height !== innerHeight){ // resize canvas if window size has changed
canvas.width = innerWidth;
canvas.height = innerHeight;
}
ctx.setTransform(1,0,0,1,0,0); // set default transform
ctx.clearRect(0,0,canvas.width,canvas.height); // clear the canvas
updateMouse();
drawGrid();
requestAnimationFrame(mainLoop);
}
requestAnimationFrame(mainLoop);
canvas {
position : absolute;
top : 0px;
left : 0px;
}
<canvas id=canvas><canvas>
I want to have 2 fakes cursors, i tried this one for creating 2 cursors.
// get the fake cursor by is id
var xyMirror = document.getElementById('fakeCursor');
var xyMirror2 = document.getElementById('fakeCursor2');
// listen for mouse movements
window.onmousemove = function(event) {
// get the user's mouse position
var X = event.clientX;
var Y = event.clientY;
// get the browser window dimensions
windowHeight = window.innerHeight;
windowWidth = window.innerWidth;
// create an inversion of the mouse X, Y position
// subtract mouse X position from window width
// subtract mouse Y position from window height
var fakeX = windowWidth - X;
var fakeY = windowHeight - Y;
// use those numbers to update the fake cursor position
xyMirror.style.top = fakeY+'px';
xyMirror.style.left = fakeX+'px';
xyMirror2.style.top = 10 + fakeY+'px' ;
xyMirror2.style.left = 20 + fakeX+'px';
}
now their movement depend on original cursor,
my question is
How can move them randomly?
You can do some thing like that
// get the fake cursor by is id
var xyMirror = document.getElementById('fakeCursor');
var xyMirror2 = document.getElementById('fakeCursor2');
xyMirror.style.position = "absolute";
xyMirror2.style.position = "absolute";
var xMax = 0;var yMax = 0;
// listen for mouse movements
window.onmousemove = function(event) {
// Use event X and Y to set max value
if (event.clientX > xMax) xMax = event.clientX;
if (event.clientY > yMax) yMax = event.clientY;
// Random position for fakeCursor
xyMirror.style.left = getRandomArbitrary(0, xMax) +'px';
xyMirror.style.top = getRandomArbitrary(0, yMax)+'px';
// Random position for fakeCursor2
xyMirror2.style.left = getRandomArbitrary(0, xMax) +'px';
xyMirror2.style.top = getRandomArbitrary(0, yMax) +'px';
}
function getRandomArbitrary(min, max) {
return Math.random() * (max - min) + min;
}
<div id="fakeCursor">fake1</div>
<div id="fakeCursor2">fake2</div>
So I have a canvas with an isometric tile map drawn on it, which looks perfect.
In the event listener at the bottom of the script, I grab the cursor's coordinates inside the canvas. How could I find out which tile the cursor is hovering over?
var cs = document.getElementById('board');
var c = cs.getContext("2d")
var gridWidth=100
var gridHeight=50
var tilesX = 12, tilesY = 12;
var spriteWidth=gridWidth
var spriteHeight=img.height/img.width*gridWidth
cs.width = window.innerWidth //spriteWidth*10
cs.height = window.innerHeight //spriteHeight*10
var ox = cs.width/2-spriteWidth/2
var oy = (tilesY * gridHeight) / 2
window.onresize=function(){
cs.width = window.innerWidth //spriteWidth*10
cs.height = window.innerHeight //spriteHeight*10
ox = cs.width/2-spriteWidth/2
oy = (tilesY * gridHeight) / 2
draw()
}
draw();
function renderImage(x, y) {
c.drawImage(img, ox + (x - y) * spriteWidth/2, oy + (y + x) * gridHeight/2-(spriteHeight-gridHeight),spriteWidth,spriteHeight)
}
function draw(){
for(var x = 0; x < tilesX; x++) {
for(var y = 0; y < tilesY; y++) {
renderImage(x,y)
}
}
}
cs.addEventListener('mousemove', function(evt) {
var x = evt.clientX,
y = evt.clientY;
console.log('Mouse position: ' + x + ',' + y);
}, false);
Sorry for pasting such lengthy code, but all of it is there just to lay the isometric grid.
EDIT: Also, how could I get the top left coordinates of the tile image to relay it?
Assuming you've arranged your tiles where the leftmost column and topmost row are zero:
var column = parseInt(mouseX / tileWidth);
var row = parseInt(mouseY / tileHeight);
BTW, if you eventually move your canvas off the top-left of the page then you must adjust your mouse coordinates by the canvas offset.
Here's an example of how to calculate mouse position:
// references to the canvas element and its context
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// get the offset position of the canvas on the web page
var BB=canvas.getBoundingClientRect();
var offsetX=BB.left;
var offsetY=BB.top;
// listen for mousedown events
canvas.onmousedown=handleMousedown;
function handleMousedown(e){
// tell the browser we will handle this event
e.preventDefault();
e.stopPropagation();
// calculate the mouse position
var mouseX=e.clientX-offsetX;
var mouseY=e.clientY-offsetY;
}
in the jsfiddle below im trying to get the yellow and red circles to initially appear in the center, as opposed to moving to the cursor's initial assumed position - which is (0,0) as the cursor is not yet in the actual screen of the page (if I'm guessing correctly).
http://jsfiddle.net/fhmkf/220/
Is there a way I can define the initial placement of the cursor - that is when calculating (window).mousemove(function(e){... - particularly the e.pageX and e.pageY?
The js looks like so:
var Circle = function(container, follower, r){
var center = {
x: $(container).width()/2 - r,
y: $(container).height()/2 - r
};
var distanceThreshold = $(container).width()/2 - r;
var mouseX = 0, mouseY = 0;
$(window).mousemove(function(e){
var d = {
x: e.pageX - center.x,
y: e.pageY - center.y
};
var distance = Math.sqrt(d.x*d.x + d.y*d.y);
if (distance < distanceThreshold) {
mouseX = e.pageX;
mouseY = e.pageY;
} else {
mouseX = d.x / distance * distanceThreshold + center.x;
mouseY = d.y / distance * distanceThreshold + center.y;
}
});
// cache the selector
var follower = $(follower);
var xp = 0, yp = 0;
var loop = setInterval(function(){
// change 12 to alter damping higher is slower
xp += (mouseX - xp) / 2;
yp += (mouseY - yp) / 2;
follower.css({left:xp, top:yp});
}, 30);
};
var c1 = new Circle(".container", "#follower", 15);
var c2 = new Circle(".container2", "#follower2", 25);
I'm trying to get the jsfiddle sample below to make the yellow circle div follow the mouse but be constraint to a circle as opposed to a square (div).
http://jsfiddle.net/fhmkf/
The JS code looks like so:
var mouseX = 0, mouseY = 0, limitX = 150-15, limitY = 150-15;
$(window).mousemove(function(e){
mouseX = Math.min(e.pageX, limitX);
mouseY = Math.min(e.pageY, limitY);
});
// cache the selector
var follower = $("#follower");
var xp = 0, yp = 0;
var loop = setInterval(function(){
// change 12 to alter damping higher is slower
xp += (mouseX - xp) / 12;
yp += (mouseY - yp) / 12;
follower.css({left:xp, top:yp});
}, 30);
I understand the structure and methodology of the code, just not too familiar with the syntax!
Where is the best place to update the limitX/Y and throw in the extra radius, distance variables?
You can do this by computing the distance away from the center of the circle (2D distances are computed with Math.sqrt(x * x + y * y)). Then check to see if the distance is greater than the radius of the circle you'd like to constrain to. If it is, scale down the distance to match your constraining radius.
Here's the snippet:
var mouseX = 0, mouseY = 0, limitX = 150-15, limitY = 150-15;
var centerX = limitX / 2, centerY = limitY / 2;
var radius = centerX;
$(window).mousemove(function(e) {
var diffX = e.pageX - centerX;
var diffY = e.pageY - centerY;
// Get the mouse distance from the center
var r = Math.sqrt(diffX * diffX + diffY * diffY);
if (r > radius) {
// Scale the distance down to length 1
diffX /= r;
diffY /= r;
// Scale back up to the radius
diffX *= radius;
diffY *= radius;
}
mouseX = centerX + diffX;
mouseY = centerY + diffY;
});
And here's the complete code: http://jsfiddle.net/fhmkf/