Make a bullet object in p5.js javascript - javascript

i was making a javascript game in p5.js. I made a lot of the game, then wanted to add some combat. I made a weapon that shoots bullets. But now the bullet is hard to make. So here is how my weapon works:
it starts from the player location
it founds the y rotation of the mouse click (looks from the center of the screen and looks what degree rotation it is (360 degrees))
looks to the y rotation of the mouse click
goes off in the distance
So how do I make the bullet? I have the base script, but the bullet only gets deleted when it hits a enemy, only goes to the mosue, has a dumb algorthm for path finding to the mouse, you can have only one bullet at once , and if it does not hit any enemies, it just sits on the ground like a mine.
Here is the psuedo code(no programming rules at all lol):
Make bullet(playerPositionX,playerPositionY,mouseX,mousey) as a object:
starter x and y = playerPostionX and playerPositionY
lookTowards a point(mouseX,mouseY)
goto the point(mouseX and mouseY) from the starter X and Y
movespeed is 20pixel per frame
So here is what i got in my game right now is:
The sketch script:
var player;
var enemy;
var bullet;
var score = 0;
function setup(){
createCanvas(600,600);
player = new Player();
enemy = new Enemy();
textSize(20);
}
function draw(){
clear();
background(51);
enemy.show();
enemy.moveToPlayer(player.x, player.y);
player.show();
player.MovePlayer();
if (bullet != undefined){
bullet.show();
bullet.toMouse();
if (dist(bullet.x,bullet.y,enemy.x,enemy.y) <= enemy.r){
enemy = new Enemy();
score += 100;
bullet = undefined;
}
}
fill(255);
text(score,500,500,100,100)
}
function mousePressed(){
//if (enemy.clicked(mouseX,mouseY)){
bullet = new Bullet(mouseX,mouseY,player.x,player.y);
//enemy = new Enemy();
//}
}
The bullet script:
function Bullet(X,Y,PX,PY){
this.speed = 20;
this.x = PX;
this.y = PY;
this.r = 5;
this.show = function(){
fill(255,255,0);
stroke(128,128,0);
circle(this.x,this.y,this.r);
}
this.toMouse = function(){
if (Y < this.y){
this.y += -1*this.speed;
} else if (Y > this.y) {
this.y += 1*this.speed;
}
if (X < this.x){
this.x += -1*this.speed;
} else if (X > this.x){
this.x += 1*this.speed;
}
}
}
The enemy script:
function Enemy(){
this.r = 25;
this.x = 0+this.r;
this.y = 0+this.r;
this.chance = random(0,1);
console.log(this.chance);
if (this.chance <= 0.10){
this.speed = 3;
this.r = 15;
this.red = 0;
this.green = 0;
this.blue = 255;
} else {
this.speed = 2;
this.red = 255;
this.green = 0;
this.blue = 0;
}
this.show = function(){
fill(this.red,this.green,this.blue);
stroke(128,0,0);
circle(this.x,this.y,this.r);
}
this.moveToPlayer = function(playerX,playerY){
if (playerY < this.y){
this.y += -1*this.speed;
} else if (playerY > this.y) {
this.y += 1*this.speed;
}
if (playerX < this.x){
this.x += -1*this.speed;
} else if (playerX > this.x){
this.x += 1*this.speed;
}
}
/*
this.clicked = function(mX,mY){
if (dist(mX,mY,this.x,this.y) <= this.r){
return true;
}
return false;
}
*/
}
The player script:
function Player(){
this.x = width/2;
this.y = height/2;
this.r = 20;
this.speed = 4;
this.show = function(){
fill(0,255,0);
stroke(0,128,0);
circle(this.x,this.y,this.r);
}
this.moveY = function(number){
this.y += (number*this.speed);
}
this.moveX = function(number){
this.x += (number*this.speed);
}
this.MovePlayer = function(){
if (keyIsDown(UP_ARROW)){
if (this.y + (-1*20) > 0)
this.moveY(-1);
}
if (keyIsDown(DOWN_ARROW)){
if (this.y + (1*20) < height)
this.moveY(1);
}
if (keyIsDown(LEFT_ARROW)){
if (this.x + (-1*20) > 0)
this.moveX(-1);
}
if (keyIsDown(RIGHT_ARROW)){
if (this.x + (1*20) < width)
this.moveX(1);
}
}
}
The html file has everything it needs
Thanks for advance!
var player;
var enemy;
var bullet;
var score = 0;
function setup(){
createCanvas(600,600);
player = new Player();
enemy = new Enemy();
textSize(20);
}
function draw(){
clear();
background(51);
enemy.show();
enemy.moveToPlayer(player.x, player.y);
player.show();
player.MovePlayer();
if (bullet != undefined){
bullet.show();
bullet.toMouse();
if (dist(bullet.x,bullet.y,enemy.x,enemy.y) <= enemy.r){
enemy = new Enemy();
score += 100;
bullet = undefined;
}
}
fill(255);
text(score,500,500,100,100)
}
function mousePressed(){
//if (enemy.clicked(mouseX,mouseY)){
bullet = new Bullet(mouseX,mouseY,player.x,player.y);
//enemy = new Enemy();
//}
}
function Bullet(X,Y,PX,PY){
this.speed = 20;
this.x = PX;
this.y = PY;
this.r = 5;
this.show = function(){
fill(255,255,0);
stroke(128,128,0);
circle(this.x,this.y,this.r);
}
this.toMouse = function(){
if (Y < this.y){
this.y += -1*this.speed;
} else if (Y > this.y) {
this.y += 1*this.speed;
}
if (X < this.x){
this.x += -1*this.speed;
} else if (X > this.x){
this.x += 1*this.speed;
}
}
}
function Enemy(){
this.r = 25;
this.x = 0+this.r;
this.y = 0+this.r;
this.chance = random(0,1);
console.log(this.chance);
if (this.chance <= 0.10){
this.speed = 3;
this.r = 15;
this.red = 0;
this.green = 0;
this.blue = 255;
} else {
this.speed = 2;
this.red = 255;
this.green = 0;
this.blue = 0;
}
this.show = function(){
fill(this.red,this.green,this.blue);
stroke(128,0,0);
circle(this.x,this.y,this.r);
}
this.moveToPlayer = function(playerX,playerY){
if (playerY < this.y){
this.y += -1*this.speed;
} else if (playerY > this.y) {
this.y += 1*this.speed;
}
if (playerX < this.x){
this.x += -1*this.speed;
} else if (playerX > this.x){
this.x += 1*this.speed;
}
}
/*
this.clicked = function(mX,mY){
if (dist(mX,mY,this.x,this.y) <= this.r){
return true;
}
return false;
}
*/
}
function Player(){
this.x = width/2;
this.y = height/2;
this.r = 20;
this.speed = 4;
this.show = function(){
fill(0,255,0);
stroke(0,128,0);
circle(this.x,this.y,this.r);
}
this.moveY = function(number){
this.y += (number*this.speed);
}
this.moveX = function(number){
this.x += (number*this.speed);
}
this.MovePlayer = function(){
if (keyIsDown(UP_ARROW)){
if (this.y + (-1*20) > 0)
this.moveY(-1);
}
if (keyIsDown(DOWN_ARROW)){
if (this.y + (1*20) < height)
this.moveY(1);
}
if (keyIsDown(LEFT_ARROW)){
if (this.x + (-1*20) > 0)
this.moveX(-1);
}
if (keyIsDown(RIGHT_ARROW)){
if (this.x + (1*20) < width)
this.moveX(1);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>

Create an array of bullets rather than a single bullet and append a new bullet to the array, if the mouse button is pressed:
var bullets = [];
function mousePressed(){
if (mouseX != player.x || mouseY != player.y ) {
bullets.push( new Bullet(mouseX,mouseY,player.x,player.y) )
}
}
Use p5.Vector to calculate the normalized direction from the player position to the mouse position in thee class [Bullet]. This is defines the moving direction of the Bullet, which can be used in toMouse, to update the position of the Bullet object.
Further add method onScreen, which verifies if the Bullet is still in bounds of the screen:
function Bullet(X,Y,PX,PY){
this.speed = 2;
this.x = PX;
this.y = PY;
this.dir = createVector(X-PX, Y-PY).normalize()
this.r = 5;
this.show = function(){
fill(255,255,0);
stroke(128,128,0);
circle(this.x,this.y,this.r);
}
this.toMouse = function() {
this.x += this.dir.x * this.speed;
this.y += this.dir.y * this.speed;
}
this.onScreen = function() {
return this.x > -this.r && this.x < width+this.r &&
this.y > -this.r && this.y < height+this.r;
}
}
Traverse the bullets in draw. Check if a bullet has hit the enemy or has left the screen. Keep the remaining bullets for the next run of draw:
let keepbullets = []
let anyhit = false;
for (let i=0; i < bullets.length; ++ i) {
bullets[i].toMouse();
let hit = dist(bullets[i].x, bullets[i].y, enemy.x, enemy.y) <= enemy.r;
anyhit = anyhit || hit
if (!hit && bullets[i].onScreen()) {
keepbullets.push(bullets[i]);
bullets[i].show();
}
}
bullets = keepbullets;
if (anyhit) {
enemy = new Enemy();
score += 100;
}
See the example, where I applied the suggestions to the original code from the question. Note, I've slowed down the speed of the bullets extremely, to make the effect of multiple bullets visible:
var player;
var enemy;
var bullets = [];
var score = 0;
function setup(){
createCanvas(600,600);
player = new Player();
enemy = new Enemy();
textSize(20);
}
function draw(){
clear();
background(51);
enemy.show();
enemy.moveToPlayer(player.x, player.y);
player.show();
player.MovePlayer();
let keepbullets = []
let anyhit = false;
for (let i=0; i < bullets.length; ++ i) {
bullets[i].toMouse();
let hit = dist(bullets[i].x, bullets[i].y, enemy.x, enemy.y) <= enemy.r;
anyhit = anyhit || hit
if (!hit && bullets[i].onScreen()) {
keepbullets.push(bullets[i]);
bullets[i].show();
}
}
bullets = keepbullets;
if (anyhit) {
enemy = new Enemy();
score += 100;
}
fill(255);
text(score,500,500,100,100)
}
function mousePressed(){
if (mouseX != player.x || mouseY != player.y ) {
bullets.push( new Bullet(mouseX,mouseY,player.x,player.y) )
}
}
function Bullet(X,Y,PX,PY){
this.speed = 2;
this.x = PX;
this.y = PY;
this.dir = createVector(X-PX, Y-PY).normalize()
this.r = 5;
this.show = function(){
fill(255,255,0);
stroke(128,128,0);
circle(this.x,this.y,this.r);
}
this.toMouse = function() {
this.x += this.dir.x * this.speed;
this.y += this.dir.y * this.speed;
}
this.onScreen = function() {
return this.x > -this.r && this.x < width+this.r &&
this.y > -this.r && this.y < height+this.r;
}
}
function Enemy(){
this.r = 25;
this.x = 0+this.r;
this.y = 0+this.r;
this.chance = random(0,1);
console.log(this.chance);
if (this.chance <= 0.10){
this.speed = 3;
this.r = 15;
this.red = 0;
this.green = 0;
this.blue = 255;
} else {
this.speed = 2;
this.red = 255;
this.green = 0;
this.blue = 0;
}
this.show = function(){
fill(this.red,this.green,this.blue);
stroke(128,0,0);
circle(this.x,this.y,this.r);
}
this.moveToPlayer = function(playerX,playerY){
if (playerY < this.y){
this.y += -1*this.speed;
} else if (playerY > this.y) {
this.y += 1*this.speed;
}
if (playerX < this.x){
this.x += -1*this.speed;
} else if (playerX > this.x){
this.x += 1*this.speed;
}
}
/*
this.clicked = function(mX,mY){
if (dist(mX,mY,this.x,this.y) <= this.r){
return true;
}
return false;
}
*/
}
function Player(){
this.x = width/2;
this.y = height/2;
this.r = 20;
this.speed = 4;
this.show = function(){
fill(0,255,0);
stroke(0,128,0);
circle(this.x,this.y,this.r);
}
this.moveY = function(number){
this.y += (number*this.speed);
}
this.moveX = function(number){
this.x += (number*this.speed);
}
this.MovePlayer = function(){
if (keyIsDown(UP_ARROW)){
if (this.y + (-1*20) > 0)
this.moveY(-1);
}
if (keyIsDown(DOWN_ARROW)){
if (this.y + (1*20) < height)
this.moveY(1);
}
if (keyIsDown(LEFT_ARROW)){
if (this.x + (-1*20) > 0)
this.moveX(-1);
}
if (keyIsDown(RIGHT_ARROW)){
if (this.x + (1*20) < width)
this.moveX(1);
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>

Related

Objects not shown on screen & keyPressed not working (Flappy Bird Code Challenge)

I created flappy bird game following The Coding Train's tutorial on Youtube.
(https://www.youtube.com/watch?v=cXgA1d_E-jY)
The original instruction created pipes and ball as objects, but I modified mine to be created as classes instead.
I have two problems.
1)The pipes indices I created in pipes array did not show on screen,
2)ball.goup();, which would be triggered by keyPressed() does nothing on screen, but console.log shows it is working.
How should I revise my code? Thanks.
let ball;
let pipes = [];
function setup() {
createCanvas(700, 600);
ball = new Ball();
pipes.push(new Pipe());
}
function draw() {
background(0);
ball.show();
ball.falldown();
if (frameCount % 60 == 0) {
pipes.push(new Pipe());
}
//since have splice, count from back to avoid uncounted indices
for (let i = pipes.length - 1; i >= 0; i--) {
pipes[i].show();
pipes[i].move();
if (pipes[i].hits(ball)) {
console.log("hit");
}
if (pipes[i].offscreen()) {
pipes.splice(i, 1);
}
}
}
function keyPressed() {
if (key == ' ') {
ball.goup;
console.log('up');
}
}
class Ball {
constructor(x = 50, y = height / 2, g = 0.6, v = 0, l = -20) {
this.x = x;
this.y = y;
this.gravity = g;
this.velocity = v;
this.lift = l;
}
goup() {
this.velocity += this.lift;
}
falldown() {
this.velocity += this.gravity;
this.velocity *= 0.9;
this.y += this.velocity;
if (this.y > height) {
this.y = height;
this.velocity = 0;
}
if (this.y < 0) {
this.y = 0;
this.velocity = 0;
}
}
show() {
noStroke();
fill(255);
ellipse(this.x, this.y, 25, 25);
}
}
class Pipe {
constructor(x =width, y=0, w=100, t=random(2/height), b=random(2/height), s=2, c=false) {
this.x = x;
this.y = y;
this.w = w;
this.top = t;
this.bottom = b;
this.speed = s;
this.colorchange = c;
}
hits(ball) {
if (ball.y < this.top || ball.y > height - this.bottom) {
if(ball.x > this.x && ball.x < this.x + this.w){
this.colorchange = true;
return true;
}
}
this.colorchange = false;
return false
}
move() {
this.x -= this.speed;
}
show() {
fill(255);
if (this.colorchange) {
fill(255, 0, 0);
}
rect(this.x, this.y, this.w, this.top);
rect(this.x, height - this.bottom, this.w, this.bottom);
}
//delete pipe indices from the array when pipes are off screen
offscreen() {
if (this.x < -this.w) {
return true;
} else {
return false;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
The logic is sound, but there are a couple of typos. First, the ball isn't going up because by using this.goup you're not executing the method: the parenthesis are missing. Change that line (inside the keyPressed() function) for: this.goup() and the ball will start responding to the keyboard input.
As for the pipes, they are drawing, but the default top and bottom are being defined as random(2 / height), and, being that height is equal to 600, it will result in a final value between 0 and 0.003333. To fix that, just rewrite the value assignment as t=random(height/2), b=random(height/2).
let ball;
let pipes = [];
function setup() {
createCanvas(700, 600);
ball = new Ball();
pipes.push(new Pipe());
}
function draw() {
background(0);
ball.show();
ball.falldown();
if (frameCount % 60 == 0) {
pipes.push(new Pipe());
}
//since have splice, count from back to avoid uncounted indices
for (let i = pipes.length - 1; i >= 0; i--) {
pipes[i].show();
pipes[i].move();
if (pipes[i].hits(ball)) {
//console.log("hit");
}
if (pipes[i].offscreen()) {
pipes.splice(i, 1);
}
}
}
function keyPressed() {
if (key == ' ') {
ball.goup();
//console.log('up');
}
}
class Ball {
constructor(x = 50, y = height / 2, g = 0.6, v = 0, l = -20) {
this.x = x;
this.y = y;
this.gravity = g;
this.velocity = v;
this.lift = l;
}
goup() {
this.velocity += this.lift;
}
falldown() {
this.velocity += this.gravity;
this.velocity *= 0.9;
this.y += this.velocity;
if (this.y > height) {
this.y = height;
this.velocity = 0;
}
if (this.y < 0) {
this.y = 0;
this.velocity = 0;
}
}
show() {
noStroke();
fill(255);
ellipse(this.x, this.y, 25, 25);
}
}
class Pipe {
constructor(x = width, y = 0, w = 100, t = random(height/2), b = random(height / 2), s = 2, c = false) {
this.x = x;
this.y = y;
this.w = w;
this.top = t;
this.bottom = b;
this.speed = s;
this.colorchange = c;
}
hits(ball) {
if (ball.y < this.top || ball.y > height - this.bottom) {
if (ball.x > this.x && ball.x < this.x + this.w) {
this.colorchange = true;
return true;
}
}
this.colorchange = false;
return false
}
move() {
this.x -= this.speed;
}
show() {
fill(255);
if (this.colorchange) {
fill(255, 0, 0);
}
rect(this.x, this.y, this.w, this.top)
rect(this.x, height - this.bottom, this.w, this.bottom);
}
//delete pipe indices from the array when pipes are off screen
offscreen() {
if (this.x < -this.w) {
return true;
} else {
return false;
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>

jQuery gets my buttons after pressing arrow buttons

In the below code, pressing C or V should change speed of that ball.
Press V ~10 times and after 5-10 seconds press an arrow button. Where is my mistake?
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
function circle(x, y, radius, fillCircle) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false);
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
};
function ball() {
this.speed = 5;
this.x = width / 2;
this.y = height / 2;
this.xSpeed = this.speed;
this.ySpeed = 0;
this.size = 5;
};
ball.prototype.move = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 0) {
this.x = width;
} else if (this.x > width) {
this.x = 0;
}
if (this.y > height) {
this.y = 0;
} else if (this.y < 0) {
this.y = height;
}
};
ball.prototype.draw = function() {
circle(this.x, this.y, this.size, true);
};
ball.prototype.setDirection = function(direction) {
if (direction === "up") {
this.xSpeed = 0;
this.ySpeed = -this.speed;
} else if (direction === "down") {
this.xSpeed = 0;
this.ySpeed = this.speed;
} else if (direction === "right") {
this.xSpeed = this.speed;
this.ySpeed = 0;
} else if (direction === "left") {
this.xSpeed = -this.speed;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
ball.prototype.doCommand = function(direction) {
if (direction === "X") {
this.size += 2;
} else if (direction === "Z") {
this.size -= 2;
} else if (direction === "C") {
this.speed -= 2;
} else if (direction === "V") {
this.speed += 2;
}
if (this.speed < 0) {
this.speed = 1;
}
if (this.size < 0) {
this.size = 1;
}
}
var Ball = new ball();
var commands = ["Z", "X", "C", "V"];
var keyActions = {
32: "stop",
37: "left",
38: "up",
39: "right",
40: "down",
90: "Z",
88: "X",
67: "C",
86: "V"
};
$("body").keydown(function(event) {
var direction = keyActions[event.keyCode];
for (var n = 0; n < commands.length; n++) {
if (direction === commands[n]) {
Ball.doCommand(direction);
} else {
Ball.setDirection(direction);
}
};
});
setInterval(function() {
ctx.clearRect(0, 0, width, height);
Ball.draw();
Ball.move();
ctx.strokeRect(0, 0, width, height);
}, 30);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>
I have updated your code.
First thing in keydown Handler we don't need for loop. I have changed this.
I have updated Do Command as well. Here is the problem: you are not updating xspeed & yspeed in the doCommand I did that change for c & v.
I hope this is what you are expecting.
Please find the updated code.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"><title>Drawing some circles...</title>
</head>
<body>
<script src = "https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id = "canvas" width="400" height="400"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;
function circle(x,y,radius,fillCircle)
{
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
if(fillCircle)
{
ctx.fill();
}
else
{
ctx.stroke();
}
};
function ball()
{
this.speed = 5;
this.x = width/2;
this.y = height/2;
this.xSpeed = this.speed;
this.ySpeed = 0;
this.size = 5;
};
ball.prototype.move = function()
{
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x<0)
{
this.x = width;
}
else if(this.x>width)
{
this.x = 0;
}
if (this.y>height)
{
this.y = 0;
}
else if(this.y<0)
{
this.y = height;
}
};
ball.prototype.draw = function()
{
circle(this.x,this.y,this.size,true);
};
ball.prototype.setDirection = function(direction)
{
if(direction ==="up")
{
this.xSpeed = 0;
this.ySpeed = -this.speed;
}else if(direction ==="down")
{
this.xSpeed = 0;
this.ySpeed = this.speed;
}else if(direction ==="right")
{
this.xSpeed = this.speed;
this.ySpeed = 0;
}else if(direction ==="left")
{
this.xSpeed = -this.speed;
this.ySpeed = 0;
}else if(direction ==="stop")
{
this.xSpeed = 0;
this.ySpeed = 0;
}
};
ball.prototype.doCommand = function(direction)
{
if(direction ==="X")
{
this.size +=2;
}else if(direction ==="Z"){
this.size -=2;
}else if(direction ==="C"){
this.speed -=2;
}else if(direction ==="V"){
this.speed +=2;
}
if(this.speed<0)
{
this.speed = 1;
}
if(this.size<0)
{
this.size = 1;
}
if(direction ==="V" || direction ==="C") {
if(this.xSpeed!=0) {
this.xSpeed = this.speed;
}
if(this.ySpeed!=0) {
this.ySpeed = this.speed;
}
}
}
var Ball = new ball();
var commands = ["Z","X","C","V"];
var keyActions = {
32:"stop",
37:"left",
38:"up",
39:"right",
40:"down",
90:"Z",
88:"X",
67:"C",
86:"V"
};
$("body").keydown(function (event)
{
var direction = keyActions[event.keyCode];
if(commands.includes(direction))
{
Ball.doCommand(direction);
}
else{
Ball.setDirection(direction);
}
});
setInterval(function()
{
ctx.clearRect(0,0,width,height);
Ball.draw();
Ball.move();
ctx.strokeRect(0,0,width,height);
}, 30);
</script>
</body>
</html>

Collision between ball and paddle in pong game on canvas

The ball seems to bounce off one side of the paddle, but when it comes from the side it glitches through the paddle. I just can't find a way behind it and it really bothers me. I am using some logic gates to define where the ball's direction is need to be invereted
function startGame() {
GameArea.start();
Ball1 = new CircleComp('white' , window.innerWidth - 200 , window.innerHeight - 20);
Ball1.ySpeed = 13.5;
Ball1.xSpeed = 6;
Paddle1 = new PaddleComp( 87, 83, 0, window.innerHeight / 2.5, 10, 70);
Paddle2 = new PaddleComp( 38, 40, window.innerWidth - 10, window.innerHeight / 2.5, 10 , 70);
}
var GameArea = {
canvas : canvas = document.querySelector("canvas"),
start : function (){
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('keydown', function (e) {
GameArea.keys = (GameArea.keys || []);
GameArea.keys[e.keyCode] = true;
})
window.addEventListener('keyup', function (e) {
GameArea.keys[e.keyCode] = false;
})
},
clear : function() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function CircleComp(color, x , y){
this.x = x;
this.y = y;
this.width = 8;
this.height = 8;
var context1 = GameArea.ctx;
this.update = function(){
context1.beginPath();
context1.fillStyle = color;
context1.fillRect(this.x, this.y, this.width, this.height);
context1.fill();
context1.stroke();
this.updatePosition();
}
this.updatePosition = function(){
this.y += this.ySpeed;
this.x += this.xSpeed;
if(this.x + this.width > GameArea.canvas.width){
this.xSpeed = -this.xSpeed;
}
if(this.y + this.height > GameArea.canvas.height){
this.ySpeed = -this.ySpeed;;
}
if(this.x - this.width < 0){
this.xSpeed = -this.xSpeed;
}
if(this.y - this.height < 0){
this.ySpeed = -this.ySpeed;
}
if(this.y + this.height > Paddle2.y && this.y - this.width < (Paddle2.y + 130) && this.x + this.width > Paddle2.x ){
this.xSpeed = -this.xSpeed;
}
if(this.y + this.height > Paddle1.y && this.y - this.width < (Paddle1.y + 70) && this.x - this.height < Paddle1.x + 10){
this.xSpeed = -this.xSpeed;
}
}
}
function PaddleComp(Upkey, Downkey, x, y, width, height){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.ySpeed = 0;
var context2 = GameArea.ctx;
this.update = function(){
context2.fillStyle = 'white';
context2.fillRect(x,this.y,this.width,this.height);
this.updatePosition();
}
this.updatePosition = function() {
this.ySpeed = 0;
if (GameArea.keys && GameArea.keys[Upkey]) {
this.ySpeed = -15; //console.log('Up');
}
if (GameArea.keys && GameArea.keys[Downkey]) {
this.ySpeed = 15; //console.log('Down');
}
if ((GameArea.keys && GameArea.keys[Downkey]) && this.y + 130 > window.innerHeight){
this.ySpeed = this.ySpeed -15 ;
}
if ((GameArea.keys && GameArea.keys[Upkey]) && this.y < 0 ){
this.ySpeed = this.ySpeed +15 ;
}
this.y += this.ySpeed;
}
}
function updateGameArea(){
GameArea.clear();
Paddle1.update();
Paddle2.update();
Ball1.update();
}
<html>
<head>
<meta charset='urf-8'>
<style>
canvas{
border: 0px solid black;
background-color: black;
}
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body onload='startGame()'>
<canvas></canvas>
<script src='Pong.js'></script>
</body>
</html>
Could not see directly what the problem was with your code so i just rewrote the code with the ball, bat (paddle) test function in the ball Object and called from the players object. ball.checkPad(player); tests if the ball has hit the players bat. To help picture what is happening I have slowed it all down and made the bats real phat. When the ball hits the bat it will turn yellow and the bat red for a second or so.
There is plenty of comments in the parts you asked about,
Hope it helps
Demo copied from OP question.
const setting = {
speed : 2, // of ball
left : 0,
width : 400,
height : 200,
padWidth : 50,
padHeight : 80,
padSpeed : 4, // double balls
hitPauseCount : 30, // nuber of frames to hold when there is a collisiotn so you
// can check all is good
}
const keys = {
ArrowUp : false,
ArrowDown : false,
ArrowLeft : false,
ArrowRight : false,
keyEvent(e) { // dont use keyCode it has depreciated
if (keys[e.code] !== undefined) {
keys[e.code] = e.type === "keydown";
e.preventDefault();
}
}
}
var ctx;
var ball1, paddle1, paddle2;
var gameArea = {
start() {
canvas.width = setting.width;
canvas.height = setting.height;
ctx = canvas.getContext('2d');
requestAnimationFrame(updateGameArea);
},
clear() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
}
}
gameArea.start();
ball = new CircleComp('white', window.innerWidth - 200, window.innerHeight - 20);
ball.ySpeed = setting.speed;
ball.xSpeed = setting.speed;
paddle1 = new PaddleComp("ArrowUp", "ArrowDown", setting.left, setting.height / 2, setting.padWidth, setting.padHeight);
paddle2 = new PaddleComp("ArrowLeft", "ArrowRight", setting.width - setting.padWidth, setting.height / 2, setting.padWidth, setting.padHeight);
window.addEventListener('keydown', keys.keyEvent);
window.addEventListener('keyup', keys.keyEvent);
function CircleComp(color, x, y) {
this.x = x;
this.y = y;
this.width = 8;
this.height = 8;
this.xSpeed = setting.speed;
var hit = 0;
var restartCount;
var serveDirection;
this.reset = function(){
this.x = ctx.canvas.width /2;
this.y = ctx.canvas.height / 2;
this.xSpeed = -this.xSpeed
this.ySpeed = setting.speed * Math.sign(Math.random() - 0.5);
restartCount = 60;
}
this.draw = function () {
if(hit > 0){
hit -= 1;
ctx.fillStyle = "yellow";
}else{
ctx.fillStyle = color;
}
ctx.fillRect(this.x, this.y, this.width, this.height);
}
// next funtion is called by the player objects
this.checkPad = function (player) {
if (player.x > canvas.width / 2) { // is player on left or right
if (this.xSpeed > 0) { // player on right only check if ball moving rigth
if (this.x + this.width > player.x) { // ball is in paddles zone
//if not bottom of ball above top of bat or top of ball bellow bottom of bat
if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
// ball and bat in contact
// is ball moving down and the balls top edge above the player
// then ball has hit the top side of the bat
if(this.ySpeed > 0 && this.y <= player.y){
this.y = player.y - this.width;
this.ySpeed = -setting.speed;
}else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
this.y = player.y + player.height;
this.ySpeed = setting.speed;
}else{ // ball hit front of bat
this.x = player.x - this.width;
this.xSpeed = - setting.speed;
}
player.hit = setting.hitPauseCount; // counters to show FX when a hit happens
hit = setting.hitPauseCount;
}
}
}
} else { // player must be left
if (this.xSpeed < 0) { // ball must move left
if (this.x < player.x + player.width) { // ball is in paddles zone
if (!(this.y + this.height <= player.y || this.y >= player.y + player.height)) {
// ball and bat in contact
// ball and bat in contact
// is ball moving down and the balls top edge above the player
// then ball has hit the top side of the bat
if(this.ySpeed > 0 && this.y <= player.y){
this.y = player.y - this.width;
this.ySpeed = -setting.speed;
}else if(this.ySpeed < 0 && this.y + this.height >= player.y + player.height){ // do bottom check
this.y = player.y + player.height;
this.ySpeed = setting.speed;
}else{ // ball hit front of bat
this.x = player.x + player.width;
this.xSpeed = setting.speed;
}
player.hit = setting.hitPauseCount; // counters to show FX when a hit happens
hit = setting.hitPauseCount;
}
}
}
}
}
this.update = function () {
if(restartCount > 0){ // wait for restart pause
restartCount -= 1;
}else{
if(hit > 0){ // do nothing if paused
return;
}
this.y += this.ySpeed;
this.x += this.xSpeed;
if (this.x + this.width >= canvas.width) {
this.reset(); // point
} else if (this.x < 0) {
this.reset(); // point
}
if (this.y + this.height >= canvas.height) {
this.y = canvas.height - this.height;
this.ySpeed = -setting.speed;
} else if (this.y < 0) {
this.y = 0;
this.ySpeed = setting.speed;
}
}
}
this.reset();
}
function PaddleComp(upKey, downKey, x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.hit = 0;
this.draw = function () {
if(this.hit > 0){
this.hit -= 1;
ctx.fillStyle = "red";
}else{
ctx.fillStyle = '#9CF';
}
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.update = function () {
if (keys[upKey]) {
this.y -= setting.padSpeed;
};
if (keys[downKey]) {
this.y += setting.padSpeed;
};
if (this.y < 0) {
this.y = 0;
}
if (this.y + this.height >= canvas.height) {
this.y = canvas.height - this.height;
}
ball.checkPad(this);
}
}
function updateGameArea() {
gameArea.clear();
paddle1.update();
paddle2.update();
ball.update();
paddle1.draw();
paddle2.draw();
ball.draw();
requestAnimationFrame(updateGameArea);
}
<canvas id=canvas style='background:#69C;border:2px blue solid'></canvas>

How to check collision with player and ball?

I'm trying to make a brick game with a ball and a player (platform). If the ball hits the player, it should go off in the other direction like ping pong. However, it's not detecting the collision.
Here's the code
html:
<canvas id="canvas" width= "400" height= "400"></canvas>
css:
#canvas{border:1px solid black}
Js:
var width = 400
var height = 400
var drawRect = function (x, y) {
ctx.fillRect(x, y, 30, 5)
};
// The Ball constructor
var Player = function () {
this.x = 395
this.y = 395
this.xSpeed = 5;
this.ySpeed = 0;
};
// Update the ball's position based on its speed
Player.prototype.move = function () {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 0) {
this.x = width;
} else if (this.x > width) {
this.x = 0;
} else if (this.y < 0) {
this.y = height;
} else if (this.y > height) {
this.y = 0;
}
};
// Draw the ball at its current position
Player.prototype.draw = function () {
drawRect(this.x, this.y);
};
// Set the ball's direction based on a string
Player.prototype.setDirection = function (direction) {
if (direction === "left") {
this.xSpeed = -5;
this.ySpeed = 0;
} else if (direction === "right") {
this.xSpeed = 5;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
// Create the ball object
var player = new Player();
// An object to convert keycodes into action names
var keyActions = {
32: "stop",
37: "left",
38: "up",
39: "right",
40: "down"
};
// The keydown handler that will be called for every keypress
$("html").keydown(function (event) {
var direction = keyActions[event.keyCode];
player.setDirection(direction);
});
var Ball = function () {
this.x = 100;
this.y = 100;
this.xSpeed = -2
this.ySpeed = 3;
};
var circle = function (x, y, radius, fillCircle) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false)
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
}
Ball.prototype.move = function () {
this.x += this.xSpeed
this.y += this.ySpeed
};
Ball.prototype.draw = function () {
circle(this.x, this.y, 3, true);
};
Ball.prototype.checkCollision = function () {
if (this.x < 0 || this.x > 400) {
this.xSpeed = -this.xSpeed
}
if (this.y < 0) {
this.ySpeed = -this.ySpeed
}
};
Ball.prototype.checkCollisionPlayer = function () {
if (this.x === Player.x || this.y === player.y) {
this.ySpeed = -this.ySpeed
this.xSpeed = -this.xSpeed
}
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
setInterval(function () {
ctx.clearRect(0, 0, 400, 400);
player.draw();
player.move();
ball.draw();
ball.move();
ball.checkCollision();
ball.checkCollisionPlayer();
}, 40);
var ball = new Ball();
Thanks for your support. :)
I've added a simple box collision and update the classes to have the box dimensions of the ball and player. Remember that the ball box has to adjust for radius offset.
update
The kind of collision detection needed for the boxes you have to know side or corner that was hit. I updated the example as a starting point for this but it's needs to have the corners added and I also don't know the optimal detection. The blocks are setup for testing. I hope this helps.
var width = 400
var height = 400
function Brick(x, y, w, h, color) {
this.x = x;
this.y = y;
this.color = color;
this.w = w;
this.h = h;
this.hits = 0;
}
Brick.prototype.draw = function() {
ctx.save();
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
ctx.fillStyle = "white";
ctx.fillText(this.hits, this.x + 2, this.y + 10);
ctx.restore();
};
var bricks = [
new Brick(80, 120, 15, 15, 'red'),
new Brick(220, 90, 15, 15, 'blue'),
new Brick(340, 100, 50, 20, 'green')
];
// The Ball constructor
var Player = function() {
this.x = 395
this.y = 395
this.xSpeed = 5;
this.ySpeed = 0;
this.w = 30;
this.h = 5;
};
// Update the ball's position based on its speed
Player.prototype.move = function() {
this.x += this.xSpeed;
this.y += this.ySpeed;
if (this.x < 0) {
this.x = width;
} else if (this.x > width) {
this.x = 0;
} else if (this.y < 0) {
this.y = height;
} else if (this.y > height) {
this.y = 0;
}
};
// Draw the ball at its current position
Player.prototype.draw = function() {
ctx.fillRect(this.x, this.y, this.w, this.h);
};
// Set the ball's direction based on a string
Player.prototype.setDirection = function(direction) {
if (direction === "left") {
this.xSpeed = -5;
this.ySpeed = 0;
} else if (direction === "right") {
this.xSpeed = 5;
this.ySpeed = 0;
} else if (direction === "stop") {
this.xSpeed = 0;
this.ySpeed = 0;
}
};
// Create the ball object
var player = new Player();
// An object to convert keycodes into action names
var keyActions = {
32: "stop",
37: "left",
38: "up",
39: "right",
40: "down"
};
// The keydown handler that will be called for every keypress
$("html").keydown(function(event) {
var direction = keyActions[event.keyCode];
player.setDirection(direction);
});
var Ball = function() {
this.x = 100;
this.y = 100;
this.xSpeed = -2
this.ySpeed = 3;
this.radius = 3;
};
var circle = function(x, y, radius, fillCircle) {
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI * 2, false)
if (fillCircle) {
ctx.fill();
} else {
ctx.stroke();
}
}
Ball.prototype.move = function() {
this.x += this.xSpeed
this.y += this.ySpeed
if ((this.y + this.radius) > ctx.canvas.height) {
// floor to ceiling
this.y = 0;
}
};
Ball.prototype.draw = function() {
circle(this.x, this.y, this.radius, true);
};
Ball.prototype.getBox = function() {
return {
x: this.x - this.radius,
y: this.y - this.radius,
w: this.radius * 2,
h: this.radius * 2
};
};
Ball.prototype.checkCollision = function() {
if (this.x < 0 || this.x > 400) {
this.xSpeed = -this.xSpeed
}
if (this.y < 0) {
this.ySpeed = -this.ySpeed
} else {
var boxA = this.getBox();
switch (boxCollide(boxA, player)) {
case 1:
case 3:
this.ySpeed = -this.ySpeed;
break;
case 2:
case 4:
this.xSpeed = -this.xSpeed;
break;
}
}
};
// does box a collide with box b
// box = {x:num,y:num,w:num,h:num}
function boxCollide(a, b) {
var ax2 = a.x + a.w;
var ay2 = a.y + a.h;
var bx2 = b.x + b.w;
var by2 = b.y + b.h;
// simple hit true, false
//if (ax2 < b.x || a.x > bx2 || ay2 < b.y || a.y > by2) return false;
// return true
var xInRange = (a.x >= b.x && a.x <= bx2 || ax2 >= b.x && ax2 <= bx2);
var yInRange = (a.y >= b.y && a.y <= by2 || ay2 >= b.y && ay2 <= by2);
// Clockwise hit from top 1,2,3,4 or -1
if (ay2 > b.y && a.y < by2 && xInRange) return 1; // A hit the top of B
if (a.x < bx2 && ax2 > b.x && yInRange) return 2; // A hit the right of B
if (a.y < by2 && ay2 > b.y && xInRange) return 3; // A hit the bottom of B
if (ax2 > b.x && a.x < bx2 && yInRange) return 4; // A hit the right of B
return -1; // nohit
}
Ball.prototype.checkCollisionPlayer = function() {
if (this.x === Player.x || this.y === player.y) {
this.ySpeed = -this.ySpeed
this.xSpeed = -this.xSpeed
}
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
setInterval(function() {
ctx.clearRect(0, 0, 400, 400);
player.draw();
player.move();
ball.draw();
ball.move();
ball.checkCollision();
ball.checkCollisionPlayer();
var boxA = ball.getBox();
for (var i = 0; i < bricks.length; i++) {
switch (boxCollide(boxA, bricks[i])) {
case 1:
ball.y = bricks[i].y - ball.radius - 1;
ball.ySpeed = -ball.ySpeed;
bricks[i].hits++;
break;
case 3:
ball.y = bricks[i].y + ball.radius + bricks[i].h + 1;
ball.ySpeed = -ball.ySpeed;
bricks[i].hits++;
break;
case 2:
ball.x = bricks[i].x + ball.radius + bricks[i].w + 1;
ball.xSpeed = -ball.xSpeed;
bricks[i].hits++;
break;
case 4:
ball.x = bricks[i].x - ball.radius - 1;
ball.xSpeed = -ball.xSpeed;
bricks[i].hits++;
break;
}
bricks[i].draw();
}
},
40);
var ball = new Ball();
#canvas {
border: 1px solid black
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas" width="400" height="400"></canvas>

Javascript canvas game

I have a problem with my canvas game. I try to make it jump but I have some troubles with it. Everything is working fine but if I touch an object from the bottom, it throw me up to the object.
Problem may be with LastColison. Can someone help me ? GIF Image link.
function Block(x, y) {
var size = 80
GameObject.call(this, x*size, y*size, size)
this.img = document.getElementById("block")
this.class = "block"
}
// Dedi vlastnosti z GameObject
Block.prototype = Object.create(GameObject.prototype)
Block.prototype.draw = function() {
ctx.fillStyle = "green"
ctx.drawImage(this.img,this.x,this.y,this.size,this.size)
}
function Player(x, y) {
var size = 120
this.dx = Math.random() * 50 - 25
this.dy = Math.random() * 50 - 25
GameObject.call(this, x*size, y*size, size)
// this.player = document.getElementById("player")
this.img = [document.getElementById("player"),document.getElementById("ball_r"),document.getElementById("ball_l"),document.getElementById("ball_j")]
this.player = this.img[0]
this.class = "player"
}
// Dedi vlastnosti z GameObject
Player.prototype = Object.create(GameObject.prototype)
Player.prototype.move = function() {
var x = this.x
var y = this.y
//ak dam this.y = y -5 môžem pohnuť aj so stlačenou sipkou dole
this.player = this.img[0]
// Posun
if ( keys[37] )
{
if(level == 0){
x -= 4;
}
if (level == 1) {
x -= 8;
}
this.player = this.img[2];
this.y = y;
}
if ( keys[39])
{
if (level == 0) {
x += 4;
}
if (level == 1) {
x += 8;
}
this.player = this.img[1];
}
if ( keys[38] )
{ this.player = this.img[3], this.dy = -10; }
// ak nedam else if mozem ouzzivat naraz viac tlacidiel takze upravit potom
// Test novej pozicie
var collision = false
for (i in scene) {
var obj = scene[i]
if (obj.class == "cloud") { continue; }
if (obj.class == "ladder") { continue; }
if (obj.class == "touched") { continue; }
if (obj.class == "dirt") { this.x = x; this.y = y }
if (obj.class == "block") { this.x = x; this.y = y }
if (obj.class == "enemy") { this.x = x; this.y = y}
var test = x +30 >= obj.x + obj.size || x + this.size - 40<= obj.x /* kolide right*/|| y >= obj.y + obj.size /*kolizia up*/|| y + 40 + this.size <= obj.y /*kolizia bottom*/
if (!test) {
collision = true;
var touch = 0;
if (obj.class == "enemy") {
touch = 1;
if (touch == 1) {
health -= 20; console.log(health);
this.x = x - 250;
if (klik % 2 == 0){
var hit = new Audio('snd/Hit_Hurt15.wav')
hit.play()
}
}
if (health == 0) { health = 0; console.log("GAMEOVER");scene = []}
}
if (obj.class == "coin") {
score += 10; obj.class = "touched";
if (klik % 2 == 0) {
var hrahra = new Audio('snd/pickcoin.wav')
hrahra.play()
}
}
else { touch = 0; }
if (obj.class == "touched") {}
break;
}
}
if (score >= 200 && score <= 200) {
if (klik % 2 == 0) {
var levelup = new Audio('snd/Powerup9.wav')
levelup.loop = false;
levelup.play()
}
level = 1;
health = 100;
score += 1;
}
// Ladder
// if(collision){score += 1,scene.pop() }
// Posun bez kolizie
if (!collision) {
this.x = x
this.y = y + this.dy
this.dy += 0.3;
}
**else {
if (obj.class == this.LastColl) {
this.dy = 0;
this.y = obj.y -160
}
this.dy = 0;
this.LastColl = obj.class
}**
}
Player.prototype.draw = function() {
ctx.fillStyle = "blue"
ctx.beginPath()
ctx.drawImage(this.player,this.x, this.y, 110,160)
ctx.shadowColor = "rgba( 0, 0, 0, 0.3 )";
ctx.shadowOffsetX = -10;
ctx.shadowOffsetY = 0
ctx.shadowBlur = 3;
ctx.drawImage(this.player,this.x,this.y,110,160)
ctx.closePath()
ctx.fill()
}
I can't currently access the GIF you provided. But from what i can gather these lines are your problem:
if (!collision) {
this.x = x
this.y = y + this.dy
this.dy += 0.3;
}
**else {
if (obj.class == this.LastColl) {
this.dy = 0;
this.y = obj.y -160
}
This line - this.y = obj.y -160
Looks like you're telling it to move up -160 pixels on the canvas.
Does this answer your question?
Just a note too - I'd recommend using semicolons at the end of each statement. Don't sometimes use them and other times don't - it will cause problems for you and is bad practice :)
I don't know much about canvas right now, but I noticed that you don't have any semicolons to end your statements...
example:
var x = this.x;
etc.
Another thing that I noticed... The score checks for both greater than or equal to and less than or equal to 200...
if (score >= 200 && score <= 200)
{
...
}

Categories