So basically I'm trying to create a shooter game. But a problem arose while trying to implement a health bar function for the player. Although I did manage to create a health bar that reduces or decreases based on its value, I can't change its value via code. Any suggestions would be appreciated.
I have created a player and enemy sprite who constantly shoot bullet sprites at each other. I am trying to make the player sprite's health bar go down when the enemy sprite's bullet (bullet_e) makes contact with it.
I'm considerably new to JavaScript, so please forgive any rookie mistakes.
Here's the script (I pasted the entire code, in case putting parts of the code cause problems):
var bg;
var player, playerImg;
var bullet_e, bulletImg;
var missile, missile_e, missileImg, missile_e_img;
var fireBall, fireBall_img;
var bg;
var enemy, enemyImg;
var trig1, trig2;
var health = 100;
var maxHealth = 100;
function preload() {
playerImg = loadImage("Assets/TBM-3.png");
bulletImg = loadImage("Assets/Bullets_01.png");
missileImg = loadImage("Assets/missile_01.png");
missile_e_img = loadImage("Assets/missile_02.png");
fireBall_img = loadImage("Assets/fireBall_01.png");
bg = loadImage("Assets/Backgrounds/BG_07.png");
enemyImg = loadImage("Assets/Enemy_FighterJet_Ba.png");
}
function setup() {
createCanvas(windowWidth, windowHeight);
player = createSprite(width / 2, height / 2 + 270);
player.addImage("player", playerImg);
player.scale = 0.5;
enemy = createSprite(windowWidth / 2 + 600, windowHeight / 2 - 300);
enemy.addImage("enemy", enemyImg);
enemy.scale = 0.6;
trig1 = createSprite(windowWidth, windowHeight - 650);
trig1.scale = 0.7;
trig1.visible = false;
trig2 = createSprite(windowWidth / 100, windowHeight - 650);
trig2.scale = 0.7;
trig2.visible = false;
}
function draw() {
background(bg, windowWidth, windowHeight);
//Health Bar
playerController();
enemyController();
//spawnBullets_p()
spawnBullets_e();
//checkCollisions()
updateHealth();
drawSprites();
}
function playerController() {
// Locomotion
if (keyDown(RIGHT_ARROW)) {
player.x = player.x + 8;
}
if (keyDown(LEFT_ARROW)) {
player.x = player.x - 8;
}
if (keyDown(UP_ARROW)) {
player.y = player.y - 6;
}
if (keyDown(DOWN_ARROW)) {
player.y = player.y + 6;
}
//Attacks
if (keyWentDown("space")) {
// Right wing
missile = createSprite(player.x + 39, player.y - 29);
missile.addImage("missile", missileImg);
missile.scale = 0.08;
missile.velocityY = -8;
missile.lifetime = 80;
// Left Wing
missile = createSprite(player.x - 39, player.y - 29);
missile.addImage("missile", missileImg);
missile.scale = 0.08;
missile.velocityY = -8;
missile.lifetime = 80;
}
}
function spawnBullets_p() {
if (frameCount % 4 === 0) {
bullet_p = createSprite(player.x + 37, player.y - 29);
bullet_p.addImage("bullet", bulletImg);
bullet_p.scale = 0.09;
bullet_p.velocityY = -30;
bullet_p.lifetime = 30;
bullet_p = createSprite(player.x - 37, player.y - 29);
bullet_p.addImage("bullet", bulletImg);
bullet_p.scale = 0.09;
bullet_p.velocityY = -30;
bullet_p.lifetime = 30;
}
}
function spawnBullets_e() {
if (frameCount % 6 === 0) {
bullet_e = createSprite(enemy.x + 33, enemy.y + 68);
bullet_e.addImage("bullet", bulletImg);
bullet_e.scale = 0.09;
bullet_e.velocityY = 30;
bullet_e.lifetime = 30;
bullet_e = createSprite(enemy.x - 33, enemy.y + 68);
bullet_e.addImage("bullet", bulletImg);
bullet_e.scale = 0.09;
bullet_e.velocityY = 30;
bullet_e.lifetime = 30;
if (bullet_e.isTouching(player)) {
health = health - 5;
bullet_e.destroyed();
}
console.log(health);
}
}
function enemyController() {
// locomotion
if (enemy.isTouching(trig1)) {
enemy.velocityX = -4;
}
if (enemy.isTouching(trig2)) {
enemy.velocityX = 4;
}
//Attack
if (frameCount % 100 === 0) {
// Right wing
missile_e = createSprite(enemy.x + 50, enemy.y + 68);
missile_e.addImage("missile2", missile_e_img);
missile_e.scale = 0.08;
missile_e.velocityY = +8;
missile_e.lifetime = 80;
// Left Wing
missile_e = createSprite(enemy.x - 50, enemy.y + 68);
missile_e.addImage("missile2", missile_e_img);
missile_e.scale = 0.08;
missile_e.velocityY = +8;
missile_e.lifetime = 80;
}
if (frameCount % 300 === 0) {
fireBall = createSprite(enemy.x, enemy.y + 30);
fireBall.addImage("fireBall", fireBall_img);
fireBall.scale = 0.09;
fireBall.velocityY = 5;
fireBall.lifetime = 90;
}
}
function checkCollisions() {
if (bullet_e.isTouching(player)) {
health = -5;
}
}
function updateHealth() {
stroke(0);
strokeWeight(4);
noFill();
rect(10, 10, 200, 20);
noStroke();
fill(255, 0, 0);
rect(10, 10, map(health, 0, maxHealth, 0, 200), 20);
}
i see your code and in this function
function checkCollisions()
{
if(bullet_e.isTouching(player))
{
health = -5;
}
}
the health variable is change to a value of -5 instead of decreasing that should be 95 and so on. Try this
function checkCollisions()
{
if(bullet_e.isTouching(player))
{
health -=5;
}
}
or health = health -5;
if the value still not changing. Try to put console.log("function name") to your functions to know if its called or not. Sometimes troubles are hidden on logical statements that hard to notice that the values or the condition dint meet properly.
Related
When I run my code I when I jump for some reason when I press a on the keyboard my character(the purple rectangle) goes into space
Here is the code:
//Global
//Game control
var stage = 0; // keeps track of which function to run
//Player
var p1X = 400; // p1 for player one
var p1Y = 375;
var pWidth = 30;
var pHeight = 70;
//Boxes (Platforms)
var b1X = 200; // b1 for box one
var b1Y = 300;
var bWidth = 200;
var bHeight = 40;
//Gravity
var jump = false; //are we jumping?
var direction = 1;
var velocity = 2;
var jumpPower = 10;
var fallingSpeed = 2;
var minHeight = 375;
//Setup
function setup() {
createCanvas(800, 500);
rectMode(CENTER);
textAlign(CENTER);
}
//Close setup
//Draw
function draw() {
//Call functions
if (stage == 0) {
game();
} //Close = 0
keyPressed();
gravity();
}
//Close draw
//////////Game
function game() {
//apperence of game
background(150, 230, 240); //Sky blue
//grass
noStroke();
fill(100, 200, 75); //green
rect(width / 2, 450, width, 100);
//window frame
noFill();
stroke(0);
strokeWeight(15);
rect(width / 2, height / 2, width, height);
//Draw box
stroke(0);
strokeWeight(5);
fill(255, 120, 0); //Orange
rect(b1X, b1Y, bWidth, bHeight);
//Draw Character
stroke(0);
fill(150, 0, 170); //Purple
rect(p1X, p1Y, pWidth, pHeight);
} //Close game
function gravity() {
if (p1Y >= minHeight && jump == false) {
p1Y = p1Y;
} else {
p1Y = p1Y + (direction * velocity);
}
if (jump == true) {
velocity = -jumpPower;
} else {
velocity = fallingSpeed;
}
}
function keyPressed() {
if (keyIsDown(LEFT_ARROW)) {
p1X = p1X - 5; //Move Left
} //Close Left
if (keyIsDown(RIGHT_ARROW)) {
p1X = p1X + 5; //Move Right
if (keyIsDown(UP_ARROW)) {
jump = true;
}
} //close keypressed
}
function keyTyped() {
if (keyIsDown(65)) {
jump = true;
} else {
jump = false;
}
}
canvas {
/* make the canvas fit in the tiny StackOverflow snippet iframe */
transform-origin: top left;
transform: scale(0.35);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
I want my player to jump and move left that's all but for some reason p5js says no and doesn't explain way it goes to space. I tried to add some more code but it still went to space but when I press another key after pressing a the character comes down
There are a few things in your code that I would change, but for jumping, here's my suggestion:
Change the velocity during the jump. When you jump in real life, gravity will constantly reduce your (vertical) velocity until you hit the ground. In this situation, you want to do the same thing: when you first jump, set the vertical velocity to a certain value. Until you hit a surface, continue to reduce the value of velocity (even to negative numbers).
Basically just translating what #jstl suggested into code, apply vertical velocity to the player position for each frame like so:
function gravity() {
let newTime = millis();
let timeDeltaSeconds = (newTime - time) / 1000;
time = newTime;
p1Y += velocity * timeDeltaSeconds * pixelsPerMeter;
// ...
}
And update velocity based on acceleration due to gravity like so:
function gravity() {
// ...
if (p1Y >= minHeight) {
// Impact with the ground, zero out velocity.
velocity = 0;
p1Y = minHeight;
}
if (p1Y < minHeight) {
velocity -= gravityAccel * timeDeltaSeconds;
}
}
With this in place "jumping" is just applying a sudden impulsive increase to velocity:
function keyTyped() {
if (keyIsDown(65) && p1Y == minHeight) {
// only "jump" when we're actually touching the ground.
velocity = jumpPower;
}
}
Here's a runnable example:
//Global
//Game control
let stage = 0; // keeps track of which function to run
//Player
let p1X = 400; // p1 for player one
let p1Y = 375;
let pWidth = 30;
let pHeight = 70;
//Boxes (Platforms)
const b1X = 200; // b1 for box one
const b1Y = 300;
const bWidth = 200;
const bHeight = 40;
//Gravity
// vertical velocity
let velocity = 0;
const jumpPower = 17;
// I'm not sure why but the real value for acceleration due to gravity (9.8)
// just doesn't look right.
const gravityAccel = 28;
// Player will be impacting the ground
const minHeight = 375;
// Number of pixels to move for every meter. Note that this is negative
// since the Y axis goes from 0 at the top to height at the bottom, so
// when we have a positive vertical velocity we want to decrease the y
// value.
const pixelsPerMeter = -30;
let time;
//Setup
function setup() {
createCanvas(800, 500);
rectMode(CENTER);
textAlign(CENTER);
time = millis();
}
//Close setup
//Draw
function draw() {
//Call functions
if (stage == 0) {
game();
} //Close = 0
movement();
gravity();
}
//Close draw
//////////Game
function game() {
//apperence of game
background(150, 230, 240); //Sky blue
//grass
noStroke();
fill(100, 200, 75); //green
rect(width / 2, 450, width, 100);
//window frame
noFill();
stroke(0);
strokeWeight(15);
rect(width / 2, height / 2, width, height);
//Draw box
stroke(0);
strokeWeight(5);
fill(255, 120, 0); //Orange
rect(b1X, b1Y, bWidth, bHeight);
//Draw Character
stroke(0);
fill(150, 0, 170); //Purple
rect(p1X, p1Y, pWidth, pHeight);
} //Close game
function gravity() {
let newTime = millis();
let timeDeltaSeconds = (newTime - time) / 1000;
time = newTime;
p1Y += velocity * timeDeltaSeconds * pixelsPerMeter;
if (p1Y >= minHeight) {
// Impact with the ground.
velocity = 0;
p1Y = minHeight;
}
if (p1Y < minHeight) {
velocity -= gravityAccel * timeDeltaSeconds;
}
}
function movement() {
if (keyIsDown(LEFT_ARROW)) {
p1X = p1X - 5; //Move Left
} //Close Left
if (keyIsDown(RIGHT_ARROW)) {
p1X = p1X + 5; //Move Right
} //close keypressed
}
function keyTyped() {
if (keyIsDown(65) && p1Y == minHeight) {
// only "jump" when we're actually touching the ground.
velocity = jumpPower;
}
}
canvas {
/* make the canvas fit in the tiny StackOverflow snippet iframe */
transform-origin: top left;
transform: scale(0.35);
}
body {
overflow: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.js"></script>
I'm working on a project where I simulate physics with balls.
Here is the link to the p5 editor of the project.
My problem is the following, when I add a lot of ball (like 200), balls are stacking but some of them will eventually collapse and I don't know why.
Can somebody explain why it does this and how to solve the problem ?
Thanks.
Here is the code of the sketch.
document.oncontextmenu = function () {
return false;
}
let isFlushing = false;
let isBallDiameterRandom = false;
let displayInfos = true;
let displayWeight = false;
let clickOnce = false;
let FRAME_RATE = 60;
let SPEED_FLUSH = 3;
let Y_GROUND;
let lastFR;
let balls = [];
function setup() {
frameRate(FRAME_RATE);
createCanvas(window.innerWidth, window.innerHeight);
Y_GROUND = height / 20 * 19;
lastFR = FRAME_RATE;
}
function draw() {
background(255);
if (isFlushing) {
for (let i = 0; i < SPEED_FLUSH; i++) {
balls.pop();
}
if (balls.length === 0) {
isFlushing = false;
}
}
balls.forEach(ball => {
ball.collide();
ball.move();
ball.display(displayWeight);
ball.checkCollisions();
});
if (mouseIsPressed) {
let ballDiameter;
if (isBallDiameterRandom) {
ballDiameter = random(15, 101);
} else {
ballDiameter = 25;
}
if (canAddBall(mouseX, mouseY, ballDiameter)) {
isFlushing = false;
let newBall = new Ball(mouseX, mouseY, ballDiameter, balls);
if (mouseButton === LEFT && !clickOnce) {
balls.push(newBall);
clickOnce = true;
}
if (mouseButton === RIGHT) {
balls.push(newBall);
}
}
}
drawGround();
if (displayInfos) {
displayShortcuts();
displayFrameRate();
displayBallCount();
}
}
function mouseReleased() {
if (mouseButton === LEFT) {
clickOnce = false;
}
}
function keyPressed() {
if (keyCode === 32) {//SPACE
displayInfos = !displayInfos;
}
if (keyCode === 70) {//F
isFlushing = true;
}
if (keyCode === 71) {//G
isBallDiameterRandom = !isBallDiameterRandom;
}
if (keyCode === 72) {//H
displayWeight = !displayWeight;
}
}
function canAddBall(x, y, d) {
let isInScreen =
y + d / 2 < Y_GROUND &&
y - d / 2 > 0 &&
x + d / 2 < width &&
x - d / 2 > 0;
let isInAnotherBall = false;
for (let i = 0; i < balls.length; i++) {
let d = dist(x, y, balls[i].position.x, balls[i].position.y);
if (d < balls[i].w) {
isInAnotherBall = true;
break;
}
}
return isInScreen && !isInAnotherBall;
}
function drawGround() {
strokeWeight(0);
fill('rgba(200,200,200, 0.25)');
rect(0, height / 10 * 9, width, height / 10);
}
function displayFrameRate() {
if (frameCount % 30 === 0) {
lastFR = round(frameRate());
}
textSize(50);
fill(255, 0, 0);
let lastFRWidth = textWidth(lastFR);
text(lastFR, width - lastFRWidth - 25, 50);
textSize(10);
text('fps', width - 20, 50);
}
function displayBallCount() {
textSize(50);
fill(255, 0, 0);
text(balls.length, 10, 50);
let twBalls = textWidth(balls.length);
textSize(10);
text('balls', 15 + twBalls, 50);
}
function displayShortcuts() {
let hStart = 30;
let steps = 15;
let maxTW = 0;
let controlTexts = [
'LEFT CLICK : add 1 ball',
'RIGHT CLICK : add 1 ball continuously',
'SPACE : display infos',
'F : flush balls',
'G : set random ball diameter (' + isBallDiameterRandom + ')',
'H : display weight of balls (' + displayWeight + ')'
];
textSize(11);
fill(0);
for (let i = 0; i < controlTexts.length; i++) {
let currentTW = textWidth(controlTexts[i]);
if (currentTW > maxTW) {
maxTW = currentTW;
}
}
for (let i = 0; i < controlTexts.length; i++) {
text(controlTexts[i], width / 2 - maxTW / 2 + 5, hStart);
hStart += steps;
}
fill(200, 200, 200, 100);
rect(width / 2 - maxTW / 2,
hStart - (controlTexts.length + 1) * steps,
maxTW + steps,
(controlTexts.length + 1) * steps - steps / 2
);
}
Here is the code of the Ball class.
class Ball {
constructor(x, y, w, e) {
this.id = e.length;
this.w = w;
this.e = e;
this.progressiveWidth = 0;
this.rgb = [
floor(random(0, 256)),
floor(random(0, 256)),
floor(random(0, 256))
];
this.mass = w;
this.position = createVector(x + random(-1, 1), y);
this.velocity = createVector(0, 0);
this.acceleration = createVector(0, 0);
this.gravity = 0.2;
this.friction = 0.5;
}
collide() {
for (let i = this.id + 1; i < this.e.length; i++) {
let dx = this.e[i].position.x - this.position.x;
let dy = this.e[i].position.y - this.position.y;
let distance = sqrt(dx * dx + dy * dy);
let minDist = this.e[i].w / 2 + this.w / 2;
if (distance < minDist) {
let angle = atan2(dy, dx);
let targetX = this.position.x + cos(angle) * minDist;
let targetY = this.position.y + sin(angle) * minDist;
this.acceleration.set(
targetX - this.e[i].position.x,
targetY - this.e[i].position.y
);
this.velocity.sub(this.acceleration);
this.e[i].velocity.add(this.acceleration);
//TODO : Effets bizarre quand on empile les boules (chevauchement)
this.velocity.mult(this.friction);
}
}
}
move() {
this.velocity.add(createVector(0, this.gravity));
this.position.add(this.velocity);
}
display(displayMass) {
if (this.progressiveWidth < this.w) {
this.progressiveWidth += this.w / 10;
}
stroke(0);
strokeWeight(2);
fill(this.rgb[0], this.rgb[1], this.rgb[2], 100);
ellipse(this.position.x, this.position.y, this.progressiveWidth);
if (displayMass) {
strokeWeight(1);
textSize(10);
let tempTW = textWidth(int(this.w));
text(int(this.w), this.position.x - tempTW / 2, this.position.y + 4);
}
}
checkCollisions() {
if (this.position.x > width - this.w / 2) {
this.velocity.x *= -this.friction;
this.position.x = width - this.w / 2;
} else if (this.position.x < this.w / 2) {
this.velocity.x *= -this.friction;
this.position.x = this.w / 2;
}
if (this.position.y > Y_GROUND - this.w / 2) {
this.velocity.x -= this.velocity.x / 100;
this.velocity.y *= -this.friction;
this.position.y = Y_GROUND - this.w / 2;
} else if (this.position.y < this.w / 2) {
this.velocity.y *= -this.friction;
this.position.y = this.w / 2;
}
}
}
I see this overlapping happen when the sum of ball masses gets bigger than the elasticity of the balls. At least it seems so. I made a copy with a smaller pool so it doesn't take so much time to reproduce the problem.
In the following example, with 6 balls (a mass of 150 units) pressing on the base row, we see that the 13 balls in the base row overlap. The base row has a width of ca. 300 pixels, which is only enough space for 12 balls of diameter 25. I think this is showing the limitation of the model: the balls are displayed circular but indeed have an amount of elasticity that they should display deformed instead. It's hard to say how this can be fixed without implementing drawing complicated shapes. Maybe less friction?
BTW: great physics engine you built there :-)
Meanwhile I was able to make another screenshot with even fewer balls. The weight of three of them (eq. 75 units) is sufficient to create overlapping in the base row.
I doubled the size of the balls and changed the pool dimensions as to detedt that there is a more serious error in the engine. I see that the balls are pressed so heavily under pressure that they have not enough space for their "volume" (area). Either they have to implode or it's elastic counter force must have greater impact of the whole scene. If you pay close attention to the pendulum movements made by the balls at the bottom, which have the least space, you will see that they are very violent, but apparently have no chance of reaching the outside.
Could it be that your evaluation order
balls.forEach(ball => {
ball.collide();
ball.move();
ball.display(displayWeight);
ball.checkCollisions();
});
is not able to propagate the collisions in a realistic way?
I stuck in one place for few hours, so I decided to go for help here. I'm beginner and i wish to try write a simple pong game.
At this link in Khan Academy you'll see result.
KHAN ACADEMY my pong game
My issue is:
I can't move two players at once. Only player can move - who hit last the keyboard. Last hit key win.
I know there are few ready pong games, but a lot of it is in Java, or all different logic. Can you help me good people? :)
//THIS IS GAME FOR 2 PEOPLE
//PLAYER 1 CONTROLS: UP ARROW (MOVE UP), DOWN ARROW (MOVE DOWN)
//PLAYER 2 CONTROLS: W KEY (MOVE UP), S KEY (MOVE DOWN)
var player1Y = height/2;
var player2Y = height/2;
var player1Score = 0;
var player2Score = 0;
var ball;
var gameStarted = false;
var t = 0;
//Constants
var PAUSE_TIME = 60;
var PLAYER_MOVE_SPEED = 2;
var BALL_SPEED = 3;
var PADDLE_HEIGHT = 80;
var PADDLE_WIDTH = 8;
angleMode = "degrees";
var Ball = function(position, speed) {
this.position = position;
this.speed = speed || BALL_SPEED;
this.radius = 6;
this.resetVelocity = function() {
this.theta = random(0, 75);
this.velocity = new PVector(
this.speed*cos(this.theta), -this.speed*sin(this.theta));
};
this.resetVelocity();
this.draw = function() {
fill(0, 0, 0);
noStroke();
ellipse(this.position.x, this.position.y,
this.radius*2, this.radius*2);
};
this.collideWithPaddle = function(x, y) {
if (this.position.x - this.radius < x + PADDLE_WIDTH/2 &&
this.position.x + this.radius > x - PADDLE_WIDTH/2) {
if (dist(0, this.position.y, 0, y) <
PADDLE_HEIGHT/2 + this.radius) {
if (this.position.x > x) {
this.position.x = x +
this.radius + PADDLE_WIDTH/2;
}
else if (this.position.x < x) {
this.position.x = x -
this.radius - PADDLE_WIDTH/2;
}
this.velocity.mult(new PVector(-1, 1));
}
}
};
this.update = function() {
//Handle wall collisions
if (this.position.x < 0) {
player2Score++;
this.position = new PVector(width/2, height/2);
gameStarted = false;
this.resetVelocity();
}
else if (this.position.x > width) {
player1Score++;
this.position = new PVector(width/2, height/2);
gameStarted = false;
this.resetVelocity();
}
if (this.position.y < 0) {
this.position.y = 0;
this.velocity.mult(new PVector(1, -1));
}
else if (this.position.y > height) {
this.position.y = height;
this.velocity.mult(new PVector(1, -1));
}
//Handle paddle collisions
this.collideWithPaddle(20, player1Y);
this.collideWithPaddle(width-20, player2Y);
this.position.add(this.velocity);
};
};
ball = new Ball(new PVector(width/2, height/2));
var drawScores = function() {
var s;
fill(0, 0, 0);
textSize(16);
s = "Player 1: " + player1Score;
text(s, width*0.25-textWidth(s)/2, 25);
s = "Player 2: " + player2Score;
text(s, width*0.75-textWidth(s)/2, 25);
};
//Move the player1 up
var movePlayer1Up = function() {
player1Y -= PLAYER_MOVE_SPEED;
};
//Move the player1 down
var movePlayer1Down = function() {
player1Y += PLAYER_MOVE_SPEED;
};
//Move the player2 up
var movePlayer2Up = function() {
player2Y -= PLAYER_MOVE_SPEED;
};
//Move the player2 down
var movePlayer2Down = function() {
player2Y += PLAYER_MOVE_SPEED;
};
var drawPlayers = function() {
//Constrain the player movement
player1Y = constrain(player1Y, 0, 400);
player2Y = constrain(player2Y, 0, 400);
rectMode(CENTER);
fill(0, 0, 0);
rect(20, player1Y, PADDLE_WIDTH, PADDLE_HEIGHT);
rect(width-20, player2Y, PADDLE_WIDTH, PADDLE_HEIGHT);
};
draw = function() {
//Control Player 1
if (keyIsPressed) {
if (keyCode===38){
movePlayer1Up();
}
else if(keyCode===40) {
movePlayer1Down();
}
}
//Control Player 2
if (keyIsPressed) {
if (key.toString()==="w"){
movePlayer2Up();
}
else if(key.toString()==="s"){
movePlayer2Down();
}
}
//Draw the environment
background(255, 255, 255);
drawPlayers();
drawScores();
stroke(100, 100, 100);
line(width/2, 0, width/2, height);
//Draw the ball
ball.draw();
if (!gameStarted) {
t++;
if (t >= PAUSE_TIME) {
t = 0;
gameStarted = true;
}
return;
}
ball.update();
};
You should be watching the onkeyup, onkeydown events for moving players, see this related question here. JavaScript multiple keys pressed at once
Now I understand concept, and I just did something like that:
Scope for multiple keys:
var keys = [];
var keyPressed = function(){
keys[keyCode] = true;
};
var keyReleased = function(){
keys[keyCode] = false;
};
and drawing function:
//Controls
if (keys[87]) {
movePlayer2Up();
}
if (keys[83]) {
movePlayer2Down();
}
if (keys[38]) {
movePlayer1Up();
}
if (keys[40]) {
movePlayer1Down();
}
And now it's working! The same link to the Khan Academy - there's the effect. Thank you one more time.
The Problem
I am creating a game where you have to move away from or dodge projectiles coming towards you, I have enabled the user to move the image they are controlling but at the moment the user can place the image anywhere on the canvas.
The Question
How can I only allow the user to move along designated part of the canvas and only along the X axis? for example:
Here is my game, "working progress":
The user is in control of the ship, they should only be able to move left or right like this for example:
The Code
<script>
var game = create_game();
game.init();
//music
var snd = new Audio("menu.mp3");
snd.play();
document.getElementById('mute').addEventListener('click', function (evt) {
if ( snd.muted ) {
snd.muted = false
evt.target.innerHTML = 'mute'
}
else {
snd.muted = true
evt.target.innerHTML = 'unmute'
}
})
function create_game() {
debugger;
var level = 1;
var projectiles_per_level = 1;
var min_speed_per_level = 1;
var max_speed_per_level = 2;
var last_projectile_time = 0;
var next_projectile_time = 0;
var width = 600;
var height = 500;
var delay = 1000;
var item_width = 30;
var item_height = 30;
var total_projectiles = 0;
var projectile_img = new Image();
var projectile_w = 30;
var projectile_h = 30;
var player_img = new Image();
var c, ctx;
var projectiles = [];
var player = {
x: 200,
y: 400,
score: 0
};
function init() {
projectile_img.src = "apple.png";
player_img.src = "basket.png";
level = 1;
total_projectiles = 0;
projectiles = [];
c = document.getElementById("c");
ctx = c.getContext("2d");
ctx.fillStyle = "#ff6600";
ctx.fillRect(0, 0, 500, 600);
c.addEventListener("mousemove", function (e) {
//moving over the canvas.
var bounding_box = c.getBoundingClientRect();
player.x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - player_img.width / 2;
player.y = (e.clientY - bounding_box.top) * (c.height / bounding_box.height) - player_img.height / 2;
}, false);
setupProjectiles();
requestAnimationFrame(tick);
}
function setupProjectiles() {
var max_projectiles = level * projectiles_per_level;
while (projectiles.length < max_projectiles) {
initProjectile(projectiles.length);
}
}
function initProjectile(index) {
var max_speed = max_speed_per_level * level;
var min_speed = min_speed_per_level * level;
projectiles[index] = {
x: Math.round(Math.random() * (width - 2 * projectile_w)) + projectile_w,
y: -projectile_h,
v: Math.round(Math.random() * (max_speed - min_speed)) + min_speed,
delay: Date.now() + Math.random() * delay
}
total_projectiles++;
}
function collision(projectile) {
if (projectile.y + projectile_img.height < player.y + 74) {
return false;
}
if (projectile.y > player.y + 74) {
return false;
}
if (projectile.x + projectile_img.width < player.x + 177) {
return false;
}
if (projectile.x > player.x + 177) {
return false;
}
return true;
}
function maybeIncreaseDifficulty() {
level = Math.max(1, Math.ceil(player.score / 10));
setupProjectiles();
}
function tick() {
var i;
var projectile;
var dateNow = Date.now();
c.width = c.width;
for (i = 0; i < projectiles.length; i++) {
projectile = projectiles[i];
if (dateNow > projectile.delay) {
projectile.y += projectile.v;
if (collision(projectile)) {
initProjectile(i);
player.score++;
} else if (projectile.y > height) {
initProjectile(i);
} else {
ctx.drawImage(projectile_img, projectile.x, projectile.y);
}
}
}
ctx.font = "bold 24px sans-serif";
ctx.fillStyle = "#ff6600";
ctx.fillText(player.score, c.width - 50, 50);
ctx.fillText("Level: " + level, 20, 50);
ctx.drawImage(player_img, player.x, player.y);
maybeIncreaseDifficulty();
requestAnimationFrame(tick);
}
return {
init: init
};
}
</script>
JSFiddle (Broken)
https://jsfiddle.net/3oc4jsf6/10/
If your ship is tied to mouse movement, and you want to only allow movement across the X-axis you can simply avoid changing its .y property in your mousemove listener.
Remove this line:
player.y = (e.clientY - bounding_box.top) * (c.height / bounding_box.height) - player_img.height / 2;
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am creating a game (using HTML5 canvas) that involves catching falling apples, i know, how original! I am having trouble finding a way to make it so multiple apples fall?
Here is the code in JSFiddle: https://jsfiddle.net/pgkL09j7/12/
var apple_x = 100;
var apple_y = 0;
var basket_x = 100;
var basket_y = 100;
var points = 0;
var basket_img = new Image();
basket_img.src = "http://s18.postimg.org/h0oe1vj91/basket.png";
var Countable = function () {}
//Background colour of canvas
var c = document.getElementById("c");
var ctx = c.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, 500, 500);
//Here is the event listener
c.addEventListener("mousemove", seenmotion, false);
//////////////////////
function seenmotion(e) {
//This is the code for the mouse
//moving over the canvas.
var bounding_box = c.getBoundingClientRect();
basket_x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - basket_img.width / 2;
basket_y = (e.clientY - bounding_box.top) * (c.height / bounding_box.height) - basket_img.height / 2;
}
function start_game() {
setInterval(game_loop, 50);
}
function game_loop() {
// The code above is called every 50ms and is a
// frame-redraw-game-animation loop.
c.width = c.width;
// Below is the code that draws the objects
draw_apple(apple_x, apple_y);
draw_basket(basket_x, basket_y);
// Below is the code that updates the balloons location
apple_x++;
if (apple_y > c.height) {
apple_y = 0;
}
//Here is the collision detection code
if (collision(apple_x, apple_y, basket_x, basket_y)) {
points -= 0.5;
}
//Here is the code for the point system
points += 1;
// and let's stick it in the top right.
var integerpoints = Math.floor(points); // make it into an integer
ctx.font = "bold 24px sans-serif";
ctx.fillText(integerpoints, c.width - 50, 50);
}
context.clearRect(0, 0, 500, 500);
function collision(basket_x, basket_y, apple_x, apple_y) {
if (apple_y + 85 < basket_y) {
return false;
}
if (apple_y > basket_y + 91) {
return false;
}
if (apple_x + 80 < basket_x) {
return false;
}
if (apple_x > basket_x + 80) {
return false;
}
return true;
}
// Code to stop the game when we're finished playing
function stop_game() {
}
//Code for the ball
function draw_app
le(x, y) {
var apple_img = new Image();
apple_img.src = "http://s15.postimg.org/3nwjmzsiv/apple.png";
ctx.drawImage(apple_img, x, y);
}
//Code for the basket
function draw_basket(x, y) {
ctx.drawImage(basket_img, x, y);
}
Change the section
apple_x++;
if (apple_x > c.width) {
apple_x = 0;
}
to use vertical instead of horizontal...
apple_y++;
if (apple_y > c.height) {
apple_y = 0;
}
You've already accepted the answer, but this looked like fun. Check out this fiddle.
https://jsfiddle.net/h82gv4xn/
Improvements include:
Fixed scoreboard
Added level progression (Level increases every 10 apples)
Allowance for many many more apples on screen (play to level 9).
Apples will fall at different speeds and speed up as the levels increase.
Uses the animation frame system for much smoother animations.
Relaxed collision handling (The center of the bucket must touch the apple)
It all gets really silly as the levels wind upwards, but it should be a nice example to improve upon. The relevant javascript follows (this would go into your onLoad function):
var game = create_game();
game.init();
function create_game() {
debugger;
var level = 1;
var apples_per_level = 1;
var min_speed_per_level = 1;
var max_speed_per_level = 2;
var last_apple_time = 0;
var next_apple_time = 0;
var width = 500;
var height = 500;
var delay = 1000;
var item_width = 50;
var item_height = 50;
var total_apples = 0;
var apple_img = new Image();
var apple_w = 50;
var apple_h = 50;
var basket_img = new Image();
var c, ctx;
var apples = [];
var basket = {
x: 100,
y: 100,
score: 0
};
function init() {
apple_img.src = "http://s15.postimg.org/3nwjmzsiv/apple.png";
basket_img.src = "http://s18.postimg.org/h0oe1vj91/basket.png";
level = 1;
total_apples = 0;
apples = [];
c = document.getElementById("c");
ctx = c.getContext("2d");
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, 500, 500);
c.addEventListener("mousemove", function (e) {
//moving over the canvas.
var bounding_box = c.getBoundingClientRect();
basket.x = (e.clientX - bounding_box.left) * (c.width / bounding_box.width) - basket_img.width / 2;
basket.y = (e.clientY - bounding_box.top) * (c.height / bounding_box.height) - basket_img.height / 2;
}, false);
setupApples();
requestAnimationFrame(tick);
}
function setupApples() {
var max_apples = level * apples_per_level;
while (apples.length < max_apples) {
initApple(apples.length);
}
}
function initApple(index) {
var max_speed = max_speed_per_level * level;
var min_speed = min_speed_per_level * level;
apples[index] = {
x: Math.round(Math.random() * (width - 2 * apple_w)) + apple_w,
y: -apple_h,
v: Math.round(Math.random() * (max_speed - min_speed)) + min_speed,
delay: Date.now() + Math.random() * delay
}
total_apples++;
}
function collision(apple) {
if (apple.y + apple_img.height < basket.y + 50) {
return false;
}
if (apple.y > basket.y + 50) {
return false;
}
if (apple.x + apple_img.width < basket.x + 50) {
return false;
}
if (apple.x > basket.x + 50) {
return false;
}
return true;
}
function maybeIncreaseDifficulty() {
level = Math.max(1, Math.ceil(basket.score / 10));
setupApples();
}
function tick() {
var i;
var apple;
var dateNow = Date.now();
c.width = c.width;
for (i = 0; i < apples.length; i++) {
apple = apples[i];
if (dateNow > apple.delay) {
apple.y += apple.v;
if (collision(apple)) {
initApple(i);
basket.score++;
} else if (apple.y > height) {
initApple(i);
} else {
ctx.drawImage(apple_img, apple.x, apple.y);
}
}
}
ctx.font = "bold 24px sans-serif";
ctx.fillStyle = "#2FFF2F";
ctx.fillText(basket.score, c.width - 50, 50);
ctx.fillText("Level: " + level, 20, 50);
ctx.drawImage(basket_img, basket.x, basket.y);
maybeIncreaseDifficulty();
requestAnimationFrame(tick);
}
return {
init: init
};
}