How to get relative mouse position of screen which is transformed - position

In win2D, Get absolute mouse position is this (from Win2D Sprite Sample)
var point = e.GetCurrentPoint((UIElement)sender).Position.ToVector2();
But, This is Absolute Position,
I make whether mouse is pointing Game Player
So, I made this Code, But It doesn't work.
var rpoint = e.GetCurrentPoint(canvas).Position.ToVector2();
// 사각형 길을 보여주기
if ((rpoint.X > wizardPosition.X - 64) && (rpoint.X < wizardPosition.X + 64) && (rpoint.Y > wizardPosition.Y - 150) && (rpoint.Y < wizardPosition.Y + 42) )
{
if (ShowBorder == true) { ShowBorder = false; }
else if (ShowBorder == false)
ShowBorder = true;
}
Does anybody have solved this problem?

I have solve myself. Anyway.
The code is this
var rpoint = e.GetCurrentPoint(this).Position.ToVector2();
// Invert the display transform, to convert pointer positions into simulation rendertarget space.
Matrix3x2 Mtransform;
Matrix3x2.Invert(transform, out Mtransform);
var xpoint = Vector2.Transform(rpoint, Mtransform);
// 사각형 길을 보여주기
if ((xpoint.X > wizardPosition.X - 64) && (xpoint.X < wizardPosition.X + 64) && (xpoint.Y > wizardPosition.Y - 150) && (xpoint.Y < wizardPosition.Y + 42) )
{
if (ShowBorder == true) { ShowBorder = false; }
else if (ShowBorder == false)
ShowBorder = true;
}

Related

How to limit pan to canvas edges?

I use fabricJS to edit an image, i've already implemented a zoom tool and a pan tool.
The paning method :
if (!this.isStartedAction) return;
var x = ev.e.screenX,
y = ev.e.screenY;
this.canvas.relativePan({ x: x - this.firstPositionPan.x, y: y - this.firstPositionPan.y });
this.firstPositionPan.x = x;
this.firstPositionPan.y = y;
Problem is, regardless if i zoomed or not, when i use the pan i can move my image outside the canvas. I would like to limit the move to the edge of the canvas but i don't know how to do.
Any suggestion?
Try this
canvas.on('mouse:move', function (e) {
if (isPanning && e && e.e) {
var delta = new fabric.Point(e.e.movementX, e.e.movementY);
canvas.relativePan(delta);
var canvasViewPort = canvas.viewportTransform;
var imageHeight = canvas.height * canvasViewPort[0];
var imageWidth = canvas.width * canvasViewPort[0];
var bottomEndPoint = canvas.height * (canvasViewPort[0] - 1);
if(canvasViewPort[5] >= 0 || -bottomEndPoint > canvasViewPort[5]) {
canvasViewPort[5] = (canvasViewPort[5] >= 0) ? 0 : -bottomEndPoint;
}
var rightEndPoint = canvas.width * (canvasViewPort[0] - 1);
if(canvasViewPort[4] >= 0 || -rightEndPoint > canvasViewPort[4]) {
canvasViewPort[4] = (canvasViewPort[4] >= 0) ? 0 : -rightEndPoint;
}
}
});

How to detect collision on certain sides of a rectangle in canvas using socket.io

