Maison  >  Article  >  interface Web  >  Apprendre en jouant avec HTML5 (7) - Le début de l'animation : les lutins volants

Apprendre en jouant avec HTML5 (7) - Le début de l'animation : les lutins volants

黄舟
黄舟original
2017-03-29 15:10:141149parcourir

1. Pourquoi choisir HTML5

Apprendre HTML5 en jouant C'est déjà le septième article Avant de commencer cet article, je veux d'abord vous expliquer pourquoi. cela s'appelle "HTML5". Apprenez en jouant, car certaines personnes ont remis en question le HTML5. Après tout, c'est une nouveauté. J'avoue que j'ai utilisé HTML5 pour attirer l'attention. Si vous lisez tous les articles de la série "Apprendre en jouant", vous constaterez que le contenu des six premiers articles n'a pas grand-chose à voir avec HTML5. Notes de programmation graphique et image 2D.

Si nous voulons apprendre la programmation 2D, il existe en fait d'innombrables environnements de programmation parmi lesquels choisir : MFC et Delphi ont tous des fonctions graphiques et de traitement d'images (c'est-à-dire GDI), sans parler de Java et .Net si vous les supportez. open source, GTK, QT et wxPython sont également de bons choix, et Flash est particulièrement performant dans ce domaine. Même plusieurs plates-formes de téléphonie mobile populaires devraient également disposer de modules 2D.

Si vous choisissez l'un des environnements de programmation ci-dessus pour apprendre la programmation 2D, vous constaterez que leur contenu est fondamentalement le même : type de ligne, remplissage, couleur, dégradé, image, combinaison, zone de recadrage, transformation, etc. . etc. Même la plupart des noms de fonctions sont exactement les mêmes. Après tout, leur base théorique est le graphique.

Après avoir déterminé ce que nous voulons vraiment apprendre, l'environnement de programmation n'est en réalité qu'un outil. Nous choisissons celui qui est le plus pratique à utiliser en fonction de nos préférences personnelles. En fait, je préfère l’environnement de programmation Python, mais si j’utilise Python, je suppose qu’il n’y aura pas trop de personnes qui communiqueront avec moi, et qu’il n’y aura pas trop de personnes qui auront le runtime Python installé sur leurs machines.

Alors pourquoi choisir HTML5 plutôt que les autres ? Tout d'abord, la syntaxe Javascript est concise et flexible, la bibliothèque de fonctions correspondante est petite mais suffisante, les capacités de performances 2D de la balise HTML5 Canvas répondent également aux exigences et la vitesse d'exécution du navigateur Chrome est satisfaisante. De plus, nous n'avons pas besoin d'installer un environnement de développement intégré ou un runtime encombrant. Nous avons seulement besoin d'un bloc-notes amélioré et d'un navigateur pour mettre en œuvre nos idées et présenter directement les effets sur le réseau. Nous publions simplement des articles pour partager nos réflexions avec les autres. En ce qui concerne les plates-formes, les frameworks et les fonctionnalités du langage, bien sûr, moins ces éléments non pertinents sont impliqués, mieux c'est.

Alors, ne vous méprenez pas sur la signification du titre : cette série ne contient pas de notes d'étude HTML5, mais utilise simplement HTML5 pour afficher du contenu de connaissances. Ce à quoi vous devriez prêter plus d'attention, ce sont les connaissances et le contenu eux-mêmes. . Ils peuvent être reproduits dans n’importe quel autre environnement de programmation.

2. Animation préliminaire

L'animation n'est qu'une série d'images continues présentées dans l'ordre. Cependant, au cinéma et à la télévision, la réalisation de ces images a été préparée. , et dans les programmes informatiques, à chaque instant que nous voyons, l'image est dessinée en temps réel. Le processus général peut être exprimé comme suit :

a. Modifier légèrement les données du graphique (coordonnées, forme, couleur, etc. .)

b. Effacez le canevas

c. Dessinez des graphiques

dRevenir à l'étape a

Bien sûr, ce n'est que le processus le plus simple. framework. , pour implémenter des animations complexes, vous devrez peut-être prendre en compte davantage de problèmes, tels que l'effacement local, la détection de collisions, etc.

De plus, deux vitesses doivent être contrôlées pendant le processus de dessin :

La première est la vitesse de dessin, c'est-à-dire le nombre de fois (images) dessinées par seconde, ou on peut aussi dire qu'à chaque fois combien de temps la trame est en pause. Si votre animation est identique à chaque image mais avec des positions différentes, cette vitesse aura peu d'effet.

La vitesse à laquelle la deuxième forme se déplace.

Alors, ne confondez pas ces deux vitesses. Plus vous dessinez vite, cela signifie seulement que l'animation est plus fluide, mais cela ne signifie pas que votre image se déplace plus vite.

Utiliser HTML5 pour dessiner des animations est essentiellement le processus ci-dessus, mais vous devez quand même faire attention à deux points :

1 Afin de faciliter le dessin de graphiques. , on change souvent le contexte L'état de l'objet, donc avant et après avoir dessiné des graphiques, n'oubliez pas de sauvegarder et de restaurer l'état Si vous ne savez pas ce que c'est. l'état est, veuillez lire l'article précédent " Apprendre en jouant à HTML5 (6) : Autobots, transformation...》

2. Nous devons mettre toute l'action de dessin dans le minuterie, sinon, l'ensemble du navigateur ne répondra plus. Javascript a deux méthodes de minuterie, à savoir :

setInterval(code,millisec) 和 setTimeout(code,millisec)

J'ai présenté ces deux méthodes, vous pouvez accéder à Google pour obtenir des informations associées.

Ci-dessous, nous donnons une petite animation du déplacement du bloc de haut en bas. Lorsqu'il rencontre le haut ou le bas, il changera de direction. Le code est le suivant :

基本动画



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas1" width="250" height="300" style="background-color:black">

    你的浏览器不支持 Canvas 标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

帧数:<input  id="txt1" type="text" value="25"/><br/>

每次移动距离:<input type="text" id="txt2" value="10"/><br/>

<input type="button" value="开始" onclick="move_box()"/>

<input type="button" value="暂停" onclick="stop()"/>





<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }



    //===================================================================

    //基本动画

    //====================================================================

    function move_box(){

        //停止动画

        stop();

        //移动速度

        var delta=parseInt(document.getElementById(&#39;txt1&#39;).value);

        //每秒绘制多少次

        var fps=parseInt(document.getElementById(&#39;txt2&#39;).value);



        //画布对象

        var canvas=document.getElementById("canvas1")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //设置颜色

        ctx.fillStyle="red";

        

        //方块的初始位置

        var x=100;var y=50;

        //方块的长度和宽度

        var w=30;var h=30;

        

        //开始动画

        interval = setInterval(function(){

            //改变 y 坐标

            y=y+delta;

            //上边缘检测

            if(y<0){

                y=0;

                delta=-delta;

            }

            //下边缘检测

            if((y+h)>canvas.getAttribute("height")){

                y=canvas.getAttribute("height")-h;

                delta=-delta;

            } 

            //清空画布

            ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

            //保存状态

            ctx.save();

            //移动坐标

            ctx.translate(x,y);

            //重新绘制

            ctx.fillRect(0,0,w,h);

            //恢复状态

            ctx.restore();

        },1000/fps);

    }    

</script>

3. Réorganisez le code

Le code ci-dessus peut fonctionner normalement, mais il y a de nombreux problèmes , comprenant principalement Les points suivants :

1. Le code de calcul de la position du bloc et le code de dessin du bloc sont mélangés, c'est-à-dire que la logique et la vue sont mélangés, qui ne peuvent fondamentalement pas être étendus

2、代码没办法复用,比如我们需要绘制多个不同的方块对象:起始位置、大小、颜色、速度各不相同,每一种情况都需要重写一遍。

下面我们重新组织一下代码,把方块的共同属性抽象出来,组成一个 Box 类,由这个 Box 类负责计算每一帧方块的位置,这样就可以解决上面两个问题了。代码如下:

重新组织代码



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas2" width="250" height="300" style="background-color:black">

    你的浏览器不支持 Canvas 标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

<input type="button" value="开始" onclick="move_box2()"/>

<input type="button" value="暂停" onclick="stop()"/>



<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }



    //===================================================================

    //重新组织代码

    //====================================================================

    //方块的构造函数

    function Box(color,x,y,w,h,delta){

        this.color=color;

        this.x=x;

        this.y=y;

        this.w=w;

        this.h=h;

        this.delta=delta;

        //三十帧

        this.fps=30;

        //每一帧的延迟时间

        this.delay=1000/this.fps;

        //上一次重绘的时间

        this.last_update=0;

    }

    

    //方块更新

    Box.prototype.update=function(canvas){

        //获取当前时间

        var now=(new Date()).getTime();

        //如果达到了延迟时间,则更新数据

        if((now-this.last_update)>this.delay){

        

            //改变 y 坐标

            this.y=this.y+this.delta;

            //上边缘检测

            if(this.y<0){

                this.y=0;

                this.delta=-this.delta;

            }

            //下边缘检测

            if((this.y+this.h)>canvas.getAttribute("height")){

                this.y=canvas.getAttribute("height")-this.h;

                this.delta=-this.delta;

            } 

            //记下最新一次绘制时间

            this.last_update=now;

        }

        

    }

    

    

    function move_box2(){

        //停止动画

        stop();

        //画布对象

        var canvas=document.getElementById("canvas2")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //清空画布

        ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

        

        //创建多个方块对象

        var boxes=[];

        boxes[0]= new Box("red",3,2,10,35,2,10);//速度10

        boxes[1]= new Box("blue",60,28,44,15,5);//速度20

        boxes[2]= new Box("green",130,200,23,18,10);//速度30

        boxes[3]= new Box("pink",200,150,35,10,20);//速度40

        

        //开始动画绘制

        interval = setInterval(function(){

            for(var i=0;i<boxes.length;i++){

                //取出一个方块

                var box=boxes[i];

                //清空这个方块

                ctx.clearRect(box.x,box.y,box.w,box.h);

                //更新数据

                box.update(canvas);

                //保存状态

                ctx.save();

                //设置颜色

                ctx.fillStyle=box.color;

                //移动坐标

                ctx.translate(box.x,box.y);

                //重新绘制

                ctx.fillRect(0,0,box.w,box.h);

                //恢复状态

                ctx.restore();

            }

        },1);//尽可能快的循环

    }    

</script>

 

四、精灵登场

据说在很久远的年代,有多远我也不知道,可能是任天堂红白机是哪个年代吧,由于游戏机处理器的计算速度有限,所以专门设置了一个硬件用来处理角色图像的相关数据,这些数据可能包括:

1、计算当前的角色应该绘制哪一帧。上面我们的方块虽然在移动,但是始终都是一个样子;可是在游戏中,一个跑动的精灵,跑动动作是由很多幅连续的图像组成,我们需要知道现在应该绘制其中的哪一幅图像;

2、表现精灵动作的很多幅连续的图像通常是集中放置在一个大图中,我们需要计算当前绘制的那一幅,在大图中处于什么位置,并把它截取出来

上面说到这个硬件,曾经被叫做 Sprite 精灵。现如今,我们的处理器已经十分强大,不再需要 Sprite 这样的辅助硬件,但是这样的功能仍然需要,只不过用软件来实现罢了,所以,我们依然用 Sprite 来称呼游戏中的一个角色。

这里有一幅图像,他描绘了一个小精灵的飞行动作

 

下面我们将实现一个 Sprite 类,让他在浏览器里面飞起来。

精灵登场



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--><canvas id="canvas3" width="250" height="300" style="background-color:black">

    你的浏览器不支持 &lt;canvas&gt;标签,请使用 Chrome 浏览器 或者 FireFox 浏览器

</canvas><br/>

帧数:<input  id="txt4" type="text" value="10"/><br/>

速度:<input type="text" id="txt5" value="5"/><br/>

比例:<input type="text" id="txt6" value="2"/><br/>

<input type="button" value="开始" onclick="animate()"/>

<input type="button" value="暂停" onclick="stop()"/>



<script type="text/javascript">

    //定时器

    var interval=null;

    

    //停止动画

    function stop(){

        clearInterval(interval);

    }

    

    //===================================================================

    //精灵登场

    //====================================================================

    //每一帧在大图中的位置

    var frames=[];

    frames[0]=[0,4,19,19];

    frames[1]=[22,1,24,19];

    frames[2]=[49,0,18,17];

    frames[3]=[1,32,18,17];

    frames[4]=[22,33,24,19];

    frames[5]=[49,36,19,19];

    

    //精灵类

    function Sprite(dx,dy,delta,fps){

        this.dx=dx;

        this.dy=dy;

        this.fps=fps;

        this.delay=1000/fps;

        this.last_update=0;

        //移动速度

        this.delta=-delta;

        //帧编号

        this.index=0;

        //方向

        this.dir_left=true;

    }

    

    Sprite.prototype.update=function(canvas){

        //获取当前时间

        var now=(new Date()).getTime();

        if((now-this.last_update)>this.delay){

            if(this.dir_left){

                //方向朝左,只绘制0 1 2帧

                if(this.index>2)

                    this.index=0;

            }

            else{

                //方向朝右,只绘制 3 4 5 帧

                if(this.index>5)

                    this.index=3;

            }

            //取出当前帧的坐标

            this.frame=frames[this.index];

            

            //当前帧在大图中的位置

            this.sx=this.frame[0];

            this.sy=this.frame[1];

            this.sw=this.frame[2];

            this.sh=this.frame[3];

            

            //当前帧大小

            this.dw=this.frame[2];

            this.dh=this.frame[3];

            

            //改变 x 坐标

            this.dx=this.dx+this.delta;

            //左边缘检测

            if(this.dx<0){

                this.dx=0;

                //转向

                this.delta=-this.delta;

                this.dir_left=false;

                this.index=3;

            }

            //右边缘检测

            if((this.dx+this.dw)>canvas.getAttribute("width")){

                this.dx=canvas.getAttribute("width")-this.dw;

                //转向

                this.delta=-this.delta;

                this.dir_left=true;

                this.index=0;

            }         

            this.dy=this.dy;//y 不移动

            



            this.index++;

            this.last_update=now;

        }

    }

    

    function animate(){

        //停止动画

        stop();

        //移动速度

        var delta=parseInt(document.getElementById(&#39;txt4&#39;).value);

        //每秒绘制多少次

        var fps=parseInt(document.getElementById(&#39;txt5&#39;).value);

        //比例

        var scale=parseInt(document.getElementById(&#39;txt6&#39;).value);

        

        //画布对象

        var canvas=document.getElementById("canvas3")

        //获取上下文对象

        var ctx = canvas.getContext("2d");

        //清空画布

        ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

        

        var img=new Image();

        img.src="http://images.cnblogs.com/cnblogs_com/myqiao/html5/sprite.gif";



        var sprite=new Sprite(120,150,delta,fps);

        interval = setInterval(function(){

            //清空画布

            ctx.clearRect(0,0,canvas.getAttribute("width"),canvas.getAttribute("height"));

            //更新数据

            sprite.update(canvas);

            //保存状态

            ctx.save();

            //移动坐标

            ctx.translate(sprite.dx,sprite.dy);

            ctx.scale(scale,scale);

            ctx.drawImage(img,sprite.sx,sprite.sy,sprite.sw,sprite.sh,0,0,sprite.dw,sprite.dh);

            //恢复状态

            ctx.restore();

        },1);

        

    }

    

</script>


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn