찾다
웹 프론트엔드H5 튜토리얼零基础开发RPG游戏开源讲座(四)-游戏脚本化&地图跳转

了解上三篇的内容请点击:

html5[color=rgb(68, 68, 68) !important]游戏
开发-零基础开发RPG游戏-开源讲座(一)

http://www.html5cn.org/article-1737-1.html

html5游戏开发-零基础开发RPG游戏-开源讲座(二)-跑起来吧英雄

http://www.html5cn.org/article-1738-1.html

html5游戏开发-零基础开发RPG游戏-开源讲座(三)-卷轴&对话实现

http://www.html5cn.org/article-1740-1.html


首先,本篇文章是零基础开发RPG游戏-开源讲座系列文章的第四篇,来实现游戏的脚本化,和利用游戏脚本实现地图场景的切换。如下应该是我们先了解的。

一,什么是游戏脚本

简单说,游戏脚本就是依据一定的格式编写的可执行文件,游戏可以通过脚本中自定义的语句来执行相应的逻辑。

二,为什么要将游戏脚本化

游戏脚本,可以令我们的游戏动态化,比如当我们开发了一款rpg游戏,里面的剧情,事件以及地图等,我们如果将这些全部写进程序里,当然是可以的,但是一旦出现问题,哪怕几个错别字,我们需要先将这几个错别字改正,并且将整个程序重新编译发布一遍,这个过程是相当令人反感的,因为如果游戏的程序跟着游戏的内容不断进行修改的话,那只会使你的程序越来越复杂。但是如果我们将这些可重复的数据,都定义到游戏程序之外的文件里面,当游戏引擎开发完毕,我们的游戏通过读取这些外部文件,来执行相应的剧情和事件,那么,像上述当我们的游戏出现了问题,我们只需要改动这些外部文件就可以了,并不需要重新编译整个程序,这样便使得我们的游戏开发,变得便利简洁。

*当然,对于html5来说,不需要重新编译程序,但是对于rpg的游戏来说,脚本还是必不可少的,因为游戏的剧本不可能全都写到程序里。

三,如何来实现游戏的脚本化

好了,接下来,先来考虑以什么形式来制作游戏的脚本,我们有多种选择,可以选择xml,可以选择json,也可以选择纯自定义语法,

这次,我为了省事,选用比较方便处理的json,因为javascript可以很轻松的处理json数据。

目前游戏中实现的内容有,地图场景添加,游戏人物添加,以及人物对话的实现。那么,我在设计游戏脚本的时候,必须包含这些数据,然后才能将这三项功能用脚本来控制。

