网络斗地主游戏的完整设计与实现(二)系统的核心技术路线

引言

在前面的文章《网络斗地主游戏的完整设计与实现(一)项目的基本结构》介绍了项目的整体结构。接下来说明一下系统中用到的核心技术路线
项目的源码可在CSDN资源中下载

游戏界面的呈现

斗地主游戏的玩家分成三个,而且在未叫牌与叫牌后玩家的角色会发生变化,因此要用不同的图片加以呈现。本项目没有使用cocos2d之类的游戏框架,而是使用基本的javascrpt+jquery实现游戏界面。

具体对这个项目来说,主要的游戏界面分为几大类:
1.背景类
这个项目中背景基本上保持不变,所以只要在网页上显示一副较大的背景图片就可以了,如下图所示
网络斗地主游戏的完整设计与实现(二)系统的核心技术路线_第1张图片
在背景图上的一些位置预留了空白,用于显示相应的文本。

  1. 人物图像类
    这里主要显示两类角色,“地主”与“农民”,随着游戏状态的变化,人物的形象也有可能发生变化。但基本的人物形象如下图所示:
    网络斗地主游戏的完整设计与实现(二)系统的核心技术路线_第2张图片
    网络斗地主游戏的完整设计与实现(二)系统的核心技术路线_第3张图片
    与背景图片不同之处在于,人物图像需要显示在某个合适的位置,所以要有办法移动图片显示的位置。这一点可以通在将图片用DIV标签包裹起来,然后动态地设置DIV的位置来实现。
    由于原生的javascript不直接支持class的定义,所以用function的方式包装了图片的显示功能
    相应的代码如下:
    ImageDiv.js

//图象DIV
function ImageDiv(imgFileName,tagValue)
{    
	this.Name="ImageDiv";
	this.value=tagValue;
		
	this.imgFileName=imgFileName;
	this.x=0;
	this.y=0;
	this.z=0;	
	this.visib=false
	
	this.Div=document.createElement("div");
	this.Div.style.position='absolute';	
	this.Div.name=this.Name;
	this.Div.style.width='74px';
    this.Div.style.height='98px';
	
	//this.Div.style.backgroundColor='#ffffff';
	this.Div.style.visibility='hidden';
	
	if(imgFileName!="")
	    this.Div.innerHTML="";
	
	document.body.appendChild(this.Div);
		
	this.GetDiv=function()
	{
		return this.Div;
	}
	
	this.GetValue=function()
	{
		return this.value;
	}
	
	this.GetX=function()
	{
		return this.x;
	}
	
	this.GetY=function()
	{
		return this.y;
	}
	
	this.GetZ=function()
	{
		return this.z;
	}
	
	
	this.SetClass=function(Classf)
	{
	    this.Div.style.width=null;
	    this.Div.style.height=null;
	    this.Div.className=Classf;
	}
	
	
	this.SetId=function(Id)
	{
	    this.Div.id=Id;
	}
	
	this.SetW=function(value)
	{
	    this.Div.style.width=value+'px';
	}
	
	this.SetH=function(value)
	{
	    this.Div.style.height=value+'px';
	}
	
	this.SetX=function(value)
	{
	     this.Div.style.left=value+'px';
	     this.x=value;
	}
	
	this.SetY=function(value)
	{
	     this.Div.style.top=value+'px';
	     this.y=value;
	     Y=value;
	    
	}
	
	this.SetZ=function(zValue)
	{
	     this.Div.style.zIndex=zValue;
	     this.z=zValue;
	}
		
	this.SetXY=function(nx,ny)
	{
		this.Div.style.left=nx+'px';
		this.x=nx;
		this.Div.style.top=ny+'px';
		this.y=ny;	
	}
	
	this.SetV=function(bVisible)
	{
		if(bVisible)
		{
			this.Div.style.visibility='visible';
			
		}
		else
		{
			this.Div.style.visibility='hidden';
			
		}
	}
	
	this.SetImg=function(imgurl)
	{ 	   
		this.Div.innerHTML="";
		this.imgFileName=imgurl;
	}
	
	this.SetHtml=function(Html)
	{
		this.Div.innerHTML=Html;
	}
	
	this.remove=function()
	{
		document.body.removeChild(this.Div);
		
	}
		
}

其中的imgFileName指明要显示的图片文件,而SetX,SetY方法设置了图片显示的位置,SetZ方法设置叠放次序。

