Effect drawing first
Preparation before starting
game.html
-
js/
Create insidegame.js
-
images/
There are three pictures inside, a background picture (background. PNG), a hero picture (hero. PNG) and a monster picture (monster. PNG)
staygame.html
Write the following lines of simple HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Canvas Game</title>
</head>
<body>
<script></script>
</body>
</html>
We aregame.html
Introducedgame.js
File, yes, all the rest of the work is in operationgame.js
, add the JS code of the game.
Create canvas
In game.js, we first need to create a canvas for the game stage:
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
Here, an element is created and set through JScanvas
Width and height, and finally add them to the < body > label.var ctx = canvas.getContext("2d");
Mediumctx
Variables will be used later. For specific canvas usage, see the link here:
https://developer.mozilla.org/en/canvas_tutorial
Prepare pictures
The game needs to load the three pictures stored under the images folder:
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "images/background.png";
// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
heroReady = true;
};
heroImage.src = "images/hero.png";
// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
monsterReady = true;
};
monsterImage.src = "images/monster.png";
The above three pictures are loaded by creating a simple picture object. Three variables similar to bgready are used to identify whether the picture has been loaded. If the picture is drawn before the picture is loaded, an error will be reported. If you’re not surenew Image()
What the hell is it? You canbgImage.src = "images/background.png";
Later useconsole.log(bgImage);
To see, you will see something similar:
<img >
Game object
We need to define some objects so that we can use them later:
var hero = {
speed: 256 // movement in pixels per second
};
var monster = {};
var monstersCaught = 0;
Since heroes catch monsters, we have to have onehero
andmonster
Object. andhero
There is onespeed
Property controls how many pixels he moves per second. Monsters will not move during the game, so you don’t need to set properties for the time being.monstersCaught
It is used to store the number of times the monster is caught. Of course, the initial value is 0.
Process user input
The game is for people to play, so how do we know what the user did in the process? Pressed the keyboard? Click the mouse? These are the user’s input when playing the game, so once we capture these inputs, we can process the user’s input according to the game logic:
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
Here, we just listen to the input of two users:
- keydown
- keyup
Then we save the user’s input first, and there is no immediate response. For this purpose, we usekeysDown
This object is used to save the key value pressed by the user(keyCode)
, if the pressed key value is in this object, we will handle it accordingly.
In front-end development, users usually trigger click events before executing animation or initiating asynchronous requests
Start a game
At the end of the game, we need to start a new round of the game, sogame.js
add toreset
function
// Reset the game when the player catches a monster
var reset = function () {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
};
reset()
Function is used to start a new round and game. In this method, we put the hero back in the center of the canvas and the monster in a random place.
Update Object
During the game, whether the user is playing (with correct input status) or the game is over, we need to update the game object in time:
var update = function (modifier) {
if (38 in keysDown) { // Player holding up
hero.y -= hero.speed * modifier;
}
if (40 in keysDown) { // Player holding down
hero.y += hero.speed * modifier;
}
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed * modifier;
}
if (39 in keysDown) { // Player holding right
hero.x += hero.speed * modifier;
}
// Are they touching?
if (
hero.x <= (monster.x + 32)
&& monster.x <= (hero.x + 32)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)
) {
++monstersCaught;
reset();
}
};
update
The function is responsible for updating each object of the game and will be called repeatedly regularly. First, it is responsible for checking that the user is currently holding down the middle arrow key, and then moving the hero in the corresponding direction.
It’s a bit of a mental effort. Maybe it’s from thismodifier
Variable. You canbehind
To be achievedmain
We can see its source in the method, but it is necessary to explain it in detail here. It is a factor that starts with 1 and changes over time. For example, after 1 second, its value is 1, and the hero’s speed will be multiplied by 1, that is, 256 pixels per second; If half a second, its value is 0.5, and the hero’s speed is multiplied by 0.5, that is, the hero moves at half the normal speed in half a second. In theory, because of thisupdate
Functions are called very quickly and frequently, somodifier
The value of will be very small, but with this factor, no matter how fast our code runs, it can ensure that the hero’s moving speed is constant.
Here we need to explain the following basis for judging monsters and Heroes:
if (
hero.x <= (monster.x + 31)
&& monster.x <= (hero.x + 31)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)
)
above31
,32
Byhero
andmonster
It depends on the size of the picture. Our hero picture is32x32
, monster picture is30x32
Therefore, the above judgment conditions can be obtained according to the law that the coordinates are located in the center of the picture.
Now the hero’s movement is based on user input (pressupper
,lower
,Left
,right
Key), then it’s time to check the events triggered during the movement, that is, the hero meets the monster. This is the winning point of the game,monstersCaught +1
Then start a new round.
Render Objects
The code written before is in the preparatory work and dealing with the state of some games. Now we will get to the point: we need to draw everything
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (heroReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
}
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Goblins caught: " + monstersCaught, 32, 32);
};
therectx
This is the variable we created earlier. Then usecanvas
ofdrawImage()
The first is, of course, to draw the background. Then draw heroes and monsters in the same way. The order in this process is particular, because the later painted objects will cover the previous objects.
After that, we changedCanvas
The style of the drawing context and callfillText
To draw the text, that is, the part of the scoreboard. There are no other complex animation effects and fighting scenes in this game. The drawing part is completed
Main loop function
After we draw the picture, what we need to implement next is the loop structure of the game, so we put it inmain
In the function:
// The main game loop
var main = function () {
var now = Date.now();
var delta = now - then;
//console.log(delta);
update(delta / 1000);
render();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
The main function above controls the flow of the whole game. First, get the current time to calculate the time difference (how many milliseconds have passed since the last main function was called). obtainmodifier
Then divide by 1000 (that is, the number of milliseconds in 1 second) and pass it inupdate
Function. Last callrender
Function and save the time of this time.
Set requestanimationframe()
On topmain
Function, we passrequestAnimationFrame()
Calledmain
Function, so we need to declare:
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
There are so many here||
, for nothing else, just considering the problem of browser compatibility.
Finally, start the game
Everything is ready, only due to the east wind. At this point, all the game codes are basically finished. What we need to do now is to call the corresponding function to start the game:
// Let's play this game!
var then = Date.now();
reset();
main();
Here, the code is finished. First, set an initial time variablethen
Used to run firstmain
Function use. Then callreset
Function to start a new round of the game (if you remember, this function is to put the hero in the middle of the screen and put the monster in a random place so that the hero can catch it)
Open with browsergame.html
, start playing games!
Further thinking
In the process of playing the game, you will find that every timehero
Capturemonster
,hero
Back tocanvas
Right in the middle of the canvas. So what we need to do now is tohero
Snap tomonster
Let’s go when we’re readyhero
Stay in the captured position, no longer backcanvas
Right in the middle.
This phenomenon is mainly due toreset
In functionhero.x
andhero.y
It’s dead, so one of the easiest ways is toreset
Parameters passed in:
var reset = function (x,y) {
hero.x = x;
hero.y = x;
};
Then inupdate
callreset
Pass in the parameters of the capture location when:
var update = function (modifier) {
//...other codes
++monstersCaught;
reset(heor.x,hero.y);
};
Finally, at the beginning of the gamehero
Put oncanvas
In the middle:
var then = Date.now();
reset(canvas.width / 2,canvas.height / 2);
main();
be accomplished!
Hapyy Hacking