Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #11 (permalink)  
Старый 22.04.2019, 21:45
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Камера движения, эффект камеры на canvas, космическая игра.
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Space game | Canvas camera (scrolling) effect</title>
</head>
<body>
<canvas width="600" height="400" style="border: 1px solid #000; background: #000;"></canvas>
<br>Arrow keys: Up / Down - acceleration / deceleration, Left / Right - rotation.
<button onclick="swapShips()">Swap ships</button>
<script>
// Fun
function swapShips() {
    if (shipA.input == humanInput) {
        camera.target = shipB; shipB.input = humanInput; shipA.input = robotInput;
    } else if (shipB.input == humanInput) {
        camera.target = shipA; shipA.input = humanInput; shipB.input = robotInput;
    }
}
// Canvas
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d'); context.font = '12px monospace';
const DEGREE = Math.PI / 180;
const sprites = new Set;
// Images
const starsImage = new Image(); starsImage.src = 'https://i.imgur.com/a4BvjCM.png';
const shipsImage = new Image(); shipsImage.src = 'https://i.imgur.com/z2bkMae.png';
const imageMap = {
    stars: { source: starsImage, x: 0, y: 0, width: 1920, height: 1080, rotation: 0 },
    shipA: { source: shipsImage, x: 2, y: 2, width: 200, height: 172, rotation: 90 * DEGREE },
    shipB: { source: shipsImage, x: 204, y: 2, width: 200, height: 172, rotation: 90 * DEGREE },
};
// Class Sprite
const Sprite = {
    image: null, x: 0, y: 0, width: 64, height: 64, rotation: 0,
    get halfWidth() { return this.width / 2; },
    get halfHeight() { return this.height / 2; },
    render(ctx) {
        ctx.translate(this.x, this.y);
        ctx.rotate(this.image.rotation + this.rotation);
        ctx.drawImage(this.image.source, this.image.x, this.image.y, this.image.width, this.image.height,
            -this.halfWidth, -this.halfHeight, this.width, this.height);
    },
};
// Class Sprite instance
let space = {
    __proto__: Sprite, image: imageMap.stars, width: 1920, height: 1080, x: 960, y: 540,
};
sprites.add(space);
// Class Ship extends Sprite
const Ship = {
    __proto__: Sprite, scene: space, input: null,
    velocityX: 0, velocityY: 0, acceleration: 0.2, deceleration: 0.98,
    maxSpeed: 5, speed: 0, rotationSpeed: 3 * DEGREE,
    update(dt) {
        this.input.start;
        if (this.input.ArrowLeft) {
            this.rotation -= this.rotationSpeed;
        }
        if (this.input.ArrowRight) {
            this.rotation += this.rotationSpeed;
        }
        if (this.input.ArrowUp) {
            this.velocityX += this.acceleration * Math.cos(this.rotation);
            this.velocityY += this.acceleration * Math.sin(this.rotation);
        }
        if (this.input.ArrowDown) {
            this.velocityX *= this.deceleration;
            this.velocityY *= this.deceleration;
        }
        this.speed = Math.hypot(this.velocityX, this.velocityY);
        if (this.speed > this.maxSpeed) {
            this.velocityX *= this.maxSpeed / this.speed;
            this.velocityY *= this.maxSpeed / this.speed;
        }
        this.x = Math.max(0, Math.min(this.x + this.velocityX, this.scene.width));
        this.y = Math.max(0, Math.min(this.y + this.velocityY, this.scene.height));
    },
};
// Inputs
const humanInput = {};
const robotInput = {
    times: 0,
    get start() { if (this.times++ > 120) this.times = 0; },
    get ArrowLeft() { return this.times < 0; },
    get ArrowRight() { return this.times > 90; },
    get ArrowUp() { return this.times < 120; },
    get ArrowDown() { return this.times > 120; },
};
// Class Ship instance
let shipA = {
    __proto__: Ship, image: imageMap.shipA, input: humanInput,
    width: 80, height: 69, x: space.x, y: space.y, rotation: -90 * DEGREE,
};
sprites.add(shipA);
// Class Ship instance
let shipB = {
    __proto__: Ship, image: imageMap.shipB, input: robotInput,
    width: 80, height: 69, x: space.x + 200, y: space.y - 150, rotation: 90 * DEGREE,
};
sprites.add(shipB);
// Class Sprite instance
const camera = {
    __proto__: Sprite, scene: space, target: shipA, mapScale: 0.2 * canvas.height / space.height,
     width: canvas.width, height: canvas.height, x: shipA.x, y: shipA.y,
    update(dt) {
        this.x = Math.max(this.halfWidth, Math.min(this.target.x, this.scene.width - this.halfWidth)); 
        this.y = Math.max(this.halfHeight, Math.min(this.target.y, this.scene.height - this.halfHeight));
    },
    render(ctx) {
        ctx.fillStyle = ctx.strokeStyle = '#ccc'; ctx.lineWidth = 1 / this.mapScale;
        ctx.translate(this.x - this.halfWidth, this.y - this.halfHeight);
        ctx.fillText(`fps: ${fps.toFixed(2)} x: ${this.target.x.toFixed(2)} `+
            `y: ${this.target.y.toFixed(2)} v: ${this.target.speed.toFixed(5)}`, 5, this.height - 5);
        ctx.scale(this.mapScale, this.mapScale);
        for (let sprite of sprites) {
            ctx.strokeRect(sprite.x - sprite.halfWidth, sprite.y - sprite.halfHeight, sprite.width, sprite.height);
        }
    },
};
sprites.add(camera);
// Listeners
window.addEventListener('keydown', (e) => { humanInput[e.code] = true; e.preventDefault(); });
window.addEventListener('keyup', (e) => { humanInput[e.code] = false; });
window.addEventListener("load", (e) => { main(0); });
// Main (frame-based animation, about 60 fps, but there is delta for time-based)
let time = 0, fps = 0;
function main(now) {
    requestAnimationFrame(main);
    let delta = Math.min(now - time, 100) / 1000;
    time = now; fps = 1 / delta;
    for (let sprite of sprites) {
        if (sprite.update) sprite.update(delta);
    }
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.save();
    context.translate(camera.halfWidth - camera.x, camera.halfHeight - camera.y);
    for (let sprite of sprites) {
        if (sprite.render) {
            context.save(); sprite.render(context); context.restore();
        }
    }
    context.restore();
}
</script>
</body>
</html>
Зацените robotInput, это же гениально!)
Ответить с цитированием
  #12 (permalink)  
