HTML5吃豆豆游戏开发实战(四)2d碰撞检测、重构-第二篇

今天下午在家没事,写代码。先总结一下学习HTML5和JS的一些经验,再来说游戏的事吧!

这完全是一个HTML5和JS的入门新手的见解,如果您和我一样是新手的话,欢迎交流,当然,高手如果不介意的话,帮小弟指点一二那就更好啦,谢谢,嘿嘿!入正题吧!

1.语法方面

1.1  JS关于数组的定义方法要注意:

比如:var walls = [new Wall(262,200,100,30),new Wall(662,60,30,400),new Wall(762,300,200,30)];

这是定义一个墙壁对象数组,基本元素是Wall对象,然后是构造函数(坐标,长宽)

更多的关于JS数组定义的可以看这里:JS定义数组以及初始化

1.2  JS定义了一个类,在类的成员变量初始化的时候,似乎不可以调用成员函数来初始化它??

比如:

function Wall(x_,y_,width_,height_)
{
    this.x = x_;
    this.y = y_;
    this.width = width_;
    this.height = height_;
    this.test = this.M();
    /**
     * @return {number}
     */
    this.M = function()
    {
        alert("....");
        return 1;
    };

.....(只是部分代码)

这样就不会看到alert效果,怎么回事呢?恳请各位指点下我初学者。

1.3 注意我写的代码中的注释:

 this.hero = hero_;        //玩家
    this.walls = walls_;      //阻碍物数组
    this.enemys = enemy_;     //敌人数组
    this.isFind = false;      //临时变量,是否找到
    this.tempWall = null;     //临时变量
   // alert("cc");
    this.walls_y = this.walls.slice();  //这里不要写walls_,因为写这个的话,就和this.walls指向一个地方,排序后,walls也变了,终于找到原因,所以我用了复制

函数传参的时候,若传的是对象,则是引用传递,如果是传数值类型,则是值传递。

2. 一点点感想,JS是弱类型语言,var其实用着开始还觉得不习惯,因为以前一直写C,C++,JAVA,C#之类的强类型语言的原因吧,但是后来还是感觉很方便的,因为定义一个变量就是var,数值类型不用自己去考虑,但是这样也会有它的缺点,因为可能存在数据类型的使用是否正确,有没有重复定义、相互覆盖之类的,程序运行前的正确性判断基本靠人了,出错的可能性比较大,这里要注意,尤其是变量名的重复要注意!

3.关于重构的一点点初步认识

好的结构是后面更大的发展的基础,如果架子都不稳,怎么建高楼,所以我觉得重构确实还是很有必要的,尤其是稍微大一点点的,层次结构又模糊的项目,如果需要继续写下去,就最好重构一下。

我个人认为重构的目的就是理清该项目的脉络,使各块代码到正确的位置上,而不是“你中有我,我中有你”

这种混乱不堪的局面,嘿嘿,比喻比喻,把代码模块儿理清楚,哪一部分该做什么,这样自己看得清楚,别人也看得清楚,同时为以后的扩展也打下基础。一个好的结构是很有必要的。

好了,总结完毕,回到游戏中来。

这是目前的工程文件目录截图:

然后说一下完成的碰撞检测吧,其实核心就是坐标的比较,图形都很规范,所以不涉及复杂计算。

当然,具体说一下,当玩家在同一个方向前进时,找到离自己最近的障碍物wallTemp,这就是继续在该方向行走下去一定会碰到的,只寻找一次,找到了把isFind=true。如果改变方向,则重新寻找wallTemp。玩家在某方向移动时,则比较自己和wallTemp之间的距离即可。上下左右都是这样。

全部代码:

1.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>物体移动简单演示</title>
</head>
<!--注意在body这里添加按键响应事件,引号内为函数名-->
<body onkeydown="onGetKey()">
<h1>小球上下移动</h1>
<canvas id="test" width="1200px" height="600px" style="background-color: white"></canvas>
<!--把引用的资源引入本页面-->
<script type="text/javascript" src="Ball.js"></script>
<script type="text/javascript" src="Wall.js"></script>
<script type="text/javascript" src="Collide.js"></script>
<script type="text/javascript" src="GameSys.js"></script>
<script type="text/javascript" src="Control.js"></script>
<script type="text/javascript">
    //1.定义游戏世界原点坐标 窗口宽高
    var Ox = 162;
    var Oy = 0;
    var WinWidth = 900;
    var WinHeight = 500;
    //2.实例化游戏管理类
    var mana = new GameSys(Ox,Oy,WinWidth,WinHeight);
    //3.获取画布
    var can = document.getElementById("test");
    var cxt = can.getContext("2d");
    //4.实例化小球对象
    var ball = new Ball(30 + mana.ox,30,20,3);
    //walls先按x从小到大排序
    //5.
    var walls = [new Wall(262,200,100,30),new Wall(662,60,30,400),new Wall(762,300,200,30)];
    //6.
    FreshWindow(162,0,900,500,walls);
    //7.玩家控制类
    var ctrl = new Control(ball,walls,null);
    //8.设置小球的动画循环
    setInterval("ball.drawBall()",100);

    function FreshWindow(ox,oy,winWidth,winHeight,walls_)       //参数代表地图上的静态景物
    {
        cxt.clearRect(ox,oy,winWidth,winHeight);    //清理画布
        cxt.strokeRect(ox,oy,winWidth,winHeight);
        //document.write("xx");
        for(var i=0;i<walls_.length;i++)
        {
            cxt.strokeRect(walls_[i].x,walls_[i].y,walls_[i].width,walls_[i].height);
        }
       // alert("alter");
    }
    function onGetKey()
    {
        ctrl.moveCtrl();

    }
</script>
</body>
</html>

2.

//玩家操控类,封装了W,A,S,D等等操作
function Control(hero_,walls_,enemies_)
{
    this.keyTemp = 0;//按键寄存器,存放上一次的按键值
    this.ball = hero_;
    this.wall = walls_;
    this.enemy = enemies_;
    this.collide = new Collide(hero_,walls_,enemies_);
    this.moveCtrl = function()
    {
        var code = event.keyCode;//对应字母的ascii
        //如果上一次的按键和这一次的不相等
        if(this.keyTemp != code)
        {
            this.keyTemp = code;         //更新按键值
            this.collide.ColideReferenceClean();  //修改了方向,清空上一次的计算值(待碰撞物体),重新的方向计算新的待碰撞物体
        }
        switch(code)
        {
            //数字是ASCII码,记不住的话可以对照ASCII码表
            //上
            case 87:
                this.ball.dir=0;
                // document.write("c");
                //if(this.ball.getMinY() >= mana.topY)
                if( !this.collide.IsCollide() && this.ball.getMinY() >= mana.topY)
                    this.ball.moveUp();
                break;
            //下
            case 83:
                this.ball.dir=1;
                //if(this.ball.getMaxY() <= mana.buttomY)
                if( !this.collide.IsCollide() && this.ball.getMaxY() <= mana.buttomY)
                    this.ball.moveDown();
                break;
            //左
            case 65:
                this.ball.dir=2;
                if( !this.collide.IsCollide() && this.ball.getMinX() >= mana.leftEgdeX)
                    this.ball.moveLeft();
                break;
            //右
            case 68:
                this.ball.dir=3;
                if( !this.collide.IsCollide() && this.ball.getMaxX() <= mana.rightEdgeX)
                    this.ball.moveRight();
                break;
            default :break;
        }
    };
}

3.

//小球类
//注意js里面类的定义方法,直接类加函数参数的形式,就相当于定义了,然后里面直接this.xx=xx_,很高效
//参数:x,y坐标,球的方向,球的半径,运动速度
function Ball(x_,y_,r_,sp_)
{

    this.x = x_;
    this.y = y_;
    this.dir = 0;
    this.r = r_;    //灰色表示还没用
    this.sp = sp_;
    this.state = 0;
    //定义上下左右:0,1,2,3
    this.moveUp = function()
    {
        this.y -= this.sp;//上
        this.dir = 0;
    };
    this.moveDown = function()
    {
        this.y += this.sp;//下
        this.dir = 1;
    };
    this.moveLeft = function()
    {
        this.x -= this.sp;//左
        this.dir = 2;
    };
    this.moveRight = function()
    {
        this.x += this.sp;//右
        this.dir = 3;
    };
    //获得小球的坐标
    this.getX = function()
    {
        return this.x;
    };
    this.getY = function()
    {
        return this.y;
    };
    //获得球的各个方向的边界值
    this.getMaxX = function() {
        return this.x + this.r;
    };
    this.getMaxY = function()
    {
        return this.y + this.r;
    };
    /**
     * @return {number}
     */
    this.getMinX = function()
    {
        return this.x - this.r;
    };
    /**
     * @return {number}
     */
    this.getMinY = function()
    {
        return this.y - this.r;
    };
    this.getDir = function()
    {
        return this.dir;
    };
    this.drawBall = function()
    {
        FreshWindow(Ox,Oy,WinWidth,WinHeight,walls);
        switch (this.dir)
        {
            case 0:
                this.drawBall_UpOrDown(true);
                break;
            case 1:
                this.drawBall_UpOrDown(false);
                break;
            case 2:
                this.drawBall_RightOrLeft(false);
                break;
            case  3:
                this.drawBall_RightOrLeft(true);
                break;
            default :
                break;
        }
    };
    this.drawBall_RightOrLeft = function(isRight)
    {
        //document.write(state);
        //画眼睛,眼睛是公共的
        //画眼睛-外圈
        var eyeX;
        if(isRight == true)     //右
            eyeX = this.x - 5;
        else eyeX = this.x + 5;//左
        var eyeY = this.y-8;
        var eyeR = 6;//目前限定死这个
        cxt.beginPath();
        cxt.fillStyle="#000000";
        cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);
        cxt.fill();
        cxt.closePath();
        //画眼睛-眼球
        var qiuR = eyeR / 2;
        cxt.beginPath();
        cxt.fillStyle="#FF0000";
        cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);
        cxt.fill();
        cxt.closePath();
        switch(this.state)
        {
            //张嘴
            case 1:
                //画红球
                cxt.beginPath();
                cxt.fillStyle="#FF0000";
                //嘴巴大小为90°
                //画圆弧--脸
                if(isRight)
                    cxt.arc(this.x,this.y,this.r,1/4 * Math.PI,3/2 * Math.PI + 1/4 * Math.PI,false);
                else
                    cxt.arc(this.x,this.y,this.r,3/4 * Math.PI, Math.PI + 1/4 * Math.PI,true);
                cxt.stroke();
                cxt.closePath();
                cxt.beginPath();
                //画嘴巴
                var ax = 0,ay = 0;
                var bx = 0,by = 0;
                var temp = this.r * Math.sqrt(2)/2;
                if(isRight)
                    ax = this.x + temp;
                else
                    ax = this.x - temp;
                ay = this.y - temp;
                bx = ax;
                by = this.y + temp;
                cxt.moveTo(this.x,this.y);
                cxt.lineTo(ax,ay);
                cxt.moveTo(this.x,this.y);
                cxt.lineTo(bx,by);
                cxt.closePath();
                cxt.stroke();
                this.state = 0;
                break;
            //闭嘴
            case 0:
                //画圆弧--脸
                cxt.beginPath();
                cxt.arc(this.x,this.y,this.r,0,Math.PI * 2,false);
                cxt.stroke();
                cxt.closePath();
                //从圆心到嘴巴末点的连线
                cxt.beginPath();
                cxt.moveTo(this.x,this.y);
                if(isRight)
                    cxt.lineTo(this.x + this.r,this.y);
                else
                    cxt.lineTo(this.x - this.r,this.y);
                cxt.stroke();
                cxt.closePath();
                this.state = 1;
                break;
            default :
                break;
        }
    };
    this.drawBall_UpOrDown = function(isUp)
    {
        //document.write(state);
        //画眼睛,眼睛是公共的
        //画眼睛-外圈
        var eyeX = this.x - 5;
        var eyeY = this.y + 8;
        if(!isUp)
        {
            eyeX = this.x + 5;
            eyeY = this.y - 8;
        }

        var eyeR = 6;//目前限定死这个
        cxt.beginPath();
        cxt.fillStyle="#000000";
        cxt.arc(eyeX,eyeY,eyeR,0,Math.PI * 2,false);
        cxt.fill();
        cxt.closePath();
        //画眼睛-眼球
        var qiuR = eyeR / 2;
        cxt.beginPath();
        cxt.fillStyle="#FF0000";
        cxt.arc(eyeX,eyeY,qiuR,0,Math.PI * 2,false);
        cxt.fill();
        cxt.closePath();
        switch(this.state)
        {
            //张嘴
            case 1:
                //画红球
                cxt.beginPath();
                cxt.fillStyle="#FF0000";
                //嘴巴大小为90°
                //画圆弧--脸
                if(!isUp)
                    cxt.arc(this.x,this.y,this.r,1/4 * Math.PI ,3/4 * Math.PI,true);
                else
                    cxt.arc(this.x,this.y,this.r,Math.PI +  1/4 * Math.PI,3/2 * Math.PI+  1/4 * Math.PI,true);
                cxt.stroke();
                cxt.closePath();
                cxt.beginPath();
                //画嘴巴
                var ax = 0,ay = 0;
                var bx = 0,by = 0;
                var temp = this.r * Math.sqrt(2)/2;
                ax = this.x - temp;
                ay = this.y - temp;
                by = ay;
                bx = this.x + temp;
                if(!isUp)
                {
                    ax = this.x + temp;
                    ay = this.y + temp;
                    by = ay;
                    bx = this.x - temp;
                }
                cxt.moveTo(this.x,this.y);
                cxt.lineTo(ax,ay);
                cxt.moveTo(this.x,this.y);
                cxt.lineTo(bx,by);
                cxt.closePath();
                cxt.stroke();
                this.state = 0;
                break;
            //闭嘴
            case 0:
                //画圆弧--脸
                cxt.beginPath();
                cxt.arc(this.x,this.y,this.r,0,Math.PI * 2,false);
                cxt.stroke();
                cxt.closePath();
                //从圆心到嘴巴末点的连线
                cxt.beginPath();
                cxt.moveTo(this.x,this.y);
                if(!isUp)
                    cxt.lineTo(this.x ,this.y + this.r);
                else
                    cxt.lineTo(this.x ,this.y- this.r);
                cxt.stroke();
                cxt.closePath();
                this.state = 1;
                break;
            default :
                break;
        }

    };
}

