Image does not translate when keys are pressed - javascript

Want to move an image across the screen. At the moment the image renders but does not translate the page when the specific keys are pressed. Can't see to get it to work - any suggestions?? I included the entire block of code as I believe it makes more sense.
var player;
var img;
function preload() {
img = loadImage("charcter.png");
}
function setup() {
background(255, 0, 0, 0.4);
createCanvas(1000, 600);
player = new Astro(0,0);
}
function draw() {
// clear();
player.show();
player.update();
}
function keyPressed() {
if (keyCode === UP_ARROW) {
player.dir(0, -10);
} else if (keyCode === DOWN_ARROW) {
player.dir(0, 10);
} else if (keyCode === RIGHT_ARROW) {
player.dir(10, 0);
} else if (keyCode === LEFT_ARROW) {
player.dir(-10, 0);
}
}
function Astro(x, y) {
this.x = x;
this.y = y;
this.xSpeed = 0;
this.ySpeed = 0;
this.img = img;
this.show = function() {
image(img, this.x, this.y);
};
this.update = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x > width || this.x < 0) {
this.xSpeed = this.xSpeed * -1;
}
if (this.y > height || this.y < 0) {
this.ySpeed = this.ySpeed * -1;
}
};
this.dir = function(x, y) {
this.xspeed = x;
this.yspeed = y;
}
}

