Как да преведа правилно картата си след мащабиране?

Създавам камера в платно като тази в Super Smash Bros, където центърът на камерата следва централната точка на всички играчи и се мащабира, за да обхване всички играчи.

Настроил съм го да намира разстоянието между двамата играчи и ако е по-голямо от размера на платното, скалата на камерата се понижава, за да намали размера на блоковете, спрайтовете на играчите и т.н.

ctx.scale(cameraS,cameraS);
ctx.translate(-(cameraX*cameraS)+(CANVAS_WIDTH/2),-(cameraY*cameraS)+(CANVAS_HEIGHT/2));

Те мащабират и преместват начертаните изображения до позиция спрямо екрана.

Това е действителната игра, използваща кода и както можете да разберете, мащабирането и преместването на изображенията е малко неправилно, но не знам защо! https://dl.dropboxusercontent.com/u/51784213/Conjugate/index.html

За справка, червената точка е центрираната позиция между двамата играчи. Линиите показват мъртвата точка на действителното платно. Когато мащабирането е 1 (никакво мащабиране), червената точка е напълно центрирана, както трябва да бъде. Когато мащабирането започне да намалява, червената точка започва да се движи извън центъра в странни посоки.

За да работи кодът правилно, точката трябва да е центрирана през цялото време, дори по време на процеса на мащабиране!


person NinthWorld    schedule 09.05.2013    source източник


Отговори (1)


Трансформациите се прилагат в обратен ред; така че първо превеждате и след това мащабирате. Това означава, че за точка (x, y), след текущата трансформация, получавате

( 
    (x + CANVAS_WIDTH/2 - cameraX*cameraS) * cameraS, 
    (y + CANVAS_HEIGHT/2 - cameraY*cameraS) * cameraS 
)

Това, което всъщност е необходимо тук, е платното да бъде преведено от мащабирано (cameraX, cameraY) и след това да бъде изместено от действителното (CANVAS_WIDTH/2, CANVAS_HEIGHT/2), така че (cameraX, cameraY) да е в центъра на видимото платно.

Или по-скоро трансформацията, необходима тук за точка (x, y) е

( 
    (x - cameraX) * cameraS + CANVAS_WIDTH/2, 
    (y - cameraY) * cameraS + CANVAS_HEIGHT/2 
)

Следователно, кодът става, ако изберете първо да приложите превод,

ctx.scale(cameraS,cameraS);
ctx.translate(-cameraX+CANVAS_WIDTH/(2*cameraS),-cameraY+CANVAS_HEIGHT/(2*cameraS));

Или, ако изберете първо да приложите мащабиране

ctx.translate(-cameraX*cameraS + CANVAS_WIDTH/2, -cameraY*cameraS + CANVAS_HEIGHT/2);
ctx.scale(cameraS, cameraS);

Работещ JSFiddle.

person Rikonator    schedule 09.05.2013