4.

//2d碰撞检测引擎
//参数:玩家,阻碍物数组,敌人数组
function Collide(hero_,walls_,enemy_)
{
    this.hero = hero_;        //玩家
    this.walls = walls_;      //阻碍物数组
    this.enemys = enemy_;     //敌人数组
    this.isFind = false;      //临时变量,是否找到
    this.tempWall = null;     //临时变量
   // alert("cc");
    this.walls_y = this.walls.slice();  //这里不要写walls_,因为写这个的话,就和this.walls指向一个地方,排序后,walls也变了,终于找到原因,所以我用了复制
    this.isSort = false;      //数组是否排序。好像不能调用类中的函数,调用了没反应。。。。

    alert(this.walls);
    /**
     * @return {boolean}
     */
    //检测是否碰到,返回true,碰到,else没碰到
    this.IsCollide = function()
    {
        //是否找到离自己最近的墙壁

        //如果没有找到,则寻找

        switch (this.hero.getDir())
        {

            //上:
            case 0:
                if(this.tempWall == null)
                {
                    //     alert("wall_已被清空");
                    this.tempWall = this.getUpNestWall();
                }
                else
                {
                    if(this.hero.getMinY() <= this.tempWall.getWY()+this.tempWall.getHeight())
                    {

                      //  alert(this.tempWall.getWX());
                        return true;
                    }

                }
                break;
            //下
            case 1:
                if(this.tempWall == null)
                {
                    //     alert("wall_已被清空");
                    this.tempWall = this.getButtomNestWall();
                }
                else
                {
                    if(this.hero.getMaxY() >= this.tempWall.getWY())
                    {

                      //  alert(this.tempWall.getWX());
                        return true;
                    }

                }
                break;
            //左
            case 2:
                // alert("按左");//因为按下左的瞬间,球是先判断,并不是先转向,所以此时的方向还是上一个方向,这样便造成了错误,逻辑bug,应该按下后先转向,再判断该方向的障碍

                if(this.tempWall == null)
                {
                    //     alert("wall_已被清空");
                    this.tempWall = this.getLeftNestWall();
                }
                else
                {
                    if(this.hero.getMinX() <= this.tempWall.getWX()+this.tempWall.getWidth())
                    {

                        alert(this.tempWall.getWX());
                        return true;
                    }

                }
                break;
            //右
            case 3:
                //alert(this.hero.getMaxX());
                if(this.tempWall == null)
                {
                    //alert("NULL");
                    this.tempWall = this.getRightNestWall();
                }
                else
                {

                    //alert("墙壁的是:");
                    return this.hero.getMaxX() >= this.tempWall.getWX();
                }
                break;
            default : return false;
                break;

        }
    };
    //获得向右方向离自己最近的墙壁
    this.getRightNestWall = function ()
    {
        var y;
        y = 0;
        var temp = 0;
        //往右
        y = this.hero.getY();
        var i;
        var wallTemp = null;
        if(!this.isFind)
        {
                for(i = 0;i<this.walls.length;i++)
                {
                    temp = this.walls[i].getWY();
                    if(y >= temp && y<=temp + this.walls[i].height)
                    {
                        if(this.hero.getMaxX() <= this.walls[i].getWX())
                        {
                            wallTemp = this.walls[i];
                           // alert("......find");
                            alert("i="+i+"x="+wallTemp.getWX()+"y="+wallTemp.getWY()+"width="+wallTemp.getWidth()+"height="+wallTemp.getHeight());
                            this.isFind = true;      //找到
                           // alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                            return wallTemp;//已经找到自己前进方向上离自己最近的墙壁,不再寻找,跳出循环
                        }
                    }

                }

        }
    };
    //获得左边离自己最近的墙
    this.getLeftNestWall = function()
    {
        var y;
        y = 0;
        var temp = 0;
        //往左
        y = this.hero.getY();
        var i;
        var wallTemp = null;
        var end = this.walls.length - 1;
        if(!this.isFind)
        {
            for(i = end;i>=0;i--)
            {
                temp = this.walls[i].getWY();
                if(y >= temp && y<=temp + this.walls[i].height)
                {
                    if(this.hero.getMinX() >= this.walls[i].getWX() + this.walls[i].getWidth() )
                    {

                        wallTemp = this.walls[i];
                        // alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);

                        this.isFind = true;      //找到
                        //alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                        return wallTemp;//已经找到自己前进方向上离自己最近的墙壁,不再寻找,跳出循环
                    }
                }

            }

        }
    };
    //获得上边离自己最近的墙
    this.getUpNestWall = function()
    {
        //如果没有排序,先排序
        if(this.isSort == false)
        {
            this.sortBy_y(this.walls_y);
            this.isSort = true;
            //alert(this.walls_y);
        }
        else
        {
            var x = 0;
            var temp = 0;
            //往右
            x = this.hero.getX();
            var i;
            var wallTemp = null;
            var end = this.walls_y.length - 1;
            if(!this.isFind)
            {
                for(i = end;i >= 0;i--)
                {
                    temp = this.walls_y[i].getWX();
                    if(x >= temp && x<=temp + this.walls_y[i].width)
                    {
                        if(this.hero.getMinY() >= this.walls_y[i].getWY() + this.walls_y[i].height)
                        {
                            wallTemp = this.walls_y[i];
                            // alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                            this.isFind = true;      //找到
                            //alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                            return wallTemp;//已经找到自己前进方向上离自己最近的墙壁,不再寻找,跳出循环
                        }
                    }

                }

            }
        }
    };
    this.getButtomNestWall = function()
    {
        //如果没有排序,先排序
        if(this.isSort == false)
        {
            this.sortBy_y(this.walls_y);
            this.isSort = true;
            //alert(this.walls_y);
        }
        else
        {
            var x = 0;
            var temp = 0;
            //往右
            x = this.hero.getX();
            var i;
            var wallTemp = null;
            if(!this.isFind)
            {
                for(i = 0;i<this.walls_y.length;i++)
                {
                    temp = this.walls_y[i].getWX();
                    if(x >= temp && x<=temp + this.walls_y[i].width)
                    {
                        if(this.hero.getMaxY() <= this.walls_y[i].getWY())
                        {
                            wallTemp = this.walls_y[i];
                            // alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                            this.isFind = true;      //找到
                            //alert("i="+i+"y="+wallTemp.getWY()+"height="+wallTemp.getHeight()+"temp="+temp+"dir="+ball.getDir()+"isRight="+isRight);
                            return wallTemp;//已经找到自己前进方向上离自己最近的墙壁,不再寻找,跳出循环
                        }
                    }

                }

            }
        }
    };
    //排序,根据y来排,由小到大
    //冒泡排序算法
    this.sortBy_y = function(arr)
    {
       // alert("endxxxxx");
        var temp = null;
        var l =  arr.length;
        //alert("length="+l);
        for(var i = 0;i < l-1;i++)
        {
            for(var j = 0;j<l -1- i;j++)
            {

                if(arr[j].getWY() >= arr[j + 1].getWY())
                {
                    //交换
                    temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                }

            }
        }

    };
    this.ColideReferenceClean = function()
    {
        this.isFind=false;
        //存放离自己最近的、如果继续直线前进不转向将会碰撞的wall
        this.tempWall=null;
       // alert("clean");
    };
}

