ホームページ > ウェブフロントエンド > H5 チュートリアル > HTML5ゲームフレームワーク cnGameJS開発記録 - エルフオブジェクト編

HTML5ゲームフレームワーク cnGameJS開発記録 - エルフオブジェクト編

黄舟
リリース: 2017-03-25 15:05:53
オリジナル
1835 人が閲覧しました

目次に戻る

1. スプライトオブジェクト(スプライト)とは何ですか?

いわゆるエルフ オブジェクトは、ゲーム内で動作する要素です。スーパー マリオを例にとると、メアリーと敵はすべてエルフ オブジェクトとみなされます。 cnGameJS フレームワークでは、スプライト オブジェクトには次の特性があります:

1. アニメーションの追加: 前回のアニメーションの記事では、cnGameJS がフレーム アニメーションを実装する方法を紹介しました。スプライトオブジェクトとしてアニメーションの使用者となります。たとえば、メアリーをさまざまな方向に歩くように制御すると、メアリーは歩行アニメーションを生成します。

2. 画像を含める : 他のスプライト オブジェクトの場合、モーション アニメーションが必要ない場合は、画像を使用するだけで済みます。

3. さまざまな種類の動きを実行できます : スプライト オブジェクトをさまざまな方向に、さまざまな加速度で動かすことができます。

2. デモ表示

ここでは、メアリーの動作(等加速度動作)をマウスで制御します。メアリーが動くときは、アニメーションを使用し、キーボードの左右の矢印キーを使ってメアリーの動きを制御します

効果:

HTML5ゲームフレームワーク cnGameJS開発記録 - エルフオブジェクト編

コード:

<body>
<div><canvas id="gameCanvas">请使用支持canvas的浏览器查看</canvas></div>
</body>
<script src="http://files.cnblogs.com/Cson/cnGame_v1.0.js"></script>
<script>
var Src="http://images.cnblogs.com/cnblogs_com/Cson/290336/o_player.png";