I am learning multiplayer development and I was wondering how I would detect collision and not allow the player to move into the collision but allow them to move away from it. I currently have a collision detection setup that is server side when the player tries to move. Though this collision detection works perfectly when the players collide they can not move out of the collision and are stuck forever. Here is the code that i'm using server-side to detect when a player moves & or collides:
socket.on('moveEvent', function(data) {
var player = players[find(connections, this.id)]
var r1 = {
left: player.position.x,
top: player.position.y,
bottom: player.position.y + 100,
right: player.position.x + 100
}
var intersects = false;
for (var i = 0; i < players.length; i++) {
if (connections[i] != this.id) {
var currPlayer = players[i]
var r2 = {
left: currPlayer.position.x,
top: currPlayer.position.y,
bottom: currPlayer.position.y + 100,
right: currPlayer.position.x + 100
}
intersects = intersectRect(r1, r2)
}
}
console.log(intersects)
if (data.direction == "x+" && intersects == false) {
player.position.x = player.position.x - speed
}
if (data.direction == "y+" && intersects == false) {
player.position.y = player.position.y - speed
}
if (data.direction == "x-" && intersects == false) {
player.position.x = player.position.x + speed
}
if (data.direction == "y-" && intersects == false) {
player.position.y = player.position.y + speed
}
});
function intersectRect(r1, r2) {
socket.emit('checkPlayers', {
p1: r1,
p2: r2
})
if (!(r2.left > r1.right || r2.right < r1.left || r2.top > r1.bottom || r2.bottom < r1.top)) {
return true;
} else {
return false;
}
}
Here is the setInterval code that gets the new coordinates and draws them to the screen. I currently have an emit event in the intersectRect function that emits the two players it is checking the collision of. The server then takes that emit and prints out the two players it sends. This is strictly for bug fixing:
setInterval(function() {
if (w == true) {
socket.emit('moveEvent', {
direction: "y+",
id: sesID
})
}
if (a == true) {
socket.emit('moveEvent', {
direction: "x+",
id: sesID
})
}
if (s == true) {
socket.emit('moveEvent', {
direction: "y-",
id: sesID
})
}
if (d == true) {
socket.emit('moveEvent', {
direction: "x-",
id: sesID
})
}
gamectx.canvas.width = window.innerWidth;
gamectx.canvas.height = window.innerHeight;
gamectx.clearRect(0, 0, game.width, game.height);
socket.emit('request', {
request: "players",
id: sesID
});
for (var i = 0; i < players.length; i++) {
gamectx.fillStyle = "#ff0000"
gamectx.fillRect(((game.width / 2) + (players[i].position.x - player.position.x)) - 50, ((game.height / 2) + (players[i].position.y - player.position.y)) - 50, 100, 100)
}
gamectx.fillStyle = "#0000ff"
gamectx.fillRect((window.innerWidth / 2) - 50, (window.innerHeight / 2) - 50, 100, 100);
gamectx.font = "48px sans-serif";
gamectx.strokeText("x: " + GameX + ", y: " + GameY, 10, 50);
var playersList = ""
for (var i = 0; i < players.length; i++) {
playersList += "x: " + players[i].position.x + ", y: " + players[i].position.y + ", "
}
gamectx.font = "30px sans-serif";
gamectx.strokeText(playersList, 10, 100);
console.log(p1, p2)
}, 30);
So I think I may need to detect collisions on every side and not allow the player to moved in that direction when they collide OR move the player away from the collision when it happens. Thanks for your help in advance. Got no answers so I reposted this hoping for some. Thanks!

How do I reverse a scanline using the jpeg-js module/node JS buffer?

