HTML5游戏开发实例

Wesley13
• 阅读 784

开发工具: vscode

一、人物拼图游戏

游戏介绍: 拼图游戏将一幅图片分割成若干拼块并将它们随机打乱顺序。当将所有拼块都放回原位置时,就完成了拼图(游戏结束)。

在“游戏”中,单击滑块选择游戏难易,“容易”为3行3列拼图游戏,中间为一个4行4列拼图游戏,“难”为5行5列拼图游戏。拼块以随机顺序排列,玩家用鼠标单击空白块的四周来交换它们的位置,直到所有拼块都回到原位置。

程序设计思路: HTML5可以把图片整合到网页中。使用canvas元素可以在这个空白的画布上填充线条,载入图片文件,甚至动画效果。这里制作拼图游戏用来展示HTML5 canvas的图片处理能力。

游戏程序首先显示以正确顺序排列的图片缩略图,根据玩家设置的分割数,将图片订割成相应tileCount行列数的拼块,并按顺序编号。动态生成一个大小tileCount_tileCount,的数组boardParts,存放用0、1、2到tileCount_ tileCount-1的数,每个数字代表一个拼块(例如4*4的游戏拼块编号如图所示)。

游戏开始时,随机打乱这个数组boardParts,假如boardParts[0]是5,则在左上角显示编号是5的拼块。根据玩家用鼠标单击的拼块和空白块所在位置,来交换该boardParts数组对应的元素,最后依据元素排列顺序来判断是否已经完成游戏。

游戏参考代码:

sliding.js

var context=document.getElementById('puzzle').getContext('2d');

var img=new Image();
img.src='defa.jpg';
img.addEventListener('load',drawTiles,false);

var boardSize=document.getElementById('puzzle').width;
var tileCount=document.getElementById('scale').value;

var tileSize=boardSize/tileCount;

var clickLoc=new Object;
clickLoc.x=0;
clickLoc.y=0;

var emptyLoc=new Object;
emptyLoc.x=0;
emptyLoc.y=0;

var solved=false;

var boardParts=new Object;
setBoard();

document.getElementById('scale').onchange=function(){
    tileCount=this.value;
    tileSize=boardSize/tileCount;
    setBoard();
    drawTiles();
};

document.getElementById('puzzle').onmousemove=function(e){
    clickLoc.x=Math.floor((e.pageX-this.offsetLeft)/tileSize);
    clickLoc.y=Math.floor((e.pageY-this.offsetTop)/tileSize);
};

document.getElementById('puzzle').onclick=function(){
    if (distance(clickLoc.x,clickLoc.y,emptyLoc.x,emptyLoc.y)==1){
        slideTile(emptyLoc,clickLoc);
        drawTiles();
    }
    if(solved){
        setTimeout(function(){alert("You solved it!");},500);
    }
};

function setBoard(){
    boardParts=new Array(tileCount);
    for(var i=0;i<tileCount;++i) {
        boardParts[i]=new Array(tileCount);
        for (var j=0;j<tileCount;++j){
            boardParts[i][j]=new Object;
            boardParts[i][j].x=(tileCount-1)-i;
            boardParts[i][j].y=(tileCount-1)-j;
        }
    }
    emptyLoc.x=boardParts[tileCount-1][tileCount-1].x;
    emptyLoc.y=boardParts[tileCount-1][tileCount-1].y;
    solved=false;
}

function drawTiles(){
    context.clearRect(0,0,boardSize,boardSize);
    for(var i=0;i<tileCount;++i){
        for(var j=0;j<tileCount;++j){
            var x=boardParts[i][j].x;
            var y=boardParts[i][j].y;
            if(i!=emptyLoc.x || j!=emptyLoc.y || solved==true){
                context.drawImage(img,x*tileSize,y*tileSize,tileSize,tileSize,
                    i*tileSize,j*tileSize,tileSize,tileSize);
            }
        }
    }
}

function distance(x1,y1,x2,y2) {
    return Math.abs(x1-x2)+Math.abs(y1-y2);
}

function slideTile(toLoc,fromLoc){
    if(!solved){
        boardParts[toLoc.x][toLoc.y].x=boardParts[fromLoc.x][fromLoc.y].x;
        boardParts[toLoc.x][toLoc.y].y=boardParts[fromLoc.x][fromLoc.y].y;
        boardParts[fromLoc.x][fromLoc.y].x=tileCount-1;
        boardParts[fromLoc.x][fromLoc.y].y=tileCount-1;
        toLoc.x=fromLoc.x;
        toLoc.y=fromLoc.y;
        checkSolved();
    }
}

