Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > C++

Ответ
 
Опции темы
Старый 23.09.2010, 02:05   #1
jimon
 
Сообщений: n/a
Qt QML : декларативный интерфейс, императивная логика

Qt захватит мир !

при разработке интерфейсов мы очень часто сталкиваемся с огромным количеством рутины, обычно нужно работать со сложным конечным автоматом, кучей асинхронных анимаций и отзывчивостью к юзеру

императивный путь работы с интерфейсом тернист, а звёзд редко кто достигает, а если и достигает то следующий раз опять все тернии надо проходить (редко какой интерфейсный проект проще поддерживать чем переписать заново), а вот декларативный способ задания интерфейса всё меняет местами, мы задаем только то что хотим получить, всё остальное на себя берет декларативный движок

добавим к этому всему что Qt имеет систему сигналов-слотов и свой препроцессор (в общем-то свою билд-систему, и свой IDE ), и что же мы получим ? мы получим QML, декларативный язык задания интерфейса со сквозным двухсторонним биндингом с C++ кодом ! другими словами мы теперь пишем интерфейс на языке подобном html и он работает напрямую с нашей C++ логикой (слава чистому MVC, слава)

перейдем к примеру :

обычный класс на Qt :
 class Stopwatch : public QObject
 {
     Q_OBJECT
 public:
     Stopwatch();

     Q_INVOKABLE bool isRunning() const;

 public slots:
     void start();
     void stop();

 private:
     bool m_running;
 };
к обычным методам (не сигналам и не слотам) добавляется только Q_INVOKABLE перед декларацией метода, что в сотни-тыщи-миллионы-раз проще и лучше любого биндинга к скриптовым системам, собственно слоты start и stop уже можно использовать из QML

что мы пишем в qml :
 import Qt 4.7

 Rectangle {
     width: 300
     height: 300

     MouseArea {
         anchors.fill: parent
         onClicked: {
             if (stopwatch.isRunning())
                 stopwatch.stop()
             else
                 stopwatch.start();
         }
     }
 }
как видим тут объявляется область 300 на 300, в ней создается область работы с мышкой на весь размер родительской области, а по нажатию вызываются наши C++ методы ! (так же возможно наоборот - вызывать QML функции из C++ кода)

сам QML очень гибкий и базируется на JavaScript, что гарантирует некую лёгкость и гибкость изложения кода, любой валидный JavaScript код можно использовать как значение для параметров объектов, сам QML имеет встроенные средства для задания стейтов (кнопка имеет нажатый и не нажатый стейт к примеру), можно задавать любые параметры в стейтах, и имеет средства анимации между стейтами так же имеются встроенные средства для анимации параметров

к примеру :
 Rectangle {
     id: rect
     width: 120; height: 200

     Image {
         id: img
         source: "pics/qt.png"
         x: 60 - img.width/2
         y: 0

         SequentialAnimation on y {
             loops: Animation.Infinite
             NumberAnimation { to: 200 - img.height; easing.type: Easing.OutBounce; duration: 2000 }
             PauseAnimation { duration: 1000 }
             NumberAnimation { to: 0; easing.type: Easing.OutQuad; duration: 1000 }
         }
     }
 }
реализация QML называется Qt Declarative, доступна в релизе Qt 4.7, визуальный редактор для QML будет встроен в Qt Creator 2.1 (сейчас в релизе 2.0.1, 2.1 скоро будет )

Qt 4.7 доступен на огромнейшем количестве разнообразных платформ, написал один раз и оно работает на симбиане, meego, windows, linux, mac и тд и тд (собсно сам Qt под LGPL лицензией)

ps. сигналы - слоты это механизм передачи вызовов сигналов в вызов слота, ближайшая аналогия - визуальное программирование логики, там тоже стрелочки между блоками таскаем, откуда тащим - сигнал, куда - слот, вызывая один из нескольких сигналов (физически декларируем метод, реализует сам Qt), вызывается слот к которому сигналы привязаны (физически описывается как метод только в секции slots)
 
Ответить с цитированием
Эти 11 пользователя(ей) сказали Спасибо за это полезное сообщение:
.Squid (23.09.2010), baton4ik (23.09.2010), BlackDragon (27.09.2010), falcon (23.09.2010), HolyDel (23.09.2010), impersonalis (23.09.2010), pax (25.09.2010), Phantom (25.09.2010), Randomize (23.09.2010), Reks888 (23.09.2010), Жека (24.09.2010)
Старый 27.09.2010, 02:21   #2
jimon
 
