Reverse image on keydown - Javascript - javascript

What I am trying to implement here is that I have a character on my screen and I can move it around to the left, right, up and down with a press on my arrow keys.
What I want to do is when I click to the left is that the image will reverse and when I click to the right and it should reverse back, with this the character is always facing the way it walks.
My code looks like this where I define the original image and the reversed one:
Game.Hero = function (myX, myY){
var my = new createjs.Bitmap("img/hero.png");
my.reverseHero = function (){
my.image.src = "img/hero-1.png";
};
Then I have a code snippet here that shows how I am trying to work this thing out:
my.moveBy = function(dirX, dirY){
var testX = my.posX + dirX;
var testY = my.posY + dirY;
if (testX < 0 || testY < 0 || testX > 21 || testY > 8){
return;
}
if (dirX === -1){
my.reverseHero();
} else if (dirX === 1) {
Game.stage.addChild(Game.hero);
}
My problem at this moment, is that when I walk to the left, the image will actually reverse, but when I try to go to the right again, the image will not reverse.
So the code is actually only running the first if statement and just keeps hanging on there.
Do you have any suggestions what could be wrong ?

Aren't you supposed to reset the image after you set it?
This means setting a second function to return the hero to his original image. Because now it just sets your character to the other image when that action is called, but that keeps that image set, even when that action isn't called anymore.
Game.Hero = function (myX, myY){
var my = new createjs.Bitmap("img/hero.png");
my.reverseHero = function (){
my.image.src = "img/hero-1.png";
};
my.returnHero = function(){
my.image.src = "img/hero.png";
};
Then, in the else if statement, call that function
my.moveBy = function(dirX, dirY){
var testX = my.posX + dirX;
var testY = my.posY + dirY;
if (testX < 0 || testY < 0 || testX > 21 || testY > 8){
return;
}
if (dirX === -1){
my.reverseHero();
} else if (dirX === 1) {
Game.stage.addChild(Game.hero);
my.returnHero();
}
Does this make sense to you, or should I clarify some more?

What's going wrong is that you initialize the image with "img/hero.png", then change that for "img/hero-1.png". This is fine, however, when you call the reverseHero method a second time it won't put back the old image ("img/hero.png").
You can change this by implementing something like this:
var direction = true; // true means forward, false means backwards
my.reverseHero = function (){
my.image.src = direction ? "img/hero-1.png" : "img/hero.png";
direction = !direction;
};

Related

javascript text animation delay issues

Okay, so I have created this javascript text-animation that has a delay when writing text to
my p element "output". The animation works just fine...but I decided that I wanted to add text color to specific words in my "message" parameter. I made that happen by using this code:
function write(message,clear,delay) {
if(clear == true) clearMessage();
if(typeof delay != "number") delay = game.message.delay;
let q = undefined;
let output = document.getElementById("output");
let applyingColor = false;
let dest = output;
for(var i = 0 ; i < message.length ; i++) {
let cur = i;
let letter = message.charAt(i);
let wait = delay*i;
q = setTimeout(() => {
if(letter == "<") {
letter = "";
applyingColor = true;
let color = undefined;
let a = message.substring(cur+1,message.length);
let colorSig = a.substring(0,a.indexOf("/"));
color = colorSig;
let span = document.createElement("span");
span.style.color = color;
output.appendChild(span);
dest = span;
} else if(letter == ">") {
letter = "";
dest = output;
} else if(letter == "|") {
letter = "<br>";
}
if(applyingColor) {
if(letter != "/") {
return;
} else {
applyingColor = false;
return;
}
}
dest.innerHTML += letter;
},wait);
writingQueue.push(q);
}
}
the code above delays each character while also checking for very specific text such as
<rgb(255,0,0)/ this is red>. the "<" and the ">" are starting and ending signifiers for the colored text, while the "/" is used to mark where the end of the color goes. The text you want to be colored would go before ">" and after "/". and that makes it red! or any color you want. But I noticed a small detail. Whenever you use this, it creates an additional delay. For example if you did something like...
write("Hello, foo! My name is <red/ bar>!");
it would delay the "b" in "bar" longer than it would delay the "f" in "foo".
I think the problem is being caused by
if(applyingColor) {
if(letter != "/") {
return
} else {
applyingColor = false
return
}
}
at around the bottom body of the q = setTimeout(...).
What this code above does is skip over any letters that are not "/" while applyingColor is true, then turns it to false when it eventually reaches that wonderful little marker ("/") and returns one last time.
Honestly I dont know how to fix this. I've been working on this for hours now and my head hurts a lot. I could really use some help!
Oh! I forgot to mention. You can just ignore the "clear" and "delay" parameters. I do not believe they are relevant to my issue. The delay parameter is just the delay between each character. I have it to where it has a default value right now. And clear is just to clear previous text and clear out the writingQueue variable.
The problem in your current code is that as i increases over every iteration, so wait is being recalculated every check.. The first time it's 0 * delay, the second 1 * delay, the third 2 * delay. The solution while implementing only the current code would be to just define wait outside of the for loop.
buggy
let delay = 3;
for(var i = 0 ; i < 93 ; i++) {
let wait = delay * i;
}
let delay = 3;
let wait = 3 * 3;
for(var i = 0 ; i < 93 ; i++) {
}
good
However, there is an even better way to do javascript animations like the one you made, assuming you want them all to take the same amount of time (given your problem, as I understand it, is that the later letters are taking longer <?>) & you're making a webpage
window.requestAnimationFrame(function)
which will wait until the next frame to execute the code, making it always happen with the illusion of no delay to the user
suboptimal
q = setTimeout(() => if(letter == "<") {
/*...*/
faster, very rarely skips frames
q = window.requestAnimationFrame(() => if(letter == "<") {
/*...*/
if you want the letters to change all at once, you can just put the entire
for loop in a function and then call it using window.requestAnimationFrame(function).
window.requestAnimationFrame(colorIn);
function colorIn() {
for(var i = 0 ; i < message.length ; i++) {
let letter = message.charAt(i);
if(letter == "<") {
/*...*/
which will either make the letters changed all at once. if it can't, they'll change after dropping a few frames- though that should only happen if your computer has a virus or you change the color of an absolutely massive string

why does my a star algorithm not work in javascript?

function algorithm(){
if(startPoint === true && endPoint === true){
//add the heuristic distance to the start position from the final position
startPosition.h = distance([startPosition.x, startPosition.y]);
let openList = []
openList.push(startPosition)
let closedList = []
while (openList.length > 0){
//print(openList)
lowPos = 0;
for(let i = 0; i < openList.length; i++){
if(openList[i].f < openList[lowPos].f){
lowPos = i;
}
}
let currentPosition = openList[lowPos];
//currentPosition.check()
//if the currentPosition is the endPosition, retrace steps and find the path, then return this path
if(currentPosition === endPosition){
let curr = currentPosition;
let ret = [];
while(curr.parent != null){
curr.path()
ret.push(curr);
curr = curr.parent;
}
endPosition.end()
return ret.reverse();
}
openList.splice(lowPos, 1);
closedList.push(currentPosition);
let neighbours = neighbors(currentPosition);
for(let i = 0; i < neighbours.length; i++){
let neighbour = neighbours[i];
if(closedList.includes(neighbour) || neighbour.colour == "black"){
continue;
}
neighbour.check()
let gScore = currentPosition.g + 1;
let gScoreBest = false;
if(openList.includes(neighbour) == false){
gScoreBest = true;
neighbour.h = distance([neighbour.x, neighbour.y]);
openList.push(neighbour);
}
else if(gScore < neighbour.g){
gScoreBest = true;
}
if(gScoreBest == true){
neighbour.parent = currentPosition;
neighbour.g = gScore;
neighbour.f = neighbour.g + neighbour.h;
}
}
}
}
//meaning that either the path is not possible or the final node/initial node
has not yet been placed.
return [];
}
this is my a star algorithm in p5, i'm trying to make an a star visualisation project, but for some reason a lot more of blocks are highlighted than expected.
[: https://i.stack.imgur.com/ILlOr.png
In reality it is supposed to be something like this: : https://i.stack.imgur.com/nsF5r.png
The second picture isn't mine, its from someone else's implementation: https://qiao.github.io/PathFinding.js/visual/ = link to the second picture
I think it's something to do with the order of the line: neighbour.check() which changes the colour of the block.
Here is a diagonal solution, as you can see for some reason there is purple in the top left, that is my issue. The top left should not be searched, but it is for some reason.
If you need more of my code, please let me know.
It looks like you are not checking the diagonals.
It is not a mistake. You are doing great.
I got it to fix, surprisingly the thing that was wrong was my distance formulae, I called the wrong variable.
here's what it looks like now! :)

Recursion to return check both array[i+1] and array[i-1]

I'm making a timeline, and want to layer 'activities' based on how many overlaps occur.
I've found several answers on stack overflow on how to count overlapping intervals, though in my case I want the count to increase when an the overlap is indirect.
I've come up with the following recursive method:
countOverlaps: function(i, allItems) {
var currentItem = allItems[i];
// Declare position variables
var currentItemStart = this.getStartTimeMinutes(currentItem.timeStartString);
var currentItemEnd = currentItemStart + currentItem.duration;
var nextItemStart = (i < allItems.length - 1) ? this.getStartTimeMinutes(allItems[i + 1].timeStartString) : null;
var nextItemEnd = (nextItemStart != null) ? nextItemStart + allItems[i + 1].duration : null;
var prevItemStart = (i >= 1) ? this.getStartTimeMinutes(allItems[i - 1].timeStartString) : null;
var prevItemEnd = (prevItemStart != null) ? prevItemStart + allItems[i - 1].duration : null;
// The logic
// If the next item is an overlap, test the next item
// If the previous item is an overlap, test the previous item
if (currentItemEnd > nextItemStart && currentItemStart < nextItemEnd && nextItemStart != null) {
return 1 + this.countOverlaps((i + 1), allItems); // BUT how do I do the same for the previous one?
} else {
return 0;
}
},
But now I'm stuck. I think it's working how I want, except that it's only counting forward. If I want to check backwards and forward, will each recursive call not test the same index again and again?
Like all recursions you do something with only ONE element/ item in the function. Remember the terminiation - this is the most important thing in a recursion (no it is not the self call, because without it it won't be a recursion at all).
After that you will call yourself with another modified parameter.
Since I understand you correctly you want to start somewhere and go to left and right as far you want. Look at the terminiation code. You should change the condition to your needs.
The start sum left and sum right is not part of the recursion, because you only want to go in one direction per recursion.
This code is simple so you can easly adapt it to you need.
function sum(index, array){
function sumRecursion(index, array, direction){
// the termination ;)
if (index < 0) return 0;
if (index > array.length) return 0;
// do some stuff with your array at the current index.
// sorry, I did'nt read your logic code
var count = ...
// now the recursion
return count + sum(index + direction, array, direction);
}
return sumRecursion(index, array, -1) + sumRecursion(index, array, +1);
}

Simple JavaScript game [Mastermind] issue

I am coding a simple JavaScript version of the classic boardgame "Mastermind".
I have some (for sure fundamental) problems, 99% with JavaScript arrays and referencing their values or elements. These issues am I "solving" currently for quite long time, so I decided to ask.
Facts:
my game pegs, and the game board at all is made in HTML table, pegs are implemented like this(a row contains 4 pegs and a td containing the results image):
<td>
<a href="javascript:void(0)"
onClick="changePegColor('0','0'); return false"
onFocus="this.blur()">
<img src="img/void.png" width=22 height=22 name="peg_0_0">
</a>
</td>
my default array declaration looks this (showing both variants tried, none of them worked for me):
var pegsAI = ['pegAI_0', 'pegAI_1', 'pegAI_2', 'pegAI_3'];
var pegsAI = new Array('pegAI_0', 'pegAI_1', 'pegAI_2', 'pegAI_3');
Setting AI's pegs, which is the player going to guess works this way (this is working, no problem with array):
pegsAI[position] = Math.floor((Math.random() * possibleColorsNumber));
And here are my issues:
At the moment of clicking Submit button, there is a check if every peg in a row has a colour this way (this does neither work, nor throws an error in chrome F12):
...
for (var position = 0; position <= 3; position++) {
if (document["peg_" + currentRow + "_" + position].src === "img/void.png") {
alert('Finish color picking!');
return false;
}
}
...
After this check, there is function that should convert players pegs to numbers and save it to an array and there is probably a problem, because it doesn't work (array got undefined values in result):
function convertToNumbers() {
for (var position = 0; position <= 3; position++) { //4 pegs in row, var 'position' declares peg's position
if (document["peg_" + currentRow + "_" + position].src === possibleColors[index] ) { //if a peg has an color (his img's src is equal to an element of array 'possibleColors', which contains possible img's src's), then ->
pegsPlayer[position] = index; // -> then index of this color saves to pegsPlayer[] array
}
}
}
///added for explanation
my function for calculating score:
var goodPegPlayer = [false, false, false, false];
var goodPegAI = [false, false, false, false];
function calcSkore() {
convertToNumbers();
alert("array values" + pegsPlayer[0] + "_" + pegsPlayer[1] + "_" + pegsPlayer[2] + "_" + pegsPlayer[3]);
for (var position = 0; position <= 3; position++) {
goodPegPlayer[position] = false;
goodPegAI[position] = false;
if (pegsPlayer[position] === pegsAI[position]) {
skoreBlack++;
goodPegPlayer[position] = true;
goodPegAI[position] = true;
}
}
for (var position = 0; position <= 3; position++) {
if (goodPegPlayer[position] === false) {
for (var positionAI = 0; positionAI <= 3; positionAI++) {
if ((position !== positionAI) && (goodPegPlayer[position] === false) && (goodPegAI[positionAI] === false)) {
if (pegsPlayer[position] === pegsAI[positionAI]) {
skoreWhite++;
goodPegPlayer[position] = true;
goodPegAI[positionAI] = true;
}
}
}
}
}
resultsSubmit();
}
!! right after using converToNumber() function in this function, an alert() is used to check if the values are correct.
You're not accessing the DOM correctly. Try using the id attribute instead of name to identify your images and update your JavaScript as follows:
for (var position = 0; position <= 3; position++) {
var id = "peg_" + currentRow + "_" + position;
if (document.getElementById(id).src === "img/void.png") {
alert('Finish color picking!');
return false;
}
}
I wrote my own version of Mastermind back in 2004.
The code is a bit outdated, but it still works in modern browsers. I'm not sure if it's helpful to you, but feel free to take a look!
The code is MIT licensed, which means you can freely use it (or parts of it) anywhere you want!
Resources
Demo
Github repository

How to detect circle gesture direction?

THis is my code gist.
Leap.loop({enableGestures: true}, function(frame) {
var gestures = frame.gestures;
for (var i = 0; i < gestures.length; i++) {
// I want to do something when draw circle with one pointable
if (gesture.type == "circle" && gesture.state == "stop" && gesture.pointableIds.length == 1) {
var isClockWise = ? ;// how to know the direction of circle ?
}
}
} );
How to know circle is clockwise or counter clock wise with gesture object ?
I was using leap motion only 2 days and really need your help.
Leap.loop({enableGestures: true},function(frame) {
var gestures = frame.gestures,
circle,
pointable,
direction,
normal;
// Check if is there any gesture going on
if(gestures.length > 0) {
// In this example we will focus only on the first gesture, for the sake of simplicity
if(gestures[0].type == 'circle') {
circle = gestures[0];
// Get Pointable object
circle.pointable = frame.pointable(circle.pointableIds[0]);
// Reset circle gesture variables as nedded, not really necessary in this case
if(circle.state == 'start') {
clockwise = true;
} else if (circle.state == 'update') {
direction = circle.pointable.direction;
// Check if pointable exists
if(direction) {
normal = circle.normal;
// Check if product of vectors is going forwards or backwards
// Since Leap uses a right hand rule system
// forward is into the screen, while backwards is out of it
clockwise = Leap.vec3.dot(direction, normal) > 0;
if(clockwise) {
//Do clockwose stuff
} else {
//Do counterclockwise stuff
}
}
}
}
}
});
Looking on the C++ sample given on the leap website, piece of code is given to detect is the circle is clockwise.
C++ code :
if (circle.pointable().direction().angleTo(circle.normal()) <= PI/4)
{
clockwiseness = "clockwise";
}
else
{
clockwiseness = "counterclockwise";
}
I haven't used the Javascript API, but I think this can be something equivalent
This code hasn't been tested, but in Javascript it may be something like :
// considere your gesture is a circle, and there is at least one pointable object.
if (gesture.type == "circle" && gesture.state == "stop" && gesture.pointableIds.length >= 1)
{
var dir = frame.pointables[gesture.pointableIds[0] ].direction; // get direction of the Pointable used for the circle gesture
var angle = dir.AngleTo (circle.normal);
var isClockWise = angle <= (3.14 / 4);
}
Got all infos from Leap JS API from GitHub and Leap Motion Developers site
-> Be careful frame.pointables return pointables objects given in arbitrary order.(Cf JS API doc). This piece of code is just for the explanation of the algorithm
This is the easiest way to find out
var isClockwise = (circleGesture.normal[2] <= 0);
It will return true or false
Tried other answers on this page and couldn't get it to work, simplified the code a bit and finally got it working. The pointableID logs normal as negative/positive based on direction of the circle gesture.
function pageScrollDown() {
window.scrollBy(0,10);
};
function pageScrollUp(){
window.scrollBy(0,-15);
};
$(window).bind('circle', function(e, gesture){
var circle = gesture;
circle.pointable = circle.pointableIds[0];
direction = gesture.normal[1];
if(direction < 0 ) {
pageScrollDown();
} else {
pageScrollUp();
}
});
I have been using the "Leap Cursor library" for my project and it is really cool. Identifying a circle gesture on a element is very simple with this library.
var circleTrackElements = document.querySelectorAll(".myDOMElements");
for (var i = 0; i < allTiles.length; i++) {
circleTrackElements[i].addEventListener("leap-circle-stop", function(e) {
console.log("CIRCLE DETECTED");
});
};
LeapManager.init({
maxCursors : 1,
interactiveSelector : ".myDOMElements"
});
GITHUB link for the library

Categories