HTML5 edit text on the canvas - javascript

I'm trying to create something similar to http://www.listhings.com where you can edit the text within the canvas.
I've read the other post HTML5 Canvas Text Edit . But I don't want to edit the text outside of the canvas. I want to edit the text within the canvas.
I'd appreciate if anyone can point me in the right direction.
Thanks

First, Mohsen correctly points out that when you do context.fillText you are actually "painting a picture of letters" on the canvas. It's not like a word processor!
You can capture the key events on the window and then write the keystrokes out to your canvas.
Here is code and a Fiddle: http://jsfiddle.net/m1erickson/7tXd4/
This example ONLY types lowercase a-z (no capitals, spaces, backspaces, etc)
You will probably want to make more enhancements like these:
Adding more keys (A-Z, 0-9, etc).
Respond to command keys like backspace to remove letters from the keyHistory.
Put a cursor so users know where they are on the line as they type (hint: http://www.html5canvastutorials.com/tutorials/html5-canvas-text-metrics/)
If you allow multi-line text, handle the [enterkey] and move to the new line.
Etc
Here's code just to get you started:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
ctx.font="18px Arial";
var keyHistory="";
window.addEventListener("keyup", keyUpHandler, true);
function addletter(letter){
keyHistory+=letter;
ctx.clearRect(0,0,300,300);
ctx.fillText(keyHistory,20,20);
}
function keyUpHandler(event){
var letters="abcdefghijklmnopqrstuvwxyz";
var key=event.keyCode;
if(key>64 && key<91){
var letter=letters.substring(key-64,key-65);
addletter(letter);
}
}
}); // end $(function(){});
</script>
</head>
<body>
<p>First click in the red canvas below</p><br/>
<p>Then type any lowercase letters from a-z</p><br/>
<canvas id="canvas" width=300 height=100></canvas>
</body>
</html>

fillText() do not create an object or text node that you can edit afterwards. It will fill text on canvas, that means it will leave pixels on canvas.
You can use Canvas libraries like http://kineticjs.com/ to have a single layer for that text so you can erase the layer and retype the text in. Kinect allows you to bind values to layers so you can save the text you have in the layer in a value binded to the layer.

Try this solution https://jsfiddle.net/tabvn/zjyoexf1/
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Canvas Input Element</title>
</head>
<body>
<canvas id="draw" width="500" height="500"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("draw");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.beginPath();
function Input(text = "", options = {}){
this.text = text;
this.options = Object.assign({width: 250, height: 40, font: "17px Arial", borderWidth: 1, borderColor: "#ccc", padding: 5}, options);
this.position = {x: 10, y: 10};
this.isFocus = false;
this.focusIndex = text.length;
this.isCommandKey = false;
this.selected = false;
this.render = function(){
ctx.clearRect(this.position.x, this.position.y, this.options.width, this.options.height);
ctx.font = this.options.font;
ctx.lineWidth = this.options.borderWidth;
ctx.strokeStyle = this.options.borderColor;
if(this.isFocus){
ctx.strokeStyle = "#000";
}
ctx.rect(this.position.x, this.position.y, this.options.width, this.options.height);
ctx.stroke();
// write text
var str = "";
for(var i = 0; i < this.text.length; i++){
if(!this.selected && this.isFocus && this.focusIndex === i){
str += "|";
}
str += this.text[i];
}
if(!this.selected && this.isFocus && this.focusIndex === this.text.length){
str += "|";
}
if(this.selected){
var _width = ctx.measureText(this.text).width;
ctx.fillStyle = 'rgba(0,0,0,0.5)';
ctx.fillRect(this.position.x + this.options.padding, this.position.y + this.options.padding, _width, parseInt(this.options.font, 17));
}
ctx.fillStyle = "#000";
ctx.fillText(str, this.position.x + this.options.padding, this.position.y + (this.options.height / 2) + this.options.padding);
}
this.handleOnClick = function(e){
let clientX = e.clientX;
let clientY = e.clientY;
if(clientX <= this.position.x + this.options.width && clientX >= this.position.x && clientY <= this.position.y + this.options.height && clientY >= this.position.y){
if(!this.isFocus){
this.isFocus = true;
this.focusIndex = this.text.length;
this.render();
}
}else{
if(this.isFocus){
this.selected = false;
this.isFocus = false;
this.render();
}
}
}
this.handleOnKeyUp = function(e){
this.isCommandKey = false;
this.render();
}
this.handleOnKeyDown = function(e){
if(e.key === "Meta" || e.key === "Control"){
this.isCommandKey = true;
}
if(this.isFocus){
e.preventDefault();
}
if(this.isCommandKey && e.key === "a"){
this.selected = true;
this.render();
return
}
if(this.isFocus && e.key === "Backspace"){
if(this.selected){
this.focusIndex = 0;
this.text = "";
this.selected = false;
this.render();
}
var str = "";
for(var i =0; i < this.text.length; i++){
if(i !== this.focusIndex - 1){
str += this.text[i];
}
}
this.text = str;
this.focusIndex --;
if(this.focusIndex <0){
this.focusIndex = 0;
}
this.render();
}
if(this.isFocus && e.key === "ArrowLeft"){
this.focusIndex --;
if(this.focusIndex < 0){
this.focusIndex = 0;
}
this.render();
}
if(this.isFocus && e.key === "ArrowRight"){
this.focusIndex ++;
if(this.focusIndex > this.text.length){
this.focusIndex = this.text.length;
}
this.render();
}
if(!this.isCommandKey && this.isFocus && (e.keyCode == 32 || (e.keyCode >= 65))){
this.text += e.key;
this.focusIndex = this.text.length;
this.render();
}
}
}
var input = new Input("I 'm an input");
input.render();
window.addEventListener("click", function(event){
input.handleOnClick(event);
});
window.addEventListener("keydown", function(event){
input.handleOnKeyDown(event);
});
window.addEventListener("keyup", function(event){
input.handleOnKeyUp(event);
});
</script>
</body>
</html>

