자 바스 크 립 트 와 Canvas 를 이용 한 게임 개발

작성 자: Matthew Casperson • 편집: Michele McDonough
1. Canvas 2 를 인식 하고 Canvas 에 그림 그리 기 3, Canvas 요 소 를 통 해 고급 이미지 조작 실현 4, Canvas 를 통 해 시차 스크롤 5, 게임 프레임 워 크 쓰기 (1) 6, 게임 프레임 워 크 쓰기 (2) 7, 애니메이션 8, JavaScript 키보드 입력 9, 종합 운용 10, 정의 단계 11, 점프 와 추락 12, 아 이 템 추가 13, 자원 추가 14, 메 인 메뉴 추가
1 、 Canvas 를 알 아 보 세 요
http://www.brighthub.com/internet/web-development/articles/38364.aspx
Canvas 요소 와 JavaScript 엔진 에 추 가 된 일부 특성 으로 웹 개발 자 들 이 제3자 플러그 인 을 빌 리 지 않 아 도 정교 하고 상호작용 이 있 는 2D 웹 페이지 를 디자인 개발 할 수 있 습 니 다.이 글 은 Canvas 요소 와 가능 한 용 도 를 소개 합 니 다.
JavaScript 와 Canvas 요소
HTML 은 정적 페이지 를 만 들 기 위해 생 긴 것 입 니 다.HTML 이 구현 할 수 있 는 동적 효 과 는 GIF 애니메이션 과 반 짝 이 는 텍스트 만 표시 합 니 다.자 바스 크 립 트 는 웹 페이지 를 동적 으로 수정 할 수 있 도록 이 모든 것 을 바 꾸 었 다.오늘날 많은 웹 서 비 스 는 AJAX 를 이용 하여 웹 페이지 를 만 들 고 사용자 에 게 더욱 유창 한 체험 을 제공 하 며 표준 HTML 페이지 에서 흔히 볼 수 있 는 '클릭 - 다시 불 러 오기 - 클릭' 식 의 상호작용 모델 을 초월 한다.
그러나 자 바스 크 립 트 의 일부 기능 은 홈 브 라 우 저의 제약 을 받는다.웹 페이지 에서 모든 요 소 를 만 들 고 수정 할 수 있 지만 자바 스 크 립 트 는 브 라 우 저 에 새로운 대상 을 쉽게 표시 할 수 없습니다.자 바스 크 립 트 를 통 해 텍스트 를 수정 하거나 그림 을 삽입 하거나 표 크기 를 조정 하 는 것 은 매우 쉽다. 왜냐하면 이 대상 들 은 원래 HTML 이 지원 하 는 것 이기 때문이다.만약 당신 이 좀 더 자극 적 으로 하고 싶다 면, 예 를 들 어 홈 페이지 게임 을 쓰 면 어떻게 합 니까?그것 은 표준 HTML 요소 의 용 도 를 바 꾸 고 여러 가지 예측 하지 못 한 것 을 극복 해 야 목적 을 달성 할 수 있 을 것 이다.아니면 플래시 나 Silverlight 같은 플러그 인 에 도움 을 청해 야 합 니 다.
캔버스 요소 가 등장 했다.이 새로운 HTML 요 소 는 자 바스 크 립 트 개발 자 에 게 플러그 인 없 이 웹 페이지 에서 직접 그림 을 그 릴 수 있 는 메커니즘 을 제공 합 니 다.Canvas 요 소 는 애플 이 웹 키 트 프레임 워 크 에 도입 한 것 으로 Safari 브 라 우 저 와 Dashboard 마이크로 부품 이 모두 사용 되 고 있다.Canvas 요 소 는 현재 HTML 5 규범 을 추가 하 는 것 이 권장 되 어 최신 Chrome, Firefox, Opera, Konqueror 등 브 라 우 저의 지원 을 받 고 있 습 니 다.Internet Explorer (적어도 IE8 이전) 는 Canvas 를 지원 하지 않 았 지만, Explorer Canvas 프로젝트 는 IE 에 Canvas 요소 와 유사 한 기능 을 제공 했다.
Canvas 요 소 는 2D 그래 픽 프로 그래 밍 을 한 사람 에 게 는 식 은 죽 먹 기다.이 요소 에 선 을 그리고 여러 모양 을 그리고 그 라 데 이 션 을 그 릴 수 있 으 며 다른 2D API 와 유사 한 함 수 를 이용 하여 모든 픽 셀 을 수정 할 수 있 습 니 다.크롬의 V8, Firefox 의 Spider Monkey, Safari 의 Nitro 등 최신 자 바스 크 립 트 엔진 의 성능 덕분에 정교 하고 상호작용 적 인 웹 애플 리 케 이 션 을 만 드 는 데 전혀 문제 가 없다.
우리 의 이 일련의 글 은 자바 스 크 립 트 와 Canvas 요 소 를 사용 하여 간단 한 플랫폼 게임 을 만 드 는 것 을 알려 줄 것 이다.애니메이션, 자원 불 러 오기, 레이 어 링, 스크롤 과 상호작용 을 포함 합 니 다.예제 코드 와 실제 효 과 를 한 걸음 한 걸음 보 여 줌 으로 써 강력 한 Canvas 요 소 를 어떻게 다 루 는 지 빨리 배 울 수 있 습 니 다.
2. Canvas 에 그림 그리 기
http://www.brighthub.com/internet/web-development/articles/38744.aspx
다음은 자바 스 크 립 트 를 사용 하여 Canvas 요소 에 그림 을 그리고 애니메이션 을 실현 하 는 방법 을 보 여 줍 니 다.
준비 작업 이 Canvas 요소 가 무엇 인지 알 게 된 후 화면 에 그림 을 그 리 는 것 을 배 워 야 합 니 다.우선, Canvas 요 소 를 배치 하고 표시 하기 위해 HTML 페이지 가 필요 합 니 다.
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
 <html lang="en">
    <head>
       <title>JavaScript Platformer 1</title>
       <script type="text/javascript" src="jsplatformer1.js"></script>
       <style type="text/css">
          body { font-family: Arial,Helvetica,sans-serif;}
       </style>
    </head>
   <body>
      <p>
         <a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx">
            Game Development with Javascript and the canvas element
         </a>
      </p>
      <canvas id="canvas" width="600" height="400">
         <p>Your browser does not support the canvas element.</p>
      </canvas>
   </body>