You need to take a step back and debug your program. For example, are you sure the keyPressed() function is firing? Are you sure the if statements are working the way you expected? Are you sure the player.dir() function is being called?
Use console.log() statements, or use the JavaScript debugger, to answer all of the above. Figure out exactly which line of code is behaving differently from what you expected, and then isolate that problem in a MCVE. (For example, don't include image loading code if the problem is not directly related to loading images. Use a basic rectangle instead.) Good luck.

Related

How can i use DOM events inside my javascript classes?

I am trying to make a function inside my class, where by pressing the ArrowUp key, it will become true. However, it just says: "Cannot read property 'key' of undefined?
class Boks{
constructor(x,y,w,h,r,k){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.r = r;
this.k = k;
}
visSnake(){
rect(this.x,this.y,this.w,this.h)
}
moveSnake(){
this.x = this.x + speed;
}
keyb(event){
if(event.key === "ArrowUp"){
return true;
}
}
}
My guess is that I have to define some sort of DOM event key in the constructor or parameter to the constructor, but i dont know how?
In p5.js you've just to define the function keyPressed() which is automatically called, if an button is pressed. You don't need to define any DOM event, p5.js does the job for you, you've just to "use" the existing callbacks, which are well documented.
I recommend to read p5.js - Get Started.
If you want to evaluate if the UP key is pressed, then you can evaluate the state of the built in variable keyIsPressed and keyCode in draw:
function draw() {
if (keyIsPressed && keyCode === UP_ARROW) {
// [...]
}
// [...]
}
See the short example:
let x=0, y=0, w=20, h=20;
function setup(){
createCanvas(window.innerWidth-20,window.innerHeight-20)
x = width/2;
y = height/2;
frameRate(10);
}
function draw(){
if (keyIsPressed && keyCode === LEFT_ARROW){
if (x > 0) {
x -= w;
}
}
if (keyIsPressed && keyCode === RIGHT_ARROW){
if (x < width-w) {
x += w;
}
}
if (keyIsPressed && keyCode === UP_ARROW) {
if (y > 0) {
y -= h;
}
}
if (keyIsPressed && keyCode === DOWN_ARROW){
if (y < height-h) {
y += h;
}
}
background(0);
stroke(255);
fill(255);
rect(x, y, w, h);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>

p5.js classes (class "example" is not changing my this.x value)

I want to move an ellipse but I am stuck because my this.x value isn't changing... print("hit this.y = 30"); is working just fine but this--; is not working. Is anything blocking it? Thank you in advance for your time!
let redBubble = 0;
let x = false;
let y = 0;
let d = 0;
function setup() {
createCanvas(400, 400);
redBubble = new Bubble(300, 100, 10);
}
function draw() {
background(56, 23, 56);
redBubble.show();
redBubble.toRight();
redBubble.toLeft();
redBubble.example();
};
class Bubble {
constructor(x, y, d) {
this.x = x;
this.y = y;
this.d = d;
}
show() {
fill(255);
ellipse(this.x, this.y, this.d * 2);
}
toRight() {
if (this.x < 350) {
this.x = this.x + 1;
} else if (this.x === 350) {
this.y = this.y - 1;
}
}
toLeft() {
if (this.y <= 30) {
x = true;
} else if (this.y === 30) {
x = false;
}
}
example() {
if (x) {
this.x--; // not working
print("hit this.y = 30"); // working
}
}
}
Your code is running, but it sounds like it's not doing what you want it to.
All of your functions show(), toRight(), toLeft(), example(), are running every single draw. So every single time, toRight() is incrementing this.x by 1 (unless this.x is exactly 350). So when example() decrements it by 1, they are in effect canceling each other out and not changing this.x, when x is true and this.x is 349.
If you wanted the net effect to be this.x to decrease, you could replace this.x--; with this.x = this.x - 2;. But this is not a great solution.
Using states
It looks like you want to do different things at different stages of your animation, i.e. go right, then go up, then go left. As you've discovered, it can be pretty tricky to coordinate all of these different changes when all of your functions are running every cycle.
Instead, it's a lot easier to conditionally run only the functions you want, depending on what stage of your animation you're in. For this you can use an internal variable to store what it should be doing (I'll use this.direction for this example). Then in your draw function, you'd use if/then statements, like this:
function draw() {
background(56, 23, 56);
redBubble.show();
if (redBubble.direction === 'right') {
redBubble.goRight();
} else if (redBubble.direction === 'up') {
redBubble.goUp();
} else if (redBubble.direction === 'left') {
redBubble.goLeft();
}
};
And then in your individual functions, you'd change direction based on some condition. For example:
toRight() {
this.x = this.x + 1;
if (this.x === 350) {
this.direction = 'up';
}
}
Here's a working snippet of the above technique:
let redBubble;
function setup() {
createCanvas(400, 400);
redBubble = new Bubble(300, 100, 10);
}
function draw() {
background(56, 23, 56);
redBubble.show();
if (redBubble.direction === 'right') {
redBubble.goRight();
} else if (redBubble.direction === 'up') {
redBubble.goUp();
} else if (redBubble.direction === 'left') {
redBubble.goLeft();
} else if (redBubble.direction === 'down') {
redBubble.goDown();
}
};
class Bubble {
constructor(x, y, d) {
this.x = x;
this.y = y;
this.d = d;
this.direction = 'right';
}
show() {
fill(255);
ellipse(this.x, this.y, this.d * 2);
}
goRight() {
this.x = this.x + 1;
if (this.x === 350) {
this.direction = 'up';
}
}
goLeft() {
this.x = this.x - 1;
if (this.x === 30) {
this.direction = 'down';
}
}
goUp() {
this.y = this.y - 1;
if (this.y === 30) {
this.direction = 'left';
}
}
goDown() {
this.y = this.y + 1;
if (this.y === 300) {
this.direction = 'right';
}
}
}
<script src="https://unpkg.com/p5#0.6.1/lib/p5.min.js"></script>

Brackets p5.js "Uncaught TypeError: Cannot read property 'offscreen' of undefined"

I am learning about Neural Networks(and learning JS at the same time) at the moment and wanted to start with a little game in Javascript to implement my learned stuff. So first things first, create a game, shouldn't be too hard right? Well.. Looks like I am too blind to find the mistake, so I would be really glad if someone could help me.
I am getting the following error message: "Uncaught TypeError: Cannot read property 'offscreen' of undefined".
It occurs when the player dies. I guess it has to do with the array being cleared when "resetting" and maybe the for-loop then still tries to delete the offscreen pipe, but it cant, as the array is empty or something like this. Dont know how to fix that tho..
https://thumbs.gfycat.com/WanDifficultAnaconda-size_restricted.gif
The Game is just an easy "objects come flying to you and you gotta jump over them".
Here's the whole code, it really isnt much:
sketch.js
let obstacle;
let player;
let obstacles = [];
let score = 0;
let highscore = 0;
function setup() {
createCanvas(600, 600);
obstacle = new Obstacle();
player = new Player();
}
function draw() {
background(0, 128, 128);
for(let i = obstacles.length-1; i >= 0; i--) {
if(obstacles[i].hits(player)) {
reset();
}
if(obstacles[i].offscreen()) {
obstacles.splice(i, 1);
}
obstacles[i].show();
obstacles[i].update();
}
player.show();
player.update();
score++;
currentScore();
newhighscore();
if(frameCount % 100 == 0) {
obstacles.push(new Obstacle());
}
}
function keyPressed() {
if(keyCode == 87 && player.y + player.h == height) {
player.jump();
}
}
function reset() {
if(score > highscore) {
highscore = score;
}
obstacles = [];
score = 0;
player = new Player();
}
function currentScore() {
strokeWeight(0);
stroke(102,205,170);
fill(14,47,68);
textSize(24);
text(score, 10, 30);
}
function newhighscore() {
strokeWeight(0);
stroke(102,205,170);
fill(14,47,68);
textSize(16);
text(highscore, 11, 48);
}
player.js
class Player {
constructor() {
this.x = 100;
this.h = 30;
this.w = this.h;
this.y = height - this.h;
this.gravity = 0.5;
this.lift = -9;
this.velocity = 0;
}
show() {
fill(0);
rect(this.x, this.y, this.w, this.h);
}
update() {
this.velocity += this.gravity;
this.y += this.velocity;
if(this.y + this.h > height) {
this.y = height - this.h;
this.velocity = 0;
}
}
jump() {
this.velocity += this.lift;
}
}
obstacle.js
class Obstacle {
constructor() {
this.x = width;
this.h = random(30, 50);
this.w = this.h;
this.y = height-this.h;
this.speed = 5;
}
show() {
noStroke();
fill(255, 115, 115);
rect(this.x, this.y, this.w, this.h);
}
update() {
this.x -= this.speed;
}
offscreen() {
if(this.x < -width) {
return true;
} else {
false;
}
}
hits(player) {
if(player.x <= this.x + this.w && player.x + player.w >= this.x) {
if(player.y + player.h >= this.y) {
return true;
} else {
return false;
}
}
}
}
My Solution
Explanation
Yeah you had the reason correct, when reset() is called, it changes to obstacles = [] but the
for(let i = obstacles.length-1; i >= 0; i--) {
if(obstacles[i].hits(player)) {
reset();
...*Continued*
}
in your draw function still continues. So you just had to add break; in the hit condition after reset. See in the link I've uploaded it works completely fine.
for(let i = obstacles.length-1; i >= 0; i--) {
if(obstacles[i].hits(player)) {
reset();
break;
...*Continued*
}
When you add break, the for loop terminates and moves down to the functions that follow. Since obstacles = [] is empty, undefined error is not shown as empty indexes are not accessed.

Why isnt collision detection working? (p5 js frame work)

I created a collision detection between Snake and BasicEnemy. I created a for loop to make five different enemies but the collision detection doesn't get called on any of the enemies that were created from the for loop. The collision only works with the one BasicEnemy object. Why isn't collision function being called for all of the enemies inside the array? Thank you.
Sketch.js
var snake;
var food;
var basicEnemy;
var scl = 20;
var enemies = [];
function setup() {
createCanvas(600, 500);
snake = new Snake();
basicEnemy = new BasicEnemy();
//** CREATE FIVE ENEMIES **
for (var i = 0; i < 5; i++) {
enemies[i] = new BasicEnemy();
}
}
// **FUNCTION WHEN SNAKE HITS ENEMY**
function collision() {
console.log("hit!");
}
function draw() {
background(51);
//Draw snake
snake.update();
snake.show();
//Draw basicEnemy
basicEnemy.update();
basicEnemy.show();
//** LOOP THROUGH ENEMIES AND UPDATE AND SHOW **
for (var i = 0; i < enemies.length; i++) {
enemies[i].show();
enemies[i].update();
if (enemies[i].hits(snake)) {
collision();
}
}
}
function keyPressed() {
if (keyCode === UP_ARROW){
snake.dir(0, -1);
} else if (keyCode === DOWN_ARROW) {
snake.dir(0, 1);
} else if (keyCode === LEFT_ARROW) {
snake.dir(-1 , 0);
} else if (keyCode === RIGHT_ARROW) {
snake.dir(1 , 0);
}
}
BasicEnemy.js
function BasicEnemy() {
this.x = random(700);
this.y = random(700);
this.velX = 15;
this.velY = 15;
}
//** FUNCTION TO CHECK IF ENEMY AND SNAKE ARE IN THE SAME LOCATION **
this.hits = function (pos) {
var = d = dist(this.x, this.y, pos.x, pos.y);
if(d < 1) {
return true;
} else {
return false;
}
}
this.show = function () {
fill(255, 0, 100);
rect(this.x, this.y, scl, scl);
}
Snake.js
function Snake() {
this.x = 0;
this.y = 0;
this.xspeed = 1;
this.yspeed = 0;
this.update = function() {
this.x = this.x + this.xspeed * scl;
this.y = this.y + this.yspeed * scl;
this.x = constrain(this.x, 0, width - scl);
this.y = constrain(this.y, 0, height - scl);
}
this.show = function() {
fill(255);
rect(this.x, this.y, scl, scl);
}
this.dir = function (x , y) {
this.xspeed = x;
this.yspeed = y;
}
}
Because you're essentially checking for the distance between the top left corners of the snake and the enemy, this'll only return true, if they completely overlap.
Use an AABB collision detection instead:
return this.x + scl >= pos.x && this.x <= pos.x + scl && this.y + scl >= pos.y && this.y <= pos.y + scl;
This returns true, if the first rectangle contains the second rectangle.
MDN says:
One of the simpler forms of collision detection is between two rectangles that are axis aligned — meaning no rotation. The algorithm works by ensuring there is no gap between any of the 4 sides of the rectangles. Any gap means a collision does not exist.

javascript Centipede, key press not working

I built centipede in javascript from a Khan Academy tutorial. Then I figured out how to put it into a web browser. however, the key presses are not working. I have tried to change the keyCode values, and change some of the function definitions to "void" but nothing has worked. The app uses processing .js to work. Here is the section of js dealing with the keys:
var Player = function(x,y,size,speed){
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.update = function(){
if(keys[LEFT]){
this.x -= this.speed;
}
if(keys[RIGHT]){
this.x += this.speed;
}
if(keys[DOWN]){
this.y += this.speed;
}
if(keys[UP]){
this.y -= this.speed;
}
if(keys[76] && bulletDelay < 0){
var b = new Bullet(this.x, this.y, 5,5);
bullets.push(b);
bulletDelay = 40;
}
if (this.x < 0){
this.x = 0;
}
if (this.x > width){
this.x = width;
}
if (this.y > 800){
this.y = 800;
}
//This adjusts the max height the player can move up on y-axis. Adjust to make more like Atari version
if (this.y < 100) {
this.y = 100;
}
noStroke();
fill(0,255,0);
ellipse(this.x, this.y, this.size, this.size);
};
};
I sorted it out. The keyPress and keyRelease functions needed to be changed from
var keyPressed = function(){
to
void keyPressed() . . .
similar for the keyReleased function
The syntax
if(keys[LEFT])
should be
if(keyCode == LEFT)
See the Processing.js keyCode reference and key
EDIT 1: For special keys (arrow, space), you should use keyCode instead of key.

Categories

Resources