/* 初始化 */
cnGame.init(&#39;gameCanvas&#39;,{width:300,height:150});
var floorY=cnGame.height-40;
var gameObj=(function(){
    /* 玩家对象 */
    var player=function(options){
        this.init(options);    
        this.speedX=0;
        this.moveDir;
        this.isJump=false;
    }
    cnGame.core.inherit(player,cnGame.Sprite);
    player.prototype.initialize=function(){
        this.addAnimation(new cnGame.SpriteSheet("playerRight",Src,{frameSize:[50,60],loop:true,width:150,height:60}));
        this.addAnimation(new cnGame.SpriteSheet("playerLeft",Src,{frameSize:[50,60],loop:true,width:150,height:120,beginY:60}));
    }
    player.prototype.moveRight=function(){
        if(cnGame.core.isUndefined(this.moveDir)||this.moveDir!="right"){
            this.moveDir="right";
            this.speedX<0&&(this.speedX=0);
            this.setMovement({aX:10,maxSpeedX:15});
            this.setCurrentAnimation("playerRight");
        }
    }
    player.prototype.moveLeft=function(){
        if(cnGame.core.isUndefined(this.moveDir)||this.moveDir!="left"){
            this.moveDir="left";
            this.speedX>0&&(this.speedX=0);
            this.setMovement({aX:-10,maxSpeedX:15});
            this.setCurrentAnimation("playerLeft");
        }
    }
    player.prototype.stopMove=function(){
        
        if(this.speedX<0){
            this.setCurrentImage(Src,0,60);
        }
        else if(this.speedX>0){
            this.setCurrentImage(Src);
        }    
        this.moveDir=undefined;
        this.resetMovement();
        
    }
    player.prototype.update=function(){
        player.prototype.parent.prototype.update.call(this);//调用父类update
if(cnGame.input.isPressed("right")){
            this.moveRight();    
        }
        else if(cnGame.input.isPressed("left")){
            this.moveLeft();
        }
        else{
            this.stopMove();
        }
        
        
    }

    return {
        initialize:function(){
            cnGame.input.preventDefault(["left","right","up","down"]);
            this.player=new player({src:Src,width:50,height:60,x:0,y:floorY-60});
            this.player.initialize();
        },
        update:function(){
            this.player.update();
        },
        draw:function(){
            this.player.draw();
        }

    };
})();
cnGame.loader.start([Src],gameObj);
</script>
复制代码
ログイン後にコピー

3. 実装

アニメーション化された spriteSheet オブジェクトと同様に、sprite オブジェクトも初期化、 更新とお絵描き

まずスプライトの初期化関数を見てみましょう:

/**
         *初始化
        **/
        init:function(options){
            
            /**
             *默认对象
            **/    
            var defaultObj={
                x:0,
                y:0,
                imgX:0,
                imgY:0,
                width:32,
                height:32,
                angle:0,
                speedX:0,
                speedY:0,
                aX:0,
                aY:0,
                maxSpeedX:postive_infinity,
                maxSpeedY:postive_infinity,
                maxX:postive_infinity,
                maxY:postive_infinity,
                minX:-postive_infinity,
                minY:-postive_infinity
            };
            options=options||{};
            options=cg.core.extend(defaultObj,options);
            this.x=options.x;
            this.y=options.y;
            this.angle=options.angle;
            this.width=options.width;
            this.height=options.height;
            this.angle=options.angle;
            this.speedX=options.speedX;
            this.speedY=options.speedY;
            this.aX=options.aX;
            this.aY=options.aY;
            this.maxSpeedX=options.maxSpeedX;
            this.maxSpeedY=options.maxSpeedY;
            this.maxX=options.maxX;
            this.maxY=options.maxY;
            this.minX=options.minX;
            this.minY=options.minY;

            
            this.spriteSheetList={};
            if(options.src){    //传入图片路径
                this.setCurrentImage(options.src,options.imgX,options.imgY);
            }
            else if(options.spriteSheet){//传入spriteSheet对象
                this.addAnimation(options.spriteSheet);        
                setCurrentAnimation(options.spriteSheet);
            }
            
        }
ログイン後にコピー

パラメータは多くあり、主にオブジェクトの位置、回転角度、サイズ、xy方向の速度、xy方向の加速度、xy方向の最大速度が含まれます。さらに、ユーザーが画像アドレスを渡すと、現在のスプライト オブジェクトがその画像を使用するように設定されます。それ以外の場合は、spriteSheet アニメーションが使用されます。

まず、スプライト オブジェクトが画像をどのように使用するかを確認します:

/**
         *设置当前显示图像
        **/
        setCurrentImage:function(src,imgX,imgY){
            if(!this.isCurrentImage(src,imgX,imgY)){
                imgX=imgX||0;
                imgY=imgY||0;
                this.image=cg.loader.loadedImgs[src];    
                this.imgX=imgX;
                this.imgY=imgY;    
                this.spriteSheet=undefined;
            }
        },
ログイン後にコピー

まず、画像が現在使用されているかどうかを確認し、使用されていない場合は、ローダーからダウンロードされた画像オブジェクトを取得します (ゲームの開始時にすべての画像リソースがダウンロードされています)。 spriteSheet を未定義 (spriteSheet アニメーションを使用しないことを意味します) に設定して、スプライト オブジェクトが画像を使用できるようにします。

アニメーションの使用方法をもう一度見てください:

/**
         *设置当前显示动画
        **/
        setCurrentAnimation:function(id){//可传入id或spriteSheet
            if(!this.isCurrentAnimation(id)){
                if(cg.core.isString(id)){
                    this.spriteSheet=this.spriteSheetList[id];
                    this.image=this.imgX=this.imgY=undefined;
                }
                else if(cg.core.isObject(id)){
                    this.spriteSheet=id;
                    this.addAnimation(id);
                    this.image=this.imgX=this.imgY=undefined;
                }
            }
        
        },
复制代码
ログイン後にコピー

まず、受信した spriteSheet または spriteSheet の ID に基づいてアニメーションが使用されているかどうかを判断し、そうでない場合は、spriteSheet アニメーションを使用するようにスプライトを設定します。

アニメーションを使用するようにスプライト オブジェクトを設定した後、コア関数 up

date は spriteSheet の update を呼び出して、スプライトで使用されるアニメーションを更新します。spriteSheet の xy はスプライトの xy であることに注意してください:

if(this.spriteSheet){//更新spriteSheet动画
                this.spriteSheet.x=this.x
                this.spriteSheet.y=this.y;
                this.spriteSheet.update();
            }
ログイン後にコピー

こうしてスプライトが完成しました オブジェクトアニメーションの表示。

最後に、最後の機能、つまりスプライトを可変速度で移動できるようにする方法を実装する方法を見てみましょう。

可変速モーションを実行するには、初速度、経過時間、加速度の

変数を確立する必要があります。次に、可変速度の動きを担当する cnGameJS の部分を見てください:

/**
         *设置移动参数
        **/
        setMovement:function(options){
            isUndefined=cg.core.isUndefined;
            isUndefined(options.speedX)?this.speedX=this.speedX:this.speedX=options.speedX;
            isUndefined(options.speedY)?this.speedY=this.speedY:this.speedY=options.speedY;
            
            isUndefined(options.aX)?this.aX=this.aX:this.aX=options.aX;
            isUndefined(options.aY)?this.aY=this.aY:this.aY=options.aY;
            isUndefined(options.maxX)?this.maxX=this.maxX:this.maxX=options.maxX;
            isUndefined(options.maxY)?this.maxY=this.maxY:this.maxY=options.maxY;
            isUndefined(options.minX)?this.minX=this.minX:this.minX=options.minX;
            isUndefined(options.minY)?this.minY=this.minY:this.minY=options.minY;

            
            if(this.aX!=0){
                this.startTimeX=new Date().getTime();
                this.oriSpeedX=this.speedX;
                isUndefined(options.maxSpeedX)?this.maxSpeedX=this.maxSpeedX:this.maxSpeedX=options.maxSpeedX;    
            }
            if(this.aY!=0){
                this.startTimeY=new Date().getTime();
                this.oriSpeedY=this.speedY;
                isUndefined(options.maxSpeedY)?this.maxSpeedY=this.maxSpeedY:this.maxSpeedY=options.maxSpeedY;    
            }
            
        }
ログイン後にコピー

ユーザーが setMovement を呼び出すたびに、スプライトの初期速度と動きの開始時間が保持されます。このようにして、更新されるたびに、最初の 2 つの変数に基づいてスプライトの現在の速度を取得し、XY 方向の現在の変位を計算できます:

if(this.aX!=0){
                var now=new Date().getTime();
                var durationX=now-this.startTimeX;
                var speedX=this.oriSpeedX+this.aX*durationX/1000;
                if(this.maxSpeedX<0){
                    this.maxSpeedX*=-1;
                }
                if(speedX<0){
                    this.speedX=Math.max(speedX,this.maxSpeedX*-1)    ;
                }
                else{
                    this.speedX=Math.min(speedX,this.maxSpeedX);
                }
            }
            if(this.aY!=0){
                var now=new Date().getTime();
                var durationY=now-this.startTimeY;
                this.speedY=this.oriSpeedY+this.aY*durationY/1000;    
            }
            this.move(this.speedX,this.speedY);
复制代码
ログイン後にコピー

更新によりスプライトの変位が更新されるとき、3番目のステージ描画メソッドを通過してスプライトを描画します。

/**
         *绘制出sprite
        **/
        draw:function(){
            var context=cg.context;
            if(this.spriteSheet){
                this.spriteSheet.x=this.x
                this.spriteSheet.y=this.y;
                this.spriteSheet.draw();
            }
            else if(this.image){
                context.save()
                context.translate(this.x, this.y);
                context.rotate(this.angle * Math.PI / 180);
                context.drawImage(this.image,this.imgX,this.imgY,this.width,this.height,0,0,this.width,this.height);
                context.restore();
            }
        
        },
ログイン後にコピー

スプライトが spriteSheet アニメーションを使用する場合と画像を使用する場合では、draw メソッドの実行が異なることに注意してください。 sprieSheet アニメーションを使用する場合、draw メソッドは基本的に spriteSheet のdraw メソッドを呼び出してフレーム画像を描画します。スプライトが画像を使用する場合、画像を描画する前に画像を回転することもできます。

スプライト オブジェクトには、スプライト オブジェクトを含む四角形を返す getRect メソッドも用意されています。このメソッドは、スプライト オブジェクトと他のオブジェクト間の衝突を検出するのに便利です。衝突検出については、HTML5 ゲームフレームワーク cnGameJS 開発記録(衝突検出)をご覧ください

また、スプライトオブジェクトには、move、moveTo、resize、resizeTo などの関数もあり、位置やサイズの制御が容易になります。オブジェクトの。

スプライトオブジェクトの全ソースコード:

/**
 *
 *sprite对象
 *
**/
cnGame.register("cnGame",function(cg){
                                  
    var postive_infinity=Number.POSITIVE_INFINITY;            
    
    var sprite=function(id,options){
        if(!(this instanceof arguments.callee)){
            return new arguments.callee(id,options);
        }
        this.init(id,options);
    }
    sprite.prototype={
        /**
         *初始化
        **/
        init:function(options){
            
            /**
             *默认对象
            **/    
            var defaultObj={
                x:0,
                y:0,
                imgX:0,
                imgY:0,
                width:32,
                height:32,
                angle:0,
                speedX:0,
                speedY:0,
                aX:0,
                aY:0,
                maxSpeedX:postive_infinity,
                maxSpeedY:postive_infinity,
                maxX:postive_infinity,
                maxY:postive_infinity,
                minX:-postive_infinity,
                minY:-postive_infinity
            };
            options=options||{};
            options=cg.core.extend(defaultObj,options);
            this.x=options.x;
            this.y=options.y;
            this.angle=options.angle;
            this.width=options.width;
            this.height=options.height;
            this.angle=options.angle;
            this.speedX=options.speedX;
            this.speedY=options.speedY;
            this.aX=options.aX;
            this.aY=options.aY;
            this.maxSpeedX=options.maxSpeedX;
            this.maxSpeedY=options.maxSpeedY;
            this.maxX=options.maxX;
            this.maxY=options.maxY;
            this.minX=options.minX;
            this.minY=options.minY;

            this.spriteSheetList={};
            if(options.src){    //传入图片路径
                this.setCurrentImage(options.src,options.imgX,options.imgY);
            }
            else if(options.spriteSheet){//传入spriteSheet对象
                this.addAnimation(options.spriteSheet);        
                setCurrentAnimation(options.spriteSheet);
            }
            
        },
        /**
         *返回包含该sprite的矩形对象
        **/
        getRect:function(){
            return new cg.shape.Rect({x:this.x,y:this.y,width:this.width,height:this.height});
            
        },
        /**
         *添加动画
        **/
        addAnimation:function(spriteSheet){
            this.spriteSheetList[spriteSheet.id]=spriteSheet;    
        },
        /**
         *设置当前显示动画
        **/
        setCurrentAnimation:function(id){//可传入id或spriteSheet
            if(!this.isCurrentAnimation(id)){
                if(cg.core.isString(id)){
                    this.spriteSheet=this.spriteSheetList[id];
                    this.image=this.imgX=this.imgY=undefined;
                }
                else if(cg.core.isObject(id)){
                    this.spriteSheet=id;
                    this.addAnimation(id);
                    this.image=this.imgX=this.imgY=undefined;
                }
            }
        
        },
        /**
         *判断当前动画是否为该id的动画
        **/
        isCurrentAnimation:function(id){
            if(cg.core.isString(id)){
                return (this.spriteSheet&&this.spriteSheet.id===id);
            }
            else if(cg.core.isObject(id)){
                return this.spriteSheet===id;
            }
        },
        /**
         *设置当前显示图像
        **/
        setCurrentImage:function(src,imgX,imgY){
            if(!this.isCurrentImage(src,imgX,imgY)){
                imgX=imgX||0;
                imgY=imgY||0;
                this.image=cg.loader.loadedImgs[src];    
                this.imgX=imgX;
                this.imgY=imgY;    
                this.spriteSheet=undefined;
            }
        },
        /**
         *判断当前图像是否为该src的图像
        **/
        isCurrentImage:function(src,imgX,imgY){
            imgX=imgX||0;
            imgY=imgY||0;
            var image=this.image;
            if(cg.core.isString(src)){
                return (image&&image.srcPath===src&&this.imgX===imgX&&this.imgY===imgY);
            }
        },
        /**
         *设置移动参数
        **/
        setMovement:function(options){
            isUndefined=cg.core.isUndefined;
            isUndefined(options.speedX)?this.speedX=this.speedX:this.speedX=options.speedX;
            isUndefined(options.speedY)?this.speedY=this.speedY:this.speedY=options.speedY;
            
            isUndefined(options.aX)?this.aX=this.aX:this.aX=options.aX;
            isUndefined(options.aY)?this.aY=this.aY:this.aY=options.aY;
            isUndefined(options.maxX)?this.maxX=this.maxX:this.maxX=options.maxX;
            isUndefined(options.maxY)?this.maxY=this.maxY:this.maxY=options.maxY;
            isUndefined(options.minX)?this.minX=this.minX:this.minX=options.minX;
            isUndefined(options.minY)?this.minY=this.minY:this.minY=options.minY;

            
            if(this.aX!=0){
                this.startTimeX=new Date().getTime();
                this.oriSpeedX=this.speedX;
                isUndefined(options.maxSpeedX)?this.maxSpeedX=this.maxSpeedX:this.maxSpeedX=options.maxSpeedX;    
            }
            if(this.aY!=0){
                this.startTimeY=new Date().getTime();
                this.oriSpeedY=this.speedY;
                isUndefined(options.maxSpeedY)?this.maxSpeedY=this.maxSpeedY:this.maxSpeedY=options.maxSpeedY;    
            }
            
        },
        /**
         *重置移动参数回到初始值
        **/
        resetMovement:function(){
            this.speedX=0;
            this.speedY=0;
            this.aX=0;
            this.aY=0;
            this.maxSpeedX=postive_infinity;
            this.maxSpeedY=postive_infinity;
            this.maxX=postive_infinity;
            this.minX=-postive_infinity;
            this.maxY=postive_infinity;
            this.minY=-postive_infinity;
        },
        /**
         *更新位置和帧动画
        **/
        update:function(){
            if(this.aX!=0){
                var now=new Date().getTime();
                var durationX=now-this.startTimeX;
                var speedX=this.oriSpeedX+this.aX*durationX/1000;
                if(this.maxSpeedX<0){
                    this.maxSpeedX*=-1;
                }
                if(speedX<0){
                    this.speedX=Math.max(speedX,this.maxSpeedX*-1)    ;
                }
                else{
                    this.speedX=Math.min(speedX,this.maxSpeedX);
                }
            }
            if(this.aY!=0){
                var now=new Date().getTime();
                var durationY=now-this.startTimeY;
                this.speedY=this.oriSpeedY+this.aY*durationY/1000;    
            }
            this.move(this.speedX,this.speedY);
            
            
            if(this.spriteSheet){//更新spriteSheet动画
                this.spriteSheet.x=this.x
                this.spriteSheet.y=this.y;
                this.spriteSheet.update();
            }
        },
        /**
         *绘制出sprite
        **/
        draw:function(){
            var context=cg.context;
            if(this.spriteSheet){
                this.spriteSheet.x=this.x
                this.spriteSheet.y=this.y;
                this.spriteSheet.draw();
            }
            else if(this.image){
                context.save()
                context.translate(this.x, this.y);
                context.rotate(this.angle * Math.PI / 180);
                context.drawImage(this.image,this.imgX,this.imgY,this.width,this.height,0,0,this.width,this.height);
                context.restore();
            }
        
        },
        /**
         *移动一定距离
        **/
        move:function(dx,dy){
            dx=dx||0;
            dy=dy||0;
            var x=this.x+dx;
            var y=this.y+dy;
            this.x=Math.min(Math.max(this.minX,x),this.maxX);
            this.y=Math.min(Math.max(this.minY,y),this.maxY);
            return this;
            
        },
        /**
         *移动到某处
        **/
        moveTo:function(x,y){
            this.x=Math.min(Math.max(this.minX,x),this.maxX);
            this.y=Math.min(Math.max(this.minY,y),this.maxY);
            return this;
        },
        /**
         *旋转一定角度
        **/
        rotate:function(da){
            this.angle+=da;
            return this;
        },
        /**
         *旋转到一定角度
        **/
        rotateTo:function(){
            this.angle=da;
            return this;
            
        },
        /**
         *改变一定尺寸
        **/
        resize:function(dw,dh){
            this.width+=dw;
            this.height+=dh;
            return this;
        },
        /**
         *改变到一定尺寸
        **/
        resizeTo:function(width,height){
            this.width=width;
            this.height=height;
            return this;
        }
        
    }
    this.Sprite=sprite;                              
                                  
});
复制代码
ログイン後にコピー

以上がHTML5ゲームフレームワーク cnGameJS開発記録 - エルフオブジェクト編の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート