Description de la fonction :
En une minute, Utilisez le bouton gauche de la souris pour encercler les bulles sur la toile, où les points des bulles sont 10 (blanc), 20 (bleu clair), 30 (jaune), -10 (rouge), -20 (vert), -30 (bleu foncé), qui peuvent être utilisés une fois encerclent plusieurs fois des bulles et le score total seront calculés à la fin du compte à rebours. Ce jeu est basé sur cnGameJS.
Aperçu de l'effet :
Analyse de mise en œuvre :
D'abord, chaque boule définit un classe ball. Puisque la balle doit utiliser des images et a une certaine taille et un certain mouvement, cette classe hérite de la classe sprite de cnGameJS. En plus d'avoir des coordonnées x et y, la classe de balle a également une coordonnée z , qui est utilisée pour que la balle ait une différence visuelle de distance par rapport au joueur.
/* 小球对象 */ var Ball=function(opt){ this.parent.call(this,opt); this.oriPos=[this.x+this.width/2,this.y+this.height/2]; this.oriSize=opt.size; this.z=opt.z||0; this.score=opt.score||0; this.oriSpeedZ=4+Math.random()*4; this.scale=1; this.resetXY(); } cg.core.inherit(Ball,Sprite);
Ensuite, nous ajoutons la méthode resetXY à la balle. Cette méthode modifie la position et la taille de la balle en fonction de la coordonnée z de la balle, de sorte que la balle ait une différence visuelle entre le loin et le proche. . Tout d'abord, calculez l'échelle du rapport de mise à l'échelle en fonction de z, puis ajustez x, y, la largeur et la hauteur en fonction de l'échelle. De plus, nous faisons disparaître la balle lorsque z est supérieur à 1 000, empêchant ainsi la balle d'être trop grande et. occupant tout l'écran.
cg.core.extendProto(Ball,{ disappear:function(){//小球被选中消失 list.remove(this); }, resetXY:function(){//根据Z改变x,y的位置和尺寸 var oriX=this.oriPos[0]; var oriY=this.oriPos[1]; var oriSize=this.oriSize; this.scale=((center[0]+this.z)/center[0]);//相对于现时的scale this.x=(oriX-center[0])*this.scale+center[0]; this.y=(oriY-center[1])*this.scale+center[1]; this.height=this.width=this.oriSize*this.scale; this.speedZ=this.oriSpeedZ*this.scale; if(this.z>1000){ this.disappear(); } }, update:function(){ this.parent.prototype.update.call(this); this.resetXY(); } });
Plus tard, afin de gérer plusieurs balles, vous pourrez ajouter un gestionnaire de balle. Le manager est chargé de modifier dynamiquement la distance entre le ballon et le joueur et de faire apparaître le ballon à une position aléatoire sur la toile :
/* 小球对象管理器 */ var ballsManager={ createDuration:200, ballSize:30, lastCreateTime:Date.now(), /* 随机生成小球 */ createRandomBalls:function(num){ var now=Date.now(); if(now-this.lastCreateTime>this.createDuration){ for(var i=0;i<num;i++){ var x=Math.random()* cg.width; var y=Math.random()* cg.height; var randomKind=ballKinds[Math.floor(Math.random()*6)];//随机获得的小球种类和分值 var newBall=new Ball({x:x,y:y,size:this.ballSize,z:-280,score:randomKind[1]}); newBall.setCurrentImage(srcObj[randomKind[0]]);//设置图片 list.add(newBall); } this.lastCreateTime=now; } }, /* 改变小球位置 */ changeBallsPos:function(){ var ballsArr=list.get(function(elem){ return elem instanceof Ball; }); for(var i=0,len=ballsArr.length;i<len;i++){ var ball=ballsArr[i]; ball.z+=ball.speedZ; } } }
Ceci est l'introduction à la gestion du ballon, et ensuite nous allons présente principalement comment réaliser la sélection du cercle de la souris.
Si nous dessinons un segment de ligne basé sur la position actuelle de la souris et la dernière position à chaque fois que le cadre est mis à jour , alors la trajectoire de mouvement de la souris peut être représentée par une courbe. Elle est composée de segments de droite dessinés à chaque fois, on peut donc aussi dire que la courbe est une courbe composée de plusieurs segments de droite reliés bout à bout. Par conséquent, nous pouvons d'abord implémenter une classe de segment de ligne :
/* 直线 */ var line=function(options){ if (!(this instanceof arguments.callee)) { return new arguments.callee(options); } this.init(options); } line.prototype = { /** *初始化 **/ init: function(options) { this.start=[0,0]; this.end=[0,0]; this.style="red"; this.lineWidth=1; this.context=cg.context; options = options || {}; cg.core.extend(this,options); },
Cette classe enregistre les coordonnées du point de départ et les coordonnées du point final du segment de ligne, ainsi que la largeur, le style, etc.
Ce qu'il faut ensuite considérer, c'est comment mettre en œuvre la sélection de cercle. Lorsque nous dessinons un cercle avec la souris, chaque petit segment de ligne forme un polygone fermé. À ce stade, nous pouvons dire que la souris a encerclé une zone fermée, puis nous pouvons calculer quelles petites boules se trouvent dans la zone.
Mais comment déterminer si la souris a fait le tour d'une zone fermée ? La méthode utilisée ici est la suivante : Parcourez chaque segment de ligne, en commençant par le segment de ligne suivant et le segment de ligne suivant, parcourez les segments de ligne restants et déterminez si l'un d'entre eux coupe le segment de ligne de départ. S'ils se croisent, prouvez. la courbe s'est fermée. Notez que passer du segment de ligne suivant au segment de ligne suivant consiste ici à ignorer la situation dans laquelle les segments de ligne sont connectés bout à bout. (Par exemple, le premier segment de ligne doit croiser le deuxième segment de ligne, alors commencez à juger à partir du troisième segment de ligne, en ignorant la situation où les segments de ligne adjacents se croisent à la fin), le code est le suivant :
/* 返回轨迹是否闭合 */ var isClose=function(lines){ var hasClose=false; for(var i=0;i<lines.length;i++){ var l1=lines[i]; for(var j=i+2;j<lines.length;j++){ var l2=lines[j]; if(l2){ var point=l1.isCross(l2);//交点坐标 if(point){//非连接的相交 resetLineSegs(lines,i,j,point); hasClosed=true; return true; } } } } return false; };
La méthode isCross renvoie les coordonnées du point d'intersection des segments de ligne. Après avoir obtenu les coordonnées, nous devons corriger le polygone en un polygone réel, car le polygone entouré avec la souris n'est pas un vrai polygone, et son les parties de début et de fin sont susceptibles d'être proéminentes, comme suit Image :
Nous supposons que la souris commence un cercle à partir de la partie verte et se termine à la partie bleue. Dans ce cas, la trajectoire n'est pas un polygone strict, car elle comporte des parties bleues et vertes supplémentaires. Il faut donc effectuer une opération de correction sur le polygone encerclé pour le transformer en un véritable polygone fermé :
/* 重置线段 */ var resetLineSegs=function(lines,i,j,point){ lines[i].end[0]=point[0]; lines[i].end[1]=point[1]; lines[i+1].start[0]=point[0]; lines[i+1].start[1]=point[1]; lines[j].start[0]=point[0]; lines[j].start[1]=point[1]; lines[j-1].end[0]=point[0]; lines[j-1].end[1]=point[1]; for(var m=i+1;m<j;m++){ closedLineSegsArr.push(lines[m]); } }
Quand on détermine que deux segments de droite se coupent, on peut obtenir ces deux Le index des segments de droite, voici respectivement i et j (i
for(var i=0,len=closedLineSegsArr.length;i<len;i++){ pointsArr.push([closedLineSegsArr[i].start[0],closedLineSegsArr[i].start[1]]); } polygon=new Polygon({pointsArr:pointsArr,style:"rgba(241,46,8,0.5)"});
Grâce au tableau d'objets de bord de polygone, vous pouvez obtenir les coordonnées de chaque sommet du polygone et construire l'objet polygone en fonction de ces coordonnées. L'étape suivante consiste à déterminer si le. la balle est à l'intérieur du polygone.
判断小球是否在多边形里,可以转化为判断小球的中点是否在多边形里,这里使用的方法叫射线法,意思是从一点向左发射出一条射线,如果射线和多边形有奇数个交点,则证明点在多边形内部。根据该定理实现的isInside方法如下:
/** *判断某点是否在多边形内(射线法) **/ isInside:function(point){ var lines=this.getLineSegs(); var count=0;//相交的边的数量 var lLine=new Line({start:[point[0],point[1]],end:[-9999,point[1]]});//左射线 var crossPointArr=[];//相交的点的数组 for(var i=0,len=lines.length;i<len;i++){ var crossPoint=lLine.isCross(lines[i]); if(crossPoint){ for(var j=0,len2=crossPointArr.length;j<len2;j++){ //如果交点和之前的交点相同,即表明交点为多边形的顶点 if(crossPointArr[j][0]==crossPoint[0]&&crossPointArr[j][1]==crossPoint[1]){ break; } } if(j==len2){ crossPointArr.push(crossPoint); count++; } } } if(count%2==0){//不包含 return false; } return true;//包含 },
另外需要注意的是,由于射线与多边形相交交点个数是通过射线和多边形的每条边是否相交来判断,所以如果射线通过多边形的顶点,我们得出的结果就是相交了两次(通过顶点使射线与两条边都有相交)。因此我们需要记录判断过的交点,每次判断时检查该交点是否已经出现过,若出现过则不纳入计数,这样就基本实现了判断小球是否在鼠标圈选的多边形区域内。
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!