Related

drag and drop soccer score incrementor Javascript

I haven't been able to correctly build logic. After dropping soccer ball into the goal, the score does not increment. As stated in my JS script code, I attempted to add score++ to scoreDisplay function (in bold).
Thank you for looking at this issue.
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3>Score:<span id="score">0</span></h3>
<button id="start-button">Start/Pause</button>
<p>Drag the ball.</p>
<img src="https://en.js.cx/clipart/soccer-gate.svg" id="gate" class="droppable">
<img src="https://picsum.photos/150/150" id="ball">
<script>
const scoreDisplay = document.querySelector('#score')
let score = 0
let currentDroppable = null;
ball.onmousedown = function(event) {
let shiftX = event.clientX - ball.getBoundingClientRect().left;
let shiftY = event.clientY - ball.getBoundingClientRect().top;
ball.style.position = 'absolute';
ball.style.zIndex = 1000;
document.body.append(ball);
moveAt(event.pageX, event.pageY);
function moveAt(pageX, pageY) {
ball.style.left = pageX - shiftX + 'px';
ball.style.top = pageY - shiftY + 'px';
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
ball.hidden = true;
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
ball.hidden = false;
if (!elemBelow) return;
let droppableBelow = elemBelow.closest('.droppable');
if (currentDroppable != droppableBelow) {
if (currentDroppable) { // null when we were not over a droppable before this event
leaveDroppable(currentDroppable);
}
currentDroppable = droppableBelow;
if (currentDroppable) { // null if we're not coming over a droppable now
// (maybe just left the droppable)
enterDroppable(currentDroppable);
}
//add score
**function scoreIncrement() {
score++;
document.getElementById("score").innerText="Score: " + score;**
}​
}
}
document.addEventListener('mousemove', onMouseMove);
ball.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
ball.onmouseup = null;
};
};
function enterDroppable(elem) {
elem.style.background = 'pink';
}
function leaveDroppable(elem) {
elem.style.background = '';
}
ball.ondragstart = function() {
return false;
};
</script>
</body>
</html>
Thanks again for for taking the time to look this over
you were almost there!. You were missing what is called a "flag". That is a variable (usually true/false) that holds some information that allows you to make decisions in the right event (which you had).
In this case a flag could tell me if I am over or not the goal, so that when I drop the ball I can add a point to the score.
As you can see in the code below, when you enterDroppable the flag is set to true and when you leaveDroppable its set back to false; then when the event mouseUp is triggered, the flag is checked. If the flag was true, then the score is incremented (and its value is updated on the screen)
Note that I changed the style of the ball so it looks more like a ball. Also note that its not a good practice to subscribe and remove events inside other events. Its better to have the events subscribed once and have more flags: for example, set a flag in the mouseDown to know that the ball was "grabed", then the mouseMove event would check that flag to see if it had to move the ball or not. I leave it as is, so not to change your code much but keep it in mind.
See the working code below (scroll all the way down and click on "Run the snipped code" to see it in action). Also if this solved your question dont forget to mark it as such using the green check left to the answer.
const scoreDisplay = document.querySelector('#score')
let score = 0
let currentDroppable = null;
let ballIsOverDroppable = false;
ball.onmousedown = function(event) {
let shiftX = event.clientX - ball.getBoundingClientRect().left;
let shiftY = event.clientY - ball.getBoundingClientRect().top;
ball.style.position = 'absolute';
ball.style.zIndex = 1000;
document.body.append(ball);
moveAt(event.pageX, event.pageY);
function moveAt(pageX, pageY) {
ball.style.left = pageX - shiftX + 'px';
ball.style.top = pageY - shiftY + 'px';
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
ball.hidden = true;
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
ball.hidden = false;
if (!elemBelow) return;
let droppableBelow = elemBelow.closest('.droppable');
if (currentDroppable != droppableBelow) {
if (currentDroppable) { // null when we were not over a droppable before this event
leaveDroppable(currentDroppable);
}
currentDroppable = droppableBelow;
if (currentDroppable) { // null if we're not coming over a droppable now
// (maybe just left the droppable)
enterDroppable(currentDroppable);
}
}
}
document.addEventListener('mousemove', onMouseMove);
ball.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
ball.onmouseup = null;
if (ballIsOverDroppable) {
score++;
scoreDisplay.textContent = `${score}`;
}
};
};
function enterDroppable(elem) {
elem.style.background = 'pink';
ballIsOverDroppable = true;
}
function leaveDroppable(elem) {
elem.style.background = '';
ballIsOverDroppable = false;
}
ball.ondragstart = function() {
return false;
};
<h3>Score:<span id="score">0</span></h3>
<button id="start-button">Start/Pause</button>
<p>Drag the ball.</p>
<img src="https://en.js.cx/clipart/soccer-gate.svg" id="gate" class="droppable">
<img src="https://picsum.photos/20/20" id="ball" style="border-radius: 20px; border: 2px solid black;">