5.

//游戏系统管理类

function GameSys(ox_,oy_,winWidth_,winHeight_)
{
   // this.can = document.getElementById(id_);//画布id
   // this.cxt = can.getContext("2d");
    this.ox = ox_;                      //游戏窗口的坐标原点
    this.oy = oy_;
    this.winWidth = winWidth_;          //窗口宽高
    this.winHeight = winHeight_;
    this.rightEdgeX = ox_ + winWidth_;  //四周边界值
    this.leftEgdeX =  ox_;
    this.topY =   oy_;
    this.buttomY = oy_ + winHeight_;
    this.walls = null;                  //地图上的静态景物,不会多,也不会少的物体,是一个数组

    document.write("xx");

}

6.

function Wall(x_,y_,width_,height_)
{
    this.x = x_;
    this.y = y_;
    this.width = width_;
    this.height = height_;
    this.getWX = function()
    {
        return this.x;
    };
    this.getWY = function()
    {
        return this.y;
    };
    this.getWidth = function()
    {
        return this.width;
    };
    this.getHeight = function()
    {
        return this.height;
    };

}

游戏运行截图:

一步步来完善吧!加油。。。



时间: 2024-10-16 22:26:25

HTML5吃豆豆游戏开发实战(四)2d碰撞检测、重构-第二篇的相关文章

