목차
시작 단어: " >시작 단어:
제작 시작" >제작 시작
먼저 lufylegend.js 엔진을 다운로드해야 합니다" >먼저 lufylegend.js 엔진을 다운로드해야 합니다
둘째, 배경과 상자를 그려주세요" >둘째, 배경과 상자를 그려주세요
三,主人公登场,推动箱子。" >三,主人公登场,推动箱子。
四,建一个开始画面" >四,建一个开始画面
五,建一个选择画面" >五,建一个选择画面
源码" >源码
웹 프론트엔드 H5 튜토리얼 [html5 게임 개발] 클래식 소코반

[html5 게임 개발] 클래식 소코반

Mar 01, 2017 pm 04:29 PM

시작 단어:

lufylegend.js 엔진이 1.6 이상으로 업데이트되었지만 나중에 몇 가지 튜토리얼을 공개했습니다. 다른 , 또한 몇 가지 간단한 게임 예제를 제공하지만 저는 여러 가지 완전한 작품을 제작한 적이 없습니다. 사실 시간이 너무 제한되어 있습니다. 다음에는 lufylegend.js 엔진을 사용하여 가능한 한 여러 게임을 개발하겠습니다. 이것은 이 엔진의 설득력을 높이기 위한 완전한 작업입니다. HTML5와 게임 개발을 좋아하는 친구들이 더 많은 의견을 제시할 수 있기를 바랍니다.

이번에는 고전적인 Sokoban 게임을 살펴 보겠습니다. Sokoban 게임은 일본에서 시작되었으며 매우 논리적인 사고 게임입니다. 게임에서는 상자를 밀기만 할 수 있고 당길 수는 없습니다. 플레이어는 아래 그림과 같이 제한된 공간에 모든 상자를 다시 제자리에 놓아야 합니다.

[html5 게임 개발] 클래식 소코반

그림 1



이것은 최신 버전의 lufylegend.js 엔진을 사용하여 제가 개발한 것입니다. 도전하고 싶다면 아래 게임 링크를 클릭하여 몇 레벨을 통과할 수 있는지 확인할 수 있습니다.

http://lufylegend.com/demo/box

게임에는 총 6개의 레벨이 있으며 순위 시스템을 추가했습니다. 레벨을 통과한 후 자신의 결과를 업로드하고 다른 사람과 경쟁할 수도 있고, 레벨 통과 방법에 대한 자신의 경험을 아래 기사에 답글로 올릴 수도 있습니다.

제작 시작

자, 이제 이 게임을 만드는 방법을 살펴보겠습니다.

먼저 lufylegend.js 엔진을 다운로드해야 합니다

다음은 제가 포스팅한 lufylegend-1.6.0 릴리스입니다. 내 블로그 게시물

http://blog.csdn.net/lufy_legend/article/details/8593968

개발에 들어가 보겠습니다. 단계별로.

둘째, 배경과 상자를 그려주세요

먼저 그림을 준비하고


그림 2

위 그림을 5개로 균등하게 나누면 일련번호는 0,1입니다. ,2,3,4.

위의 작은 그림 5개를 사용하여 방을 연결하고 방에 상자를 배치할 수 있습니다.

예를 들어 제 블로그 시작 부분의 예시 그림 1은 게임의 첫 번째 레벨 스크린샷입니다. 이 방을 그리려면 먼저 이 그림들이 어디에 있어야 하는지 알아야 합니다. 배열을 준비합니다.


var stage01 = [
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1],
[-1,-1, 1, 1, 1, 1, 1, 1,-1,-1,-1],
[-1,-1, 1, 0, 0, 0, 0, 1, 1,-1,-1],
[-1,-1, 1, 0, 0, 4, 0, 0, 1,-1,-1],
[-1,-1, 1, 4, 4, 0, 4, 4, 1,-1,-1],
[-1,-1, 1, 0, 0, 4, 0, 0, 1,-1,-1],
[-1,-1, 1, 1, 0, 0, 0, 0, 1,-1,-1],
[-1,-1,-1, 1, 1, 1, 1, 1, 1,-1,-1],
[-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]
];