function checkSolved(){
    var flag=true;
    for(var i=0;i<tileCount;++i){
        for(var j=0;j<tileCount;++j){
            if(boardParts[i][j].x!=i || boardParts[i][j].y!=j){
                flag=false;
            }
        }
    }
    solved=flag;
}

index.html

<!doctype html>
<html>
    <head>
        <title>拼图游戏</title>
        <style>
            .picture{
                border:1px solid black;
            }
        </style>
    </head>
    <body>
        <div id="title">
            <h2>拼图游戏</h2>
        </div>
        <div id="slider">
            <form>
                <label>低</label>
                <input type="range" id="scale" value="4" min="3" max="5" step="1">
                <label>高</label>
            </form>
            <br>
        </div>
        <div id="main" class="main">
            <canvas id="puzzle" width="480px" height="480px"></canvas>
        </div>
        <script src="sliding.js"></script>
    </body>
</html> 

运行结果:

HTML5游戏开发实例

HTML5游戏开发实例

HTML5游戏开发实例

二、雷电飞机射击游戏

游戏介绍: 通过上下左右控制飞机移动,空格键完成射击

程序设计步骤: 将游戏种所用到的玩家、敌人、子弹等封装成类,planobj()来检测飞机的碰撞

游戏参考代码:

<!DOCTYPE html>
<html>
    <head>
        <title>飞机大战</title>
        <meta charset="utf-8">
    </head>
    <body>
        <canvas id='myCanvas' width="320" height="480" style="border: solid">
            你的浏览器不支持canves画布元素,请更新浏览器获得演示效果。
        </canvas>
        <div id="message_txt" style="display: block;">飞机大战</div>
        <div id="score_txt" style="display: block;">分数:0分</div>
        <script type="text/javascript">
            var canvas=document.getElementById('myCanvas');
            var context=canvas.getContext('2d');
            document.addEventListener('keydown',onKeydown);
            //飞机类和其属性
            var Plan=function(image,x,y,n){
                this.image=image;
                this.x=x;
                this.y=y;
                this.orignx=x;
                this.origny=y;
                this.width=image.width/n;
                this.height=image.height;
                this.isCaught=false;
                this.frm=0;
                this.dis=0;
                this.n=n;
            };
            Plan.prototype.getCaught=function(bool){
                this.isCaught=bool;
                if (bool==false){
                    this.orignx=0;
                    this.origny=this.y;
                }
            };
            Plan.prototype.testPoint=function(x,y){
                var betweenX=(x>=this.x)&&(x<=this.x+this.width);
                var betweenY=(y>=this.y)&&(y<=this.y+this.height);
                return betweenX&&betweenY;
            };
            

            Plan.prototype.move=function(dx,dy){
                this.x+=dx;
                this.y+=dy;
            };
            Plan.prototype.Y=function(){
                return this.y;
            };
            //不断下移飞机
            Plan.prototype.draw=function(ctx){
                ctx.save();
                ctx.translate(this.x,this.y);
                ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
                ctx.restore();
                this.y++;
                this.x=this.orignx+20*Math.sin(Math.PI/100*this.y);
                this.dis++;
                if(this.dis>=3){
                    this.dis=0;
                    this.frm++;
                    if(this.frm>=this.n) this.frm=0;
                }
            };
            //原地不动画飞机
            Plan.prototype.draw2=function(ctx){
                ctx.save();
                ctx.translate(this.x,this.y);
                ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
                ctx.restore();
                this.dis++;
                //3帧换一次图片
                if(this.dis>=3){
                    this.dis=0;
                    this.frm++;
                    if(this.frm>=this.n) this.frm=0;
                }
            };
            //检测飞机碰撞
            Plan.prototype.hitTestObject=function(planobj){
                if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))
                    return true;
                else
                    return false;
            }

            function iscolliding(ax,ay,aw,ah,bx,by,bw,bh){
                if(ay>by+bh||by>ay+ah||ax>bx+bw||bx>ax+aw)
                    return false;
                else
                    return true;
            }
            //子弹类和其属性
            var Bullet=function(image,x,y){
                this.image=image;
                this.x=x;
                this.y=y;
                this.orignx=x;
                this.orignx=y;
                this.width=image.width/4;
                this.height=image.height;
                this.isCaught=false;
                this.frm=0;
                this.dis=0;
            }
            Bullet.prototype.testPoint=function(x,y){
                var betweenX=(x>=this.x)&&(x<this.x+this.width);
                var betweenY=(y>=this.y)&&(y<this.y+this.height);
                return betweenX&&betweenY;
            };
            Bullet.prototype.move=function(dx,dy){
                this.x+=dx;
                this.y+=dy;
            };
            Bullet.prototype.Y=function(){
                return this.y;
            };
            Bullet.prototype.draw=function(ctx){
                ctx.save();
                ctx.translate(this.x,this.y);
                ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
                ctx.restore();
                this.y--;
                this.dis++;
                if(this.dis>=10){
                    this.dis=0;
                    this.frm++;
                    if(this.frm>=4) this.frm=0;
                }
            };
            //检测子弹与敌人的碰撞
            Bullet.prototype.hitTestObject=function(planobj){
                if(iscolliding(this.x,this.y,this.width,this.height,planobj.x,planobj.y,planobj.width,planobj.height))
                    return true;
                else
                    return false;
            }
            //爆炸动画类和属性
            var Bomb=function(image,x,y){
                this.image=image;
                this.x=x;
                this.y=y;
                this.width=image.width/6;
                this.height=image.height;
                this.frm=0;
                this.dis=0;
            };


            Bomb.prototype.draw2=function(ctx){
                ctx.save();
                ctx.translate(this.x,this.y);
                if(this.frm>=6) return ;
                ctx.drawImage(this.image,this.frm*this.width,0,this.width,this.height,0,0,this.width,this.height);
                ctx.restore();
                this.dis++;
                if(this.dis>=10){
                    this.dis=0;
                    this.frm++;
                }
            };
            var plan1,plan2,plan3,plan4,caughtplan=null;
            var isClick=false;
            var mouseX,mouseY,preX,preY;
            var plans=[];
            var bullets=[];
            var bombs=[];
            var score=0;
            var overflag=false;
            var myplane;
            //导入外部材料图
            var image=new Image();
            var image2=new Image();
            var image3=new Image();
            var image4=new Image();
            var image5=new Image();
            var bakground=new Image();
            bakground.src='map_0.png';
            image.src='plan.png';
            image.onload=function(){

            }
            image2.src='bomb.png';
            image2.onload=function(){

            }
            image3.src='enemy.png';
            image3.onload=function(){
                myplane=new Plan(image,300*Math.random(),400,6);

                plan_interval=setInterval(function(){
                    plans.push(new Plan(image,300*Math.random(),20*Math.random(),2));
                },3000);//3秒产生一架敌机
                setInterval(function(){
                    context.clearRect(0,0,320,480);
                    context.drawImage(bakground,0,0);
                //画己方飞机
                    if(!overflag)
                        myplane.draw2(context);
                //画敌机
                    for(var i=plans.length-1;i>=0;i--){
                        if (plans[i].Y()>400){
                            plans.splice(i,1);//删除敌机
                        }
                        else{
                            plans[i].draw(context);
                        }
                    }
                //画子弹
                    for (var i=bullets.length-1;i>=0;i--){
                        if (bullets[i].Y()<100){
                            bullets.splice(i,1);//删除子弹
                        }
                        else{
                            bullets[i].draw(context);
                        }
                    }
                //检测玩家是否撞到敌机
                    for (vari=plans.length-1;i>=0;i--){
                        e1=plans[i];
                        if(e1!=null && myplane!=null && myplane.hitTestObject(e1)){
                            clearInterval(plan_interval);
                            plans.splice(i,1);//删除敌机
                            bombs.push(new Bomb(image2,myplane.x,myplane.y));

                            message_txt.innerHTML='敌机碰到玩家自己飞机,游戏结束';
                            overflag=true;
                        }
                    }
            //判断子弹击中没有
                    for(var j=bullets.length-1;j>=0;j--){
                        var b1=bullets[j];
                        for(var i=plans.length-1;i>=0;i--){
                            e1=plans[i];
                            if (e1!=null && b1!=null && b1.hitTestObject(e1)){
                                plans.splice(i,1);
                                bullets.splice(i,1);
                                bombs.push(new Bomb(image2,b1.x,b1.y-36));

                                message_txt.innerHTML='敌机被击中,加20分';
                                score+=20;
                                score_txt.innerHTML='分数:'+score+'分';
                            }
                        }
                    }
                //画爆炸
                    for (var i=bombs.length-1;i>=0;i--){
                        if (bombs[i].frm>=6){
                            bombs.splice(i,1);
                        }
                        else{
                            bombs[i].draw2(context);
                        }
                    }

                },1000/60);
            };
            image4.src='bullet.png';
            image4.onload=function(){

            };
            //飞机移动控制
            function onKeydown(e){
                if(e.keyCode==32){
                    bullets.push(new Bullet(image4,myplane.x,myplane.y-36));
                }else if(e.keyCode==37){
                    myplane.move(-10,0);
                }else if(e.keyCode==39){
                    myplane.move(10,0);
                }else if(e.keyCode==38){
                    myplane.move(0,-10);
                }else if(e.keyCode==40){
                    myplane.move(0,10);
                }
            }
        </script>
    </body>