HTML5吃豆豆游戏开发实战(一)使用Canvas绘制游戏主角

最近在学习HTML5,爱因斯坦曾说过,"最好的学习就是自己去经历".于是,我想在学习HTML5的同时,做一款简单的小游戏,这样学习起来也会很有趣的,我想做的是以前小时候玩儿的小霸王上面的很经典的一款游戏,叫"吃豆豆",后面有怪物跟着跑,蛮好玩的,还很虐心,相信大家都玩儿过. 吃豆豆就是这款啦: 我就用前面学的一些HTML5的简单的一些知识来简单模拟这款游戏吧.我做这款游戏不打算用图片,全部用canvas来画,这样才有意思,嘿嘿. 正如大家所看到的,我们游戏的主角就是

HTML5吃豆豆游戏开发实战(二)主角移动和动画循环设置

接着上一篇讲,在上一篇中呢,我已经使用Canvas绘制出了我们游戏的主角,姑且叫它"小嘴"吧,因为只有嘴巴,嘿嘿,我还添了眼睛. 在这一篇中呢,就实现物体的移动和动画播放(一直张开嘴吧关闭嘴巴的动画,很饥渴的样子). 1. 要做玩家和游戏的交互,当然要考虑--如何设置按键响应这个问题. 那么如何设置呢? 我们可以通过在body标签里面添加事件来响应用户的操作: 由于我们要用W,A,S,D来控制物体的上下移动,这是按键响应,于是我们选择用onkeydown事件. onkeydown 事件