Старый 23.04.2019, 14:33
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Есть идеи как добавить путь или маршрут в интерфейс robotInput? (из примера выше) Чтобы было допустим свойство path, как последовательность направлений, прямо столько-то пикселей, затем налево или направо столько-то градусов, и тд, в конце остановка или обратно или к началу, а может еще что-то. Может даже проще не в пикселях, а в фреймах указывать, прямо столько-то фреймов, затем налево или направо столько-то фреймов, и тд.
const robotInput = {
    times: 0,
    get start() { if (this.times++ > 120) this.times = 0; },
    get ArrowLeft() { return this.times < 0; },
    get ArrowRight() { return this.times > 90; },
    get ArrowUp() { return this.times < 120; },
    get ArrowDown() { return this.times > 120; },
};
Ответить с цитированием
  #13 (permalink)  
Старый 23.04.2019, 17:24
Кандидат Javascript-наук
Отправить личное сообщение для Всемогущий Посмотреть профиль Найти все сообщения от Всемогущий
 
Регистрация: 11.09.2018
Сообщений: 128

Rise вы гений !!! Где вы откопали такой замечательный код !!!! Хотя он и не весь мне понятен, вместо переменных константы и тд, но код и правда крутой !!!!!!!!!! да еще и показываются координаты корабля что я никак не мог сделать. Очень интересный и необычный код надо будет поизучать и переформатировать в удобный мне формат.Robotinput. Это ваш код ? не алгоритмы я не писал про пути и маршруты. Но можно написать чтобы было рандомное перемещение в разные стороны

Как на сайте этой игры - fightz.io там монстры двигаются в рандомном направлении

Последний раз редактировалось Всемогущий, 23.04.2019 в 20:34.
Ответить с цитированием
  #14 (permalink)  
Старый 23.04.2019, 22:07
Кандидат Javascript-наук
Отправить личное сообщение для Всемогущий Посмотреть профиль Найти все сообщения от Всемогущий
 
Регистрация: 11.09.2018
Сообщений: 128

Сразу видно что за соседним компьютером сидит профи
Ответить с цитированием
  #15 (permalink)  
Старый 24.04.2019, 11:03
Кандидат Javascript-наук
Отправить личное сообщение для Всемогущий Посмотреть профиль Найти все сообщения от Всемогущий
 
Регистрация: 11.09.2018
Сообщений: 128

Я вот только не понимаю как ты узнаешь координаты корабля. Я вообще так поизучал весь твой код и много всего мне непонятно
Ответить с цитированием
  #16 (permalink)  
Старый 24.04.2019, 22:02
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Да здесь всё просто насколько это возможно, если много непонятного значит есть чему учиться.
Ответить с цитированием
  #17 (permalink)  
