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.
Related
i need to quit application as soon as stop button pressed from HTML.The start and stop button working fine but the problem with stop button is that it pause the game not quit the application. i wrote this code in else block window.setTimeout(animloop, 1000); it will pause the game but not quit the game or if i use windows.close() it will close browser immediately .
my code:
var gameStarted = false;
// Infinte loop for game play
(function animloop() {
if (gameStarted) {
requestAnimFrame(animloop);
render();
} else {
window.setTimeout(animloop, 1000); // check the state per second
}
})(); // ends (function animloop() )
}); // ends $(doc).ready
HTML code:
<html>
<head>
<link rel="icon" href="./arrows/clubbackground.jpg" type="image/gif" sizes="16x16">
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="jsRev.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<title>DDR-Project 1</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="BackgroundScene">
<div id="DanceScoreboard">
<div id="GameStopped"><button id="StartBtn" class="btnStyle" onclick="gameStarted=true;">Begin Game</button>
<br><br><br>
<div class="Status">Click Begin Game to start</div>
</div>
<div id="GameRunning"><button id="StopBtn" class="btnStyle" onclick="gameStarted=false;">Stop Game</button>
<div id="Status" class="Status"></div>
</div>
<div id="dancePoints" class="Points">Points Earned:
<div class="OutputText" id="CorrectCount">0</div>
</div>
</div>
<div class="stage"></div>
<!-- ENDS .STAGE -->
<div id="controls">
<img id="left" src="./arrows/staticLeft.png">
<img id="up" src="./arrows/staticUp.png">
<img id="down" src="./arrows/staticDown.png">
<img id="right" src="./arrows/staticRight.png">
</div>
<!-- ENDS #CONTROLS -->
</body>
</html>
java script code:
var notes = [];
var gameStarted = false;
var Score = 0;
// ==== CLASS FOR ARROWS ==== //
// 1. Direction of arrows
// 2. jQuery img that links to direction bottom
// 3. Destroy when it arrow gets to the
// 4. Explode when arrow gets to the bottom
// Class Arrow
function Arrow(direction) {
// CSS spacings for the arrows //
var xPos = null;
switch (direction) {
case "left":
xPos = "350px";
break;
case "up":
xPos = "420px";
break;
case "down":
xPos = "490px";
break;
case "right":
xPos = "560px";
break;
}
this.direction = direction;
this.image = $("<img src='./arrows/" + direction + ".gif'/>");
this.image.css({
position: "absolute",
top: "0px",
left: xPos
});
$('.stage').append(this.image);
} // ends CLASS Arrow
// To enable animating the arrows
Arrow.prototype.step = function() {
// Controls the speed of the arrows
this.image.css("top", "+=4px");
};
// Deletes arrows when they get to bottom of page
Arrow.prototype.destroy = function() {
// removes the image of the DOM
this.image.remove();
// Removes the note/arrow from memory/array
notes.splice(0, 1);
};
// Explodes arrow when hit
Arrow.prototype.explode = function() {
this.image.remove();
};
// For random arrows
var randNum = 0;
// Frame increasing
var frame = 0;
// Determines the speed of notes
var arrowSpawnRate = 40;
// Random generator for arrows
function randomGen() {
// Randomizes between 1 and 4
randNum = Math.floor(Math.random() * 4) + 1;
if (randNum === 1) {
notes.push(new Arrow("left"));
}
if (randNum === 2) {
notes.push(new Arrow("right"));
}
if (randNum === 3) {
notes.push(new Arrow("up"));
}
if (randNum === 4) {
notes.push(new Arrow("down"));
}
} // ends randomGen()
// Render function //
function render() {
if (frame++ % arrowSpawnRate === 0) {
randomGen();
}
// Animate arrows showering down //
for (var i = notes.length - 1; i >= 0; i--) {
notes[i].step();
// Check for cleanup
if (notes[i].image.position().top > 615) {
notes[i].destroy();
}
}
} // ends render()
// jQuery to animate arrows //
$(document).ready(function() {
// shim layer with setTimeout fallback
window.requestAnimFrame = (function() {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 40 / 75);
};
})();
/* place the rAF *before* the render()
to assure as close to 60fps with the
setTimeout fallback. */
// Infinte loop for game play
(function animloop() {
if (gameStarted) {
requestAnimFrame(animloop);
render();
} else {
window.setTimeout(animloop, 1000); // check the state per second
}
})(); // ends (function animloop() )
}); // ends $(doc).ready
// Listening for when the key is pressed
$(document).keydown(function(event) {
for (var i = 0; i < notes.length; i++) {
if (event.keyCode == 37 && notes[i].direction == "left") {
if (notes[i].image.position().top > 490 && notes[i].image.position().top < 730) {
console.log("LEFT! " + notes[i].explode());
Score++;
score();
}
}
if (event.keyCode == 38 && notes[i].direction == "up") {
if (notes[i].image.position().top > 490 && notes[i].image.position().top < 730) {
console.log("UP! " + notes[i].explode());
Score++;
score();
}
}
if (event.keyCode == 40 && notes[i].direction == "down") {
if (notes[i].image.position().top > 490 && notes[i].image.position().top < 730) {
console.log("DOWN! " + notes[i].explode());
Score++;
score();
}
}
if (event.keyCode == 39 && notes[i].direction == "right") {
if (notes[i].image.position().top > 490 && notes[i].image.position().top < 730) {
console.log("RIGHT! " + notes[i].explode());
Score++;
score();
}
}
} // ends loop
}); // ends $(doc).keyup
function score() {
document.querySelector(".Points").textContent = Score;
}
What does "quit the application" mean?
You can close the browser window, or redirect the user to another route.
But the exact semantics of "quit the application" for your game in the browser need to be defined.
If you mean "Close the web browser", then you need to have your game open in a new window from the game code when it starts, so that it can close the window when it finishes.
So you have a launcher page, and that opens the game in a new window. You can then communicate between the windows, and close the child window later.
See here for an example of opening a child window. And here for closing it. And here for communicating between them.
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.
I've been building on top of an assignment we did in class and I'm stumped at the detection part.
I want my Mew to be "caught" when he stands on top of the pokeball, the player moves the keyboard to control the Mew and the pokeball randomly repositions on a time delay.
How can I create a function that will detect when the mew.gif is in overlap with the pokeball?
var _stage = document.getElementById("stage");
var _Mew = document.querySelector("img");
var _PokeBall = document.getElementById("PokeBall");
_stage.style.width = "800px";
_stage.style.height = "600px";
_stage.style.backgroundColor = "black";
_stage.style.marginLeft = "auto";
_stage.style.marginRight = "auto";
_Mew.style.position = "relative"; // Uses top and left from parent
_PokeBall.style.position = "relative"; // Uses top and left from parent
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
var player = [ 400, 300 ]; // Left, Top
var PokeBall = [100, 100];// Top, Left
var uIval = setInterval(update, 22.22); // 30fps update loop
var map = []; // empty Map Array
window.addEventListener("keydown", onKeyDown);
window.addEventListener("keyup", onKeyUp);
var Pval= setInterval(MovePokeball, 2000);
function generateMap()
{
for (var row = 0; row < 2; row++)
{
for(var col = 0; col <8; col++)
{
console.log("In row "+row);
}
}
}
/*map[row] = []; // Creating new array in specified row
for (var col = 0; col <8; col++)
{
console.log("In row "+row+"doing col"+col);
}
*/
function onKeyDown(event)
{
switch(event.keyCode)
{
case 37: // Left.
if ( leftPressed == false )
leftPressed = true;
break;
case 39: // Right.
if ( rightPressed == false )
rightPressed = true;
break;
case 38: // Up.
if ( upPressed == false )
upPressed = true;
break;
case 40: // Down.
if ( downPressed == false )
downPressed = true;
break;
default:
console.log("Unhandled key.");
break;
}
}
function onKeyUp(event)
{
switch(event.keyCode)
{
case 37: // Left.
leftPressed = false;
break;
case 39: // Right.
rightPressed = false;
break;
case 38: // Up.
upPressed = false;
break;
case 40: // Down.
downPressed = false;
break;
default:
console.log("Unhandled key.");
break;
}
}
function update() // Going to run 30fps
{
movePlayer();
// move enemies
// collision check
// animate sprites
PlayerCaught();
render();
}
function movePlayer()
{
if ( leftPressed == true && player[0] >= _Mew.width/2)
player[0] -= 10;
if ( rightPressed == true && player[0] < 800 - _Mew.width/2)
player[0] += 10;
if ( upPressed == true && player[1] >= _Mew.height/2 )
player[1] -= 10;
if ( downPressed == true && player[1] < 600 - _Mew.width/2)
player[1] += 10;
}
function render()
{
_Mew.style.left = player[0]-_Mew.width/2+"px";
_Mew.style.top = player[1]-_Mew.width/2+"px";
}
function PlayerCaught()
{
if (_PokeBall [100,100] = player [100,100])
window.alert("Mew Has Been Captured!")
}
function MovePokeball()
{
_PokeBall.style.left= Math.floor(Math.random()*801)+"px";
_PokeBall.style.top= Math.floor(Math.random()*601)+"px";
}
You're asking about collision detection. This is done by determining if two polygons intersect. Since your program is very simplified, I'm offering a very simplified solution. We're going to determine if the graphics intersect. This is not the ideal way to do it. Normally, graphics and physics are completely separated. But this will work (mostly), and hopefully it'll encourage you to continue to experiment.
First, we need the height and width of both images so we can do our geometric magic. This can be easily set in JavaScript, just like you did for _stage. However, you've already defined the src of your images elsewhere (probably in HTML), so it would be best to define the height and width there.
HTML Example:
<img id="PokeBall" src="pokeball.png" style="width:50px; height:50px" />
Note: This uses "inline CSS" which is another bad practice. But this works, and I don't want to overcomplicate simple things right now.
Now your PlayerCaught method has all the information it needs to do it's job, so how do we detect collisions? If we're working with rectangles, it's very simple. We just determine if any of the corners of one object are inside the other object. So how do we do that? Basically, we see if they intersect on both the X and Y axes.
Take two rectangles: A and B. Both have four edges: top, left, right, and bottom. The edges top and bottom are Y values, and the edges left and right are X values. The two rectangles intersect if any of the following is true:
(
A.left < B.left < A.right
OR A.left < B.right < A.right
) AND (
A.top < B.top < A.bottom
OR A.top < B.bottom < A.bottom
)
Translate that into JavaScript and you've got your collision detection function. To get the edges in your program, use the following:
function findEdges(img){
var result = [];
result["left"] = parseInt(img.style.left, 10);
result["top"] = parseInt(img.style.top, 10);
result["right"] = result["left"] + parseInt(img.style.width, 10);
result["bottom"] = result["top"] + parseInt(img.style.height, 10);
return result;
}
You can see that we are using the inline style that we set earlier for the width and height as well as the top and left you are already using for rendering.
SPOILER...
Putting all the pieces together might look like:
function PlayerCaught(){
if (detectImgCollision(_PokeBall, _Mew)){
window.alert("Mew Has Been Captured!")
}
}
function detectImgCollision(imgA, imgB){
var A = findEdges(imgA);
var B = findEdges(imgB);
return detectRectCollision(A, B);
}
function detectRectCollision(A, B){
return (
isBetween(A.left, B.left, A.right)
|| isBetween(A.left, B.right, A.right)
) && (
isBetween(A.top, B.top, A.bottom)
|| isBetween(A.top, B.bottom, A.bottom)
);
}
function isBetween(low, middle, high){
return (low <= middle && middle <= high);
}
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>
I recently began developing a little javascript game, just for fun. The idea was that you controlled a little dot with the arrow keys (or awsd or i don't care what) within a box on the screen. Little rectangles would then randomly spawn on all edges of the box and progress across it. you have to avoid contact with them. The project turned out to be harder than I expected and I couldn't get the movement to work right. If you could help me with that that would be great. also, feel free to take the concept and what little I have done so far and do whatever you want with it. I would be interested to see your results. Below is the code I used for the spawns without any of the movement scripts. I was using the basic idea of this code to do the movement:
var x = 5; //Starting Location - left
var y = 5; //Starting Location - top
var dest_x = 300; //Ending Location - left
var dest_y = 300; //Ending Location - top
var interval = 2; //Move 2px every initialization
function moveImage() {
//Keep on moving the image till the target is achieved
if(x<dest_x) x = x + interval;
if(y<dest_y) y = y + interval;
//Move the image to the new location
document.getElementById("ufo").style.top = y+'px';
document.getElementById("ufo").style.left = x+'px';
if ((x+interval < dest_x) && (y+interval < dest_y)) {
//Keep on calling this function every 100 microsecond
// till the target location is reached
window.setTimeout('moveImage()',100);
}
}
main body:
<html>
<head>
<style type="text/css">
html::-moz-selection{
background-color:Transparent;
}
html::selection {
background-color:Transparent;
}
img.n {position:absolute; top:0px; width:5px; height:10px;}
img.e {position:absolute; right:0px; width:10px; height:5px;}
img.s {position:absolute; bottom:0px; width:5px; height:10px;}
img.w {position:absolute; left:0px; width:10px; height:5px;}
#canvas {
width:300px;
height:300px;
background-color:black;
position:relative;
}
</style>
<script type="text/javascript">
nmecount=0
function play(){
spawn()
var t=setTimeout("play()",1000);
}
function spawn(){
var random=Math.floor(Math.random()*290)
var side=Math.floor(Math.random()*5)
var name=1
var z=10000
if (side=1)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'n');
nme.setAttribute('id', name);
nme.setAttribute('style', 'left:'+random+'px;');
nme.onload = moveS;
document.getElementById("canvas").appendChild(nme);
}
if (side=2)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'e');
nme.setAttribute('id', name);
nme.setAttribute('style', 'top:'+random+'px;');
nme.onload = moveW;
document.getElementById("canvas").appendChild(nme);
}
if (side=3)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 's');
nme.setAttribute('id', name);
nme.setAttribute('style', 'left:'+random+'px;');
nme.onload = moveN;
document.getElementById("canvas").appendChild(nme);
}
if (side=4)
{
var nme = document.createElement('img');
nme.setAttribute('src', '1.png');
nme.setAttribute('class', 'w');
nme.setAttribute('id', name);
nme.setAttribute('style', 'top:'+random+'px;');
nme.onload = moveE;
document.getElementById("canvas").appendChild(nme);
}
name=name+1
}
</script>
</head>
<body onLoad="play()">
<div id="canvas">
<img id="a" src="1.png" style="position:absolute; z-index:5; left:150px; top:150px; height:10px; width=10px;" />
<button onclick="moveleft()"><</button>
</body>
</html>
I can't figure out what your game is about, and so don't know what to do with that code. However, since you mentioned you were having trouble with movement, I wrote a quick JavaScript movement engine just for you, complete with acceleration and deceleration. Use the arrow keys to move. The following code represents a complete HTML document, so copy and paste it into a blank text file and save as .html. And make sure you have a 10x10 image called '1.png' in the same folder as the file.
<html>
<head>
<script type='text/javascript'>
// movement vars
var xpos = 100;
var ypos = 100;
var xspeed = 1;
var yspeed = 0;
var maxSpeed = 5;
// boundary
var minx = 0;
var miny = 0;
var maxx = 490; // 10 pixels for character's width
var maxy = 490; // 10 pixels for character's width
// controller vars
var upPressed = 0;
var downPressed = 0;
var leftPressed = 0;
var rightPressed = 0;
function slowDownX()
{
if (xspeed > 0)
xspeed = xspeed - 1;
if (xspeed < 0)
xspeed = xspeed + 1;
}
function slowDownY()
{
if (yspeed > 0)
yspeed = yspeed - 1;
if (yspeed < 0)
yspeed = yspeed + 1;
}
function gameLoop()
{
// change position based on speed
xpos = Math.min(Math.max(xpos + xspeed,minx),maxx);
ypos = Math.min(Math.max(ypos + yspeed,miny),maxy);
// or, without boundaries:
// xpos = xpos + xspeed;
// ypos = ypos + yspeed;
// change actual position
document.getElementById('character').style.left = xpos;
document.getElementById('character').style.top = ypos;
// change speed based on keyboard events
if (upPressed == 1)
yspeed = Math.max(yspeed - 1,-1*maxSpeed);
if (downPressed == 1)
yspeed = Math.min(yspeed + 1,1*maxSpeed)
if (rightPressed == 1)
xspeed = Math.min(xspeed + 1,1*maxSpeed);
if (leftPressed == 1)
xspeed = Math.max(xspeed - 1,-1*maxSpeed);
// deceleration
if (upPressed == 0 && downPressed == 0)
slowDownY();
if (leftPressed == 0 && rightPressed == 0)
slowDownX();
// loop
setTimeout("gameLoop()",10);
}
function keyDown(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 1;
if (code == 40)
downPressed = 1;
if (code == 37)
leftPressed = 1;
if (code == 39)
rightPressed = 1;
}
function keyUp(e)
{
var code = e.keyCode ? e.keyCode : e.which;
if (code == 38)
upPressed = 0;
if (code == 40)
downPressed = 0;
if (code == 37)
leftPressed = 0;
if (code == 39)
rightPressed = 0;
}
</script>
</head>
<body onload="gameLoop()" onkeydown="keyDown(event)" onkeyup="keyUp(event)" bgcolor='gray'>
<!-- The Level -->
<div style='width:500;height:500;position:absolute;left:0;top:0;background:black;'>
</div>
<!-- The Character -->
<img id='character' src='1.png' style='position:absolute;left:100;top:100;height:10;width:10;'/>
</body>
</html>
It works as follows: There is a game loop that gets called as soon as the body loads. This game loop calls itself every 10 millis for smooth animation. While it might not actually loop every 10 millis because of run-time speeds, such a low value will ensure that the frame rate is as smooth as can be for any browser.
Within the game loop we manipulate the x and y position of the object based on its current speed. Simple: add x speed to x position, and y speed to y position. Then, we change the actual position of the element based on the current x and y coordinates.
To manipulate the x and y speeds, we take keyboard input using event handlers. Based on the key code, we set a variable which tells the game if a key is down or up. Based on whether the key is down or up, we accelerate or decelerate the object up to the maximum speed. For more gradual speed-ups and slow-downs, floating point values can be used.
You should be able to get the gist of this simple engine by examining the code. Hopefully this will help you in implementing your own movement engine for the game.