위의 -1은 넣지 않는다는 뜻이고, 0, 1, 4 등은 각각 그림 2의 일련번호에 해당한다.

이 배열에 따라 방을 그리는 것은 간단합니다. 아래 함수를 보세요.

function drawFloor(x,y){
	if(list[y][x] < 0)return;
	var bitmap = new LBitmap(bitmapDataList[list[y][x]]);
	bitmap.x = x*STEP;
	bitmap.y = y*STEP;
	boxLayer.addChild(bitmap);
}

이 목록 배열은 위의 stage01 배열이고, 매개변수 x와 y는 각각 배열의 열과 행의 일련번호이고, STEP은 작은 타일을 그리기 위해 실제로 LBitmap 개체를 만들었습니다.

LSprite 정보, LBitmap 및 기타 개체는 lufylegend.js 엔진에서 매우 일반적으로 사용되는 개체입니다. 자세한 내용은 공식 API 문서를 참조하거나 이전 기사를 읽어보세요. . 여기서 자세히 설명할 필요가 없습니다.

물론 처음에는 방에 상자가 있어야 하고 상자의 초기 위치도 미리 설정해 주어야 합니다.

var box01 = [
{x:3,y:3},
{x:4,y:3},
{x:5,y:3},
{x:5,y:5},
{x:6,y:5},
{x:7,y:5}
];

상자 그리기 기능은 다음과 같습니다

function drawBox(){
	var bitmap;
	for(var i=0;i<boxList[stageIndex].length;i++){
		bitmap = new LBitmap(bitmapDataList[2]);
		bitmap.x = boxList[stageIndex][i].x*STEP;
		bitmap.y = boxList[stageIndex][i].y*STEP;
		boxLayer.addChild(bitmap);
		nowBoxList.push(bitmap);
	}
}

위에서도 LBitmap 개체를 사용하여 이러한 상자를 표시하고 nowBoxList 배열을 사용하여 이를 저장합니다. 게임 인터페이스에 로드된 상자입니다. 상자 개체는 나중에 게임 통과 여부를 결정하는 데 사용됩니다.

stage01 배열의 4는 복원해야 할 상자의 위치를 ​​나타내므로 게임 통과 여부를 판단할 때 이 위치가 일치하는지 여부만 판단하면 됩니다. 모든 상자의 위치는 다음과 같습니다.

function checkBox(){
	var bitmap,x,y,win=true;
	list = [];
	for(var i=0;i<stageList[stageIndex].length;i++){
		list.push(stageList[stageIndex][i].join(",").split(","));
	}
	
	for(var i=0;i<nowBoxList.length;i++){
		bitmap = nowBoxList[i];
		x = bitmap.x / STEP;
		y = bitmap.y / STEP;
		if(list[y][x] == 4){
			bitmap.bitmapData = bitmapDataList[3];
		}else{
			bitmap.bitmapData = bitmapDataList[2];
			win = false;
		}
		list[y][x] += 10;
	}
	if(win)gameClearShow();
}

프로그램에서 직접 코드를 가로채서 새로운 배열과 객체가 등장했습니다.

stageList储存了所有的关卡信息,stageIndex是当前关卡的序号,stageList[stageIndex]就可以获取当前关卡的信息,bitmapDataList数组储存了图1中小图片的LBitmapData对象,这些暂且不说,关键是下面。

		if(list[y][x] == 4){
			bitmap.bitmapData = bitmapDataList[3];
		}else{
			bitmap.bitmapData = bitmapDataList[2];
			win = false;
		}

函数中循环了所有箱子的位置,如果他们的位置的序号为4,则表示该箱子已经归位,全部归位表示过关,否则游戏继续,返回false。

三,主人公登场,推动箱子。

同样准备一张图片,如下


图3

人物走动动画,当然就需要lufylegend引擎中另一个重要的对象LAnimation,它专门用来顺序播放图片以形成动画,具体用法请参照官方API文档。

