How to make a 2d character run and jump in JavaScript - javascript

I'm trying to make a square using canvas and making it jump and run, and I have followed the toturial of PothOnProgramming on youtube. I have written the code in a html document and for some reason nothing shows up on the browser when i test it.
<body>
<script>
var context, controller, player, loop;
context=document.querySelector("canvas").getContext("2d");
context.canvas.height=180;
context.canvas.width=320;
player={
height=32,
jumping=true,
width=32,
x=144,
x_velocity=0,
y=0,
y_velocity:0
};
controller={
left=false,
right=false,
up=false,
keyListener:function(event){
var kay_state=(event.type=="keydown")?true:false;
switch(event.keyCode){
case 87:
controller.up=key_state;
break;
case 68:
controller.right=key_state;
break;
case 65:
controller.left=key_state;
break;
}
}
};
loop=function(){
if(controller.up && player.jumping==false){
player.y_velocity-=20;
player.jumping=true;
}
if(controller.left){
player.x_velocity-=0.5; //For at "player" akselererer smooth
}
if(controller.right){
player.x_velocity+=0.5; //For at "player" akselererer smooth
}
player.y_velocity+=1.5; //Gravity
player.x+=player.x_velocity;
player.y+=player-y_velocity;
player.x_velocity*=0.9; //Friksjon (må leggest til eller så synker ikke farten)
player.y_velocity*=0.9; //Friksjon
//dersom player faller til y verdien så koliderer den (bunn linjen)
if(player.y>180-16-32){
player.jumping=false;
player.y=180-16-32;
player.y_velocity=0;
}
context.fillStyle = "#202020";
context.fillRect(0, 0, 320, 180);
context.fillStyle="#ff0000";
context.beginPath();
context.rect(player.x, player.y, player.width, player.height);
context.fill();
context.strokeStyle="#ff0000";
context.lineWidth=4;
context.beginPath();
context.moveTo(0, 164);
context.lineTo(320, 164);
context.stroke();
window.requestAnimationFrame(loop);
};
window.addEventListener("keydown", controller.keyListener);
window.addEventListener("keyup", controller.keyListener);
window.requestAnimationFrame(loop);
</script>
</body>
I'm quite new to this so it may be a simple typo, but I would love to find out what I can do differently to make it work.

You have numerous issues with this code. First you need to fix the object declarations. Objects don't use = for assigning values. You also have several typos with your variable names that I have fixed. Here is a working version:
var context, controller, player, loop
context = document.querySelector('canvas').getContext('2d')
context.canvas.height = 180
context.canvas.width = 320
player = {
height: 32,
jumping: true,
width: 32,
x: 144,
x_velocity: 0,
y: 0,
y_velocity: 0,
}
controller = {
left: false,
right: false,
up: false,
keyListener: function(event) {
var key_state = event.type == 'keydown' ? true : false
switch (event.keyCode) {
case 87:
controller.up = key_state
break
case 68:
controller.right = key_state
break
case 65:
controller.left = key_state
break
}
},
}
loop = function() {
if (controller.up && player.jumping == false) {
player.y_velocity -= 20
player.jumping = true
}
if (controller.left) {
player.x_velocity -= 0.5 //For at "player" akselererer smooth
}
if (controller.right) {
player.x_velocity += 0.5 //For at "player" akselererer smooth
}
player.y_velocity += 1.5 //Gravity
player.x += player.x_velocity
player.y += player.y_velocity
player.x_velocity *= 0.9 //Friksjon (må leggest til eller så synker ikke farten)
player.y_velocity *= 0.9 //Friksjon
//dersom player faller til y verdien så koliderer den (bunn linjen)
if (player.y > 180 - 16 - 32) {
player.jumping = false
player.y = 180 - 16 - 32
player.y_velocity = 0
}
context.fillStyle = '#202020'
context.fillRect(0, 0, 320, 180)
context.fillStyle = '#ff0000'
context.beginPath()
context.rect(player.x, player.y, player.width, player.height)
context.fill()
context.strokeStyle = '#ff0000'
context.lineWidth = 4
context.beginPath()
context.moveTo(0, 164)
context.lineTo(320, 164)
context.stroke()
window.requestAnimationFrame(loop)
}
window.addEventListener('keydown', controller.keyListener)
window.addEventListener('keyup', controller.keyListener)
window.requestAnimationFrame(loop)
<canvas></canvas>