Making game character walk, Javascript

I'm trying to make a simple game with a walking character. When a button is pressed down i want to continuously switch between two images (while the button is held down) which will make it look like the character is moving. It does move, however the switch between pictures happens only once at the beginning. Can anyone tell me what am i doing wrong? Or suggest a way to do it. Been stuck on this for hours.
Any help will be much appreciated.
<!DOCTYPE html>
<html>
<head>
<link href="./styles/style.css" rel="stylesheet" type="text/css"><link>
<meta charset="utf-8" />
<title>Playa Haters</title>
<style>
* { padding: 0; margin: 0; }
</style>
</head>
<body>
<canvas id="myCanvas" width="800" height="450"></canvas>
<img id="step1" src="media/step1.jpg" width="120" height="150">
<img id="step2" src="media/step2.jpg" width="120" height="150">
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d"); //get content
var step1 = document.getElementById("step1");
var step2 = document.getElementById("step2");
var currentStep = step1;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
var rightPressed = false;
var leftPressed = false;
var step = 5;
var distance = null;
function keyDownHandler(e) {
if(e.keyCode == 39){
rightPressed = true;
}
else if(e.keyCode = 37){
leftPressed = true;
}
}
function keyUpHandler(e) {
if(e.keyCode == 39) {
rightPressed = false;
}
else if(e.keyCode == 37) {
leftPressed = false;
}
}
//initial position
var x = canvas.width/2;
var y = canvas.height/2 - 100;
function drawShooter(){
ctx.drawImage(currentStep, x, y);
}
function walk(){
if (currentStep = step1){
currentStep = step2;
}
else if (currentStep = step2){
currentStep = step1;
}
}
function draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawShooter();
if(rightPressed) {
x += step;
setInterval(walk, 500);
}
else if(leftPressed) {
x -= step;
setInterval(walk, 500);
}
}
setInterval(draw, 20);
</script>
</body>
</html>
On your walk function you are assigning instead of comparing inside the if statement... you have:
function walk(){
if (currentStep = step1){
currentStep = step2;
}
else if (currentStep = step2){
currentStep = step1;
}
}
You should have instead:
function walk(){
if (currentStep === step1){
currentStep = step2;
}
else if (currentStep === step2){
currentStep = step1;
}
}
Note the triple equals inside the conditional. This should solve the problem with swapping the images.

