자 바스 크 립 트 와 Canvas 를 이용 한 게임 개발
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
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
기초 정리 - 1문자 (String) 숫자 (Number) 불린 (Boolean) null undefined 심볼 (Symbol) 큰정수 (BigInt) 따옴표로 묶어 있어야 함 Not-A-Number - 숫자 데이터 / 숫자로 표...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.