</html>
이 HTML 코드 들 은 매우 직관 적 이다.그 중 에는 두 개의 중요 한 원소 가 있다.
<script type="text/javascript" src="jsplatformer1.js"></script>
여기 에는 Canvas 요 소 를 수정 할 자바 스 크 립 트 코드 가 포함 되 어 있 습 니 다. 이에 대응 하 는 Canvas 요소 의 표 시 는 다음 과 같 습 니 다.
<canvas id="canvas" width="600" height="400">
	<p>Your browser does not support the canvas element.</p>
</canvas>

이 코드 는 Canvas 요 소 를 만 들 었 습 니 다.Canvas 브 라 우 저 는 지원 되 지 않 습 니 다. 예 를 들 어 Internet Explorer (IE8 이전 버 전) 는 이 요 소 를 무시 하고 하위 요소 만 표시 합 니 다.이 간단 한 예 에서 이 하위 요 소 는 하나의 단락 입 니 다. 그 중의 텍스트 는 사용자 에 게 브 라 우 저가 Canvas 요 소 를 지원 하지 않 는 다 는 것 을 알려 줍 니 다.Chrome, Opera, Firefox 와 같은 Canvas 요 소 를 지원 하 는 브 라 우 저 는 Canvas 요소 의 하위 요 소 를 무시 합 니 다.
이 Canvas 요소 의 ID 속성 은 매우 중요 합 니 다. 왜냐하면 뒤의 JavaScript 는 이 요 소 를 통 해 인용 을 얻 을 수 있 기 때 문 입 니 다.한편, width 와 height 속성 은 캔버스 의 너비 와 높이 를 지정 합 니 다. 이 두 속성 은 table 이나 img 등 다른 HTML 요소 의 동명 속성 역할 과 같 습 니 다.
다음은 jsplatformer 1. js 코드 입 니 다.
//   target 
const FPS = 30;
var x = 0;
var y = 0;
var xDirection = 1;
var yDirection = 1;
var image = new Image();
//              (   ,        Content-Type application/empty,       )
image.src = "http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg";
var canvas = null;
var context2D = null;

window.onload = init;
function init(){
	canvas = document.getElementById('canvas');
	context2D = canvas.getContext('2d');
	setInterval(draw, 1000/FPS);
}
function draw(){
	context2D.clearRect(0, 0, canvas.width, canvas.height);
	context2D.drawImage(image, x, y);
	x += 1* xDirection;
	y += 1* yDirection;

	if (x >= 450) {
		x = 450;
		xDirection = -1;
	}else if(x <= 0){
		x = 0;
		xDirection = 1;
	}
	if (y >= 250) {
		y = 250;
		yDirection = -1;
	}else if(y <= 0){
		y = 0;
		yDirection = 1;
	}
}

