Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to build Snooker Snooker Club with HTML 5

2025-03-29 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

How to use HTML 5 to build a snooker billiards club, this article introduces the corresponding analysis and solutions in detail, hoping to help more partners who want to solve this problem to find a more simple and feasible way.

How to use HTML5 technology to create a very cool snooker billiards game, the article lists in detail the whole process of development, and explains several key points to achieve this game.

There is no doubt that we have witnessed the great revolution in Web development behind HTML5. After so many years of HTML4 rule, a new movement is about to completely change the current Web world. It was his modernity and rich user experience that quickly made it a unique plug-in that runs on frameworks like Flash and Silverlight.

If you are a very young developer, maybe you are just starting to learn HTML5, so maybe you haven't noticed that he has changed much. I hope this article will help you at any time, and of course, I also hope that veterans like me can learn some new tricks from it.

Your comments are very important to me, so I look forward to hearing from you. Of course, what excites me even more is when you right-click on that game screen and secretly say, "Hey, this is not Flash! it's not Silverlight!"

System requirements

To use the HTML5 billiard application provided in this article, you must install the following browsers: Chrome 12, Internet Explorer 9 or Fire Fox 5

Rules of the game

Maybe you already know what kind of game this is, yes, this is "British snooker", actually more specifically "simple English snooker", because all the rules of the snooker game have not been implemented. Your goal is to put the target ball into the bag in order to get more points than other players. When it's your turn, you're going to hit the shot: according to the hint, you must first score a red ball to get a point, and if you do, you can continue to play other balls-but this time you can only play the colored ball (that is, except the red ball). If you score successfully, you will get the corresponding score of your own color ball. Then the colored ball will return to the table and you can continue to hit other red balls. Do this over and over again until you fail. When you have played all the red balls, there will be only six balls left on the table. your goal is to put the six balls into the bag in the following order: yellow (2 points), green (3 points), brown (4 points), blue (5 points), pink (6 points) and black (7 points). If a ball is not scored in the above order, it will return to the table, otherwise, it will eventually stay in the bag. When all the balls are played, the game is over and the person who scores the most wins.

Foul handling

In order to punish you for your foul, other players will get your penalty points:

◆ white ball fell into the bag and fined 4 points.

The score of the first penalty if the first hit of the ◆ white ball is wrong.

◆ 's first wrong ball fell into the bag and punished the score of the first ball.

The ◆ penalty score is at least 4.

The following code shows how I calculate fouls:

Var strokenBallsCount = 0; console.log ('strokenBalls.length:' + strokenBalls.length); for (var I = 0; I

< strokenBalls.length; i++) { var ball = strokenBalls[i]; //causing the cue ball to first hit a ball other than the ball on if (strokenBallsCount == 0) { if (ball.Points != teams[playingTeamID - 1].BallOn.Points) { if (ball.Points == 1 || teams[playingTeamID - 1].BallOn.Points == 1 || fallenRedCount == redCount) { if (teams[playingTeamID - 1].BallOn.Points < 4) { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1] .FoulList.length] = 4; $('#gameEvents').append(' Foul 4 points : Expected ' + teams[playingTeamID - 1].BallOn.Points + ', but hit ' + ball.Points); } else { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1] .FoulList.length] = teams[playingTeamID - 1].BallOn.Points; $('#gameEvents').append(' Foul ' + teams[playingTeamID - 1] .BallOn.Points + ' points : Expected ' + teams[playingTeamID - 1] .BallOn.Points + ', but hit ' + ball.Points); } break; } } } strokenBallsCount++; } //Foul: causing the cue ball to miss all object balls if (strokenBallsCount == 0) { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length] = 4; $('#gameEvents').append(' Foul 4 points : causing the cue ball to miss all object balls'); } for (var i = 0; i < pottedBalls.length; i++) { var ball = pottedBalls[i]; //causing the cue ball to enter a pocket if (ball.Points == 0) { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length] = 4; $('#gameEvents').append(' Foul 4 points : causing the cue ball to enter a pocket'); } else { //causing a ball different than the target ball to enter a pocket if (ball.Points != teams[playingTeamID - 1].BallOn.Points) { if (ball.Points == 1 || teams[playingTeamID - 1].BallOn.Points == 1 || fallenRedCount == redCount) { if (teams[playingTeamID - 1].BallOn.Points < 4) { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1] .FoulList.length] = 4; $('#gameEvents').append(' Foul 4 points : ' + ball.Points + ' was potted, while ' + teams[playingTeamID - 1] .BallOn.Points + ' was expected'); $('#gameEvents').append(' ball.Points: ' + ball.Points); $('#gameEvents').append(' teams[playingTeamID - 1] .BallOn.Points: ' + teams[playingTeamID - 1].BallOn.Points); $('#gameEvents').append(' fallenRedCount: ' + fallenRedCount); $('#gameEvents').append(' redCount: ' + redCount); } else { teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1] .FoulList.length] = teams[playingTeamID - 1].BallOn.Points; $('#gameEvents').append(' Foul ' + teams[playingTeamID - 1] .BallOn.Points + ' points : ' + ball.Points + ' was potted, while ' + teams[playingTeamID - 1].BallOn.Points + ' was expected'); } } } } } 得分 我们根据下面的规则来计算得分:红(1分)、黄(2分)、绿(3分)、棕(4分)、蓝(5分)、粉(6分)、黑(7分)。代码如下: if (teams[playingTeamID - 1].FoulList.length == 0) { for (var i = 0; i < pottedBalls.length; i++) { var ball = pottedBalls[i]; //legally potting reds or colors wonPoints += ball.Points; $('#gameEvents').append(' Potted +' + ball.Points + ' points.'); } } else { teams[playingTeamID - 1].FoulList.sort(); lostPoints = teams[playingTeamID - 1].FoulList[teams[playingTeamID - 1].FoulList.length - 1]; $('#gameEvents').append(' Lost ' + lostPoints + ' points.'); } teams[playingTeamID - 1].Points += wonPoints; teams[awaitingTeamID - 1].Points += lostPoints; 选手的闪动动画头像

The game is played by two players, each with their own nickname and avatar, so we simply named the player's nickname "player 1" and "player 2" (maybe it would be more beautiful to let the user type it). The profile picture of each player is a cute puppy playing billiards. When it is one of the contestants' turn, his avatar will have a flash animation effect, while the opponent's avatar will stop flashing.

This effect is achieved by changing the value of the CSS3 attribute opacity of the img element: we use the animatio function of jquery to change the value of opacity between 0 and 1.0.

Function animateCurrentPlayerImage () {var otherPlayerImageId = 0; if (playingTeamID = = 1) otherPlayerImageId = 'player2Image'; else otherPlayerImageId =' player1Image'; var playerImageId = 'player' + playingTeamID +' Image' $('#'+ playerImageId). Animate ({opacity: 1.0}, 500, function () {$('#'+ playerImageId). Animate ({opacity: 0}, 500, function () {$('#'+ playerImageId). Animate ({opacity: 1.0}, 500) Function () {}) });}); $('#'+ otherPlayerImageId) .animate ({opacity: 0.25}, 1500, function () {});}

Force control bar

A good snooker player can grasp the strength of each shot very well. Different skills require different ways of hitting the ball: directly, indirectly, or using corners, and so on. Thousands of possible paths can be constructed by the combination of different directions and different forces. Fortunately, the game provides a very beautiful strength control bar to help players adjust their clubs before hitting the ball.

To achieve this, we use HTML5's meter element tag, which measures distances. The meter tag is best used when you know the minimum and maximum values for this measurement. In our example, the value is between 0 and 100, because IE9 does not support meter, so I use a background image instead, and the effect is the same.

# strengthBar {position: absolute; margin:375px 00139px; width: 150px; color: lime; background-color: orange; z-index: 5;}

When you click on the strength bar, you actually choose a new strength. You may not be very skilled at first, but in the real world, it takes time to train your abilities. The code for clicking the strength bar is as follows:

$('# strengthBar') .click (function (e) {var left = $('# strengthBar'). Css ('margin-left'). Replace (' px','); var x = e.pageX-left; strength = (x / 150.0); $('# strengthBar') .val (strength * 100);})

In the picture frame of the current player, you will notice that there is a small ball. I call it "ball on", which is the ball that the current player should hit within the specified time. If the ball disappears, the player will lose four points. Similarly, if the player's first hit is not the ball shown in the box, he will also lose 4 points.

This "ball on" directly overlays the canvas element on the user's avatar, so the ball you see in the avatar looks like it has an img element on top of the standard div, but the ball is not implemented by img. Of course, we can't draw arcs and lines directly on div, which is why I want to overlay canvas on my profile picture. Look at the code:

Var player1BallOnContext = player1BallOnCanvas.getContext ('2d'); var player2BallOnContext = player2BallOnCanvas.getContext (' 2d'); . . Function renderBallOn () {player1BallOnContext.clearRect (0,0500,500); player2BallOnContext.clearRect (0,0500,500); if (playingTeamID = = 1) {if (teams [0] .BallOn! = null) drawBall (player1BallOnContext, teams [0] .BallOn, new Vector2D (30,120), 20) } else {if (teams [1] .BallOn! = null) drawBall (player2BallOnContext, teams [1] .BallOn, new Vector2D (30,120), 20); player1BallOnContext.clearRect (0,0,133,70);}}

Rotate the electric fan on the roof

In this game, this fan is just for fun. Then why is there an electric fan here? Well, the name of the game is HTML5 Snooker Club, put an electric fan to have the atmosphere of the club, of course, I also want to show how to achieve the rotation of CSS3.

This is very simple: first we need an electric fan image in PNG format. It's just that we didn't use the picture of the fan itself, we used his projection. By showing the projection of the fan on the table, let us feel that it is spinning on the roof, thus achieving our goal:

# roofFan {position:absolute; left: 600px; top:-100px; width: 500px; height: 500px; border: 2px solid transparent; background-image: url ('/ Content/Images/roofFan.png'); background-size: 100%; opacity: 0.3; z-index: 2;}. . .

In order to get a more realistic atmosphere, I smoothed the fan picture with Paint.Net software, and now you can no longer see the edge of the fan. I think this is the easiest way to achieve such a cool effect.

In addition to using this image processing trick, we only use a normal div element with a background image, which is nothing special. Now that we've got the picture of the fan, we're going to let it start spinning. Here we use the rotate property of CSS3 to do all this.

Club animation

Club animation is not necessary for the game, but it does add a lot of fun to it. When you start to move around the table with the mouse, you will notice that the club is indeed following your mouse. This means that the club will always follow the movement of the mouse, as real as if you are there. Because the competitor can only aim with his eyes, this effect will also be helpful to the contestant.

The club is a single PNG picture, the picture itself is not shown directly in the form of img, nor in the form of background, on the contrary, it is shown directly on a special canvas. Of course, we can also use div and css3 to achieve the same effect, but I think this will better explain how to show the image on canvas.

First, the canvas element occupies almost the entire width of the page. Note that this particular canvas has a large z-index value so that the club can always be on top of each ball without being covered by the ball. When you move the mouse on the table, the target point will be updated in real time, and the club picture will be changed twice: first, calculate the position of the cue ball, and then flip the cue around the cue ball. Through these two steps, we get the mouse point and the center of the cue ball.

# cue {position:absolute;}. . . If (drawingtopCanvas.getContext) {var cueContext = drawingtopCanvas.getContext ('2d');}. . . Var cueCenter = [15,-4]; var cue = new Image; cue.src =''; var shadowCue = new Image; shadowCue.src =''; cueContext.clearRect (0,0, topCanvasWidth, topCanvasHeight); if (isReady) {cueContext.save (); cueContext.translate (cueBall.position.x + 351, cueBall.position.y + 145); cueContext.rotate (shadowRotationAngle-Math.PI / 2) CueContext.drawImage (shadowCue, cueCenter [0] + cueDistance, cueCenter [1]); cueContext.restore (); cueContext.save (); cueContext.translate (cueBall.position.x + 351, cueBall.position.y + 140); cueContext.rotate (angle-Math.PI / 2); cueContext.drawImage (cue, cueCenter [0] + cueDistance, cueCenter [1]); cueContext.restore ();}

In order to make the club more realistic, we add a projection to the club, and we deliberately make the rotation angle of the club projection different from the angle of the club, we do this in order to make the club have a 3D effect. The end result is really cool.

Push-pull club

This club animation mimics real human characteristics: have you ever seen snooker players push and pull clubs when aiming? We achieve this effect by changing the distance between the cue ball and the cue through HTML5. When one pole is reached, the club is pulled back, and then when it reaches another pole, it is pushed forward. Over and over again, until the player stops moving the mouse.

Var cueDistance = 0; var cuePulling = true;. . . Function render () {. . . If (cuePulling) {if (lastMouseX = = mouseX | | lastMouseY = = mouseY) {cueDistance + = 1;} else {cuePulling = false; getMouseXY () }} else {cueDistance-= 1;} if (cueDistance > 40) {cueDistance = 40; cuePulling = false;} else if (cueDistance

< 0) { cueDistance = 0; cuePulling = true; } . . . 显示目标路径 当选手移动鼠标时,我们会在母球和当前鼠标点之间画一条虚线。这对选手们长距离瞄准相当的便利。 这条目标路径只有在等待用户击球时才会显示: if (!cueBall.pocketIndex) { context.strokeStyle = '#888'; context.lineWidth = 4; context.lineCap = 'round'; context.beginPath(); //here we draw the line context.dashedLine(cueBall.position.x, cueBall.position.y, targetX, targetY); context.closePath(); context.stroke(); } 需要注意的是在HTML5 canvas中并没有内置函数来画虚线。幸运的是有一个叫phrogz的家伙在StackOverflow网站上发布了一个关于这个画虚线的帖子: //function kindly provided by phrogz at: //http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas var CP = window.CanvasRenderingContext2D && CanvasRenderingContext2D.prototype; if (CP && CP.lineTo) { CP.dashedLine = function (x, y, x2, y2, dashArray) { if (!dashArray) dashArray = [10, 5]; var dashCount = dashArray.length; this.moveTo(x, y); var dx = (x2 - x), dy = (y2 - y); var slope = dy / dx; var distRemaining = Math.sqrt(dx * dx + dy * dy); var dashIndex = 0, draw = true; while (distRemaining >

) {var dashLength = dashArray [dashIndex++% dashCount]; if (dashLength > distRemaining) dashLength = distRemaining; var xStep = Math.sqrt (dashLength * dashLength / (1 + slope * slope)); var signal = (x2 > x? 1:-1); x + xStep * signal; y + = slope * xStep * signal; this [draw? 'lineTo':' moveTo'] (x, y); distRemaining-= dashLength; draw =! draw;}

Show tracking path

When the player hits the cue ball, the cue ball leaves a tracking line on the table to indicate the location of its last point.

Creating this trace path is a little more complex than the target path mentioned earlier. First I have to instantiate a Queue object, and the Queue object prototype in this project is provided by Stephen Morley.

Var tracingQueue = new Queue ()

Once the ball starts to move, we press the real-time position of the cue ball into the Queue:

If (renderStep% 2 = = 0) {draw (); enqueuePosition (new Vector2D (cueBall.position.x, cueBall.position.y));}

The enqueuePosition function ensures that we only save the location of the first 20 points, which is why we only show the path of the nearest cue ball.

Function enqueuePosition (position) {tracingQueue.enqueue (position); var len = tracingQueue.getLength (); if (len > 20) {tracingQueue.dequeue ();}}

Next, we will traverse the data in Queue to create this trace path:

/ / drawing the tracing line var lastPosX = cueBall.position.x; var lastPosY = cueBall.position.y; var arr = tracingQueue.getArray (); if (! cueBall.pocketIndex) {context.strokeStyle ='# 363; context.lineWidth = 8; context.lineCap = 'round'; context.beginPath (); var I = arr.length; while (--I >-1) {var posX = ARR [I] .x Var posY = arr [I] .y; context.dashedLine (lastPosX, lastPosY, posX, posY, [10 posY; 200helm 10 dagger 20]); lastPosX = posX; lastPosY = posY;} context.closePath (); context.stroke ();}

Draw a small ball

The balls and their projections are presented on a special canvas (below the club canvas).

When presenting the ball, we first have to present its projection, which is mainly to simulate the 3D environment. Every ball must have a projection, and our projection position for each ball will be slightly different, which indicates that the ball is projected in different directions and the position of the light source.

Each ball is drawn by a common function, which has two parameters: 1) canvas context;2) the ball object. The function first draws a complete arc and then linearly fills the arc according to the color provided by the ball object.

Each ball object has three colors: light, medium, and dark, which are used to create linear gradients, as do 3D effects.

Function drawBall (context, ball, newPosition, newSize) {var position = ball.position; var size = ball.size; if (newPosition! = null) position = newPosition; if (newSize! = null) size = newSize; / / main circle context.beginPath (); context.fillStyle = ball.color; context.arc (position.x, position.y, size, 0, Math.PI * 2, true) Var gradient = context.createRadialGradient (position.x-size / 2, position.y-size / 2,0, position.x, position.y, size); / / bright spot gradient.addColorStop (0, ball.color); gradient.addColorStop (1, ball.darkColor); context.fillStyle = gradient; context.fill (); context.closePath (); context.beginPath () Context.arc (position.x, position.y, size * 0.85,270,270,200, true); context.lineTo (ball.x, ball.y); var gradient = context.createRadialGradient (position.x-size * .5, position.y-size * .5,0, position.x, position.y, size) Gradient.addColorStop (0, ball.lightColor); gradient.addColorStop (0.5, 'transparent'); context.fillStyle = gradient; context.fill ();} function drawBallShadow (context, ball) {/ / main circle context.beginPath () Context.arc (ball.position.x + ball.size * .25, ball.position.y + ball.size * .25, ball.size * 2,0, Math.PI * 2, true) Try {var gradient = context.createRadialGradient (ball.position.x + ball.size * .25, ball.position.y + ball.size * .25,0, ball.position.x + ball.size * .25, ball.position.y + ball.size * .25, ball.size * 1.5);} catch (err) {alert (err) Alert (ball.position.x +','+ ball.position.y);} gradient.addColorStop (0,'# 000000'); gradient.addColorStop (1, 'transparent'); context.fillStyle = gradient; context.fill (); context.closePath ();}

Detect collisions between balls

The ball is presented on the canvas in a fast and continuous manner: first, we empty the canvas, then draw the projection on it, then draw the ball, and finally update the position coordinates of the ball, over and over again. In the meantime, we need to check whether the ball collides with another ball, and we do this through collision detection of the ball.

Function isColliding (ball1, ball2) {if (ball1.pocketIndex = = null & & ball2.pocketIndex = = null) {var xd = (ball1.position.x-ball2.position.x); var yd = (ball1.position.y-ball2.position.y); var sumRadius = ball1.size + ball2.size; var sqrRadius = sumRadius * sumRadius; var distSqr = (xd * xd) + (yd * yd) If (Math.round (distSqr) 0) / / return; / / collision impulse var i = (- 0.08) * vn) / (im1 + im2); var impulse = mtd.multiply (0.5); var totalImpulse = Math.abs (impulse.x) + Math.abs (impulse.y); / / Do some collision audio effects here... / / change in momentum if (! ball1.isFixed) ball1ball1.velocity = ball1.velocity.add (impulse.multiply (im1)); if (! ball2.isFixed) ball2ball2.velocity = ball2.velocity.subtract (impulse.multiply (im2));}

Detect the collision between the ball and the corner

At first glance, it seems a little complicated to detect the collision between the ball and the corner, but fortunately there is a very simple but effective way to solve this problem: because the corner is also a circular element, we can think of them as fixed balls. if we can correctly determine the size and position of the fixed ball, then we solve the collision problem between the ball and the corner as we deal with the collision between the balls. In fact, we can do this with the same function, the only difference is that these corners are fixed.

The following picture assumes that there are small balls around the corner, and that's what it would look like:

Analyze the collision between the ball and the corner

As mentioned above, the only difference between the collision between balls and the collision between balls and corners is the latter. We want to make sure that it remains fixed. The code is as follows:

Function resolveCollision (ball1, ball2) {. . . / / push-pull them apart based off their mass if (! ball1.isFixed) ball1ball1.position = ball1.position.add ((mtd.multiply (im1 / (im1 + im2); if (! ball2.isFixed) ball2ball2.position = ball2.position.subtract (mtd.multiply (im2 / (im1 + im2)); . . / / change in momentum if (! ball1.isFixed) ball1ball1.velocity = ball1.velocity.add (impulse.multiply (im1)); if (! ball2.isFixed) ball2ball2.velocity = ball2.velocity.subtract (impulse.multiply (im2));}

Detect the collision between the ball and the edge of the rectangle

We use the collision detection between the ball and the edge of the rectangle to know whether the ball has reached the upper and lower left and right edges of the table. The way of detection is very simple: each ball needs to detect four points: we calculate these points by adding and subtracting the x and y coordinates of the ball. Then compare them with our defined rectangular range of the table to see if they are within this range.

Analyze the collision between the ball and the edge of the rectangle

The picture above is from Wikipedia.

It is much easier to deal with the collision between a ball and the edge of a rectangle than between balls. We need to find the closest point to the center point of the ball on the rectangular boundary. If this point is within the radius of the ball, it means the collision.

Play audio

No game is silent, and different platforms deal with audio in different ways. Fortunately, HTML5 provides us with an audio tag, which simplifies our work of defining audio files, loading audio, and adjusting volume.

The general HTML5 example is to show you the standard usage of audio, which is to show a playback control bar. In this game, we use different methods and hide the audio playback control bar. This makes sense because audio playback is not directly controlled by the user, but is triggered by events in the game.

There are a total of eight audio tags on the page, of which six are the sound of a ball bumping, one is the sound of hitting, and the other is the sound of a ball falling into a bag. These sounds can be played at the same time, so we don't have to worry about concurrency.

When the player shoots the cue ball, we play the audio of the hitting sound corresponding to the volume according to the strength selected by the user.

$('# topCanvas') .click (function (e) {. . . AudioShot.volume = strength / 100.0; audioShot.play ();. . . });

When one ball touches another, we calculate the intensity of the collision and choose the audio tag with the appropriate volume to play.

Function resolveCollision (ball1, ball2) {. . . Var totalImpulse = Math.abs (impulse.x) + Math.abs (impulse.y); var audioHit; var volume = 1.0; if (totalImpulse > 5) {audioHit = audioHit06; volume = totalImpulse / 60.0;} else if (totalImpulse > 4) {audioHit = audioHit05; volume = totalImpulse / 12.0 } else if (totalImpulse > 3) {audioHit = audioHit04; volume = totalImpulse / 8.0;} else if (totalImpulse > 2) {audioHit = audioHit03; volume = totalImpulse / 5.0;} else {audioHit = audioHit02; volume = totalImpulse / 5.0 } if (audioHit! = null) {if (volume > 1) volume = 1.0; / / audioHit.volume = volume; audioHit.play ();}. . . }

Finally, when the ball falls into the bag, we play the file "fall.mp3":

Function pocketCheck () {for (var ballIndex = 0; ballIndex)

< balls.length; ballIndex++) { var ball = balls[ballIndex]; for (var pocketIndex = 0; pocketIndex < pockets.length; pocketIndex++) { . . some code here... . if (Math.round(distSqr) < Math.round(sqrRadius)) { if (ball.pocketIndex == null) { ball.velocity = new Vector2D(0, 0); ball.pocketIndex = pocketIndex; pottedBalls[pottedBalls.length] = ball; if (audioFall != null) audioFall.play(); } } } } } 本地存储游戏状态 有时候我们叫它web存储或者DOM存储,本地存储HTML5定义的一种机制,用来保持本地数据。文章开头提到的那几种浏览器原生就支持本地存储,所以我们不需要使用额外的js框架。 我们使用本地存储主要用来保存用户的游戏状态。简而言之,我们是要允许用户在开始游戏一段时间后,关闭浏览器,第二天打开还能继续往下玩。 当游戏开始后,我们需要检索在本地是否有数据存储着,有的话就加载它们: jQuery(document).ready(function () { ... retrieveGameState(); ... 另一方面,游戏开始后我们需要对每一次射击的数据进行保存。 function render() { ... processFallenBalls(); saveGameState(); ... } 本地存储是由一个字符串字典实现的。这个简单的结构体接受传入的字符串和数字。我们只需要用setItem来将数据存储到本地。下面的代码说明了我们是如存储时间数据,小球位置坐标数据,选手数据和当前击球选手与等待击球选手的id: function saveGameState() { //we use this to check whether the browser supports local storage if (Modernizr.localstorage) { localStorage["lastGameSaveDate"] = new Date(); lastGameSaveDate = localStorage["lastGameSaveDate"]; localStorage.setItem("balls", $.toJSON(balls)); localStorage.setItem("teams", $.toJSON(teams)); localStorage.setItem("playingTeamID", playingTeamID); localStorage.setItem("awaitingTeamID", awaitingTeamID); } } 我觉得除了下面的部分,上面的代码都已经解释了自己的作用了: localStorage.setItem("balls", $.toJSON(balls)); localStorage.setItem("teams", $.toJSON(teams)); 目前为止,本地存储还不能工作,我们需要将它们字符化,上面的2行代码是利用了jquery的toJSON方法将复杂的对象转换成了json字符串。 [{"isFixed":false,"color":"#ff0000","lightColor":"#ffffff","darkColor":"#400000","bounce":0.5, "velocity":{"x":0,"y":0},"size":10,"position":{"x":190,"y":150},"pocketIndex":null,"points":1, "initPosition":{"x":190,"y":150},"id":0},{"isFixed":false,"color":"#ff0000","lightColor":"#ffffff", "darkColor":"#400000","bounce":0.5,"velocity":{"x":0,"y":0},"size":10,"position":{"x":172,"y":138}, "pocketIndex":null,"points":1,"initPosition":{"x":172,"y":138},"id":1},........ 一旦我们将这些对象序列化到本地存储后,我们就可以用类似的方法将它们检索出来,我们现在就是用getItem方法来检索他们。 function retrieveGameState() { //we use this to check whether the browser supports local storage if (Modernizr.localstorage) { lastGameSaveDate = localStorage["lastGameSaveDate"]; if (lastGameSaveDate) { var jsonBalls = $.evalJSON(localStorage.getItem("balls")); balls = []; var ballsOnTable = 0; for (var i = 0; i < jsonBalls.length; i++) { var jsonBall = jsonBalls[i]; var ball = {}; ball.position = new Vector2D(jsonBall.position.x, jsonBall.position.y); ball.velocity = new Vector2D(0, 0); ball.isFixed = jsonBall.isFixed; ball.color = jsonBall.color; ball.lightColor = jsonBall.lightColor; ball.darkColor = jsonBall.darkColor; ball.bounce = jsonBall.bounce; ball.size = jsonBall.size; ball.pocketIndex = jsonBall.pocketIndex; ball.points = jsonBall.points; ball.initPosition = jsonBall.initPosition; ball.id = jsonBall.id; balls[balls.length] = ball; if (ball.points >

0 & & ball.pocketIndex = = null) {ballsOnTable++;}} / / if there is no more balls on the table, clear local storage / / and reload the game if (ballsOnTable = = 0) {localStorage.clear (); _ window.location.reload () } var jsonTeams = $.evalJSON (localStorage.getItem ("teams")); teams = jsonTeams; if (jsonTeams [0] .BallOn) teams [0] .BallOn = balls [jsonTeams [0] .BallOn.id]; if (jsonTeams [1] .BallOn) teams [1] .BallOn = balls [jsonTeams [1] .BallOn.id] PlayingTeamID = localStorage.getItem ("playingTeamID"); awaitingTeamID = localStorage.getItem ("awaitingTeamID");}}

There is no doubt that HTML5 will completely change the world of web. This reform is under way, and I hope this article will invite you to join the revolution, where we see Canvas,CSS3, audio and local storage in HTML5. Although the snooker game looks complex, it becomes very simple after using HTML5 technology. I never thought it would have such a good effect.

This is the answer to the question about how to build a snooker billiard club with HTML 5. I hope the above content can be of some help to you. If you still have a lot of doubts to be solved, you can follow the industry information channel for more related knowledge.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report