I've been fiddling around with the jpeg-js module and Node JS Buffer, and attempting to create a small command line program that modifies the decoded JPEG buffer data and creates a pattern of X number of reversed scanlines and X number of normal scanlines before saving a new JPEG. In other words, I'm looking to flip portions of the image, but not the entire image itself (plenty of modules that do such a thing, of course, but not the specific use case I have).
To create the reversed/normal line patterns, I've been reading/writing line by line, and saving a slice of that line to a variable, then starting at the end of scanline and incrementally going down by slices of 4 bytes (the alloc for an RGBA value) until I'm at the beginning of the line. Code for the program:
'use strict';
const fs = require('fs');
const jpeg = require('jpeg-js');
const getPixels = require('get-pixels');
let a = fs.readFileSync('./IMG_0006_2.jpg');
let d = Buffer.allocUnsafe(a.width * a.height * 4);
let c = jpeg.decode(a);
let val = false; // track whether normal or reversed scanlines
let lineWidth = b.width * 4;
let lineCount = 0;
let track = 0;
let track2 = 0;
let track3 = 0;
let curr, currLine; // storage for writing/reading scnalines, respectively
let limit = {
one: Math.floor(Math.random() * 141),
two: Math.floor(Math.random() * 151),
three: Math.floor(Math.random() * 121)
};
if (limit.one < 30) {
limit.one = 30;
}
if (limit.two < 40) {
limit.two = 40;
}
if (limit.two < 20) {
limit.two = 20;
}
let calc = {};
calc.floor = 0;
calc.ceil = 0 + lineWidth;
d.forEach(function(item, i) {
if (i % lineWidth === 0) {
lineCount++;
/* // alternate scanline type, currently disabled to figure out how to succesfully reverse image
if (lineCount > 1 && lineCount % limit.one === 0) {
// val = !val;
}
*/
if (lineCount === 1) {
val = !val; // setting alt scanline check to true initially
} else if (calc.floor + lineWidth < b.data.length - 1) {
calc.floor += lineWidth;
calc.ceil += lineWidth;
}
currLine = c.data.slice(calc.floor, calc.ceil); // current line
track = val ? lineWidth : 0; // tracking variable for reading from scanline
track2 = val ? 4 : 0; // tracking variable for writing from scanline
}
//check if reversed and writing variable has written 4 bytes for RGBA
//if so, set writing source to 4 bytes at end of line and read from there incrementally
if (val && track2 === 4) {
track2 = 0; // reset writing count
curr = currLine.slice(track - 4, track); // store 4 previous bytes as writing source
if (lineCount === 1 && lineWidth - track < 30) console.log(curr); //debug
} else {
curr = currLine; //set normal scanline
}
d[i] = curr[track2];
// check if there is no match between data source and decoded image
if (d[i] !== curr[track2]) {
if (track3 < 50) {
console.log(i);
}
track3++;
}
track2++; //update tracking variable
track = val ? track - 1 : track + 1; //update tracking variable
});
var rawImageData = {
data: d,
width: b.width,
height: b.height
};
console.log(b.data.length);
console.log('errors\t', track3);
var jpegImageData = jpeg.encode(rawImageData, 100);
fs.writeFile('foo2223.jpg', jpegImageData.data);
Alas, the reversed scanline code I've written does not properly. Unfortunately, I've only been able successfully reverse the red channel of my test image (see below left), with the blue and green channels just turning into vague blurs. The color scheme should look something like the right image.
What am I doing wrong here?
For reversed lines, you stored slices of 4 bytes(4 bytes = 1 pixel), then write the first value of the pixel(red) correctly.
But in the next iteration, you overwrite the slice curr with currLine, rest of channels gets wrong values.
if (val && track2 === 4) {
track2 = 0; // reset writing count
curr = currLine.slice(track - 4, track); // store 4 previous bytes as writing source
if (lineCount === 1 && lineWidth - track < 30) console.log(curr); //debug
} else {
curr = currLine; //set normal scanline
}
Iteration 0: val == true, track2 == 4, set curr to next pixel, write red channel.
Iteration 1: val == true, track2 == 1, (val && track2 === 4) == false, set curr to currLine, write green channel.
You can move track2 === 4 branch to avoid this:
if (val) {
if (track2 === 4) {
track2 = 0; // reset writing count
curr = currLine.slice(track - 4, track); // store 4 previous bytes as writing source
if (lineCount === 1 && lineWidth - track < 30) console.log(curr); //debug
}
} else {
curr = currLine; //set normal scanline
}
Fixed code should look like this:
function flipAlt(input, output) {
const fs = require('fs');
const jpeg = require('jpeg-js');
let a = fs.readFileSync(input);
let b = jpeg.decode(a);
let d = Buffer.allocUnsafe(b.width * b.height * 4);
let val = false; // track whether normal or reversed scanlines
let lineWidth = b.width * 4;
let lineCount = 0;
let track = 0;
let track2 = 0;
let track3 = 0;
let curr, currLine; // storage for writing/reading scnalines, respectively
let limit = {
one: Math.floor(Math.random() * 141),
two: Math.floor(Math.random() * 151),
three: Math.floor(Math.random() * 121)
};
if (limit.one < 30) {
limit.one = 30;
}
if (limit.two < 40) {
limit.two = 40;
}
if (limit.two < 20) {
limit.two = 20;
}
let calc = {};
calc.floor = 0;
calc.ceil = 0 + lineWidth;
d.forEach(function(item, i) {
if (i % lineWidth === 0) {
lineCount++;
if (lineCount > 1) {
val = !val;
}
if (lineCount === 1) {
val = !val; // setting alt scanline check to true initially
} else if (calc.floor + lineWidth < b.data.length - 1) {
calc.floor += lineWidth;
calc.ceil += lineWidth;
}
currLine = b.data.slice(calc.floor, calc.ceil); // current line
track = val ? lineWidth : 0; // tracking variable for reading from scanline
track2 = val ? 4 : 0; // tracking variable for writing from scanline
}
//check if reversed and writing variable has written 4 bytes for RGBA
//if so, set writing source to 4 bytes at end of line and read from there incrementally
if (val) {
if (track2 === 4) {
track2 = 0; // reset writing count
curr = currLine.slice(track - 4, track); // store 4 previous bytes as writing source
if (lineCount === 1 && lineWidth - track < 30) console.log(curr); //debug
}
} else {
curr = currLine; //set normal scanline
}
d[i] = curr[track2];
// check if there is no match between data source and decoded image
if (d[i] !== curr[track2]) {
if (track3 < 50) {
console.log(i);
}
track3++;
}
track2++; //update tracking variable
track = val ? track - 1 : track + 1; //update tracking variable
});
var rawImageData = {
data: d,
width: b.width,
height: b.height
};
console.log(b.data.length);
console.log('errors\t', track3);
var jpegImageData = jpeg.encode(rawImageData, 100);
fs.writeFile(output, jpegImageData.data);
}
flipAlt('input.jpg', 'output.jpg');
Instead of tracking array indices, you can use utility library like lodash, it should make things easier:
function flipAlt(input, output) {
const fs = require('fs');
const jpeg = require('jpeg-js');
const _ = require('lodash');
const image = jpeg.decode(fs.readFileSync(input));
const lines = _.chunk(image.data, image.width*4);
const flipped = _.flatten(lines.map((line, index) => {
if (index % 2 != 0) {
return line;
}
const pixels = _.chunk(line, 4);
return _.flatten(pixels.reverse());
}));
const imageData = jpeg.encode({
width: image.width,
height: image.height,
data: new Buffer(flipped)
}, 100).data;
fs.writeFile(output, imageData);
}
flipAlt('input.jpg', 'output.jpg');

