【整理】HTML5游戏开发学习笔记(1)-骰子游戏

《HTML5游戏开发》,该书出版于2011年,似乎有些老,可对于我这样没有开发过游戏的人来说,却比较有吸引力,选择自己感兴趣的方向来学习html5,css3,相信会事半功倍。不过值得注意的是,该书的游戏是些小的游戏,内容相对比较基础,而且html5标准已经正式发布,可能会和书中所描述有少许出处。当然了,书中的小游戏还是比较不错的,适合我这样的前端开发不咋地的来练手,学习方式是在以自己的思路实现之后,再来看书中的实现思路,因为每个人有自己的开发习惯。

1.预备知识
在做第一个骰子游戏开发前,必须知道在html5中,如何绘制矩形和圆形

			/*获取2d绘图上下文
			var ctx = document.getElementById(‘diceCanvas‘).getContext(‘2d‘)
			*/

			/*绘制矩形
			ctx.lineWidth = 1
			ctx.strokeStyle = ‘#000‘
			ctx.strokeRect(100,50,100,100)

			ctx.fillStyle = ‘#f00‘
			ctx.fillRect(100,50,100,100)
			*/

			/*绘制圆形或弧形.关闭路径,如果不关闭,这绘制的是不闭合的半圆
			ctx.lineWidth = 1
			ctx.strokeStyle = ‘#000‘
			ctx.beginPath()
			ctx.arc(200,200,50,0,2*Math.PI*90/360,false)
			ctx.closePath()
			ctx.stroke()
			*/

2.实现思路
设计和思考整个游戏中涉及的对象,包括骰子和游戏玩法。
为了简化在绘制每个圆点的时候对坐标的定位计算,我选择九宫格的布局,所以增加了个九宫格坐标对象

3.代码