Top attribute won't update. Function only works when I set if function value = to initial top value in javascript

I was working on collision detection and thought I would start out simple by testing when the object reaches a certain x-position. It works when I set it to 100, the initial top value for 'character, which leads me to believe the problem is with top updating; however, I don't see why the circles would be moving if that were the case.If you could tell me how to keep 'top' updated or better yet, help me with collision detection that would be great!
(ps. I know it's not good to put css, javascript, and html in one page. I have this as part of a website but moved it to one file so I could test it separately without looking through the code of the entire website and I will add it in the appropriate files once I get this figured out.)
<html>
<head>
<style>
#character {
position: absolute;
width: 42px;
height: 42px;
background: black;
border-radius: 50%;
}
#character2 {
position: absolute;
width: 42px;
height: 42px;
background: pink;
border-radius: 50%;
} </style>
</head>
<body>
<div id = 'character'></div>
<div id = 'character2'></div>
<script>
var keys = {};
keys.UP = 38;
keys.LEFT = 37;
keys.RIGHT = 39;
keys.DOWN = 40;
keys.W = 87;
keys.A = 65;
keys.D = 68;
keys.S = 83;
/// store reference to character's position and element
var character = {
x: 1000,
y: 100,
speedMultiplier: 1,
element: document.getElementById("character")
};
var character2 = {
x: 100,
y: 100,
speedMultiplier: 3,
element: document.getElementById("character2")
};
/// key detection (better to use addEventListener, but this will do)
document.body.onkeyup =
document.body.onkeydown = function(e){
/// prevent default browser handling of keypresses
if (e.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}
var kc = e.keyCode || e.which;
keys[kc] = e.type == 'keydown';
};
/// character movement update
var moveCharacter = function(dx, dy){
character.x += (dx||0) * character.speedMultiplier;
character.y += (dy||0) * character.speedMultiplier;
character.element.style.left = character.x + 'px';
character.element.style.top = character.y + 'px';
};
var moveCharacter2 = function(dx, dy){
character2.x += (dx||0) * character2.speedMultiplier;
character2.y += (dy||0) * character2.speedMultiplier;
character2.element.style.left = character2.x + 'px';
character2.element.style.top = character2.y + 'px';
};
/// character control
var detectCharacterMovement = function(){
if ( keys[keys.LEFT] ) {
moveCharacter(-1, 0);
}
if ( keys[keys.RIGHT] ) {
moveCharacter(1, 0);
}
if ( keys[keys.UP] ) {
moveCharacter(0, -1);
}
if ( keys[keys.DOWN] ) {
moveCharacter(0, 1);
}
if ( keys[keys.A] ) {
moveCharacter2(-1, 0);
}
if ( keys[keys.D] ) {
moveCharacter2(1, 0);
}
if ( keys[keys.W] ) {
moveCharacter2(0, -1);
}
if ( keys[keys.S] ) {
moveCharacter2(0, 1);
}
};
/// update current position on screen
moveCharacter();
moveCharacter2();
/// game loop
setInterval(function(){
detectCharacterMovement();
}, 1000/24);
function getPosition() {
var elem = document.getElementById("character");
var top = getComputedStyle(elem).getPropertyValue("top");
if (top == '200px') {
alert ("hi");
}
getPosition()
}
getPosition()
// var pos1 = document.getElementById('character').style.top
</script>
</body>
</html>
I figured it out! I just added Jquery's .position() to get the coordinates! For the collision detection I added this:
function collision1() {
$(document).ready(function(){
var x = $("#character").position();
var y = $("#character2").position();
var zid = '#' + id
var z = $(zid).position();
var topX = parseInt(x.top);
var topZ = parseInt(z.top);
var leftX = parseInt(x.left);
var leftZ = parseInt(z.left);
var topY = parseInt(y.top);
var leftY = parseInt(y.left);
if (topX > topZ && topX < (topZ + 50) && leftX > leftZ && leftX < (leftZ + 100)) {
alert('Player 1 Won! Click restart to play again.')
document.getElementById("button2").style.display = "block";
document.getElementById("def").style.display = "none";
document.getElementById("def2").style.display = "none";
document.getElementById("def3").style.display = "none";
document.getElementById("def4").style.display = "none";
document.getElementById("term").style.display = "none";
}
else {
collision1()}
});}
I know it is probably not the most effective way to program this but it works!

