当前位置: 首页 > Web前端 > HTML5

javascript实现QQ堂小游戏

时间:2023-04-05 22:45:36 HTML5

介绍QQ堂是我初中的时候玩的一款游戏。本着学习的精神,想着尝试着用js来实现。还有一些细节有待优化,不过核心玩法已经实现,废话不多说,截图和地址项目地址在线Demodemo地址可能会改,打不开请移步项目地址技术选择绘图引擎。看了很多引擎对比,最终还是选择了使用pixi.js。一方面,性能更好。另一方面,这是一个纯粹的绘图引擎,没有其他复杂的功能,更符合我的目的。声音引擎用的是Howler,在线用的socket.io,代码量不小,用的是typescript。另外,搜索了游戏中的图片和声音资源,有的不是很清楚。这个想法是首先分析游戏玩法。首先是一张大地图。地图初始化时有障碍物。玩家分组,在地图中使用泡泡互相攻击。泡泡爆炸是十字形的,一些障碍物可以被泡泡摧毁,并且可能会掉落物品。玩家在获得物品后会获得好处,比如增加泡泡攻击范围,加快移动速度等,当泡泡击中敌人时,敌人会被困在泡泡中。敌人失败,当被困在泡泡中时可以被队友复活。通过分析,新建了以下几个类//地图类,为什么叫grid,因为地图上的item都是一格一格的,加载地图的时候会讲classGrid{}//item定义对于地图上的所有item,它都有坐标,在哪一行,在哪一列等属性。坐标row:Numbercol:Numberdestructible:boolean;//气泡爆炸检测是否可破坏passable:boolean;//是否可以通过//...//每个对象都有对应的render方法,只初始化调用,会获取pixi的实例,后面更新status,再调用实例方法更新thedrawingrender():void{}}//PlayerclassPlayerextendsMaterial{}//障碍物,玩家不能通过障碍物classStoneextendsMaterial{}//Mask,玩家可以躲在面具下classMaskextendsMaterial{}//bubbleclassBubbleextendsMaterial{}//medicineclassMedicineextendsMaterial{}//medicineclassAddSpeedextendsMedicine{}//由于手机和pc的控制不一样,所以控制器需要根据平台类进行初始化GameController{}首先需要绘制地图,这里的地图其实就是一个重复的正方形图片,然后在上面添加各种小物体,这里我用了一个矩阵数组gocontrol//mtypeconsta=1,b=2,c=3,d=4,e=5,f=6,z=-1,x=-2;constmap=[//123456789101112131415161718z,b,a,b,0,a,0,0,e,e,0,0,a,0,b,a,b,z,//1z,d,c,0,0,0,0,c,d,d,c,0,0,0,0,c,d,z,//2z,b,b,0,d,0,a,a,a,a,a,a,a,0,d,b,b,z,//3z,d,0,z,z,0,a,0,0,0,0,0,a,0,z,0,d,z,//4x,e,0,e,d,0,a,0,x,x,x,0,a,0,e,0,e,x,//5x,e,0,e,d,0,a,0,0,0,0,0,a,0,e,0,e,x,//6z,d,0,z,z,0,a,a,a,a,a,a,a,0,z,0,d,z,//7z,b,b,0,0,x,b,b,b,x,b,b,b,x,0,b,b,z,//8z,d,c,0,0,0,0,x,d,x,d,x,0,0、0、c、d、z、//9z、b、a、b、c、c、c、d、c、x、c、d、c、c、b、a、b、z、//10]先根据数组绘制一张大地图,这里所有的图片都是一样的,然后绘制物体,0代表空白可移动区域,然后根据其他不同的数字加载石头等物体,所以地图这里可以根据后端返回的不同数组来加载不同的地图,然后我们需要添加我们的玩家。先实现单人版,多人版其实就是在地图上加上Player,然后通过websocket控制行为。玩家和其他物体一样,不同的是需要监听控制器实现不同的行为,方向键控制角色的方位,行进的方向,在行进中播放角色行走的动画,并同时进行碰撞检测,如果玩家碰到了Stone,则不允许前进,如果遇到Medicine,比如增加速度,则玩家的速度+1。(这里对碰撞检测有个小优化,每次碰撞检测都会获取玩家当前所在的行和列,然后寻找相邻的物体,否则需要遍历整个地图的物体。)init():void{gameControler.onDirectionChange=(e)=>{this.self.faceTo(e.direction)switch(e.direction){case'ArrowLeft':this.self.moveLeft()break;case'ArrowRight':this.self.moveRight()中断;case'ArrowUp':this.self.moveUp()中断;case'ArrowDown':this.self.moveDown()中断;case'Center':this.self.stop()break;}}}move():void{consthitMd:Material=this.hitTest()if(hitMd){//如果物体被触摸if(!hitMd.passable){//不能通过this.stopMove()}elseif(hitMd.isMedicine){//如果是药,吃掉它,增益在药中实现修改玩家的属性this.eat(hitMd)}}}当玩家吐出泡泡时,泡泡会根据玩家的属性,有不同的爆炸范围等属性。当它爆炸时,计算它爆炸范围内的所有物体。碰到石头就会被破坏,后面的不会被破坏。如果它接触到玩家,则确定玩家是否是敌人,如果他们被困则更新玩家的状态。此时,我们可以添加我们的服务器端支持。Websocket其实就像一个事件一个一个的发生,所以我们把游戏中的所有变化发送到服务器,服务器通知地图上的玩家做出相应的变化。首先,必须有一个房间类型Room,只有这个房间的玩家才会同步状态,游戏开始时玩家会加入房间,当房间数量满时,会发送游戏开始事件,然后服务端会自动生成药品,玩家的位置,然后客户端根据数据进行Render和初始化。这里需要注意一点,每个客户端的屏幕大小不一样,这里需要统一坐标。这里坐标除以屏幕尺寸,传给其他客户端时,再乘以屏幕尺寸还原坐标。当玩家移动时,会发送移动事件,房间会通知其他客户端更新玩家位置,攻击同理。Server.on("player_walk",(data)=>{letplayer=this.players.find((item)=>{returnitem.id===data.id;})player.faceTo(data.direction);player.move()})Server.on("player_walk",(data)=>{//...})Server.on("player_create_bubble",(data)=>{//...})Server.on("player_bubble_boom",(data)=>{//...})//...总结写这个游戏的时候,毕业一年了。那时候我也是抱着学习的心态,所以现在看到的很多东西确实是不忍心写的。.游戏中有很多代码是pixi渲染的,不过主要的逻辑在文中已经基本涵盖,有时间我们会继续优化游戏。谢谢阅读