/*九宫格坐标图*/
			function NineBlockBoxMap(squareSize){
				var size = squareSize/3,
						maps = [[],[],[]],
						x,y,
						n = 3

				for(x=0; x<n; x++){
					for(y=0; y<n; y++){
						maps[x][y] = {x : x*size + size/2, y : y*size + size/2}
						//alert(maps[x][y].x+‘|‘+maps[x][y].y)
					}
				}

				this.maps = maps
			}

			NineBlockBoxMap.prototype.locate = function(x,y,offsetX,offsetY){
				var map = this.maps[x][y]
				return {x:map.x+offsetX,y:map.y+offsetY}
			}

			/*骰子*/
			function Dice(){

				var opts,
						ctx,
						maps

				function clearCanvas(){
					//WARNNING : 不能清除整个Canvas画布,而是要清除当前骰子尺寸的部分画布,因为整个画布有多个骰子
					//ctx.clearRect(0,0,opts.canvasWidth,opts.canvasHeight)
					ctx.clearRect(opts.diceX,opts.diceY,opts.diceWidth+2*opts.diceLineWidth,opts.diceHeight+2*opts.diceLineWidth)
				}

				function dotRandom(){
					return Math.floor(Math.random()*6+1)
				}

				function drawDots(num){		

					var doDraw = function(points){
						var point,i

						for(i=0; i<points.length; i++){
							point = points[i]

							ctx.beginPath()
							ctx.arc(point.x,point.y,opts.dotRadius,0,Math.PI*2,false)
							ctx.closePath()
							ctx.fill()
						}
					}

					var points = []

					//根据1-6的骰子点数在九宫格图中绘制1-6个圆点
					switch(num){
						case 1 :
						  points.push(maps.locate(1,1,opts.diceX,opts.diceY))
							break
						case 2 :
							points.push(maps.locate(0,1,opts.diceX,opts.diceY))
							points.push(maps.locate(2,1,opts.diceX,opts.diceY))
							break
						case 3 :
							points.push(maps.locate(2,0,opts.diceX,opts.diceY))
							points.push(maps.locate(1,1,opts.diceX,opts.diceY))
							points.push(maps.locate(0,2,opts.diceX,opts.diceY))
							break
						case 4 :
							points.push(maps.locate(0,0,opts.diceX,opts.diceY))
							points.push(maps.locate(0,2,opts.diceX,opts.diceY))
							points.push(maps.locate(2,0,opts.diceX,opts.diceY))
							points.push(maps.locate(2,2,opts.diceX,opts.diceY))
							break
						case 5 :
							points.push(maps.locate(0,0,opts.diceX,opts.diceY))
							points.push(maps.locate(0,2,opts.diceX,opts.diceY))
							points.push(maps.locate(1,1,opts.diceX,opts.diceY))
							points.push(maps.locate(2,0,opts.diceX,opts.diceY))
							points.push(maps.locate(2,2,opts.diceX,opts.diceY))
							break
						case 6 :
							points.push(maps.locate(0,0,opts.diceX,opts.diceY))
							points.push(maps.locate(0,2,opts.diceX,opts.diceY))
							points.push(maps.locate(0,1,opts.diceX,opts.diceY))
							points.push(maps.locate(2,1,opts.diceX,opts.diceY))
							points.push(maps.locate(2,0,opts.diceX,opts.diceY))
							points.push(maps.locate(2,2,opts.diceX,opts.diceY))
							break
						default :
							alert(num + ‘ num must be 1~6‘)
							break
					}

					ctx.fillStyle = opts.dotFillStyle
					doDraw(points)
				}

				function drawDice(){
					//绘制骰子矩形
					ctx.lineWidth = opts.diceLineWidth
					ctx.strokeStyle = opts.diceStrokeStyle
					ctx.strokeRect(opts.diceX,opts.diceY,opts.diceWidth,opts.diceHeight)

					//绘制骰子上的圆点
					var num = dotRandom()
					drawDots(num)

					return num
				}

				function extend(opt1,opt2){
					var name

					opt1 = opt1||{}
					opt2 = opt2||{}

					for(name in opt2){
						opt1[name] = opt1[name]||opt2[name]
					}

					return opt1
				}

				return {

					init : function(options){
						opts = extend(options,{
							canvasId : ‘diceCanvas‘,
							canvasWidth : 400,
							canvasHeight : 400,
							diceWidth : 90,
							diceHeight : 90,
							diceX : 50,
							diceY : 50,
							diceLineWidth : 5,
							diceStrokeStyle : ‘#000‘,
							dotFillStyle : ‘#000‘,
							dotRadius : 10
						})

						var canvas = document.getElementById(opts.canvasId)

						if(canvas==null||canvas.tagName !== ‘CANVAS‘){
							alert(‘element must be canvas tag.‘)
							return
						}

						ctx = canvas.getContext(‘2d‘)
						maps = new NineBlockBoxMap(opts.diceWidth)

						return this
					},

					throwDice : function(onThrow){
						//清除当前骰子的绘图区域
						clearCanvas()

						var num = drawDice()

						if(typeof onThrow === ‘function‘){
							onThrow(num)
						}

						return this
					}

				}
			}//end-Dice

			/*游戏规则
				2个骰子之和(2-12)
				第一次(7,11) 胜
				第一次(2,3,12 )输
				第一次 (4,5,6,8,9,10),继续 (第二次(7)输,如果正好和之前相同的点数则 胜,否则继续)
			*/
			var GameResult = {Lose:-1,Unknown:0,Win:1}

			var rule = function GameRule(){
				var throwCount = 0
				var continual = false
				var previousSum = 0

				return {

					getResult : function(sum){
						var result = GameResult.Unknown,
								sum = parseInt(sum)

						throwCount++

						if( throwCount==1 ){
							if( sum==7||sum==11 ){
								result = GameResult.Win
							}
							else if( sum==2||sum==3||sum==12 ){
								result = GameResult.Lose
							}
						}
						else if(throwCount>1 && continual){
							if(throwCount==2&&sum==7){
								result = GameResult.Lose
							}
							else if(sum==previousSum){
								result = GameResult.Win
							}
						}

						previousSum = sum
						continual = ( result==GameResult.Unknown )

						return result
					},

					reset : function(result){
						if(result==GameResult.win||result==GameResult.Lose){
							throwCount = 0
							continual = false
							previousSum = 0
						}
					}

				}
			}()	

			/*app*/
			var throwDiceButton = document.getElementById(‘throwDiceButton‘)
			var dice1TextBox = document.getElementById(‘dice1TextBox‘)
			var dice2TextBox = document.getElementById(‘dice2TextBox‘)
			var resultTextBox = document.getElementById(‘resultTextBox‘)

			var dice1 = new Dice().init()
			var dice2 =new Dice().init({diceX : 200,diceY : 50,})

			throwDiceButton.onclick = function(){

				var result = GameResult.Unknown
						sum = 0

				//投掷骰子1
				dice1.throwDice(function(num){
					dice1TextBox.value = num
					sum += num
				})

				//投掷骰子2
				dice2.throwDice(function(num){
					dice2TextBox.value = num
					sum += num
				})

				result = rule.getResult(sum)
				rule.reset(result)

				if(result==GameResult.Win){
					resultTextBox.value = ‘You Win : ‘ + sum
				}
				else if(result==GameResult.Lose){
					resultTextBox.value = ‘You Lose : ‘ + sum
				}
				else{
					resultTextBox.value = ‘Play again : ‘ + sum
				}
			}

4.优化和完善
精简代码和抽象,增加记录得分,初始一定金额等效功能,使其更像是个赌博游戏。

时间: 2024-08-01 21:48:55

【整理】HTML5游戏开发学习笔记(1)-骰子游戏的相关文章

cocos2dx游戏开发学习笔记3-lua面向对象分析

在lua中,可以通过元表来实现类.对象.继承等.与元表相关的方法有setmetatable().__index.getmetatable().__newindex. 具体什么是元表在这里就不细说了,网上很多介绍,这里主要讲与cocos2dx相关联的部分. 在lua-binding库中extern.lua里,有如下方法: --Create an class. function class(classname, super) local superType = type(super) local c

