Unable to invoke JS function: Syntax mistake or eyes too crossed? - javascript

Happy holidays first of all.
I am unable to find the reason why I am unsuccessful at invoking the 'commands' function with its relative orders on this Javascript exercise. Have I messed up with the {}?
//// Rover object goes here ////
const rover = {
direction: "N",
x: 5,
y: 5,
travelLog: []
};
// ========================
//// Rover turns left switch case ////
function turnLeft(rover) {
switch (rover.direction) {
case "N":
rover.direction = "W";
break;
case "W":
rover.direction = "S";
break;
case "S":
rover.direction = "E";
break;
case "E":
rover.direction = "N";
break;
}
console.log("turnLeft was called!");
console.log(`Rover has now direction:"${rover.direction}"`);
}
//// Rover turns right switch case ////
function turnRight(rover) {
switch (rover.direction) {
case "N":
rover.direction = "E";
break;
case "W":
rover.direction = "N";
break;
case "S":
rover.direction = "W";
break;
case "E":
rover.direction = "S";
break;
}
console.log("turnRight was called!");
console.log(`Rover has now direction:"${rover.direction}"`);
}
//// Moving the rover ////
function moveForward(rover) {
console.log("moveForward was called!");
let newPosition = { x: rover.x, y: rover.y };
rover.travelLog.push(newPosition);
switch (rover.direction) {
case "N":
if (rover.y <= 0) {
console.log("you can't travel out there, bud");
} else {
rover.y--;
console.log(
`Rover moved North: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "E":
if (rover.x >= 9) {
console.log("you can't travel out there, bud");
} else {
rover.x++;
console.log(
`Rover moved East: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "S":
if (rover.y >= 9) {
console.log("you can't travel out there, bud");
} else {
rover.y++;
console.log(
`Rover moved South: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "W":
if (rover.x <= 0) {
console.log("you can't travel out there, bud");
} else {
rover.x--;
console.log(
`Rover moved West: position is now: ${rover.x} , ${rover.y}`
);
}
break;
}
}
//move backward//
function moveBackward(rover) {
console.log("moveBackward was called!");
let newPosition = { x: rover.x, y: rover.y };
rover.travelLog.push(newPosition);
switch (rover.direction) {
case "N": // Rover is facing North, but it will take one step backwards, hence direction South //
if (rover.y >= 9) {
console.log("watch your steps, don't trip");
} else {
rover.y++;
console.log(
`Rover moonwalked South: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "E": //moving direction South
if (rover.x <= 0) {
console.log("watch your steps, don't trip");
} else {
rover.x--;
console.log(
`Rover moonwalked West: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "S": // direction North
if (rover.y <= 0) {
console.log("watch your steps,don't trip");
} else {
rover.y--;
console.log(
`Rover moonwalked North: position is now: ${rover.x} , ${rover.y}`
);
}
break;
case "W": //direction East
if (rover.x >= 9) {
console.log("watch your steps, don't trip");
} else {
rover.x++;
console.log(
`Rover moonwalked East: position is now: ${rover.x} , ${rover.y}`
);
}
break;
}
//// Assigning commands ////
function commands(rover, orders) {
for (let i = 0; i < orders.length; i++) {
let order = orders[i];
switch (order) {
case "f":
moveForward(rover, order);
break;
case "b":
moveBackward(rover, order);
break;
case "r":
turnRight(rover, order);
break;
case "l":
turnLeft(rover, order);
break;
default:
console.log("Please use only 'r', 'f', 'b' or 'l'");
}
}
}
commands(rover,"ffbrl");
////printout all the rover's movements////
/*
for (let i = 0; i < rover.travelLog.length; i++) {
console.log(`Path ${i} ==> x=${rover.travelLog[i].x}, y=${rover.travelLog[i].y}`);
}
*/
}
Any input/suggestion will be greatly appreciated. I can't seem to find the mistake and it is quite infuriating. However, thank you again and have a lovely and festive time!

You need one more closing brace } at the end of the moveBackward function. You closed the switch statement but not the function.
Happy Holidays!

Related

Switch Statement running more than once

I'm back again, just as stumped as ever... I have gotten further with my game, but looking back at one part of the game, I have a check to see if you have potions, and if you do, and you try to use it, it calculates whether the current health and the added amount from the potion is more than the max health of the player. If it is then it tells you you cannot drink it, and if it isn't, then it lets you drink it. And then if you don't have any potions and you try to use it, then it tells you you don't have any.
The part I am having issue with, is that it is running twice, and I am not sure why. Here is a snippet of the Switch Statement:
while (currentarea == "Hero's Turn") {
if (hTurn == true) {
switch (classType) {
case "Warrior":
case "Archer":
switch (input) {
case "punch":
case "p":
Punch();
break;
case "kick":
case "k":
Kick();
break;
case "attack":
case "a":
Attack();
break;
case "health potion":
case "h":
HealthPotion();
break;
default:
}
case "Mage":
switch (input) {
case "fire":
case "f":
FireMagic();
break;
case "wind":
case "w":
WindMagic();
break;
case "frost":
case "c":
IceMagic();
break;
case "health potion":
case "h":
HealthPotion();
break;
case "mana potion":
case "m":
ManaPotion();
break;
default:
}
default:
}
return;
}
}
I tried to move the Archer to its own line and that just made it run three times. The issue is with the Warrior and Archer, the Mage only pushes the info once as intended.
This is the code for the function:
function HealthPotion() {
if (healthPotion.AmountOf < 1) {
$("<p>Sorry, you don't have any more of those.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
checkH();
return;
}
if (healthPotion.AmountOf != 0) {
if(battleHealth + healthPotion.Health <= maxHealth) {
$("<p>You regained some Health! You regained " + healthPotion.Health + " HP!</p>").hide().insertBefore("#placeholder").fadeIn(1000);
battleHealth += healthPotion.Health;
document.getElementById("battleHealth").innerHTML = battleHealth;
healthPotion.AmountOf--;
document.getElementById("healthPotion.AmountOf").innerHTML = healthPotion.AmountOf;
checkE();
return;
}
else {
$("<p>Your health isn't damaged enough for that! It would be a waste to use that right now.<br />Press enter to carry on.</p>").hide().insertBefore("#placeholder").fadeIn(1000);
checkH();
return;
}
}
}
Here is how I have the potion constructed:
var healthPotion = { //Recovers battle HP.
Name: "Health Potion",
Health: 20,
AmountOf: 5,
Value: 30,
}
This is where the loops go to (the enemy and the hero check):
function checkE() {
if (eHealth >= 1) {
currentarea = "Enemy's Turn";
document.getElementById("currentarea").innerHTML = currentarea;
hTurn = false;
eTurn = true;
return;
}
else if (eHealth <= 0) {
eHealth = 0;
document.getElementById("eHealth").innerHTML = eHealth;
currentarea = "Death";
win++;
document.getElementById("win").innerHTML = win;
hTurn = false;
eTurn = false;
return;
}
}
function checkH() {
if (battleHealth >= 1) {
currentarea = "Battle";
document.getElementById("currentarea").innerHTML = currentarea;
eTurn = false;
hTurn = true;
return;
}
else if (battleHealth <= 0) {
battleHealth = 0;
document.getElementById("battleHealth").innerHTML = battleHealth;
currentarea = "Death";
document.getElementById("currentarea").innerHTML = currentarea;
lose++;
document.getElementById("lose").innerHTML = lose;
return;
}
}
At this point I am completely stumped, as I have switch statements and nested functions in all of my coding at this point, but this is the only area I am seeing this issue.
My main browser is Firefox, but I I tested on Chrome and Edge, which both have the same results. IE will not play my game, mainly because I haven't coded it to do so yet.
I looked around at other's questions before posting here, and didn't see anything that matched up to this particular issue.
Looking in the Admin Console of each browser, no error was thrown, just the multiple lines of repeated verbage.
If you keep playing and taking damage enough to use the potion, you see this:
You break out of the inner switch, that break does nothing for the outer switch so when you have "Warrior" it does that case and since there is no break at its level, it goes to "Mage"
switch (classType) {
case "Warrior":
case "Archer":
switch (input) {
case "punch":
case "p":
Punch();
break;
case "kick":
case "k":
Kick();
break;
case "attack":
case "a":
Attack();
break;
case "health potion":
case "h":
HealthPotion();
break;
default:
}
break; // <-- YOU NEED THIS HERE
case "Mage":
switch (input) {
case "fire":
case "f":
FireMagic();
break;
case "wind":
case "w":
WindMagic();
break;
case "frost":
case "c":
IceMagic();
break;
case "health potion":
case "h":
HealthPotion();
break;
case "mana potion":
case "m":
ManaPotion();
break;
default:
}
break; // <-- YOU NEED THIS HERE IF YOU DO SOMETHING IN DEFAULT
default:
}

Move 2 images simultaniously with keyboard events?

I'm making a primitive typescript game for fun. So far everything works fine.
Player one moves around with ASWD and second player with HUJK.
These are the two events and they are declared in the constructor as so this.move(); and this.moveBug();
private move() {
window.addEventListener('keypress', (e: KeyboardEvent) => {
switch (e.keyCode) {
case 97:
this._player.move(-10, 0);
break;
case 119:
this._player.move(0, -10);
break;
case 100:
this._player.move(+10, 0);
break;
case 115:
this._player.move(0, +10);
break;
}
this.update();
});
}
private moveBug() {
window.addEventListener('keypress', (e: KeyboardEvent) => {
switch (e.keyCode) {
case 104:
this._bugPlayer.moveBug(-10, 0);
break;
case 117:
this._bugPlayer.moveBug(0, -10);
break;
case 107:
this._bugPlayer.moveBug(+10, 0);
break;
case 106:
this._bugPlayer.moveBug(0, +10);
break;
}
this.update();
});
}
However both images move turn based, I can't move them both at the same time.
I want this game to be playable on 1 keyboard.
Is there a way this can be achieved?
I would define the move function once and call it based on the pressed key. Here is a rough skeleton of the approach.
class Movement {
move(target, x, y) {
// handle move code...
}
constructor() {
const move = this.move;
window.addEventListener('keypress', (e: KeyboardEvent) => {
let charCode = e.which || e.keyCode;
switch (charCode) {
case 97:
move('player', -10, 0);
break;
case 119:
move('player', 0, -10);
break;
case 100:
move('player', +10, 0);
break;
case 115:
move('player', 0, +10);
break;
case 104:
move('bug', -10, 0);
break;
case 117:
move('bug', 0, -10);
break;
case 107:
move('bug', +10, 0);
break;
case 106:
move('bug', 0, +10);
break;
}
});
}
}
const m = new Movement();
https://jsfiddle.net/zp3vj7ma/

"this" function with parameter

I've got a class Robot as defined below. But for some reason there's an error with the processCommand function and I can't figure out what it is. It's the only function that takes a parameter so I'm wondering if there's something wrong with the way I pass it in the readCommands function?
Any help or opinion is appreciated!
function Robot(pos){
this.pos = pos;
this.language;
this.printCoords = function(){}
this.setLanguage = function() {}
this.setPos = function() {}
this.processCommand = function(s){
var direction = this.pos[2];
direction = direction.replace(" ", "");
if( (s.match('V') && this.language.match("svenska")) ||
(s.match('L') && this.language.match("engelska")) ){
switch(direction){
case "N":
// Look West
this.pos[2] = " W";
break;
case "E":
// Look North
this.pos[2] = " N";
break;
case "S":
// Look East
this.pos[2] = " E";
break;
case "W":
// Look South
this.pos[2] = " S";
break;
default:
break;
}
}
else if( (s.match('H') && this.language.match("svenska")) ||
(s.match('R') && this.language.match("engelska")) ){
switch(direction){
case "N":
// Look East
this.pos[2] = " E";
break;
case "E":
// Look South
this.pos[2] = " S";
break;
case "S":
// Look West
this.pos[2] = " W";
break;
case "W":
// Look North
this.pos[2] = " N";
break;
default:
break;
}
}
else if( (s.match('G') && this.language.match("svenska")) ||
(s.match('F') && this.language.match("engelska"))){
switch(direction){
case "N":
// Walk North
this.pos[1] += 1;
break;
case "E":
// Walk East
this.pos[0] += 1;
break;
case "S":
// Walk South
this.pos[1] -= 1;
break;
case "W":
// Walk West
this.pos[0] -= 1;
break;
default:
break;
}
}
this.printCoords();
}
this.readCommands = function() {
document.getElementById("textField").onkeyup = function(key){
key = window.event;
keyCode = key.keyCode || key.which;
if(keyCode == '13'){
var commandString = document.getElementById("textField").value;
for(var i = 0; i < commandString.length; i++){
this.processCommand(commandString[i]);
}
}
}
}
}
I believe your event handler, (function(key){}) isn't doing what you want it to do.
This is because in the context of an event handler invocation, this usually refers to the DOM element on which the event occurred, not the instance of Robot.
Try this code instead:
this.readCommands = function() {
var that = this;
document.getElementById("textField").onkeyup = function(key){
key = window.event;
keyCode = key.keyCode || key.which;
if(keyCode == '13'){
var commandString = document.getElementById("textField").value;
for(var i = 0; i < commandString.length; i++){
that.processCommand(commandString[i]);
}
}
}
}
This way, you store a reference to the actual object you want to call the method processCommand() on, and can invoke it in the event handler.
using the old that=this trick:
function Robot(pos){
this.pos = pos;
this.language;
this.printCoords = function(){}
this.setLanguage = function() {}
this.setPos = function() {}
this.processCommand = function(s){
var direction = this.pos[2];
direction = direction.replace(" ", "");
if( (s.match('V') && this.language.match("svenska")) ||
(s.match('L') && this.language.match("engelska")) ){
switch(direction){
case "N":
// Look West
this.pos[2] = " W";
break;
case "E":
// Look North
this.pos[2] = " N";
break;
case "S":
// Look East
this.pos[2] = " E";
break;
case "W":
// Look South
this.pos[2] = " S";
break;
default:
break;
}
}
else if( (s.match('H') && this.language.match("svenska")) ||
(s.match('R') && this.language.match("engelska")) ){
switch(direction){
case "N":
// Look East
this.pos[2] = " E";
break;
case "E":
// Look South
this.pos[2] = " S";
break;
case "S":
// Look West
this.pos[2] = " W";
break;
case "W":
// Look North
this.pos[2] = " N";
break;
default:
break;
}
}
else if( (s.match('G') && this.language.match("svenska")) ||
(s.match('F') && this.language.match("engelska"))){
switch(direction){
case "N":
// Walk North
this.pos[1] += 1;
break;
case "E":
// Walk East
this.pos[0] += 1;
break;
case "S":
// Walk South
this.pos[1] -= 1;
break;
case "W":
// Walk West
this.pos[0] -= 1;
break;
default:
break;
}
}
this.printCoords();
}
var that=this;
this.readCommands = function() {
document.getElementById("textField").onkeyup = function(key){
key = window.event;
keyCode = key.keyCode || key.which;
if(keyCode == '13'){
var commandString = document.getElementById("textField").value;
for(var i = 0; i < commandString.length; i++){
that.processCommand(commandString[i]);
}
}
}
}
}
That's a lot of code to quickly glance at and surmise an answer. But, this errors are typically a result of this not having the value you think it should.
It's important to recognize that the value of this changes based on the calling context of the function. A typical solution to solve errors like this is to store the value of this in a variable that can be referenced later, i.e.;
var self = this;
and then use self instead of this directly.

How to make a moving div restricted in an outside div?

So I have a div you move with your arrow keys, but how do I make it so it can't go outside the "border div"?
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 37: // Left
$("#cube").css("left", $("#cube").offset().left - 101);
break;
case 38: // Up
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 39: // Right
$("#cube").css("left", $("#cube").offset().left - 97);
break;
case 40: // Down
$("#cube").css("top", $("#cube").offset().top - 7);
break;
}
});
});
http://jsfiddle.net/SfKHN/
Here you go:- I tested in FF and Chrome and seems to be fine....
Demo
Probably this is not completely perfect but you can build on it. Key here is to get the margins of the parent right and make sure the cube's left/right/top/bottom doesn't go beyond it. Border width also should be considered. Another thing is your Step should be a multiple of its width/height(as it is a square)
$(document).ready(function(){
$(document).keydown(function(e) {
var cube = $("#cube");
var leftMargin = 0;
var rightMargin = $('#outside').position().left + $('#outside').width() - cube.width();
var topMargin =0;
var bottomMargin = $('#outside').position().top + $('#outside').height() - cube.height();
switch (e.which) {
case 37: // Left
var newLeft = parseInt(cube.position().left - 50);
if(leftMargin <= newLeft)
{
cube.css("left", newLeft);
}
break;
case 38: // Up
var newTop = parseInt(cube.position().top - 50);
if(topMargin <= newTop)
{
cube.css("top",newTop);
}
break;
case 39: // Right
var newRight = (cube.position().left + 50);
if(rightMargin > newRight)
{
cube.css("left", newRight);
}
break;
case 40: // Down
var newBottom = parseInt(cube.position().top + 50);
if(bottomMargin > newBottom)
{
cube.css("top", newBottom);
}
break;
}
});
});
You add simple if statements to make sure you haven't passed the border. Here's an example:
$(document).ready(function(){
$(document).keydown(function(e) {
switch (e.which) {
case 38: // Up
if( ( $("#cube").offset().top - 11 ) >= 0 )
$("#cube").css("top", $("#cube").offset().top - 11);
break;
case 40: // Down
if( ( $( "#cube" ).offset( ).top - 7 ) < ( 400 - 50 ) )
$("#cube").css("top", $("#cube").offset().top - 7 );
break;
}
});
});
You'd make similar changes to the left and right arrows
$(document).ready(function () {
var $out = $('#outside'),
w = $out.width(),
$cube = $('#cube'),
cw = $cube.outerWidth();
$(document).up(function (e) {
switch (e.which) {
case 37:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left !== 0) return left - cw;
});
break;
case 38:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== -1) return top - cw;
});
break;
case 39:
$cube.css('left', function (_, left) {
left = parseInt(left, 10);
if (left + cw < w) return left + cw;
});
break;
case 40:
$cube.css('top', function (_, top) {
top = parseInt(top, 10);
if (top !== 349) return top + cw;
});
break;
}
});
});
http://jsfiddle.net/QmBNC/

JQuery while keydown

How can i make a movement of a element while the user is "keydown" and then if he make "keyup" to stop the animation(movement), this is my code by now
$(document).ready(function(){
function checkKey(e){
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
if ($.browser.mozilla) {
$(document).keydown (checkKey);
} else {
$(document).keydown (checkKey);
}
})
i want to move the cube while the user press the key (down, left, up, right), not with every press, is possible?
You need a simple 2D engine that will setup a game loop.
Simple demo: http://jsfiddle.net/kzXek/
Source: https://github.com/superrob/simple-2D-javascript-engine/blob/master/simple2d.html
Is that you are looking for?
$(document).on("keyup", function() {
$("#cube").stop(true);
});
DEMO: http://jsfiddle.net/LjGRe/
you can just change the checkKey function, and add this to it :
function checkKey(e){
$(document).keyup(return);
switch (e.keyCode) {
case 40:
//alert('down');
$('#cube').animate({top: "+=20px"})
break;
case 38:
//alert('up');
$('#cube').animate({top: "-=20px"})
break;
case 37:
//alert('left');
$('#cube').animate({left: "-=20px"})
break;
case 39:
//alert('right');
$('#cube').animate({left: "+=20px"})
break;
default:
alert('???');
}
}
I think using a timer to handle the animation is better.
You just start the timer when a key is pressed and stop it when the key is released ..
Here is a simple solution that handles multiple keypresses (can move diagonally)
var direction = {top:0,left:0},
animator = null,
cube = $("#cube");
function animate(){
cube.css({
top: '+=' + direction.top,
left: '+=' + direction.left
});
}
function setProperties(keyCode, unset){
switch (keyCode) {
case 40:
direction.top = (unset)?0:2;
break;
case 38:
direction.top = (unset)?0:-2;
break;
case 37:
direction.left = (unset)?0:-2;
break;
case 39:
direction.left = (unset)?0:2;
break;
}
}
function setKey(e) {
setProperties(e.keyCode);
if (animator === null){
animator = setInterval(animate, 10);
}
}
function unsetKey(e){
setProperties(e.keyCode, true);
if (direction.top === 0 && direction.left === 0){
clearTimeout(animator);
animator = null;
}
}
$(document)
.on("keyup", unsetKey)
.on('keydown', setKey);
Demo at http://jsfiddle.net/gaby/Cu6nW/

Categories

Resources