首先看下面的json
  1. var script = {
  2.         stage01:{
  3.                 map:[
  4.                     [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
  5.                         [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
  6.                         [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
  7.                         [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
  8.                         [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
  9.                         [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
  10.                         [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
  11.                         [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
  12.                         [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
  13.                         [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
  14.                         [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]],
  15.                 mapdata:[
  16.                         [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  17.                         [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
  18.                         [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
  19.                         [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
  20.                         [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
  21.                         [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
  22.                         [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
  23.                         [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
  24.                         [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  25.                         [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
  26.                         [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],
  27.                 add:[
  28.                      {chara:"player",img:"mingren",x:5,y:6},
  29.                      {chara:"npc",img:"npc1",x:7,y:6},
  30.                      {chara:"npc",img:"npc1",x:3,y:3}],
  31.                 talk:{
  32.                         talk1:[
  33.                                       {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},
  34.                                       {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}
  35.                               ],
  36.                     talk2:[
  37.                                   {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},
  38.                                       {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}
  39.                               ]
  40.                 }
  41.         }


  42. };
复制代码

我将脚本定义成了变量,实际游戏制作的时候,脚本应该储存到一个外部文档当中,在这里我只是讲解一下理论,如何完善那是后话了。

可以看到,json中,包含了地图相关的map数组和mapdata数组,添加人物的相关数据,以及对话的数组。这样,我在游戏显示的时候,只需要读入json数据,然后根据这些内容来显示游戏画面就可以了,定义一个initScript函数来进行这些操作。
  1. function initScript(){
  2.         //地图位置初始化
  3.         mapLayer.x = 0;
  4.         mapLayer.y = 0;


  5.         //地图层初始化
  6.         mapLayer.removeAllChild();
  7.         //人物层初始化
  8.         charaLayer.removeAllChild();
  9.         //效果层初始化
  10.         effectLayer.removeAllChild();
  11.         //对话层初始化
  12.         talkLayer.removeAllChild();
  13.         
  14.         //地图数据获取
  15.         map = stage.map;
  16.         mapdata = stage.mapdata;
  17.         //对话数据获取
  18.         talkScriptList = stage.talk;
  19.         
  20.         //添加地图
  21.         addMap(0,0);
  22.         delMap();
  23.         //添加人物
  24.         addChara();
  25. }
复制代码

removeAllChild方法是legendForHtml5Programming引擎独有的方法,可以用来移出LScript显示层上的所有子对象,从而实现本游戏中各个显示层的初始化工作。

修改一下addChara方法,如下
  1. //添加人物
  2. function addChara(){
  3.         var charaList = stage.add;
  4.         var chara,charaObj;
  5.         for(var i=0;i ;i++){
  6.                 charaObj = charaList[i];
  7.                 if(charaObj.chara == "player"){
  8.                         //加入英雄
  9.                         bitmapdata = new LBitmapData(imglist[charaObj.img]);
  10.                         chara = new Character(true,i,bitmapdata,4,4);
  11.                         player = chara;
  12.                 }else{
  13.                         //加入npc
  14.                         bitmapdata = new LBitmapData(imglist[charaObj.img]);
  15.                         chara = new Character(false,i,bitmapdata,4,4);
  16.                 }
  17.                 chara.x = charaObj.x * 32;
  18.                 chara.y = charaObj.y * 32;
  19.                 charaLayer.addChild(chara);
  20.         }
  21. }
复制代码

即,根据json脚本中的add数组,来添加游戏中的人物。

好了,运行一下游戏,可以看到,游戏正常显示了,和之前一模一样,实现了同样的功能。

1122.jpg



四,利用游戏脚本实现地图的切换

为了让大家看到游戏脚本的便利性,现在利用脚本实现游戏中的场景切换。

将json脚本修改如下
  1. var script = {
  2.         stage01:{
  3.                 map:[
  4.                     [18,18,18,18,18,18,18,18,18,18,18,18,55,55,18,18,18],
  5.                         [18,18,18,17,17,17,17,17,17,17,17,17,55,55,17,17,18],
  6.                         [18,18,17,17,17,17,18,18,17,17,17,17,55,55,17,17,18],
  7.                         [18,17,17,17,18,18,18,18,18,17,17,55,55,17,17,17,18],
  8.                         [18,17,17,18,22,23,23,23,24,18,17,55,55,17,17,17,18],
  9.                         [18,17,17,18,25,28,26,79,27,18,55,55,17,17,17,17,18],
  10.                         [18,17,17,17,17,10,11,12,18,18,55,55,17,17,17,17,18],
  11.                         [18,18,17,17,10,16,16,16,11,55,55,17,17,17,17,17,18],
  12.                         [18,18,17,17,77,16,16,16,16,21,21,17,17,17,17,17,18],
  13.                         [18,18,17,17,77,16,16,16,16,55,55,17,17,17,17,17,18],
  14.                         [18,18,18,18,18,18,18,18,18,55,55,18,18,18,18,18,18]],
  15.                 mapdata:[
  16.                         [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  17.                         [1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1],
  18.                         [1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,1],
  19.                         [1,0,0,0,1,1,1,1,1,0,0,1,1,0,0,0,1],
  20.                         [1,0,0,1,1,1,1,1,1,1,0,1,1,0,0,0,1],
  21.                         [1,0,0,1,1,1,0,1,1,1,1,1,0,0,0,0,1],
  22.                         [1,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1],
  23.                         [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
  24.                         [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
  25.                         [1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1],
  26.                         [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]],
  27.                 add:[
  28.                      {chara:"player",img:"mingren",x:5,y:6},
  29.                      {chara:"npc",img:"npc1",x:7,y:6},
  30.                      {chara:"npc",img:"npc1",x:3,y:3}],
  31.                 talk:{
  32.                         talk1:[
  33.                                       {img:"m",name:"鸣人",msg:"我是木叶村的鸣人,你是谁?"},
  34.                                       {img:"n",name:"黑衣忍者甲",msg:"你就是鸣人?九尾还在你身体里吗?"}
  35.                               ],
  36.                     talk2:[
  37.                                   {img:"n",name:"黑衣忍者乙",msg:"鸣人,听说忍者大战就要开始了。"},
  38.                                       {img:"m",name:"鸣人",msg:"真的吗?一定要想想办法啊。"}
  39.                               ]
  40.                 },
  41.                 jump:[
  42.                       {at:{x:6,y:5},to:"stage02"}
  43.                 ]
  44.         },
  45.         stage02:{
  46.                 map:[
  47.                     [0,0,1,2,2,2,2,2,2,2,2,1,0,0,0],
  48.                     [0,0,1,3,5,5,1,5,5,5,5,1,0,0,0],
  49.                     [0,0,1,80,4,4,1,80,4,4,4,1,0,0,0],
  50.                     [0,0,1,80,4,4,1,80,8,7,8,1,0,0,0],
  51.                         [0,0,1,80,4,4,5,81,4,4,4,1,0,0,0],
  52.                         [0,0,1,2,2,2,6,4,4,4,4,1,0,0,0],
  53.                         [0,0,1,3,5,5,81,4,4,4,4,1,0,0,0],
  54.                         [0,0,1,80,4,4,4,4,4,4,9,1,0,0,0],
  55.                         [0,0,1,2,2,2,2,6,2,2,2,1,0,0,0]],
  56.                 mapdata:[
  57.                         [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  58.                         [1,1,1,0,0,0,1,0,0,0,0,1,1,1,1],
  59.                         [1,1,1,0,0,0,1,0,0,0,0,1,1,1,1],
  60.                         [1,1,1,0,0,0,1,0,0,1,0,1,1,1,1],
  61.                         [1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
  62.                         [1,1,1,1,1,1,0,0,0,0,0,1,1,1,1],
  63.                         [1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
  64.                         [1,1,1,0,0,0,0,0,0,0,1,1,1,1,1],
  65.                         [1,1,1,1,1,1,1,0,1,1,1,1,1,1,1]],
  66.                 add:[
  67.                      {chara:"player",img:"mingren",x:7,y:8},
  68.                      {chara:"npc",img:"npc1",x:8,y:3},
  69.                      {chara:"npc",img:"npc1",x:10,y:3}],
  70.                 talk:{
  71.                       talk1:[
  72.                                     {img:"m",name:"鸣人",msg:"你们在干什么啊?"},
  73.                                             {img:"n",name:"黑衣忍者甲",msg:"我们在喝茶。"}
  74.                               ],
  75.                       talk2:[
  76.                                         {img:"n",name:"黑衣忍者乙",msg:"我们在喝茶,你不要打扰我们。"},
  77.                                             {img:"m",name:"鸣人",msg:"....."}
  78.                               ]
  79.                 },
  80.                 jump:[
  81.                       {at:{x:7,y:8},to:"stage01"}
  82.                 ]
  83.         }


  84. };
复制代码

可以看到,我添加了stage02,即第二个场景,并且在脚本里引入了jump节点来控制游戏场景的切换,其中jump中的at表示游戏主人公移动到达的坐标,to表示到达这个坐标后跳转到的画面名称。这里的jump之所以是数组,是因为一个场景也可以跳转到其他多个场景。

上面的脚本实现了stage01和stage02两个场景的互相跳转。

为了读取这个jump,以及实现跳转,我们需要在游戏主人公移动一个步长之后,判断一下是否应该跳转了,修改Character类的onmove方法
  1. /**
  2. * 开始移动
  3. **/
  4. Character.prototype.onmove = function (){
  5.         var self = this;
  6.         //设定一个移动步长中的移动次数
  7.         var ml_cnt = 4;
  8.         //计算一次移动的长度
  9.         var ml = STEP/ml_cnt;
  10.         //根据移动方向,开始移动
  11.         switch (self.direction){
  12.                 case UP:
  13.                         if(mapmove){
  14.                                 mapLayer.y += ml;
  15.                                 charaLayer.y += ml;
  16.                         }
  17.                         self.y -= ml;
  18.                         break;
  19.                 case LEFT:
  20.                         if(mapmove){
  21.                                 mapLayer.x += ml;
  22.                                 charaLayer.x += ml;
  23.                         }
  24.                         self.x -= ml;
  25.                         break;
  26.                 case RIGHT:
  27.                         if(mapmove){
  28.                                 mapLayer.x -= ml;
  29.                                 charaLayer.x -= ml;
  30.                         }
  31.                         self.x += ml;
  32.                         break;
  33.                 case DOWN:
  34.                         if(mapmove){
  35.                                 mapLayer.y -= ml;
  36.                                 charaLayer.y -= ml;
  37.                         }
  38.                         self.y += ml;
  39.                         break;
  40.         }
  41.         self.moveIndex++;
  42.         //当移动次数等于设定的次数,开始判断是否继续移动
  43.         if(self.moveIndex >= ml_cnt){
  44.                 //一个地图步长移动完成后,判断地图是否跳转
  45.                 if(self.isHero && self.moveIndex > 0)checkJump();
  46.                 self.moveIndex = 0;
  47.                 //一个地图步长移动完成后,如果地图处于滚动状态,则移除多余地图块
  48.                 if(mapmove)delMap();
  49.                 //如果已经松开移动键,或者前方为障碍物,则停止移动,否则继续移动
  50.                 if(!isKeyDown || !self.checkRoad()){
  51.                         self.move = false;
  52.                         return;
  53.                 }else if(self.direction != self.direction_next){
  54.                         self.direction = self.direction_next;
  55.                         self.anime.setAction(self.direction);
  56.                 }
  57.                 //地图是否滚动
  58.                 self.checkMap(self.direction);
  59.         }
  60. };
复制代码
我添加了一行
  1. if(self.isHero && self.moveIndex > 0)checkJump();
复制代码

表示,移动完后如果该人物是游戏主人公则进行跳转判断

所以,我们需要添加一个checkJump方法
  1. //游戏场景跳转测试
  2. function checkJump(){
  3.         var jump = stage.jump;
  4.         var jumpstage;
  5.         for(var i=0;i ;i++){
  6.                 jumpstage = jump[0];
  7.                 if(player.x == jumpstage.at.x * 32 && player.y == jumpstage.at.y * 32){
  8.                         //获取该场景脚本数据
  9.                         stage = script[jumpstage.to];
  10.                         //开始跳转
  11.                         initScript(stage);
  12.                         return;
  13.                 }
  14.         }
  15. }
复制代码

好了,一切都很简单吧,运行游戏看看效果吧,小鸣人走到地图的小房门的部分是,场景发生跳转

12121.jpg




游戏测试URL:

http://fsanguo.comoj.com/html5/rpg5/index.html

本次更新源代码下载:

http://legend-demo.googlecode.com/files/rpg5.zip



本文转自个人博客:http://blog.csdn.net/lufy_legend
성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
H5 코드 해체 : 태그, 요소 및 속성H5 코드 해체 : 태그, 요소 및 속성Apr 18, 2025 am 12:06 AM

HTML5 코드는 태그, 요소 및 속성으로 구성됩니다. 1. 태그는 컨텐츠 유형을 정의하고 다음과 같은 각도 브래킷으로 둘러싸여 있습니다. 2. 요소는 컨텐츠와 같은 시작 태그, 내용 및 엔드 태그로 구성됩니다. 3. 속성 시작 태그에서 키 값 쌍을 정의하고 기능을 향상시킵니다. 웹 구조를 구축하기위한 기본 단위입니다.

H5 코드 이해 : HTML5의 기본 사항H5 코드 이해 : HTML5의 기본 사항Apr 17, 2025 am 12:08 AM

HTML5는 현대적인 웹 페이지를 구축하는 핵심 기술로 많은 새로운 요소와 기능을 제공합니다. 1. HTML5는 웹 페이지 구조 및 SEO를 향상시키는 의미 론적 요소를 소개합니다. 2. 멀티미디어 요소를 지원하고 플러그인없이 미디어를 포함시킵니다. 3. 양식은 새로운 입력 유형 및 검증 속성을 향상시켜 검증 프로세스를 단순화합니다. 4. 웹 페이지 성능 및 사용자 경험을 향상시키기 위해 오프라인 및 로컬 스토리지 기능을 제공합니다.

H5 코드 : 웹 개발자를위한 모범 사례H5 코드 : 웹 개발자를위한 모범 사례Apr 16, 2025 am 12:14 AM

H5 코드에 대한 모범 사례는 다음과 같습니다. 1. 올바른 문서 선언 및 문자 인코딩 사용; 2. 시맨틱 태그를 사용하십시오. 3. HTTP 요청을 줄입니다. 4. 비동기 부하 사용; 5. 이미지 최적화. 이러한 관행은 웹 페이지의 효율성, 유지 관리 및 사용자 경험을 향상시킬 수 있습니다.

H5 : 웹 표준 및 기술의 발전H5 : 웹 표준 및 기술의 발전Apr 15, 2025 am 12:12 AM

웹 표준과 기술은 현재까지 HTML4, CSS2 및 간단한 JavaScript에서 발전했으며 중대한 개발을 거쳤습니다. 1) HTML5는 캔버스 및 웹 스토리지와 같은 API를 도입하여 웹 응용 프로그램의 복잡성과 상호 작용을 향상시킵니다. 2) CSS3은 애니메이션 및 전환 기능을 추가하여 페이지를보다 효과적으로 만듭니다. 3) JavaScript는 화살표 기능 및 클래스와 같은 Node.js 및 ES6의 최신 구문을 통해 개발 효율 및 코드 가독성을 향상시킵니다. 이러한 변경으로 인해 웹 애플리케이션의 성능 최적화 및 모범 사례의 개발이 촉진되었습니다.

H5는 HTML5의 속기입니까? 세부 사항을 탐색합니다H5는 HTML5의 속기입니까? 세부 사항을 탐색합니다Apr 14, 2025 am 12:05 AM

H5는 HTML5의 약어 일뿐 만 아니라 더 넓은 현대 웹 개발 기술 생태계를 나타냅니다. 1. H5는 HTML5, CSS3, JavaScript 및 관련 API 및 기술을 포함합니다. 2. 그것은 더 풍부하고 대화식이며 부드러운 사용자 경험을 제공하며 여러 장치에서 원활하게 실행할 수 있습니다. 3. H5 기술 스택을 사용하여 반응 형 웹 페이지와 복잡한 대화식 기능을 만들 수 있습니다.

H5 및 HTML5 : 웹 개발에 일반적으로 사용되는 용어H5 및 HTML5 : 웹 개발에 일반적으로 사용되는 용어Apr 13, 2025 am 12:01 AM

H5 및 HTML5는 동일한 것을, 즉 html5를 나타냅니다. HTML5는 HTML의 다섯 번째 버전으로 시맨틱 태그, 멀티미디어 지원, 캔버스 및 그래픽, 오프라인 스토리지 및 로컬 스토리지와 같은 새로운 기능을 제공하여 웹 페이지의 표현성 및 상호 작용성을 향상시킵니다.

H5는 무엇을 언급합니까? 맥락 탐색H5는 무엇을 언급합니까? 맥락 탐색Apr 12, 2025 am 12:03 AM

h5referstohtml5, apivotaltechnologyinwebdevelopment.1) html5introducesnewelements 및 dynamicwebapplications.2) itsupp ortsmultimediawithoutplugins, enovannangeserexperienceacrossdevices.3) SemanticLementsImproveContentsTructUreAndSeo.4) H5'Srespo

H5 : 도구, 프레임 워크 및 모범 사례H5 : 도구, 프레임 워크 및 모범 사례Apr 11, 2025 am 12:11 AM

H5 개발에서 마스터 해야하는 도구 및 프레임 워크에는 vue.js, React 및 Webpack이 포함됩니다. 1.vue.js는 사용자 인터페이스를 구축하고 구성 요소 개발을 지원하는 데 적합합니다. 2. 복잡한 응용 프로그램에 적합한 가상 DOM을 통해 페이지 렌더링을 최적화합니다. 3. Webpack은 모듈 포장에 사용되며 리소스로드를 최적화합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

MinGW - Windows용 미니멀리스트 GNU

MinGW - Windows용 미니멀리스트 GNU

이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

WebStorm Mac 버전

WebStorm Mac 버전

유용한 JavaScript 개발 도구

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전