Unable to upload svg images

I am using the following code in my event system to upload svg Images. But this gives "Parameter is not valid error" when saving the image. The following is the code I am using. Is there anything I am missing?? Any help would be really appreciated. Thanks in advance.
//only for imagaes: svg
if (mimeType.Contains("svg") && !String.IsNullOrEmpty(filename))
{
messageLog.WriteEntry("OnComponentSavePre - resizing image - for component: " + comp.Title);
// need to save first new component to be able to get type in next step
if (args.IsNewItem)
{
comp.Save();
}
BinaryContent bc = comp.BinaryContent;
var objConvertor = System.ComponentModel.TypeDescriptor.GetConverter(typeof(System.Drawing.Bitmap));
var bmpObj = (Bitmap)objConvertor.ConvertFrom(bc.GetByteArray());
//reades multimedia fields
ItemFields itemFields = new ItemFields(comp.Metadata, comp.MetadataSchema);
if (itemFields.Contains("MM_Width"))
{
NumberField width = itemFields["MM_Width"] as NumberField;
if (width != null && width.Value <= 0)
{
messageLog.WriteEntry("width = " + width.Value, EventLogEntryType.Information, 0, 0);
width.Value = bmpObj.Width;
}
}
if (itemFields.Contains("MM_Height"))
{
NumberField height = itemFields["MM_Height"] as NumberField;
if (height != null && height.Value <= 0)
{
messageLog.WriteEntry("width = " + height.Value, EventLogEntryType.Information, 0, 0);
height.Value = bmpObj.Height;
}
}
comp.Metadata = itemFields.ToXml();
messageLog.WriteEntry("metadata updated", EventLogEntryType.Information, 0, 0);
}

Optimising A* pathfinding, runs very slow. Possible bugs(?) visual c++