Сообщений: n/a
Ответ: Qt QML : декларативный интерфейс, императивная логика

чтобы опробовать инструмент решил написать понг чисто на QML, в принципе результирующий код вышел немного громоздким из-за асинхронного javascript кода и qml анимаций

мышкой управляются обе платформы, скорость игры постепенно увеличивается, необходимо набрать наибольшее количество очков

// imports
import Qt 4.7

// root object
Rectangle
{
	id:screen; width:1024; height:768; color:"#DDDDDD"

	// game text, show status of the game
	Text
	{
		id:gameText;
		anchors.top:screen.top; anchors.horizontalCenter:screen.horizontalCenter
		text:"QML pong by jimon"
	}

	// score text
	Text
	{
		id:gameScoreText;
		anchors.top:screen.top; x:5;
		font.family: "Courier New"; font.pointSize: 16; color: "#000000"

		function zeroPad(num, count)
		{
			while(num.length < count) num = "0" + num;
			return num;
		}

		function setScore(score)
		{
			text = "SCORE : " + zeroPad(score.toString(), 7)
		}

		Component.onCompleted:setScore(0);
	}

	// ball
	Rectangle
	{
		id:ball; width:64; height:64; color:"#000000"
		x:(screen.width - ball.width) / 2; y:(screen.height - ball.height) / 2

		property variant wayX: 0 // ball way X
		property variant wayY: 0 // ball way Y
		property double speed: 0
		property double speedDefault: 0.25 // in pixels per millisec

		// moving, use number animation on x and y, calculate duration by hands
		// moving by javascript and etc is a really BAD idea

		NumberAnimation on x {id:ballAnimX}
		NumberAnimation on y {id:ballAnimY}

		function moveTo(newV, oldV, anim)
		{
			anim.stop();
			anim.duration = Math.abs(oldV - newV) / speed;
			anim.from = oldV;
			anim.to = newV;
			anim.start();
		}

		function moveToX(newX)
		{
			moveTo(newX, ball.x, ballAnimX)
		}

		function moveToY(newY)
		{
			moveTo(newY, ball.y, ballAnimY)
		}

		function stopAnimations()
		{
			ballAnimX.stop();
			ballAnimY.stop();
		}

		function setWayX(newWayX)
		{
			if(newWayX != wayX)
			{
				ball.moveToX(newWayX == 1 ? screen.width - ball.width : 0);
				wayX = newWayX;
			}
		}

		function setWayY(newWayY)
		{
			if(newWayY != wayY)
			{
				ball.moveToY(newWayY == 1 ? screen.height - ball.height : 0);
				wayY = newWayY;
			}
		}
	}

	// left platform
	Rectangle
	{
		id:left; width:32; height:128; color:"#5555FF"; anchors.left:screen.left
		y:(screen.height - left.height) / 2
	}

	// right platform
	Rectangle
	{
		id:right; width:32; height:128; color:"#5555FF"; anchors.right:screen.right
		y:(screen.height - right.height) / 2
	}

	// game logic timer
	Timer
	{
		interval:20; running:true; repeat:true
		onTriggered:gameTick();
	}

	// work with mouse
	MouseArea
	{
		id:mouse;
		anchors.fill:screen; hoverEnabled:true
		onPositionChanged:gameUpdateMouse();
		onClicked:gameRestart();
	}

	property variant gameCanRestart:1;
	property variant gameScore:0;

	function gameTick()
	{
		if(!gameCanRestart) // if game running
		{
			gameScore = gameScore + 10;
			gameScoreText.setScore(gameScore);

			ball.speed = ball.speed * 1.001;
		}

		if(gamePlatformCheck(left)) // horizontal moving
			ball.setWayX(1);
		if(gamePlatformCheck(right))
			ball.setWayX(-1);
		else if(ball.x <= 0 || ball.x >= screen.width - ball.width)
			screen.gameLose();

		if(ball.y >= screen.height - ball.height) // vertical moving
			ball.setWayY(-1);
		else if(ball.y <= 0)
			ball.setWayY(1);
	}

	function gamePlatformCheck(platform)
	{
		return (Math.abs(platform.x - ball.x + (platform.width - ball.width) / 2) < (platform.width + ball.width) / 2) &&
		   (Math.abs(platform.y - ball.y + (platform.height - ball.height) / 2) < (platform.height + ball.height) / 2);
	}

	function gameUpdateMouse()
	{
		left.y = mouse.mouseY - left.height / 2;
		right.y = mouse.mouseY - right.height / 2;
	}

	function gameLose()
	{
		gameText.text = "Game Over !";
		ball.stopAnimations();
		ball.x = (screen.width - ball.width) / 2;
		ball.y = (screen.height - ball.height) / 2;

		gameCanRestart = 1;
	}

	function gameRestart()
	{
		if(gameCanRestart)
		{
			gameScore = 0;
			gameScoreText.setScore(gameScore);

			ball.speed = ball.speedDefault;

			ball.wayX = 0;
			ball.wayY = 0;
			ball.setWayX(-1);
			ball.setWayY(-1);
			gameText.text = "Game Started !";
			gameCanRestart = 0;
		}
	}
}
основная громоздкость в необходимости хранить направление движения, потому что функция moveTo выполняется асинхронно с анимациями и может банально не дать анимации стартовать