下面是主人公的构造器

/**
 * 循环事件 
 * @param data 图片数据
 * @param row 图片分割行数
 * @param col 图片分割列数
 **/
function Character(data,row,col){
	base(this,LSprite,[]);
	var self = this;
	//设定人物动作速度
	self.speed = 2;
	self.speedIndex = 0;
	//设定人物大小
	data.setProperties(0,0,data.image.width/col,data.image.height/row);
	//得到人物图片拆分数组
	var list = LGlobal.pideCoordinate(data.image.width,data.image.height,row,col);
	//设定人物动画
	self.anime = new LAnimation(this,data,list);
	//设定不移动
	self.move = false;
	//在一个移动步长中的移动次数设定
	self.moveIndex = 0;
};

主人公如何推动箱子,看下面的onmove函数

/**
 * 开始移动 
 **/
Character.prototype.onmove = function (){
	var self = this;
	//设定一个移动步长中的移动次数
	var ml_cnt = 4;
	//计算一次移动的长度
	var ml = STEP/ml_cnt;
	//根据移动方向,开始移动
	switch (self.direction){
		case UP:
			self.y -= ml;
			if(box)box.y -= ml;
			break;
		case LEFT:
			self.x -= ml;
			if(box)box.x -= ml;
			break;
		case RIGHT:
			self.x += ml;
			if(box)box.x += ml;
			break;
		case DOWN:
			self.y += ml;
			if(box)box.y += ml;
			break;
	}
	self.moveIndex++;
	//当移动次数等于设定的次数,开始判断是否继续移动
	if(self.moveIndex >= ml_cnt){
		self.moveIndex = 0;
		box = null;
		self.move = false;
		checkBox();
	}
};

可以看到,箱子是不是跟着主人公一起走,关键是要看box这个变量,这个变量的值是在下面的checkRoad函数中设置的。

Character.prototype.checkRoad = function (dir){
	var self = this;
	var tox,toy;
	//开始计算移动目的地的坐标
	switch (dir){
		case UP:
			tox = 0;
			toy = -1;
			break;
		case LEFT:
			tox = -1;
			toy = 0;
			break;
		case RIGHT:
			tox = 1;
			toy = 0;
			break;
		case DOWN:
			tox = 0;
			toy = 1;
			break;
	}
	if(list[self.y/STEP + toy][self.x/STEP + tox]==1)return false;
	if(list[self.y/STEP + toy][self.x/STEP + tox]>4){
		if(list[self.y/STEP + toy*2][self.x/STEP + tox*2]==1 || list[self.y/STEP + toy*2][self.x/STEP + tox*2]>4)return false;
		box = getBox(self.x + tox*STEP,self.y + toy*STEP);
	}
	return true;
};

其实,就是判断一下主人公要走的方向的前方是不是有障碍物,如果障碍物是墙则不可移动,如果是箱子的话,就要看看箱子的后面是不是有障碍物,如果有则不可移动,否则箱子就需要跟着主人公一起移动,将box设置为主人公前方的箱子即可。
上面这个函数,是在人物即将发生移动的时候被调用的,如下。

/**
 * 改变人物方向,并判断是否可移动
 **/
Character.prototype.changeDir = function (dir){
	var self = this;
	if(self.move)return;
	self.direction = dir;
	self.anime.setAction(dir);
	if(!self.checkRoad(dir))return;
	self.move = true;
	steps.text = parseInt(steps.text) + 1;
};

当图1中的方向图标被按下的时候,根据点击的方向,来实现人物的移动。

点击方向图标的方法当然是鼠标事件

ctrlLayer.addEventListener(LMouseEvent.MOUSE_UP,onCtrl);

然后在onCtrl函数中根据点击的位置,来进行相应的移动。