3.扑克牌图像类
由于扑克牌图像有时需要显示一张,有时需要显示一组,所以用CardDiv.js与CardGroupDiv.js进行包装。而且扑克牌又分为水平显示与重直显示两种情形,所以又分别用CardHorizonGrpDiv.js与CardVerticalGrpDiv.js进行包装。相应的源码可以将完整的项目下载后进行查看。

4.文字类
需要在指定的位置动态显示文本块,用TextDiv.js与TextGroupDiv.js进行包装。与显示图像类似的是要可以动态地设置文本块的位置。

游戏状态的刷新

为了能够及时地刷新游戏的状态,需求前端与后台服务器进行通信。由于浏览器与服务器间的通信过程是请求、应答式的。一旦服务上的状态发生了变化,该如何及时地通知前端呢?理论是有两种解决方案
1,由服务器推送消息给客户端
2,由客户端连续不断地向服务器进行查询,也就是轮询。
本项目采用轮询的方式,客户端每秒向服务器发起一次请求,检查是否有新的状态需要更新。与此同时,每秒发出一次请求,也做为心跳请求,如果服务器发现客户端长期没有心跳,就会判断客户端已经离线。

由存储过程实现后台业务逻辑

数据库表只能保存静态数据,如果要想实现后台的业务逻辑,必须安排在某处执行相关的代码。一般来说这种后台业务逻辑缓组成一个业务逻辑层。这层代码可以由jsp,serverlet,php,asp等等服务器脚本技术来实现。

本项目将业务逻辑交由数据库的存储过程来实现。为此设计了一个调用其它存储过程的入口存储过程。

CREATE      PROCEDURE dbo.callProc
	@procName varchar(100) ,
	@inStr varchar(200) ,
	@outStr varchar(4000) output
as
set nocount on
begin
	declare @SQLString nvarchar(500)
	declare @ParmDefinition nvarchar(500)
	declare @outPara varchar(4000)

	if rtrim(ltrim(@inStr)) <>''
	begin
		set @inStr = @inStr + ','
	end
	
	set @SQLString = N'exec '+ @procName + ' '+@inStr+ '@outPara out'
	set @ParmDefinition = N'@outPara varchar(4000) OUTPUT'	
	
	EXECUTE sp_executesql @SQLString, @ParmDefinition, @outPara=@outStr output
	return 0
end

这样一来,就可以极大地简化后台脚本代码。下面是调用这个入口存储过程的php代码
proc.php

  

    // 测试用url http://localhost:8080/poker/proc.php?proc=addPlayer&inParas=t1,t1

    require_once 'conf/db.config.php';
   
    handleRequest();

    function handleRequest(){

        //接收网页参数
        $procName=trim($_REQUEST["proc"]);
        $inStr=trim($_REQUEST["inParas"]);
        
        if ($procName==""){
            echo "";
            return;
        }

        try{
            $db = new PDO( "sqlsrv:Server=".DATABASE_SERVER.";Database=".DATABASE_NAME, DATABASE_USER, DATABASE_PWD);   

        }catch (Exception $e) {
            $json = ['msg'=>$e->getMessage(),'error'=>-1];
            echo json_encode($json);
            return;
            
        }

        try{
            $res = execStoreProc($db,$procName,$inStr);
        }catch (Exception $e) {
            $json = ['msg'=>$e->getMessage(),'error'=>-1];
            echo json_encode($json);
            return;
        } 
        
        echo $res;
    }     

    //执行存储过程,返回输出参数
    function execStoreProc($db,$procName,$inStr)
    {
        $sql="exec callproc ?,?,?";
        $stmt = $db->prepare($sql, array($db::ATTR_CURSOR=>$db::CURSOR_SCROLL)); 

        // 绑定入参
        $stmt->bindParam(1, $procName, $db::PARAM_STR);
        $stmt->bindParam(2, $inStr, $db::PARAM_STR);
 
        // 绑定出参
        $result ='';        
        $stmt->bindParam(3, $result, $db::PARAM_STR | $db::PARAM_INPUT_OUTPUT, 4000);
        $stmt->execute();
        return $result;
    } 

为了在javascript代码中调用存储过程,再用js函数包装一下:
proc.js

//调用存储过程
function callProc(procName,inputStr,callBackFunc)
{    
    $.post
    (
        "proc.php","proc="+procName+"&inParas=" + inputStr ,callBackFunc
    );       
}

这样一来,在javascript中就通过调用函数callProc,实现了调用数据库的存储过程。

你可能感兴趣的:(前端开发,游戏开发,斗地主,源码,javascript,存储过程,php)