하나의 Canvas 요소 일 뿐 아무 소 용이 없다.JavaScript 는 이 캔버스 에 무엇 을 그 려 야 합 니까? 해당 코드 는 jsplatformer 1. js 에 저장 해 야 합 니 다.쉽게 말 하면 자 바스 크 립 트 는 그림 을 불 러 온 다음 캔버스 위 에 그 려 놓 고 캔버스 위 에서 이동 시 켰 다.
우선, 전역 변 수 를 정의 합 니 다.
const FPS = 30;
FPS 는 캔버스 재 그림 의 빈 도 를 정의 합 니 다.
var x = 0;
var y = 0;
var xDirection = 1;
var yDirection = 1;
변수 x, y, xDirection 과 yDirection 은 그림 (캔버스 왼쪽 상단 에 비해) 의 위 치 를 정의 하고 임의의 시간 에 이동 하 는 방향 을 정의 합 니 다.
var image = new Image();
image.src = "http://javascript-tutorials.googlecode.com/files/jsplatformer1-smiley.jpg";
그림 을 캔버스 에 그 리 려 면 먼저 그림 을 불 러 와 야 한다.이 를 위해, src 속성 을 그림 파일 의 URL 로 설정 하 는 Image 대상 을 만 듭 니 다. (그림 을 로 컬 에 다운로드 하 는 것 을 권장 합 니 다. - 번역자 주)
var canvas = null;
var context2D = null;
우 리 는 Canvas 요소 와 그림 컨 텍스트 (잠시 후에 그림 컨 텍스트 를 자세히 소개 합 니 다) 에 대한 인용 도 받 아야 합 니 다.잠시 후 우 리 는 이 두 변수 에 정확 한 값 을 부여 할 것 입 니 다. 지금 은 null 로 설정 합 니 다.
window.onload = init;

마지막 으로 페이지 로 딩 이 완료 되면 캔버스 를 그 리 는 코드 를 즉시 실행 해 야 합 니 다.따라서 window 대상 의 onload 이벤트 가 발생 했 을 때 init 함 수 를 즉시 호출 합 니 다.
init 함수
function init(){
	canvas = document.getElementById('canvas');
	context2D = canvas.getContext('2d');
	setInterval(draw, 1000/FPS);
}

페이지 불 러 오기 가 끝나 면 이 init 함 수 를 호출 합 니 다.이 함수 에서 우 리 는 먼저 HTML 파일 에서 지정 한 ID 속성 을 통 해 캔버스 요 소 를 얻 은 다음 에 이 캔버스 의 2D 그래 픽 컨 텍스트 대상 을 얻 을 수 있 습 니 다.
문맥 대상 은 캔버스 에 그림 을 그 리 는 방법 을 정의 하 는 데 사용 된다.말 그대로 2D 컨 텍스트 는 캔버스 에 2D 그래 픽, 이미지, 텍스트 를 그 리 는 것 을 지원 합 니 다.캔버스 요 소 를 지원 하 는 브 라 우 저 는 2D 컨 텍스트 를 지원 합 니 다. 2D 컨 텍스트 를 제외 하고 다른 시험 적 인 컨 텍스트 대상 도 있 습 니 다.Opera 는 게임 을 위 한 2D 컨 텍스트 가 있 고 Mozilla 는 3D 장면 을 표시 할 수 있 는 컨 텍스트 가 있 습 니 다.안 타 깝 게 도 현재 이 컨 텍스트 대상 들 은 특정 브 라 우 저 만 지원 합 니 다.캔버스 로 웹 애플 리 케 이 션 을 만 들 려 면 흔히 볼 수 있 는 2D 컨 텍스트 만 사용 하 는 것 이 좋 습 니 다.
이동 할 수 있 는 그림 을 그 리 려 면 렌 더 링 순환 (render loop) 을 만들어 야 합 니 다.렌 더 링 순환 이란 실제 적 으로 중복 호출 된 함수 입 니 다. 렌 더 링 순환 의 매번 교체 입 니 다. (이 예 에서) 그림 이 화면 에 약간의 위 치 를 이동 하 게 할 수 있 습 니 다. 이렇게 반복 하면 그림 이 이동 하 는 느낌 을 줄 수 있 습 니 다.이 를 위해 setInterval 함 수 를 호출 했 습 니 다. 첫 번 째 매개 변 수 는 중복 호출 되 어야 할 함수 입 니 다. 여기 함수 이름 은 draw 입 니 다.setInterval 함수 의 두 번 째 매개 변 수 는 호출 함수 의 빈 도 를 지정 합 니 다.이 매개 변수 값 의 단 위 는 밀리초 이 며, 1000 을 이전에 정 의 된 FPS 로 나 누 면 호출 할 때마다 간격 이 있 는 밀리초 수 를 얻 을 수 있 습 니 다.
1 초 에 30 번 씩 draw 함 수 를 호출 할 것 을 지정 하지만 실제로는 30 번 을 호출 하지 않 습 니 다.draw 함 수 를 얼마나 자주 호출 하 느 냐 는 바 텀 JavaScript 엔진 의 속도 와 실행 할 draw 함수 코드 의 복잡 정도 에 달 려 있 습 니 다.시스템 이 느 리 면 1 초 에 한 번 씩 draw 함수 만 호출 할 수 있 습 니 다.그래서 여기 서 setInterval 에 지 정 된 빈 도 는 가장 이상 적 인 상황 일 뿐이다.
draw 함수
캔버스 에 그림 을 그 리 는 작업 은 사실상 draw 함수 로 이 루어 진다.다음은 그 중의 그림 그리 기 동작 을 한 걸음 한 걸음 설명 하 겠 습 니 다.
context2D.clearRect(0, 0, canvas.width, canvas.height);
모든 그림 그리 기 작업 은 문맥 대상 에서 발생 하 는 것 이지 캔버스 요소 에서 발생 하 는 것 이 아니다.모든 화면 을 그리 기 위해 깨끗 한 지면 을 준비 할 수 있 도록 컨 텍스트 를 먼저 비 웁 니 다.
context2D.drawImage(image, x, y);
, , x y 。
x += 1 * xDirection;
y += 1 * yDirection;
, xDirection yDirection 1( ) -1( ), x y 。
if (x >= 450){
	x = 450;
	xDirection = -1;
} else if (x <= 0) {
	x = 0;
	xDirection = 1;
}
if (y >= 250) {
	y = 250;
	yDirection = -1;
} else if (y <= 0) {
	y = 0;
	yDirection = 1;
}

