지난 며칠간 프로젝트로 인해 이것은 나를 괴롭혔습니다.
나는 현재 그리드에 엄지 손톱을 많이 표시해야하는 앱을 만들고 있습니다.
그리드는 수직으로 스크롤해야하며 축소판을 클릭해야합니다.
이제 Phaser의 그룹에서 드래그를 구현하려고 시도해 본 적이 있다면 쉬운 일이 아닌지 알 수 있습니다.
Phaser의 창시자 인 Richard Davey는 html5gamedevs 포럼에서이 게시물의 그룹을 끌 수있는 기본 방법이없는 이유를 설명합니다.
"그것은 실제로 생각보다 조금 더 복잡합니다. 그룹에는 모든 영역이 없으며 모든 방향에서 무한합니다. 따라서 클릭 한 경우 감지 할 수 없습니다. 그러나 드래그하여 다른 모든 자식, 그 자식 또는 그룹 x / y 배치 자체를 업데이트해야한다면 쉽게 자식을 클릭 할 수 있습니까? (차례 차례로 다른 아이들을, 당신이 예기 할 방법에서 어쩌면 단지) 새롭게 할 것입니다. 그리고 중첩 된 그룹은 어떻습니까?"
필자는이 기능이 마음에 든다. 표면에 나타나는 것처럼 구현하기가 쉽지 않다.
Brainstorming the solution
그래서 내가 뭘해야하니? 내가 생각해 낸 첫 번째 해결책은 그룹의 높이와 너비가 같고 드래그 할 수 있도록 스프라이트를 만드는 것입니다. 작동하지만 새로운 자체 문제는 스프라이트를 클릭하여 개별 축소판에 도달 할 수 없다는 것입니다. 이것은 프로젝트의 핵심 부분입니다. 이제는 더 나은 솔루션이 필요하다는 것을 알게되었습니다. 이것은 내가 지금까지 알고있는 것이다 :
내 요구 사항 :
- 그룹 드래그
- 자녀를 클릭 할 수있는 상태로두기
내가 지금까지 알고있는 것 :
- 클릭 할 수있는 스프라이트는 마우스 이벤트를 다른 스프라이트로 차단합니다.
- 그룹이 마우스 이벤트를 감지 할 수 없습니다.
- Phaser의 드래그를 사용하여 그룹을 끌 수 없습니다.
- game.input은 아무것도 차단되지 않습니다.
그 마지막 요점은 내가 끌기가 무엇인지 생각하고있다 :
- 마우스 다운 이벤트
- 마우스가 눈금의 범위 내에 있는지 확인하기
- 마우스의 움직임을 확인하고 필요에 따라 눈금을 업데이트하십시오.
여기서 마우스라는 용어를 사용하고 있지만 터치 이벤트 일 수도 있습니다.
여기에 내가 지금 애플 리케이션에서 사용하고있는 해결책이있다. 이 예제에서는 Javascript 클래스를 사용합니다.
드래그를 위해 DragBox라는 클래스를 사용하고 있으며이 클래스도 그룹을 확장합니다. 나는 아이들을 여기에 추가하고 있지 않지만 내장 된 업데이트 기능을 사용할 수 있도록 그룹을 확장 중입니다. 드래그 해야하는 객체는 DragBox의 인스턴스로 유일한 매개 변수로 전달됩니다.
class DragBox extends Phaser.Group {
constructor(dragObj) {
super(game);
this.dragObj = dragObj;
game.input.onDown.add(this.onDown, this);
}
onDown() {
//set canDrag to false
this.canDrag = false;
//check if the mouse is in bounds
//since my dragObject is the full width of the game
//I only need to check the y position
//The top of the drag object is the y position
//and the bottom is the top plus the height
//
if (game.input.y > this.dragObj.y && game.input.y < (this.dragObj.y + this.dragObj.height)) {
//set the canDrag to true;
this.canDrag = true;
//get the start position of the dragObject
//so we may compare it to the current position
//when dragging
this.startY = this.dragObj.y;
//the offset is how far down on the grid the
//mouse is when the user started dragging
//without this line the grid will jump when
//the drag starts
this.offSet = this.dragObj.y - game.input.y;
}
}
update() {
if (game.input.mousePointer.isDown) {
if (this.canDrag == true) {
//calculate the difference between the startY
//and the current mouse y position
//and add in the offSet
var diff = game.input.y - this.startY + this.offSet;
//update the start position
//by adding the difference to the start position
this.dragObj.y = this.startY + diff;
}
}
}
}
대부분의 코드는 주석입니다. 노트가 없는 코드는 약 23 행뿐입니다.
class DragBox extends Phaser.Group {
constructor(dragObj) {
super(game);
this.dragObj = dragObj;
game.input.onDown.add(this.onDown, this);
}
onDown() {
this.canDrag = false;
if (game.input.y > this.dragObj.y && game.input.y < (this.dragObj.y + this.dragObj.height)) {
this.canDrag = true;
this.startY = this.dragObj.y;
this.offSet = this.dragObj.y - game.input.y;
}
}
update() {
if (game.input.mousePointer.isDown) {
if (this.canDrag == true) {
var diff = game.input.y - this.startY + this.offSet;
this.dragObj.y = this.startY + diff;
}
}
}
}
그룹을 직접 드래그하려면 코드 클래스를 직접 복사하여 프로젝트에 포함해야합니다.
그런 다음, 이 코드를 사용하여 개체를 만든 직후에 구현합니다.
var dragBox = new DragBox(objectYouWantToDrag);
이렇게하면 객체를 세로로 드래그 할 수 있지만 코드는 수평이 좋도록 조정할 수 있습니다.
다음은 내가 하는 일의 예입니다.
먼저 Phaser 그룹을 확장하는 그리드 클래스를 만들었습니다.
이 그리드 클래스는 같은 크기의 자식 요소 용입니다.
열 수에 'cols' 매개 변수가 필요합니다.
class Grid extends Phaser.Group {
constructor(cols) {
super(game);
this.cols = cols;
}
arrange() {
var xx = 0;
var yy = 0;
this.children.forEach(function(item) {
//place the item on a column with a 10 percent buffer
item.x = item.width * xx * 1.1;
//place the item on a row with a 10 percent buffer
item.y = item.height * yy * 1.1;
xx++;
if (xx ==this.cols) {
xx = 0;
yy++;
}
}.bind(this));
}
center() {
this.x = game.width / 2-this.width/2;
this.y = game.height / 2-this.height/2;
}
}
미리보기 이미지의 경우 Box라는 클래스를 사용하고 있습니다. 이것은 단순히 마우스 리스너가 연결된 이미지가 포함 된 그룹을 확장하는 클래스입니다.
class Box extends Phaser.Group
{
constructor()
{
super(game);
var thumb=this.create(0,0,"box");
thumb.anchor.set(0.5,0.5);
thumb.inputEnabled=true;
thumb.events.onInputDown.add(this.clicked);
}
clicked()
{
console.log("click");
}
}
그리고 이건 내 stateMain.js 코드입니다.
var StateMain = {
preload: function() {
game.load.image("box", "images/box.png");
},
create: function() {
//make a grid
//
this.grid = new Grid(5);
//make 30 boxes and add to the grid
//
for (var i = 0; i < 30; i++) {
var box = new Box();
this.grid.add(box);
}
//arrange the child objects into a grid
//
this.grid.arrange();
//center on stage
//
this.grid.center();
//make a dragBox and pass the grid to it
//
var dragBox = new DragBox(this.grid);
}
}
그리고 드래그 그룹 코드가 실제로 작동합니다. 개발자 콘솔을 열면 사각형이 여전히 클릭 가능한지 확인할 수 있습니다. 드래그 중에 실수로 사각형이 클릭되지 않도록하려면 마우스를 아래로 내리고 마우스를 위로 올리는 시간을 확인하는 함수를 구현할 것입니다. 그것은 빠른 다음 그렇지 않으면 클릭이 될 것입니다, 나는 사용자가 드래그하고 있다고 가정합니다.
댓글 없음:
댓글 쓰기