подход выполнения логики в javascriptе мне совсем не понравился, он слишком сырой сейчас, попробую еще реализовать логику на C++
Миниатюры
Нажмите на изображение для увеличения
Название: snapshot1.png
Просмотров: 1063
Размер:	4.6 Кб
ID:	11374  
 
Ответить с цитированием
Старый 27.09.2010, 20:46   #3
Morganolla
Бывалый
 
Аватар для Morganolla
 
Регистрация: 03.12.2008
Адрес: наша раша
Сообщений: 762
Написано 129 полезных сообщений
(для 245 пользователей)
Ответ: Qt QML : декларативный интерфейс, императивная логика

Один заголовок темы тянет на статью в солидном западном журнале
Дядя Дима не пугай детей...
ЗЫ Отвлеченный вопрос, сорри. А что такое explicit? Это термин из С++ или...?
__________________
Reality Simulation Games
Core 2 Duo 2,8GHz, RAM 1Gb, ATI R5670 1Gb. WinXP 32
(Offline)
 
Ответить с цитированием
Старый 27.09.2010, 21:56   #4
jimon
 
Сообщений: n/a
Ответ: Qt QML : декларативный интерфейс, императивная логика

Morganolla
А что такое explicit?
запрет на автоприведение типов при вызове конструктора

к примеру :
class A
{
A(int V){ ... }
};
...
A foo = 5;    // работает
A foo = A(5); // работает
class A
{
explicit A(int V){ ... }
};
...
A foo = 5;    // не работает
A foo = A(5); // работает
 
Ответить с цитированием
Эти 4 пользователя(ей) сказали Спасибо за это полезное сообщение:
developer (27.09.2010), impersonalis (27.09.2010), Morganolla (27.09.2010), Randomize (27.09.2010)
Старый 05.01.2013, 04:10   #5
jimon
 
Сообщений: n/a
Ответ: Qt QML : декларативный интерфейс, императивная логика

вышел qt quick 2, намного более шустрый фреймворк для qml

в итоге 1200 прямоугольников, которые случайно перемещаются по экранму и меняют цвет, выдает 60 фпс
import QtQuick 2.0
 
Rectangle
{
        width: 1024
        height: 768
        focus: true
 
        Repeater
        {
                id: rep;
                model: 1200
 
                Rectangle
                {
                        id: rectt;
                        width: 16; height: 16;
                        color: "black";
 
                        SequentialAnimation
                        {
                                running: true; loops: -1;
                                ColorAnimation { target: rectt; property:"color"; from: "black"; to: "yellow"; duration: 1000;}
                                ColorAnimation { target: rectt; property:"color"; from: "yellow"; to: "black"; duration: 1000;}
                        }
                }
 
        }
        Timer
        {
                interval: 16; running: true; repeat: true;
                onTriggered:
                {
                        for(var i = 0; i < rep.count; i++)
                        {
                                var o = rep.itemAt(i);
                                o.x = Math.random()*1024;
                                o.y = Math.random()*768;
                        }
                }
        }
 
        Keys.onPressed: { if(event.key == Qt.Key_Escape) Qt.quit(); }
}
а сколько html5 на таком коде выдаст ?