</html>

运行结果:

HTML5游戏开发实例

三、FlappyBird游戏

游戏介绍: 通过鼠标点击来控制小鸟,跨越由各种不同长度水管所组成的障碍。

游戏参考代码:

bird.js

var  canvas=document.getElementById("canvas");
var c=canvas.getContext("2d");

function Bird(x,y,image) {
    this.x=x,
    this.y=y,
    this.width=image.width/2,
    this.height=image.height,
    this.image=image;
    this.draw=function (context,state) {
        if(state==="up")
            context.drawImage(image,0,0,this.width,this.height,this.x,this.y,this.width,this.height);
        else {
            context.drawImage(image,this.width,0,this,width,this.height,this.x,this.y,this.width,this.height);
        }
    }
};
function Obstacle(x,y,h,image) {
    this.x=x,
    this.y=y,
    this.width=image.width/2,
    this.height=h,
    this.flypast=false;
    this.draw=function (context,state) {
        if(state==="up")
            context.drawImage(image,0,0,this.width,this.height,this.x,this.y,this.width,this.height);
        else {
            context.drawImage(image,this.width,image.height-this.height,this.height,this.width,this.height,this.x,this.y,this.width,this.height)
        }
    }
};

function FlappyBird() {}
FlappyBird.prototype= {
    bird: null,
    bg: null,
    obs: null,
    obsList: [],

    mapWidth: 340,
    mapHeight: 453,
    startX: 90,
    startY: 225,
    obsDistance: 150,
    obsSpeed: 2,
    obsInterval: 2000,
    upSpeed: 8,
    downSpeed: 3,
    line: 56,
    score: 0,
    touch: false,
    gameOver: false,

    CreateMap: function () {
        //背景
        this.bg = new Image();
        this.bg.src = "img/bg.png";
        var startBg = new Image();
        startBg.src = "img/start.jpg";
        startBg.onload = function () {
            c.drawImage(startBg, 0, 0);
        };
        //小鸟
        var image = new Image();
        image.src = "img/bird.png";
        image.onload = function () {
            this.bird = new Bird(this.startX, this.startY, image);
        }.bind(this);

        //障碍物
        this.obs = new Image();
        this.obs.src = "img/obs.png";
        this.obs.onload = function () {
            var h = 100;
            var h2 = this.mapHeight - h - this.obsDistance;
            var obs1 = new Obstacle(this.mapWidth, 0, h, this.obs);
            var obs2 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line, this.obs);
            this.obsList.push(obs1);
            this.obsList.push(obs2);
        }.bind(this);
    },

    CreatObs: function () {
        var h = Math.floor(Math.random() * (this.mapHeight - this.obsDistance - this.line));
        var h2 = this.mapHeight - h - this.obsDistance;
        var obs1 = new Obstacle(this.mapWidth, 0, h, this.obs);
        var obs2 = new Obstacle(this.mapWidth, this.mapHeight - h2, h2 - this.line, this.obs);
        this.obsList.push(obs1);
        this.obsList.push(obs2);

        if (this.obsList[0].x < -this.obsList[0].width)
            this.obsList.splice(0, 2);
    },
    DrawObs:function(){
        c.fillStyle="#00ff00";
        for(var i=0;i<this.obsList.length;i++){
            this.obsList[i].x-=this.obsSpeed;
            if(i%2)
                this.obsList[i].draw(c,"up");
            else
                this.obsList[i].draw(c,"down");
        }
    },
    
    CountScore:function () {
        if(this.obsList[0].x + this.obsList[0].width < this.startX &&this.obsList[0].flypast==false){
            this.score+=1;
            this.obsList[0].flypast=true;
        }
    },
    ShowScore:function () {
        c.strokeStyle="#000";
        c.lineWidth=1;
        c.fillStyle="#fff";
        c.fillText(this.score,10,50);
        c.strokeText(this.score,10,50);
    },
    CanMove:function () {
        if(this.bird.y<0 || this.bird.y > this.mapHeight-this.bird.height-this.line){
            this.gameOver=true;
        }else{
            var boundary=[{
                x:this.bird.x,
                y:this.bird.y
            },{
                x:this.bird.x+this.bird.width,
                y:this.bird.y
            },{
                x:this.bird.x,
                y:this.bird.y+this.bird.height
            },{
                x:this.bird.x+this.bird.width,
                y:this.bird.x+this.bird.height
            }];
            for (var i=0;i<this.obsList.length;i++){
                for(var j=0;j<4;j++)
                    if(boundary[j].x>=this.obsList[i].x && boundary[j].x <= this.obsList[i].x+this.obsList[i].width &&
                    boundary[j].y>=this.obsList[i].y&& boundary[j].y<=this.obsList[i].y+this.obsList[i].height){
                        this.gameOver=false;
                        break;
                    }
                if(this.gameOver)
                    break;
            }
        }
    },
    CheckTouch:function () {
        if(this.touch){
            this.bird.y-=this.upSpeed;
            this.bird.draw(c,"up");
        }else {
            this.bird.y+=this.downSpeed;
            this.bird.draw(c,"down");
        }
    },
    ClearScreen:function () {
        c.drawImage(this.bg,0,0);
    },
    ShowOver:function () {
        var overImg=new Image();
        overImg.src="img/over.png";
        overImg.onload=function () {
            c.drawImage(overImg,(this.mapWidth-overImg.width)/2,(this.mapHeight-overImg.height)/2-50);
        }.bind(this);
        return;
    }
};