HTML5游戏开发实战--注意点

1.WebSocket是HTML5标准的一部分,Web页面可以用它来持久连接到socket服务器上.该接口提供了浏览器与服务器之间的事件驱动型连接,这意味着客户端不必再每隔一个时间段就需要向服务器发送一次新的数据请求.当有数据需要更新时,服务器就可以直接推送数据更新给浏览器.该功能的好处之一就是玩家之间可以实时进行交互.当一个玩家做了些事,就会向服务器发送数据,服务器将广播一个事件给其他已连接的所有浏览器,让它们知道玩家做了什么.这样就使得制作HTML5网络游戏成为可能. 2.随着现代浏览器对H

unity3D游戏开发实战原创视频讲座系列12之U3D的2D开发新方法实战

 U3D的2D开发新方法实战 (Unity3d-4.x的打飞机2D游戏开发新的方法应用 ) 大纲介绍:不使用NGUI和TK2d插件,   使用 U3D内置强大的最大的工具. 开发过程设计到如下内容: 从图片集中截取出 精灵.(这些与以前的方法是不同的) 连续图片的动画制作. 对动画的编辑 Mecanim动画系统的使用 2D物理系统和碰撞检测. 游戏的简单完善(敌机的产生.背景滚动.声音.分数的实现). 会用8讲的时间来介绍. 视持续更新中.... 视频存放地址如下:http://ipd.pp