еще одна хорошая новость, Desktop Components for QML почти готовы к релизу и будут включены в qt 5.1
посмотрите насколько просто и быстро создавать настольные приложения : http://www.youtube.com/watch?v=Y1pqL5bXe0A
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
HolyDel (05.01.2013)
Старый 05.01.2013, 05:46   #6
moka
.
 
Регистрация: 05.08.2006
Сообщений: 10,429
Написано 3,454 полезных сообщений
(для 6,863 пользователей)
Ответ: Qt QML : декларативный интерфейс, императивная логика

http://moka.co/rects/
Chrome: 150
FF: 116
1200 прямоугольников, цвет циклируется.
Шустро же
(Offline)
 
Ответить с цитированием
Старый 05.01.2013, 10:28   #7
Skaner
ПроЭктировщик
 
Аватар для Skaner
 
Регистрация: 30.01.2012
Сообщений: 162
Написано 40 полезных сообщений
(для 86 пользователей)
Ответ: Qt QML : декларативный интерфейс, императивная логика

Моя опера выдала ~20 фпс... Chrome (Яндекс.Б) ~20, Ыфафкш (Safari то есть под винду) ~65 фпс...
__________________
Blitz3D - СИЛА!
(Offline)
 
Ответить с цитированием
Старый 05.01.2013, 14:05   #8
jimon
 
Сообщений: n/a
Ответ: Qt QML : декларативный интерфейс, императивная логика

Сообщение от MoKa Посмотреть сообщение
http://moka.co/rects/
Chrome: 150
FF: 116
1200 прямоугольников, цвет циклируется.
Шустро же
попробуй не canvas, а на dom дереве, а то не интересно : в qml тесте создаются честные 1200 объектов, я кстати чуть модифицировал тест вчера и с 60 фпс рендерило уже 1700 объектов

ps. модифицированый тест http://pastebin.com/ATdvC6PK, фпс мерялся фрапсом
 
Ответить с цитированием
Старый 05.01.2013, 15:50   #9
Randomize
[object Object]
 
Аватар для Randomize
 
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,354
Написано 2,470 полезных сообщений
(для 6,850 пользователей)
Ответ: Qt QML : декларативный интерфейс, императивная логика

Сообщение от jimon Посмотреть сообщение
попробуй не canvas, а на dom дереве, а то не интересно : в qml тесте создаются честные 1200 объектов, я кстати чуть модифицировал тест вчера и с 60 фпс рендерило уже 1700 объектов
Попробуй игры в экселе писать.
HTML нужен только для представления данных, а СSS для их стилизации.
Для динамики используется canvas/webgl.
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
moka (05.01.2013)
Старый 05.01.2013, 16:05   #10
jimon
 
Сообщений: n/a
Ответ: Qt QML : декларативный интерфейс, императивная логика

Сообщение от Randomize Посмотреть сообщение
Попробуй игры в экселе писать.
HTML нужен только для представления данных, а СSS для их стилизации.
Для динамики используется canvas/webgl.
what ? что же еще все сайты на canvas не делают ? ведь у некоторых анимаций больше чем данных
я ведь не выложил тест где 100500 прямоугольников рисуются шейдером за 1 дип, а то он бы выдал вам 100500 тыс фпс и было бы что canvas в 100500x раз медленее, я выложил честный тест с честными отдельными объектами, они эквивалентны dom, можно такой же тест с xaml провести
 
Ответить с цитированием
Старый 05.01.2013, 16:38   #11
Randomize
[object Object]
 
Аватар для Randomize
 
Регистрация: 01.08.2008
Адрес: В России
Сообщений: 4,354
Написано 2,470 полезных сообщений
(для 6,850 пользователей)
Ответ: Qt QML : декларативный интерфейс, императивная логика

Сообщение от jimon Посмотреть сообщение
what ? что же еще все сайты на canvas не делают ? ведь у некоторых анимаций больше чем данных
Потому что есть Internet Explorer, Windows XP, Intel GMA, Opera а так же ряд ущербных и беспросветных мобильных калькуляторов
__________________
Retry, Abort, Ignore? █
Intel Core i7-9700 4.70 Ghz; 64Gb; Nvidia RTX 3070
AMD Ryzen 7 3800X 4.3Ghz; 64Gb; Nvidia 1070Ti
AMD Ryzen 7 1700X 3.4Ghz; 8Gb; AMD RX 570
AMD Athlon II 2.6Ghz; 8Gb; Nvidia GTX 750 Ti
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
moka (05.01.2013)
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 20:58.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com