I'm trying to get 2 objects locations, so I can make the AI I coded to not walk through walls. My problem is that it's ignoring any extra if statements when I add them to the script.
function findEntities() { //Function for finding the players position and setting the playerLeft and playerTop variables
playerLeft = parseInt(player.style.left);
playerTop = parseInt(player.style.top);
enemyLeft = parseInt(enemy.style.left);
enemyTop = parseInt(enemy.style.top);
WallLeft = parseInt(wall.style.left);
WallTop = parseInt(wall.style.top);
chooseMovement();
setTimeout(findEntities, 1000) //starting a loop.
}
findEntities();
function chooseMovement() { //Chooses the direction to move, moves on X-axis first, then Y-axis
if((playerLeft - 64) > enemyLeft) || ((WallLeft - 64) != enemyLeft) {
Right();
} else if((playerLeft + 64) < enemyLeft) {
Left();
} else if((playerTop + 64) < enemyTop) {
Up();
} else if((playerTop - 64) > enemyTop) {
Down();
} else {
damagePlayer();
}}
function Right() { //Moves the enemy right
enemy.style.left = parseInt(enemy.style.left) + 64;
enemyLeft += 64;
}
function Left() { //Moves the enemy left
enemy.style.left = parseInt(enemy.style.left) - 64;
enemyLeft -= 64;
}
function Up() { //Moves the enemy up
enemy.style.top = parseInt(enemy.style.top) - 64;
enemyTop -= 64;
}
function Down() { //Moves the enemy down
enemy.style.top = parseInt(enemy.style.top) + 64;
enemyTop += 64;
}
I'm honestly not sure what exactly is giving you issues, but one thought is to maybe define the "checks" as their own function, for example:
function chooseMovement() {
if(checkMoveRight()) {
Right();
} else if((playerLeft + 64) < enemyLeft) {
Left();
} else if((playerTop + 64) < enemyTop) {
Up();
} else if((playerTop - 64) > enemyTop) {
Down();
} else {
damagePlayer();
}
}
function checkMoveRight(){
if(playerLeft - 64 > enemyLeft){ return true }
if(WallLeft - 64 != enemyLeft){ return true }
return false
}
This introduces it's own set of problems when it comes to complexity and state and what not but extracting things out into their own definitions rather than trying to have everything exist in the primary/singular if/else call thread might be useful.
Related
I'm new to Javascript, I'm working on a small game to get a better handle of it. I'm trying to define a character object with methods, but for some reason I'm getting weird errors from my IDE, "Label 'updateHealth' on function statement, Missing name in function declaration". I'm just trying to figure out what I'm doing wrong. In my code, display is how the character's health display's on the screen.
function Character(display) {
this.health = 100;
this.display = display;
// updates the health on the screen
updateHealth: function() {
if(health == 100) {
this.display.innerText = 'HP: ' + health;
}
else if(health > 10 && health < 100) {
this.display.innerText = 'HP: 0' + health;
}
else if(health < 10 && health > 0) {
this.display.innerText = 'HP: 00' + health;
}
else {
this.display.innerText = 'HP: 000';
}
}
// returns true if character has died
checkForDeath: function() {
if(health <= 0) return true;
else return false;
}
// function used when damage is inflicted on
// a character object
takeDamange: function(damage) {
this.health -= damage;
}
// handles the four possible moves
// opponent is null because if player heals
// then it does not make sense for there to be
// an opponent
makeMove: function(move, opponent=null) {
switch(move) {
case 'PUNCH':
opponent.takeDamage(parseInt(Math.random() * 100) % 10);
opponent.updateHealth();
break;
case 'HEAL':
this.health += 20;
break;
case 'KICK':
opponent.takeDamage(parseInt(Math.random() * 100) % 20);
opponent.updateHealth();
break;
case 'EXTERMINATE':
opponent.takeDamage(opponent.health);
opponent.updateHealth();
break;
}
return opponent.checkForDeath();
}
}
Object's can be instantiated via a constructor function such as your Character() function however, you'll need to ensure object methods (such as updateHealth(), etc) are "attached" to the instance of the character object.
One way to achieve that is via the this keyword:
/* Attach the checkForDeath() function as a method of "this" Character instance */
this.checkForDeath = function() {
/* Accessing "this" corresponds to the instance of the character object */
if (this.health <= 0) return true;
else return false;
}
By making these changes, checkForDeath() is now defined as a member function of the corresponding character instance. You'll need to ensure that you access fields on the instance via this, as shown on this line if(this.health <= 0) { ... }
You'll also need to ensure that you instantiate instances of Character via the new operator like this:
const characterInstance = new Character( someElement );
Here is a revised version of your code demonstrating this approach:
function Character(display) {
this.health = 100;
this.display = display;
this.updateHealth = function() {
const health = this.health; /* Add this */
if (this.health == 100) {
this.display.innerText = 'HP: ' + health;
} else if (health > 10 && health < 100) {
this.display.innerText = 'HP: 0' + health;
} else if (health < 10 && health > 0) {
this.display.innerText = 'HP: 00' + health;
} else {
this.display.innerText = 'HP: 000';
}
}
this.checkForDeath = function() {
if (this.health <= 0) return true;
else return false;
}
this.takeDamange = function(damage) {
this.health -= damage;
}
this.makeMove = function(move, opponent = null) {
switch (move) {
case 'PUNCH':
opponent.takeDamage(parseInt(Math.random() * 100) % 10);
opponent.updateHealth();
break;
case 'HEAL':
this.health += 20;
break;
case 'KICK':
opponent.takeDamage(parseInt(Math.random() * 100) % 20);
opponent.updateHealth();
break;
case 'EXTERMINATE':
opponent.takeDamage(opponent.health);
opponent.updateHealth();
break;
}
return opponent.checkForDeath();
}
}
const player = new Character( document.querySelector('p') );
player.takeDamange();
player.updateHealth();
<p></p>
change : to =, and assign it to a local property, such as
this.updateHealth = function() {
...
}
I'd recommend using the class syntax.
class Character {
constructor(display) {
this.health = 100;
this.display = display;
}
// updates the health on the screen
updateHealth() {
this.display.innerText = `HP: ${Math.max(health, 0).toString().padStart(3, '0')}`;
}
// returns true if character has died
checkForDeath() {
return health <= 0;
}
// function used when damage is inflicted on
// a character object
takeDamange(damage) {
this.health -= damage;
}
// handles the four possible moves
// opponent is null because if player heals
// then it does not make sense for there to be
// an opponent
makeMove(move, opponent = null) {
switch (move) {
case 'PUNCH':
opponent.takeDamage(parseInt(Math.random() * 100) % 10);
opponent.updateHealth();
break;
case 'HEAL':
this.health += 20;
break;
case 'KICK':
opponent.takeDamage(parseInt(Math.random() * 100) % 20);
opponent.updateHealth();
break;
case 'EXTERMINATE':
opponent.takeDamage(opponent.health);
opponent.updateHealth();
break;
}
return opponent.checkForDeath();
}
}
I also did some slight refactoring, which should make it easier to understand what is happening.
I'm doing this exercise with JavaScript and we're supposed to create a ninja pacman-style game with Javascript and then keep score. The ninja eats sushis and I'm doing one point per sushi.
The current behavior is that I can store scores when the ninja goes up or down. Problem is that when the ninja moves horizontally, the score only counts the first sushi. Second and third sushis aren't counted. I did use the same logic for vertical and horizontal moving around.
Here is my code. Added the whole code for context, but the problematic part is after "document.onkeydown = function(e) {".
<script type="text/javascript">
var world = [
[1,1,1,1,1],
[1,0,2,2,1],
[1,2,1,2,1],
[3,2,2,2,3],
[1,2,1,2,1],
[1,2,2,2,1],
[3,2,1,2,3],
[1,2,2,2,1],
[1,1,1,3,1],
]
var worldDict = {
0 : 'blank',
1 : 'wall',
2 : 'sushi',
3 : 'onigiri'
}
var ninjaScore = 0;
function drawWorld() {
var output = "";
for (var row = 0; row < world.length; row++) {
output += "<div class='row'></div>"
for (var x = 0; x <world[row].length; x++) {
output += "<div class='" + worldDict[world[row][x]]+"'></div>"
}
output += "</div>"
}
document.getElementById('world').innerHTML = output;
}
drawWorld();
var ninjaman = {
x: 1,
y: 1
}
function drawNinjaMan() {
document.getElementById('ninjaman').style.top = ninjaman.y * 40 + "px"
document.getElementById('ninjaman').style.left = ninjaman.x * 40 + "px"
}
drawNinjaMan();
document.onkeydown = function(e) {
if (e.keyCode == 40) { //DOWN
if (world[ninjaman.y + 1][ninjaman.x] != 1) {
ninjaman.y++;
if (world[ninjaman.y + 1][ninjaman.x] == 2) { //Checking if next block is sushi; adding to score
ninjaScore = ninjaScore + 1;
}
}
}
if (e.keyCode == 38) { //UP
if (world[ninjaman.y - 1][ninjaman.x] != 1) {
ninjaman.y--;
if (world[ninjaman.y - 1][ninjaman.x] == 2) { //Checking if next block is sushi; adding to score
ninjaScore = ninjaScore + 1;
}
}
}
if (e.keyCode == 37) { //LEFT
if (world[ninjaman.y][ninjaman.x - 1] != 1) {
ninjaman.x--;
if (world[ninjaman.y][ninjaman.x - 1] == 2) { //Checking if next block is sushi; adding to score
//Somehow this is returning false on the second key press; need to check why
ninjaScore = ninjaScore + 1;
}
}
}
if (e.keyCode == 39) { //RIGHT
if (world[ninjaman.y][ninjaman.x + 1] != 1) {
ninjaman.x++;
if (world[ninjaman.y][ninjaman.x + 1] == 2) { //Checking if next block is sushi; adding to score
//Somehow this is returning false on the second key press; need to check why
ninjaScore = ninjaScore + 1;
}
}
}
world[ninjaman.y][ninjaman.x] = 0;
drawWorld()
drawNinjaMan()
}
Could anyone please point out what I'm getting wrong?
Also, to give credit: This is an exercise from the pre-bootcamp course at Coding Dojo (https://www.codingdojo.com/). They came up with most of the code and the exercise itself.
I think it's because you're moving the ninja on top of a sushi, and then checking the block ahead of the block you are on in the direction you are moving. And all your motions are wrong, up, down, left and right.
This should fix it.
https://plnkr.co/edit/VCsa2cTWYaUn2jiTgmS4?p=preview
if (world[ninjaman.y][ninjaman.x-1] == 2) { //Checking if
should be
if (world[ninjaman.y][ninjaman.x] == 2) { //Checking if
I'm making an alcohol simulator, so when I press a button, you see an alcohol bottle being drained, but at the same time I should see the stomach filling. I have a code already for 'drinking', but I want to fix that if the water of the bottle moves 2 steps, that the water of the stomach only moves one step. I'll put just the js here, if you want the html as well, let me know.
var top_max = 475,
top_min = 400,
left_max = 200;
function move_img(str) {
var step = 1; // change this to different step value
var el = document.getElementById('i1');
var el2 = document.getElementById('i2');
if (str == 'up' || str == 'down') {
var top = el.offsetTop;
var height = el.offsetHeight;
console.log(height);
if (str == 'up') {
top -= step;
height += step;
} else {
top += step;
height -=step;
}
if (top_max >= top && top >= 110) {
document.getElementById('i1').style.top = top + "px";
document.getElementById('i1').style.height = height;
} else {
clearInterval(myVar)
}
} else if (str == 'left' || str == 'right') {
var left = el.offsetLeft;
if (str == 'left') {
left += step;
} else {
left -= step;
}
if (top_left < left && left >= 0) {
document.getElementById('i1').style.left = top + "px";
} else {
clearInterval(myVar)
}
}
}
function auto(str) {
myVar = setInterval(function () {
move_img(str);
}, 90);
}
function nana() {}
var myVar;
function handler() {
clearInterval(myVar);
auto(this.id);
}
function auto(str) {
myVar = setInterval(function(){ move_img(str); }, 2) ;
}
function stop(){
setTimeout(function( ) { clearInterval( myVar ); }, 1);
}
I'm trying to create a "spawn point" for a div. I have made it work and I have a working collision detector for it. There are two things I wanted to ask regarding my code.
How do I get my code to work with more than one player (window.i). - At the moment, after an hour of fiddling, I've only broken my code. This whole area screws up the collision detector, I have more than one player showing at times, but I'm unable to move.
How do I make it so that it detects the contact before it happens - I've tried working with the "tank's" margin and subtracting it's width, so that before it makes contact it calls an event, but it has been unsuccessful and completely stopped the collision function working.
I'm sorry that it's asking a lot, I really do understand that, but the issues come into eachother and rebound off so I thought it was best I put it all into one question rather than 2 separate ones an hour apart.
function animate() {
var tank = document.createElement("div");
tank.id= "tank";
tank.style.marginLeft="0px";
tank.style.marginTop="0px";
tank.style.height="10px";
tank.style.width="10px";
document.body.appendChild(tank);
x = parseInt(tank.style.marginLeft);
y = parseInt(tank.style.marginTop);
document.onkeydown = function () {
e = window.event;
if (e.keyCode == '37') {
if (x > 0) {
if (collisionDetector() == false) {
x = x - 10;
tank.style.marginLeft = x + "px";
} else {
alert();
}
}
} else if (e.keyCode == '39') {
if (x < 790) {
if (collisionDetector() == false) {
x = x + 10;
tank.style.marginLeft = x + "px";
} else {
alert();
}
}
} else if (e.keyCode == '38') {
if (y > 0) {
if (collisionDetector() == false) {
y = y - 10;
tank.style.marginTop = y + "px";
} else {
alert();
}
}
} else if (e.keyCode == '40') {
if (y < 490) {
if (collisionDetector() == false) {
y = y + 10;
tank.style.marginTop = y + "px";
} else {
alert();
}
}
}
}
}
window.lives = 3;
function playerSpawn() {
window.i = 1;
while (i > 0) {
var player = document.createElement("div");
randMarL = Math.ceil(Math.random()*80)*10;
randMarT = Math.ceil(Math.random()*50)*10;
player.id = "player";
player.style.marginLeft= randMarL + "px";
player.style.marginTop= randMarT + "px";
player.style.height="10px";
player.style.width="10px";
document.body.appendChild(player);
i--;
}
}
function collisionDetector() {
x1 = tank.style.marginLeft;
x2 = player.style.marginLeft;
y1 = tank.style.marginTop;
y2 = player.style.marginTop;
if ((x1 == x2 && y1 == y2)) {
return true;
} else {
return false;
}
}
When I attempt to move the div (tank) to the right ONLY in the first "movement command", and only in that direction, I come across in issue whereby my div shoots off a few thousand pixels to the right, way off of the screen region. Was hoping someone would assist me to see why this is.
function animate() {
var tank = document.getElementById("tank");
tank.style.marginLeft="360px";
tank.style.marginTop="440px";
window.xpos = tank.style.marginLeft;
window.ypos = tank.style.marginTop;
window.x = xpos.replace("px","");
window.y = ypos.replace("px","");
document.onkeydown = checkKey;
function checkKey(e) {
e = e || window.event;
if (e.keyCode == '37') {
if (x > 0) {
x = x - 20;
tank.style.marginLeft = x + "px";
}
} else if (e.keyCode == '39') {
if (x < 70) {
x = x + 20;
tank.style.marginLeft = x + "px";
}
} else if (e.keyCode == '38') {
if (y > 0) {
y = y - 20;
tank.style.marginTop = y + "px";
}
} else if (e.keyCode == '40') {
if (y < 440) {
y = y + 20;
tank.style.marginTop = y + "px";
}
}
}
checkKey(e);
}
window.lives = 3;
function destroy() {
if (lives != 0) {
alert("Life Lost!");
lives--;
window.collision == false;
animate();
} else {
alert("Try Again!");
}
}
window.collision = true;
function state() {
if (collision == false) {
window.state = 1;
} else if (collision == true) {
window.state = 0;
}
return state;
}
state();
if (state == 1) {
animate();
} else {
destroy();
}
You think you are doing a math operation but what you really are doing a string concatenation. In Javascript "360"-20 equals 340 because in this case the string is converted to a number and then an arithmetic subtraction is performed with both numeric values, however a different set of rules apply for the plus operator: in this case "360"+20 yields "36020" because the number is converted to a string and then both strings are concatenated.
Do this:
window.x = Number(xpos.replace("px",""));
window.y = Number(ypos.replace("px",""));