function onCtrl(event){
	var ctrlSize = 60;
	if(event.selfX >= ctrlSize && event.selfX <= ctrlSize*2){
		if(event.selfY >= 0 && event.selfY <= ctrlSize){
			player.changeDir(UP);
		}else if(event.selfY >= ctrlSize*2 && event.selfY <= ctrlSize*3){
			player.changeDir(DOWN);
		}
	}else if(event.selfY >= ctrlSize && event.selfY <= ctrlSize*2){
		if(event.selfX >= 0 && event.selfX <= ctrlSize){
			player.changeDir(LEFT);
		}else if(event.selfX >= ctrlSize*2 && event.selfX <= ctrlSize*3){
			player.changeDir(RIGHT);
		}
	}
}

这样,游戏的主要功能部分,就介绍完了。

四,建一个开始画面

如下。


[html5 게임 개발] 클래식 소코반

图4

使用lufylegend.js引擎做个界面,可以说毫无难度,代码如下。

function GameLogo(){
	base(this,LSprite,[]);
	var self = this;
	
	var logolist = [[1,1,1,1],[1,2,4,1],[1,4,2,1],[1,1,1,1]];
	var bitmap,logoLayer;
	
	logoLayer = new LSprite();
	logoLayer.graphics.drawRect(6,"#FF7F50",[0,0,LGlobal.width,LGlobal.height],true,"#FFDAB9");
	self.addChild(logoLayer);
	
	logoLayer = new LSprite();
	logoLayer.x = 50;
	logoLayer.y = 50;
	for(var i=0;i<logolist.length;i++){
		for(var j=0;j<logolist.length;j++){
			bitmap = new LBitmap(bitmapDataList[logolist[i][j]]);
			bitmap.x = j*STEP;
			bitmap.y = i*STEP;
			logoLayer.addChild(bitmap);
		}
	}
	bitmap = new LBitmap(new LBitmapData(imglist["player"],0,0,STEP,STEP));
	bitmap.x = STEP;
	bitmap.y = 2*STEP;
	logoLayer.addChild(bitmap);
	self.addChild(logoLayer);
	
	labelText = new LTextField();
	labelText.rotate = -20;
	labelText.color = "#4B0082";
	labelText.font = "HG行書体";
	labelText.size = 100;
	labelText.x = 300;
	labelText.y = 50;
	labelText.stroke = true;
	labelText.lineWidth = 4;
	labelText.text = "推";
	self.addChild(labelText);
	
	labelText = new LTextField();
	labelText.color = "#4B0082";
	labelText.font = "HG行書体";
	labelText.size = 100;
	labelText.x = 450;
	labelText.y = 60;
	labelText.stroke = true;
	labelText.lineWidth = 4;
	labelText.text = "箱";
	self.addChild(labelText);
	
	labelText = new LTextField();
	labelText.rotate = 20;
	labelText.color = "#4B0082";
	labelText.font = "HG行書体";
	labelText.size = 100;
	labelText.x = 600;
	labelText.y = 60;
	labelText.stroke = true;
	labelText.lineWidth = 4;
	labelText.text = "子";
	self.addChild(labelText);
	
	labelText = new LTextField();
	labelText.color = "#B22222";
	labelText.font = "HG行書体";
	labelText.size = 40;
	labelText.x = 100;
	labelText.y = 250;
	labelText.stroke = true;
	labelText.lineWidth = 4;
	labelText.text = "Click to Start Game !!";
	self.addChild(labelText);
	
	var social = new Social();
	social.x = 220;
	social.y = 330;
	self.addChild(social);
	
	labelText = new LTextField();
	labelText.font = "HG行書体";
	labelText.size = 14;
	labelText.x = 400;
	labelText.y = 390;
	labelText.text = "- Html5 Game Engine lufylegend.js";
	self.addChild(labelText);
	labelText = new LTextField();
	labelText.color = "#006400";
	labelText.font = "HG行書体";
	labelText.size = 14;
	labelText.x = 400;
	labelText.y = 410;
	labelText.text = "http://www.lufylegend.com/lufylegend";
	self.addChild(labelText);
	
	self.addEventListener(LMouseEvent.MOUSE_UP,menuShow);
};