Старый 24.04.2019, 22:41
Кандидат Javascript-наук
Отправить личное сообщение для Всемогущий Посмотреть профиль Найти все сообщения от Всемогущий
 
Регистрация: 11.09.2018
Сообщений: 128

Привет Rise !!!!! как в приведенном ниже коде узнать координаты корабля которыq по центру ???!!! я не понял как ты сделал это в robotinput !
<head>
       <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
   </head>
   <body>
       <canvas id='myCanvas' height='500' width='700' style="border:1px solid black;"class="invisible"> </canvas>	 
				 
<script type="text/javascript">
 
	var angle1 = 0;  
	var sp = 1;
	var x = 400;
	var y = 250;
	var speed = 1;
	var angle = 0;
	var mod = 0;
	var stop = 0;

	var canvas  = document.getElementById("myCanvas");
	var ctx     = canvas.getContext('2d');
  
ship1 = new Image();
ship1.src = "https://i.paste.pics/74f8b071f80f88d8f71df1ffa634ee38.png";
ship1.onload = game;
 
function draw() {
	
    ctx.fillStyle = "green";
    ctx.fillRect(x, y, 30, 45);

	 
    ctx.save();
    ctx.translate(400, 200);
	ctx.rotate(Math.PI / 480 * angle); 
	ctx.scale(0.5,0.5);
    ctx.drawImage(ship1, -40, -40,80,80);
    ctx.restore();
    ctx.save();
 
 ctx.font = "14px Arial";
ctx.fillStyle = "black";
ctx.fillText("x:" + Math.round(x),110,40);
ctx.fillText("y:" + Math.round(y),190,40);
 
document.onkeydown = function(event) {
    if (event.keyCode == 87 || event.keyCode == 83) {
        mod = 0; e = 1; stop = 1;}
}
document.onkeydown = function(event) {
    //console.log(event.keyCode);
    if (event.keyCode == 87) {
        mod = 1;   
    }
    if (event.keyCode == 83) {
        mod = -1;  
    }
    if (event.keyCode == 65) {
        angle -= 10;  stop = 0;
    }
    if (event.keyCode == 68) {
        angle += 10;  stop =0;
    }
    if (event.keyCode == 32) {
		
    }
  if(event.keyCode == 70){  stop = 1;}
}}

function move(){
	
	 if( stop == 0){
	x += (speed * mod) * Math.cos(Math.PI / 480 * angle);
    y += (speed * mod) * Math.sin(Math.PI / 480 * angle);
    angle1 += 0.2 * Math.PI / 180;   
	}}

function game() {
	        ctx.clearRect(0, 0, canvas.width, canvas.height);
	        draw();
	        move();
	        requestAnimationFrame(game);
	    
	}
       </script>
   </body>
</html>

Последний раз редактировалось Всемогущий, 24.04.2019 в 22:43.
Ответить с цитированием
  #18 (permalink)  
Старый 24.04.2019, 23:09
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Всемогущий,
Про robotInput был просто философский вопрос обращенный к форуму. А твой вопрос и код такой же как в этой теме. Ты что ничему не учишься?
Ответить с цитированием
  #19 (permalink)  
Старый 25.04.2019, 00:23
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,068

Сообщение от Rise
Есть идеи
canvas Движение объектов по массиву координат
Ответить с цитированием
  #20 (permalink)  
Старый 25.04.2019, 17:54
Кандидат Javascript-наук
Отправить личное сообщение для Всемогущий Посмотреть профиль Найти все сообщения от Всемогущий
 
Регистрация: 11.09.2018
Сообщений: 128

Сообщение от Rise Посмотреть сообщение
Всемогущий,
Про robotInput был просто философский вопрос обращенный к форуму. А твой вопрос и код такой же как в этой теме. Ты что ничему не учишься?
Да я задавал этот вопрос в другой теме, но не получил на него ответов. Да ctx.translate(400,200); ЭТО СМЕНА СИСТЕМЫ КООРДИНАТ ЧТОБЫ КОРАБЛЬ БЫЛ ПО ЦЕНТРУ !!! но это его координаты относительно центра !!!! но не других обьектов!!!!!1
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Реализация расчета физического явления faceoff Общие вопросы Javascript 0 15.02.2017 21:31
Реализация пространства имен SunYang Общие вопросы Javascript 0 09.12.2015 10:38
Реализация сложного Tooltip IvanBond Работа 3 22.08.2013 14:34
Реализация игрового поля для игры "Точки" last-art Events/DOM/Window 7 22.04.2012 03:18
Реализация функции include BreatheInTheVoid Общие вопросы Javascript 4 23.09.2010 14:23