unity3D游戏开发实战原创视频讲座系列10之《保卫战:异形入侵》游戏开发第一季

讲解目录 <保卫战:异形入侵>游戏开发    1 第一讲   游戏演示和资源的介绍    1 第二讲  "异形"怪物的实现    1 第三讲  "异形"怪物生命值的体现    9 第四讲  "异形"怪物死后处理    12 第五讲  玩家的制作    15 第六讲  玩家的行走控制(键盘)    16 第七讲  武器的切换(鼠标)     16 第八讲  摄像头的变化(鼠标)    19 第九讲  子弹预制体和特效的制作    20

Cocos2d-x+3.x游戏开发实战pdf

下载地址:网盘下载 内容简介  · · · · · · <Cocos2d-x 3.x游戏开发实战>是一本介绍Cocos2d-x游戏引擎的实用图书,全面介绍了最新的Cocos2d-x 3.2游戏引擎各方面的知识. <Cocos2d-x 3.x游戏开发实战>从内容层次上可分为四个部分.第一部分介绍了游戏开发的基础知识.游戏引擎概念.Cocos2d-x的下载与安装,以及跨平台开发环境的搭建.第二部分介绍了Cocos2d-x中的核心类.动作.动画.3D特效.文字.字体.菜单.事件处理.UI