var game=new FlappyBird();
var Speed=20;
var IsPlay=false;
var GameTime=null;
var btn_start;
window.onload=InitGame;

function InitGame() {
    c.font="3em 微软雅黑";
    game.CreateMap();
    canvas.onmousedown=function () {
        game.touch=true;
    }
    canvas.onmouseup=function () {
        game.touch=false;
    };
    canvas.onclick=function () {
        if (!IsPlay) {
            IsPlay = true;
            GameTime = RunGame(Speed);
        }
    }
}


function RunGame(speed) {
    var updateTimer=setInterval(function () {
        game.CanMove();
        if(game.gameOver){
            game.ShowOver();
            clearInterval(updateTimer);
            return;
        }
        game.ClearScreen();
        game.DrawObs();
        game.CheckTouch();
        game.CountScore();
        game.ShowScore();
    },speed);
    var obsTimer=setInterval(function () {
        if (game.gameOver){
            clearInterval(obsTimer);
            return;
        }
        game.CreatObs();
    },game.obsInterval);
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flappy Bird</title>
</head>
<body>
<canvas id="canvas" width="340" height="453" style="border: 2px solid #000;background: #fff;"></canvas>
<script src="bird.js" type="text/javascript"></script>
</body>

</html>

运行结果:

HTML5游戏开发实例

HTML5游戏开发实例

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
Cocos Creator 如何制作拼图游戏,支持无规则形状!
预览效果!(https://oscimg.oschina.net/oscnet/c075e00adf85d09d261e7006e2eeeef3065.gif)  实现思路  假设一张图,按照row行col列分成count(row\col) 份,由count份碎片组成,每个碎片有自己特定的
Wesley13 Wesley13
3年前
html5小游戏Untangle
   今天介绍一个HTML5的小游戏,让大家体验到HTML5带来的乐趣。这个小游戏很简单,只要用鼠标拖动蓝点,让图上的所有线都不相交,游戏时间就会停止,是动用大家头脑的时候啦。!html5小游戏Untangle,以最快的速度把所有线都做到互不相交(http://static.oschina.net/uploads/img/201403
Stella981 Stella981
3年前
Html5游戏开发案例
Html5游戏开发案例Html游戏开发案例(一)拼图游戏游戏规则介绍:拼图游戏将一幅图片分割成若干拼块并将它们随机打乱顺序。当将所有拼块都放回原位置时,就完成了拼图(游戏结束)。在“游戏”中,单击滑块选择游戏难易,“容易”为3行3列拼图游戏,中间为一个4行4列拼图游戏,“难”为5行5列拼图游戏。拼块
Wesley13 Wesley13
3年前
2D小游戏开发学习笔记(5)
一、围住神经猫游戏游戏玩法:玩法很简单,蓝色圆圈代表神经猫,通过点击周围圆圈把猫困住,就算游戏成功游戏效果!(https://oscimg.oschina.net/oscnet/up968a35abafe07c092eacca8126719e14a50.png)逻辑梳理:1、
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
300行代码不到的tornadofx拼图游戏
!(https://oscimg.oschina.net/oscnet/801dfa96d248ac5d1f9cea1911dad503058.jpg)packagecom.cyy.game.pingtuimportjavafx.application.Applicationimportjavafx.bea