, 。 150×150 , 600×400 , 450(600 – 150) 250(400 – 150) 。

。 , : DIV 。 。 。 , , 。

3、 Canvas

http://www.brighthub.com/internet/web-development/articles/39509.aspx

JavaScript Canvas , Canvas 。

Canvas 。 , IMG DIV HTML , 。 , 。

, HTML 。

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
 <html lang="en">
    <head>
       <title>JavaScript Platformer 2</title>
       <script type="text/javascript" src="jsplatformer2.js"></script>
       <style type="text/css">
          body { font-family: Arial,Helvetica,sans-serif;}
       </style>
    </head>
   <body>
      <p>
         <a href="http://www.brighthub.com/internet/web-development/articles/38364.aspx">
            Game Development with Javascript and the canvas element
         </a>
      </p>
      <canvas id="canvas" width="600" height="400">
         <p>Your browser does not support the canvas element.</p>
      </canvas>
      <br />
      <button onclick="currentFunction=alpha;">Change Alpha</button>
      <button onclick="currentFunction=shear;">Shear</button>
      <button onclick="currentFunction=scale;">Scale</button>
      <button onclick="currentFunction=rotate;">Rotate</button>
   </body>
</html>
HTML , 。 , currentFunction ( ) , 。

jsplatformer2.js 。
//      
const FPS = 30;
const SECONDSBETWEENFRAMES = 1 / FPS;
const HALFIMAGEDIMENSION = 75;
const HALFCANVASWIDTH = 300;
const HALFCANVASHEIGHT = 200;
var image = new Image();
image.src = "jsplatformer2-smiley.jpg"; //           
var canvas = null;
var context2D = null;
var currentFunction = null;
var currentTime = 0;
var sineWave = 0;

window.onload = init;

function init()
{
   canvas = document.getElementById('canvas');
   context2D = canvas.getContext('2d');
   setInterval(draw, SECONDSBETWEENFRAMES * 1000);
   currentFunction = scale;
}

function draw()
{
    currentTime += SECONDSBETWEENFRAMES;
    sineWave = (Math.sin(currentTime) + 1) / 2;

    context2D.clearRect(0, 0, canvas.width, canvas.height);

    context2D.save();

    context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);

    currentFunction();

    context2D.drawImage(image, 0, 0);

    context2D.restore();
}

function alpha()
{
    context2D.globalAlpha = sineWave;
}

function shear()
{
    context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
}

function scale()
{
    context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
    context2D.scale(sineWave, sineWave);
}

function rotate()
{
    context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
    context2D.rotate(sineWave * Math.PI * 2);
    context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
}

, JavaScript 。

  • FPS:
  • SECONDSBETWEENFRAMES: (FPS )
  • HALFIMAGEDIMENSION: / ,
  • HALFCANVASWIDTH: , HALFIMAGEDIMENSION ,
  • HALFCANVASHEIGHT: , HALFIMAGEDIMENSION ,
  • currentFunction: ( )
  • currentTime:
  • sineWave:0 1 ,
  • image:
  • canvas:
  • context2D: 2D

, , window onload init ( init , )。

draw

draw :

function draw()
{
    currentTime += SECONDSBETWEENFRAMES;
    sineWave = (Math.sin(currentTime) + 1) / 2;

    context2D.clearRect(0, 0, canvas.width, canvas.height);

    context2D.save();
    context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
    currentFunction();
    context2D.drawImage(image, 0, 0);
    context2D.restore();
}

4 : alpha ( ), 、 。 , 。 sineWave 。

-1 1 。 , currentTime , 。 ( -1 1) 1 2, 0 1 。

currentTime += SECONDSBETWEENFRAMES;
sineWave = (Math.sin(currentTime) + 1) / 2;
, clearRect , 。
context2D.clearRect(0, 0, canvas.width, canvas.height);

, “ ” 。 , , 、 。 , , ( )。

,save restore , , “ ” 。 ?save , restore 。 , :

  • save ( )
  • restore , save ,

, 。 , , 。