就是显示几张图片,以及添加一些文字,LTextField对象的使用方法请参考官方API文档。

五,建一个选择画面

如下。


[html5 게임 개발] 클래식 소코반

图5

代码如下。

function GameMenu(){
	base(this,LSprite,[]);
	var self = this;
	
	var menuLayer;
	menuLayer = new LSprite();
	menuLayer.graphics.drawRect(6,"#ADD8E6",[0,0,LGlobal.width,LGlobal.height],true,"#E6E6FA");
	self.addChild(menuLayer);
	
	labelText = new LTextField();
	labelText.color = "#B22222";
	labelText.font = "HG行書体";
	labelText.size = 40;
	labelText.x = 200;
	labelText.y = 30;
	labelText.stroke = true;
	labelText.lineWidth = 4;
	labelText.text = "Please select !!";
	menuLayer.addChild(labelText);
	for(var i=0;i<stageMenu.length;i++){
		self.stageVsMenu(stageMenu[i]);
	}
};
GameMenu.prototype.stageVsMenu = function(obj){
	var self = this;
	
	var menuButton,btn_up;
	if(obj.open){
		btn_up = new LSprite();
		btn_up.graphics.drawRect(2,"#000",[0,0,150,90],true,"#191970");
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 20;
		labelText.x = 40;
		labelText.y = 5;
		btn_up.addChild(labelText)
		labelText.text = "第"+(obj.index+1)+"关";
		
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 12;
		labelText.x = 10;
		labelText.y = 40;
		btn_up.addChild(labelText)
		labelText.text = "step:"+obj.step;
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 12;
		labelText.x = 10;
		labelText.y = 60;
		btn_up.addChild(labelText)
		labelText.text = "times:"+obj.times;
		
		
		var btn_down = new LSprite();
		btn_down.graphics.drawRect(2,"#000",[0,0,150,90],true,"#2F4F4F");
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 20;
		labelText.x = 40;
		labelText.y = 5;
		labelText.text = "第"+(obj.index+1)+"关";
		btn_down.addChild(labelText);
		
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 12;
		labelText.x = 10;
		labelText.y = 40;
		btn_down.addChild(labelText)
		labelText.text = "step:"+obj.step;
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 12;
		labelText.x = 10;
		labelText.y = 60;
		btn_down.addChild(labelText)
		labelText.text = "times:"+obj.times;
		
		menuButton = new LButton(btn_up,btn_down);
		menuButton.obj = obj;
		menuButton.addEventListener(LMouseEvent.MOUSE_UP,function(event,self){
			gameStart(self.obj.index);
		});
	}else{
		btn_up = new LSprite();
		btn_up.graphics.drawRect(2,"#000",[0,0,150,90],true,"#708090");
		labelText = new LTextField();
		labelText.color = "#ffffff";
		labelText.font = "HG行書体";
		labelText.size = 20;
		labelText.x = 40;
		labelText.y = 5;
		btn_up.addChild(labelText)
		labelText.text = "???";
		menuButton = btn_up;
	};
	self.addChild(menuButton);
	menuButton.x = obj.x * 220 + 100; 
	menuButton.y = obj.y * 140 + 130;
}

好了,游戏主要的代码已经都贴出来了。

源码

由于上面的代码比较零碎,而且我也只是挑中心部分说了一下,下面提供完整游戏源代码,想研究一下的朋友可以点击下面的连接下载。

http://lufylegend.com/lufylegend_download/box.rar

注意:该附件只包含本次文章源码,lufylegend.js引擎请到http://lufylegend.com/lufylegend进行下载。


 以上就是[html5游戏开发]经典的推箱子的内容,更多相关内容请关注PHP中文网(m.sbmmt.com)!


본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

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

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

microdata 란 무엇입니까? HTML5가 설명했습니다 microdata 란 무엇입니까? HTML5가 설명했습니다 Jun 10, 2025 am 12:09 AM