cocos2d-x游戏开发实战原创视频讲座系列1之2048游戏开发

 第一讲 游戏的演示和工具介绍...1 第二讲 创建项目...2 第三讲 界面显示...3 第四讲 数字2的产生...7 第五讲 输入操作的推断...9 第六讲 输入操作的反应...13 第七讲 分数的累加.游戏结束检測...18 第八讲 界面美化...22 视持续更新中.... 视频存放地址例如以下:http://ipd.pps.tv/user/1058663622 或者:http://www.iqiyi.com/u/1058663622 持续更新中~~~~~~~~~~~~~~. 第一讲 

Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现(不定期更新中~~~)

系列目录 Unity3D手机斗地主游戏开发实战(01)_发牌功能实现 Unity3D手机斗地主游戏开发实战(02)_叫地主功能实现 一.大体思路 前面我们实现了点击开始游戏按钮,系统依次给玩家发牌的逻辑和动画,并展示当前的手牌.这期我们继续实现接下来的功能--叫地主. 1.首先这两天,学习了DOTween,这是一个强大的Unity动画插件,大家可以参考:官方文档,个人感觉DOTween还是比较好用的. 好的,我们先来重构一下动画部分的代码(没有绝对牛逼的架构和设计,项目过程中不要不断的持续改进嘛

cocos2d 游戏开发实战

文章转自:http://uliweb.clkg.org/tutorial/read/40 6   cocos2d 游戏开发实战 6.1   创建cocos2d项目 6.2   cocos2d v3 "hello world" 6.2.1   显示一个飞船 6.3   精灵 6.4   開始 space viking 之旅 6.4.1   添加 sneakyinput 6.5   精灵的移动效果,旋转效果 6.6   定时器效果 6.7   启动 cocos2d,默认竖屏 6.8   检