context2D.save();
, 。 , translate , 。
context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
, currentFunction 。 , alpha( ) 、 。 。
currentFunction();
, 。 , drawImage 。
context2D.drawImage(image, 0, 0);
, restore , save 。
context2D.restore();

alpha

function alpha()
{
    context2D.globalAlpha = sineWave;
}

globalAlpha , 。 globalAlpha 0, , 1, 。 , globalAlpha , 。

shear

function shear()
{
    context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
}

transform 。 , , , 2D (http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics), transform 。 , 。

scale

function scale()
{
    context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
   context2D.scale(sineWave, sineWave);
}

,scale( ) 。 , transalte 。 。 , 。 translate , 。

rotate

function rotate()
{
    context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
    context2D.rotate(sineWave * Math.PI * 2);
    context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
}

scale ,rotate( ) : 。 scale , translate 。 translate , 。

4 , HTML 。 , scale rotate , transform ( )。

Demo 。http://webdemos.sourceforge.net/jsplatformer2/jsplatformer2.html

4、 ( )

http://www.brighthub.com/internet/web-development/articles/40512.aspx
, , , 。 , / 。

, Demo。 , Demo , ( ) , , 。

JavaScript 。 JavaScript , 。 JavaScript , Mozilla Developer Network https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript 。 。

, : 2D ( 、 、 ) 。 , 。 , 。

Main.js

, Main.js 。

/**      
    @type Number
*/
var FPS = 30;
/**         
    @type Number
*/
var SECONDS_BETWEEN_FRAMES = 1 / FPS;
/** GameObjectManager        
    @type GameObjectManager
*/
var g_GameObjectManager = null;
/**         
    @type Image
*/
var g_image = new Image();
g_image.src = "jsplatformer3-smiley.jpg";

//          init  
window.onload = init;

/**
         
*/
function init()
{
    new GameObjectManager().startupGameObjectManager();
}

。 , , init 。 init , GameObjectManager 。

GameObjectManager startupGameObjectManager 。 startupClassName 。 , 。

,JavaScript ( )。 , 。 ( startupClassName1、startupClassName2), 。

( ) 。 C++、Java C# , , 。 C# :

class Test
{
	public void Test() {this.a = 5;}
	public int a;
}
, 。 JavaScript :
function Test()
{
	this.a = 5;
	var a;
}

, a 5 。 var a; , a 。 , 。 startupClassName , ( ) , , 。

GameObjectManager.js

/**
                 
    @class
*/
function GameObjectManager()
{
    /**           
        @type Arary
    */
    this.gameObjects = new Array();
    /**           
        @type Date
    */
    this.lastFrame = new Date().getTime();
    /** x       
        @type Number
    */
    this.xScroll = 0;
    /** y       
        @type Number
    */
    this.yScroll = 0;
    /**  ApplicationManager     
        @type ApplicationManager
    */
    this.applicationManager = null;
    /**         
        @type HTMLCanvasElement
    */
    this.canvas = null;
    /**      2D      
        @type CanvasRenderingContext2D
    */
    this.context2D = null;
    /**                  
        @type HTMLCanvasElement
    */
    this.backBuffer = null;
    /**         2D      
        @type CanvasRenderingContext2D
    */
    this.backBufferContext2D = null;

    /**
               
        @return A reference to the initialised object
    */
    this.startupGameObjectManager = function()
    {
        //     this       
        g_GameObjectManager = this;

        //         2D      
        this.canvas = document.getElementById('canvas');
        this.context2D = this.canvas.getContext('2d');
        this.backBuffer = document.createElement('canvas');
        this.backBuffer.width = this.canvas.width;
        this.backBuffer.height = this.canvas.height;
        this.backBufferContext2D = this.backBuffer.getContext('2d');

        //       ApplicationManager
        this.applicationManager = new ApplicationManager().startupApplicationManager();

        //   setInterval   draw  
        setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);

        return this;
    }

    /**
            
    */
    this.draw = function ()
    {
        //             
        var thisFrame = new Date().getTime();
        var dt = (thisFrame - this.lastFrame)/1000;
        this.lastFrame = thisFrame;

        //        
        this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
        this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);

        //           
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].update)
            {
                this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        //           
        for (x in this.gameObjects)
        {
            if (this.gameObjects[x].draw)
            {
                this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
            }
        }

        //                
        this.context2D.drawImage(this.backBuffer, 0, 0);
    };

    /**
         gameObjects       GameObject
        @param gameObject The object to add
    */
    this.addGameObject = function(gameObject)
    {
        this.gameObjects.push(gameObject);
        this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})
    };

    /**
         gameObjects       GameObject
        @param gameObject The object to remove
    */
    this.removeGameObject = function(gameObject)
    {
        this.gameObjects.removeObject(gameObject);
    }
}

GameObjectManager 。GameObjectManager , , GameObject ( ) 。

GameObjectManager startupGameObjectManager :

