내가 지금 이 두 com/downloads/global/corporate/iar/esg_prosupport. 후 질문:
단, 이 유형의 선발경기가 can& 작동됨 (https://stackoverflow.com/questions/11464550/html5-creating-a-viewport-for-canvas), t # 39 의 코드가 내거냐 재현한다.
(https://stackoverflow.com/questions/8592872/changing-the-view-center-of-an-html5-canvas) 등도 있지만, 단지 퍼포먼트 보다 밝은 것으로 이해해야 제대로 객체에는 드로잉하기 위해 다른 모든 것은 상대적인 기준으로 실행자이자 스크롤하지 어떻게 이 캔바스를 뷰포트가 플레이어가 우선 i want to developer. 물론이겠지.
내 코드 (단순화됨 - 게임 논리가 별도로):
var canvas = document.getElementById("game");
canvas.tabIndex = 0;
canvas.focus();
var cc = canvas.getContext("2d");
// Define viewports for scrolling inside the canvas
/* Viewport x position */ view_xview = 0;
/* Viewport y position */ view_yview = 0;
/* Viewport width */ view_wview = 960;
/* Viewport height */ view_hview = 560;
/* Sector width */ room_width = 5000;
/* Sector height */ room_height = 3000;
canvas.width = view_wview;
canvas.height = view_hview;
function draw()
{
clear();
requestAnimFrame(draw);
// World's end and viewport
if (player.x < 20) player.x = 20;
if (player.y < 20) player.y = 20;
if (player.x > room_width-20) player.x = room_width-20;
if (player.y > room_height-20) player.y = room_height-20;
if (player.x > view_wview/2) ... ?
if (player.y > view_hview/2) ... ?
}
The way i am 이해했소 apc® 하는 느낌이 완전히 잘못된 줄 아는 것, 나는 이 don& 쉐퍼드도 # 39 못할 정도였습니다. 아무 생각 없어? Context.transform-thing 어떻게 생각하는지?
누군가 내 바란다 "고 설명, 그리고 그 이해하겠니 제기됐다. 감사합니다.
8 개의 새로운 방법을) 의 변형 트로이마지 매개변수입니다. 우리는 이 방법을 사용할 수 있는 부분을 슬라이스에 그릴 수 있는 소스 이미지와 캔바스를. >. 트로이마지 (이미지, sx, sy,,, dx dy · 드와이트하 스위데스 셰이트 다이트) 첫 번째 매개변수입니다 이미지, 마찬가지로 다른 변형, 또는 객체 또는 참조입니다 참조입니다 이미지에 다른 캔바스를 요소. 다른 8 개의 매개변수입니다 it& # 39 의 아래 이미지를 보는 것이 좋습니다. 처음 네 개의 매개변수입니다 위치와 크기를 슬라이스에 정의하십시오 소스에 이미지. 마지막 4 매개변수입니다 위치와 크기를 정의하십시오 대상에 캔바스를. ! 캔바스를 트로이마지 글꼴: < https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images>;
var sx, sy, dx, dy;
var sWidth, sHeight, dWidth, dHeight;
// offset point to crop the image
sx = xView;
sy = yView;
// dimensions of cropped image
sWidth = context.canvas.width;
sHeight = context.canvas.height;
// if cropped image is smaller than canvas we need to change the source dimensions
if(image.width - sx < sWidth){
sWidth = image.width - sx;
}
if(image.height - sy < sHeight){
sHeight = image.height - sy;
}
// location on canvas to draw the croped image
dx = 0;
dy = 0;
// match destination with source to not scale the image
dWidth = sWidth;
dHeight = sHeight;
// draw the cropped image
context.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
이 게임은 게임 등을 고려할 때 world& # 39 의 객체는 업데이트되도록 포지셔닝하십시오 것을 알 수 있습니다. 즉, (x, y) 의 위치를 객체인지 포지셔닝하십시오 세계. 이후 불구하고 제대로 하는 것이 뷰포트에 변화하고 객체에는 렌더링됩니다 포지셔닝하십시오 world& # 39 의 포지셔닝하십시오 및 렌더링합니다 것과는 다를 것입니다. 변환 간단합니다. 포지셔닝해야 객체에는 세계 (룸): (x, y) ',' < br>. 뷰포트가 위치: ' (스비에프, 이비에프)'
>. 카메라스폴로 (player, canvas.width/2, canvas.height/2)
See the full 코드와 구하겠죠 해봐. 대부분의 지역이 주석이 있는 코드를 안내하는. # 39, ll solaris. 알고 i& Javascript 와 기본적인 사용하는 방법을 프로토타입 (저도 가끔 라는 용어를 사용할 " class"; kingdome. seattle. 프로토타입 객체는 클래스의 그냥 가지고 있기 때문에 비슷한 비헤이비어를 같은 언어로 자바). [ 라이브입니다 데모 ] (
) 전체 코드:<!DOCTYPE HTML>
<html>
<body>
<canvas id="gameCanvas" width=400 height=400 />
<script>
// wrapper for our game "classes", "methods" and "objects"
window.Game = {};
// wrapper for "class" Rectangle
(function() {
function Rectangle(left, top, width, height) {
this.left = left || 0;
this.top = top || 0;
this.width = width || 0;
this.height = height || 0;
this.right = this.left + this.width;
this.bottom = this.top + this.height;
}
Rectangle.prototype.set = function(left, top, /*optional*/ width, /*optional*/ height) {
this.left = left;
this.top = top;
this.width = width || this.width;
this.height = height || this.height
this.right = (this.left + this.width);
this.bottom = (this.top + this.height);
}
Rectangle.prototype.within = function(r) {
return (r.left <= this.left &&
r.right >= this.right &&
r.top <= this.top &&
r.bottom >= this.bottom);
}
Rectangle.prototype.overlaps = function(r) {
return (this.left < r.right &&
r.left < this.right &&
this.top < r.bottom &&
r.top < this.bottom);
}
// add "class" Rectangle to our Game object
Game.Rectangle = Rectangle;
})();
// wrapper for "class" Camera (avoid global objects)
(function() {
// possibles axis to move the camera
var AXIS = {
NONE: 1,
HORIZONTAL: 2,
VERTICAL: 3,
BOTH: 4
};
// Camera constructor
function Camera(xView, yView, viewportWidth, viewportHeight, worldWidth, worldHeight) {
// position of camera (left-top coordinate)
this.xView = xView || 0;
this.yView = yView || 0;
// distance from followed object to border before camera starts move
this.xDeadZone = 0; // min distance to horizontal borders
this.yDeadZone = 0; // min distance to vertical borders
// viewport dimensions
this.wView = viewportWidth;
this.hView = viewportHeight;
// allow camera to move in vertical and horizontal axis
this.axis = AXIS.BOTH;
// object that should be followed
this.followed = null;
// rectangle that represents the viewport
this.viewportRect = new Game.Rectangle(this.xView, this.yView, this.wView, this.hView);
// rectangle that represents the world's boundary (room's boundary)
this.worldRect = new Game.Rectangle(0, 0, worldWidth, worldHeight);
}
// gameObject needs to have "x" and "y" properties (as world(or room) position)
Camera.prototype.follow = function(gameObject, xDeadZone, yDeadZone) {
this.followed = gameObject;
this.xDeadZone = xDeadZone;
this.yDeadZone = yDeadZone;
}
Camera.prototype.update = function() {
// keep following the player (or other desired object)
if (this.followed != null) {
if (this.axis == AXIS.HORIZONTAL || this.axis == AXIS.BOTH) {
// moves camera on horizontal axis based on followed object position
if (this.followed.x - this.xView + this.xDeadZone > this.wView)
this.xView = this.followed.x - (this.wView - this.xDeadZone);
else if (this.followed.x - this.xDeadZone < this.xView)
this.xView = this.followed.x - this.xDeadZone;
}
if (this.axis == AXIS.VERTICAL || this.axis == AXIS.BOTH) {
// moves camera on vertical axis based on followed object position
if (this.followed.y - this.yView + this.yDeadZone > this.hView)
this.yView = this.followed.y - (this.hView - this.yDeadZone);
else if (this.followed.y - this.yDeadZone < this.yView)
this.yView = this.followed.y - this.yDeadZone;
}
}
// update viewportRect
this.viewportRect.set(this.xView, this.yView);
// don't let camera leaves the world's boundary
if (!this.viewportRect.within(this.worldRect)) {
if (this.viewportRect.left < this.worldRect.left)
this.xView = this.worldRect.left;
if (this.viewportRect.top < this.worldRect.top)
this.yView = this.worldRect.top;
if (this.viewportRect.right > this.worldRect.right)
this.xView = this.worldRect.right - this.wView;
if (this.viewportRect.bottom > this.worldRect.bottom)
this.yView = this.worldRect.bottom - this.hView;
}
}
// add "class" Camera to our Game object
Game.Camera = Camera;
})();
// wrapper for "class" Player
(function() {
function Player(x, y) {
// (x, y) = center of object
// ATTENTION:
// it represents the player position on the world(room), not the canvas position
this.x = x;
this.y = y;
// move speed in pixels per second
this.speed = 200;
// render properties
this.width = 50;
this.height = 50;
}
Player.prototype.update = function(step, worldWidth, worldHeight) {
// parameter step is the time between frames ( in seconds )
// check controls and move the player accordingly
if (Game.controls.left)
this.x -= this.speed * step;
if (Game.controls.up)
this.y -= this.speed * step;
if (Game.controls.right)
this.x += this.speed * step;
if (Game.controls.down)
this.y += this.speed * step;
// don't let player leaves the world's boundary
if (this.x - this.width / 2 < 0) {
this.x = this.width / 2;
}
if (this.y - this.height / 2 < 0) {
this.y = this.height / 2;
}
if (this.x + this.width / 2 > worldWidth) {
this.x = worldWidth - this.width / 2;
}
if (this.y + this.height / 2 > worldHeight) {
this.y = worldHeight - this.height / 2;
}
}
Player.prototype.draw = function(context, xView, yView) {
// draw a simple rectangle shape as our player model
context.save();
context.fillStyle = "black";
// before draw we need to convert player world's position to canvas position
context.fillRect((this.x - this.width / 2) - xView, (this.y - this.height / 2) - yView, this.width, this.height);
context.restore();
}
// add "class" Player to our Game object
Game.Player = Player;
})();
// wrapper for "class" Map
(function() {
function Map(width, height) {
// map dimensions
this.width = width;
this.height = height;
// map texture
this.image = null;
}
// creates a prodedural generated map (you can use an image instead)
Map.prototype.generate = function() {
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = this.width;
ctx.canvas.height = this.height;
var rows = ~~(this.width / 44) + 1;
var columns = ~~(this.height / 44) + 1;
var color = "red";
ctx.save();
ctx.fillStyle = "red";
for (var x = 0, i = 0; i < rows; x += 44, i++) {
ctx.beginPath();
for (var y = 0, j = 0; j < columns; y += 44, j++) {
ctx.rect(x, y, 40, 40);
}
color = (color == "red" ? "blue" : "red");
ctx.fillStyle = color;
ctx.fill();
ctx.closePath();
}
ctx.restore();
// store the generate map as this image texture
this.image = new Image();
this.image.src = ctx.canvas.toDataURL("image/png");
// clear context
ctx = null;
}
// draw the map adjusted to camera
Map.prototype.draw = function(context, xView, yView) {
// easiest way: draw the entire map changing only the destination coordinate in canvas
// canvas will cull the image by itself (no performance gaps -> in hardware accelerated environments, at least)
/*context.drawImage(this.image, 0, 0, this.image.width, this.image.height, -xView, -yView, this.image.width, this.image.height);*/
// didactic way ( "s" is for "source" and "d" is for "destination" in the variable names):
var sx, sy, dx, dy;
var sWidth, sHeight, dWidth, dHeight;
// offset point to crop the image
sx = xView;
sy = yView;
// dimensions of cropped image
sWidth = context.canvas.width;
sHeight = context.canvas.height;
// if cropped image is smaller than canvas we need to change the source dimensions
if (this.image.width - sx < sWidth) {
sWidth = this.image.width - sx;
}
if (this.image.height - sy < sHeight) {
sHeight = this.image.height - sy;
}
// location on canvas to draw the croped image
dx = 0;
dy = 0;
// match destination with source to not scale the image
dWidth = sWidth;
dHeight = sHeight;
context.drawImage(this.image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
}
// add "class" Map to our Game object
Game.Map = Map;
})();
// Game Script
(function() {
// prepaire our game canvas
var canvas = document.getElementById("gameCanvas");
var context = canvas.getContext("2d");
// game settings:
var FPS = 30;
var INTERVAL = 1000 / FPS; // milliseconds
var STEP = INTERVAL / 1000 // seconds
// setup an object that represents the room
var room = {
width: 500,
height: 300,
map: new Game.Map(500, 300)
};
// generate a large image texture for the room
room.map.generate();
// setup player
var player = new Game.Player(50, 50);
// Old camera setup. It not works with maps smaller than canvas. Keeping the code deactivated here as reference.
/* var camera = new Game.Camera(0, 0, canvas.width, canvas.height, room.width, room.height);*/
/* camera.follow(player, canvas.width / 2, canvas.height / 2); */
// Set the right viewport size for the camera
var vWidth = Math.min(room.width, canvas.width);
var vHeight = Math.min(room.height, canvas.height);
// Setup the camera
var camera = new Game.Camera(0, 0, vWidth, vHeight, room.width, room.height);
camera.follow(player, vWidth / 2, vHeight / 2);
// Game update function
var update = function() {
player.update(STEP, room.width, room.height);
camera.update();
}
// Game draw function
var draw = function() {
// clear the entire canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// redraw all objects
room.map.draw(context, camera.xView, camera.yView);
player.draw(context, camera.xView, camera.yView);
}
// Game Loop
var gameLoop = function() {
update();
draw();
}
// <-- configure play/pause capabilities:
// Using setInterval instead of requestAnimationFrame for better cross browser support,
// but it's easy to change to a requestAnimationFrame polyfill.
var runningId = -1;
Game.play = function() {
if (runningId == -1) {
runningId = setInterval(function() {
gameLoop();
}, INTERVAL);
console.log("play");
}
}
Game.togglePause = function() {
if (runningId == -1) {
Game.play();
} else {
clearInterval(runningId);
runningId = -1;
console.log("paused");
}
}
// -->
})();
// <-- configure Game controls:
Game.controls = {
left: false,
up: false,
right: false,
down: false,
};
window.addEventListener("keydown", function(e) {
switch (e.keyCode) {
case 37: // left arrow
Game.controls.left = true;
break;
case 38: // up arrow
Game.controls.up = true;
break;
case 39: // right arrow
Game.controls.right = true;
break;
case 40: // down arrow
Game.controls.down = true;
break;
}
}, false);
window.addEventListener("keyup", function(e) {
switch (e.keyCode) {
case 37: // left arrow
Game.controls.left = false;
break;
case 38: // up arrow
Game.controls.up = false;
break;
case 39: // right arrow
Game.controls.right = false;
break;
case 40: // down arrow
Game.controls.down = false;
break;
case 80: // key P pauses the game
Game.togglePause();
break;
}
}, false);
// -->
// start the game when page is loaded
window.onload = function() {
Game.play();
}
</script>
</body>
</html>
< br>;
// Set the right viewport size for the camera
var vWidth = Math.min(room.width, canvas.width);
var vHeight = Math.min(room.height, canvas.height);
var camera = new Game.Camera(0, 0, vWidth, vHeight, room.width, room.height);
camera.follow(player, vWidth / 2, vHeight / 2);
이 코드의 수락됨 답이 좀 많은 편이다. 이 단순한 있다.
function draw() {
ctx.setTransform(1,0,0,1,0,0);//reset the transform matrix as it is cumulative
ctx.clearRect(0, 0, canvas.width, canvas.height);//clear the viewport AFTER the matrix is reset
//Clamp the camera position to the world bounds while centering the camera around the player
var camX = clamp(-player.x + canvas.width/2, yourWorld.minX, yourWorld.maxX - canvas.width);
var camY = clamp(-player.y + canvas.height/2, yourWorld.minY, yourWorld.maxY - canvas.height);
ctx.translate( camX, camY );
//Draw everything
}
및 종양이라고요 같습니다.
function clamp(value, min, max){
if(value < min) return min;
else if(value > max) return max;
return value;
}
A 는 정말 큰 이미지를 한 부분을 뷰포트가 오려내었거나 사용자에게 표시되는.
이 경우 사용자에게 뷰포트에 표시할지를 대한 캔바스를 () 는 이 캔바스를 뷰포트에).
첫째, 코드 a 움직이십시오 함수은 뷰포트에 팬합니다 주변에 있는 큰 이미지.
이 함수는 마이그레이션합니다 뷰포트에 왼쪽 상단 / 5px 의해 지정된 방향으로.
function move(direction){
switch (direction){
case "left":
left-=5;
break;
case "up":
top-=5;
break;
case "right":
left+=5;
break;
case "down":
top+=5
break;
}
draw(top,left);
}
이러한 움직임은 함수 호출을 함수은 추첨.
Draw () 는 '에서' 기능은 특정 부분을 트로이마지 오려내기로 큰 이미지를.
또한 "오려내었거나 배경" 에 있는 '표시' 트로이마지 사용자에게 캔바스를.
context.clearRect(0,0,game.width,game.height);
context.drawImage(background,cropLeft,cropTop,cropWidth,cropHeight,
0,0,viewWidth,viewHeight);
이 예에서
배경은 전체 배경 이미지 () 는 일반적으로 표시안된 하지만 오히려 소스임을 자르기)
크로플프트 &. 여기서 작물 가기 정의하십시오 배경 이미지에 있는 자를 시작됩니다.
크로포비데스 &. 얼마나 큰 사각형에는 적립율은 오려내었거나 크로페이트 정의하십시오 &solarisdvd 배경 이미지입니다.
0.0) 에서 온 것이라고 말할 서브 이미지 오려내었거나 http://support. 0.0 뷰포트에 캔바스를 대한 배경 그려집니다.
비에프위드스 &. 비에프헤이트 폭과 높이를 뷰포트에 캔바스를 있다.
그래서 숫자를 사용하여 트로이마지 의 예를 들어보겠습니다.
합시다 우리 뷰포트가 (= 우리 디스플레이 캔바스를) 는 150 픽셀이고 및 100mb/s 픽셀입니다 높음입니다.
context.drawImage(background,75,50,150,100,0,0,150,100);
75 &. 말을 자르기 50 x = 75/y = 50 배경 이미지에 있는 위치에 있는 시작됩니다.
이 될 수 있다고 사각형에는 150,100 오려내었거나 150 넓고 100mb/s 높음입니다.
이미지 크기를 사용하여 있다고 이 0.0,150,100 오려내었거나 사각형에는 표시할지를 전체 뷰포트에 캔바스를.
그게 더 메카닉스 그릴 수 있도록 추가 비에프포트지저스트 주요 제어!
다음은 코드 및 해야했다.
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var game=document.getElementById("game");
var gameCtx=game.getContext("2d");
var left=20;
var top=20;
var background=new Image();
background.onload=function(){
canvas.width=background.width/2;
canvas.height=background.height/2;
gameCtx.fillStyle="red";
gameCtx.strokeStyle="blue";
gameCtx.lineWidth=3;
ctx.fillStyle="red";
ctx.strokeStyle="blue";
ctx.lineWidth=3;
move(top,left);
}
background.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/game.jpg";
function move(direction){
switch (direction){
case "left":
left-=5;
break;
case "up":
top-=5;
break;
case "right":
left+=5;
break;
case "down":
top+=5
break;
}
draw(top,left);
}
function draw(top,left){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.drawImage(background,0,0,background.width,background.height,0,0,canvas.width,canvas.height);
gameCtx.clearRect(0,0,game.width,game.height);
gameCtx.drawImage(background,left,top,250,150,0,0,250,150);
gameCtx.beginPath();
gameCtx.arc(125,75,10,0,Math.PI*2,false);
gameCtx.closePath();
gameCtx.fill();
gameCtx.stroke();
ctx.beginPath();
ctx.rect(left/2,top/2,125,75);
ctx.stroke();
ctx.beginPath();
ctx.arc(left/2+125/2,top/2+75/2,5,0,Math.PI*2,false);
ctx.stroke();
ctx.fill();
}
$("#moveLeft").click(function(){move("left");});
$("#moveRight").click(function(){move("right");});
$("#moveUp").click(function(){move("up");});
$("#moveDown").click(function(){move("down");});
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="game" width=250 height=150></canvas><br>
<canvas id="canvas" width=500 height=300></canvas><br>
<button id="moveLeft">Left</button>
<button id="moveRight">Right</button>
<button id="moveUp">Up</button>
<button id="moveDown">Down</button>
</body>
</html>
이 특정 " Viewport", 추상적인 논리를 수 있습니다. 위치를 파악하는 데 필요한 계산을 처리할 수 있는 방법을 " Camera" 됩니다;; 지도상에 필요가 있는지, 그리고 고객의 문자 X, Y 좌표 일치시킵니다 센터급 디지털 카메라.
또한 디지털 카메라 위치를 확인할 수 있는 방법 및 뒤집기 문자를 바탕으로 포지셔닝하십시오 (예: ' (포지션릭스 - (desired_camera_size.width / 2)') 와 그리는 카메라 거기서 on out.
카메라에서 깨달았습니다 포지셔닝하십시오 있을 때, 첫 번째 레이어에는 자신을 걱정하는 드로잉을 통해 캔바스를 방이요 시작할 수 있습니다.
이는 단순한 뷰포트에 target& # 39 의 x, y 좌표 설정 문제에 대한 [tpc. 콜턴 상태] (https://stackoverflow.com/a/24719569/6243352), 각 프레임에서. 하지만 원하는 대로 필요하지 않은 변환해 사용할 수 있습니다. 이 식은 작동했던 가져다줄래요 없었다.
function update() {
// Assign the viewport to follow a target for this frame
viewport.x = -target.x + canvas.width / 2;
viewport.y = -target.y + canvas.height / 2;
// Draw each entity, including the target, relative to the viewport
ctx.fillRect(
entity.x + viewport.x,
entity.y + viewport.y,
entity.size,
entity.size
);
}
선택적입니다 매핑해야 용어에 대한 두 번째 단계:
function update() {
// Assign the viewport to follow a target for this frame
viewport.x = -target.x + canvas.width / 2;
viewport.y = -target.y + canvas.height / 2;
// Keep viewport in map bounds
viewport.x = clamp(viewport.x, canvas.width - map.width, 0);
viewport.y = clamp(viewport.y, canvas.height - map.height, 0);
// Draw each entity, including the target, relative to the viewport
ctx.fillRect(
entity.x + viewport.x,
entity.y + viewport.y,
entity.size,
entity.size
);
}
// Restrict n to a range between lo and hi
const clamp = (n, lo, hi) => n < lo ? lo : n > hi ? hi : n;
2d 로 생각할 수 있는 사각형 안에 카메라 팬합니다 큰 지도. 영점 있다 '는' (x, y) 좌표, 즉 '이 맵에서, 그 크기는 캔바스를 캔버s.위드스' 와 '캔버스트레이트'. 즉, 'x' 를 '-' 0 '의 범위는' 및 'y' 를 '-' 0 '에서 마피비데스 캔버s.위드스 마피하이트 캔버스트레이트' (포함). 이들은 '분' 와 '맥스' 가 ',' s # 39 에 우리가 급지가 @Colton& 종양이라고요 메서드입니다.
하지만, 제가 작동합니까 전환할 수 있도록 하겠다고 했다 'x' 와 'y' 이후 사인온을 ['콘테스트리트란슬레이트'] (https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate), 양의 값을 캔바스를 이동할 수 있는 권리 (착각에서요 만드는 것처럼 왼쪽에 카메라 팬합니다) 및 제외어 - 왼쪽에 카메라 팬합니다 것처럼 (오른쪽).