microdataenhancesseoandcontentDisplayInsearchResultsBeddingstructuredDataintohtml.1) useitemScope, itemType, anditemPropattRiptestEdSemanticManing.2) ApplyMicRodatokeyContent likesbooksorproductsnippets.3) bancumentUOGOFOOMPLUTETHTHTHTML

HTML5 MicroData : 최고의 온라인 도구 HTML5 MicroData : 최고의 온라인 도구 Jun 09, 2025 am 12:06 AM

thebestonlinetoolsforhtml5microdataarearegoogluctureddatamarkuphelperandschema.org'smarkupvalidator.1) GooglestructuredDatama rkuphelperisuser- 친근한, 안내 원자로 dmicrodatatagsforenhancedseo.2) schema.org'smarkupvalidatorchecksmicrodataimplementa

HTML5의 MicroData : 더 나은 검색 엔진 순위의 열쇠 HTML5의 MicroData : 더 나은 검색 엔진 순위의 열쇠 Jun 12, 2025 am 10:22 AM

microdataSignically improvesseobyenhancingsearchengineNderdingand andwwebpages.1) ItaddsSmanticmeaningtohtml, AidingBetterIndexing.2) ItenablesRoughsnippets, insecorrectschema.orgvocabularyAbularyAbularyAblated

HTML5 목표 : 빠른 시작 가이드 HTML5 목표 : 빠른 시작 가이드 May 18, 2025 am 12:18 AM

html5aimstoimprovewebaccessibility, 효율성 및 산림 론적 분야 및 개발자

HTML5 사양 : 주요 목표와 동기 탐색 HTML5 사양 : 주요 목표와 동기 탐색 May 16, 2025 am 12:19 AM

TheKeyGoalSandMotivationSBehindhtml5WeretoEnhancesemanticstructure, EverneMultImediasupport, andensureBetTerferfortPerformanceAndCompatibilityAcrossDevices, DrivenBytheneedToaddresshtml4'SlimitationsAndModernWebDemands.1) HTMl5AIMEDTOMPROVETUCETUR

HTML5에 소개 된 주요 기능은 무엇입니까? HTML5에 소개 된 주요 기능은 무엇입니까? Jun 19, 2025 pm 11:57 PM

html5intructeDkeyFeaturestHattransformedWebDevelopment.1. SemanticElementslike, and andAccessility, andaccessibility.2.nativeMultimediasupportViaandTagseliminatedRelianceonPlugins.3.enhancedFormControlSinCludingType = "이메일"andr

HTML5 서버-미시록 이벤트로 다시 연결 및 오류를 처리합니다. HTML5 서버-미시록 이벤트로 다시 연결 및 오류를 처리합니다. Jul 03, 2025 am 02:28 AM

HTML5SSE를 사용하는 경우 재 연결 및 오류를 처리하는 방법에는 다음이 포함됩니다. 1. 기본 재 연결 메커니즘을 이해하십시오. 이벤트 소스는 기본적으로 연결이 중단 된 후 3 초 후에 재 시도합니다. 레트리 필드를 통해 간격을 사용자 정의 할 수 있습니다. 2. 오류 이벤트를 듣고 연결 고장 또는 구문 분석 오류를 처리하고 오류 유형을 구별하고 자동 재 연결에 의존하는 네트워크 문제, 서버 오류 재 연결 지연 및 인증 실패 TOKEN과 같은 해당 논리를 실행합니다. 3. 연결을 수동으로 닫고 재건하고, 최대 리트리 시간 수를 설정하고, Navigator.online과 네트워크 상태를 결합하여 재판 전략을 최적화하는 등 재 연결 로직을 적극적으로 제어하십시오. 이러한 조치는 응용 프로그램 안정성과 사용자 경험을 향상시킬 수 있습니다.

HTML5를 사용하여 목표를 달성하기가 어렵습니까? HTML5를 사용하여 목표를 달성하기가 어렵습니까? May 16, 2025 am 12:06 AM

html5isnotparticular indifficulttousebutreequiresunderstandingStandingStandingStandingStandingStandingStandingStandingStandingStandingStandingStandingS

See all articles