/**
           
    @return A reference to the initialised object
*/
this.startupGameObjectManager = function()
{
    //     this       
    g_GameObjectManager = this;

    //         2D      
    this.canvas = document.getElementById('canvas');
    this.context2D = this.canvas.getContext('2d');
    this.backBuffer = document.createElement('canvas');
    this.backBuffer.width = this.canvas.width;
    this.backBuffer.height = this.canvas.height;
    this.backBufferContext2D = this.backBuffer.getContext('2d');

    //       ApplicationManager
    this.applicationManager = new ApplicationManager().startupApplicationManager();

    //   setInterval   draw  
    setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);

    return this;
}

, startupClassName 。 ,GameObjectManager startupGameObjectManager 。

GameObjectManager g_GameObjectManager , 。

//     this       
g_GameObjectManager = this;

//         2D      
this.canvas = document.getElementById('canvas');
this.context2D = this.canvas.getContext('2d');

, 。 。 , : , ( ) , ( )。

(http://www.brighthub.com/internet/web-development/articles/11012.aspx) 。 , , 。

, 。 JavaScript ( 、 ), 。

, ( ) , 。

HTML , 。 , document.createElement , 。

this.backBuffer = document.createElement('canvas');
this.backBuffer.width = this.canvas.width;
this.backBuffer.height = this.canvas.height;
this.backBufferContext2D = this.backBuffer.getContext('2d');
, ApplicationManager , startupApplicationManager 。 ApplicationManager 。
//       ApplicationManager
this.applicationManager = new ApplicationManager().startupApplicationManager();
, setInterval draw , 。
//   setInterval   draw  
setInterval(function(){g_GameObjectManager.draw();}, SECONDS_BETWEEN_FRAMES);
draw 。
/**
        
*/
this.draw = function ()
{
    //             
    var thisFrame = new Date().getTime();
    var dt = (thisFrame - this.lastFrame)/1000;
    this.lastFrame = thisFrame;

    //        
    this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
    this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);

    //           
    for (x in this.gameObjects)
    {
        if (this.gameObjects[x].update)
        {
            this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
        }
    }

    //           
    for (x in this.gameObjects)
    {
        if (this.gameObjects[x].draw)
        {
            this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
        }
    }

    //                
    this.context2D.drawImage(this.backBuffer, 0, 0);
};

draw 。 , ( )。 , 。 , , draw , , 。

, 。 30 draw , 。 , 。

//             
var thisFrame = new Date().getTime();
var dt = (thisFrame - this.lastFrame)/1000;
this.lastFrame = thisFrame;

//        
this.backBufferContext2D.clearRect(0, 0, this.backBuffer.width, this.backBuffer.height);
this.context2D.clearRect(0, 0, this.canvas.width, this.canvas.height);
, ( GameObject , ) (update) (draw) 。 , ( ), 。
//           
for (x in this.gameObjects)
{
    if (this.gameObjects[x].update)
    {
        this.gameObjects[x].update(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
    }
}

//           
for (x in this.gameObjects)
{
    if (this.gameObjects[x].draw)
    {
        this.gameObjects[x].draw(dt, this.backBufferContext2D, this.xScroll, this.yScroll);
    }
}
, , 。
//                
this.context2D.drawImage(this.backBuffer, 0, 0);
draw , addGameObject removeGameObject 。
/**
     gameObjects       GameObject
    @param gameObject The object to add
*/
this.addGameObject = function(gameObject)
{
    this.gameObjects.push(gameObject);
    this.gameObjects.sort(function(a,b){return a.zOrder - b.zOrder;})
};

/**
     gameObjects       GameObject
    @param gameObject The object to remove
*/
this.removeGameObject = function(gameObject)
{
    this.gameObjects.removeObject(gameObject);
}

addGameObject removeGameObject( Utils.js Array.prototype ) , GameObjectManager GameObject ( gameObjects ) 。

GameObjectManager 。 , :GameObject、VisualGameObject、Bounce ApplicationManager。

, , Demo 。

4、 ( )

, JavaScript 。

GameObjectManager , GameObject 。 GameObject 。

GameObject.js

/**
                 
    @class
*/
function GameObject()
{
    /**        。   zOrder      ,       。
        @type Number
    */
    this.zOrder = 0;
    /**
        x    
        @type Number
    */
    this.x = 0;
    /**
        y    
        @type Number
    */
    this.y = 0;

    /**
               ,      GameObjectManager        
        @param x        x    
        @param y        y    
        @param z           z  (     z   )
    */
    this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.zOrder = z;
        this.x = x;
        this.y = y;
        g_GameObjectManager.addGameObject(this);
        return this;
    }

    /**
              ,   GameObjectManager          
    */
    this.shutdownGameObject = function()
    {
        g_GameObjectManager.removeGameObject(this);
    }
}

GameObject ( ) , , (x y) (z)。 , GameObject , 。

x y —— 。 GameObject z , 。 , GameObject 。 ,z GameObject z GameObject 。

, startupClassName 。 ,GameObject startupGameObject 。 , , addGameObject GameObject GameObjectManager GameObject 。

