I really wanna know how to make 2d camera movement in html and javascript, so i wrote this code which is just a character and a block so i can test if the camera movement is working. This is my code:
var c = document.getElementById("screen");
var ctx = c.getContext("2d");
var rightPressed;
var leftPressed;
var x = (c.width - 75) / 2;
var speed = 10;
function block() {
ctx.fillStyle = "#fff";
ctx.fillRect(390, 225, 80, 25);
}
function character() {
ctx.fillStyle = "#00f"
ctx.fillRect(x, 250, 50, 50);
}
function keyUpHandler(event) {
if (event.keyCode == 37) {
leftPressed = false;
} else if (event.keyCode == 39) {
rightPressed = false;
}
}
function keyDownHandler(event) {
if (event.keyCode == 37) {
leftPressed = true;
} else if (event.keyCode == 39) {
rightPressed = true;
}
}
document.addEventListener("keyup", keyUpHandler, false);
document.addEventListener("keydown", keyDownHandler, false);
function draw() {
ctx.clearRect(0, 0, c.width, c.height);
block();
character();
if (rightPressed && (x + 50) < c.width) {
x += speed;
} else if (leftPressed && x > 0) {
x -= speed;
}
requestAnimationFrame(draw);
}
requestAnimationFrame(draw);
#screen {
display: block;
margin: auto;
background-color: #0f0;
border: 2px solid black;
}
#headline {
text-align: center;
}
<h1 id="headline">2d Camera movement</h1>
<canvas id="screen" width="500" height="300"></canvas>
Is there anyone who knows how to do this then please tell me, also it would be nice if you could put it into this code :)
I created two classes, a Game and a Ball. The balls will move when a player presses the left or right key.
The balls know their own position and speed, the game does not care.
Just tell the ball to update according to the game's current state.
I adapted a good portion of code from here:
"Quick Tip: How to Make a Game Loop in JavaScript"
I added ES6 classes, vector support and dynamic game element support.
Demo
const canvasTxt = window.canvasTxt.default;
const KeyCodeMap = {
37: 'left',
38: 'up',
39: 'right',
40: 'down',
65: 'left',
68: 'right',
83: 'down',
87: 'up'
};
Object.assign(canvasTxt, {
align: 'left',
vAlign: 'top',
font: 'monospace',
fontSize: 24
});
const main = () => {
Game.DEBUG = true; // Enable global DEBUG mode.
const ctx = document.getElementById('screen').getContext('2d');
const game = new Game(ctx);
game.gameElements.push(...[
new Ball({
speed: new Victor(10, 0),
position: new Victor(game.getWidth() / 2, game.getHeight() / 2),
color: 'red',
size: 20
}),
new Ball({
speed: new Victor(20, 0),
position: new Victor(game.getWidth() / 2, game.getHeight() / 4),
color: 'green',
size: 30
}),
new Ball({
speed: new Victor(20, 50),
position: new Victor(100, 140),
color: 'cyan',
size: 25
}),
]);
game.redraw();
};
class Ball {
constructor(options) {
let opts = Object.assign({}, Ball.defaultOptions, options);
this.position = opts.position;
this.speed = opts.speed;
this.size = opts.size;
this.color = opts.color;
}
update(container, state) {
if (state.pressedKeys.left && !state.pressedKeys.right) {
this.position.subtract(this.speed);
}
if (state.pressedKeys.right && !state.pressedKeys.left) {
this.position.add(this.speed);
}
this.checkBounds(container); // Make sure object is in-bounds...
}
checkBounds(container) {
if (this.position.x > container.width) {
this.position.x = 0;
}
if (this.position.x < 0) {
this.position.x = container.width;
}
if (this.position.y > container.height) {
this.position.y = 0;
}
if (this.position.y < 0) {
this.position.y = container.height;
}
}
draw(ctx) {
ctx.save();
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.size / 2, 0, 2 * Math.PI, false);
ctx.fillStyle = this.color;
ctx.fill();
//ctx.lineWidth = 1;
//ctx.strokeStyle = '#000000';
ctx.stroke();
ctx.restore();
}
}
Ball.defaultOptions = {
position: new Victor(0, 0),
speed: new Victor(0, 0),
size: 1,
color: '#FFFFFF'
};
class Game {
constructor(ctx) {
this.ctx = ctx;
this.gameElements = [];
this.resize();
this.state = {
pressedKeys: {} // Capture key pressed
};
this.__lastRender = 0;
this.__animationId = null;
window.onresize = (e) => this.resize(e);
document.addEventListener('click', (e) => this.clickHandler(e), false);
document.addEventListener('keyup', (e) => this.keyUpHandler(e), false);
document.addEventListener('keydown', (e) => this.keyDownHandler(e), false);
}
clickHandler(e) {
this.isRunning() ? this.pause() : this.run(); // Pause, if running
}
keyUpHandler(event) {
let key = KeyCodeMap[event.keyCode];
delete this.state.pressedKeys[key];
}
keyDownHandler(event) {
let key = KeyCodeMap[event.keyCode];
if (key) this.state.pressedKeys[key] = true;
}
getWidth() {
return this.ctx.canvas.width;
}
getHeight() {
return this.ctx.canvas.height;
}
resize(event) {
this.ctx.canvas.width = window.innerWidth * 2
this.ctx.canvas.height = window.innerHeight * 2
}
update(progress) {
this.gameElements.forEach(gameElement => gameElement.update(this.ctx.canvas, this.state));
}
redraw() {
this.ctx.clearRect(0, 0, this.getWidth(), this.getHeight());
this.gameElements.forEach(gameElement => gameElement.draw(this.ctx));
if (Game.DEBUG) {
this.__renderDebugText(this.ctx);
}
}
/* #private */ __renderDebugText(ctx) {
ctx.save();
let text = 'DEBUG OUTPUT:\n\n' + JSON.stringify(Object.assign({
running: this.isRunning()
}, this.state), null, 2);
let offset = { x: 16, y: 16 };
let bounds = { width: 280, height: 320 };
ctx.fillStyle = 'rgba(16, 16, 16, 0.8)';
ctx.fillRect(offset.x, offset.y, bounds.width, bounds.height);
ctx.lineWidth = 1;
ctx.strokeStyle = '#333';
ctx.strokeRect(offset.x, offset.y, bounds.width, bounds.height);
ctx.fillStyle = '#FFF';
canvasTxt.drawText(ctx, text, offset.x + 4, offset.y + 4, bounds.width, bounds.height);
ctx.restore();
}
loop(timestamp) {
this.update(timestamp - this.__lastRender);
this.redraw();
this.__lastRender = timestamp;
this.__animationId = window.requestAnimationFrame((ts) => this.loop(ts));
}
isRunning() {
return this.__animationId != null;
}
run() {
this.__animationId = window.requestAnimationFrame((ts) => this.loop(ts));
}
pause() {
cancelAnimationFrame(this.__animationId);
this.__animationId = null;
this.redraw();
}
}
Game.DEBUG = false; // Default is off
main();
html,
body {
margin: 0;
padding: 0;
}
canvas {
background: #000;
height: 100%;
width: 100%;
display: block
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.min.js"></script>
<script src="https://unpkg.com/canvas-txt#2.0.6/build/index.js"></script>
<canvas id="screen" />
Related
I am relatively new to JavaScript, and am looking to create a platformer game for a class project. I have tried multiple ways to make a player rectangle collide with an obstacle rectangle but none have worked the way I intended. This method that I wrote myself is not functioning at all, and I have no clue why.
var ctx = myCanvas.getContext("2d");
var fps = 50
var level = 1
var gravity = 0.5
var player = {
x: 0,
y: 0,
x_v: 0,
y_v: 0,
width: 20,
height: 20,
speed: 3,
jump: 10,
color: "blue"
}
const obstacle = {
x: 0,
y: 550,
width: 600,
height: 100,
color: "black"
}
function MyKeyUpHandler(MyEvent) {
if (MyEvent.keyCode == 37 || MyEvent.keyCode == 39) {
player.x_v = 0
}; // not left or right
if (MyEvent.keyCode == 38 || MyEvent.keyCode == 40) {
player.y_v = 0
}; // not up or down
}
function MyKeyDownHandler(MyEvent) {
if (MyEvent.keyCode == 37) {
player.x_v = -player.speed
}; // left
if (MyEvent.keyCode == 38) {
player.y_v = -player.jump
}; // up
if (MyEvent.keyCode == 39) {
player.x_v = player.speed
}; // right
MyEvent.preventDefault();
}
function renderplayer() {
player.y_v = player.y_v + gravity
player.x = player.x + player.x_v
player.y = player.y + player.y_v
ctx.fillStyle = player.color
ctx.fillRect(player.x, player.y, player.width, player.height)
}
function renderobstacle() {
ctx.fillStyle = obstacle.color
ctx.fillRect(obstacle.x, obstacle.y, obstacle.width, obstacle.height)
}
function collision() {
if (player.y == obstacle.y - player.height) {
player.y_v = 0
}
}
function frameyshit() {
ctx.clearRect(0, 0, 600, 600)
renderplayer();
renderobstacle();
collision();
if (player.y >= 600) {
player.y = 1
player.x = 1
player.y_v = 0
}
}
setInterval(frameyshit, 1000 / fps)
addEventListener("keydown", MyKeyDownHandler)
addEventListener("keyup", MyKeyUpHandler)
<canvas id=myCanvas width=600 height=600 style="background-color: transparent;"> </canvas>
I have the code below. What I want to do is instead of a small square to move around the canvas, I want to use an image instead. In my snippet, I tried to use the drawImage function so that I could display the image I want to use. I was able to display the image but when I try to use the WASD keys, it does not move. Instead, the black square is still the one that is being controlled by the keys. Is there a way on how I can control the image using WASD keys and not the black square?
var canvas;
var context;
var ctx;
var xaxis = 10;
var yaxis = 10;
var obstacle = [];
window.onload = function() {
canvas = document.getElementById("textbox");
context = canvas.getContext("2d");
ctx = canvas.getContext("2d");
player.img.src = 'https://64.media.tumblr.com/tumblr_lkl5spPdno1qfamg6.gif'; //
canvas.width = 400;
canvas.height = 400;
drawCanv();
}
/* obstacle object */
var object = {
height: 50,
width: 50,
x: 100,
y: 100,
}
/* player object */
var player = {
height: 10,
width: 10,
img: new Image() //
};
function drawCanv() {
/* canvas */
context.beginPath();
context.fillStyle = "#ffffff";
context.fillRect(0, 0, canvas.width, canvas.height);
/* player */
context.beginPath();
context.fillStyle = "black";
context.drawImage(player.img, player.height, player.width, 10, 10); //
context.fillRect(xaxis, yaxis, player.width, player.height);
/* obstacle object */
var ndx = obstacle.push({
x: object.x,
y: object.y,
width: object.width,
height: object.height,
}) - 1;
ctx.beginPath();
ctx.fillStyle = "red";
ctx.fillRect(obstacle[ndx].x, obstacle[ndx].y, obstacle[ndx].width, obstacle[ndx].height);
}
function hitObsta(player, array) {
for (var value of array) {
if ((player.x + player.width > value.x && player.x < value.x + value.width)
&& (player.y + player.height > value.y && player.y < value.y + value.height)) {
return true;
}
}
return false;
}
function onkeydown(e) {
/* Going right*/
if (e.keyCode == 68 && xaxis + 10 < canvas.width) {
xaxis++;
var updatedCoords = (Object.assign({
x: xaxis,
y: yaxis,
}, player));
if (hitObsta(updatedCoords, obstacle)) {
xaxis--;
}
}
/* Going left*/
else if (e.keyCode == 65 && xaxis > 0) {
xaxis--;
var updatedCoords = (Object.assign({
x: xaxis,
y: yaxis,
}, player));
if (hitObsta(updatedCoords, obstacle)) {
xaxis++;
}
}
/* Going up*/
else if (e.keyCode == 87 && yaxis > 0) {
yaxis--;
var updatedCoords = (Object.assign({
x: xaxis,
y: yaxis,
}, player));
if (hitObsta(updatedCoords, obstacle)) {
yaxis++;
}
}
/* Going down*/
else if (e.keyCode == 83 && yaxis + 10 < canvas.height) {
yaxis++;
var updatedCoords = (Object.assign({
x: xaxis,
y: yaxis,
}, player));
if (hitObsta(updatedCoords, obstacle)) {
yaxis--;
}
}
//render();
drawCanv();
}
function render()
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(player.img, player.height, player.width, 10, 10); //
}
window.addEventListener("keydown", onkeydown);
<html>
<head>
<title>Canvas</title>
<style>
</style>
</head>
<body>
<canvas id="textbox" style="border: 1px solid black"></canvas>
<script src="js/app.js"></script>
</body>
</html>
You don't need the black square at all. You can just do something like this:
const image = new Image(10, 10)
image.src = 'https://64.media.tumblr.com/tumblr_lkl5spPdno1qfamg6.gif';
/* player object */
var player = {
height: 10,
width: 10,
img: image
};
function drawCanv() {
// ...
/* player */
context.beginPath();
context.drawImage(player.img, xaxis, yaxis, 10, 10); //
// ...
}
This question already has answers here:
How do I rotate a single object on an html 5 canvas?
(8 answers)
Closed 2 years ago.
I want to simulate car rotation and movement in the new direction in a game I am designing.
According to the following answer, within the HTML5 canvas element you cannot rotate individual elements.
The movement itself is happening in this function, I expect the vehicle to move but the entire canvas moves (try pressing left and right). I couldn't figure out how to rotate the car.
Game._rotate = function(dirx, direction) {
this.ctx.translate(200,200);
}
According to this tutorial, I can only rotate the car itself by rotating the canvas. I'd like the rotation and movement to emulate the following: https://oseiskar.github.io/js-car/.
The code itself here: https://plnkr.co/edit/K5X8fMhUlRLhdeki.
You need to render the car relative to ITS position. Also, you can do the rotation inside its RENDER.
The changes below will handle rotation for the car, but you have bigger problems. I would take time and invest in learning how vectors work. The position, speed and acceleration should all be 2D vectors that provide vector math like adding and multiplication.
Also, provide an initial angle to your car so it is initially rendered the right way. It also appears that your acceleration and deceleration are mixed up.
function Car(map, x, y) {
this.map = map;
this.x = x;
this.y = y;
this.angle = 0; // IMPORTANT
this.width = map.tsize;
this.height = map.tsize;
this.image = Loader.getImage('car');
}
Car.speed = 0;
Car.acceleration = 0;
Car.friction = 5;
Car.moveAngle = 0;
Car.maxSpeed = 500;
Car.forward = 'FORWARD';
Car.backward = 'BACKWARD';
Car.left = 'LEFT';
Car.right = 'RIGHT';
// Render relative to car...
Car.prototype.render = function(ctx) {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(this.image, -this.width / 2, -this.height / 2);
ctx.restore();
};
Game.update = function (delta) {
var dirx = 0;
var diry = 0;
if (Keyboard.isDown(Keyboard.LEFT)) {
this._rotate(dirx, Car.left)
}
else if (Keyboard.isDown(Keyboard.RIGHT)) {
this._rotate(dirx, Car.right)
}
else if (Keyboard.isDown(Keyboard.UP)) {
this._rotate(dirx, Car.up)
diry = accelerate(diry, Car.forward);
}
else if (Keyboard.isDown(Keyboard.DOWN)) {
this._rotate(dirx, Car.down)
diry = accelerate(diry, Car.backward);
}
else {
decelerate();
}
this.car.move(delta, dirx, diry);
this.camera.update();
};
Game._rotate = function(dirx, direction) {
let angleInDegrees = 0;
switch (direction) {
case 'UP':
angleInDegrees = 0;
break;
case 'RIGHT':
angleInDegrees = 90;
break;
case 'DOWN':
angleInDegrees = 180;
break;
case 'LEFT':
angleInDegrees = 270;
break;
}
this.car.angle = angleInDegrees * (Math.PI / 180);
}
Game.render = function () {
// draw map background layer
this._drawLayer(0);
this.car.render(this.ctx);
// draw map top layer
this._drawLayer(1);
};
Vectors
Here is an example using vectors.
loadImage('https://i.stack.imgur.com/JY7ai.png')
.then(function(img) {
main(img);
})
function main(img) {
let game = new Game({
canvas: document.querySelector('#viewport')
});
let car = new Car({
img: img,
imgRadiansOffset : -Math.PI / 2,
position: new Victor(game.canvas.width, game.canvas.height).divide(new Victor(2, 2)),
velocity: new Victor(0, -1),
showBorder: true
});
game.addLayer(car);
game.start();
}
class Game {
constructor(options) {
Object.assign(this, Game.defaultOptions, options);
if (this.canvas != null) {
Object.assign(this, {
width: this.canvas.width,
height: this.canvas.height
});
this.addListeners();
}
}
addLayer(layer) {
this.layers.push(layer);
layer.parent = this;
}
start() {
this.id = setInterval(() => {
this.render();
}, 1000 / this.rate); // frames per second
}
render() {
let ctx = this.canvas.getContext('2d');
ctx.clearRect(0, 0, this.width, this.height);
this.layers.forEach(layer => layer.render(ctx));
}
addListeners() {
if (this.canvas != null) {
window.addEventListener('keydown', (e) => {
this.handleKeyDown(e.keyCode);
});
window.addEventListener('keyup', (e) => {
this.handleKeyUp(e.keyCode);
});
}
}
handleKeyDown(keyCode) {
this.layers.forEach(layer => {
layer.update(keyCode !== this.lastKeyCode ? keyCode : null);
});
this.lastKeyCode = keyCode;
}
handleKeyUp(keyCode) {
this.layers.forEach(layer => {
layer.update(this.lastKeyCode); // calls reset...
});
}
}
Game.defaultOptions = {
id: null,
rate: 30,
layers: [],
canvas: null,
width: 0,
height: 0
};
class Car {
constructor(options) {
Object.assign(this, Car.defaultOptions, options);
if (this.img != null) {
Object.assign(this, {
width: this.img.width,
height: this.img.height
});
}
}
render(ctx) {
ctx.save();
ctx.translate(this.position.x, this.position.y);
ctx.rotate(this.velocity.angle() - this.imgRadiansOffset);
ctx.drawImage(this.img, -this.width / 2, -this.height / 2, this.width, this.height);
if (this.showBorder) {
ctx.strokeStyle = '#C00';
ctx.setLineDash([4, 8]);
ctx.lineWidth = 1;
ctx.beginPath();
ctx.rect(-this.width / 2, -this.height / 2, this.width, this.height);
ctx.stroke();
}
ctx.restore();
}
update(keyCode) {
if (keyCode != null) this.changeDirection(keyCode);
this.position.add(this.velocity.add(this.acceleration));
this.detectCollision();
}
detectCollision() {
let xMin = this.width / 2, xMax = this.parent.width - xMin;
let yMin = this.height / 2, yMax = this.parent.height - yMin;
if (this.position.x < xMin) this.position.x = xMin;
if (this.position.x > xMax) this.position.x = xMax;
if (this.position.y < yMin) this.position.y = yMin;
if (this.position.y > yMax) this.position.y = yMax;
}
changeDirection(keyCode) {
switch (keyCode) {
case 37:
this.reset(new Victor(-1, 0)); // LEFT
break;
case 38:
this.reset(new Victor(0, -1)); // UP
break;
case 39:
this.reset(new Victor(1, 0)); // RIGHT
break;
case 40:
this.reset(new Victor(0, 1)); // DOWN
break;
}
}
reset(dirVect) {
this.velocity = new Victor(this.speedFactor, this.speedFactor).multiply(dirVect);
this.acceleration = new Victor(this.accelFactor, this.accelFactor).multiply(dirVect);
}
}
Car.defaultOptions = {
position: new Victor(0, 0),
width: 0,
height: 0,
img: null,
imgRadiansOffset: 0,
velocity: new Victor(0, 0),
acceleration: new Victor(0, 0),
showBorder: false,
speedFactor: 3, // Velocity scalar
accelFactor: 1 // Acceleration scalar
};
function loadImage(url) {
return new Promise(function(resolve, reject) {
var img = new Image;
img.onload = function() {
resolve(this)
};
img.onerror = img.onabort = function() {
reject("Error loading image")
};
img.src = url;
})
}
#viewport {
border: thin solid grey;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/victor/1.1.0/victor.min.js"></script>
<canvas id="viewport" width="400" height="160"></canvas>
So i have a simple html5 canvas render loop and I'm handling keydown and keyup.
A rectangle drawn on the screen can move left,right, up and down.
The problem is when you move left and right in succession, the rectangle seems to stop for a very long time, like it's being interrupted and I just want it to have a more smooth transition towards the opposite direction.
Even just changing any direction causes the rectangle to stop.
here's the Jsfiddle: https://jsfiddle.net/NeuroTypicalCure/sq6czebr/39/
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
key: null,
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
direction: null,
speed: 5
}
// start
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(input.key === 'w'){
player.direction = input.directions.up;
}
if(input.key === 's'){
player.direction = input.directions.down;
}
if(input.key === 'a'){
player.direction = input.directions.left;
}
if(input.key === 'd'){
player.direction = input.directions.right;
}
// keyup -> speed 0 // else -> speed 5
if(input.key === null){
player.speed = 0;
}else{
player.speed = 5;
}
player.x += Math.cos(player.direction*Math.PI)*player.speed;
player.y += Math.sin(player.direction*Math.PI)*player.speed;
ctx.fillRect(player.x,player.y,50,50);
requestAnimationFrame(draw);
}
function handleKeyDown(e){
e.preventDefault();
input.key = e.key
}
function handleKeyUp(e){
e.preventDefault();
input.key = null;
}
window.addEventListener('keydown',handleKeyDown);
window.addEventListener('keyup',handleKeyUp);
Your problem lies with the fact that you can hold multiple keys at the same time, your logic should reflect that. i.e.:
https://jsfiddle.net/danfoord1/cr84xh2n/19/
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
keys: [],
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
directions: [],
speed: 5
}
const directions = {
'w': 1.5,
's': 0.5,
'a': 1,
'd': 2
};
// start
draw();
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// keyup -> speed 0 // else -> speed 5
if (input.keys.length === 0) {
player.speed = 0;
} else {
player.speed = 5;
}
player.directions = input.keys.map(k => directions[k]);
player.directions.forEach(d => {
player.x += Math.cos(d * Math.PI) * player.speed;
player.y += Math.sin(d * Math.PI) * player.speed;
});
ctx.fillRect(player.x, player.y, 50, 50);
requestAnimationFrame(draw);
}
function handleKeyDown(e) {
e.preventDefault();
if (input.keys.indexOf(e.key) === -1) {
input.keys.push(e.key);
}
}
function handleKeyUp(e) {
e.preventDefault();
if (input.keys.indexOf(e.key) > -1) {
input.keys.splice(input.keys.indexOf(e.key), 1);
}
}
window.addEventListener('keydown', handleKeyDown);
window.addEventListener('keyup', handleKeyUp);
The problem with your code lies in your handling of keyup events:
function handleKeyUp(e){
e.preventDefault();
input.key = null;
}
You're basically reseting input.key whenever a key is released, no matter if it's a different key than the one that initiated the move. So if you press two keys and then release one, it will reset input.key (until your computer sent another keydown event - if you're still holding down the key). This can be fixed with a simple check if the keyup event belongs to the current input.key.
function handleKeyUp(e){
e.preventDefault();
if (e.key === input.key) input.key = null;
}
Here's a code snippet:
let canvas = document.getElementById('c');
let ctx = canvas.getContext('2d');
canvas.width = 800;
canvas.height = 600;
let input = {
key: null,
directions: {
up: 1.5,
down: 0.5,
left: 1,
right: 2
}
}
let player = {
x: 0,
y: 0,
direction: null,
speed: 5
}
// start
draw();
function draw(){
ctx.clearRect(0,0,canvas.width,canvas.height);
if(input.key === 'w'){
player.direction = input.directions.up;
}
if(input.key === 's'){
player.direction = input.directions.down;
}
if(input.key === 'a'){
player.direction = input.directions.left;
}
if(input.key === 'd'){
player.direction = input.directions.right;
}
// keyup -> speed 0 // else -> speed 5
if(input.key === null){
player.speed = 0;
}else{
player.speed = 5;
}
player.x += Math.cos(player.direction*Math.PI)*player.speed;
player.y += Math.sin(player.direction*Math.PI)*player.speed;
ctx.fillRect(player.x,player.y,50,50);
requestAnimationFrame(draw);
}
function handleKeyDown(e){
e.preventDefault();
input.key = e.key
}
function handleKeyUp(e){
e.preventDefault();
if (e.key === input.key) input.key = null;
}
window.addEventListener('keydown',handleKeyDown);
window.addEventListener('keyup',handleKeyUp);
canvas{
border: 1px solid aqua;
}
<!DOCTYPE html>
<html>
<body>
<canvas id="c"></canvas>
</body>
</html>
I want change the middle point of canvas quadratic curve which is far away from the line while dragging middle point. On dragging i want to stick with the link as now its increasing the distance of the middle point.http://jsfiddle.net/ashishbhatt/yqgak7eq/1/
http://s25.postimg.org/hegxhlgrj/123123.jpg
Please check the above reference image for the same.
Code :
(function() {
var canvas, ctx, code, point, style, drag = null, dPoint;
// define initial points
function Init(quadratic) {
point = {
p1: { x:0, y:100 },
p2: { x:200, y:100 }
};
if (quadratic) {
point.cp1 = { x: 100, y: 50 };
}
else {
point.cp1 = { x: 100, y: 100 };
point.cp2 = { x: 100, y: 100 };
}
// default styles
style = {
curve: { width: 2, color: "#333" },
cpline: { width: 1, color: "#C00" },
point: { radius: 6, width: 1, color: "#900", fill: "rgba(200,200,200,0.5)", arc1: 0, arc2: 2 * Math.PI }
}
// line style defaults
ctx.lineCap = "round";
ctx.lineJoin = "round";
// event handlers
canvas.onmousedown = DragStart;
canvas.onmousemove = Dragging;
canvas.onmouseup = canvas.onmouseout = DragEnd;
DrawCanvas();
}
// draw canvas
function DrawCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// control lines
ctx.lineWidth = style.cpline.width;
ctx.strokeStyle = style.cpline.color;
ctx.beginPath();
//ctx.moveTo(point.p1.x, point.p1.y);
//ctx.lineTo(point.cp1.x, point.cp1.y);
if (point.cp2) {
//ctx.moveTo(point.p2.x, point.p2.y);
//ctx.lineTo(point.cp2.x, point.cp2.y);
}
else {
//ctx.lineTo(point.p2.x, point.p2.y);
}
ctx.stroke();
// curve
ctx.lineWidth = style.curve.width;
ctx.strokeStyle = style.curve.color;
ctx.beginPath();
ctx.moveTo(point.p1.x, point.p1.y);
if (point.cp2) {
//ctx.bezierCurveTo(point.cp1.x, point.cp1.y, point.cp2.x, point.cp2.y, point.p2.x, point.p2.y);
}
else {
ctx.quadraticCurveTo(point.cp1.x, point.cp1.y, point.p2.x, point.p2.y);
}
ctx.stroke();
// control points
for (var p in point) {
ctx.lineWidth = style.point.width;
ctx.strokeStyle = style.point.color;
ctx.fillStyle = style.point.fill;
ctx.beginPath();
ctx.arc(point[p].x, point[p].y, style.point.radius, style.point.arc1, style.point.arc2, true);
ctx.fill();
ctx.stroke();
}
ShowCode();
}
// show canvas code
function ShowCode() {
var myCounter = 0;
if(point.cp1.y < 100){
myCounter = point.cp1.y-100;
}else if(point.cp1.y > 100){
myCounter = point.cp1.y-100;
}
if (code) {
code.firstChild.nodeValue = myCounter
}
}
// start dragging
function DragStart(e) {
e = MousePos(e);
var dx, dy;
for (var p in point) {
//console.log(p)
//dx = point[p].x - e.x;
if(p == 'cp1'){
dy = point[p].y - e.y;
if ((dy * dy) < style.point.radius * style.point.radius) {
drag = p;
dPoint = e;
canvas.style.cursor = "move";
return;
}
}
}
}
// dragging
function Dragging(e) {
if (drag) {
e = MousePos(e);
//point[drag].x += e.x - dPoint.x;
point[drag].y += e.y - dPoint.y;
dPoint = e;
DrawCanvas();
}
}
// end dragging
function DragEnd(e) {
drag = null;
canvas.style.cursor = "default";
DrawCanvas();
}
// event parser
function MousePos(event) {
event = (event ? event : window.event);
return {
//x: event.pageX - canvas.offsetLeft,
y: event.pageY - canvas.offsetTop
}
}
// start
canvas = document.getElementById("canvasSettings");
code = document.getElementById("code");
if (canvas.getContext) {
ctx = canvas.getContext("2d");
Init(canvas.className == "quadratic");
}
})();