To assign values to properties of an object you should use : instead of =.
So for player object it should be:
player={
height:32,
jumping:true,
width:32,
x:144,
x_velocity:0,
y:0,
y_velocity:0
};

Related

Arrow Key implementation javascript

ive been trying to flip the arrows when the cars are in different side of the road. The image shows two multi-lane roads where forward on the left side goes up and i want forward on the right to go down, and the same for right and left. ive tried my method but it doesnt seem to work so i think im doing something stupid. please hep with a method that can work, heres the code
class Controls
{
constructor(type,laneIndex)
{
this.laneIndex = laneIndex;
this.forward =false;
this.left = false ;
this.foward = false ;
this.reverse =false;
switch (type)
{
case "KEYS":
this.#addKeyboardListeners();
break;
case "DUMMY":
this.forward =true;
break;
}
}
#addKeyboardListeners()
{
if (this.laneIndex <= 3)
{
document.onkeydown=(event)=>
{
switch(event.key)
{
case "ArrowLeft":
this.left =true;
break;
case "ArrowRight":
this.right =true;
break;
case "ArrowUp":
this.forward =true;
break;
case "ArrowDown":
this.reverse =true;
break;
}
}
document.onkeyup=(event)=>
{
switch(event.key)
{
case "ArrowLeft":
this.left = false;
break;
case "ArrowRight":
this.right = false;
break;
case "ArrowUp":
this.forward = false;
break;
case "ArrowDown":
this.reverse =false;
break;
}
}
}
if (this.laneIndex >= 4)
{
document.onkeydown=(event)=>
{
switch(event.key)
{
case "ArrowLeft":
this.right =true;
break;
case "ArrowRight":
this.left =true;
break;
case "ArrowUp":
this.reverse =true;
break;
case "ArrowDown":
this.forward =true;
break;
}
}
document.onkeyup=(event)=>
{
switch(event.key)
{
case "ArrowLeft":
this.right =false;
break;
case "ArrowRight":
this.left =false;
break;
case "ArrowUp":
this.reverse =false;
break;
case "ArrowDown":
this.forward =false;
break;
}
}
}
}
}
Basic keyboard input
This answer shows a method for monitoring the ongoing keyboard state.
Keys of interest are flagged as true when down and false when up.
There is a demo (bottom) to show how this method can be used in an animated app interface.
Some pointers
Keep IO (mouse, keyboards, touch, joysticks etc..) and game logic separate as this help keeps the code simple.
Don't add events via the named event property. Eg document.onkeydown = function. As it can easily be overwritten by you or 3rd party code.
Use addEventListener to ensure the event will stay in place
Example of keyboard input
The example creates an object keys that has a property for each of the keys you want to keep track of. The keyboard event listener will set the state to true when a key is down and false if not.
You can add other keys by adding the KeyboardEvent.code name to keys object. Example I have added Space to listen for the space key (I will use it to switch tracks in next example.
const keys = (() => {
const keys = { // only names of keys you are interested in
ArrowUp: false,
ArrowRight: false,
ArrowDown: false,
ArrowLeft: false,
Space: false,
};
function listener(e) {
keys[e.code] !== undefined && (keys[e.code] = e.type === "keydown");
}
addEventListener("keyup", listener);
addEventListener("keydown", listener);
return keys;
})();
Using the input
Once you have the controlling input setup, your app logic need only monitor the state of the input and react as needed.
The example below uses the keys object to move the active car. W moves the car forward, and D moves it in reverse. The function that moves cars is Car.update
To switch cars press the space key. Switching cars can be found in renderLoop
Note Use WASD for control as arrow keys are not safe in stack overflow snippets
Note you need to focus the snippet for the keyboard events to be seen as stack overflow snippets can not automatically focus.
const keys = (() => {
const keys = { // only names of keys you are interested in
KeyW: false,
KeyS: false,
Space: false,
};
function listener(e) {
keys[e.code] !== undefined && (keys[e.code] = e.type === "keydown");
e.preventDefault(); // to stop stack overflow snippet problems
}
addEventListener("keyup", listener);
addEventListener("keydown", listener);
return keys;
})();
const P2 = (x, y) => ({x, y}); // creates 2D point
const Car = { // common properties for a car
on: false,
col: "#888",
/* Function that inspects keyboard state and moves car */
update() {
if (this.on) { // only if active
let mx = 0, my = 0;
if (keys.KeyW) { /* Check forward */
mx += this.dir.x * 3;
my += this.dir.y * 3;
}
if (keys.KeyS) { /* Check reverse */
mx -= this.dir.x;
my -= this.dir.y;
}
// Keep on canvas
if (this.pos.x + mx > W - 40 || this.pos.x + mx < 40) { mx = 0; }
if (this.pos.y + my > H - 40 || this.pos.y + my < 40) { my = 0; }
this.pos.x += mx;
this.pos.y += my;
}
},
draw() {
ctx.fillStyle = this.col;
const sx = this.size.x, sy = this.size.y;
ctx.setTransform(this.dir.y, this.dir.x, -this.dir.x, this.dir.y, this.pos.x, this.pos.y);
ctx.fillRect(sx * -0.5, sy * -0.5, sx, sy);
ctx.fillStyle = "#9AD";
ctx.fillRect(sx * -0.4, sy * -0.4, sx * 0.1, sy * 0.25);
ctx.fillRect(sx * -0.4, sy * -0.1, sx * 0.8, sy * 0.2);
ctx.fillRect(sx * 0.3, sy * -0.4, sx * 0.1, sy * 0.25);
ctx.strokeStyle = "#EA5";
ctx.lineWidth = 2;
ctx.beginPath();
if (this.on) {
ctx.moveTo(sx * -0.4 , sy * 1.5);
ctx.lineTo(sx * -0.25, sy * 0.5);
ctx.lineTo(sx * -0.1 , sy * 1.5);
ctx.moveTo(sx * 0.4 , sy * 1.5);
ctx.lineTo(sx * 0.25, sy * 0.5);
ctx.lineTo(sx * 0.1 , sy * 1.5);
}
ctx.moveTo(sx * -0.1 , sy * 0.5);
ctx.lineTo(sx * -0.4 , sy * 0.5);
ctx.moveTo(sx * 0.1 , sy * 0.5);
ctx.lineTo(sx * 0.4 , sy * 0.5);
ctx.stroke();
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore default transform incase
// you draw stuff not using setTransform
}
}
const cars = [{
dir: P2(0, 1), // forward direction
size: P2(30, 50),
pos: P2(100, 100),
...Car
}, {
dir: P2(0, -1), // forward direction
size: P2(30, 50),
pos: P2(200, 100),
...Car
},
];
requestAnimationFrame(renderLoop);
const ctx = canvas.getContext("2d"), W = canvas.width, H = canvas.height;
var carOnIdx = 0;
cars[carOnIdx].on = true;
function renderLoop(time) {
ctx.setTransform(1,0,0,1,0,0);
ctx.clearRect(0, 0, W, H);
ctx.fillStyle = "#555";
ctx.fillRect(10, 10, W - 20, H - 20);
ctx.fillStyle = "#DDD";
ctx.fillRect(70, 10, 2, H - 20);
ctx.fillRect(130, 10, 2, H - 20);
ctx.fillRect(175, 10, 2, H - 20);
ctx.fillRect(225, 10, 2, H - 20);
// If space key press changed cars
if (keys.Space) {
cars[carOnIdx].on = false;
carOnIdx = (carOnIdx + 1) % cars.length;
cars[carOnIdx].on = true;
// Only want the key down for space to flag it as used
keys.Space = false;
}
for (const car of cars) { car.update(); }
for (const car of cars) { car.draw(); }
requestAnimationFrame(renderLoop);
}
* {
font-family: arial;
}
canvas {
background: #4A6;
}
.info {
position: absolute;
left: 340px;
top: 20px;
font-size: large;
}
ul {
position: absolute;
left: 320px;
top: 30px;
}
<canvas id="canvas" width="300" height="300"></canvas>
<div class="info">Using keyboard input</div>
<ul>
<li>To focus keyboard on snippet, click snippet</li>
<li>Uses WASD rather than arrow keys</li>
<li>Space to switch cars</li>
<li>W to drive forward</li>
<li>D to reverse</li>
<li><b>Note</b> cars can not go outside canvas</li>
</ul>

If statement inside requestanimationframe continues even if parameters aren't met

I'm making a little video game, where the background (platform) moves down with my character (square) jumps. On line 113 I have tried different strategies to implement this thought, and that is the closest it has gotten to work. The issue is that even when the square velocity is 0, the platform velocity isn't. I have been stuck for a week now, and feels like javascript is the problem (even though I know it isn't).
canvasmain.width = window.innerWidth;
canvasmain.height = window.innerHeight;
//CHARACTER:
const square = {
height: 75,
jumping: true,
width: 75,
x: canvasmain.width / 2,
xVelocity: 0,
y: canvasmain.height / 2,
yVelocity: 0
};
//floor
const platform = {
height: 30,
width: 100,
x: square.x,
xVelocity: 0,
y: square.y + square.height,
yVelocity:0
}
//MOVEMENT:
const controller = {
left: false,
right: false,
up: false,
keyListener: function (event) {
let key_state = (event.type == "keydown") ? true : false;
switch (event.keyCode) {
case 37: // left arrow
controller.left = key_state;
break;
case 38: // up arrow
controller.up = key_state;
break;
case 39: // right arrow
controller.right = key_state;
break;
}
}
};
const loop = function () {
if (controller.up && square.jumping == false) {
square.yVelocity -= 30;
square.jumping = true;
}
if (controller.left) {
square.xVelocity -= 0.5;
}
if (controller.right) {
square.xVelocity += 0.5;
}
square.yVelocity += 1.5;// gravity
square.x += square.xVelocity;
square.y += square.yVelocity;
square.xVelocity *= 0.9;// friction
square.yVelocity *= 0.9;// friction
// if square is falling below floor line
if (square.y > canvasmain.height - 75) {
square.jumping = false;
square.y = canvasmain.height - 75;
square.yVelocity = 0;
}
// if square is going off the left of the screen
if (square.x < 0) {
square.x = 0;
} else if (square.x > canvasmain.width - 75) {// if square goes past right boundary
square.x = canvasmain.width - 75;
}
// Creates the backdrop for each frame
context.fillStyle = "#394129";
context.fillRect(0, 0, canvasmain.width, canvasmain.height); // x, y, width, height
// Creates and fills the cube for each frame
context.fillStyle = "#8DAA9D"; // hex for cube color
context.beginPath();
context.rect(square.x, square.y, square.width, square.height);
context.fill();
// Creates the "ground" for each frame
context.fillStyle = "#202020";
context.beginPath();
context.rect(platform.x, platform.y, platform.width, platform.height)
context.fill();
// call update when the browser is ready to draw again
window.requestAnimationFrame(loop);
//platform
platform.y += platform.yVelocity;
console.log(square.yVelocity)
if (square.yVelocity > 0.1 ) {
platform.yVelocity = 1.5
};
if (square.yVelocity < 0 ) {
platform.yVelocity = -1.5
};
}
window.addEventListener("keydown", controller.keyListener)
window.addEventListener("keyup", controller.keyListener);
window.requestAnimationFrame(loop);
You're not reseting the value of yVelocity.
Got it guys, thx #Teemu, I just needed to set it to 0 if it wasn't the if's. Dang, really took a while. if (square.yVelocity > 0 ) {platform.yVelocity = 1.5} else{ platform.yVelocity = 0}; if (square.yVelocity < 0 ) {platform.yVelocity = -1.5} else { platform.yVelocity = 0} }
edit: frick, it only moves the platform when the cube is going up, not down ;-;

How can I shoot a moving bullet?

Hi I'm new here and also in the programming world, so, I have a little problem: I'm making a simple game engine in JS because I want to replicate the original Space Invaders game, the problem is just the bullet is not moving, only appears and disappears, like a laser shot. I want to have a moving bullet. Anyone can help me?
P.S. I don't wanna use object oriented programming here, I want to make the whole game in a single .js file.
console.log('GAME LOADED//SPACE INVADERS');
////////////////////////////////////////////////
let screen = document.createElement('canvas');
screen.width = 800;
screen.height = 900;
document.body.appendChild(screen);
document.addEventListener('keydown', keyDown, false);
document.addEventListener('keyup', keyUp, false);
let ctx = screen.getContext('2d');
////////////////////////////////////////////////
let x = screen.width / 2;
let y = screen.height / 2;
let bulletY = screen.height - 20;
let bulletSpeed = 10;
let bulletLifeTime = 3;
let size = 20;
let sWidth = screen.width;
let sHeight = screen.height;
let columns = screen.width / size;
let rows = screen.height / size;
let speed = 5;
let right = false;
let left = false;
let up = false;
let down = false;
let shot = false;
let gravity = 10;
let jumpForce = 40 ;
/////////////////////////////////////////////////
function keyDown() {
switch(event.keyCode) {
case 39: right = true;
break;
case 37: left = true;
break;
//case 40: up = true;
//break;
//case 38: down = true;
//break;
case 32: shot = true;
break;
}
}
function keyUp() {
switch(event.keyCode) {
case 39: right = false;
break;
case 37: left = false;
break;
//case 40: up = false;
//break;
//case 38: down = false;
//break;
case 32: shot = false;
break;
}
}
function move() {
if(right == true) {
x += 1 * speed;
} else if(left == true) {
x -= 1 * speed;
}
//if(up == true) {
//y += 1 * speed;
//} else if(down == true) {
//y -= 1 * speed;
//}
}
function player() {
ctx.fillStyle = '#1CE80D';
ctx.fillRect(x, y, size, size);
ctx.fillRect(x+10, y, size, size);
ctx.fillRect(x+20, y, size, size);
ctx.fillRect(x-10, y, size, size);
ctx.fillRect(x-20, y, size, size);
ctx.fillRect(x+5, y-1, 10, 10);
ctx.fillRect(x+5, y-2, 10, 10);
ctx.fillRect(x+5, y-3, 10, 10);
ctx.fillRect(x+5, y-4, 10, 10);
ctx.fillRect(x+5, y-5, 10, 10);
ctx.fillRect(x+5, y-6, 10, 10);
ctx.fillRect(x+5, y-7, 10, 10);
ctx.fillRect(x+9, y-8, 2, 2);
ctx.fillRect(x+9, y-9, 2, 2);
ctx.fillRect(x+9, y-10, 2, 2);
ctx.fillStyle = 'black';
ctx.fillRect(x+35, y, 5, 5);
ctx.fillRect(x-20, y, 5, 5);
}
function enemy1() {
ctx.fillStyle = '#1CE80D';
ctx.fillRect(444, 375, 5, 5);
ctx.fillRect(411, 375, 5, 5);
ctx.fillRect(416, 380, 5, 5);
ctx.fillRect(439, 380, 5, 5);
ctx.fillRect(410, 385, 40, 5);
ctx.fillRect(405, 390, 50, 5);
ctx.fillRect(400, 395, 60, 5);
ctx.fillRect(400, 400, 60, 5);
ctx.fillRect(400, 405, 5, 5);
ctx.fillRect(455, 405, 5, 5);
ctx.fillRect(410, 405, 40, 5);
ctx.fillStyle = '#001119';
ctx.fillRect(415, 405, 30, 5);
ctx.fillStyle = '#1CE80D';
ctx.fillRect(415, 410, 30, 5);
ctx.fillStyle = '#001119';
ctx.fillRect(440, 390, 5, 5);
ctx.fillRect(414, 390, 5, 5);
ctx.fillRect(428, 410, 4, 5);
}
function draw() {
ctx.fillStyle = '#001119';
let background = ctx.fillRect(0, 0, sWidth, sHeight);
player();
ctx.fillStyle = '#EAEEB7';
let wall1 = ctx.fillRect(0, 0, 10, sHeight);
let wall2 = ctx.fillRect(0, 0, sHeight, 10);
let wall3 = ctx.fillRect(0, sHeight - 10, sWidth, 10);
let wall4 = ctx.fillRect(sWidth - 10, 0, 10, sHeight);
}
function gravityForce() {
y += gravity;
}
function jumpAct() {
if(jump == true) {
y -= jumpForce;
} else if(jump == false) {
gravityForce();
}
}
function bulletDraw() {
let bulletX = x;
ctx.fillStyle = '#1CE80D';
ctx.fillRect(bulletX + 9, bulletY, 1, 8);
}
function bulletPos() {
bulletY -= bulletSpeed;
}
function attack() {
if(shot == true) {
for(let i = screen.height; i > 0; i--) {
bulletDraw();
bulletPos();
}
console.log('shooting');
} else if(shot == false) {
bulletY = 880;
}
}
function gameLoop() {
ctx.clearRect(0, 0, screen.width, screen.height);
draw();
move();
gravityForce();
attack();
enemy1();
bulletPos();
requestAnimationFrame(gameLoop);
if(x > screen.width - size - 30) {
x = 30
} else if(x < 30) {
x = screen.width - 50;
}
if(y > screen.height - size - 10) {
y -= (size - 10);
} else if(y < 0) {
y += size;
}
}
////////////////////////////////////////////////
requestAnimationFrame(gameLoop);
I think you have to manage both timer interval and canvas redraw function. I don't thing it is a good idea to redraw the entire canvas in each interval, instead you can redraw only the required canvas area. I have modified your code with setTimeout() function without redraw the entire canvas. You can see the complete code in this fiddler path https://jsfiddle.net/SyamKumarD/knyt7shf/18/
Some of the key code you need to check
1. setTimeout() method
2. hitTarget() method and its instantiation
3. Key down and up events
Hope this will helps

2D Platform shooter Canvas game | Creating the shooting function

So I'm making this pretty basic game I would say for a school project. I have all the basic controllers working, jumping, navigating left and right, but I'm struggling to find a way to make the character be able to shoot. I would also like to make it so it's like a break between each shoot, like a bolt action. The collision part shouldn't be a problem, so no need for help there.
(function() {
var requestAnimationFrame =
window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 640,
height = 480,
player = {
x: width / 2,
y: height - 140,
width: 35,
height: 90,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false
},
keys = [],
friction = 0.8,
gravity = 0.3;
var hovedkarakterBilde = new Image();
hovedkarakterBilde.src = "mc1.png";
var boxes = [];
// dimensions
boxes.push({
// venstre vegg
x: 0,
y: 0,
width: 10,
height: height
});
boxes.push({
// gulv
x: 0,
y: height - 68,
width: width,
height: 1
});
boxes.push({
x: 120,
y: 250,
width: 80,
height: 80
});
boxes.push({
x: 170,
y: 275,
width: 80,
height: 80
});
boxes.push({
x: 220,
y: 325,
width: 80,
height: 80
});
boxes.push({
x: 270,
y: 225,
width: 40,
height: 40
});
canvas.width = width;
canvas.height = height;
function update() {
// check keys
if (keys[38]) {
// up arrow or space
if (!player.jumping && player.grounded) {
player.jumping = true;
player.grounded = false;
player.velY = -player.speed * 2;
}
}
if (keys[39]) {
// right arrow
if (player.velX < player.speed) {
player.velX++;
}
}
if (keys[37]) {
// left arrow
if (player.velX > -player.speed) {
player.velX--;
}
}
player.velX *= friction;
player.velY += gravity;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.beginPath();
player.grounded = false;
for (var i = 0; i < boxes.length; i++) {
ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
var dir = colCheck(player, boxes[i]);
if (dir === "l" || dir === "r") {
player.velX = 0;
player.jumping = false;
} else if (dir === "b") {
player.grounded = true;
player.jumping = false;
} else if (dir === "t") {
player.velY *= -1;
}
}
if (player.grounded) {
player.velY = 0;
}
player.x += player.velX;
player.y += player.velY;
ctx.fill();
ctx.drawImage(
hovedkarakterBilde,
player.x,
player.y,
player.width,
player.height
);
requestAnimationFrame(update);
}
function colCheck(shapeA, shapeB) {
// get the vectors to check against
var vX = shapeA.x + shapeA.width / 2 - (shapeB.x + shapeB.width / 2),
vY = shapeA.y + shapeA.height / 2 - (shapeB.y + shapeB.height / 2),
// add the half widths and half heights of the objects
hWidths = shapeA.width / 2 + shapeB.width / 2,
hHeights = shapeA.height / 2 + shapeB.height / 2,
colDir = null;
// if the x and y vector are less than the half width or half height, they
we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
// figures out on which side we are colliding (top, bottom, left, or right)
var oX = hWidths - Math.abs(vX),
oY = hHeights - Math.abs(vY);
if (oX >= oY) {
if (vY > 0) {
colDir = "t";
shapeA.y += oY;
} else {
colDir = "b";
shapeA.y -= oY;
}
} else {
if (vX > 0) {
colDir = "l";
shapeA.x += oX;
} else {
colDir = "r";
shapeA.x -= oX;
}
}
}
return colDir;
}
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
window.addEventListener("load", function() {
update();
});
HTML:
</head>
<body>
<canvas id="canvas" style="background: url('bakgrunn1.png')"></canvas>
</body>
<script src="spillv2.js"></script>
First thing you have to consider is if the bullet is hit-scan or projectile. Hit-scan means when the bullet is shot, the bullet instantly hits the target. This can be done by using a ray-cast to check if it hits an object. Projectile based bullets are when the user points in a direction, the bullet actually "moves". This can be implemented by adding an array of "bullets" to the player. So when the player clicks, a bullet object is added the array. This bullet object will be drawn on it's own in the draw loop and will move from the user to the direction it's pointed at.
Adding a delay is simple, you can have a "cooldown" variable that is a counter that lasts for n milliseconds. When the user fires, the counter is set to n and starts to count down to 0. When it reaches 0, you are able to fire again.
Well, you could make a shoot(e) function, which will be called when user presses (keydown) space for example and then make a new array, lets say ammo[]. Then, inside shoot() you will do something like:
const ammo = [];
let shooting = false;
function shoot(e) {
e = e || event;
const key = e.keyCode;
if(shooting) return; // This will prevent from shooting more bullets while holding space
// So you'd need to press space for each time you want to shoot.
if(key == 32) { // Key code 32 is SPACE
shooting = true;
// You get the coordinates from your player, from which the bullet will shoot
ammo.push({
x: player.x,
y: player.y + (player.height / 2)
// Player.height / 2 is basically setting the ammo at the middle of the character
});
}
}
And then, I presume you do all the updates in the update() function (yea, logically :D), you'll do something like:
function update() {
// Insert it somewhere
for(let i = 0; i < ammo.length; i++) {
// The "theBullet" part refers to either your image for the bullet
ctx.drawImage(theBullet, ammo[i].x, ammo[i].y;
ammo[i].x++ // Or however fast you'd like it to go.
}
}
Hope its somewhat clear, I am working myself on a spaceshooter type of game, almost finished, so shared some of my code here :) Not implying that its the best, but it does the work :)

Grid system needed to fix a position issue on canvas?

I am trying to create a simple snake game. My problem is, most of the times when the snake meets the food, the position of the snake is not how it should be.
For a better understanding, please look at this screenshot where the snake (white) meets the food (green):
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
x = 0,
y = 0,
speed = 3;
x_move = speed,
y_move = 0,
food_position_x = Math.floor(Math.random() * canvas.width) - 20;
food_position_y = Math.floor(Math.random() * canvas.height) - 20;
// Drawing
function draw() {
requestAnimationFrame(function() {
draw();
});
// Draw the snake
ctx.beginPath();
ctx.rect(x, y, 20, 20);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = '#ffffff';
ctx.fill();
ctx.closePath();
// Draw the food
ctx.beginPath();
ctx.rect(food_position_x, food_position_y, 20, 20);
ctx.fillStyle = "lightgreen";
ctx.fill();
ctx.closePath();
// Increase the value of x and y in order to animate
x = x + x_move;
y = y + y_move;
}
draw();
// Key Pressing
document.addEventListener('keydown', function(event) {
switch(event.keyCode) {
case 40: // Moving down
if (x_move != 0 && y_move != -1) {
x_move = 0;
y_move = speed;
}
break;
case 39: // Moving right
if (x_move != -1 && y_move != 0) {
x_move = speed;
y_move = 0;
}
break;
case 38: // Moving top
if (x_move != 0 && y_move != 1) {
x_move = 0;
y_move = -speed;
}
break;
case 37: // Moving left
if (x_move != 1 && y_move != 0) {
x_move = -speed;
y_move = 0;
}
break;
}
});
canvas { background-color:red }
<canvas id="canvas" width="600" height="400"></canvas>
So it seems like I would need a simple grid system but how would I go ahead on this to fix this issue?
I can't see the code for your collision. But I think you have a mistake in your origin. The origin of your squares is not in the middle, it is on the top left corner.

Categories

Resources