/**
           ,      GameObjectManager        
    @param x        x    
    @param y        y    
    @param z           z  (     z   )
*/
this.startupGameObject = function(/**Number*/ x, /**Number*/ y, /**Number*/ z)
{
    this.zOrder = z;
    this.x = x;
    this.y = y;
    g_GameObjectManager.addGameObject(this);
    return this;
}
shutdownGameObject GameObject。 , GameObject removeGameObject GameObjectManager 。
/**
          ,   GameObjectManager          
*/
this.shutdownGameObject = function()
{
    g_GameObjectManager.removeGameObject(this);
}

VisualGameObject.js

/**
                  
    @class
*/
function VisualGameObject()
{
    /**
                  
        @type Image
    */
    this.image = null;

    /**
                    
        @param dt             
    */
    this.draw = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
        context.drawImage(this.image, this.x - xScroll, this.y - yScroll);
    }

    /**
               
        @param image       
    */
    this.startupVisualGameObject = function(/**Image*/ image, /**Number*/ x, /**Number*/ y, /**Number*/ z)
    {
        this.startupGameObject(x, y, z);
        this.image = image;
        return this;
    }

    /**
              
    */
    this.shutdownVisualGameObject = function()
    {
        this.shutdownGameObject();
    }
}
VisualGameObject.prototype = new GameObject;
VisualGameObject , GameObject , 。 , , VisualGameObject image , , 。
/**
              
    @type Image
*/
this.image = null;
, , —— draw , GameObject x y 。
/**
                
    @param dt             
*/
this.draw = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
{
    context.drawImage(this.image, this.x - xScroll, this.y - yScroll);
}

ApplicationManager.js

/**
    ApplicationManager      
    @class
*/
function ApplicationManager()
{
    /**
             
        @return          
    */
    this.startupApplicationManager = function()
    {
        this.bounce = new Bounce().startupBounce(g_image);
        return this;
    }
}

ApplicationManager , , , 。 , Bounce 。 , 。 , 。

Bounce.js

/**
       ,    VisualGameObject    
    @class
*/
function Bounce()
{
	/** x      
        @type Number
    */
	this.xDirection = 1;
	/** y      
        @type Number
    */
	this.yDirection = 1;
	/**     
        @type Number
    */
	this.speed = 10;

	/**
             
        @return          
    */
	this.startupBounce = function(image)
	{
		this.startupVisualGameObject(image, 0, 0, 0);
		return this;
	}

	/**
           
        @param dt             
        @param context      
        @param xScroll x       
        @param yScroll y       
    */
	this.update = function (/**Number*/ dt, /**CanvasRenderingContext2D*/context, /**Number*/ xScroll, /**Number*/ yScroll)
	{
		this.x += dt * this.speed * this.xDirection;
		this.y += dt * this.speed * this.yDirection;

		if (this.x >= 450)
		{
			this.x = 450;
			this.xDirection = -1;
		}
		else if (this.x <= 0)
		{
			this.x = 0;
			this.xDirection = 1;
		}

		if (this.y >= 250)
		{
			this.y = 250;
			this.yDirection = -1;
		}
		else if (this.y <= 0)
		{
			this.y = 0;
			this.yDirection = 1;
		}
	}
}
Bounce.prototype = new VisualGameObject;

Bounce , VisualGameObject , 。Bounce , 。 。

startupBounce , startupVisualGameObject 。

/**
            
       @return          
   */
this.startupBounce = function(image)
{
	this.startupVisualGameObject(image, 0, 0, 0);
	return this;
}
update ( GameObjectManager ) , 。
	/**
           
        @param dt             
        @param context      
        @param xScroll x       
        @param yScroll y       
    */
	this.update = function (/**Number*/ dt, /**CanvasRenderingContext2D*/context, /**Number*/ xScroll, /**Number*/ yScroll)
	{
		this.x += dt * this.speed * this.xDirection;
		this.y += dt * this.speed * this.yDirection;

		if (this.x >= 450)
		{
			this.x = 450;
			this.xDirection = -1;
		}
		else if (this.x <= 0)
		{
			this.x = 0;
			this.xDirection = 1;
		}

		if (this.y >= 250)
		{
			this.y = 250;
			this.yDirection = -1;
		}
		else if (this.y <= 0)
		{
			this.y = 0;
			this.yDirection = 1;
		}
	}
}

。 , ? VisualGameObject draw 。 , VisualGameObject GameObject , update draw 。Bounce , x y。

, , 。 , 。

Demo 。http://webdemos.sourceforge.net/jsplatformer3/jsplatformer3.html

Canvas

http://www.brighthub.com/internet/web-development/articles/40511.aspx

2D 。 。

, 。

, , 。 2D 。

RepeatingGameObject.js

