이 기사의 내용은 간단한 퍼즐 게임을 구현하기 위해 기본 JavaScript를 사용하는 방법에 대한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
1. 게임의 기본 로직
언어를 사용하여 게임을 개발하려면 먼저 이 언어를 사용하여 이미지 그리기, 상호 작용 처리, 타이머, 등.
그래픽 그리기는 모든 것의 기본입니다. 여기서는 JavaScript
를 사용하여 캔버스
에 그립니다. 즉, 먼저 html
에서 canvas
요소를 생성한 다음 JavaScript
에서 이 요소를 ID로 가져오고 canvas code> 후속 그리기를 준비하기 위해 해당 컨텍스트 환경 <code>context
를 가져옵니다. JavaScript
在 canvas
上进行绘制。即先在 html
中创建 canvas
元素,然后在 JavaScript
中,通过 id 拿到这个元素,并且通过 canvas
拿到对应的上下文环境 context
,为后续的绘图做好准备。
<canvas id="background" width="450px" height="450px"></canvas>
var background = document.getElementById("background"); var context = background.getContext('2d');
通过 context
的 drawImage
方法可以绘制图片,这里进行了相应的封装:
注:这里要等图片加载完毕后再进行绘制,即在 onload
中去调用 drawImage
方法,否则会绘制失败。
var drawImageItem = function(index, position) { var img = new Image(); img.src = './image/dog_0' + String(index+1) + '.jpg'; img.onload = () => { var rect = rectForPosition(position); context.drawImage(img, rect[0], rect[1], rect[2], rect[3]); } }
在绘制图片之后,我们还需要去动态刷新视图,否则 canvas
就只是一张静态的图片。如果是简单的图形刷新,只需在原来的位置重新绘制,进行覆盖即可。但有时候我们只需要将原来已存在的图形清除掉,而不需要绘制新图案。比如在拼图游戏中,将一个方块移动到另一个位置后,需要清空原来的位置。
通过 context
的 clearRect
方法可以达到清除的目的。以下是清除 canvas
的某个区域的代码:
var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]);
有了图形的绘制后,我们还需要处理玩家的输入事件,然后根据输入事件,来决定什么时候刷新视图。输入事件可以分为 3 种:在手机上有触屏事件;在 PC 上,有鼠标和键盘事件。
JavaScript
中对触屏和鼠标点击的监听是一样的,都是通过 canvas
的 onclick
事件进行回调,具体如下:
// 屏幕点击 background.onclick = function(e) { };
我们可以通过 e.offsetX
、 e.offsetY
来获取触控点在 canvas
中的位置。
注: canvas
的坐标原点在左上角,即左上角的坐标是 (0, 0)
。
键盘的按键点击则是通过 document
的 onkeyup
、 onkeydown
等事件进行回调。 onkeyup
是指按键的抬起事件, onkeydown
是指按键的按下事件。我们可以通过 keyCode
知道当前具体是哪一个按键,然后根据不同的按键去处理不同的逻辑,如下:
if (event.keyCode == '37') { // 左 // do something } else if (event.keyCode == '38') { // 上 // do something } else if (event.keyCode == '39') { // 右 // do something } else if (event.keyCode == '40') { // 下 // do something }
有时候,除了在玩家输入的时候需要去刷新视图,还需要每隔一段时间定时去刷新视图。比如在一个贪吃蛇游戏中,就需要每隔一段时间就去刷新蛇的位置。
这个时候我们就需要一个定时器,让它每隔一段时间去执行一段刷新视图的代码。我们通过 setInterval
方法来实现定时器功能:
setInterval("run()", 100);
上面这段代码表示每隔 100 毫秒,去执行一次 run
方法。
有了游戏的基础逻辑,下面来看一下如何实现拼图的逻辑。
因为不是任意序列都可以通过平移的方式来还原,所以我们不能简单地生成一个随机序列。比如 1、0、2、3、4、5、6、7、8
这个序列,无论怎么平移,都不可能还原。
这里采取的做法是:预先设置了 4 个可还原的序列,先从这 4 个序列中随机选取一个,然后再对序列进行模拟平移若干步骤。以此来尽可能地保证初始序列的多样性,也保证了序列的可还原性。具体代码如下:
var setupRandomPosition = function() { var list1 = [4, 3, 2, 8, 0, 7, 5, 6, 1]; var list2 = [2, 0, 5, 6, 8, 7, 3, 1, 4]; var list3 = [3, 7, 2, 4, 1, 6, 8, 0, 5]; var list4 = [3, 2, 4, 1, 7, 6, 5, 0, 8]; var lists = [list1, list2, list3, list4]; imageIndexForPosition = lists[parseInt(Math.random() * 4)]; // 获取空位位置 var emptyPosition = 0; for (var i = imageIndexForPosition.length - 1; i >= 0; i--) { if (imageIndexForPosition[i] == lastIndex()) { emptyPosition = i; break; } } background.emptyPosition = emptyPosition; // 随机移动次数 var times = 10; while (times--) { // 获取随机数,决定空位哪个位置进行移动 var direction = parseInt(Math.random() * 4); var target = -1; if (direction == 0) { target = topOfPosition(emptyPosition); // 上 } else if (direction == 1) { target = leftOfPosition(emptyPosition); // 左 } else if (direction == 2) { target = rightOfPosition(emptyPosition); // 右 } else if (direction == 3) { target = bottomOfPosition(emptyPosition); // 下 } if (target < 0 || target > lastIndex()) { // 位置不合法,继续下一次循环 continue; } var result = moveImageIfCanAtPosition(target); if (result >= 0) { // 如果移动成功,更新空位的位置 emptyPosition = target; } } }
在保存顺序的时候,是用 0~8 这 9 个数字来保存,而空白的方块是数字 8 的位置。所以判断可以移动的唯一条件是,目标位置的值是否为 8。代码如下:
var isPositionEmpty = function(position) { if (position < 0 || position > lastIndex()) { return false; } if (imageIndexForPosition[position] == lastIndex()) { return true; } else { return false; } }
上面 lastIndex()
var refreshImagePositions = function(origin, target) { var originRect = rectForPosition(origin); context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]); drawImageItem(imageIndexForPosition[target], target); }
var checkIfFinish = function() { for (var index = 0; index < imageIndexForPosition.length; index++) { if (index != imageIndexForPosition[index]) { return false; } } return true; }
context
의 drawImage
메서드를 통해 그림을 그릴 수 있습니다. 해당 캡슐화는 여기에서 수행됩니다.
참고:
그림이 나타날 때까지 기다려야 합니다. 즉,onload
에서 drawImage
메서드를 호출하세요. 그렇지 않으면 그리기가 실패합니다. // 屏幕点击 background.onclick = function(e) { if (isFinish) { return; } // do something }; // 键盘按钮事件 document.onkeyup = function(event) { if (isFinish) { return; } // do something }
캔버스
는 정적 그림일 뿐입니다. 단순한 그래픽 새로고침이라면 원래 위치에 다시 그려서 덮어쓰면 됩니다. 하지만 때로는 새로운 그래픽을 그리지 않고 기존 그래픽을 지워야 하는 경우도 있습니다. 예를 들어 직소 퍼즐의 경우 블록을 다른 위치로 이동한 후 원래 위치를 지워야 합니다. 삭제 목적은 context
의 clearRect
메서드를 통해 달성할 수 있습니다. 다음은 캔버스
의 특정 영역을 지우는 코드입니다: 🎜rrreee🎜2.이벤트 처리🎜🎜그래픽을 그린 후 플레이어의 입력 이벤트도 처리한 다음 이를 기반으로 결정해야 합니다. 입력 이벤트에서 보기를 새로 고칠 시기입니다. 입력 이벤트는 휴대폰의 터치스크린 이벤트, PC의 마우스 및 키보드 이벤트의 세 가지 유형으로 나눌 수 있습니다. 🎜🎜JavaScript
는 터치 스크린과 마우스 클릭을 동일한 방식으로 모니터링하며, 둘 다 다음과 같이 canvas
의 onclick
이벤트를 통해 호출됩니다. 🎜 rrreee🎜e.offsetX
및 e.offsetY
를 사용하여 캔버스
에서 터치 포인트의 위치를 가져올 수 있습니다. 🎜🎜참고: 캔버스
의 좌표 원점은 왼쪽 상단에 있습니다. 즉, 왼쪽 상단의 좌표는 (0, 0)
입니다. 🎜🎜키보드 키 클릭은 document
의 onkeyup
및 onkeydown
과 같은 이벤트를 통해 다시 호출됩니다. onkeyup
은 키 리프트 이벤트를 나타내고, onkeydown
은 키 누름 이벤트를 나타냅니다. keyCode
를 사용하여 현재 어떤 키가 눌러져 있는지 알 수 있으며 다음과 같이 다른 키에 따라 다른 논리를 처리할 수 있습니다. 🎜rrreee🎜3. Timer🎜🎜때때로 플레이어가 입력할 때를 제외하고 새로 고쳐지려면 뷰를 주기적으로 새로 고쳐야 합니다. 예를 들어, 뱀 게임에서는 뱀의 위치를 가끔씩 새로 고쳐야 합니다. 🎜🎜이때 가끔씩 뷰를 새로 고치는 코드를 실행하는 타이머가 필요합니다. setInterval
메소드를 통해 타이머 기능을 구현합니다. 🎜rrreee🎜위 코드는 run
메소드가 100밀리초마다 실행된다는 의미입니다. 🎜1, 0, 2, 3, 4, 5, 6, 7, 8
시퀀스는 어떻게 번역하더라도 복원할 수 없습니다. 🎜🎜여기에서 취한 접근 방식은 4개의 축소 가능 시퀀스를 미리 설정하고, 먼저 이 4개의 시퀀스 중 하나를 무작위로 선택한 다음 해당 시퀀스에서 여러 단계의 번역을 시뮬레이션하는 것입니다. 이런 방식으로 초기 서열의 다양성이 최대한 보장되고, 서열의 환원성도 보장됩니다. 구체적인 코드는 다음과 같습니다. 🎜rrreee🎜2. 사각형을 이동할 수 있는지 여부를 결정합니다🎜🎜순서를 저장할 때 0부터 8까지 9개의 숫자를 사용하여 저장하며, 빈 사각형은 숫자 8의 위치입니다. 따라서 이동 가능 여부를 판단하는 유일한 조건은 목표 위치의 값이 8인지 여부입니다. 코드는 다음과 같습니다. 🎜rrreee🎜위의 lastIndex()
값은 8입니다. 🎜🎜3. 블록 이동 실현🎜🎜블록 이동 구현은 매우 간단합니다. 먼저 이전 위치에서 그래픽을 지우고 새 위치에 그립니다. 🎜rrreee🎜4. 완료되었는지 확인🎜🎜패턴이 복원되었는지 확인하려면 배열을 한 번만 순회하여 순서대로 확인하면 됩니다. 🎜var checkIfFinish = function() { for (var index = 0; index < imageIndexForPosition.length; index++) { if (index != imageIndexForPosition[index]) { return false; } } return true; }
当图案还原之后,我们不希望玩家还能通过键盘或鼠标来移动方块,这个时候就需要对交互事件进行屏蔽。
只需要一个标志位就可以达到这个目的:
// 屏幕点击 background.onclick = function(e) { if (isFinish) { return; } // do something }; // 键盘按钮事件 document.onkeyup = function(event) { if (isFinish) { return; } // do something }
当图案还原之后,标志位 isFinish 会被置为 true ,然后在屏幕点击和键盘按钮响应事件的开始处添加判断,如果已经结束,则不继续走方块移动的逻辑。
위 내용은 네이티브 JavaScript를 사용하여 간단한 퍼즐 게임을 구현하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!