• [Canvas]Bowman


    试玩请点此下载并用浏览器打开index.html

    这个游戏是弓箭射击敌人,用方向键移动人物,空格键发射箭枝。

    图例:

    代码:

    <!DOCTYPE html>
    <html lang="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <head>
         <title>弓箭手打怪物 19.3.8 9:23 by:逆火狂飙 horn19782016@163.com</title>
         
         <style>
         #canvas{
            background:#ffffff;
            cursor:pointer;
            margin-left:10px;
            margin-top:10px;
            -webkit-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
            -moz-box-shadow:3px 3px 6px rgba(0,0,0,0.5);
            box-shadow:3px 3px 6px rgba(0,0,0,0.5);
         }
         
         #controls{
            margin-top:10px;
            margin-left:15px;
         }
         </style>
         
        </head>
    
         <body onload="init()">
            <div id="controls">
                <input id='animateBtn' type='button' value='开始'/>
            </div>
         
            <canvas id="canvas" width="160px" height="160px" >
                出现文字表示你的浏览器不支持HTML5
            </canvas>
         </body>
    </html>
    <script type="text/javascript">
    <!--
    var paused=true;
    animateBtn.onclick=function(e){
        paused=! paused;
        
        if(paused){
            animateBtn.value="开始";    
    
        }else{    
            animateBtn.value="停止";
            window.requestAnimationFrame(animate); 
        }
    }
    
    var BL=32;// Block length,边长
    var ctx;// 绘图环境
    var terrain;// 地形
    var hero;// 英雄/主角
    var arrows;// 箭矢数组
    var monsterMng;// 怪物管理者
    
    //------------------------------------
    //  初始化函数
    //------------------------------------
    function init(){
        // init Canvas
        var canvas=document.getElementById('canvas');
        canvas.width =40*BL;
        canvas.height=18*BL;
        ctx=canvas.getContext('2d');
        
        terrain=new Terrain();
        hero=new Hero();
        arrows=new Array();
        monsterMng=new MonsterMng();
            
        // 响应键盘事件
        canvas.addEventListener('keydown', doKeyDown, true);
        canvas.focus();  
        window.addEventListener('keydown', doKeyDown, true);
    };
    
    //------------------------------------
    // 响应键盘事件
    //------------------------------------
    function doKeyDown(e) {
        var keyID = e.keyCode ? e.keyCode :e.which;
        if(keyID === 38 || keyID === 87)  { // up arrow and W
            hero.move('up');
            e.preventDefault();
        }
        if(keyID === 39 || keyID === 68)  { // right arrow and D
            hero.move('right');
            e.preventDefault();
        }
        if(keyID === 40 || keyID === 83)  { // down arrow and S
            hero.move('down');
            e.preventDefault();
        }
        if(keyID === 37 || keyID === 65)  { // left arrow and A
            hero.move('left');
            e.preventDefault();
        }
    
        if(keyID === 32 )  { // SpaceBar
            var a=new Arrow(hero.x+BL/2,hero.y+BL/2,hero.direction);
            arrows.push(a);
            //console.log('arrows.length='+arrows.length);
            e.preventDefault();
        }
    }
    
    //------------------------------------
    // 更新各实例状态
    //------------------------------------
    function update(){
        for(var i=arrows.length-1;i>-1;i--){
            var arrow=arrows[i];
            var x=parseInt(arrow.x / 32,10);
            var y=parseInt(arrow.y / 32,10);
    
            // 箭矢射中怪物所在
            if(monsterMng.shoot(x,y)==true){
                //monsterMng.setValue(x,y,2);
                arrows.splice(i,1);
                break;
            }
            
            // 箭矢射中树木房屋等障碍物
            if(terrain.getValue(x,y)!=0){
                arrows.splice(i,1);
            }
        }
        
        var heroX=parseInt(hero.x/BL,10);
        var heroY=parseInt(hero.y/BL,10);
            
        // 看英雄碰到怪物没
        if(monsterMng.isTouched(heroX,heroY)){
            hero.setDead();
        }
        
        // 游戏结束条件
        if(hero.alive==false){ // 英雄死亡
            alert("You lost!");
            init();
        }
        
        if(monsterMng.noMonster()){ // 怪物全清除
            alert("You Win!");
            init();
        }
    }
    
    //------------------------------------
    // 在ctx里画出各实例
    //------------------------------------
    function draw(){
        // Clear Canvas
        ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
        ctx.fillStyle="#ffffff";
        ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);
        
        terrain.paint(ctx);    // 画地形
        
        // 画怪物
        monsterMng.paint(ctx);
        
        // 画箭矢
        for(var i=0;i<arrows.length;i++){
            var arrow=arrows[i];
            arrow.paint(ctx);
        }
        
        hero.paint(ctx);    // 画英雄
    }
    
    //------------------------------------
    // 运行动画
    //------------------------------------
    function animate(){
        if(!paused){
            update();
            draw();
            window.requestAnimationFrame(animate); /// 让浏览器自行决定帧速率
        }
    }
    
    //------------------------------------
    //  常规函数:角度得到弧度
    //------------------------------------
    function getRad(degree){
        return degree/180*Math.PI;
    }
    
    //------------------------------------
    //生成从minNum到maxNum的随机数
    //------------------------------------
    function randomNum(minNum,maxNum){ 
        switch(arguments.length){ 
            case 1: 
                return parseInt(Math.random()*minNum+1,10); 
            break; 
            case 2: 
                return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10); 
            break; 
                default: 
                    return 0; 
                break; 
        } 
    }
    
    //---------------------------------------------------地形类定义开始------------------------------------------------------------------->>
    Terrain=function(){
        this.files=["road.png",           //  0
                    "tree.png",            //  1
                    "farmerHouse.png",    //  2
                    "twoBuilding.png",    //  3
                    "threeBuilding.png",//  4
                    "bank.png",            //  5
                    "villa.png",];        //  6
        
        /*this.maps=new Array(
            [0,0,0,0,0],
            [0,0,1,0,0],
            [0,0,0,0,0],
            [0,2,0,0,0],
            [0,0,0,3,0],
        );*/
        
        this.maps=new Array(
            [1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,],
            [0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,0,2,0,0,2,0,0,0,0,0,0,3,0,0,0,0,],
            [0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,5,0,0,6,6,0,0,0,],
            [0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,2,2,2,2,2,2,2,0,0,1,0,0,0,0,3,0,],
            [0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,3,0,],
            [0,0,0,2,0,0,2,0,0,0,0,0,0,3,0,0,3,0,],
            [0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,4,0,],
            [0,0,0,0,0,0,0,0,0,0,5,0,0,6,6,0,4,0,],
            [0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,4,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,5,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,],
            [0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,5,0,],
            [0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,0,2,0,0,2,0,0,0,0,0,2,3,0,0,6,0,],
            [0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,6,0,],
            [0,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,6,0,],
            [0,0,0,0,0,0,0,0,0,0,5,0,0,6,6,0,0,0,],
            [0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,],
            [0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,2,0,0,0,4,0,0,0,0,0,0,0,],
            [0,0,0,2,0,0,2,0,0,0,0,0,0,3,0,0,0,0,],
            [0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,],
            [0,2,2,2,2,2,2,2,4,0,0,0,0,0,0,0,0,0,],
            [0,0,0,0,0,0,0,0,0,0,5,0,0,6,6,0,0,0,],
            [0,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,],
        );
    }
    Terrain.prototype={
        files:[],
        maps:[],
        
        // 在ctx画自己
        paint:function(ctx){
            for(var i=0;i<this.maps.length;i++){
                var arr=this.maps[i];
                
                for(var j=0;j<arr.length;j++){
                    var value=arr[j];
                    
                    var img=new Image();
                    img.src=this.files[value];
                    
                    ctx.drawImage(img,i*BL,j*BL);
                }
            }
        },
        
        // 是否有障碍
        hasObstacle:function(i,j){
            if(i<0 || i>=this.maps.length){
                return true;
            }
            var arr=this.maps[i];
            if(j<0 || j>=arr.length){
                return true;
            }
            var value=arr[j];
            if(value==0){
                return false;
            }else{
                return true;
            }
        },
    
        // 取值
        getValue:function(i,j){
            if(i<0 || i>=this.maps.length){
                return undefined;
            }
            var arr=this.maps[i];
            if(j<0 || j>=arr.length){
                return undefined;
            }
            var value=arr[j];
            return value;
        },
        
        // 设值
        setValue:function(i,j,value){
            if(i<0 || i>=this.maps.length){
                return undefined;
            }
            var arr=this.maps[i];
            if(j<0 || j>=arr.length){
                return undefined;
            }
            arr[j]=value;
        },
    }
    //---------------------------------------------------地形类定义结束-------------------------------------------------------------------<<
    
    //---------------------------------------------------英雄类定义开始------------------------------------------------------------------->>
    Hero=function(){
        this.pngs=[
            {left:0,top:10,40,height:40},
            {left:0,top:68,40,height:40},
            {left:0,top:123,40,height:40},
            {left:0,top:180,40,height:40},
        ];
    }
    Hero.prototype={
        pngs:[],
        x:160,
        y:160,
        xTo:160,
        yTo:160,
        step:32,
        direction:'up',
        alive:true,
        
        setDead:function(){
            //console.log('Hero dead');
            this.alive=false;
        },
        
        paint:function(ctx){
            if(this.alive){
                var img=new Image();
                img.src='bowman.png';
                
                var index=0;
                if(this.direction=='up'){
                    index=3;
                }
                if(this.direction=='down'){
                    index=0;
                }
                if(this.direction=='left'){
                    index=1;
                }
                if(this.direction=='right'){
                    index=2;
                }
                var pos=this.pngs[index];
                ctx.drawImage(img,pos.left,pos.top,pos.width,pos.height,this.x,this.y,32,32);
            }else{
                var img=new Image();
                img.src='skull.png';
                ctx.drawImage(img,this.x,this.y);
            }
        },
        
        move:function(direction){
            if(this.alive){
                this.direction=direction;
                
                if(this.direction=='up'){
                    this.yTo-=this.step;
                }
                if(this.direction=='down'){
                    this.yTo+=this.step;
                }
                if(this.direction=='left'){
                    this.xTo-=this.step;
                }
                if(this.direction=='right'){
                    this.xTo+=this.step;
                }
                
                if(terrain.getValue(this.xTo/this.step,this.yTo/this.step)==0){
                    this.x=this.xTo;
                    this.y=this.yTo;
                }else{
                    this.xTo=this.x;
                    this.yTo=this.y;
                }
            }
        }
    }
    //---------------------------------------------------英雄类定义结束-------------------------------------------------------------------<<
    
    //---------------------------------------------------怪物类定义开始------------------------------------------------------------------->>
    Monster=function(x,y,step,direction){
        this.x=x;
        this.y=y;
        this.step=step;
        this.direction=direction;
        
        this.files=["monster.png",               //  0
                    "monsterDead.png",            //  1
                    "monsterUpdated.png",        //  2
                    "monsterUpdatedDead.png",];    //  3
    }
    Monster.prototype={
        x:0,            // 横坐标,乘以32等于真正的横坐标
        y:0,            // 纵坐标,乘以32等于真正的纵坐标
        step:1,            // 行走速度
        direction:'',    // 方向
        files:[],        // 显示图片
        alive:true,        // 是否活着
        
        // 步长加倍
        doubleStep:function(){
            this.step*=2;
        },
        
        // 被射中了
        beShooted:function(){
            this.alive=false;
        },
        
        // 移动
        move:function(){
            if(this.alive){
                
            }
        },
        
        turnAround:function(){
            var arr=['left','right','up','down',];
            var newArr=[];
            for(var i=0;i<arr.length;i++){
                if(this.direction!=arr[i]){
                    newArr.push(arr[i]);
                }
            }
            console.log("newArr="+newArr);
            var index=randomNum(0,newArr.length-1);
            console.log("index="+index);
            this.direction=newArr[index];
        },
        
        paint:function(ctx){
            var img=new Image();
            
            if(this.alive==true && this.step==1){
                img.src=this.files[0];
            }
            if(this.alive==false && this.step==1){
                img.src=this.files[1];
            }
            if(this.alive==true && this.step==2){
                img.src=this.files[2];
            }
            if(this.alive==false && this.step==2){
                img.src=this.files[3];
            }
            
            ctx.drawImage(img,this.x,this.y);
        },
        
    }
    //---------------------------------------------------怪物类定义结束-------------------------------------------------------------------<<
    
    //---------------------------------------------------怪物管理类定义开始------------------------------------------------------------------->>
    MonsterMng=function(){
        this.generateMonsters();
    }
    MonsterMng.prototype={
        monsters:[],
        
        // 生成怪物
        generateMonsters:function(){
            this.monsters=new Array();
            this.monsters.push(new Monster(1*BL,1*BL,1,"right"));
            this.monsters.push(new Monster(1*BL,10*BL,1,"right"));
            this.monsters.push(new Monster(16*BL,16*BL,1,"right"));
            this.monsters.push(new Monster(10*BL,13*BL,1,"right"));
            this.monsters.push(new Monster(10*BL,10*BL,1,"right"));
        },
        
        // 画怪物
        paint:function(ctx){
            for(var i=0;i<this.monsters.length;i++){
                var m=this.monsters[i];
                m.paint(ctx);
            }
        },
        
        // 判断怪物还是否存在
        hasMonster:function(){
            return true;
        },
    
        // 用箭射击怪物
        shoot:function(arrowX,arrowY){
            for(var i=0;i<this.monsters.length;i++){
                var monster=this.monsters[i];
                
                // 变量名不宜太短,词必答意
                var monsterX=parseInt(monster.x/BL,10);
                var monsterY=parseInt(monster.y/BL,10);
                
                //console.log(arrowX,arrowY,monsterX,monsterY);
                if(monsterX==arrowX && monsterY==arrowY && monster.alive==true){
                    monster.beShooted();
                    //console.log('shooted',arrowX,arrowY,monsterX,monsterY);
                    return true;
                }
            }
            
            return false;
        },
        
        // 看英雄是否碰到怪物
        isTouched:function(heroX,heroY){
            for(var i=0;i<this.monsters.length;i++){
                var monster=this.monsters[i];
    
                var monsterX=parseInt(monster.x/BL,10);
                var monsterY=parseInt(monster.y/BL,10);
    
                console.log('isTouched',heroX,heroY,monsterX,monsterY);
                if(heroX==monsterX && heroY==monsterY && monster.alive==true){
                    console.log('touched',heroX,heroY,monsterX,monsterY);
                    return true;
                }
            }
            
            return false;
        },
        
        // 看有没有怪物了
        noMonster:function(heroX,heroY){
            var count=0;
        
            for(var i=0;i<this.monsters.length;i++){
                var monster=this.monsters[i];
    
                if(monster.alive){
                    count++;
                }
            }
            
            return count==0;
        },
    }
    //---------------------------------------------------怪物管理类定义结束-------------------------------------------------------------------<<
    
    //---------------------------------------------------箭矢类定义开始------------------------------------------------------------------->>
    Arrow=function(x,y,direction){
        this.x=x;
        this.y=y;
        this.direction=direction;
    }
    Arrow.prototype={
        x:0,
        y:0,
        velocity:1,// 飞行速度
        len:16,// 箭杆长
        direction:'',
        
        // method
        paint:function(ctx){
            var x1=this.x,y1=this.y;
            var leaf=4;//箭头箭羽长
            var x2,y2,x3,y3;
            var angle=getRad(15);
        
            if(this.direction=='up'){
                this.y-=this.velocity;
                y1=this.y-this.len;
                x1=this.x;
                
                y2=y1+leaf*Math.cos(angle);
                x2=x1-leaf*Math.sin(angle);
                y3=y2;
                x3=x1+leaf*Math.sin(angle);
            }
            if(this.direction=='down'){
                this.y+=this.velocity;
                y1=this.y+this.len;
                x1=this.x;
                y2=y1-leaf*Math.cos(angle);
                x2=x1-leaf*Math.sin(angle);
                y3=y2;
                x3=x1+leaf*Math.sin(angle);
            }
            if(this.direction=='left'){
                this.x-=this.velocity;
                x1=this.x-this.len;
                y1=this.y;
                
                x2=x1+leaf*Math.cos(angle);
                y2=y1-leaf*Math.sin(angle);
                x3=x2;
                y3=y1+leaf*Math.sin(angle);
            }
            if(this.direction=='right'){
                this.x+=this.velocity;
                x1=this.x+this.len;
                y1=this.y;
                
                x2=x1-leaf*Math.cos(angle);
                y2=y1-leaf*Math.sin(angle);
                x3=x2;
                y3=y1+leaf*Math.sin(angle);
            }
    
            ctx.beginPath();
            ctx.lineWidth = 2;
            ctx.strokeStyle = "#ff0000";
            ctx.lineTo(this.x,this.y);
            ctx.lineTo(x1,y1);
            ctx.lineTo(x2,y2);
            ctx.lineTo(x3,y3);
            ctx.lineTo(x1,y1);
    
            ctx.stroke();
            ctx.closePath();
        },
    }
    //---------------------------------------------------箭矢类定义结束-------------------------------------------------------------------<<
    //-->
    </script>

    2019年3月8日12点32分

  • 相关阅读:
    python读取excel保存到mysql
    python读取mysql返回json
    在C#后台使用MD5值对文件进行加
    使用文件流的形式上传大文件
    IE8兼容性问题
    解决 CentOS 下找不到库文件的问题
    openssl/ossl_typ.h:没有那个文件或目录
    解决 VSCode 进行 C/C++ 开发时 gcc 依赖缺失问题
    VSCode 中进行 C/C++ 开发需要的配置文件
    记一下使用 WeBASE 搭建自己的联盟链过程
  • 原文地址:https://www.cnblogs.com/heyang78/p/10495066.html
Copyright © 2020-2023  润新知