How to stop multiple running mouse event functions - javascript

I want to resize squares drawn on canvas (created by clicking) with mouse by moving from corners. Should only resize selected square. I have four different functions for each corner, and after resizing from more than one corner functions keep executing. How to prevent this?
var isMouseDown = false;
var canvas;
var ctx, size;
$(document).ready(function() {
canvas = $('#area')[0];
ctx = canvas.getContext('2d');
$('#area').on('mousedown', canvasClick);
$('#area').on('mouseup', up);
});
function up(event) {
isMouseDown = false;
resizing = false;
console.log("up");
return;
}
function Square(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.isSelected = false;
}
var x, y;
function addSquare(event) {
x = event.pageX - canvas.offsetLeft;
y = event.pageY - canvas.offsetTop;
var size = parseInt(Math.random() * 81 + 49);
x -= size / 2;
y -= size / 2;
ctx.fillRect(x, y, size, size);
var square = new Square(x, y, size);
squares.push(square);
drawSquares();
}
var squares = new Array;
var previousSelectedSquare;
function drawSquares() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < squares.length; i++) {
var Square = squares[i];
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.rect(Square.x, Square.y, Square.size, Square.size);
ctx.strokeStyle = "black";
if (Square.isSelected) {
ctx.lineWidth = 4;
} else {
ctx.lineWidth = 1;
}
ctx.fill();
ctx.stroke();
}
}
function canvasClick(event) {
isMouseDown = true;
x = event.pageX - canvas.offsetLeft;
y = event.pageY - canvas.offsetTop;
if (squares.length < 1) {
addSquare(event);
return;
}
var Square;
if (previousSelectedSquare) {
var prevX = previousSelectedSquare.x;
var prevY = previousSelectedSquare.y;
size = previousSelectedSquare.size;
}
var change = 7;
if (((x <= prevX + size + change) && (x >= prevX + size - change)) ||
((x >= prevX - change) && (x <= prevX + change)))
if (((y <= prevY + size + change) && (y >= prevY + size - change)) ||
((y <= prevY + change) && (y >= prevY - change))) {
console.log("borders");
$('#area').on('mousemove', resize(event));
return;
}
for (var i = squares.length - 1; i >= 0; i--) {
Square = squares[i];
if ((x >= Square.x && x <= Square.x + Square.size) && (y <= Square.y + Square.size && y >= Square.y)) {
Square.isSelected = true;
if (previousSelectedSquare != null)
previousSelectedSquare.isSelected = false;
if (previousSelectedSquare == Square)
previousSelectedSquare = null;
else
previousSelectedSquare = Square;
drawSquares();
return;
}
if (i === 0) {
addSquare(event);
return;
}
}
return;
}
// Part that resizes
var resizing = false;
function resize(event) {
if (!isMouseDown)
return;
resizing = true;
x = (event.pageX - canvas.offsetLeft);
y = (event.pageY - canvas.offsetTop);
size = previousSelectedSquare.size;
var centreX = previousSelectedSquare.x + size / 2;
var centreY = previousSelectedSquare.y + size / 2;
if (x > centreX && y < centreY) {
topr = true;
//top right
$('#area').on('mousemove', topR);
return;
}
if (x < centreX && y < centreY) {
//top left
$('#area').on('mousemove', topL);
return;
}
if (x > centreX && y > centreY) {
//bot right
$('#area').on('mousemove', botR);
return;
}
if (x < centreX && y > centreY) {
//bot left
$('#area').on('mousemove', botL);
return;
}
resizing = false;
return;
}
function topR(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("top right");
size = previousSelectedSquare.size;
var yb = previousSelectedSquare.y + size;
if (parseInt(yb - (event.pageY - canvas.offsetTop)) < 60)
return;
previousSelectedSquare.size = parseInt(yb - (event.pageY - canvas.offsetTop));
previousSelectedSquare.y = parseInt(event.pageY - canvas.offsetTop);
drawSquares();
return;
}
function topL(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("top left");
x = previousSelectedSquare.x + previousSelectedSquare.size;
y = previousSelectedSquare.y + previousSelectedSquare.size;
if (parseInt(y - (event.pageY - canvas.offsetTop)) < 60)
return;
previousSelectedSquare.size = parseInt(y - (event.pageY - canvas.offsetTop));
previousSelectedSquare.y = parseInt(event.pageY - canvas.offsetTop);
previousSelectedSquare.x = parseInt(event.pageX - canvas.offsetLeft);
drawSquares();
return;
}
function botR(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("bot right");
size = previousSelectedSquare.size;
if ((event.pageX - canvas.offsetLeft - previousSelectedSquare.x + size) / 2 < 60)
return;
previousSelectedSquare.size = parseInt((event.pageX - canvas.offsetLeft - previousSelectedSquare.x + size) / 2);
drawSquares();
return;
}
function botL(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("bot left");
var xr = previousSelectedSquare.x + previousSelectedSquare.size;
if (xr - event.pageX - canvas.offsetLeft < 60)
return;
previousSelectedSquare.size = parseInt(previousSelectedSquare.x + previousSelectedSquare.size - (event.pageX - canvas.offsetLeft));
previousSelectedSquare.x = parseInt(event.pageX - canvas.offsetLeft);
drawSquares();
return;
}
#area {
margin-top: 0;
border: 4px black solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="area" width="1250" height="550"></canvas>