/**
                 ,       x  y   
    @class
*/
function RepeatingGameObject()
{
    /**          
 	@type Number
    */
    this.width = 0;
    /**          
    	@type Number
    */
    this.height = 0;
    /**        scrollX scrollY
	@type Number
    */
    this.scrollFactor = 1;

    /**
             
        @return          
    */
    this.startupRepeatingGameObject = function(image, x, y, z, width, height, scrollFactor)
    {
        this.startupVisualGameObject(image, x, y, z);
        this.width = width;
        this.height = height;
        this.scrollFactor = scrollFactor;
        return this;
    }

    /**
            
    */
    this.shutdownstartupRepeatingGameObject = function()
    {
        this.shutdownVisualGameObject();
    }

	/**
                    
        @param dt             
		@param context      
		@param xScroll x       
		@param yScroll y       

    */
    this.draw = function(dt, canvas, xScroll, yScroll)
    {
        var areaDrawn = [0, 0];

        for (var y = 0; y < this.height; y += areaDrawn[1])
        {
            for (var x = 0; x < this.width; x += areaDrawn[0])
            {
                //             
		var newPosition = [this.x + x, this.y + y];
		//        
                var newFillArea = [this.width - x, this.height - y];
		//                
		//             
                var newScrollPosition = [0, 0];
                if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
                if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
                areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
            }
        }
    }

    this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
    {
        //              (   )
        var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
        var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
        var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
        var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
        var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
        var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

        //     
        canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

        return [width, height];
    }
}
RepeatingGameObject.prototype = new VisualGameObject();

RepeatingGameObject 。 , 。 RepeatingGameObject , ( )。 ( ) , 。

GameObjectManager xScroll yScroll , GameObject draw updata 。 x y 。RepeatingGameObject , 。

, RepeatingGameObject 。 GameObject x y , width height 。

   /**          
	@type Number
   */
   this.width = 0;
   /**          
   	@type Number
   */
   this.height = 0;
   /**        scrollX scrollY
@type Number
   */
scrollFactor RepeatingGameObject , draw xScroll yScroll 。 scrollFactor 1 , , 。
   /**        scrollX scrollY
@type Number
   */
   this.scrollFactor = 1;
draw drawRepeat 。
/**
                   
       @param dt             
	@param context      
	@param xScroll x       
	@param yScroll y       

   */
   this.draw = function(dt, canvas, xScroll, yScroll)
   {
       var areaDrawn = [0, 0];

       for (var y = 0; y < this.height; y += areaDrawn[1])
       {
           for (var x = 0; x < this.width; x += areaDrawn[0])
           {
               //             
	var newPosition = [this.x + x, this.y + y];
	//        
               var newFillArea = [this.width - x, this.height - y];
	//                
	//             
               var newScrollPosition = [0, 0];
               if (x==0) newScrollPosition[0] = xScroll * this.scrollFactor;
               if (y==0) newScrollPosition[1] = yScroll * this.scrollFactor;
               areaDrawn = this.drawRepeat(canvas, newPosition, newFillArea, newScrollPosition);
           }
       }
   }

   this.drawRepeat = function(canvas, newPosition, newFillArea, newScrollPosition)
   {
       //              (   )
       var xOffset = Math.abs(newScrollPosition[0]) % this.image.width;
       var yOffset = Math.abs(newScrollPosition[1]) % this.image.height;
       var left = newScrollPosition[0]<0?this.image.width-xOffset:xOffset;
       var top = newScrollPosition[1]<0?this.image.height-yOffset:yOffset;
       var width = newFillArea[0] < this.image.width-left?newFillArea[0]:this.image.width-left;
       var height = newFillArea[1] < this.image.height-top?newFillArea[1]:this.image.height-top;

       //     
       canvas.drawImage(this.image, left, top, width, height, newPosition[0], newPosition[1], width, height);

       return [width, height];
   }   

ApplicationManager.js

/**
    ApplicationManager      
    @class
*/
function ApplicationManager()
{
    /**
             
        @return A          
    */
    this.startupApplicationManager = function()
    {
        this.startupGameObject();
	this.background3 = new RepeatingGameObject().startupRepeatingGameObject(g_back2, 0, 100, 3, 600, 320, 1);
        this.background2 = new RepeatingGameObject().startupRepeatingGameObject(g_back1, 0, 100, 2, 600, 320, 0.75);
        this.background = new RepeatingGameObject().startupRepeatingGameObject(g_back0, 0, 0, 1, 600, 320, 0.5);
        return this;
    }

	/**
              
        @param dt             
        @param context      
        @param xScroll x       
        @param yScroll y       
    */
    this.update = function(/**Number*/ dt, /**CanvasRenderingContext2D*/ context, /**Number*/ xScroll, /**Number*/ yScroll)
    {
		g_GameObjectManager.xScroll += 50 * dt;
	}
}
ApplicationManager.prototype = new GameObject

, ApplicationManager RepeatingGameObject , , z( ) scrollFactor RepeatingGameObject 。

。 , 。

Demo 。http://webdemos.sourceforge.net/jsplatformer4/jsplatformer4.html


좋은 웹페이지 즐겨찾기