Javascript Canvas - Functions making all entities disapear

I am using javascript canvas to create a little school project.
I have problem with function. After I add it nothing will load.
Like the canvas dont work.
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<canvas id="ctx" width="800" height="500" style="border:1px solid #000000;background-image:url('space-1.jpg')"></canvas>
<script>
var ctx = document.getElementById("ctx").getContext("2d");
ctx.font = '30px Arial';
ctx.fillStyle = 'white';
document.onkeydown = function(event){
if (event.keyCode === 68 && falcon.x < 600 ) { //d
falcon.x += 10;
bullet.x +=10;
}
if (event.keyCode === 83 && falcon.y < 360){ //s
falcon.y +=10;
}
if (event.keyCode === 65 && falcon.x > 0) { //a
falcon.x -=10;
bullet.x -=10;
}
if (event.keyCode === 87 && falcon.y > 0) { //w
falcon.y -=10;
}
if (event.keyCode === 32) {
fire = setInterval(fireBullet,10);
if(bullet.x < 0) {
bullet.x = falcon.x;
clearInterval(fire);
}
}
};
falcon = {
x : 10,
y : 10,
img : 'falcon1.png'
};
bullet = {
x : falcon.x,
y : falcon.y+55,
img : 'bullet.png'
};
enemy = {
x: 0,
y : 0,
img : 'enemy_1.png'
};
setInterval(update,10);
function update(){
/* Clear rect*/
ctx.clearRect(0,0,800,500);
/*Draw Falcon and coords*/
drawEntity(falcon.x, falcon.y, falcon.img);
ctx.fillText("X : " + falcon.x + " Y : " + falcon.y, 600,480);
/* Bullet moving with falcon and fire */
drawEntity(bullet.x, bullet.y, bullet.img);
bullet.y = falcon.y+55;
/* Enemy*/
drawEntity(enemy.x, enemy.y, enemy.img);
}
function drawEntity(x, y, img){
var Img = new Image();
Img.src = img;
ctx.drawImage(Img,x, y);
}
function fireBullet(){
bullet.x -=10;
}
function testCollision(entity1, entity2) {
var distance = getDistace(entity1, entity2);
return distance < 2;
}
</script>
</body>
</html>
This code works fine but after I add this code and I need it for collision
and I even tried to get the code inside the function to testCollision function and it wont help.
function getDistance(entity1, entity2) {
var vx = entity1.x - entity2.x;
var vy = entity1.y - entity2.y;
return Math.Sqrt(vx*vx+*vy*vy);
}
All my entities just dont render I uploaded pictures about it.
BEFORE adding
AFTER adding
Can someone help ?
Your function getDistance should return this:
return Math.sqrt(vx*vx+vy*vy);
Hope this helps.

Snake Game with Mobile Button Controls