Using namespace events, after you check the position, remove other handlers then add the one for the current corner.
e.g.: $('#area').off('mousemove.botR').off('mousemove.topL').off('mousemove.botL').on('mousemove.topR', topR);
var isMouseDown = false;
var canvas;
var ctx, size;
$(document).ready(function() {
canvas = $('#area')[0];
ctx = canvas.getContext('2d');
$('#area').on('mousedown', canvasClick);
$('#area').on('mouseup', up);
});
function up(event) {
isMouseDown = false;
resizing = false;
console.log("up");
return;
}
function Square(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.isSelected = false;
}
var x, y;
function addSquare(event) {
x = event.pageX - canvas.offsetLeft;
y = event.pageY - canvas.offsetTop;
var size = parseInt(Math.random() * 81 + 49);
x -= size / 2;
y -= size / 2;
ctx.fillRect(x, y, size, size);
var square = new Square(x, y, size);
squares.push(square);
drawSquares();
}
var squares = new Array;
var previousSelectedSquare;
function drawSquares() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < squares.length; i++) {
var Square = squares[i];
ctx.beginPath();
ctx.fillStyle = "orange";
ctx.rect(Square.x, Square.y, Square.size, Square.size);
ctx.strokeStyle = "black";
if (Square.isSelected) {
ctx.lineWidth = 4;
} else {
ctx.lineWidth = 1;
}
ctx.fill();
ctx.stroke();
}
}
function canvasClick(event) {
isMouseDown = true;
x = event.pageX - canvas.offsetLeft;
y = event.pageY - canvas.offsetTop;
if (squares.length < 1) {
addSquare(event);
return;
}
var Square;
if (previousSelectedSquare) {
var prevX = previousSelectedSquare.x;
var prevY = previousSelectedSquare.y;
size = previousSelectedSquare.size;
}
var change = 7;
if (((x <= prevX + size + change) && (x >= prevX + size - change)) ||
((x >= prevX - change) && (x <= prevX + change)))
if (((y <= prevY + size + change) && (y >= prevY + size - change)) ||
((y <= prevY + change) && (y >= prevY - change))) {
console.log("borders");
$('#area').on('mousemove', resize(event));
return;
}
for (var i = squares.length - 1; i >= 0; i--) {
Square = squares[i];
if ((x >= Square.x && x <= Square.x + Square.size) && (y <= Square.y + Square.size && y >= Square.y)) {
Square.isSelected = true;
if (previousSelectedSquare != null)
previousSelectedSquare.isSelected = false;
if (previousSelectedSquare == Square)
previousSelectedSquare = null;
else
previousSelectedSquare = Square;
drawSquares();
return;
}
if (i === 0) {
addSquare(event);
return;
}
}
return;
}
// Part that resizes
var resizing = false;
function resize(event) {
if (!isMouseDown)
return;
resizing = true;
x = (event.pageX - canvas.offsetLeft);
y = (event.pageY - canvas.offsetTop);
size = previousSelectedSquare.size;
var centreX = previousSelectedSquare.x + size / 2;
var centreY = previousSelectedSquare.y + size / 2;
if (x > centreX && y < centreY) {
topr = true;
//top right
$('#area').off('mousemove.botR').off('mousemove.topL').off('mousemove.botL').on('mousemove.topR', topR);
return;
}
if (x < centreX && y < centreY) {
//top left
$('#area').off('mousemove.topR').off('mousemove.botL').off('mousemove.botR').on('mousemove.topL', topL);
return;
}
if (x > centreX && y > centreY) {
//bot right
$('#area').off('mousemove.topR').off('mousemove.topL').off('mousemove.botL').on('mousemove.botR', botR);
return;
}
if (x < centreX && y > centreY) {
//bot left
$('#area').off('mousemove.topR').off('mousemove.topL').off('mousemove.botR').on('mousemove.botL', botL);
return;
}
resizing = false;
return;
}
function topR(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("top right");
size = previousSelectedSquare.size;
var yb = previousSelectedSquare.y + size;
if (parseInt(yb - (event.pageY - canvas.offsetTop)) < 60)
return;
previousSelectedSquare.size = parseInt(yb - (event.pageY - canvas.offsetTop));
previousSelectedSquare.y = parseInt(event.pageY - canvas.offsetTop);
drawSquares();
return;
}
function topL(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("top left");
x = previousSelectedSquare.x + previousSelectedSquare.size;
y = previousSelectedSquare.y + previousSelectedSquare.size;
if (parseInt(y - (event.pageY - canvas.offsetTop)) < 60)
return;
previousSelectedSquare.size = parseInt(y - (event.pageY - canvas.offsetTop));
previousSelectedSquare.y = parseInt(event.pageY - canvas.offsetTop);
previousSelectedSquare.x = parseInt(event.pageX - canvas.offsetLeft);
drawSquares();
return;
}
function botR(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("bot right");
size = previousSelectedSquare.size;
if ((event.pageX - canvas.offsetLeft - previousSelectedSquare.x + size) / 2 < 60)
return;
previousSelectedSquare.size = parseInt((event.pageX - canvas.offsetLeft - previousSelectedSquare.x + size) / 2);
drawSquares();
return;
}
function botL(event) {
if (!resizing || !isMouseDown)
return;
$('#area').on('mouseup', up);
console.log("bot left");
var xr = previousSelectedSquare.x + previousSelectedSquare.size;
if (xr - event.pageX - canvas.offsetLeft < 60)
return;
previousSelectedSquare.size = parseInt(previousSelectedSquare.x + previousSelectedSquare.size - (event.pageX - canvas.offsetLeft));
previousSelectedSquare.x = parseInt(event.pageX - canvas.offsetLeft);
drawSquares();
return;
}
#area {
margin-top: 0;
border: 4px black solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="area" width="1250" height="550"></canvas>

Related

Why can't I use a function to do collision check in javascript?

I have a simple collision detection working that lets you jump off of blocks, and yet if I call a function that has the same code block in it. It will break.
call without the function:
for(let i = 0; i < blocks.length; i++){
if(blockCollision(sprite, blocks[i])){
sprite.vy = 0;
// sprite.vy += gravity;
if(blockCollisionLeft(sprite, blocks[i])){
sprite.vx = 0;
sprite.x = blocks[i].x - sprite.w - offset;
}
if(blockCollisionRight(sprite, blocks[i])){
sprite.vx = 0;
sprite.x = blocks[i].x + blocks[i].w + offset;
}
if(blockCollisionTop(sprite, blocks[i])){
sprite.y = blocks[i].y - sprite.h - offset;
sprite.canJump = true;
}else{
// sprite.vy = 0;
sprite.y = blocks[i].y + blocks[i].h + offset;
sprite.vy += gravity;
}
}
}
and the call with the function:
for(let i = 0; i < blocks.length; i++){
if(blockCollision(sprite, blocks[i])){
checkCollisions(sprite, blocks[i]);
break;
}
}
I'm not sure what to do at this point, the sprite block keeps jumping out of control, can't quite understand why a function call would do this.
const PI = Math.PI;
const offset = 1;
const gravity = .33;
function inCanvas(obj){
if(obj.x - offset < 0 && obj.x + obj.w + offset > w
&& obj.y - offset < 0 && obj.y + obj.h + offset > h){
return true;
}
return false;
}
function groundCollision(obj){
if(obj.y + obj.h + offset == h){
return true;
}
return false;
}
function blockCollision(obj, block){
if(obj.x - offset < block.x + block.w && obj.x + obj.w + offset > block.x
&& obj.y - offset < block.y + block.h && obj.y + obj.h + offset > block.y){
return true;
}
return false;
}
function blockCollisionTop(obj, block){
if(obj.y + obj.h + offset > block.y && obj.y + obj.h + offset < block.y + block.h){
return true;
}
return false;
}
function blockCollisionLeft(obj, block){
if(obj.x + obj.w + offset > block.x && obj.x + obj.w < block.x){
return true;
}
return false;
}
function blockCollisionRight(obj, block){
if(obj.x - offset < block.x + block.w && obj.x > block.x + block.w){
return true;
}
return false;
}
function Sprite(_x, _y, _w, _h){
this.x = _x;
this.y = _y;
this.w = _w;
this.h = _h;
this.vx = 0;
this.vy = 0;
this.jv = -11;
this.canJump = false;
// this.maxv = 3;
};
Sprite.prototype.draw = function(){
ctx.fillRect(this.x, this.y, this.w, this.h);
};
Sprite.prototype.update = function(){
this.x += this.vx;
this.y += this.vy;
this.vy += gravity;
// this.yv -= gravity;
// this.xv -= gravity;
// this.xv += gravity;
if(this.y + this.h + offset > h){
this.y = h - this.h - offset;
}
if(this.y - offset < 0){
this.y = offset;
}
if(this.x - offset < 0){
this.x = offset;
}
if(this.x + this.w + offset > w){
this.x = w - this.w - offset;
}
};
Sprite.prototype.jump = function(){
this.vy = this.jv;
};
function Block(_x, _y, _w, _h){
this.x = _x;
this.y = _y;
this.w = _w;
this.h = _h;
this.steppedOn = false;
};
Block.prototype.draw = function(){
ctx.fillRect(this.x, this.y, this.w, this.h);
};
const canvas = document.getElementById("game");
const ctx = canvas.getContext("2d");
const w = canvas.width = 600;
const h = canvas.height = 600;
var right = false,
left = false,
up = false;
var sprite = new Sprite(100, 200, 20, 40);
var box1 = new Block(w - 300, h - 80, 300, 10);
var blocks = [];
for(let i = 1; i <= 10; i++){
blocks.push(new Block(Math.round(Math.random() * w), Math.round(Math.random() * h), w/4 + Math.round(Math.random() * (w)), 15));
}
//console.log(blocks);
(function update(){
ctx.clearRect(0, 0, w, h);
sprite.draw();
for(let i = 0; i < blocks.length; i++){
blocks[i].draw();
}
box1.draw();
sprite.update();
// pOne.xv = left ? -2 : right ? 2 : 0;
if(left && right){
sprite.vx = 0;
}
else if(left){
sprite.vx = -2;
}
else if(right){
sprite.vx = 2;
}
else{
sprite.vx = 0;
}
if(up && sprite.canJump){
sprite.jump();
sprite.canJump = false;
}
if(groundCollision(sprite)){
sprite.canJump = true;
}
checkCollisions(sprite, box1);
for(let i = 0; i < blocks.length; i++){
if(blockCollision(sprite, blocks[i])){
checkCollisions(sprite, blocks[i]);
break;
}
}
// if(blockCollision(sprite, box1)){
// // checkCollisions(sprite, box1);
// sprite.vy = 0;
// // sprite.vy += gravity;
// if(blockCollisionLeft(sprite, box1)){
// sprite.vx = 0;
// sprite.x = box1.x - sprite.w - offset;
// }
// if(blockCollisionRight(sprite, box1)){
// sprite.vx = 0;
// sprite.x = box1.x + box1.w + offset;
// }
// if(box1.steppedOn = blockCollisionTop(sprite, box1)){
// sprite.y = box1.y - sprite.h - offset;
// sprite.canJump = true;
// }else{
// // sprite.vy = 0;
// sprite.y = box1.y + box1.h + offset;
// sprite.vy += gravity;
// }
// }
window.addEventListener("keydown", (e)=>{
// console.log(e.key);
if(e.key == "a" || e.key == "ArrowLeft"){
left = true;
}
if(e.key == "d" || e.key == "ArrowRight"){
right = true;
}
if(e.key == " " || e.key == "ArrowUp"){
up = true;
}
});
window.addEventListener("keyup", (e)=>{
if(e.key == "a" || e.key == "ArrowLeft"){
left = false;
}
if(e.key == "d" || e.key == "ArrowRight"){
right = false;
}
if(e.key == " " || e.key == "ArrowUp"){
up = false;
}
});
window.requestAnimationFrame(update);
}());
function checkCollisions(obj, block){
if(blockCollision(obj, block)){
obj.vy = 0;
// obj.vy += gravity;
if(blockCollisionLeft(obj, block)){
obj.vx = 0;
obj.x = block.x - obj.w - offset;
}
if(blockCollisionRight(obj, block)){
obj.vx = 0;
obj.x = block.x + block.w + offset;
}
if(block.steppedOn = blockCollisionTop(obj, block)){
obj.y = obj.y - obj.h - offset;
obj.canJump = true;
}else{
// obj.vy = 0;
obj.y = block.y + block.h + offset;
obj.vy += gravity;
}
}
}
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Block Jump</title>
<style>
*{margin:0; padding: 0;}
#game{
display:inherit;
margin:30px auto;
border:thin solid black;
}
</style>
</head>
<body>
<canvas id="game"></canvas>
<script src="JS/main.js"></script>
</body>
Your first two code snippets are not equivalent, you seem to have added a break statement in your example with a function. This will have the effect of terminating the for loop prematurely when blockCollision(sprite, blocks[i]) is true, which might be why you are seeing a difference between the two.
edit:
You also seem to have changed the third if-block slightly in your function. In your first code snippet that if-block is defined as:
if(blockCollisionTop(sprite, blocks[i])){
sprite.y = blocks[i].y - sprite.h - offset;
sprite.canJump = true;
}
but in your function is defined as:
if(block.steppedOn = blockCollisionTop(obj, block)){
obj.y = obj.y - obj.h - offset;
obj.canJump = true;
}
which is not equivalent because you have replaced blocks[i] with obj, but it should be block.

