当前位置: 移动技术网 > IT编程>开发语言>JavaScript > 画布和JS综合应用之酷跑小游戏

画布和JS综合应用之酷跑小游戏

2020年09月01日  | 移动技术网IT编程  | 我要评论
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> body{ .

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            justify-content: center;
        }
        canvas{
            border:1px solid orange;
        }
        img{
            display: none;
        }
    </style>
    <script>
        window.onload =function (){
            let canvas = document.getElementsByTagName("canvas")[0]
            let ctx = canvas.getContext("2d")

            //背景信息
            let systemDate = {
                bgMovespeed: 2,//背景移速
                horizon:470,//水平线
                upspeed:14.5,//上跳速度
                a:0.5,//加速度
                score: 0,//得分
                life: 3//生命值
            }

            let firstbg = {
                firstbg:document.getElementById("bg1"),//背景图
                x: 0,
                y:0,
                width:canvas.width,
                height:canvas.height
            }
            let secondbg = {
                secondbg:document.getElementById("bg2"),//背景图
                x: canvas.width,
                y: 0,
                width:canvas.width,
                height:canvas.height
            }

            //人物信息
            let roleData = {
                role:document.getElementById("role"),
                row:4,//行
                col:4,//列
                i:1,//几行
                j:0,//几列
                x:canvas.width/3,//人物在画布中的水平坐标
                control: 0,//人物行走速度
                control1: 0,
                upspeed:systemDate.upspeed,
                jump: 0,//0:没有跳跃的状态,1:跳跃状态
            }

            //台阶信息
            let step1 = {
                step1: document.getElementById("step1"),
                width:158,
                height:42
            }

            let step2 = {
                step2: document.getElementById("step2"),
                width:84,
                height:33
            }

            let steps = {
                x: canvas.width,//台阶初始x坐标
                y:[290,110],//台阶y坐标
                mystep: [],//台阶数组
                who:0,//0:添加台阶1 1:添加台阶2
                movespeed:3,
                control:0,//控制添加台阶的速度
                control1:0
            }

            //金币信息
            let coin1 = {
                coin1: document.getElementById("coin1"),
                cutheight:78
            }

            let coin2 = {
                coin2: document.getElementById("coin2"),
                cutheight:78
            }

            let coins = {
                //剪裁的x坐标
                cutx:[0,80,166,246,322,376,410,462,532,608],
                //剪裁的y坐标
                cuty: 0,
                //剪裁的宽度
                cutwidth: [80,86,80,76,54,34,52,70,76,80],
                //金币在画布中的位置
                x:canvas.width,
                y:[80,160,250,340,410],
                mycoins:[],//空数组,装金币
                movespeed:3,
                who: 0,//若为0,添加金币1;若为1,添加金币2
                control: 0,
                control1: 0,
                rotate:  1,//cutx和cutwidth中的下标
                rotatetime: 0,
                rotatetime1:0
            }

            let extra = {
                y:systemDate.horizon - roleData.role.height / roleData.row,//人物y坐标
            }

            //障碍信息
            let thorn1 = {
                thorn1: document.getElementById("thorn1"),
                width:550,
                height:197,
            }

            let thorn2 = {
                thorn2: document.getElementById("thorn2"),
                width:729,
                height:395,
            }

            let thorns = {
                x: canvas.width,//障碍初始x坐标
                y:systemDate.horizon,//障碍y坐标
                mythorns: [],//障碍数组
                who:0,//0:添加障碍1 1:添加障碍2
                movespeed:3,
                control:0,//控制添加障碍的速度
                control1:0
            }

            let game = null//控制定时器
            //绘制背景
            function drawbackground (){
                //图片对象,画布中x的坐标,画布中y的坐标,图片在画布中绘制宽,图片在画布中绘制的高
                ctx.drawImage(firstbg.firstbg,firstbg.x,firstbg.y,firstbg.width,firstbg.height)
                ctx.drawImage(secondbg.secondbg,secondbg.x,secondbg.y,secondbg.width,secondbg.height)
            }

            //绘制人物
            function drawRole (){
                //图片
                ctx.drawImage(roleData.role,
                //裁剪的坐标(x,y)
                roleData.role.width / roleData.col * roleData.j, roleData.role.height / roleData.row*roleData.i,
                //裁剪宽高
                roleData.role.width / roleData.col, roleData.role.height / roleData.row,
                //画布中x,y坐标
                roleData.x,extra.y,
                //图像在画布中绘制大小
                roleData.role.width / 3,roleData.role.height / 3
                )
            }

            //绘制台阶
            function drawSteps(){
                for(let a = 0;a < steps.mystep.length;a++){//遍历数组
                //绘制
                    ctx.drawImage(steps.mystep[a].bg,
                    steps.mystep[a].x,steps.mystep[a].y,
                    steps.mystep[a].width,steps.mystep[a].height)
                }
            }

            //绘制金币
            function drawCoins(){
                for(let e = 0;e<coins.mycoins.length;e++){
                    //图片对象
                    ctx.drawImage(coins.mycoins[e].bg,
                    //剪裁的坐标
                    coins.mycoins[e].cutx,coins.mycoins[e].cuty,
                    //剪裁的宽高
                    coins.mycoins[e].cutwidth,coins.mycoins[e].cutheight,
                    //金币在画布中的坐标
                    coins.mycoins[e].x,coins.mycoins[e].y,
                    //金币在画布中的宽高
                    coins.mycoins[e].cutwidth/3,coins.mycoins[e].cutheight/3)
                }
            }

            //绘制得分
            function drawScore(){
                ctx.fillStyle = "#fff"
                ctx.font = "32px 华文新魏"
                //绘制内容,内容绘制在画布上的x坐标,y坐标
                ctx.fillText(`得分: ${systemDate.score}`,10,30)
            }

            //绘制障碍
            function drawThorn(){
                for(let k = 0;k < thorns.mythorns.length;k++){
                    ctx.drawImage(thorns.mythorns[k].bg,
                    thorns.mythorns[k].x,thorns.mythorns[k].y,
                    thorns.mythorns[k].width/10,thorns.mythorns[k].height/10)
                }
            }

            //绘制生命值
            function draeLife(){
                ctx.fillStyle = "white"
                ctx.font = "32px 华文新魏"
                ctx.fillText(`生命值:${systemDate.life}`,650,30) 
            }

            function draw(){
                drawbackground()
                drawRole()
                drawSteps()
                drawCoins()
                drawScore()
                drawThorn()
                draeLife()
            }

            function changeData(){

                //背景移动
                firstbg.x = firstbg.x - systemDate.bgMovespeed
                secondbg.x = secondbg.x - systemDate.bgMovespeed

                //如果第一张背景移出画布
                if(firstbg.x <= -canvas.width){
                    //将第一张放在第二张之后
                    firstbg.x = secondbg.x+canvas.width
                    //若第二张背景移出画布
                }else if(secondbg.x <= -canvas.width){
                    //将第二张放在第一张之后
                    secondbg.x = firstbg.x+canvas.width
                }

                //让小人跑起来
                roleData.control1 = roleData.control1 + 0.09
                roleData.control = Math.floor(roleData.control1)//放缓人物奔跑速度
                if(roleData.control == 1){
                    //改变奔跑状态
                    roleData.j++
                    if(roleData.j>=4){
                        roleData.j = 0
                    }
                    roleData.control1 = 0
                    roleData.control = 0
                }

                //让小人跳跳跳
                if(roleData.jump == 1){
                    extra.y = extra.y - roleData.upspeed
                    roleData.upspeed = roleData.upspeed - systemDate.a
                   /*  //让人物条上台阶
                    for(let o=0;o<steps.mystep.length;o++){
                        if(extra.y<=steps.mystep[o].y
                        &&(roleData.x+roleData.role.width/3)>=steps.mystep[o].x
                        &&(roleData.x<=(steps.mystep[o].x+))
                    } */
                    
                    //若下落回原来的位置,停止其跳跃
                    if(extra.y >=(systemDate.horizon - roleData.role.height / roleData.row)){
                        roleData.jump = 0
                        extra.y = systemDate.horizon - roleData.role.height / roleData.row
                        roleData.upspeed = systemDate.upspeed
                    }
                }
    

                //向数组中添加台阶数据
                steps.control1 = steps.control1 + Math.random()*0.03
                steps.control = Math.floor(steps.control1)//控制往数组里添加台阶的速度
                if(steps.control == 1){
                    //随机让who出现0,1
                    steps.who = Math.floor(Math.random()*2)
                    let b = steps.mystep.length
                    //随机让c出现0,1
                    let c = Math.floor(Math.random()*2)
                    if(steps.who == 0){//若who为0,往数组中添加台阶1
                    //往数组里添加一个空对象,台阶的数据都保存在对象中
                        steps.mystep[b] = new Object
                        steps.mystep[b].bg = step1.step1//图片
                        steps.mystep[b].x = steps.x//x坐标
                        steps.mystep[b].y = steps.y[c]
                        steps.mystep[b].width = step1.width
                        steps.mystep[b].height = step1.height
                    }else if(steps.who == 1){
                        steps.mystep[b] = new Object
                        steps.mystep[b].bg = step2.step2
                        steps.mystep[b].x = steps.x
                        steps.mystep[b].y = steps.y[c]
                        steps.mystep[b].width = step2.width
                        steps.mystep[b].height = step2.height
                    }
                    steps.control1 = 0
                    steps.control = 0
                }

                //向数组中添加障碍信息
                thorns.control1 = thorns.control1 + Math.random()*0.02
                thorns.control = Math.floor(thorns.control1)//控制往数组里添加台阶的速度
                if(thorns.control == 1){
                    //随机让who出现0,1
                    thorns.who = Math.floor(Math.random()*2)
                    let l = thorns.mythorns.length
                    //随机让c出现0,1
                    let m = Math.floor(Math.random()*2)
                    if(thorns.who == 0){//若who为0,往数组中添加台阶1
                    //往数组里添加一个空对象,台阶的数据都保存在对象中
                        thorns.mythorns[l] = new Object
                        thorns.mythorns[l].id ="thorn1" 
                        thorns.mythorns[l].bg = thorn1.thorn1//图片
                        thorns.mythorns[l].x = thorns.x//x坐标
                        thorns.mythorns[l].y = thorns.y-thorn1.height/10+10
                        thorns.mythorns[l].width = thorn1.width
                        thorns.mythorns[l].height = thorn1.height
                    }else if(thorns.who == 1){
                        thorns.mythorns[l] = new Object
                        thorns.mythorns[l].id ="thorn2" 
                        thorns.mythorns[l].bg = thorn2.thorn2
                        thorns.mythorns[l].x = thorns.x
                        thorns.mythorns[l].y = thorns.y-thorn2.height/10+30
                        thorns.mythorns[l].width = thorn2.width/1.2
                        thorns.mythorns[l].height = thorn2.height/1.8
                    }
                    thorns.control1 = 0
                    thorns.control = 0
                }
                

                //移动台阶
                for(let d = 0;d < steps.mystep.length;d++){
                    steps.mystep[d].x = steps.mystep[d].x - steps.movespeed
                    if(steps.mystep[d].x < -canvas.width){
                        steps.mystep.shift()//删除数组的第一个元素
                    }
                }

                //移动障碍
                for(let j = 0;j< thorns.mythorns.length;j++){
                    thorns.mythorns[j].x = thorns.mythorns[j].x - thorns.movespeed
                    if(thorns.mythorns[j].x < -canvas.width){
                        thorns.mythorns.shift()//删除数组的第一个元素
                    }
                } 

                //障碍与人物碰撞
                let x3 = roleData.x//人物左边的坐标
                let x4 = x3 + roleData.role.width / 3//人物右边坐标
                let y3 = extra.y//人物头顶坐标
                let y4 = y3 + roleData.role.height / 3
                for(let m = 0; m<thorns.mythorns.length;m++){
                    if((thorns.mythorns[m].x+13)>x3&&(thorns.mythorns[m].x+13)<x4&&(thorns.mythorns[m].y+13)>y3&&(thorns.mythorns[m].y+13)<y4){
                        thorns.mythorns[m].x = -50
                        systemDate.life--
                    }
                }

                //向数组中添加金币信息
                coins.control1 = coins.control1 + Math.random()*0.1
                coins.control = Math.floor(coins.control1)//控制添加速度

                if(coins.control == 1){
                    coins.who = Math.floor(Math.random()*2)//数据放在数组的末尾
                    let f = coins.mycoins.length//拿到最后的一个数据
                    let g = Math.floor(Math.random()*5)
                    if(coins.who == 0){
                        coins.mycoins[f] = new Object
                        coins.mycoins[f].id = "coin1"
                        coins.mycoins[f].bg = coin1.coin1
                        coins.mycoins[f].cutx = 0
                        coins.mycoins[f].cuty = 0
                        coins.mycoins[f].cutwidth = 80
                        coins.mycoins[f].cutheight = 78
                        coins.mycoins[f].x = coins.x
                        coins.mycoins[f].y = coins.y[g]
                    }else if(coins.who == 1){
                        coins.mycoins[f] = new Object
                        coins.mycoins[f].id = "coin2"
                        coins.mycoins[f].bg = coin2.coin2
                        coins.mycoins[f].cutx = 0
                        coins.mycoins[f].cuty = 0
                        coins.mycoins[f].cutwidth = 80
                        coins.mycoins[f].cutheight = 78
                        coins.mycoins[f].x = coins.x
                        coins.mycoins[f].y = coins.y[g]
                    }
                    coins.control1=0
                    coins.control=0
                }
                

                //移动金币
                //遍历取出金币进行移动
                for(let h = 0;h<coins.mycoins.length;h++){
                    coins.mycoins[h].x = coins.mycoins[h].x - coins.movespeed
                    if(coins.mycoins[h].x <= -canvas.width){
                        coins.mycoins.shift()
                    }
                }

                //旋转金币
                coins.rotatetime1 = coins.rotatetime1 + 0.3
                coins.rotatetime = Math.floor(coins.rotatetime1)
                if(coins.rotatetime == 1){
                    //遍历数组取出金币进行旋转
                    for(let i = 0;i < coins.mycoins.length; i++){
                        coins.mycoins[i].cutx = coins.cutx[coins.rotate]
                        coins.mycoins[i].cutwidth = coins.cutwidth[coins.rotate]
                    }
                    //更改下标值
                    coins.rotate++
                    if(coins.rotate >= 9){
                        coins.rotate = 0
                    }
                    coins.rotatetime = 0
                    coins.rotatetime1 =0
                }

                //人物与金币碰撞
                let x1 = roleData.x//人物左边的坐标
                let x2 = x1 + roleData.role.width / 3//人物右边坐标
                let y1 = extra.y//人物头顶坐标
                let y2 = y1 + roleData.role.height / 3
                for(let j = 0; j<coins.mycoins.length;j++){
                    if((coins.mycoins[j].x+13)>x1&&(coins.mycoins[j].x+13)<x2&&(coins.mycoins[j].y+13)>y1&&(coins.mycoins[j].y+13)<y2){
                        coins.mycoins[j].x = -50
                        if(coins.mycoins[j].id == "coin1"){
                            systemDate.score += 2
                        } else if(coins.mycoins[j].id =="coin2"){
                            systemDate.score += 1
                        }
                    }
                }
                

                //结束游戏
                if(systemDate.life == 0){
                    extra.y = extra.y - roleData.upspeed
                    roleData.upspeed = roleData.upspeed - systemDate.a
                    if(extra.y >=580){
                        ctx.fillStyle = "red"
                        ctx.font="64px 华文琥珀"
                        ctx.fillText("游戏结束",300,270) 
                        clearInterval(game)
                    }
                }
                //监听事件
                window.onkeydown = function(e){//用于接收事件参数
                //如果按下空格键
                    if(e.key == " "){
                        roleData.jump = 1
                    }
                }

            }

            function main(){
                game = window.setInterval(()=>{
                    //清空画布:要清除区域的x坐标,要清楚区域的y坐标,清除区域的宽度,高度
                    ctx.clearRect(0,0,canvas.width,canvas.height)
                    draw()
                    changeData()
                },20)
            }

            main()
        }
    </script>
</head>
<body>
    <canvas width="800px" height="530px"></canvas>
    <img id="bg1" src="img/background.jpg" alt="">
    <img id="bg2" src="img/background.jpg" alt="">
    <img id="role" src="img/role.png" alt="">
    <img id="step1" src="img/step1.png" alt="">
    <img id="step2" src="img/step2.png" alt="">
    <img id="coin1" src="img/coin1.png" alt="">
    <img id="coin2" src="img/coin2.png" alt="">
    <img id="thorn1" src="img/thorn1.png" alt="">
    <img id="thorn2" src="img/thorn2.png" alt="">
</body>
</html>

采用了画布的布局方式,使用了drawImage()、setTime()、window.open()等一系列监听事件,其中画布中的元素均采用先定义在绘制在调用等方式,整体框架比较简单,只是需要注意各变量之间的对应。该网页版小游戏能够实现功能,由于上传时吃传成静态页面了。
在这里插入图片描述

本文地址:https://blog.csdn.net/wyhcczz/article/details/108559039

如您对本文有疑问或者有任何想说的,请点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网