cocos2dx游戏开发学习笔记1-基本概念

这里主要讲构建整个游戏需要的基本元素,很大部分都摘自cocos2dx官网. 1.Director 导演 导演,顾名思义,就是对整个游戏进行整体控制的. "Director"是一个共享的(单元素集)对象,负责不同场景之间的控制.导演知道当前哪个场景处于活动状态,允许你改变场景,或替换当前的场景,或推出一个新场景.当你往场景堆中推出一个新场景时,"Director"会暂停当前场景,但会记住这个场景.之后场景堆中最顶层的场景跳离时,该场景又会继续活跃.此外"Di

cocos2dx游戏开发学习笔记2-从helloworld开始

一.新建工程 具体安装和新建工程的方法在cocos2dx目录下的README.md文件中已经有详细说明,这里只做简单介绍. 1.上官网下载cocos2dx-3.0的源码,http://www.cocos2d-x.org/ 2.安装python2.7 3.运行setup.py安装 4.执行cocos new helloworld -p helloworld -l cpp,生成新工程 二.新建工程中包含的东西 -Classes AppDelegate.cpp      -----游戏真正开始执行的地

[Android游戏开发学习笔记]View和SurfaceView

本文为阅读http://blog.csdn.net/xiaominghimi/article/details/6089594的笔记. 在Android游戏中充当主要角色的,除了控制类就是显示类.而在Android中涉及到显示的是View类,及继承自它的SurfaceView类和SurfaceView的其他子类等. 这里先只说View和SurfaceView.SurfaceView的直接子类有GLSurfaceView和VideoView,可以看出GL和视频播放以及CAmera摄像头一般均使用Su

[游戏开发-学习笔记]菜鸟慢慢飞(一)

"菜鸟"就是我自己. 分享一下我从零开始学习游戏开发的过程,心得什么的.本篇先扯个开头,说说个人一些乱七八糟的想法. 从0开始 其实,只要有心,不管干哪一行,都不能算从零开始.总会有办法了解到行业的信息.我之前是干船舶电气的,一路过来,最大的感觉是:不怕你找不到资料,就怕你没时间.我要做的是分清楚自己想学什么,怎么样去提高自己,然后沿着自己路线"慢慢"朝前飞.比如:知乎就是个很好的地方,我最早接触游戏开发,是在这里.决定学这个,也是在知乎喝了鸡汤. 游戏开发 对我来

[游戏开发-学习笔记]菜鸟慢慢飞(二)-迷宫

简介:练手Demo,<走出迷宫>,文章主要说说如何创建迷宫. 学习Unity3D有一段时间了,自己想了一个项目来练手手.然后就有了这篇. 一.固定的格数,开局后随机生成. 说明:这个迷宫10*10,开始后随机生成,四周留下一个空做出口. 先说如何实现: 主要准备了三个Prefab:横墙,竖墙,柱子,墙高度是10,宽度是10,厚度是1,柱子高度是10.宽度和厚度都是10. 手动按照10*10排列(参考下图) 脚本 #region //初始化游戏 #endregion using System.C

[游戏开发-学习笔记]菜鸟慢慢飞(四)-Camera

游戏开发中,主相机应该是最重要的GameObject之一,毕竟游戏呈现给玩家,就是通过它. 相机的使用,在不同的游戏中,有很大的不同.这里总结一下自己学到的一些相关知识. 固定位置-游戏过程中相机的Transform属性不改变. 调整好位置后就不要动了,一般使用正交相机,即Camera-Projection选择Orthographic.Unity Manual-Camera 适用:2D游戏.比如飞机大战,消消乐. 游戏开始后,相机追踪某一物体,然后固定不动. 游戏开始后,我们才能确定追踪物体的位

cocos2d-x 3.x游戏开发学习笔记(1)--mac下配置cocos2d-x 3.x开发环境

打开用户文件夹下.bash_profile文件,配置环境 vim ~/.bash_profile //按键i,进行插入编辑(假设输错d进行删除一行) 环境配置过程例如以下: 1.首先配置下android sdk,我的是在opt文件夹下 #sdk export ANDROID_SDK_ROOT=/opt/android-sdk-macosx export PATH=$PATH:$ANDROID_SDK_ROOT export PATH=$PATH:$ANDROID_SDK_ROOT/platfor

【整理】HTML5游戏开发学习笔记(2)- 弹跳球

1.预备知识(1)在画布上绘制外部图片资源(2)梯度(gradient):HTML5中的对象类型,包括线性梯度和径向梯度.如createLinearGradient,绘制梯度需要颜色组http://www.w3school.com.cn/tags/canvas_createlineargradient.asp function test1(){ //在画布上绘制外部图片资源 var ctx = document.getElementById('ballCanvas').getContext('2