What's wrong with my rewrite from jquery to react

I try to rewrite this liquid button https://codepen.io/waaark/pen/VbgwEM , it use jquery.
I want to rewrite it for my react component, but don't know what is wrong:
here is the component code:
import React from "react";
import Link from "next/link";
import { useRef } from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
const getPixelRatio = context => {
var backingStore =
context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio ||
1;
return (window.devicePixelRatio || 1) / backingStore;
};
const useMove = () => {
let ref = useRef();
/* let msx = 0;
let msy = 0;
let mlx = 0;
let mly = 0; */
/* function mouseSpeed() {
msx = state.x - state.mouseLastXX;
msy = state.y - state.mouseLastYY;
mlx = state.x;
mly = state.y;
setTimeout(mouseSpeed, 50);
} */
const [state, setState] = useState({x: 0, y: 0, mouseDirectionXX:0, mouseDirectionYY:0, mouseSpeedXX:0, mouseSpeedYY:0, mouseLastXX:0, mouseLastYY:0})
const handleMouseMove = e => {
//e.persist()
let xx = state.mouseDirectionX;
let yy = state.mouseDirectionY;
//mouseSpeed();
if (state.x < e.clientX)
xx = 1;
else if (state.x > e.clientX)
xx = -1;
else
xx = 0;
if (state.y < e.clientY)
yy = 1;
else if (state.y > e.clientY)
yy = -1;
else
yy = 0;
//rx = (state.x - offset.left);
//ry = (state.y - offset.top);
setState(state => ({...state, x: e.clientX, y: e.clientY, mouseDirectionXX:xx, mouseDirectionYY:yy}))
//mouseX = e.clientX;
//mouseY = e.clientY;
//relMouseX = (mouseX - canvas.offsetLeft);
//relMouseY = (mouseY - canvas.offsetTop);
//console.log(xx + "///" + yy);
}
useEffect(() => {
window.addEventListener("mousemove", handleMouseMove);
return () => window.removeEventListener("mousemove", handleMouseMove);
}, []);
return {
mouseX: state.x,
mouseY: state.y,
mouseDirectionX: state.mouseDirectionXX,
mouseDirectionY: state.mouseDirectionYY,
mouseLastX: state.mouseLastXX,
mouseLastY: state.mouseLastYY,
mouseSpeedX: state.mouseSpeedXX,
mouseSpeedY: state.mouseSpeedYY,
//relMouseX: state.relMouseXX,
//relMouseY: state.relMouseYY,
handleMouseMove,
}
}
const LiquidButton = () => {
const {mouseX, mouseY, mouseDirectionX, mouseDirectionY, handleMouseMove} = useMove();
let ref = useRef();
let buttonWidth = 240;
let buttonHeight = 60;
let points = 8;
let pointsA = [], pointsB = [];
let viscosity = 10, mouseDist = 70, damping = 0.05, showIndicators = false;
let relMouseX = 0;
let relMouseY = 0;
//let canvas = ref.current;
/* function mouseSpeed() {
mouseSpeedX = mouseX - mouseLastX;
mouseSpeedY = mouseY - mouseLastY;
mouseLastX = mouseX;
mouseLastY = mouseY;
setTimeout(mouseSpeed, 50);
//console.log("AYE");
}
mouseSpeed(); */
useEffect(() => {
let canvas = ref.current;
let context = canvas.getContext('2d');
let canvaspos = canvas.getBoundingClientRect();
let offset = {
top: canvaspos.top,
left: canvaspos.left,
};
let mouseLastX = 0;
let mouseLastY = 0;
//mouseDirectionX = 0,
//mouseDirectionY = 0,
let mouseSpeedX = 0;
let mouseSpeedY = 0;
relMouseX = (mouseX - offset.left);
relMouseY = (mouseY - offset.top);
mouseSpeedX = mouseX - mouseLastX;
mouseSpeedY = mouseY - mouseLastY;
mouseLastX = mouseX;
mouseLastY = mouseY;
//NEW
console.log("mouseX:" + mouseX)
console.log("mouseLastX: "+ mouseLastX);
console.log("mouseSpeedX: "+ mouseSpeedX);
console.log("relMouseX:" + relMouseX)
console.log("mouseDirectionX: "+ mouseDirectionX);
console.log("mouseY:" + mouseY)
console.log("mouseLastY: "+ mouseLastY);
console.log("mouseSpeedY: "+ mouseSpeedY);
console.log("relMouseY:" + relMouseY)
console.log("mouseDirectionY: "+ mouseDirectionY);
function Point(x, y, level) {
this.x = this.ix = 75+x;
this.y = this.iy = 75+y;
this.vx = 0;
this.vy = 0;
this.cx1 = 0;
this.cy1 = 0;
this.cx2 = 0;
this.cy2 = 0;
this.level = level;
}
Point.prototype.move = function() {
this.vx += (this.ix - this.x) / (viscosity*this.level);
this.vy += (this.iy - this.y) / (viscosity*this.level);
var dx = this.ix - relMouseX,
dy = this.iy - relMouseY;
var relDist = (1-Math.sqrt((dx * dx) + (dy * dy))/mouseDist);
// Move x
if ((mouseDirectionX > 0 && relMouseX > this.x) || (mouseDirectionX < 0 && relMouseX < this.x)) {
if (relDist > 0 && relDist < 1) {
this.vx = (mouseSpeedX / 4) * relDist;
}
}
this.vx *= (1 - damping);
this.x += this.vx;
// Move y
if ((mouseDirectionY > 0 && relMouseY > this.y) || (mouseDirectionY < 0 && relMouseY < this.y)) {
if (relDist > 0 && relDist < 1) {
this.vy = (mouseSpeedY / 4) * relDist;
}
}
this.vy *= (1 - damping);
this.y += this.vy;
};
function addPoints(x, y) {
pointsA.push(new Point(x, y, 1));
pointsB.push(new Point(x, y, 2));
}
//NEW-END
let ratio = getPixelRatio(context);
let width = getComputedStyle(canvas)
.getPropertyValue('width')
.slice(0, -2);
let height = getComputedStyle(canvas)
.getPropertyValue('height')
.slice(0, -2);
canvas.width = buttonWidth+150;
canvas.height = buttonHeight+150;
//canvas.width = width * ratio;
//canvas.height = height * ratio;
canvas.style.width = width+`px`;
canvas.style.height = height+`px`;
let x = buttonHeight/2;
for(var j = 1; j < points; j++) {
addPoints((x+((buttonWidth-buttonHeight)/points)*j), 0);
}
addPoints(buttonWidth-buttonHeight/5, 0);
addPoints(buttonWidth+buttonHeight/10, buttonHeight/2);
addPoints(buttonWidth-buttonHeight/5, buttonHeight);
for(var j = points-1; j > 0; j--) {
addPoints((x+((buttonWidth-buttonHeight)/points)*j), buttonHeight);
}
addPoints(buttonHeight/5, buttonHeight);
addPoints(-buttonHeight/10, buttonHeight/2);
addPoints(buttonHeight/5, 0);
let requestId, i = 0;
const render = () => {
// Clear scene
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "rgba(0, 0, 200, 0.0)";
context.fillRect(0, 0, canvas.width, canvas.height);
// Move points
for (var i = 0; i <= pointsA.length - 1; i++) {
pointsA[i].move();
pointsB[i].move();
}
// Create dynamic gradient
var gradientX = Math.min(Math.max(mouseX - offset.left, 0), canvas.width);
var gradientY = Math.min(Math.max(mouseY - offset.top, 0), canvas.height);
var distance = Math.sqrt(Math.pow(gradientX - canvas.width/2, 2) + Math.pow(gradientY - canvas.height/2, 2)) / Math.sqrt(Math.pow(canvas.width/2, 2) + Math.pow(canvas.height/2, 2));
var gradient = context.createRadialGradient(gradientX, gradientY, 300+(300*distance), gradientX, gradientY, 0);
gradient.addColorStop(0, '#102ce5');
gradient.addColorStop(1, '#E406D6');
// Draw shapes
var groups = [pointsA, pointsB]
for (var j = 0; j <= 1; j++) {
var points = groups[j];
if (j == 0) {
// Background style
context.fillStyle = '#1CE2D8';
} else {
// Foreground style
context.fillStyle = gradient;
}
context.beginPath();
context.moveTo(points[0].x, points[0].y);
for (var i = 0; i < points.length; i++) {
var p = points[i];
var nextP = points[i + 1];
var val = 30*0.552284749831;
if (nextP != undefined) {
// if (nextP.ix > p.ix && nextP.iy < p.iy) {
// p.cx1 = p.x;
// p.cy1 = p.y-val;
// p.cx2 = nextP.x-val;
// p.cy2 = nextP.y;
// } else if (nextP.ix > p.ix && nextP.iy > p.iy) {
// p.cx1 = p.x+val;
// p.cy1 = p.y;
// p.cx2 = nextP.x;
// p.cy2 = nextP.y-val;
// } else if (nextP.ix < p.ix && nextP.iy > p.iy) {
// p.cx1 = p.x;
// p.cy1 = p.y+val;
// p.cx2 = nextP.x+val;
// p.cy2 = nextP.y;
// } else if (nextP.ix < p.ix && nextP.iy < p.iy) {
// p.cx1 = p.x-val;
// p.cy1 = p.y;
// p.cx2 = nextP.x;
// p.cy2 = nextP.y+val;
// } else {
p.cx1 = (p.x+nextP.x)/2;
p.cy1 = (p.y+nextP.y)/2;
p.cx2 = (p.x+nextP.x)/2;
p.cy2 = (p.y+nextP.y)/2;
context.bezierCurveTo(p.x, p.y, p.cx1, p.cy1, p.cx1, p.cy1);
// continue;
// }
// context.bezierCurveTo(p.cx1, p.cy1, p.cx2, p.cy2, nextP.x, nextP.y);
} else {
nextP = points[0];
p.cx1 = (p.x+nextP.x)/2;
p.cy1 = (p.y+nextP.y)/2;
context.bezierCurveTo(p.x, p.y, p.cx1, p.cy1, p.cx1, p.cy1);
}
}
// context.closePath();
context.fill();
}
if (showIndicators) {
// Draw points
context.fillStyle = '#000';
context.beginPath();
for (var i = 0; i < pointsA.length; i++) {
var p = pointsA[i];
context.rect(p.x - 1, p.y - 1, 2, 2);
}
context.fill();
// Draw controls
context.fillStyle = '#f00';
context.beginPath();
for (var i = 0; i < pointsA.length; i++) {
var p = pointsA[i];
context.rect(p.cx1 - 1, p.cy1 - 1, 2, 2);
context.rect(p.cx2 - 1, p.cy2 - 1, 2, 2);
}
context.fill();
}
requestId = requestAnimationFrame(render);
};
render();
return () => {
cancelAnimationFrame(requestId);
};
});
return (
<div>
<canvas ref={ref} style={{ width: '390px', height: '210px' }} >
<a href="#" className="btn-liquid">
<span className="inner">Press Button</span>
</a>
</canvas>
<div className="mouseArea">
Hook
<div className="mouseInfo">
The current mouse position is ({mouseX}, {mouseY}) <br />
Mouse Direction is ({mouseDirectionX}, {mouseDirectionY}) <br />
{/* Mouse Last ({mouseLastX}, {mouseLastY}) <br /> */}
{/* Mouse Speed ({mouseSpeedX}, {mouseSpeedY}) <br /> */}
</div>
</div>
</div>
);
};
export default LiquidButton;
i tried to calculate the mouse speed and mouse direction, but still confuse where to put the code.When I console log the value, the mouse position, mouse speed and mouse last position are the same value
How about this?
let pointsA = [];
let pointsB = [];
let $canvas = null;
let canvas = null;
let context = null;
// let vars = null;
let points = 8;
let viscosity = 20;
let mouseDist = 70;
let damping = 0.05;
let showIndicators = false;
let mouseX = 0;
let mouseY = 0;
let relMouseX = 0;
let relMouseY = 0;
let mouseLastX = 0;
let mouseLastY = 0;
let mouseDirectionX = 0;
let mouseDirectionY = 0;
let mouseSpeedX = 0;
let mouseSpeedY = 0;
function mouseDirection(e) {
if (mouseX < e.pageX)
mouseDirectionX = 1;
else if (mouseX > e.pageX)
mouseDirectionX = -1;
else
mouseDirectionX = 0;
if (mouseY < e.pageY)
mouseDirectionY = 1;
else if (mouseY > e.pageY)
mouseDirectionY = -1;
else
mouseDirectionY = 0;
mouseX = e.pageX;
mouseY = e.pageY;
relMouseX = (mouseX - $canvas.offset().left);
relMouseY = (mouseY - $canvas.offset().top);
}
function mouseSpeed() {
mouseSpeedX = mouseX - mouseLastX;
mouseSpeedY = mouseY - mouseLastY;
mouseLastX = mouseX;
mouseLastY = mouseY;
setTimeout(mouseSpeed, 50);
}
mouseSpeed();
function initButton(button) {
// Get button
// var button = $('.btn-liquid');
var buttonWidth = button.width();
var buttonHeight = button.height();
// Create canvas
$canvas = $('<canvas></canvas>');
button.append($canvas);
canvas = $canvas.get(0);
canvas.width = buttonWidth + 100;
canvas.height = buttonHeight + 100;
context = canvas.getContext('2d');
// Add points
var x = buttonHeight / 2;
for (let j = 1; j < points; j++) {
addPoints((x + ((buttonWidth - buttonHeight) / points) * j), 0);
}
addPoints(buttonWidth - buttonHeight / 5, 0);
addPoints(buttonWidth + buttonHeight / 10, buttonHeight / 2);
addPoints(buttonWidth - buttonHeight / 5, buttonHeight);
for (let j = points - 1; j > 0; j--) {
addPoints((x + ((buttonWidth - buttonHeight) / points) * j), buttonHeight);
}
addPoints(buttonHeight / 5, buttonHeight);
addPoints(-buttonHeight / 10, buttonHeight / 2);
addPoints(buttonHeight / 5, 0);
// addPoints(x, 0);
// addPoints(0, buttonHeight/2);
// addPoints(0, buttonHeight/2);
// addPoints(buttonHeight/4, 0);
// Start render
renderCanvas();
}
function addPoints(x, y) {
pointsA.push(new Point(x, y, 1));
pointsB.push(new Point(x, y, 2));
}
function Point(x, y, level) {
this.x = this.ix = 50 + x;
this.y = this.iy = 50 + y;
this.vx = 0;
this.vy = 0;
this.cx1 = 0;
this.cy1 = 0;
this.cx2 = 0;
this.cy2 = 0;
this.level = level;
}
Point.prototype.move = function() {
this.vx += (this.ix - this.x) / (viscosity * this.level);
this.vy += (this.iy - this.y) / (viscosity * this.level);
var dx = this.ix - relMouseX,
dy = this.iy - relMouseY;
var relDist = (1 - Math.sqrt((dx * dx) + (dy * dy)) / mouseDist);
// Move x
if ((mouseDirectionX > 0 && relMouseX > this.x) || (mouseDirectionX < 0 && relMouseX < this.x)) {
if (relDist > 0 && relDist < 1) {
this.vx = (mouseSpeedX / 4) * relDist;
}
}
this.vx *= (1 - damping);
this.x += this.vx;
// Move y
if ((mouseDirectionY > 0 && relMouseY > this.y) || (mouseDirectionY < 0 && relMouseY < this.y)) {
if (relDist > 0 && relDist < 1) {
this.vy = (mouseSpeedY / 4) * relDist;
}
}
this.vy *= (1 - damping);
this.y += this.vy;
};
function renderCanvas() {
// rAF
// rafID =
requestAnimationFrame(renderCanvas);
// Clear scene
context.clearRect(0, 0, $canvas.width(), $canvas.height());
context.fillStyle = '#fff';
context.fillRect(0, 0, $canvas.width(), $canvas.height());
// Move points
for (var i = 0; i <= pointsA.length - 1; i++) {
pointsA[i].move();
pointsB[i].move();
}
// Create dynamic gradient
var gradientX = Math.min(Math.max(mouseX - $canvas.offset().left, 0), $canvas.width());
var gradientY = Math.min(Math.max(mouseY - $canvas.offset().top, 0), $canvas.height());
var distance = Math.sqrt(Math.pow(gradientX - $canvas.width() / 2, 2) + Math.pow(gradientY - $canvas.height() / 2, 2)) / Math.sqrt(Math.pow($canvas.width() / 2, 2) + Math.pow($canvas.height() / 2, 2));
var gradient = context.createRadialGradient(gradientX, gradientY, 300 + (300 * distance), gradientX, gradientY, 0);
gradient.addColorStop(0, '#102ce5');
gradient.addColorStop(1, '#E406D6');
// Draw shapes
var groups = [pointsA, pointsB]
for (var j = 0; j <= 1; j++) {
var points = groups[j];
if (j === 0) {
// Background style
context.fillStyle = '#1CE2D8';
} else {
// Foreground style
context.fillStyle = gradient;
}
context.beginPath();
context.moveTo(points[0].x, points[0].y);
for (let i = 0; i < points.length; i++) {
var p = points[i];
var nextP = points[i + 1];
// var val = 30*0.552284749831;
if (nextP !== undefined) {
// if (nextP.ix > p.ix && nextP.iy < p.iy) {
// p.cx1 = p.x;
// p.cy1 = p.y-val;
// p.cx2 = nextP.x-val;
// p.cy2 = nextP.y;
// } else if (nextP.ix > p.ix && nextP.iy > p.iy) {
// p.cx1 = p.x+val;
// p.cy1 = p.y;
// p.cx2 = nextP.x;
// p.cy2 = nextP.y-val;
// } else if (nextP.ix < p.ix && nextP.iy > p.iy) {
// p.cx1 = p.x;
// p.cy1 = p.y+val;
// p.cx2 = nextP.x+val;
// p.cy2 = nextP.y;
// } else if (nextP.ix < p.ix && nextP.iy < p.iy) {
// p.cx1 = p.x-val;
// p.cy1 = p.y;
// p.cx2 = nextP.x;
// p.cy2 = nextP.y+val;
// } else {
p.cx1 = (p.x + nextP.x) / 2;
p.cy1 = (p.y + nextP.y) / 2;
p.cx2 = (p.x + nextP.x) / 2;
p.cy2 = (p.y + nextP.y) / 2;
context.bezierCurveTo(p.x, p.y, p.cx1, p.cy1, p.cx1, p.cy1);
// continue;
// }
// context.bezierCurveTo(p.cx1, p.cy1, p.cx2, p.cy2, nextP.x, nextP.y);
} else {
nextP = points[0];
p.cx1 = (p.x + nextP.x) / 2;
p.cy1 = (p.y + nextP.y) / 2;
context.bezierCurveTo(p.x, p.y, p.cx1, p.cy1, p.cx1, p.cy1);
}
}
// context.closePath();
context.fill();
}
if (showIndicators) {
// Draw points
context.fillStyle = '#000';
context.beginPath();
for (let i = 0; i < pointsA.length; i++) {
// var p = pointsA[i];
context.rect(p.x - 1, p.y - 1, 2, 2);
}
context.fill();
// Draw controls
context.fillStyle = '#f00';
context.beginPath();
for (let i = 0; i < pointsA.length; i++) {
// var p = pointsA[i];
context.rect(p.cx1 - 1, p.cy1 - 1, 2, 2);
context.rect(p.cx2 - 1, p.cy2 - 1, 2, 2);
}
context.fill();
}
}
const StaticLiquidButton = ({
className,
liquidBtnRef,
href
}) => ( <
a href = {
href
}
className = "btn-liquid"
ref = {
liquidBtnRef
} >
<
span class = "inner" >
Liquid button ?
<
/span> <
/a>
);
StaticLiquidButton.propTypes = {
className: PropTypes.string.isRequired
};
const LiquidButton = () => {
const liquidBtnRef = React.useRef()
React.useEffect(() => {
const button = liquidBtnRef.current;
initButton($(button));
$(document).on('mousemove', mouseDirection);
return () => {
$(document).off('mousemove', mouseDirection)
}
},[])
return (
<StaticLiquidButton
className="TeslaAppUI-LiquidButton"
href="http://waaark.com"
liquidBtnRef={liquidBtnRef}
/>
)
}
function App() {
return ( <
div >
<
LiquidButton / >
<
/div>
);
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
body {
margin: 0;
display: flex;
height: 100vh;
align-items: center;
justify-content: center;
}
.btn-liquid {
display: inline-block;
position: relative;
width: 240px;
height: 60px;
border-radius: 27px;
color: #fff;
font: 700 14px/60px "Droid Sans", sans-serif;
letter-spacing: 0.05em;
text-align: center;
text-decoration: none;
text-transform: uppercase;
}
.btn-liquid .inner {
position: relative;
z-index: 2;
}
.btn-liquid canvas {
position: absolute;
top: -50px;
right: -50px;
bottom: -50px;
left: -50px;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js" integrity="sha512-ssNhh7jlzc+K93ckIlSXFHHz6fSFv0l619WOv8xbFNRbFOujbasb42LVMOggDrQR1ScJncoWb+KAJx1uF3ipjw==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Good Luck...

how can I detect collision in a 2D tile game map

I made this basic game where I drew a map and a player, the player can move anywhere but how can I make so that it wont move when its on the tile[1] in the map?
also when I try to check if the player.x is greater than 50 it could go left it works but than if I click 2 keys at once it goes through
const context = document.querySelector("canvas").getContext("2d");
var rgb = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random() + ')';
document.onload = Loop();
var width = 1500;
var height = 800;
function Loop(){
var width = 1500;
var height = 800;
context.canvas.height = height;
context.canvas.width = width;
this.interval = setInterval(Update, 1000/100);
}
const Player = function(x, y, w, h, color) {
this.x = x; this.y = y; this.w = w; this.h = h;
this.speedY = 0; this.speedX = 0;
this.Draw = function(){
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
};
this.Move = function(){
this.x += this.speedX;
this.y += this.speedY;
};
};<code>
var player = new Player(100,100,50, 50, rgb);
var Key = {};
function Update(){
context.clearRect(0, 0, width, height);
Map();
player.Draw();
player.Move();
onkeydown = onkeyup = function(e){
player.speedX = 0;
player.speedY = 0;
e = e || event;
Key[e.keyCode] = e.type == 'keydown';
if(Key[37] || Key[65]) {player.speedX -= 2}
if(Key[38] || Key[87]) {player.speedY -= 2}
if(Key[39] || Key[68]) {player.speedX += 2}
if(Key[40] || Key[83]) {player.speedY += 2}
if(Key[32]) {player.color = 'rgb(' + Math.random()*256 + ',' + Math.random()*256 + ',' + Math.random()*256 + ','+Math.random()*1 + ')';}
};
}
var map = [
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
];
var row = 5;
var column = 5;
function Map(){
for(let y = -1; y < column; y++){
for(let x = -1; x < row; x++){
switch(map[((y*row) + x)]) {
case 0: context.fillStyle = player.color;
break;
case 1: context.fillStyle = "#ffffff";
break;
default: context.fillStyle = "#000000";
}
context.fillRect(x*50, y*50, 50, 50);
}
}
}
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
script {
display: none;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
function Camera(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
}
Camera.prototype = {
set: function(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
},
pan: function(x,y) {
this.x += x || 0.0;
this.y += y || 0.0;
}
};
var nextID = 0;
function Tile(colour) {
this.id = nextID++;
this.colour = colour || "black";
}
function Map(width,height) {
this.width = width || 1;
this.height = height || 1;
this.map = [];
this.map.length = this.height;
for (var y = 0; y < this.height; ++y) {
this.map[y] = [];
this.map[y].length = width;
for (var x = 0; x < this.width; ++x) {
this.map[y][x] = Math.random() < 0.2 ?
this.TILE_WALL:
this.TILE_GRASS;
}
this.map[y][0] = this.TILE_WALL;
this.map[y][this.width - 1] = this.TILE_WALL;
}
for (var x = 0; x < this.width; ++x) {
this.map[0][x] = this.TILE_WALL;
this.map[this.height - 1][x] = this.TILE_WALL;
}
}
Map.prototype = {
TILE_WIDTH: 32.0,
TILE_HEIGHT: 32.0,
INV_TILE_WIDTH: 0.0,
INV_TILE_HEIGHT: 0.0,
TILE_AIR: new Tile("#00000000"),
TILE_GRASS: new Tile("#00AA00FF"),
TILE_WALL: new Tile("#555555FF"),
set: function(x,y,tile) {
this.map[y][x] = tile;
},
scaleX: function(x) {
return (x * this.INV_TILE_WIDTH) | 0;
},
scaleY: function(y) {
return (y * this.INV_TILE_HEIGHT) | 0;
},
isColliding: function(x,y) {
return x > -1 && x < this.width
&& y > -1 && y < this.height
&& this.map[y][x].id > 1;
},
render: function(ctx,camera) {
for (var y = 0; y < this.height; ++y) {
for (var x = 0; x < this.width; ++x) {
var tile = this.map[y][x];
var _x = x * this.TILE_WIDTH - camera.x;
var _y = y * this.TILE_HEIGHT - camera.y;
ctx.fillStyle = tile.colour;
ctx.fillRect(_x,_y,this.TILE_WIDTH - 1,this.TILE_HEIGHT - 1);
}
}
}
};
Map.prototype.INV_TILE_WIDTH = 1.0 / Map.prototype.TILE_WIDTH;
Map.prototype.INV_TILE_HEIGHT = 1.0 / Map.prototype.TILE_HEIGHT;
function Player(x,y) {
this.x = x || 0.0;
this.y = y || 0.0;
this.dx = 0.0;
this.dy = 0.0;
this.isUp = false;
this.isDown = false;
this.isLeft = false;
this.isRight = false;
}
Player.prototype = {
WIDTH: 20.0,
HEIGHT: 20.0,
ACCELERATION: 1.0,
DEACCELERATION: 0.5,
MAX_SPEED: 3.0,
tick: function(map) {
// Movement
if (this.isUp) {
this.dy -= this.ACCELERATION;
if (this.dy < -this.MAX_SPEED) {
this.dy = -this.MAX_SPEED;
}
} else if (this.dy < 0.0) {
this.dy += this.DEACCELERATION;
if (this.dy > 0.0) {
this.dy = 0.0;
}
}
if (this.isDown) {
this.dy += this.ACCELERATION;
if (this.dy > this.MAX_SPEED) {
this.dy = this.MAX_SPEED;
}
} else if (this.dy > 0.0) {
this.dy -= this.DEACCELERATION;
if (this.dy < 0.0) {
this.dy = 0.0;
}
}
if (this.isLeft) {
this.dx -= this.ACCELERATION;
if (this.dx < -this.MAX_SPEED) {
this.dx = -this.MAX_SPEED;
}
} else if (this.dx < 0.0) {
this.dx += this.DEACCELERATION;
if (this.dx > 0.0) {
this.dx = 0.0;
}
}
if (this.isRight) {
this.dx += this.ACCELERATION;
if (this.dx > this.MAX_SPEED) {
this.dx = this.MAX_SPEED;
}
} else if (this.dx > 0.0) {
this.dx -= this.DEACCELERATION;
if (this.dx < 0.0) {
this.dx = 0.0;
}
}
// Collision
if (this.dx !== 0.0) {
var minY = map.scaleY(this.y);
var maxY = map.scaleY(this.y + this.HEIGHT);
var minX = 0;
var maxX = 0;
if (this.dx < 0.0) {
minX = map.scaleX(this.x + this.dx);
maxX = map.scaleX(this.x);
} else {
minX = map.scaleX(this.x + this.WIDTH);
maxX = map.scaleX(this.x + this.WIDTH + this.dx);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.x = this.dx < 0.0 ?
(x + 1) * map.TILE_WIDTH:
x * map.TILE_WIDTH - this.WIDTH - 1;
this.dx = 0.0;
break loop;
}
}
}
}
if (this.dy !== 0.0) {
var minX = map.scaleX(this.x);
var maxX = map.scaleX(this.x + this.WIDTH);
var minY = 0;
var maxY = 0;
if (this.dy < 0.0) {
minY = map.scaleY(this.y + this.dy);
maxY = map.scaleY(this.y);
} else {
minY = map.scaleY(this.y + this.HEIGHT);
maxY = map.scaleY(this.y + this.HEIGHT + this.dy);
}
loop:
for (var y = minY; y <= maxY; ++y) {
for (var x = minX; x <= maxX; ++x) {
if (map.isColliding(x,y)) {
this.y = this.dy < 0.0 ?
(y + 1) * map.TILE_HEIGHT:
y * map.TILE_HEIGHT - this.HEIGHT - 1;
this.dy = 0.0;
break loop;
}
}
}
}
this.x += this.dx;
this.y += this.dy;
},
render: function(ctx,camera) {
camera.set(this.x,this.y);
ctx.lineWidth = 1;
ctx.strokeStyle = "black";
ctx.fillStyle = "darkred";
ctx.beginPath();
ctx.rect(this.x - camera.x,this.y - camera.y,this.WIDTH,this.HEIGHT);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 180;
var canvasHeight = 160;
var canvas = null;
var ctx = null;
var camera = null;
var map = null;
var player = null;
// Functions
function onKeyDown(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = true; break;
case "S": player.isDown = true; break;
case "A": player.isLeft = true; break;
case "D": player.isRight = true; break;
}
}
function onKeyUp(e) {
switch(e.key.toUpperCase()) {
case "W": player.isUp = false; break;
case "S": player.isDown = false; break;
case "A": player.isLeft = false; break;
case "D": player.isRight = false; break;
}
}
function loop() {
// Tick
player.tick(map);
// Render
ctx.fillStyle = "gray";
ctx.fillRect(-canvasWidth >> 1,-canvasHeight >> 1,canvasWidth,canvasHeight);
map.render(ctx,camera);
player.render(ctx,camera);
//
requestAnimationFrame(loop);
}
// Entry point (first to execute)
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
ctx = canvas.getContext("2d");
ctx.translate(canvasWidth >> 1,canvasHeight >> 1);
camera = new Camera(0.0,0.0);
map = new Map(10,10);
player = new Player(40.0,40.0);
map.set(1,1,map.TILE_GRASS);
addEventListener("keydown",onKeyDown);
addEventListener("keyup",onKeyUp);
loop();
}
}();
</script>
</body>
</html>
Firstly, looking at your code, there are some things that are missing which is required to implement basic collision detection and those are:
The player's current direction that he/she is moving in. This is important because it allows the function determining the collision detection to distinguish which side it is checking for the collision (Up, down, left, or right) since a player can only collide with one side at a time.
The tile's position and size. This is also very important because like the first point, there is only one side of the tile that the player can collide with and knowing the size and position can determine if it is a collision or not based on the players size and position.
Also, since you mentioned it is a basic game, the implementation below is a basic collision detection. If you were to make a more complex and bigger game, you should try looking into quad trees for more efficient collision detection:
https://gamedevelopment.tutsplus.com/tutorials/quick-tip-use-quadtrees-to-detect-likely-collisions-in-2d-space--gamedev-374
Now this is the function for detecting collision, for the sake of readability and shortness, p will represent the player object and t would represent the tile object. This function returns whether or not the player is colliding with a tile based on their direction of movement.
function isColliding(p, t){
if (p.direction == 'up') {
return p.y +(p.height/2)-p.speedY< t.y + t.height && p.y > t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'down') {
return p.y + (p.height/2)+p.speedY > t.y && p.y < t.y
&& p.x + p.width > t.x && p.x < t.x + t.width;
}
if (p.direction == 'right') {
return p.x + p.width+p.speedX > t.x && p.x < t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
if (p.direction == 'left') {
return p.x -p.speedX< t.x + t.width && p.x > t.x
&& p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
}
return false;
}
You would probably want to put this in the player move function to constantly detect for tiles as it is moving. To do that, you'd want to modify your keydown detection so that with each different keydown, it would update the player's direction, here's a simple example:
document.onkeydown = function(event){
if (event.keyCode == 87)
player.up = true;
else if (event.keyCode == 65)
player.left = true;
else if (event.keyCode == 83)
player.down = true;
else if (event.keyCode == 68)
player.right = true;
}
and another simple example for every time the player moves (user presses a keydown):
const Player= function(/*Param stuff*/){
/*Property stuff*/
//tileArray is the array (or object, your choice) of all the current tiles in the map
this.move=function(tileArray){
//Go through all tiles to see if player is colliding with any of them
for(var t in tileArray){
if(this.up){
if(isColliding(this, tileArray[t]){
//functionality for when player collides
}else{
//functionality for when player doesn't collide
}
}
//check if player is going down, left, etc
}
}
}
These are just examples of how to implement the detection. You should use it as a reference to implement it relatively to how your code function because I didn't write it based on what you posted.
PS.
Make sure to also convert the directions to false after the user stops pressing the key.

How to limit the boundary of pan in fabric js?

How to limit the boundary of pan in fabric js?
I wrote the following code to limit the pan of my canvas but it is just not working. I want it to remember how much it has move outside of the canvas so that even after your pointer goes out of the canvas, you will have to move back the same amount to start dragging again. Currently, after the pointer move out of the canvas, the image will stick it. I cannot understand what I am doing wrong. Can someone help me?
Update
The following solution seems to work for zoom 1x. Still need to figure out how to solve it after zoom. But it is so verbose. Is there a better way to do this? https://jsfiddle.net/yxchng/0hL2khro/356/
canvas.on('mouse:move', function (opt) {
if (this.isDragging) {
var e = opt.e;
var zoom = canvas.getZoom();
var moveX = 0;
var moveY = 0;
if ((e.clientX - this.lastPosX) * this.offsetX > 0) {
this.offsetX += e.clientX - this.lastPosX;
} else if (e.clientX - this.lastPosX > 0 && this.offsetX < 0) {
moveX = e.clientX - this.lastPosX + this.offsetX;
if (moveX > 0) {
this.viewportTransform[4] += moveX;
this.offsetX = 0;
} else {
this.offsetX = moveX;
}
} else if (e.clientX - this.lastPosX < 0 && this.offsetX > 0) {
moveX = e.clientX - this.lastPosX + this.offsetX;
if (moveX < 0) {
this.viewportTransform[4] += moveX;
this.offsetX = 0;
} else {
this.offsetX = moveX;
}
} else {
this.viewportTransform[4] += e.clientX - this.lastPosX;
if (this.viewportTransform[4] < 0) {
this.offsetX = this.viewportTransform[4];
this.viewportTransform[4] = 0;
}
if (this.viewportTransform[4] > canvas.width) {
this.offsetX = this.viewportTransform[4] - canvas.width;
this.viewportTransform[4] = canvas.width;
}
}
if ((e.clientY - this.lastPosY) * this.offsetY > 0) {
this.offsetY += e.clientY - this.lastPosY;
} else if (e.clientY - this.lastPosY > 0 && this.offsetY < 0) {
moveY = e.clientY - this.lastPosY + this.offsetY;
if (moveY > 0) {
this.viewportTransform[5] += moveY;
this.offsetY = 0;
} else {
this.offsetY = moveY;
}
} else if (e.clientY - this.lastPosY < 0 && this.offsetY > 0) {
moveY = e.clientY - this.lastPosY + this.offsetY;
if (moveY < 0) {
this.viewportTransform[5] += moveY;
this.offsetY = 0;
} else {
this.offsetY = moveY;
}
} else {
this.viewportTransform[5] += e.clientY - this.lastPosY;
if (this.viewportTransform[5] < 0) {
this.offsetY = this.viewportTransform[5];
this.viewportTransform[5] = 0;
}
if (this.viewportTransform[5] > canvas.height) {
this.offsetY = this.viewportTransform[5] - canvas.height;
this.viewportTransform[5] = canvas.height;
}
}
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
});

How can I make the ball bounce off the red bricks without it (the red brick) breaking? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So basically I want the red bricks to have an extra bounce (but not the blue ones). It means if I hit it once the red brick reflects the ball without it disappearing but when I hit it the second time it does. Thank you in advance.
<!DOCTYPE html>
<html>
<head>
<title>Breakout_Game</title>
</head>
<body>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script type="text/javascript">
var canvas, canvasContext;
var ballX = 75, ballY = 75;
var ballSpeedX = 3, ballSpeedY = 3;
var ballR = 7;
const brickW = 80;
const brickH = 20;
const brickCols = Math.floor(800 / brickW);
const brickRows = Math.floor(600 / (brickH * 3));
const brickGap = 1;
var brickGrid = new Array(brickCols * brickRows);
var bricksLeft = 0;
const paddleW = 100, paddleH = 10;
var paddleX = 400, paddleY = 600;
const distanceBP = 60;
var mouseX, mouseY;
function updateMousePos (evt) {
var rect = canvas.getBoundingClientRect(); // this is for adjustments only (getting the mouse coordinates even if the page is scrollable)
var root = document.documentElement;
mouseX = evt.clientX - rect.left - root.scrollLeft; // clientX is the X of mouse
mouseY = evt.clientY - rect.top - root.scrollTop;
paddleX = mouseX - paddleW/2;
/* //Cheats Help debugging
ballX = mouseX;
ballY = mouseY;*/
}
function brickReset () {
bricksLeft = 0;
var i;
for(i = 0; i < 3 * brickCols; i++) {
brickGrid[i] = false;
}
for (; i < brickCols * brickRows; i++) {
brickGrid[i] = true;
bricksLeft++;
}
randBrickColor();
}
window.onload = function () {
canvas = document.getElementById("myCanvas");
canvasContext = canvas.getContext("2d");
var fps = 60;
setInterval(updateAll, 1000 / fps);
canvas.addEventListener("mousemove", updateMousePos); // everytime the mouse moves we call the function updateMousePos()
brickReset();
ballReset();
}
function updateAll () {
drawAll();
moveAll();
}
function ballReset () {
ballX = canvas.width / 2;
ballY = canvas.height / 2;
}
function ballMove () {
ballX += ballSpeedX;
ballY += ballSpeedY;
//COLLISION
//left
if (ballX - ballR < 0 && ballSpeedX < 0.0) {
ballSpeedX = -ballSpeedX;
}
//right
if (ballX + ballR > canvas.width && ballSpeedX > 0.0) {
ballSpeedX = -ballSpeedX;
}
//top
if (ballY - ballR < 0 && ballSpeedY < 0.0) {
ballSpeedY = -ballSpeedY;
}
//bottom
if (ballY > canvas.height) {
ballReset();
brickReset();
}
}
function isBrickAtColRow (col, row) {
if (col >= 0 && col < brickCols && row >= 0 && row < brickRows) {
var brickIndexUnderCoord = rowColToArrayIndex(col, row);
return brickGrid[brickIndexUnderCoord];
} else {
return false;
}
}
function ballBrickHandling () {
var ballBrickCol = Math.floor(ballX / brickW);
var ballBrickRow = Math.floor(ballY / brickH);
var brickIndexUnderBall = rowColToArrayIndex(ballBrickCol, ballBrickRow);
if (brickIndexUnderBall >= 0 && brickIndexUnderBall < brickCols * brickRows) {
if (isBrickAtColRow( ballBrickCol,ballBrickRow)) {
brickGrid[brickIndexUnderBall] = false;
bricksLeft--;
//console.log( bricksLeft)
var prevBallX = ballX - ballSpeedX;
var prevBallY = ballY - ballSpeedY;
var prevBrickCol = Math.floor(prevBallX / brickW);
var prevBrickRow = Math.floor(prevBallY / brickH);
var bothTestsFailed = true;
if (prevBrickCol != ballBrickCol) {
if (isBrickAtColRow(prevBrickCol, ballBrickRow) == false) {
ballSpeedX = -ballSpeedX;
bothTestsFailed = false;
}
}
if (prevBrickRow != ballBrickRow) {
if (isBrickAtColRow(ballBrickCol, prevBrickRow) == false) {
ballSpeedY = -ballSpeedY;
bothTestsFailed = false;
}
}
if (bothTestsFailed) {
ballSpeedX = -ballSpeedX;
ballSpeedY = -ballSpeedY;
}
}
}
}
function ballPaddleHandling () {
var paddleTopEdgeY = canvas.height - distanceBP;
var paddleBottomEdgeY = paddleTopEdgeY + paddleH;
var paddleLeftEdgeX = paddleX;
var paddleRightEdgeX = paddleLeftEdgeX + paddleW;
if (ballY + ballR > paddleTopEdgeY &&
ballY - ballR < paddleBottomEdgeY &&
ballX + ballR > paddleLeftEdgeX &&
ballX - ballR < paddleRightEdgeX
) {
ballSpeedY *= -1;
var centerOfPaddleX = paddleX + paddleW / 2;
var ballDistFromPadlleCenterX = ballX - centerOfPaddleX;
ballSpeedX = ballDistFromPadlleCenterX * 0.2;
if (bricksLeft == 0) {
brickReset();
}
}
}
function moveAll () {
//console.log("X: " + ballSpeedX,"Y: " + ballSpeedY);
ballMove();
ballBrickHandling();
ballPaddleHandling();
}
function rowColToArrayIndex (col, row) {
return col + brickCols * row;
}
// Random COLOR
var brickColors = [];
function randBrickColor () {
for (var eachRow = 0; eachRow < brickRows; eachRow++) {
brickColors[eachRow] = [];
for (var eachCol = 0; eachCol < brickCols; eachCol++) {
if (Math.random() > 0.7) {
brickColors[eachRow][eachCol] = "red";
} else {
brickColors[eachRow][eachCol] = "blue";
}
}
}
}
//end of Random COLOR
function drawBricks () {
for (var eachRow = 0; eachRow < brickRows; eachRow++) {
for (var eachCol = 0; eachCol < brickCols; eachCol++) {
var arrayIndex = brickCols * eachRow + eachCol;
if (brickGrid[arrayIndex]) {
colorRect(brickW * eachCol, brickH * eachRow, brickW-brickGap, brickH-brickGap, brickColors[eachRow][eachCol]);
}
}
}
}
function drawAll () {
// Black Screen
colorRect(0,0, canvas.width, canvas.height, "black");
// Ball
colorCircle(ballX,ballY, ballR, "white");
// Paddle
colorRect(paddleX, paddleY - distanceBP, paddleW, paddleH, "white");
// Bricks
drawBricks();
// Position of the mouse
colorText(mouseX+","+mouseY, mouseX,mouseY, "yellow");
}
function colorRect (topLeftX, topLeftY, boxWidth, boxHeight, fillColor) {
canvasContext.fillStyle = fillColor;
canvasContext.fillRect(topLeftX, topLeftY, boxWidth, boxHeight);
}
function colorCircle(centerX, centerY, radius, fillColor) {
canvasContext.fillStyle = fillColor;
canvasContext.beginPath();
canvasContext.arc(centerX, centerY, radius, 0, Math.PI * 2, true);
canvasContext.fill();
}
function colorText(showWords, textX, textY, fillColor) {
canvasContext.fillStyle = fillColor;
canvasContext.fillText(showWords, textX, textY);
}
</script>
</body>
</html>
in ballBrickHandling() replace
brickGrid[brickIndexUnderBall] = false;
bricksLeft--;
with
if(brickColors[ballBrickRow][ballBrickCol] != "red") {
brickGrid[brickIndexUnderBall] = false;
bricksLeft--;
} else brickColors[ballBrickRow][ballBrickCol] = "blue"

Categories

Resources