In this Snake game, I need the buttons to control the snake just like the arrow keys do. This will allow the game to be played on a mobile device. You can see i have code in there for the buttons, but they are not working properly and not controlling the movement of the snake.
Any advice to make the buttons work would be greatly appreciated! thanks!
HTML
<section class="game" id="share">
<div class="container">
<div class="columns twelve borders center">
<div class="game-container">
<div class="container">
<div class="SplashScreen">
<h1>
Snake
</h1>
<h2>
Click To Start.
</h2>
<input class="StartButton" type="button" value="Start" />
</div>
<div class="FinishScreen" style="display:none">
<h1>
Game Over
</h1>
<p>
Your score was: <span id="score"></span>
</p>
<input class="StartButton" type="button" value="Restart" />
</div>
<canvas id="canvasArea" height="300" width="300" style="display:none;"></canvas>
</div>
<div class="button-pad">
<div class="btn-up">
<input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-up.png" alt="Up" class="button up-btn" />
</div>
<div class="btn-right">
<input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-right.png" alt="Right" class="button right-btn" />
</div>
<div class="btn-down">
<input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-down.png" alt="Down" class="button down-btn" />
</div>
<div class="btn-left">
<input type="image" src="http://aaronblomberg.com/sites/ez/images/btn-left.png" alt="Left" class="button left-btn" />
</div>
</div>
</div>
</div>
</div>
</section>
JAVASCRIPT
( function( $ ) {
$( function() {
$(document).ready(function () {
$(".StartButton").click(function () {
$(".SplashScreen").hide();
$(".FinishScreen").hide();
$("#canvasArea").show();
init();
});
//Canvas stuff
var canvas = $("#canvasArea")[0];
var ctx = canvas.getContext("2d");
var w = $("#canvasArea").width();
var h = $("#canvasArea").height();
//Lets save the cell width in a variable for easy control
var sw = 10;
var direction;
var nd;
var food;
var score;
//Lets create the snake now
var snake_array; //an array of cells to make up the snake
function endGame() {
$("#canvasArea").hide();
$("#score").text(score);
$(".FinishScreen").show();
}
function init() {
direction = "right"; //default direction
nd = [];
create_snake();
create_food(); //Now we can see the food particle
//finally lets display the score
score = 0;
//Lets move the snake now using a timer which will trigger the paint function
//every 60ms
if (typeof game_loop != "undefined") clearInterval(game_loop);
game_loop = setInterval(paint, 60);
}
function create_snake() {
var length = 5; //Length of the snake
snake_array = []; //Empty array to start with
for (var i = length - 1; i >= 0; i--) {
//This will create a horizontal snake starting from the top left
snake_array.push({
x: i,
y: 0
});
}
}
//Lets create the food now
function create_food() {
food = {
x: Math.round(Math.random() * (w - sw) / sw),
y: Math.round(Math.random() * (h - sw) / sw),
};
//This will create a cell with x/y between 0-44
//Because there are 45(450/10) positions accross the rows and columns
}
//Lets paint the snake now
function paint() {
if (nd.length) {
direction = nd.shift();
}
//To avoid the snake trail we need to paint the BG on every frame
//Lets paint the canvas now
ctx.fillStyle = "#0056a0";
ctx.fillRect(0, 0, w, h);
ctx.strokeStyle = "#ffffff";
ctx.strokeRect(0, 0, w, h);
//The movement code for the snake to come here.
//The logic is simple
//Pop out the tail cell and place it infront of the head cell
var nx = snake_array[0].x;
var ny = snake_array[0].y;
//These were the position of the head cell.
//We will increment it to get the new head position
//Lets add proper direction based movement now
if (direction == "right") nx++;
else if (direction == "left") nx--;
else if (direction == "up") ny--;
else if (direction == "down") ny++;
//Lets add the game over clauses now
//This will restart the game if the snake hits the wall
//Lets add the code for body collision
//Now if the head of the snake bumps into its body, the game will restart
if (nx == -1 || nx == w / sw || ny == -1 || ny == h / sw || check_collision(nx, ny, snake_array)) {
//end game
return endGame();
}
//Lets write the code to make the snake eat the food
//The logic is simple
//If the new head position matches with that of the food,
//Create a new head instead of moving the tail
if (nx == food.x && ny == food.y) {
var tail = {
x: nx,
y: ny
};
score++;
//Create new food
create_food();
} else
{
var tail = snake_array.pop(); //pops out the last cell
tail.x = nx;
tail.y = ny;
}
//The snake can now eat the food.
snake_array.unshift(tail); //puts back the tail as the first cell
for (var i = 0; i < snake_array.length; i++) {
var c = snake_array[i];
//Lets paint 10px wide cells
paint_cell(c.x, c.y);
}
//Lets paint the food
paint_cell(food.x, food.y);
//Lets paint the score
var score_text = "Score: " + score;
ctx.fillStyle = "#ffffff";
ctx.fillText(score_text, 5, h - 5);
//Set the font and font size
ctx.font = '12px Arial';
//position of the fill text counter
ctx.fillText(itemCounter, 10, 10);
}
//Lets first create a generic function to paint cells
function paint_cell(x, y) {
ctx.fillStyle = "#d8d8d8";
ctx.fillRect(x * sw, y * sw, sw, sw);
}
function check_collision(x, y, array) {
//This function will check if the provided x/y coordinates exist
//in an array of cells or not
for (var i = 0; i < array.length; i++) {
if (array[i].x == x && array[i].y == y) return true;
}
return false;
}
// Lets prevent the default browser action with arrow key usage
var keys = {};
window.addEventListener("keydown",
function(e){
keys[e.keyCode] = true;
switch(e.keyCode){
case 37: case 39: case 38: case 40: // Arrow keys
case 32: e.preventDefault(); break; // Space
default: break; // do not block other keys
}
},
false);
window.addEventListener('keyup',
function(e){
keys[e.keyCode] = false;
},
false);
//Lets add the keyboard controls now
$(document).keydown(function (e) {
var key = e.which;
var td;
if (nd.length) {
var td = nd[nd.length - 1];
} else {
td = direction;
}
//We will add another clause to prevent reverse gear
if (key == "37" && td != "right") nd.push("left");
else if (key == "38" && td != "down") nd.push("up");
else if (key == "39" && td != "left") nd.push("right");
else if (key == "40" && td != "up") nd.push("down");
//The snake is now keyboard controllable
});
});
$(document).on('click', '.button-pad > button', function(e) {
if ($(this).hasClass('left-btn')) {
e = 37;
}
else if ($(this).hasClass('up-btn')) {
e = 38;
}
else if ($(this).hasClass('right-btn')) {
e = 39;
}
else if ($(this).hasClass('down-btn')) {
e = 40;
}
$.Event("keydown", {keyCode: e});
});
});
})( jQuery );
FIDDLE
AND TIME
So basically you have some errors going on. Your first one is your styling. You really need to make your styles more flexible, but this will solve the right button problem I was having.
.button-pad > div {
z-index: 9999;
width: 50px;
}
http://jsfiddle.net/34oeacnm/8/
$(document).on('click', '.button-pad .button', function(e) {
var e = jQuery.Event("keydown");
if ($(this).hasClass('left-btn')) {
e.which = 37;
}
else if ($(this).hasClass('up-btn')) {
e.which = 38;
}
else if ($(this).hasClass('right-btn')) {
e.which = 39;
}
else if ($(this).hasClass('down-btn')) {
e.which = 40;
}
$(document).trigger(e);
});
You had some of your selectors off. And I stole some information on how to trigger from Definitive way to trigger keypress events with jQuery.
Here is the code to add moile control to the snake game; (If you want the whole code for the snake game please comment);
//Here is javascript;
// left key
function l() {
if(snake.dx === 0) {
snake.dx = -grid;
snake.dy = 0;
}
}
// up key
function u() {
if(snake.dy === 0) {
snake.dy = -grid;
snake.dx = 0;
}
}
// right key
function r() {
if(snake.dx === 0) {
snake.dx = grid;
snake.dy = 0;
}
}
// down key
function d() {
if(snake.dy === 0) {
snake.dy = grid;
snake.dx = 0;
}
}
Here is HTML;
<div>
<button onclick="u()" type="button" id="U">U</button>
<button onclick="l()" type="button" id="L">L</button>
<button onclick="r()" type="button" id="R">R</button>
<button onclick="d()" type="button" id="D">D</button>
</div>
Description: I simply added four buttons in the html page, created four functions in the js which will move snake as it should move in different directions and simply added them to the 'onclick' attribute of the different buttons respectively.

Categories

Resources