Hi I'm having a few problems with my A* pathfinding algorithm. The algorithm does successfully execute, however in a debug environment it executes in about 10 seconds, in release it will still take 2-3 seconds. This speed is way too slow. I suspect this is either due to a bug in the code, or the fact it isn't well optimised.
The map that pathfinding is being used on is a 30*30 grid, with each square being 10 unites away from one another.
I have noticed when running the algorithm, that when the open and closed list are searched to see if a node already exists, the node already stored in one of the lists always has a lower cost, so there is no updating of nodes. Not sure if this is normal or not. Also, I am not sure if quicksort is a good sort to be using in this situation.
Here is the code:
The coords struture used as a node:
struct coords
{
int x;
int z;
coords* parent;
int cost;
int score;
};
The sort compare function:
bool decompare(coords* o1, coords* o2)
{
return (o1->score < o2->score);
}
The main pathfind loop:
while (!goalFound) //While goal has not been found
{
current = openList.front(); //Retrieve current state from the open list
openList.pop_front();
for (int count = 1; count < 5; count++)
{
if (!goalFound)
{
coords* possibleState = new (coords); //Allocate new possible state
found = false;
if (count == 1)
{
possibleState->x = current->x;
possibleState->z = current->z + 10; //North
}
else if (count == 2)
{
possibleState->x = current->x + 10; //East
possibleState->z = current->z;
}
else if (count == 3)
{
possibleState->x = current->x; //South
possibleState->z = current->z - 10;
}
else if (count == 4)
{
possibleState->x = current->x - 10; //West
possibleState->z = current->z;
}
if (possibleState->x >-1 && possibleState->x <291 && possibleState->z >-1 && possibleState->z < 291) //If possible state is in game boundary
{
possibleState->cost = current->cost + 10; //Add 10 to current state to get cost of new possible state
int a = (possibleState->x / 10) + (30 * (possibleState->z / 10)); //get index of map
if (map[a] != wallTest) //Test possible state is not inside a wall
{
p = openList.begin();
while (p != openList.end() && !found) //Search open list to see if possible state already exists
{
if (possibleState->x == (*p)->x && possibleState->z == (*p)->z) //Already exists
{
found = true;
if (!possibleState->cost >= (*p)->cost) //Test possible state has lower cost
{
(*p)->parent = current; //Update existing with attributes of possible state
a = abs((*p)->x - goalState->x);
b = abs((*p)->z - goalState->z);
(*p)->cost = possibleState->cost;
(*p)->score = (possibleState->cost) + ((a)+(b));
}
}
else
{
found = false; //Set not found
}
p++;
}
q = closedList.begin();
while (q != closedList.end())
{
if (possibleState->x == (*q)->x && possibleState->z == (*q)->z)
{
found = true;
int a = (*q)->cost;
if (possibleState->cost < a) //Test if on closed list
{
(*q)->parent = current;
a = abs((*q)->x - goalState->x);
b = abs((*q)->z - goalState->z);
(*q)->cost = possibleState->cost;
(*q)->score = (possibleState->cost) + ((a)+(b)); //If cost lower push onto open list
coords* newcoord;
newcoord->x = (*q)->x;
newcoord->z = (*q)->z;
newcoord->score = (*q)->score;
newcoord->cost = (*q)->cost;
openList.push_back(newcoord);
closedList.erase(q);
}
}
q++;
}
if (!found) //If not found on either list
{
possibleState->parent = current; //Push onto open list
a = abs((possibleState)->x / 10 - goalState->x / 10);
b = abs((possibleState)->z / 10 - goalState->z / 10);
(possibleState)->score = (possibleState->cost) + ((a)+(b));
openList.push_back(possibleState);
}
sort(openList.begin(), openList.end(), decompare); // Sort the open list by score
}
if (possibleState->x == goalState->x && possibleState->z == goalState->z) //if goal found
{
openList.push_back(possibleState);
node = possibleState;
goalFound = true;
while (node != 0)
{
wayPoints.push_back(*node);
node = node->parent;
wayCount = wayPoints.size() - 1;
}
}
}
}
}
closedList.push_back(current);
}
player->setWayPoints(wayPoints);
wayPoints.clear();
player->setMoved(2);
player->setPath(1);
openList.clear();
closedList.clear();
goalFound = false;
player->setNewPath(1);
return true;
}
else {
return false;
}
}
Are there any bugs that need to be sorted in this code that anyone can see? Or is it just important optimizations that need making? Thanks

Resources